forked from jess/Acord
Icon, Windows, Dead Code. I bought a pizza. Er, right, this is git. But the pizza was REALLY good
This commit is contained in:
parent
43c1698797
commit
1b7377792f
|
|
@ -1,54 +1,48 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<svg viewBox="0 0 489.61898 491.035" version="1.1" id="svg29" width="489.61899" height="491.035" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">
|
<svg viewBox="0 0 489.61898 491.035" version="1.1" id="svg29" width="489.61899" height="491.035" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" xmlns:bx="https://boxy-svg.com">
|
||||||
<defs id="defs26">
|
<defs id="defs26">
|
||||||
<path id="text-path-1" d="m 77.219,406.062 c 77.897,-187.809 190.069,-151.33 256.629,-99.786 18.407,14.254 76.718,135.623 76.524,160.854"/>
|
<path id="text-path-1" d="m 77.219,406.062 c 77.897,-187.809 190.069,-151.33 256.629,-99.786 18.407,14.254 76.718,135.623 76.524,160.854"/>
|
||||||
<path id="path-2" d="m 77.219,406.062 c 77.897,-187.809 190.069,-151.33 256.629,-99.786 18.407,14.254 76.718,135.623 76.524,160.854"/>
|
<path id="path-2" d="m 77.219,406.062 c 77.897,-187.809 190.069,-151.33 256.629,-99.786 18.407,14.254 76.718,135.623 76.524,160.854"/>
|
||||||
<path id="path-3" d="m 77.219,406.062 c 77.897,-187.809 190.069,-151.33 256.629,-99.786 18.407,14.254 76.718,135.623 76.524,160.854"/>
|
<path id="path-3" d="m 77.219,406.062 c 77.897,-187.809 190.069,-151.33 256.629,-99.786 18.407,14.254 76.718,135.623 76.524,160.854"/>
|
||||||
<linearGradient gradientUnits="userSpaceOnUse" x1="242.681" y1="70.670998" x2="242.681" y2="419.965" id="gradient-0" gradientTransform="matrix(0.11880809,-1.1178257,0.27505632,0.03710317,76.138972,683.49193)">
|
<filter id="drop-shadow-filter-0" bx:preset="drop-shadow 1 0 2 20 1 #fff" color-interpolation-filters="sRGB" x="-50%" y="-50%" width="200%" height="200%">
|
||||||
<stop offset="0" style="stop-color: rgb(255, 0, 232); stop-opacity: 0.73;" id="stop1"/>
|
<title>Drop shadow</title>
|
||||||
<stop offset="0.151" style="stop-color: rgb(97, 0, 200); stop-opacity: 0.84;" id="stop2"/>
|
<feGaussianBlur in="SourceAlpha" stdDeviation="20"/>
|
||||||
<stop offset="0.267" style="stop-color: rgb(0, 87, 255);" id="stop3"/>
|
<feOffset dx="0" dy="2"/>
|
||||||
<stop offset="0.382" style="stop-color: rgb(0, 236, 255);" id="stop4"/>
|
<feComponentTransfer result="offsetblur">
|
||||||
<stop offset="0.539" style="stop-color: rgb(22, 197, 13); stop-opacity: 0.82;" id="stop5"/>
|
<feFuncA id="spread-ctrl" type="linear" slope="2"/>
|
||||||
<stop offset="0.725" style="stop-color: rgb(255, 233, 0);" id="stop6"/>
|
</feComponentTransfer>
|
||||||
<stop offset="0.897" style="stop-color: rgb(248, 142, 0);" id="stop7"/>
|
<feFlood flood-color="#fff"/>
|
||||||
<stop offset="1" style="stop-color: rgb(233, 0, 0); stop-opacity: 0.827;" id="stop8"/>
|
<feComposite in2="offsetblur" operator="in"/>
|
||||||
</linearGradient>
|
<feMerge>
|
||||||
<linearGradient gradientUnits="userSpaceOnUse" x1="227.47" y1="250.679" x2="227.47" y2="545.37598" id="gradient-1" gradientTransform="matrix(0.531844,0.846845,-0.939658,0.590138,518.63561,-7.578286)">
|
<feMergeNode/>
|
||||||
<stop offset="0" style="stop-color: rgb(249, 0, 106);" id="stop17"/>
|
<feMergeNode in="SourceGraphic"/>
|
||||||
<stop offset="0.088" style="stop-color: rgb(86, 0, 154);" id="stop18"/>
|
</feMerge>
|
||||||
<stop offset="0.16" style="stop-color: rgb(87, 0, 255);" id="stop19"/>
|
</filter>
|
||||||
<stop offset="0.229" style="stop-color: rgb(32, 40, 252);" id="stop20"/>
|
<filter id="drop-shadow-filter-1" bx:preset="drop-shadow 1 -3 10 4 0.87 #fff" color-interpolation-filters="sRGB" x="-50%" y="-50%" width="200%" height="200%">
|
||||||
<stop offset="0.354" style="stop-color: rgb(86, 151, 244);" id="stop21"/>
|
<feGaussianBlur in="SourceAlpha" stdDeviation="4"/>
|
||||||
<stop offset="0.43" style="stop-color: rgb(76, 245, 241);" id="stop22"/>
|
<feOffset dx="-3" dy="10"/>
|
||||||
<stop offset="0.551" style="stop-color: rgb(2, 255, 0);" id="stop23"/>
|
<feComponentTransfer result="offsetblur">
|
||||||
<stop offset="0.676" style="stop-color: rgb(211, 224, 69);" id="stop24"/>
|
<feFuncA id="spread-ctrl" type="linear" slope="1.74"/>
|
||||||
<stop offset="0.827" style="stop-color: rgb(244, 182, 87);" id="stop25"/>
|
</feComponentTransfer>
|
||||||
<stop offset="1" style="stop-color: rgb(225, 72, 72);" id="stop26"/>
|
<feFlood flood-color="#fff"/>
|
||||||
</linearGradient>
|
<feComposite in2="offsetblur" operator="in"/>
|
||||||
<radialGradient gradientUnits="userSpaceOnUse" cx="176.311" cy="197.825" r="243.31" id="gradient-2" gradientTransform="matrix(-1.802258, 2.07656, -0.757245, -0.657219, 890.103713, -190.568589)">
|
<feMerge>
|
||||||
<stop offset="0" style="stop-color: rgb(255, 7, 0);"/>
|
<feMergeNode/>
|
||||||
<stop offset="0.111" style="stop-color: rgb(255, 255, 255); stop-opacity: 0.64;"/>
|
<feMergeNode in="SourceGraphic"/>
|
||||||
<stop offset="0.215" style="stop-color: rgb(40, 163, 242);"/>
|
</feMerge>
|
||||||
<stop offset="0.314" style="stop-color: rgb(255, 0, 19);"/>
|
</filter>
|
||||||
<stop offset="0.328" style="stop-opacity: 0.46;"/>
|
|
||||||
<stop offset="0.516" style="stop-color: rgb(245, 224, 255); stop-opacity: 0.58;"/>
|
|
||||||
<stop offset="0.516" style="stop-color: rgb(27, 28, 202);"/>
|
|
||||||
<stop offset="0.715" style="stop-color: rgb(232, 223, 194);"/>
|
|
||||||
<stop offset="0.79" style="stop-color: rgb(213, 176, 164);"/>
|
|
||||||
<stop offset="0.92" style="stop-color: rgb(206, 104, 91); stop-opacity: 0.02;"/>
|
|
||||||
<stop offset="1" style="stop-color: rgb(221, 32, 27); stop-opacity: 0.54;"/>
|
|
||||||
</radialGradient>
|
|
||||||
</defs>
|
</defs>
|
||||||
<g id="g29" transform="matrix(1, 0, 0, 1, 9.478192, 0.432)">
|
<g id="g29" transform="matrix(0.886065, 0, 0, 0.886065, 36.532902, 33.434132)" style="">
|
||||||
<rect style="fill-rule: nonzero; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; paint-order: fill; stroke: url("#gradient-2"); stroke-width: 33px; fill: rgb(37, 54, 219);" x="-7.9781923" y="1.068" width="486.61899" height="488.035" id="rect26" rx="102.547" ry="102.547"/>
|
<g transform="matrix(1, 0, 0, 1, 4.60941, -10.628809)">
|
||||||
<path style="stroke:#ffffff;stroke-width:1.06069" d="M 349.92887,207.47326 97.322642,39.308335 141.23747,366.24784" id="path26"/>
|
<rect style="fill-rule: nonzero; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; paint-order: stroke; stroke-width: 5px; filter: url("#drop-shadow-filter-0"); stroke: rgba(248, 240, 255, 0.263);" x="-7.978" y="10.863" width="476.853" height="478.24" id="rect26" rx="134.974" ry="134.974"/>
|
||||||
<path d="M 119.56386,429.97631 94.617429,36.739247 357.01616,205.03927 Z M 96.495189,40.380102 139.09489,370.77245 353.7893,205.40516 Z" style="fill:url(#gradient-0);fill-rule:nonzero;stroke:#ffd500;stroke-width:7.42481px;stroke-linecap:round;stroke-linejoin:round;paint-order:stroke" id="path27"/>
|
<path d="M 120.199 287.137 L 108.703 309.698 L 83.418 305.274 L 62.5 346.346 L 78.893 368.212 L 67.69 390.221 L -3.131 291.252 L 8.042 269.309 L 120.199 287.137 Z M 64.664 301.997 L 23.613 294.275 L 50.386 330.03 L 64.664 301.997 Z M 155.052 186.303 L 140.578 202.168 C 137.804 198.887 134.875 197.052 131.794 196.663 C 128.706 196.28 125.595 197.28 122.461 199.663 C 118.303 202.826 115.953 206.967 115.411 212.086 C 114.875 217.204 116.88 223.559 121.423 231.149 C 126.477 239.592 131.304 244.601 135.907 246.175 C 140.51 247.741 144.933 246.914 149.176 243.693 C 152.343 241.28 154.331 238.29 155.14 234.723 C 155.943 231.156 155.277 226.578 153.142 220.988 L 171.435 211.666 C 174.811 221.448 175.378 230.344 173.139 238.353 C 170.893 246.355 165.706 253.445 157.578 259.623 C 148.347 266.639 139.021 268.952 129.6 266.562 C 120.173 264.164 111.986 257.159 105.04 245.546 C 98.009 233.8 95.29 222.562 96.883 211.832 C 98.476 201.109 103.969 192.176 113.364 185.035 C 121.055 179.195 128.285 176.415 135.055 176.695 C 141.832 176.974 148.497 180.177 155.052 186.303 Z M 203.458 187.837 C 204.385 180.372 206.921 173.403 211.067 166.931 C 215.206 160.459 220.497 155.859 226.941 153.13 C 233.391 150.394 240.311 149.611 247.702 150.78 C 259.113 152.589 267.943 158.245 274.191 167.747 C 280.439 177.257 282.77 188.385 281.183 201.131 C 279.577 213.987 274.563 224.059 266.141 231.348 C 257.726 238.636 247.93 241.394 236.753 239.622 C 229.84 238.526 223.464 235.72 217.628 231.204 C 211.798 226.696 207.672 220.779 205.25 213.454 C 202.834 206.136 202.237 197.597 203.458 187.837 Z M 223.758 192.283 C 222.707 200.711 223.677 207.445 226.667 212.483 C 229.663 217.528 233.763 220.463 238.966 221.286 C 244.176 222.11 248.824 220.562 252.911 216.642 C 256.998 212.722 259.574 206.492 260.638 197.953 C 261.682 189.635 260.719 182.957 257.749 177.919 C 254.779 172.881 250.688 169.947 245.479 169.115 C 240.275 168.292 235.617 169.84 231.504 173.76 C 227.391 177.68 224.809 183.854 223.758 192.283 Z M 305.489 268.669 L 288.528 256.402 L 329.687 184.185 L 345.434 195.581 L 339.587 205.852 C 345.045 202.955 349.289 201.513 352.318 201.528 C 355.347 201.543 358.233 202.539 360.975 204.518 C 364.833 207.312 367.869 211.207 370.082 216.201 L 355.334 229.064 C 353.669 224.909 351.61 221.945 349.155 220.172 C 346.779 218.451 344.347 217.73 341.859 218.01 C 339.365 218.289 336.548 220.014 333.408 223.184 C 330.268 226.354 325.199 234.08 318.2 246.362 L 305.489 268.669 Z M 367.223 365.675 L 358.37 347.096 L 368.231 341.128 C 362.924 340.363 358.331 338.447 354.453 335.38 C 350.581 332.313 347.627 328.647 345.59 324.381 C 341.451 315.695 341.011 306.377 344.268 296.426 C 347.533 286.468 354.724 278.127 365.842 271.405 C 377.221 264.521 387.304 262.304 396.092 264.753 C 404.886 267.195 411.476 273.02 415.864 282.228 C 419.892 290.678 420.257 299.875 416.96 309.819 L 450.324 289.63 L 459.863 309.631 L 367.223 365.675 Z M 376.78 291.109 C 369.619 295.44 364.97 299.688 362.836 303.851 C 359.741 309.881 359.571 315.795 362.326 321.59 C 364.526 326.194 368.13 329.055 373.138 330.173 C 378.151 331.298 384.115 329.772 391.029 325.595 C 398.739 320.932 403.541 316.008 405.434 310.823 C 407.334 305.638 407.119 300.603 404.788 295.72 C 402.529 290.976 398.961 288.012 394.084 286.828 C 389.208 285.651 383.44 287.078 376.78 291.109 Z" style="paint-order: stroke; stroke-linecap: round; stroke-linejoin: round; text-wrap-mode: nowrap; fill: rgba(0, 245, 255, 0.992); stroke-width: 4.51434px; stroke: rgb(255, 163, 2);"/>
|
||||||
<path d="M 127.57 310.87 L 115.83 331.32 L 90.01 327.31 L 68.65 364.54 L 85.39 384.36 L 73.95 404.31 L 1.63 314.6 L 13.04 294.71 Z M 70.86 324.34 L 28.94 317.34 L 56.28 349.75 Z M 163.16 219.47 L 148.38 233.85 Q 144.13 229.39 139.41 228.86 Q 134.68 228.34 129.88 231.58 Q 123.51 235.88 122.68 242.84 Q 121.86 249.8 128.82 260.12 Q 136.56 271.6 143.61 273.74 Q 150.66 275.87 157.16 271.49 Q 162.01 268.21 163.25 263.36 Q 164.48 258.51 161.21 250.91 L 179.89 242.46 Q 185.06 255.76 181.63 266.65 Q 178.19 277.53 165.74 285.93 Q 151.6 295.47 137.17 292.22 Q 122.73 288.96 112.09 273.17 Q 101.32 257.2 103.76 242.61 Q 106.2 228.03 120.59 218.32 Q 132.37 210.38 142.74 210.76 Q 153.12 211.14 163.16 219.47 Z M 212.59 220.86 Q 214.01 210.71 220.36 201.91 Q 226.7 193.11 236.57 189.4 Q 246.45 185.68 257.77 187.27 Q 275.25 189.73 284.82 202.65 Q 294.39 215.58 291.96 232.91 Q 289.5 250.39 276.6 260.3 Q 263.71 270.21 246.59 267.8 Q 236 266.31 227.06 260.17 Q 218.13 254.04 214.42 244.08 Q 210.72 234.13 212.59 220.86 Z M 233.32 224.89 Q 231.71 236.35 236.29 243.2 Q 240.88 250.06 248.85 251.18 Q 256.83 252.3 263.09 246.97 Q 269.35 241.64 270.98 230.03 Q 272.58 218.72 268.03 211.87 Q 263.48 205.02 255.5 203.89 Q 247.53 202.77 241.23 208.1 Q 234.93 213.43 233.32 224.89 Z M 316.78 294.13 L 299.46 283.01 L 341.49 217.55 L 357.57 227.88 L 351.6 237.19 Q 359.96 233.25 364.6 233.27 Q 369.24 233.29 373.44 235.98 Q 379.35 239.78 382.74 246.57 L 367.68 258.23 Q 365.13 252.58 361.37 250.17 Q 357.73 247.83 353.92 248.21 Q 350.1 248.59 345.29 252.9 Q 340.48 257.21 329.76 273.91 Z M 379.82 382.06 L 370.78 365.22 L 380.85 359.81 Q 372.72 358.77 366.78 354.6 Q 360.85 350.43 357.73 344.63 Q 351.39 332.82 356.38 319.29 Q 361.38 305.75 378.41 296.61 Q 395.84 287.25 409.3 290.58 Q 422.77 293.9 429.49 306.42 Q 435.66 317.91 430.61 331.43 L 464.68 313.13 L 474.42 331.26 Z M 389.58 314.47 Q 378.61 320.36 375.34 326.02 Q 370.6 334.22 374.82 342.1 Q 378.19 348.36 385.86 349.88 Q 393.54 351.41 404.13 345.73 Q 415.94 339.39 418.84 332.34 Q 421.75 325.29 418.18 318.65 Q 414.72 312.2 407.25 310.59 Q 399.78 308.99 389.58 314.47 Z" transform="matrix(0.999336, 0, 0, 1.125805, -4.66082, -66.978394)" style="paint-order: stroke; stroke: rgb(255, 0, 0); stroke-linecap: round; stroke-linejoin: round; stroke-width: 6.20419px; text-wrap-mode: nowrap;"/>
|
<path style="mix-blend-mode: difference; fill: rgb(0, 205, 220); stroke-width: 18.0574px; stroke: rgba(20, 30, 110, 0.43);" d="M 342.746 213.125 L 95.209 48.335 L 138.243 368.713" id="path26"/>
|
||||||
<ellipse style="stroke:#000000;stroke-width:1.06069" cx="225.81729" cy="233.35777" rx="0.32278565" ry="0.054038659" id="ellipse27"/>
|
<path d="M 117.004 431.163 L 92.558 45.818 L 349.691 210.74 L 117.004 431.163 Z M 94.398 49.386 L 136.143 373.147 L 346.529 211.099 L 94.398 49.386 Z" style="fill-rule: nonzero; stroke-width: 7.42481px; stroke-linecap: round; stroke-linejoin: round; paint-order: stroke; fill: rgb(255, 246, 255); stroke: rgb(134, 40, 187);" id="path27"/>
|
||||||
<ellipse style="stroke:#000000;stroke-width:1.06069" cx="225.81729" cy="233.35777" rx="0.029980088" ry="0.023641912" id="ellipse28"/>
|
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 1.06069; fill: rgba(30, 44, 177, 0.29);" cx="221.125" cy="238.49" rx="0.316" ry="0.053" id="ellipse27"/>
|
||||||
<path d="M 127.57 310.87 L 115.83 331.32 L 90.01 327.31 L 68.65 364.54 L 85.39 384.36 L 73.95 404.31 L 1.63 314.6 L 13.04 294.71 Z M 70.86 324.34 L 28.94 317.34 L 56.28 349.75 Z M 163.16 219.47 L 148.38 233.85 Q 144.13 229.39 139.41 228.86 Q 134.68 228.34 129.88 231.58 Q 123.51 235.88 122.68 242.84 Q 121.86 249.8 128.82 260.12 Q 136.56 271.6 143.61 273.74 Q 150.66 275.87 157.16 271.49 Q 162.01 268.21 163.25 263.36 Q 164.48 258.51 161.21 250.91 L 179.89 242.46 Q 185.06 255.76 181.63 266.65 Q 178.19 277.53 165.74 285.93 Q 151.6 295.47 137.17 292.22 Q 122.73 288.96 112.09 273.17 Q 101.32 257.2 103.76 242.61 Q 106.2 228.03 120.59 218.32 Q 132.37 210.38 142.74 210.76 Q 153.12 211.14 163.16 219.47 Z M 212.59 220.86 Q 214.01 210.71 220.36 201.91 Q 226.7 193.11 236.57 189.4 Q 246.45 185.68 257.77 187.27 Q 275.25 189.73 284.82 202.65 Q 294.39 215.58 291.96 232.91 Q 289.5 250.39 276.6 260.3 Q 263.71 270.21 246.59 267.8 Q 236 266.31 227.06 260.17 Q 218.13 254.04 214.42 244.08 Q 210.72 234.13 212.59 220.86 Z M 233.32 224.89 Q 231.71 236.35 236.29 243.2 Q 240.88 250.06 248.85 251.18 Q 256.83 252.3 263.09 246.97 Q 269.35 241.64 270.98 230.03 Q 272.58 218.72 268.03 211.87 Q 263.48 205.02 255.5 203.89 Q 247.53 202.77 241.23 208.1 Q 234.93 213.43 233.32 224.89 Z M 316.78 294.13 L 299.46 283.01 L 341.49 217.55 L 357.57 227.88 L 351.6 237.19 Q 359.96 233.25 364.6 233.27 Q 369.24 233.29 373.44 235.98 Q 379.35 239.78 382.74 246.57 L 367.68 258.23 Q 365.13 252.58 361.37 250.17 Q 357.73 247.83 353.92 248.21 Q 350.1 248.59 345.29 252.9 Q 340.48 257.21 329.76 273.91 Z M 379.82 382.06 L 370.78 365.22 L 380.85 359.81 Q 372.72 358.77 366.78 354.6 Q 360.85 350.43 357.73 344.63 Q 351.39 332.82 356.38 319.29 Q 361.38 305.75 378.41 296.61 Q 395.84 287.25 409.3 290.58 Q 422.77 293.9 429.49 306.42 Q 435.66 317.91 430.61 331.43 L 464.68 313.13 L 474.42 331.26 Z M 389.58 314.47 Q 378.61 320.36 375.34 326.02 Q 370.6 334.22 374.82 342.1 Q 378.19 348.36 385.86 349.88 Q 393.54 351.41 404.13 345.73 Q 415.94 339.39 418.84 332.34 Q 421.75 325.29 418.18 318.65 Q 414.72 312.2 407.25 310.59 Q 399.78 308.99 389.58 314.47 Z" transform="matrix(0.999336, 0, 0, 1.125805, -2.662937, -80.566888)" style="fill: rgb(40, 37, 37); paint-order: stroke; stroke: rgb(71, 71, 71); stroke-linecap: round; stroke-linejoin: round; stroke-width: 4px; text-wrap-mode: nowrap; vector-effect: non-scaling-stroke;"/>
|
<ellipse style="stroke: rgb(0, 0, 0); stroke-width: 1.06069; fill: rgba(30, 44, 177, 0.29);" cx="221.125" cy="238.49" rx="0.029" ry="0.023" id="ellipse28"/>
|
||||||
<rect style="stroke:#000000;stroke-width:1.06069" x="225.55846" y="233.32962" width="0.51665688" height="0.05516446" id="rect28"/>
|
<path d="M 122.157 273.821 L 110.66 296.382 L 85.375 291.958 L 64.458 333.031 L 80.851 354.896 L 69.648 376.905 L -1.173 277.936 L 10 255.993 L 122.157 273.821 Z M 66.622 288.681 L 25.571 280.959 L 52.344 316.714 L 66.622 288.681 Z M 157.01 172.988 L 142.536 188.852 C 139.761 185.572 136.833 183.737 133.752 183.347 C 130.664 182.964 127.553 183.965 124.419 186.348 C 120.261 189.51 117.91 193.651 117.368 198.77 C 116.833 203.889 118.837 210.243 123.381 217.833 C 128.434 226.276 133.262 231.285 137.865 232.859 C 142.467 234.426 146.89 233.598 151.134 230.377 C 154.3 227.964 156.288 224.975 157.098 221.408 C 157.901 217.841 157.235 213.262 155.1 207.673 L 173.393 198.351 C 176.768 208.132 177.336 217.028 175.097 225.037 C 172.851 233.039 167.664 240.129 159.536 246.307 C 150.305 253.324 140.979 255.637 131.558 253.246 C 122.131 250.849 113.944 243.843 106.998 232.23 C 99.967 220.485 97.248 209.247 98.84 198.516 C 100.433 187.793 105.927 178.86 115.322 171.719 C 123.012 165.879 130.243 163.099 137.013 163.379 C 143.789 163.658 150.455 166.861 157.01 172.988 Z M 205.415 174.521 C 206.343 167.056 208.879 160.088 213.025 153.615 C 217.164 147.143 222.455 142.543 228.899 139.814 C 235.349 137.078 242.269 136.295 249.659 137.464 C 261.071 139.274 269.901 144.929 276.149 154.432 C 282.397 163.941 284.727 175.069 283.141 187.815 C 281.535 200.671 276.521 210.743 268.099 218.032 C 259.684 225.32 249.888 228.078 238.711 226.306 C 231.797 225.21 225.422 222.404 219.586 217.888 C 213.756 213.38 209.63 207.463 207.208 200.138 C 204.792 192.82 204.195 184.281 205.415 174.521 Z M 225.716 178.967 C 224.665 187.396 225.634 194.129 228.624 199.167 C 231.621 204.212 235.721 207.147 240.924 207.971 C 246.134 208.794 250.782 207.246 254.869 203.326 C 258.956 199.406 261.531 193.176 262.596 184.638 C 263.64 176.319 262.677 169.641 259.707 164.603 C 256.736 159.565 252.646 156.631 247.436 155.8 C 242.233 154.976 237.575 156.524 233.462 160.444 C 229.349 164.364 226.767 170.539 225.716 178.967 Z M 307.447 255.353 L 290.486 243.086 L 331.645 170.87 L 347.391 182.266 L 341.545 192.537 C 347.003 189.639 351.247 188.197 354.276 188.212 C 357.305 188.227 360.191 189.223 362.933 191.202 C 366.791 193.997 369.827 197.891 372.04 202.885 L 357.292 215.748 C 355.627 211.593 353.567 208.629 351.113 206.856 C 348.736 205.135 346.304 204.415 343.817 204.694 C 341.323 204.973 338.506 206.698 335.366 209.868 C 332.226 213.038 327.156 220.764 320.158 233.047 L 307.447 255.353 Z M 369.18 352.359 L 360.328 333.781 L 370.189 327.812 C 364.881 327.047 360.289 325.132 356.411 322.065 C 352.539 318.998 349.585 315.331 347.548 311.066 C 343.409 302.38 342.968 293.061 346.226 283.11 C 349.49 273.152 356.682 264.812 367.8 258.089 C 379.179 251.205 389.262 248.988 398.05 251.437 C 406.844 253.879 413.434 259.704 417.821 268.912 C 421.849 277.362 422.215 286.56 418.918 296.503 L 452.282 276.314 L 461.82 296.316 L 369.18 352.359 Z M 378.738 277.793 C 371.576 282.125 366.928 286.372 364.793 290.535 C 361.699 296.566 361.529 302.479 364.284 308.274 C 366.484 312.879 370.088 315.74 375.095 316.857 C 380.109 317.983 386.073 316.457 392.987 312.279 C 400.697 307.616 405.499 302.692 407.392 297.507 C 409.292 292.322 409.076 287.288 406.746 282.404 C 404.487 277.66 400.919 274.696 396.042 273.512 C 391.165 272.336 385.397 273.762 378.738 277.793 Z" style="paint-order: stroke; stroke: rgb(71, 71, 71); stroke-linecap: round; stroke-linejoin: round; stroke-width: 4px; text-wrap-mode: nowrap; vector-effect: non-scaling-stroke; fill: rgba(30, 44, 177, 0.29);"/>
|
||||||
<path d="M 127.57 310.87 L 115.83 331.32 L 90.01 327.31 L 68.65 364.54 L 85.39 384.36 L 73.95 404.31 L 1.63 314.6 L 13.04 294.71 Z M 70.86 324.34 L 28.94 317.34 L 56.28 349.75 Z M 163.16 219.47 L 148.38 233.85 Q 144.13 229.39 139.41 228.86 Q 134.68 228.34 129.88 231.58 Q 123.51 235.88 122.68 242.84 Q 121.86 249.8 128.82 260.12 Q 136.56 271.6 143.61 273.74 Q 150.66 275.87 157.16 271.49 Q 162.01 268.21 163.25 263.36 Q 164.48 258.51 161.21 250.91 L 179.89 242.46 Q 185.06 255.76 181.63 266.65 Q 178.19 277.53 165.74 285.93 Q 151.6 295.47 137.17 292.22 Q 122.73 288.96 112.09 273.17 Q 101.32 257.2 103.76 242.61 Q 106.2 228.03 120.59 218.32 Q 132.37 210.38 142.74 210.76 Q 153.12 211.14 163.16 219.47 Z M 212.59 220.86 Q 214.01 210.71 220.36 201.91 Q 226.7 193.11 236.57 189.4 Q 246.45 185.68 257.77 187.27 Q 275.25 189.73 284.82 202.65 Q 294.39 215.58 291.96 232.91 Q 289.5 250.39 276.6 260.3 Q 263.71 270.21 246.59 267.8 Q 236 266.31 227.06 260.17 Q 218.13 254.04 214.42 244.08 Q 210.72 234.13 212.59 220.86 Z M 233.32 224.89 Q 231.71 236.35 236.29 243.2 Q 240.88 250.06 248.85 251.18 Q 256.83 252.3 263.09 246.97 Q 269.35 241.64 270.98 230.03 Q 272.58 218.72 268.03 211.87 Q 263.48 205.02 255.5 203.89 Q 247.53 202.77 241.23 208.1 Q 234.93 213.43 233.32 224.89 Z M 316.78 294.13 L 299.46 283.01 L 341.49 217.55 L 357.57 227.88 L 351.6 237.19 Q 359.96 233.25 364.6 233.27 Q 369.24 233.29 373.44 235.98 Q 379.35 239.78 382.74 246.57 L 367.68 258.23 Q 365.13 252.58 361.37 250.17 Q 357.73 247.83 353.92 248.21 Q 350.1 248.59 345.29 252.9 Q 340.48 257.21 329.76 273.91 Z M 379.82 382.06 L 370.78 365.22 L 380.85 359.81 Q 372.72 358.77 366.78 354.6 Q 360.85 350.43 357.73 344.63 Q 351.39 332.82 356.38 319.29 Q 361.38 305.75 378.41 296.61 Q 395.84 287.25 409.3 290.58 Q 422.77 293.9 429.49 306.42 Q 435.66 317.91 430.61 331.43 L 464.68 313.13 L 474.42 331.26 Z M 389.58 314.47 Q 378.61 320.36 375.34 326.02 Q 370.6 334.22 374.82 342.1 Q 378.19 348.36 385.86 349.88 Q 393.54 351.41 404.13 345.73 Q 415.94 339.39 418.84 332.34 Q 421.75 325.29 418.18 318.65 Q 414.72 312.2 407.25 310.59 Q 399.78 308.99 389.58 314.47 Z" style="fill: url("#gradient-1"); paint-order: fill; stroke: rgb(0, 0, 0); stroke-linecap: round; stroke-linejoin: round; stroke-width: 0px; text-wrap-mode: nowrap; vector-effect: non-scaling-stroke;" transform="matrix(0.999336, 0, 0, 1.125805, -1.747034, -80.556085)"/>
|
<rect style="stroke: rgb(0, 0, 0); stroke-width: 1.06069; fill: rgba(30, 44, 177, 0.29);" x="220.871" y="238.463" width="0.506" height="0.054" id="rect28"/>
|
||||||
|
<path d="M 122.979 273.832 L 111.482 296.392 L 86.197 291.969 L 65.279 333.041 L 81.673 354.907 L 70.47 376.916 L -0.352 277.947 L 10.822 256.004 L 122.979 273.832 Z M 67.444 288.692 L 26.392 280.97 L 53.166 316.725 L 67.444 288.692 Z M 157.831 172.998 L 143.357 188.862 C 140.583 185.582 137.655 183.747 134.573 183.357 C 131.485 182.975 128.374 183.975 125.241 186.358 C 121.082 189.521 118.732 193.661 118.19 198.78 C 117.655 203.899 119.659 210.254 124.203 217.844 C 129.256 226.287 134.084 231.296 138.686 232.87 C 143.289 234.436 147.712 233.609 151.956 230.387 C 155.122 227.975 157.11 224.985 157.919 221.418 C 158.722 217.851 158.056 213.273 155.922 207.683 L 174.215 198.361 C 177.59 208.143 178.158 217.038 175.919 225.048 C 173.673 233.05 168.486 240.14 160.358 246.318 C 151.126 253.334 141.8 255.647 132.38 253.257 C 122.953 250.859 114.766 243.854 107.819 232.241 C 100.788 220.495 98.069 209.257 99.662 198.527 C 101.255 187.803 106.749 178.871 116.143 171.73 C 123.834 165.89 131.064 163.11 137.834 163.389 C 144.611 163.669 151.277 166.872 157.831 172.998 Z M 206.237 174.532 C 207.164 167.067 209.7 160.098 213.846 153.626 C 217.985 147.154 223.276 142.553 229.72 139.825 C 236.17 137.089 243.091 136.306 250.481 137.475 C 261.893 139.284 270.723 144.94 276.97 154.442 C 283.218 163.952 285.549 175.08 283.962 187.825 C 282.356 200.682 277.343 210.754 268.921 218.042 C 260.505 225.331 250.709 228.089 239.533 226.316 C 232.619 225.221 226.244 222.415 220.407 217.899 C 214.577 213.391 210.451 207.474 208.029 200.148 C 205.614 192.83 205.016 184.292 206.237 174.532 Z M 226.537 178.978 C 225.486 187.406 226.456 194.139 229.446 199.177 C 232.443 204.223 236.542 207.157 241.746 207.981 C 246.955 208.805 251.604 207.257 255.691 203.337 C 259.778 199.417 262.353 193.187 263.417 184.648 C 264.462 176.33 263.499 169.652 260.528 164.614 C 257.558 159.576 253.468 156.641 248.258 155.81 C 243.055 154.987 238.397 156.535 234.284 160.455 C 230.171 164.375 227.589 170.549 226.537 178.978 Z M 308.268 255.364 L 291.307 243.096 L 332.466 170.88 L 348.213 182.276 L 342.367 192.547 C 347.825 189.649 352.068 188.208 355.097 188.223 C 358.127 188.237 361.012 189.234 363.754 191.212 C 367.613 194.007 370.648 197.901 372.861 202.895 L 358.114 215.759 C 356.449 211.603 354.389 208.639 351.934 206.867 C 349.558 205.146 347.126 204.425 344.639 204.705 C 342.145 204.984 339.328 206.709 336.187 209.879 C 333.047 213.049 327.978 220.775 320.979 233.057 L 308.268 255.364 Z M 370.002 352.369 L 361.149 333.791 L 371.011 327.823 C 365.703 327.058 361.11 325.142 357.232 322.075 C 353.361 319.008 350.407 315.342 348.37 311.076 C 344.231 302.39 343.79 293.072 347.048 283.121 C 350.312 273.162 357.503 264.822 368.621 258.1 C 380 251.216 390.084 248.998 398.871 251.448 C 407.665 253.889 414.256 259.714 418.643 268.922 C 422.671 277.373 423.037 286.57 419.74 296.514 L 453.104 276.325 L 462.642 296.326 L 370.002 352.369 Z M 379.56 277.803 C 372.398 282.135 367.75 286.383 365.615 290.545 C 362.52 296.576 362.351 302.49 365.106 308.285 C 367.306 312.889 370.909 315.75 375.917 316.868 C 380.931 317.993 386.895 316.467 393.808 312.29 C 401.518 307.627 406.32 302.703 408.213 297.518 C 410.113 292.333 409.898 287.298 407.567 282.415 C 405.308 277.671 401.74 274.707 396.864 273.523 C 391.987 272.346 386.219 273.773 379.56 277.803 Z" style="stroke-linecap: round; stroke-linejoin: round; text-wrap-mode: nowrap; fill: rgb(255, 116, 162); paint-order: stroke; stroke-width: 10.1573px; stroke: rgb(0, 0, 0); filter: url("#drop-shadow-filter-1"); mix-blend-mode: lighten;"/>
|
||||||
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
|
|
@ -4,12 +4,11 @@ use std::time::Instant;
|
||||||
|
|
||||||
use iced_wgpu::core::keyboard::{self, Modifiers};
|
use iced_wgpu::core::keyboard::{self, Modifiers};
|
||||||
use iced_wgpu::core::keyboard::key;
|
use iced_wgpu::core::keyboard::key;
|
||||||
use iced_wgpu::core::text::{Highlight, LineHeight, Wrapping};
|
use iced_wgpu::core::text::{Highlight, Wrapping};
|
||||||
use iced_wgpu::core::{
|
use iced_wgpu::core::{
|
||||||
border, padding, alignment, Background, Border, Color, Element, Font, Length,
|
border, padding, alignment, Background, Border, Color, Element, Font, Length,
|
||||||
Padding, Pixels, Point, Rectangle, Shadow, Theme,
|
Padding, Point, Shadow, Theme,
|
||||||
};
|
};
|
||||||
use iced_widget::canvas;
|
|
||||||
use iced_widget::container;
|
use iced_widget::container;
|
||||||
use iced_widget::markdown;
|
use iced_widget::markdown;
|
||||||
use iced_widget::MouseArea;
|
use iced_widget::MouseArea;
|
||||||
|
|
@ -25,7 +24,7 @@ use crate::hr_block::HrBlock;
|
||||||
use crate::oklab;
|
use crate::oklab;
|
||||||
use crate::palette;
|
use crate::palette;
|
||||||
use crate::sidecar::{self, Sidecar, TableSidecar};
|
use crate::sidecar::{self, Sidecar, TableSidecar};
|
||||||
use crate::syntax::{self, SyntaxHighlighter, SyntaxSettings, LineDecor, compute_line_decors};
|
use crate::syntax::{self, SyntaxHighlighter, SyntaxSettings, compute_line_decors};
|
||||||
use crate::table_block::{self, TableBlock, TableMessage};
|
use crate::table_block::{self, TableBlock, TableMessage};
|
||||||
use crate::text_block::TextBlock;
|
use crate::text_block::TextBlock;
|
||||||
use crate::tree_block::TreeBlock;
|
use crate::tree_block::TreeBlock;
|
||||||
|
|
@ -4151,247 +4150,6 @@ fn context_menu_item_style(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vim-style cursorline overlay. Renders the editor's base background and a
|
|
||||||
/// highlight band behind the focused logical line. Sits underneath the
|
|
||||||
/// `text_editor` in a `Stack` so the line shows through the editor's
|
|
||||||
/// transparent background.
|
|
||||||
///
|
|
||||||
/// Wrapped lines render the highlight at the LOGICAL line's first visual row,
|
|
||||||
/// not at every visual row of a soft-wrapped span — iced doesn't expose the
|
|
||||||
/// per-visual-row layout coordinates from cosmic-text yet.
|
|
||||||
struct Cursorline {
|
|
||||||
cursor_line: Option<usize>,
|
|
||||||
font_size: f32,
|
|
||||||
top_pad: f32,
|
|
||||||
/// (after_line, height) pairs from anchored children — shifts y for lines below.
|
|
||||||
item_offsets: Vec<(usize, f32)>,
|
|
||||||
/// `Off` suppresses the row-highlight band; `On` and `Vim` show it.
|
|
||||||
indicator: LineIndicator,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl canvas::Program<Message, Theme, iced_wgpu::Renderer> for Cursorline {
|
|
||||||
type State = ();
|
|
||||||
|
|
||||||
fn draw(
|
|
||||||
&self,
|
|
||||||
_state: &(),
|
|
||||||
renderer: &iced_wgpu::Renderer,
|
|
||||||
_theme: &Theme,
|
|
||||||
bounds: Rectangle,
|
|
||||||
_cursor: iced_wgpu::core::mouse::Cursor,
|
|
||||||
) -> Vec<canvas::Geometry<iced_wgpu::Renderer>> {
|
|
||||||
let mut frame = canvas::Frame::new(renderer, bounds.size());
|
|
||||||
let p = palette::current();
|
|
||||||
|
|
||||||
// Page background — replaces the text_editor's own bg, which is set
|
|
||||||
// transparent so this canvas shows through.
|
|
||||||
frame.fill_rectangle(Point::ORIGIN, bounds.size(), p.base);
|
|
||||||
|
|
||||||
if let Some(line) = self.cursor_line {
|
|
||||||
if self.indicator != LineIndicator::Off {
|
|
||||||
let lh = self.font_size * 1.3;
|
|
||||||
let extra: f32 = self.item_offsets.iter()
|
|
||||||
.filter(|(after, _)| *after < line)
|
|
||||||
.map(|(_, h)| h)
|
|
||||||
.sum();
|
|
||||||
let y = self.top_pad + line as f32 * lh + extra;
|
|
||||||
if y < bounds.height && y + lh > 0.0 {
|
|
||||||
// ~6% tint of the foreground color. Reads as a faint band in
|
|
||||||
// both light and dark themes without screaming.
|
|
||||||
let band = Color { a: 0.06, ..p.text };
|
|
||||||
frame.fill_rectangle(
|
|
||||||
Point::new(0.0, y),
|
|
||||||
iced_wgpu::core::Size::new(bounds.width, lh),
|
|
||||||
band,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vec![frame.into_geometry()]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Gutter {
|
|
||||||
line_count: usize,
|
|
||||||
global_line_offset: usize,
|
|
||||||
font_size: f32,
|
|
||||||
scroll_offset: f32,
|
|
||||||
/// Cursor line within this block, only when the block is focused. Drives
|
|
||||||
/// the rainbow line-number coloring; `None` falls back to a flat dim hue.
|
|
||||||
cursor_line: Option<usize>,
|
|
||||||
top_pad: f32,
|
|
||||||
line_decors: Vec<LineDecor>,
|
|
||||||
item_offsets: Vec<(usize, f32)>,
|
|
||||||
indicator: LineIndicator,
|
|
||||||
rainbow: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Distance-driven fade ratio for the gutter rainbow. `0.0` at the cursor
|
|
||||||
/// (full saturation), `1.0` at the far end of the fade window (fully grey).
|
|
||||||
/// Width is 2.5 full passes through the shared 8-slot palette.
|
|
||||||
const GUTTER_FADE_CYCLES: f32 = 2.5;
|
|
||||||
|
|
||||||
fn gutter_fade_t(distance: usize) -> f32 {
|
|
||||||
let max_d = GUTTER_FADE_CYCLES * syntax::USER_IDENT_PALETTE_SIZE as f32;
|
|
||||||
(distance as f32 / max_d).min(1.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Gutter {
|
|
||||||
fn gutter_width(&self) -> f32 {
|
|
||||||
let total = self.global_line_offset + self.line_count;
|
|
||||||
let count = if total == 0 { 1 } else { total };
|
|
||||||
let digits = (count as f32).log10().floor() as usize + 1;
|
|
||||||
let char_width = self.font_size * 0.6;
|
|
||||||
(digits.max(2) as f32 * char_width + 16.0).ceil()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl canvas::Program<Message, Theme, iced_wgpu::Renderer> for Gutter {
|
|
||||||
type State = ();
|
|
||||||
|
|
||||||
fn draw(
|
|
||||||
&self,
|
|
||||||
_state: &(),
|
|
||||||
renderer: &iced_wgpu::Renderer,
|
|
||||||
_theme: &Theme,
|
|
||||||
bounds: Rectangle,
|
|
||||||
_cursor: iced_wgpu::core::mouse::Cursor,
|
|
||||||
) -> Vec<canvas::Geometry<iced_wgpu::Renderer>> {
|
|
||||||
let mut frame = canvas::Frame::new(renderer, bounds.size());
|
|
||||||
let lh = self.font_size * 1.3;
|
|
||||||
|
|
||||||
// Fill the gutter background only below `top_pad` — the first block
|
|
||||||
// reserves that strip for the titlebar / traffic-light buttons, and
|
|
||||||
// painting it in crust draws an awkward rectangle behind the system
|
|
||||||
// window controls.
|
|
||||||
if self.top_pad < bounds.height {
|
|
||||||
frame.fill_rectangle(
|
|
||||||
Point::new(0.0, self.top_pad),
|
|
||||||
iced_wgpu::core::Size::new(bounds.width, bounds.height - self.top_pad),
|
|
||||||
palette::current().crust,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let visible_count = (bounds.height / lh).ceil() as usize + 1;
|
|
||||||
// Locally clamp `scroll_offset` against the gutter's own bounds —
|
|
||||||
// the editor's `Action::Scroll` ceiling uses `(line_count - 1) * lh`,
|
|
||||||
// which over-scrolls short documents (gutter slides off the top,
|
|
||||||
// shows empty). Keep the same first-line / sub-pixel math but on the
|
|
||||||
// bounded value so the gutter never disappears.
|
|
||||||
let content_h = self.line_count as f32 * lh;
|
|
||||||
let max_scroll = (content_h - bounds.height + self.top_pad).max(0.0);
|
|
||||||
let eff_scroll = self.scroll_offset.min(max_scroll);
|
|
||||||
let first_visible = (eff_scroll / lh).floor() as usize;
|
|
||||||
let sub_pixel = eff_scroll - first_visible as f32 * lh;
|
|
||||||
|
|
||||||
let gw = self.gutter_width();
|
|
||||||
|
|
||||||
for i in 0..visible_count {
|
|
||||||
let line_idx = first_visible + i;
|
|
||||||
if line_idx >= self.line_count {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
let line_num = self.global_line_offset + line_idx;
|
|
||||||
let extra: f32 = self.item_offsets.iter()
|
|
||||||
.filter(|(after, _)| *after < line_idx)
|
|
||||||
.map(|(_, h)| h)
|
|
||||||
.sum();
|
|
||||||
let y = self.top_pad + i as f32 * lh - sub_pixel + extra;
|
|
||||||
if y + lh < 0.0 || y > bounds.height {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let decor = if line_idx < self.line_decors.len() {
|
|
||||||
self.line_decors[line_idx]
|
|
||||||
} else {
|
|
||||||
LineDecor::None
|
|
||||||
};
|
|
||||||
let p = palette::current();
|
|
||||||
|
|
||||||
match decor {
|
|
||||||
LineDecor::CodeBlock | LineDecor::FenceMarker => {
|
|
||||||
frame.fill_rectangle(
|
|
||||||
Point::new(0.0, y),
|
|
||||||
iced_wgpu::core::Size::new(gw, lh),
|
|
||||||
Color { a: 0.15, ..p.surface2 },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
LineDecor::Blockquote => {
|
|
||||||
frame.fill_rectangle(
|
|
||||||
Point::new(gw - 3.0, y),
|
|
||||||
iced_wgpu::core::Size::new(3.0, lh),
|
|
||||||
p.lavender,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
LineDecor::HorizontalRule => {
|
|
||||||
let mid_y = y + lh / 2.0;
|
|
||||||
let path = canvas::Path::line(
|
|
||||||
Point::new(4.0, mid_y),
|
|
||||||
Point::new(gw - 4.0, mid_y),
|
|
||||||
);
|
|
||||||
frame.stroke(&path, canvas::Stroke::default()
|
|
||||||
.with_width(1.0)
|
|
||||||
.with_color(oklab::lighten_for_size(p.overlay1, 1.0)));
|
|
||||||
}
|
|
||||||
LineDecor::None => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// `Off` skips the number entirely — gutter strip stays for
|
|
||||||
// layout (and decors still draw above), but no digits.
|
|
||||||
if self.indicator == LineIndicator::Off {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let raw_color = if self.rainbow {
|
|
||||||
match self.cursor_line {
|
|
||||||
Some(cl) if line_idx == cl => p.text,
|
|
||||||
Some(cl) if line_idx > cl => {
|
|
||||||
let d = line_idx - cl - 1;
|
|
||||||
let hue = syntax::rainbow_color(d as u32);
|
|
||||||
oklab::desaturate(hue, gutter_fade_t(d))
|
|
||||||
}
|
|
||||||
Some(cl) /* line_idx < cl */ => {
|
|
||||||
let d = cl - line_idx - 1;
|
|
||||||
let hue = oklab::invert_hue(syntax::rainbow_color(d as u32));
|
|
||||||
oklab::desaturate(hue, gutter_fade_t(d))
|
|
||||||
}
|
|
||||||
None => p.surface2,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Plain gutter: cursor line bright, others dim.
|
|
||||||
match self.cursor_line {
|
|
||||||
Some(cl) if line_idx == cl => p.text,
|
|
||||||
_ => p.surface2,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Vim mode: relative numbers everywhere except the cursor line
|
|
||||||
// itself, which stays absolute (the standard vim hybrid look).
|
|
||||||
let label = match (self.indicator, self.cursor_line) {
|
|
||||||
(LineIndicator::Vim, Some(cl)) if line_idx != cl => {
|
|
||||||
let d = if line_idx > cl { line_idx - cl } else { cl - line_idx };
|
|
||||||
format!("{d}")
|
|
||||||
}
|
|
||||||
_ => format!("{}", line_num + 1),
|
|
||||||
};
|
|
||||||
frame.fill_text(canvas::Text {
|
|
||||||
content: label,
|
|
||||||
position: Point::new(gw - 8.0, y),
|
|
||||||
max_width: gw,
|
|
||||||
color: oklab::lighten_for_size(raw_color, self.font_size),
|
|
||||||
size: Pixels(self.font_size),
|
|
||||||
line_height: LineHeight::Relative(1.3),
|
|
||||||
font: Font::MONOSPACE,
|
|
||||||
align_x: iced_wgpu::core::text::Alignment::Right,
|
|
||||||
align_y: alignment::Vertical::Top,
|
|
||||||
shaping: iced_wgpu::core::text::Shaping::Basic,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
vec![frame.into_geometry()]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip obsolete inline-result lines from documents saved before eval
|
// Strip obsolete inline-result lines from documents saved before eval
|
||||||
// results moved into anchored child elements.
|
// results moved into anchored child elements.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,11 @@ pub struct ViewportHandle {
|
||||||
pub needs_redraw: bool,
|
pub needs_redraw: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Install a panic hook that flushes a full backtrace to stderr before
|
/// Install a panic hook that flushes a full backtrace to stderr AND to
|
||||||
/// the process aborts. Called once on first viewport_create. Without this
|
/// `~/.acord/crash.log` before the process aborts. Called once on first
|
||||||
/// the host (Swift / winit) often eats the panic message and the user sees
|
/// viewport_create. Without the file fallback, the Windows release build
|
||||||
/// only a silent SIGABRT with no `.ips` file.
|
/// (`#![windows_subsystem = "windows"]`) detaches the console and stderr
|
||||||
|
/// goes nowhere — users get a silent crash with no diagnostic surface.
|
||||||
fn install_panic_hook() {
|
fn install_panic_hook() {
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
static ONCE: Once = Once::new();
|
static ONCE: Once = Once::new();
|
||||||
|
|
@ -59,18 +60,45 @@ fn install_panic_hook() {
|
||||||
let prior = std::panic::take_hook();
|
let prior = std::panic::take_hook();
|
||||||
std::panic::set_hook(Box::new(move |info| {
|
std::panic::set_hook(Box::new(move |info| {
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
let mut err = std::io::stderr().lock();
|
|
||||||
let _ = writeln!(err, "===== ACORD RUST PANIC =====");
|
|
||||||
let _ = writeln!(err, "{}", info);
|
|
||||||
let bt = std::backtrace::Backtrace::force_capture();
|
let bt = std::backtrace::Backtrace::force_capture();
|
||||||
let _ = writeln!(err, "{}", bt);
|
let header = "===== ACORD RUST PANIC =====";
|
||||||
let _ = writeln!(err, "============================");
|
let footer = "============================";
|
||||||
let _ = err.flush();
|
{
|
||||||
|
let mut err = std::io::stderr().lock();
|
||||||
|
let _ = writeln!(err, "{}", header);
|
||||||
|
let _ = writeln!(err, "{}", info);
|
||||||
|
let _ = writeln!(err, "{}", bt);
|
||||||
|
let _ = writeln!(err, "{}", footer);
|
||||||
|
let _ = err.flush();
|
||||||
|
}
|
||||||
|
if let Some(home) = dirs::home_dir() {
|
||||||
|
let dir = home.join(".acord");
|
||||||
|
let _ = std::fs::create_dir_all(&dir);
|
||||||
|
let path = dir.join("crash.log");
|
||||||
|
if let Ok(mut f) = std::fs::OpenOptions::new()
|
||||||
|
.create(true).append(true).open(&path)
|
||||||
|
{
|
||||||
|
let _ = writeln!(f, "{} {}", header, chrono_now());
|
||||||
|
let _ = writeln!(f, "{}", info);
|
||||||
|
let _ = writeln!(f, "{}", bt);
|
||||||
|
let _ = writeln!(f, "{}", footer);
|
||||||
|
}
|
||||||
|
}
|
||||||
prior(info);
|
prior(info);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Best-effort timestamp for the crash log header. Avoids pulling chrono
|
||||||
|
/// for one line — uses SystemTime::now() epoch seconds as a stable suffix.
|
||||||
|
fn chrono_now() -> String {
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.map(|d| format!("(epoch {}s)", d.as_secs()))
|
||||||
|
.unwrap_or_else(|_| String::from("(time unavailable)"))
|
||||||
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn viewport_create(
|
pub extern "C" fn viewport_create(
|
||||||
nsview: *mut c_void,
|
nsview: *mut c_void,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$root = Split-Path -Parent $PSScriptRoot
|
||||||
|
Set-Location $root
|
||||||
|
|
||||||
|
Write-Host "Building Rust workspace (release)..."
|
||||||
|
cargo build --release -p acord-windows
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "cargo build failed" }
|
||||||
|
|
||||||
|
$exe = Join-Path $root "target\release\acord.exe"
|
||||||
|
if (-not (Test-Path $exe)) { throw "binary not found at $exe" }
|
||||||
|
|
||||||
|
# Rasterize the SVG icon next to the exe so load_window_icon picks it up.
|
||||||
|
# Falls back silently if rsvg-convert isn't installed.
|
||||||
|
$svg = Join-Path $root "assets\Acord.svg"
|
||||||
|
$png = Join-Path (Split-Path -Parent $exe) "icon.png"
|
||||||
|
if (Test-Path $svg) {
|
||||||
|
if (Get-Command rsvg-convert -ErrorAction SilentlyContinue) {
|
||||||
|
Write-Host "Rasterizing icon..."
|
||||||
|
rsvg-convert --width 256 --height 256 $svg -o $png
|
||||||
|
} else {
|
||||||
|
Write-Host "rsvg-convert not found on PATH; skipping icon rasterization"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Built: $exe"
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
$root = Split-Path -Parent $PSScriptRoot
|
||||||
|
Set-Location $root
|
||||||
|
|
||||||
|
Write-Host "Building Rust workspace (debug)..."
|
||||||
|
$env:RUST_BACKTRACE = "1"
|
||||||
|
cargo build -p acord-windows
|
||||||
|
if ($LASTEXITCODE -ne 0) { throw "cargo build failed" }
|
||||||
|
|
||||||
|
$exe = Join-Path $root "target\debug\acord.exe"
|
||||||
|
if (-not (Test-Path $exe)) { throw "binary not found at $exe" }
|
||||||
|
|
||||||
|
# Same icon rasterization as build.ps1 — debug builds want the icon too.
|
||||||
|
$svg = Join-Path $root "assets\Acord.svg"
|
||||||
|
$png = Join-Path (Split-Path -Parent $exe) "icon.png"
|
||||||
|
if (Test-Path $svg) {
|
||||||
|
if (Get-Command rsvg-convert -ErrorAction SilentlyContinue) {
|
||||||
|
rsvg-convert --width 256 --height 256 $svg -o $png
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Foreground exec so panic output (RUST_BACKTRACE=1) lands in this terminal
|
||||||
|
# rather than vanishing on a detached console. Debug builds use the
|
||||||
|
# `console` subsystem by default so stderr is wired up automatically.
|
||||||
|
Write-Host "Launching $exe ..."
|
||||||
|
& $exe
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
use std::ffi::{c_void, CString};
|
use std::ffi::CString;
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
use std::ffi::c_void;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use winit::application::ApplicationHandler;
|
use winit::application::ApplicationHandler;
|
||||||
use winit::dpi::{LogicalSize, PhysicalPosition};
|
use winit::dpi::{LogicalSize, PhysicalPosition};
|
||||||
|
|
@ -26,6 +30,9 @@ pub struct App {
|
||||||
cursor_pos: PhysicalPosition<f64>,
|
cursor_pos: PhysicalPosition<f64>,
|
||||||
scale: f32,
|
scale: f32,
|
||||||
modifiers: ModifiersState,
|
modifiers: ModifiersState,
|
||||||
|
current_file: Option<PathBuf>,
|
||||||
|
last_autosave_attempt: Instant,
|
||||||
|
last_autosaved_hash: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
|
|
@ -38,6 +45,9 @@ impl App {
|
||||||
cursor_pos: PhysicalPosition::new(0.0, 0.0),
|
cursor_pos: PhysicalPosition::new(0.0, 0.0),
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
modifiers: ModifiersState::empty(),
|
modifiers: ModifiersState::empty(),
|
||||||
|
current_file: None,
|
||||||
|
last_autosave_attempt: Instant::now(),
|
||||||
|
last_autosaved_hash: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,28 +116,39 @@ impl App {
|
||||||
let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("Acord");
|
let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("Acord");
|
||||||
w.set_title(&format!("{name} - Acord"));
|
w.set_title(&format!("{name} - Acord"));
|
||||||
}
|
}
|
||||||
|
self.current_file = Some(path);
|
||||||
|
self.last_autosaved_hash = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_file(&self) {
|
fn save_file(&mut self) {
|
||||||
self.save_file_as();
|
match self.current_file.clone() {
|
||||||
|
Some(path) => self.write_to(&path),
|
||||||
|
None => self.save_file_as(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn save_file_as(&self) {
|
fn save_file_as(&mut self) {
|
||||||
let dialog = rfd::FileDialog::new()
|
let dialog = rfd::FileDialog::new()
|
||||||
.add_filter("Markdown", &["md"])
|
.add_filter("Markdown", &["md"])
|
||||||
.add_filter("All Files", &["*"])
|
.add_filter("All Files", &["*"])
|
||||||
.set_file_name("note.md");
|
.set_file_name("note.md");
|
||||||
if let Some(path) = dialog.save_file() {
|
if let Some(path) = dialog.save_file() {
|
||||||
let text_ptr = viewport_get_text(self.handle);
|
self.write_to(&path);
|
||||||
if !text_ptr.is_null() {
|
self.current_file = Some(path);
|
||||||
let text = unsafe { std::ffi::CStr::from_ptr(text_ptr) }
|
}
|
||||||
.to_string_lossy()
|
}
|
||||||
.into_owned();
|
|
||||||
viewport_free_string(text_ptr);
|
fn write_to(&mut self, path: &std::path::Path) {
|
||||||
let _ = std::fs::write(&path, text);
|
let text_ptr = viewport_get_text(self.handle);
|
||||||
}
|
if text_ptr.is_null() { return; }
|
||||||
|
let text = unsafe { std::ffi::CStr::from_ptr(text_ptr) }
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned();
|
||||||
|
viewport_free_string(text_ptr);
|
||||||
|
if std::fs::write(path, &text).is_ok() {
|
||||||
|
self.last_autosaved_hash = Some(text_hash(&text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,6 +158,35 @@ impl App {
|
||||||
if let Some(w) = &self.window {
|
if let Some(w) = &self.window {
|
||||||
w.set_title("Acord");
|
w.set_title("Acord");
|
||||||
}
|
}
|
||||||
|
self.current_file = None;
|
||||||
|
self.last_autosaved_hash = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hash-gated autosave. Mirrors the macOS Swift `persistViewportToNotesDir`:
|
||||||
|
/// fires on a poll cadence, skips the disk write when the buffer hash
|
||||||
|
/// matches the last saved value. Without the hash gate this would rewrite
|
||||||
|
/// the note every poll tick (~MB/s on a busy doc).
|
||||||
|
fn try_autosave(&mut self) {
|
||||||
|
if self.handle.is_null() { return; }
|
||||||
|
let text_ptr = viewport_get_text(self.handle);
|
||||||
|
if text_ptr.is_null() { return; }
|
||||||
|
let text = unsafe { std::ffi::CStr::from_ptr(text_ptr) }
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned();
|
||||||
|
viewport_free_string(text_ptr);
|
||||||
|
|
||||||
|
let hash = text_hash(&text);
|
||||||
|
if Some(hash) == self.last_autosaved_hash { return; }
|
||||||
|
|
||||||
|
let path = self.current_file.clone().unwrap_or_else(|| {
|
||||||
|
self.config.notes_dir().join("Untitled.md")
|
||||||
|
});
|
||||||
|
if let Some(parent) = path.parent() {
|
||||||
|
let _ = std::fs::create_dir_all(parent);
|
||||||
|
}
|
||||||
|
if std::fs::write(&path, &text).is_ok() {
|
||||||
|
self.last_autosaved_hash = Some(hash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn winit_button(button: MouseButton) -> u8 {
|
fn winit_button(button: MouseButton) -> u8 {
|
||||||
|
|
@ -299,6 +349,13 @@ impl ApplicationHandler for App {
|
||||||
while let Some(action) = AppMenu::poll() {
|
while let Some(action) = AppMenu::poll() {
|
||||||
self.dispatch_menu(action, _event_loop);
|
self.dispatch_menu(action, _event_loop);
|
||||||
}
|
}
|
||||||
|
// Hash-gated autosave on a 500ms cadence. The hash skip means
|
||||||
|
// an idle doc doesn't tick the disk; a typing doc writes once
|
||||||
|
// per cadence regardless of keystroke rate.
|
||||||
|
if self.last_autosave_attempt.elapsed() >= Duration::from_millis(500) {
|
||||||
|
self.last_autosave_attempt = Instant::now();
|
||||||
|
self.try_autosave();
|
||||||
|
}
|
||||||
// Request a redraw if the viewport has pending work.
|
// Request a redraw if the viewport has pending work.
|
||||||
if let Some(w) = &self.window {
|
if let Some(w) = &self.window {
|
||||||
if !self.handle.is_null() {
|
if !self.handle.is_null() {
|
||||||
|
|
@ -313,6 +370,13 @@ impl ApplicationHandler for App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn text_hash(s: &str) -> u64 {
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
|
let mut h = std::collections::hash_map::DefaultHasher::new();
|
||||||
|
s.hash(&mut h);
|
||||||
|
h.finish()
|
||||||
|
}
|
||||||
|
|
||||||
/// Map winit logical keys to the macOS-style keycodes the bridge expects.
|
/// Map winit logical keys to the macOS-style keycodes the bridge expects.
|
||||||
/// For Named keys, return the matching keycode. For character keys, the
|
/// For Named keys, return the matching keycode. For character keys, the
|
||||||
/// bridge ignores the keycode and uses the text parameter directly, so
|
/// bridge ignores the keycode and uses the text parameter directly, so
|
||||||
|
|
@ -357,6 +421,10 @@ fn encode_modifiers(state: ModifiersState) -> u32 {
|
||||||
if state.control_key() { flags |= 1 << 18; }
|
if state.control_key() { flags |= 1 << 18; }
|
||||||
if state.alt_key() { flags |= 1 << 19; }
|
if state.alt_key() { flags |= 1 << 19; }
|
||||||
if state.super_key() { flags |= 1 << 20; }
|
if state.super_key() { flags |= 1 << 20; }
|
||||||
|
// Mirror Ctrl→LOGO so the viewport's `modifiers.logo()` shortcut arms fire.
|
||||||
|
// Matches `decode_winit_modifiers` below; without this, only menu-accelerated
|
||||||
|
// shortcuts (B/I/T) reach the viewport on Windows.
|
||||||
|
if state.control_key() { flags |= 1 << 20; }
|
||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ impl AppMenu {
|
||||||
let view = Submenu::new("View", true);
|
let view = Submenu::new("View", true);
|
||||||
view.append(&MenuItem::with_id("zoom_in", "Zoom In", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::Equal)))).ok();
|
view.append(&MenuItem::with_id("zoom_in", "Zoom In", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::Equal)))).ok();
|
||||||
view.append(&MenuItem::with_id("zoom_out", "Zoom Out", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::Minus)))).ok();
|
view.append(&MenuItem::with_id("zoom_out", "Zoom Out", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::Minus)))).ok();
|
||||||
view.append(&MenuItem::with_id("zoom_reset", "Reset Zoom", true, Some(Accelerator::new(Some(Modifiers::CONTROL), Code::Digit0)))).ok();
|
view.append(&MenuItem::with_id("zoom_reset", "Reset Zoom", true, Some(Accelerator::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::Digit0)))).ok();
|
||||||
|
|
||||||
menu.append(&file).ok();
|
menu.append(&file).ok();
|
||||||
menu.append(&edit).ok();
|
menu.append(&edit).ok();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue