posts
128
images/qt.svg
Normal file
|
@ -0,0 +1,128 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
|
||||
<g transform="matrix(1,0,0,1,0,-589.074)">
|
||||
<g id="Artboard1" transform="matrix(1,0,0,1,0,589.074)">
|
||||
<rect x="0" y="0" width="512" height="512" style="fill:none;"/>
|
||||
<clipPath id="_clip1">
|
||||
<rect x="0" y="0" width="512" height="512"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip1)">
|
||||
<g id="Layer1" transform="matrix(1,0,0,1,0,-589.074)">
|
||||
<g transform="matrix(0.965008,0,0,0.965008,23.2392,71.4057)">
|
||||
<path d="M370.679,738.299C456.871,761.639 422.713,878.823 422.713,878.823L275.848,878.251C261.223,935.304 343.256,947.547 331.884,1040.16L48.842,1041.06C10.744,1005.07 77.185,889.061 91.071,867.709C91.071,867.709 17.974,777.383 121.465,693.125C219.402,613.39 284.488,714.959 370.679,738.299Z" style="fill:rgb(106,163,145);"/>
|
||||
<path d="M377.884,711.693C336.293,700.43 300.054,669.785 262.138,652.082C214,629.607 164.062,622.901 104.062,671.749C67.119,701.826 49.678,732.963 42.535,761.243C30.962,807.062 46.794,846.723 58.684,868.134C43.249,895.242 17.657,946.156 11.292,987.599C6.554,1018.45 12.699,1044.84 29.913,1061.1C35.052,1065.96 41.86,1068.65 48.93,1068.63L331.972,1067.72C345.863,1067.68 357.55,1057.31 359.243,1043.52C366.154,987.234 345.224,955.205 324.246,928.746C317.981,920.843 311.7,913.643 306.933,906.122C306.893,906.06 306.854,905.998 306.815,905.936C306.815,905.936 422.605,906.387 422.605,906.387C434.897,906.435 445.736,898.338 449.176,886.536C449.176,886.536 463.389,837.158 453.114,791.761C445.218,756.873 424.397,724.288 377.884,711.693ZM370.679,738.299C456.871,761.639 422.713,878.823 422.713,878.823L275.848,878.251C261.223,935.304 343.256,947.547 331.884,1040.16L48.842,1041.06C10.744,1005.07 77.185,889.061 91.071,867.709C91.071,867.709 17.974,777.383 121.465,693.125C219.402,613.39 284.488,714.959 370.679,738.299Z"/>
|
||||
</g>
|
||||
<g transform="matrix(0.965008,0,0,0.965008,23.2392,84.9158)">
|
||||
<path d="M349.012,809.299C348.694,825.035 352.045,850.739 376.405,851.227C376.405,851.227 382.456,851.451 382.671,851.246L382.671,909.882C386.372,942.314 390.849,949.228 422.075,947.254L440.018,922.172L458.968,946.8C469.376,947.243 472.354,936.796 472.952,916.37L473.831,867.082C473.308,824.468 470.519,810.706 432.434,810.998L349.012,809.299Z" style="fill:rgb(234,167,208);"/>
|
||||
<path d="M355.106,874.532L355.106,909.882C355.106,910.926 355.165,911.969 355.284,913.007C358.14,938.034 364.005,952.328 372.47,960.872C382.012,970.502 396.654,976.481 423.814,974.764C430.191,974.361 436.169,971.761 440.774,967.494C445.456,971.624 451.452,974.069 457.795,974.339C479.971,975.284 499.23,960.699 500.505,917.177C500.508,917.072 500.511,916.967 500.512,916.861L501.391,867.573C501.396,867.297 501.397,867.02 501.393,866.744C501.169,848.42 500.217,834.596 497.45,824.38C494.296,812.737 488.935,804.176 481.519,797.649C471.786,789.082 457.01,783.308 432.618,783.432C432.631,783.432 349.573,781.74 349.573,781.74C342.263,781.591 335.193,784.352 329.92,789.417C324.646,794.481 321.6,801.433 321.453,808.743C320.994,831.48 328.784,863.173 355.106,874.532ZM349.012,809.299C348.694,825.035 352.045,850.739 376.405,851.227C376.405,851.227 382.456,851.451 382.671,851.246L382.671,909.882C386.372,942.314 390.849,949.228 422.075,947.254L440.018,922.172L458.968,946.8C469.376,947.243 472.354,936.796 472.952,916.37L473.831,867.082C473.308,824.468 470.519,810.706 432.434,810.998L349.012,809.299Z"/>
|
||||
</g>
|
||||
<g transform="matrix(0.965008,0,0,0.965008,23.2392,71.4057)">
|
||||
<path d="M168.383,626.429L68.958,552.932L98.573,607.589L58.397,608.077L63.127,634.14L107.426,678.848L96.294,686.03L9.687,652.172C3.055,688.979 13.988,739.904 71.769,761.705L25.995,759.807C29.163,787.849 59.682,794.751 102.342,794.96C129.994,795.095 229.395,824.144 229.395,824.144C232.97,816.998 230.65,812.512 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z" style="fill:rgb(200,208,208);"/>
|
||||
<path d="M143.354,573.648L85.344,530.766C74.956,523.087 60.629,523.652 50.878,532.125C41.127,540.598 38.569,554.706 44.723,566.064L52.861,581.084C46.739,582.329 41.17,585.641 37.13,590.54C31.968,596.8 29.826,605.016 31.275,612.999L34.795,632.392L19.723,626.5C12.045,623.498 3.427,624.091 -3.768,628.115C-10.963,632.139 -15.979,639.172 -17.441,647.285C-22.82,677.138 -19.169,714.245 3.053,744.528C-0.524,749.897 -2.13,756.398 -1.395,762.902C1.423,787.843 15.503,804.12 39.265,813.471C55.154,819.723 76.836,822.4 102.206,822.524C128.236,822.652 221.663,850.602 221.663,850.602C230.871,853.293 240.516,850.965 247.421,845.001C264.36,853.893 280.969,863.432 285.692,866.065C306.138,877.465 321.199,860.942 321.491,860.599C326.696,854.484 330.698,848.331 333.549,842.161C333.549,842.161 424.78,866.145 424.78,866.145C434.364,868.665 444.564,865.845 451.494,858.76L465.299,844.646C469.305,840.55 471.936,835.307 472.824,829.647C472.824,829.647 478.593,791.172 470.735,761.279C465.952,743.081 456.254,727.983 441.989,719.529C417.831,705.214 418.483,707.649 362.211,689.084C359.77,688.278 358.552,685.678 356.777,683.477C353.423,679.316 350.241,674.697 346.857,670.214C338.459,659.092 328.818,649.004 316.552,642.757C316.576,642.77 291.449,628.831 291.449,628.831C291.449,628.831 212.596,533.359 212.596,533.359C204.287,523.299 190.062,520.443 178.514,526.516C159.19,536.678 145.255,553.948 143.354,573.648ZM168.383,626.429L68.958,552.932L98.573,607.589L58.397,608.077L63.127,634.14L107.426,678.848L96.294,686.03L9.687,652.172C3.055,688.979 13.988,739.904 71.769,761.705L25.995,759.807C29.163,787.849 59.682,794.751 102.342,794.96C129.994,795.095 229.395,824.144 229.395,824.144C232.97,816.998 230.65,812.512 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z"/>
|
||||
</g>
|
||||
<g transform="matrix(0.708667,0.490222,-0.590127,0.85309,472.165,-35.3645)">
|
||||
<path d="M288.042,686.084L304.852,642.53L398.993,643.531C395.213,658.829 383.565,669.414 356.913,668.092L333.317,666.622L324.656,699.811L288.042,686.084Z" style="fill:rgb(200,208,208);"/>
|
||||
<path d="M357.816,693.781C379.27,694.41 394.552,689.435 405.628,682.19C417.919,674.15 425.773,662.686 429.231,648.687C431.083,641.196 428.812,633.409 423.039,627.451C417.266,621.494 408.593,617.988 399.388,617.89L305.247,616.889C291.685,616.745 279.598,623.972 275.457,634.701L258.647,678.255C253.855,690.669 261.039,704.094 275.344,709.457L311.957,723.184C320.451,726.369 330.222,726.195 338.544,722.712C346.867,719.229 352.849,712.81 354.824,705.244L357.816,693.781ZM288.042,686.084L304.852,642.53L398.993,643.531C395.213,658.829 383.565,669.414 356.913,668.092L333.317,666.622L324.656,699.811L288.042,686.084Z"/>
|
||||
</g>
|
||||
<g transform="matrix(0.965008,0,0,0.965008,23.2392,71.4057)">
|
||||
<path d="M370.679,738.299C456.871,761.639 422.713,878.823 422.713,878.823L275.848,878.251C261.223,935.304 343.256,947.547 331.884,1040.16L48.842,1041.06C10.744,1005.07 77.185,889.061 91.071,867.709C91.071,867.709 17.974,777.383 121.465,693.125C219.402,613.39 284.488,714.959 370.679,738.299Z" style="fill:rgb(106,163,145);"/>
|
||||
<clipPath id="_clip2">
|
||||
<path d="M370.679,738.299C456.871,761.639 422.713,878.823 422.713,878.823L275.848,878.251C261.223,935.304 343.256,947.547 331.884,1040.16L48.842,1041.06C10.744,1005.07 77.185,889.061 91.071,867.709C91.071,867.709 17.974,777.383 121.465,693.125C219.402,613.39 284.488,714.959 370.679,738.299Z"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip2)">
|
||||
<g transform="matrix(1.03626,0,0,1.03626,-10.6104,-73.9949)">
|
||||
<path d="M327.641,919.784C327.641,919.784 19.841,915.492 203.986,733.277L29.629,774.209L27.848,1095.35L134.952,1094.74C100.026,1000.83 183.219,931.635 183.219,931.635L327.886,932.176L327.641,919.784Z" style="fill:rgb(78,131,128);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.03626,0,0,1.03626,-10.6104,-73.9949)">
|
||||
<path d="M199.207,978.338L194.488,978.338C187.08,978.338 181.065,984.352 181.065,991.761L181.065,1018.61C181.065,1026.02 187.08,1032.03 194.488,1032.03L196.496,1032.03C190.628,1033.37 186.245,1038.63 186.245,1044.9L186.245,1071.3C186.245,1078.59 192.16,1084.5 199.446,1084.5L408.512,1084.5C415.798,1084.5 421.713,1078.59 421.713,1071.3L421.713,1044.9C421.713,1037.62 415.798,1031.7 408.512,1031.7L375.501,1031.7C381.48,1030.34 385.949,1024.99 385.949,1018.61L385.949,991.761C385.949,984.352 379.935,978.338 372.526,978.338L348.751,978.338C353.329,976.615 356.59,972.194 356.59,967.017L356.59,942.836C356.59,936.163 351.173,930.746 344.5,930.746L213.879,941.893C207.206,941.893 191.368,936.163 191.368,942.836L191.368,967.017C191.368,972.194 194.628,976.615 199.207,978.338Z" style="fill:rgb(218,182,240);stroke:black;stroke-width:23.2px;"/>
|
||||
</g>
|
||||
<g>
|
||||
<g transform="matrix(1.49551,0,0,0.811757,-68.9641,269.615)">
|
||||
<path d="M331.231,910.593C331.231,901.292 327.133,893.74 322.084,893.74L177.219,893.74C172.17,893.74 168.071,901.292 168.071,910.593L168.071,944.297C168.071,953.598 172.17,961.149 177.219,961.149L322.084,961.149C327.133,961.149 331.231,953.598 331.231,944.297L331.231,910.593Z" style="fill:rgb(218,182,240);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.30126,0,0,0.825417,-41.6844,202.11)">
|
||||
<path d="M331.231,910.593C331.231,901.292 326.441,893.74 320.542,893.74L178.761,893.74C172.861,893.74 168.071,901.292 168.071,910.593L168.071,944.297C168.071,953.598 172.861,961.149 178.761,961.149L320.542,961.149C326.441,961.149 331.231,953.598 331.231,944.297L331.231,910.593Z" style="fill:rgb(229,210,240);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.04936,0,0,0.743456,11.3293,226.044)">
|
||||
<path d="M331.231,910.593C331.231,901.292 325.881,893.74 319.292,893.74L180.011,893.74C173.421,893.74 168.071,901.292 168.071,910.593L168.071,944.297C168.071,953.598 173.421,961.149 180.011,961.149L319.292,961.149C325.881,961.149 331.231,953.598 331.231,944.297L331.231,910.593Z" style="fill:rgb(218,182,240);"/>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M168.383,626.429L68.958,552.932L76.8,603.031L58.397,608.077L63.127,634.14L107.426,678.848L96.294,686.03L9.687,652.172C3.055,688.979 13.988,739.904 71.769,761.705L25.995,759.807C29.163,787.849 59.682,794.751 102.342,794.96C129.994,795.095 229.395,824.144 229.395,824.144C232.97,816.998 230.65,812.512 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z" style="fill:none;stroke:black;stroke-width:24.04px;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.965008,0,0,0.965008,23.2392,84.9158)">
|
||||
<path d="M349.012,809.299C348.694,825.035 352.045,850.739 376.405,851.227C376.405,851.227 382.456,851.451 382.671,851.246L382.671,909.882C386.372,942.314 390.849,949.228 422.075,947.254L440.018,922.172L458.968,946.8C469.376,947.243 472.354,936.796 472.952,916.37L473.831,867.082C473.308,824.468 470.519,810.706 432.434,810.998" style="fill:rgb(234,167,208);"/>
|
||||
<clipPath id="_clip3">
|
||||
<path d="M349.012,809.299C348.694,825.035 352.045,850.739 376.405,851.227C376.405,851.227 382.456,851.451 382.671,851.246L382.671,909.882C386.372,942.314 390.849,949.228 422.075,947.254L440.018,922.172L458.968,946.8C469.376,947.243 472.354,936.796 472.952,916.37L473.831,867.082C473.308,824.468 470.519,810.706 432.434,810.998"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip3)">
|
||||
<path d="M431.785,825.472C436.196,825.531 440.671,826.375 440.658,834.109L440.018,932.263L455.298,946.8C484.319,949.064 493.525,936.796 491.605,916.37L492.484,867.082C494.969,824.742 470.519,810.706 432.434,810.998" style="fill:rgb(234,134,177);"/>
|
||||
<g transform="matrix(1,0,0,1,0,-14)">
|
||||
<path d="M168.383,626.429L77.248,552.932L85.09,603.031L66.687,608.077L71.417,634.14L115.716,678.848L104.584,686.03L17.977,652.172C11.345,688.979 22.041,738.658 79.821,760.458L47.756,759.807C50.925,787.849 59.682,794.751 102.342,794.96C129.994,795.095 220.32,823.237 220.32,823.237C223.592,820.023 230.65,813.419 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z" style="fill:none;stroke:black;stroke-width:24.04px;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.965008,0,0,0.965008,23.2392,71.4057)">
|
||||
<path d="M168.383,626.429L68.958,552.932L98.573,607.589L58.397,608.077L63.127,634.14L107.426,678.848L96.294,686.03L9.687,652.172C3.055,688.979 13.988,739.904 71.769,761.705L25.995,759.807C29.163,787.849 59.682,794.751 102.342,794.96C129.994,795.095 229.395,824.144 229.395,824.144C232.97,816.998 230.65,812.512 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z" style="fill:rgb(200,208,208);"/>
|
||||
<clipPath id="_clip4">
|
||||
<path d="M168.383,626.429L68.958,552.932L98.573,607.589L58.397,608.077L63.127,634.14L107.426,678.848L96.294,686.03L9.687,652.172C3.055,688.979 13.988,739.904 71.769,761.705L25.995,759.807C29.163,787.849 59.682,794.751 102.342,794.96C129.994,795.095 229.395,824.144 229.395,824.144C232.97,816.998 230.65,812.512 228.673,805.457C252.977,815.261 300.374,842.882 300.5,842.733C310.587,830.883 313.8,819.033 308.911,807.183L431.788,839.486L445.593,825.372C445.593,825.372 455.886,759.805 427.937,743.243C405.459,729.923 405.934,732.535 353.574,715.26C333.336,708.583 325.538,677.946 303.688,667.142L273.518,650.405L191.343,550.913C175.865,559.052 164.837,575.079 174.866,591.863L189.002,626.915L168.383,626.429Z"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip4)">
|
||||
<g transform="matrix(1.03626,0,0,1.03626,-10.6104,-73.9949)">
|
||||
<path d="M270.728,894.871L100.432,790.886C63.478,765.434 37.671,753.561 26.716,699.023L2.403,894.926L267.356,920.428L270.728,894.871Z" style="fill:rgb(172,170,169);"/>
|
||||
</g>
|
||||
<g transform="matrix(-1.03551,0.0394868,-0.0394868,-1.03551,497.719,1558.87)">
|
||||
<path d="M163.842,871.577L126.417,815.955C118.286,808.738 60.71,796.535 46.524,779.572C21.875,750.098 39.493,711.067 37.417,693.437L-44.713,755.284L45.371,913.462L163.842,871.577Z" style="fill:rgb(172,170,169);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.03626,0,0,1.03626,155.247,-182.181)">
|
||||
<path d="M22.944,780.709L72.33,780.858L25.042,704.623L2.809,730.81L22.944,780.709Z" style="fill:rgb(172,170,169);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.991053,-0.302738,0.302738,0.991053,-177.855,-92.9109)">
|
||||
<path d="M39.909,798.246L85.999,816.588L14.692,720.663L2.809,730.81L39.909,798.246Z" style="fill:rgb(172,170,169);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.896534,0.442974,-0.442974,0.896534,369.005,-73.9169)">
|
||||
<path d="M368.002,761.693L391.151,763.055" style="fill:none;stroke:rgb(83,61,54);stroke-width:19.91px;"/>
|
||||
</g>
|
||||
<g transform="matrix(1.0836,0.991179,-0.64138,0.769827,186.571,-341.914)">
|
||||
<path d="M351.964,770.691L376.735,752.239L387.713,766.58" style="fill:none;stroke:black;stroke-width:3.21px;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.965008,0,0,0.965008,8.66827,66.9035)">
|
||||
<ellipse cx="221.733" cy="727.732" rx="38.255" ry="46.49" style="fill:rgb(251,248,235);"/>
|
||||
<clipPath id="_clip5">
|
||||
<ellipse cx="221.733" cy="727.732" rx="38.255" ry="46.49"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip5)">
|
||||
<g transform="matrix(1.90259,0,0,1.40285,-162.229,-333.591)">
|
||||
<ellipse cx="203.804" cy="757.093" rx="25.898" ry="33.515" style="fill:rgb(251,248,235);"/>
|
||||
</g>
|
||||
<g transform="matrix(1.90259,0,0,1.40285,-192.925,-329.328)">
|
||||
<ellipse cx="203.804" cy="757.093" rx="25.898" ry="33.515" style="fill:rgb(127,66,180);"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1.1684,1.99638,-148.036)">
|
||||
<rect x="170.37" y="672.129" width="113.591" height="70.11" style="fill:rgb(78,131,128);"/>
|
||||
<clipPath id="_clip6">
|
||||
<rect x="170.37" y="672.129" width="113.591" height="70.11"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#_clip6)">
|
||||
<g transform="matrix(1.03626,0,0,0.886908,-15.273,46.6391)">
|
||||
<circle cx="228.602" cy="798.456" r="38.625" style="fill:rgb(106,163,145);"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path d="M221.733,669.221C194.68,669.221 171.458,694.855 171.458,727.732C171.458,760.609 194.68,786.243 221.733,786.243C248.787,786.243 272.009,760.609 272.009,727.732C272.009,694.855 248.787,669.221 221.733,669.221ZM221.733,681.242C242.847,681.242 259.988,702.074 259.988,727.732C259.988,753.391 242.847,774.223 221.733,774.223C200.62,774.223 183.479,753.391 183.479,727.732C183.479,702.074 200.62,681.242 221.733,681.242Z"/>
|
||||
</g>
|
||||
<g transform="matrix(0.708667,0.490222,-0.590127,0.85309,472.165,-35.3645)">
|
||||
<path d="M288.042,686.084L304.852,642.53L398.993,643.531C395.213,658.829 383.565,669.414 356.913,668.092L333.317,666.622L324.656,699.811" style="fill:rgb(200,208,208);"/>
|
||||
</g>
|
||||
<g transform="matrix(1,0,0,1,9,9)">
|
||||
<path d="M280.43,915.61C252.675,916.872 236.398,922.853 201.061,922.853L183.825,922.757C171.311,921.177 163.129,919.303 151.665,907.851" style="fill:none;stroke:black;stroke-width:11.6px;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 21 KiB |
|
@ -1,274 +0,0 @@
|
|||
---
|
||||
title: rainbow quox
|
||||
date: 2024-11-17
|
||||
tags: [computer, website, fursona]
|
||||
summary: q.t. colour scheme generator
|
||||
...
|
||||
|
||||
so how about that regular posting, huh. ha ha ha
|
||||
|
||||
i haven't been up to much unusual. [drawing], mostly. i installed [nixos] on both my computers and it's going pretty well so far [(less than a week)]{.note}, but every computer toucher does that at some point, so, whatever.
|
||||
|
||||
[drawing]: https://gallery.niss.website
|
||||
[nixos]: https://nixos.org
|
||||
|
||||
anyway, to the point.
|
||||
|
||||
:::banner
|
||||
[go here if you just want to play with the thing][thing]
|
||||
<!-- TODO add this link!!! -->
|
||||
:::
|
||||
|
||||
# the point {.unnumbered}
|
||||
|
||||
the animal-inclined might know that [q.t.][qt] can change its colour any time it wants. if you click that link you can clearly see i have some tendencies, but it can in theory be anything. so something i have wanted for a while is a page where you can click a button and get a bespoke randomly-generated quox theme of your very own.
|
||||
|
||||
so i did that.
|
||||
|
||||
:::aside
|
||||
you can also skip to [what i _actually_ ended up doing](#actual), if you don't care about the false starts.
|
||||
:::
|
||||
|
||||
[qt]: https://gallery.niss.website/by-any/#qt
|
||||
|
||||
# doing that
|
||||
|
||||
{.floating .expandable .nobg .shaped}
|
||||
|
||||
pretty much what i want to do, at least to begin with, is take the original colours of the image and move the hues around at random.
|
||||
|
||||
if you look at [mdn], you might see this interesting [`hue-rotate()`][hr] thing that might do what i want. let's have a look.
|
||||
|
||||
[mdn]: https://developer.mozilla.org/en-US/docs/Web/CSS
|
||||
[hr]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/hue-rotate
|
||||
|
||||
> **Note:** `hue-rotate()` is specified as a matrix operation on the RGB color. It does not actually convert the color to the HSL model, which is a non-linear operation. Therefore, it may not preserve the saturation or lightness of the original color, especially for saturated colors.
|
||||
|
||||
well that doesn't sound very promising. but maybe it'll be fine, so let's try it. first, separate the pictures from [q.t.'s refsheet][ref] into bits. like this.
|
||||
|
||||
[ref]: https://gallery.niss.website/main/niss/2024-06-27-qt
|
||||
|
||||
{.expandable .lightbg}
|
||||
|
||||
now let's layer them back on top of each other with some css.
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<style>
|
||||
#container {
|
||||
width: 100%; position: relative;
|
||||
img { position: absolute; inset: 0; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id=container>
|
||||
<img src=outer.png> <img src=belly.png> <img src=eyes.png>
|
||||
<img src=tongues.png> <img src=collars.png> <img src=masks.png>
|
||||
<img src=socks.png> <img src=stripes.png> <img src=lines.png>
|
||||
</div>
|
||||
```
|
||||
|
||||
{.floating .left .nobg .expandable .shaped}
|
||||
|
||||
ok, next, actually try to do the hue stuff. to check it works at all, i shoved everything to hue 0° (using krita's _hue HSL_ blend mode), and used `hue-rotate()` to change it back to the 'main' colour of each region---it won't look exact, but it'll be close.
|
||||
|
||||
```css
|
||||
#container img { filter: hue-rotate(var(--hue)); }
|
||||
|
||||
#outer { --hue: 273deg; } #belly { --hue: 26deg; }
|
||||
#eyes { --hue: 133deg; } #masks { --hue: 284deg; }
|
||||
#stripes { --hue: 188deg; } #lines { --hue: 273deg; }
|
||||
/* also add the id to each image */
|
||||
```
|
||||
|
||||
right?
|
||||
|
||||
{.expandable .nobg}
|
||||
|
||||
well that's no good at all. i guess that warning was serious.
|
||||
|
||||
# ok what about blend modes
|
||||
|
||||
{.floating .expandable}
|
||||
|
||||
all right, fine. what else. as a chronic over-user of `overlay`, i can certainly tell you that css has a few [blending modes][bm]. not as many as krita, which has approximately "too many", but enough for most purposes. one of them is `hue`. how about that.
|
||||
|
||||
[bm]: https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode
|
||||
|
||||
this takes a bit more messing, because i need to create a flood fill of one of the colours from that layer, and blend with that. so how about an SVG filter, i guess. or, six SVG filters---one for each filter, since you can't parametrise them.
|
||||
|
||||
time to copy and paste the same five lines six times. yaaaaaaaaay
|
||||
|
||||
{.bigemoji .pixel} \
|
||||
|
||||
```svg
|
||||
<svg style="position: absolute">
|
||||
<filter id="fouter">
|
||||
<feFlood result="hue" flood-color="#57267e" />
|
||||
<feBlend in="hue" in2="SourceGraphic" mode="hue" result="res" />
|
||||
<!-- ↓ without this the background will also be filled in -->
|
||||
<feComposite in="res" in2="SourceGraphic" operator="in" />
|
||||
</filter>
|
||||
<!-- …and same for the others, with different flood-colors -->
|
||||
</svg>
|
||||
```
|
||||
|
||||
```css
|
||||
#outer { filter: url(#fouter); }
|
||||
/* …etc… */
|
||||
```
|
||||
|
||||
and…
|
||||
|
||||
{.expandable .nobg}
|
||||
|
||||
i was expecting at least the same thing, but a different, also wrong, result is pretty cool.
|
||||
|
||||
# drastic measures {#actual}
|
||||
|
||||
ok, enough messing around, time to bite the bullet. separate every single colour into its own layer, and use those as _masks_ for colour fills.
|
||||
|
||||
now the pieces look like _this_:
|
||||
|
||||
{.expandable .lightbg}
|
||||
|
||||
the colours in the images no longer matters, only the alpha channel. [(except for the eyes.)]{.note} each one is just a mask over a background fill of the right colour.
|
||||
|
||||
```css
|
||||
@layer {
|
||||
#container { position: relative; width: 90vw; aspect-ratio: 3439/2240; }
|
||||
#container div { position: absolute; inset: 0; mask-size: contain; }
|
||||
}
|
||||
|
||||
@layer {
|
||||
#static { background: url(front/static.png) 0 0 / contain; }
|
||||
#eye-shine {
|
||||
background: url(front/eyes.png) 0 0 / contain;
|
||||
mix-blend-mode: luminosity;
|
||||
}
|
||||
/* the others all look like this: */
|
||||
#spines {
|
||||
background: oklch(30.77% 0.1306 var(--hue)); --hue: 298.19;
|
||||
mask-image: url(front/spines.png);
|
||||
}
|
||||
/* etc… */
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
<div id=container>
|
||||
<!-- divs not images now. the images are all in the background properties -->
|
||||
<div class=part id=static></div>
|
||||
<div class=part id=spines></div>
|
||||
<div class=part id=stripes></div>
|
||||
<!-- etc… -->
|
||||
<div id=eye-shine></div>
|
||||
</div>
|
||||
```
|
||||
|
||||
since the hue is separated out into a variable, i can just do:
|
||||
|
||||
```js
|
||||
for (const elem of document.getElementsByClassName('part')) {
|
||||
elem.style.setProperty('--hue', Math.random() * 360);
|
||||
}
|
||||
```
|
||||
|
||||
and instantly i have _something_ working. i used `oklch` because it was more likely than `hsl` or whatever to keep the colours the same kind of distance from each other, since that is what it's designed for.
|
||||
|
||||
{.expandable .hasborder}
|
||||
|
||||
|
||||
# keeping the colours in sync
|
||||
|
||||
so as of last year, most browsers got a thing called [relative colours]. if you have an existing colour `--hi`, you can rotate its hue by half a turn by saying something like
|
||||
|
||||
[relative colours]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_colors/Relative_colors
|
||||
|
||||
```css
|
||||
:root {
|
||||
--hi: #ea9aa1;
|
||||
--wow: oklch(from var(--hi) l c calc(h + 180));
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
header-includes: |
|
||||
<style>
|
||||
#relcolor {
|
||||
max-width: 20em; margin: auto;
|
||||
display: grid; grid-template-columns: 1fr 1fr; gap: .5em;
|
||||
font-weight: bold;
|
||||
--hi: #ea9aa1; --wow: oklch(from var(--hi) l c calc(h + 180));
|
||||
}
|
||||
#relcolor div {
|
||||
text-align: center; font-size: 125%;
|
||||
padding: .4em; border-radius: .5em;
|
||||
color: black;
|
||||
background: var(--bg);
|
||||
border: 4px solid oklch(from var(--bg) .25 75% h);
|
||||
}
|
||||
#hi { --bg: var(--hi); }
|
||||
#wow { --bg: var(--wow); }
|
||||
</style>
|
||||
...
|
||||
|
||||
<div id=relcolor>
|
||||
<div id=hi>\--hi</div>
|
||||
<div id=wow>\--wow</div>
|
||||
</div>
|
||||
|
||||
you're taking the value of `var(--hi)`, keeping the lightness and chroma channels the same, and adding 180° to the hue.
|
||||
|
||||
:::aside
|
||||
that's not quite true. safari, as always, does it slightly wrong. according to the spec, all channels in a relative colour must be dimensionless, but in safari, the hue is an `<angle>`. other browsers, following the spec correctly, _don't allow_ that. so you _actually_ have to write
|
||||
|
||||
```css
|
||||
:root {
|
||||
--hi: #ea9aa1;
|
||||
--wow: oklch(from var(--hi) l c calc(h + 180));
|
||||
}
|
||||
@supports (color: oklch(from red l c 10deg)) {
|
||||
:root { --wow: oklch(from var(--hi) l c calc(h + 180deg)); }
|
||||
}
|
||||
```
|
||||
|
||||
thanks apple!
|
||||
:::
|
||||
|
||||
so based on that, i can pick one initial colour and base all the others on it. like
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* these aren't attempting to be the same colours, just guessing something
|
||||
that MIGHT look nice */
|
||||
--outer: #57267e;
|
||||
--spines: oklch(from var(--outer) calc(l * .75) calc(c * 1.25) h);
|
||||
--vitiligo1: oklch(from var(--outer) calc(1 - (1 - l)/4) calc(c / 2) h);
|
||||
|
||||
/* static l/c values because the socks are always some pale colour */
|
||||
--stripes: oklch(from var(--outer) .9 12.5% calc(h + 120));
|
||||
--cuffs: oklch(from var(--stripes) .8 25% h);
|
||||
/* etc */
|
||||
}
|
||||
|
||||
.outer { background: var(--outer); mask-image: url(front/outer.png); }
|
||||
/* etc */
|
||||
```
|
||||
|
||||
so after guessing a bunch of relative colours, i ended up with this:
|
||||
|
||||
{.expandable .nobg}
|
||||
|
||||
|
||||
## notes for niss. if this goes online i fucked up
|
||||
|
||||
- palette types
|
||||
- randomise distance between analogous colours
|
||||
- light, dark, light-dark, dark-light (belly vs outer)
|
||||
- reinstate chaos mode
|
||||
- can you set the random seed in the browser
|
||||
- no. anyway the algorithm might be different
|
||||
- make yr own
|
||||
- or <https://stackoverflow.com/a/47593315>. whatever
|
||||
- if so: use that to make palette permalinks
|
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 67 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 418 KiB |
Before Width: | Height: | Size: 536 KiB |
Before Width: | Height: | Size: 652 KiB |
191
posts/aoc2024.md
Normal file
|
@ -0,0 +1,191 @@
|
|||
---
|
||||
title: advent of code 2024, day 1, part 1
|
||||
date: 2024-12-02
|
||||
tags: [computer, quox. the language, december adventure]
|
||||
summary: don't expect me to do the whole thing okay
|
||||
...
|
||||
|
||||
i don't think i'm going to __get into it__ this year. maybe this will be the only one i do. but i did this one.
|
||||
|
||||
i haven't done much on quox this year [(nothing in the last… six months…)]{.note}, but it's not abandoned! i promise.
|
||||
|
||||
it even has the beginnings of a standard library! which also mostly existed last year too.
|
||||
|
||||
```quox
|
||||
load "bool.quox"
|
||||
load "ordering.quox"
|
||||
load "list.quox"
|
||||
load "nat.quox"
|
||||
load "string.quox"
|
||||
load "io.quox"
|
||||
```
|
||||
|
||||
it's not very big, though, so it doesn't have line splitting yet. that's fine though.
|
||||
|
||||
```quox
|
||||
def lines : ω.String → List String =
|
||||
λ str ⇒ string.split (char.eq char.newline) str
|
||||
```
|
||||
|
||||
:::aside
|
||||
**what does ω mean?**
|
||||
quox has linear types, which means that by default, each argument to a function, both sites of a pair, etc., have to be used exactly once in each code path. for function arguments that need to be uses more flexibly than that (more than once, a statically-unknown number of times, or whatever), they can be marked `ω` like above. the function passed to `string.split` also has the type `ω.Char → Bool`. it wouldn't be very useful if testing a character also consumed it: then you wouldn't be able to put it in the string.
|
||||
|
||||
obviously this is not a very _ergonomic_ design. at some point i want to have something that fills the same role as rust's borrowed values, but that is not yet the case. so right now there are _lots_ of `ω`s.
|
||||
:::
|
||||
|
||||
|
||||
so. let's actually read [the puzzle][aoc1]. blah blah blah… elves… lists of numbers… blah blah… right.
|
||||
|
||||
- list of pairs of numbers
|
||||
- [(read the string representation into actual numbers)]{.note}
|
||||
- unzip the pairs into two lists of numbers
|
||||
- sort each list
|
||||
- find the difference between each corresponding element in the sorted lists and sum them
|
||||
|
||||
[aoc1]: https://adventofcode.com/2024/day/1
|
||||
|
||||
:::{.aside .floating .right}
|
||||
one of the bits of detritus in the growing stdlib is half an implementation of merge sort. the half that's possible.
|
||||
:::
|
||||
|
||||
easy, except, oh no. __sorting__. that's not very structurally recursive. [(reminder: the only recursion is natural numbers)]{.note}
|
||||
|
||||
after thinking about whether i can model [`@accessibility predicates@`][acc] with what i already have for an hour---i don't think so---i decided to just give up and use insertion sort. that's structurally recursive. the list isn't gonna be _that_ long.
|
||||
|
||||
[acc]: https://github.com/agda/agda-stdlib/blob/master/src/Induction/WellFounded.agda#L40-L43
|
||||
|
||||
|
||||
currently, the way lists are defined is via `@vectors@`, which are what people with dependent type brain call lists of known length. not arrays. sorry it's not my fault. we get vectors by recursion on our one recursive thing.
|
||||
|
||||
```quox
|
||||
def0 Vec : ℕ → Type → Type =
|
||||
λ len A ⇒
|
||||
case len return Type of {
|
||||
zero ⇒ {nil};
|
||||
succ len', Tail ⇒ A × Tail
|
||||
};
|
||||
```
|
||||
|
||||
:::{.figure .floating .right .shaped .nobg}
|
||||
<img src=aoc2024/succ.png style='height: 1.5em'>
|
||||
:::
|
||||
|
||||
in a match on a `ℕ`, there is (optionally) a second variable in the `succ` case, which is the result of a recursive call. in this case, in a call to `Vec 4 ℕ`, `Tail` refers to the result of `Vec 3 ℕ` (which is `ℕ × ℕ × ℕ × {nil}`).
|
||||
|
||||
types that look `\{like, this}` are enums. values of an enum type look like `'this`.
|
||||
|
||||
finally, a `List A` is just a number, paired with a vector of that length.
|
||||
|
||||
```quox
|
||||
def0 List : Type → Type = (len : ℕ) × Vec len A
|
||||
```
|
||||
|
||||
given a definition of a comparison function, it's possible to insert a value into a vector of length `n`, getting one of length `succ n` in return. apart from the excessive annotations (also not done yet: any kind of anything-inference!) and the slightly weird-looking recursive call, this should be pretty normal.
|
||||
|
||||
```quox
|
||||
def0 Ordering : Type = {lt, eq, gt}
|
||||
def0 Compare : Type → Type = λ A → ω.A → ω.A → Ordering
|
||||
|
||||
def insertV :
|
||||
0.(A : Type) → ω.(Compare A) → ω.(len : ℕ) →
|
||||
ω.A → ω.(Vec len A) → Vec (succ len) A =
|
||||
λ A cmp len ⇒
|
||||
caseω len return len' ⇒ ω.A → ω.(Vec len' A) → Vec (succ len') A of {
|
||||
zero ⇒ λ x _ ⇒ (x, 'nil);
|
||||
succ len', ω.inTail ⇒ λ x xs ⇒
|
||||
let0 len : ℕ = succ len'; Res : Type = Vec (succ len) A in
|
||||
caseω xs return Res of { (y, ys) ⇒
|
||||
case cmp x y return Res of {
|
||||
'lt ⇒ (x, y, ys);
|
||||
'eq ⇒ (x, y, ys);
|
||||
'gt ⇒ (y, inTail x ys)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
if you strip away those bits, you essentially get the equivalent of this.
|
||||
|
||||
```haskell
|
||||
insertV :: (α → α → Ordering) → α → [α] → [α]
|
||||
insertV cmp x [] = [x]
|
||||
insertV cmp x (y:ys) = case cmp x y of
|
||||
LT → x : y : ys
|
||||
EQ → x : y : ys
|
||||
GT → y : insertV cmp x ys
|
||||
```
|
||||
|
||||
to insert into a list, just take the length off and put the new one back on.
|
||||
|
||||
```quox
|
||||
def insert : 0.(A : Type) → ω.(Compare A) → ω.A → ω.(List A) → List A =
|
||||
λ A cmp x ys ⇒
|
||||
letω len = fst ys; elems = snd ys in
|
||||
(succ len, insertV A cmp len x elems)
|
||||
```
|
||||
|
||||
so to inefficiently sort a list, take each element, one by one, and insert it into the right place!
|
||||
|
||||
```quox
|
||||
def sort : 0.(A : Type) → ω.(Compare A) → ω.(List A) → List A =
|
||||
λ A cmp ⇒ list.foldrω A (List A) (list.Nil A) (insert A cmp)
|
||||
```
|
||||
|
||||
does it work? let's write one (1) test. \
|
||||
if it doesn't, then `sort ℕ (λ m n ⇒ nat.compare m n) (5, 1,4,2,5,3,'nil)` (probably) won't reduce to the right thing, and the definition won't typecheck.
|
||||
|
||||
```quox
|
||||
def0 sort-14253 :
|
||||
sort ℕ (λ m n ⇒ nat.compare m n) (5, 1,4,2,5,3,'nil)
|
||||
≡ (5, 1,2,3,4,5,'nil) : List ℕ =
|
||||
δ _ ⇒ (5, 1,2,3,4,5,'nil)
|
||||
```
|
||||
|
||||
good enough for me!
|
||||
|
||||
next up, symmetric difference. or `|x - y|`, or whatever you wanna call it. you can do that by recursing on both arguments in lockstep, which luckily is something i added to the stdlib last year. oh and in the compiled output just use scheme's arithmetic operators instead of going O(n).
|
||||
|
||||
```quox
|
||||
#[compile-scheme "(lambda% (m n) (abs (- m n)))"]
|
||||
def sd : ω.ℕ → ω.ℕ → ℕ =
|
||||
nat.elim-pairω (λ _ _ ⇒ ℕ)
|
||||
0 -- |0 - 0| = 0
|
||||
(λ m _ ⇒ succ m) -- |succ m - 0| = succ m
|
||||
(λ n _ ⇒ succ n) -- |0 - succ n| = succ n
|
||||
(λ _ _ d ⇒ d) -- |succ m - succ n| = |m - n|
|
||||
|
||||
def0 sd-6-3 : sd 6 3 ≡ 3 : ℕ = δ _ ⇒ 3
|
||||
def0 sd-3-6 : sd 3 6 ≡ 3 : ℕ = δ _ ⇒ 3
|
||||
```
|
||||
|
||||
now the annoying part. chopping up lines. break it on whitespace, then on non-whitespace, and convert the first and third parts to numbers.
|
||||
|
||||
```quox
|
||||
def number-pair : ω.String → ℕ × ℕ =
|
||||
λ str ⇒
|
||||
letω a_bc = string.break char.ws? str;
|
||||
a = fst a_bc; bc = snd a_bc;
|
||||
c = snd (string.span char.ws? bc) in
|
||||
(string.to-ℕ-or-0 a, string.to-ℕ-or-0 c)
|
||||
```
|
||||
|
||||
and the main function. boy i wish i had some `do` notation right now..! one day.
|
||||
|
||||
```quox
|
||||
#[main]
|
||||
def part1 : IO True =
|
||||
io.bindω String True (io.read-fileω "1.txt") (λ str ⇒
|
||||
letω pairs = list.mapω String (ℕ × ℕ) number-pair (lines str);
|
||||
lists = list.unzip ℕ ℕ pairs;
|
||||
sortℕ = sort ℕ (λ m n ⇒ nat.compare m n);
|
||||
as = sortℕ (fst lists); bs = sortℕ (snd lists);
|
||||
diffs = list.zip-with-uneven ℕ ℕ ℕ sd as bs;
|
||||
in
|
||||
io.dump ℕ (list.sum diffs))
|
||||
```
|
||||
|
||||
after taking almost four entire seconds to compile, it… works. after i add another `compile-scheme` thing to the stdlib's `nat.compare`, anyway.
|
||||
|
||||
i had other things to do today so i didn't get around to even looking at part two.
|
||||
bye [<img src=/images/qt.svg alt=mlem class=emoji><img src=/images/qt.svg alt='' class=emoji><img src=/images/qt.svg alt='' class=emoji>]{.emojiseq}
|
BIN
posts/aoc2024/succ.png
Normal file
After Width: | Height: | Size: 41 KiB |
216
posts/rainbow-quox.md
Normal file
|
@ -0,0 +1,216 @@
|
|||
---
|
||||
title: rainbow quox
|
||||
date: 2024-12-03
|
||||
tags: [computer, website, fursona, december adventure]
|
||||
summary: q.t. colour scheme generator
|
||||
header-includes: |
|
||||
<style>
|
||||
#relcolor {
|
||||
max-width: 20em; margin: auto;
|
||||
display: grid; grid-template-columns: 1fr 1fr; gap: .5em;
|
||||
font-weight: bold;
|
||||
--hi: #ea9aa1; --wow: oklch(from var(--hi) l c calc(h + 180));
|
||||
}
|
||||
#relcolor div {
|
||||
text-align: center; font-size: 125%;
|
||||
padding: .4em; border-radius: .5em;
|
||||
color: black;
|
||||
background: var(--bg);
|
||||
border: 4px solid oklch(from var(--bg) .25 75% h);
|
||||
}
|
||||
#hi { --bg: var(--hi); }
|
||||
#wow { --bg: var(--wow); }
|
||||
|
||||
#patterns { display: flex; gap: 1em; }
|
||||
#patterns figure { margin: 0; }
|
||||
|
||||
#result {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
svg { height: 1.25em; vertical-align: -20%; }
|
||||
rect { stroke: currentcolor; stroke-width: 0.075; }
|
||||
</style>
|
||||
...
|
||||
|
||||
the animal-inclined might know that [q.t.][qt] can change its colour any time it wants. if you click that link you can clearly see i have some tendencies, but it can in theory be anything. so something i have wanted for a while is a page where you can click a button and get a bespoke randomly-generated quox theme of your very own.
|
||||
|
||||
so for today's [`@december adventure@`][decadv], i did that. (yesterday's was retroactively the AOC stuff.)
|
||||
|
||||
[decadv]: https://eli.li/december-adventure
|
||||
|
||||
:::banner
|
||||
[go here if you just want to play with the thing][thing]
|
||||
:::
|
||||
|
||||
[thing]: https://yummy.cricket/rainbow-quox
|
||||
|
||||
you can also skip to [what i _actually_ ended up doing](#actual), if you don't care about the false starts.
|
||||
|
||||
[qt]: https://gallery.niss.website/by-any/#qt
|
||||
|
||||
# doing that
|
||||
|
||||
{.floating .expandable .nobg .shaped}
|
||||
|
||||
pretty much what i want to do, at least to begin with, is take the original colours of the image and move the hues around at random.
|
||||
|
||||
if you look at [mdn], you might see this interesting [`hue-rotate()`][hr] thing that might do what i want. let's have a look.
|
||||
|
||||
[mdn]: https://developer.mozilla.org/en-US/docs/Web/CSS
|
||||
[hr]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/hue-rotate
|
||||
|
||||
> **Note:** `hue-rotate()` is specified as a matrix operation on the RGB color. It does not actually convert the color to the HSL model, which is a non-linear operation. Therefore, it may not preserve the saturation or lightness of the original color, especially for saturated colors.
|
||||
|
||||
|
||||
{.floating .right .nobg .expandable .shaped}
|
||||
|
||||
well that doesn't sound very encouraging. but maybe it'll be fine.
|
||||
|
||||
i shoved [all of the colours][jofo] to hue 0° (using krita's _hue HSL_ blend mode), and used `hue-rotate()` to change it back to the 'main' colour of each region.
|
||||
|
||||
it won't look exact, but it'll be close. right?
|
||||
|
||||
[jofo]: https://johnnyforeigner.bandcamp.com/track/all-of-the-colours
|
||||
|
||||
{.expandable .nobg}
|
||||
|
||||
well that's no good at all. i guess that warning was serious.
|
||||
|
||||
# ok what about blend modes
|
||||
|
||||
all right, fine. what else. as a chronic over-user of `overlay`, i can certainly tell you that css has a few [blending modes][bm]. not as many as krita, which has approximately "too many", but enough for most purposes. one of them is `hue`. how about that.
|
||||
|
||||
[bm]: https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode
|
||||
|
||||
this takes a bit more messing, because i need to create a flood fill of one of the colours from that layer, and blend with that. so how about an SVG filter, i guess. or, six SVG filters---one for each layer, since you can't parametrise them. each one looks like this, with a different `flood-color`.
|
||||
|
||||
```svg
|
||||
<filter id="f-outer">
|
||||
<feFlood result="hue" flood-color="#57267e" />
|
||||
<feBlend in="hue" in2="SourceGraphic" mode="hue" result="res" />
|
||||
<feComposite in="res" in2="SourceGraphic" operator="in" />
|
||||
</filter>
|
||||
```
|
||||
|
||||
and…
|
||||
|
||||
{.expandable .nobg}
|
||||
|
||||
i was expecting at least the same thing, but a different, also wrong, result is pretty cool.
|
||||
|
||||
# drastic measures {#actual}
|
||||
|
||||
ok, enough messing around, time to bite the bullet. separate _every_ colour into its own layer, and use those as masks for colour fills.
|
||||
|
||||
```css
|
||||
#spines {
|
||||
background: oklch(30.77% 0.1306 var(--hue)); --hue: 298.19;
|
||||
mask-image: url(front/spines.png);
|
||||
}
|
||||
/* etc… */
|
||||
```
|
||||
|
||||
since the hue is separated out into a variable, i can just randomise them all and instantly have _something_ working.
|
||||
|
||||
{.expandable .hasborder #chaos}
|
||||
|
||||
|
||||
# digression about relative colours
|
||||
|
||||
[» skip »](#js)
|
||||
|
||||
another thing i played with was using [`@relative colours@`][relcol] to generate a whole palette from one starting colour. relative colours work like this: if you have an existing colour `--hi`, you can rotate its hue by half a turn (in real `oklch` this time!!!), keeping its luma and chroma the same, by saying this:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--hi: #ea9aa1;
|
||||
--wow: oklch(from var(--hi) l c calc(h + 180));
|
||||
}
|
||||
```
|
||||
|
||||
<div id=relcolor>
|
||||
<div id=hi>\--hi</div>
|
||||
<div id=wow>\--wow</div>
|
||||
</div>
|
||||
|
||||
[relcol]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_colors/Relative_colors
|
||||
|
||||
so i tried that. after guessing a bunch of relative colours, i ended up with this:
|
||||
|
||||
{.expandable .nobg}
|
||||
|
||||
|
||||
# just do it in ~~java~~typescript. fine {#js}
|
||||
|
||||
that was pretty cool, but i decided i actually want more flexibility. lighter and darker colour schemes. triadic schemes. whatever.
|
||||
|
||||
maybe that would be possible in pure css with increasingly illegible relative colours. but the randomise button is going to need javascript anyway, so i might as well just fill in the colours directly. but `oklch` is still useful for generating consistent palettes.
|
||||
|
||||
the constraints for a "good" q.t. are something like:
|
||||
|
||||
1. the spines should be a similar colour to its main body.
|
||||
2. the same applies to the four fin colours; the belly colours; the sock colours; and the mask and claw colours.
|
||||
3. the belly should be very different from the rest of the body.
|
||||
4. the eyes should be a similar colour to the body, the fins, or the belly.
|
||||
5. the vitiligo patches should match the colour that they are on.
|
||||
6. the sock stripes should be pale and not too saturated.
|
||||
|
||||
a good place to start is the same place everyone does: with complementary and triadic colours.
|
||||
|
||||
:::{#patterns}
|
||||
{.expandable .nobg}
|
||||
|
||||
{.expandable .nobg}
|
||||
|
||||
{.expandable .nobg}
|
||||
:::
|
||||
|
||||
using this as a starting point, i pick some evenly-spaced colours for each bit. the final palettes come out like this!
|
||||
|
||||
:::{#result}
|
||||
- fins:
|
||||
<svg viewBox='-0.1 -0.1 8.7 1.2'>
|
||||
<rect fill=#770084 width=2 height=1 />
|
||||
<rect fill=#9d0058 width=2 height=1 x=2 />
|
||||
<rect fill=#a11916 width=2 height=1 x=4 />
|
||||
<rect fill=#eead91 width=2 height=1 x=6.5 />
|
||||
</svg>
|
||||
- body:
|
||||
<svg viewBox='-0.1 -0.1 6.7 1.2'>
|
||||
<rect fill=#00709b width=2 height=1 />
|
||||
<rect fill=#008fca width=2 height=1 x=2 />
|
||||
<rect fill=#7dd1f1 width=2 height=1 x=4.5 />
|
||||
</svg>
|
||||
- belly:
|
||||
<svg viewBox='-0.1 -0.1 8.7 1.2'>
|
||||
<rect fill=#dc8d7b width=2 height=1 />
|
||||
<rect fill=#efa4b0 width=2 height=1 x=2 />
|
||||
<rect fill=#f9aba1 width=2 height=1 x=4.5 />
|
||||
<rect fill=#e3adbc width=2 height=1 x=6.5 />
|
||||
</svg>
|
||||
- mask/claws/socks:
|
||||
<svg viewBox='-0.1 -0.1 9.2 1.2'>
|
||||
<rect fill=#ebc1c8 width=2 height=1 />
|
||||
<rect fill=#b4aaae width=2 height=1 x=2.5 />
|
||||
<rect fill=#ffc1a2 width=2 height=1 x=5 />
|
||||
<rect fill=#c46c49 width=2 height=1 x=7 />
|
||||
</svg>
|
||||
|
||||
{ .right .expandable .nobg}
|
||||
:::
|
||||
|
||||
# ok what now
|
||||
|
||||
it's not finished. some things i plan to add at, uh, some point, include:
|
||||
|
||||
- put [chaos mode](#chaos) back in.
|
||||
- permalinks for colour schemes. to do this i need to write another random number generator, since `Math.random` can't be manually seeded. and by "write" i mean "look up online".
|
||||
- colour schemes with a light body and dark belly, rather than the other way around.
|
||||
- render onto a `<canvas>`, or something. whatever's needed to be able to save the images without having to take a screenshot.
|
||||
|
||||
:::banner
|
||||
[here's the link again to save you scrolling back up][thing]
|
||||
:::
|
BIN
posts/rainbow-quox/compl1.avif
Normal file
After Width: | Height: | Size: 125 KiB |
BIN
posts/rainbow-quox/compl2.avif
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
posts/rainbow-quox/dark.webp
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
posts/rainbow-quox/dark2.webp
Normal file
After Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 153 KiB |
BIN
posts/rainbow-quox/quoxes1.avif
Normal file
After Width: | Height: | Size: 570 KiB |
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 210 KiB |
BIN
posts/rainbow-quox/result.webp
Normal file
After Width: | Height: | Size: 142 KiB |
BIN
posts/rainbow-quox/triad.avif
Normal file
After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 397 KiB |
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 382 KiB |
Before Width: | Height: | Size: 302 KiB After Width: | Height: | Size: 361 KiB |
Before Width: | Height: | Size: 6.4 MiB |
BIN
sources/rainbow-quox/result.png
Normal file
After Width: | Height: | Size: 742 KiB |