7 #include "ansihighlighter.h"
9 #include "definition.h"
10 #include "definition_p.h"
12 #include "ksyntaxhighlighting_logging.h"
21 #include <QTextStream>
107 constexpr Lab xterm240_Oklabs[] {
126 {0x0p+0, 0x0p+0, 0x0p+0},
127 {0x1.5f181b2779cap+4, -0x1.930f78e22f09ap+0, -0x1.e41dbddfca08ap+3},
128 {0x1.c2d3be821f882p+4, -0x1.02c70dd8af008p+1, -0x1.36d1623919ffp+4},
129 {0x1.10a39beeb2926p+5, -0x1.38fe38b7dab01p+1, -0x1.77efa95d520b4p+4},
130 {0x1.3de43fe8d92efp+5, -0x1.6cf188320fff2p+1, -0x1.b655790a27192p+4},
131 {0x1.69950098864afp+5, -0x1.9f19c42a8c674p+1, -0x1.f293e325bec2ep+4},
132 {0x1.50853f46a9f9ep+5, -0x1.6b6901a80404fp+3, 0x1.16bdec11e60d8p+3},
133 {0x1.5fa625f2c3fbcp+5, -0x1.d0691ed5aa7ap+2, -0x1.eac16e8cb9241p+0},
134 {0x1.6f4222fc3f0dbp+5, -0x1.61b0e7ffa5e8ap+2, -0x1.05e8906ee23d7p+3},
135 {0x1.83e99e6187f46p+5, -0x1.1a61c98b895p+2, -0x1.c3da094bbcf2fp+3},
136 {0x1.9ca47689a503dp+5, -0x1.e9259e3439104p+1, -0x1.396812c634de3p+4},
137 {0x1.b872b55db6144p+5, -0x1.ccd50a2fd6662p+1, -0x1.89dec898ec996p+4},
138 {0x1.b01d15d276ef1p+5, -0x1.d2a4448f6ccacp+3, 0x1.65ec167dcb488p+3},
139 {0x1.b9760adf5c444p+5, -0x1.6a3760af4b6c4p+3, 0x1.a26bb322495e2p+1},
140 {0x1.c38a22a31944p+5, -0x1.2a2a93c4b741p+3, -0x1.3b14a376ffbecp+1},
141 {0x1.d185a36cfcd6ep+5, -0x1.e760f29e8fcb4p+2, -0x1.0bf936f2a6743p+3},
142 {0x1.e321d754f2b44p+5, -0x1.95a749a95debp+2, -0x1.c3928e31b9cf8p+3},
143 {0x1.f7eb8d9ad84b9p+5, -0x1.5e28b7cc193ddp+2, -0x1.38bda7259441ep+4},
144 {0x1.0552717cdb82p+6, -0x1.1a33f75f67b0fp+4, 0x1.b0e8bd24c3fdep+3},
145 {0x1.08898a5b7805dp+6, -0x1.e29bd3071d97ap+3, 0x1.e0b5994e0238ep+2},
146 {0x1.0c10ad1b87866p+6, -0x1.a54f2215371a5p+3, 0x1.45758e5457898p+1},
147 {0x1.1111e924447e9p+6, -0x1.68a24e1d5efe1p+3, -0x1.7d178a838ea32p+1},
148 {0x1.178bb94d30a5cp+6, -0x1.335d7d75dd017p+3, -0x1.13f78c003ba13p+3},
149 {0x1.1f6aa49fcff2p+6, -0x1.0830d167759a4p+3, -0x1.c578e33f21d88p+3},
150 {0x1.30b236b57ac86p+6, -0x1.490afbe3d8e11p+4, 0x1.f8c35fbb689dap+3},
151 {0x1.331144aae0ad4p+6, -0x1.289bac3eeb83p+4, 0x1.626ea3a63748p+3},
152 {0x1.35b09f5c62a7ap+6, -0x1.0d33e3db59803p+4, 0x1.b66836d6f7ff6p+2},
153 {0x1.3973d5b39baa4p+6, -0x1.de87e61f0c86ap+3, 0x1.de8cf8346969cp+0},
154 {0x1.3e64dbeab2c38p+6, -0x1.a47dea5d85dbbp+3, -0x1.bc586cdcba45p+1},
155 {0x1.44815d7f73a41p+6, -0x1.706c35b4850ecp+3, -0x1.1d13e731dfc5bp+3},
156 {0x1.5a92b1ff8af32p+6, -0x1.76441609cfb3ap+4, 0x1.1f1186319beaap+4},
157 {0x1.5c6885a0ab4cap+6, -0x1.5c0bf4148d03dp+4, 0x1.c5b4a75d0a01ep+3},
158 {0x1.5e72281eb918cp+6, -0x1.4422b7d2ad44bp+4, 0x1.5305a49da3492p+3},
159 {0x1.61631d5752788p+6, -0x1.282b31110d79dp+4, 0x1.8b1a60b561753p+2},
160 {0x1.65488920f4795p+6, -0x1.0b1a0cfacacfbp+4, 0x1.3d72a3bb176fp+0},
161 {0x1.6a27499e4d3d6p+6, -0x1.de4892c062f8p+3, -0x1.f96a59bc9de4cp+1},
162 {0x1.e7d1475ebe201p+4, 0x1.5d4f5ebb6cf8ep+3, 0x1.86e150bac0e61p+2},
163 {0x1.10883ee613f6bp+5, 0x1.aa957aceb4328p+3, -0x1.06e4a6bcf37ep+3},
164 {0x1.2a507c82ee1e7p+5, 0x1.880d450b132c9p+3, -0x1.c81b5ba73664ap+3},
165 {0x1.4902475f20191p+5, 0x1.4f4dfeda4e013p+3, -0x1.38d6c960a7255p+4},
166 {0x1.6aa42ff68fb65p+5, 0x1.1116140836dp+3, -0x1.84f2dbb4bf7b2p+4},
167 {0x1.8def7d6adc3d5p+5, 0x1.ab6406f65a5b9p+2, -0x1.caee116cbc66ep+4},
168 {0x1.77f724f99d0c9p+5, -0x1.bb9ee0e906bf2p+1, 0x1.345d15707c9e4p+3},
169 {0x1.8465d178eda3bp+5, -0x1.021519c6d64p-11, -0x1.11ebea130b3p-8},
170 {0x1.917d476fba08dp+5, 0x1.84e9b4b9a4816p+0, -0x1.89910d2df7414p+2},
171 {0x1.a32d016052029p+5, 0x1.352fbc1045df3p+1, -0x1.847eed4ab1e03p+3},
172 {0x1.b8cfd7baeb72ap+5, 0x1.5d6575ced028ep+1, -0x1.1bff70d82f589p+4},
173 {0x1.d1a20bfd91dbap+5, 0x1.4de285fe39a4dp+1, -0x1.6f381fca63bcep+4},
174 {0x1.c99e943a2d79fp+5, -0x1.219ec15c5de22p+3, 0x1.78f2db7cd8205p+3},
175 {0x1.d20af5c832c06p+5, -0x1.86c31353f2968p+2, 0x1.15f4d958ffb6ep+2},
176 {0x1.db2d2b76b7db4p+5, -0x1.107aa185fa178p+2, -0x1.3a545f6bb32fep+0},
177 {0x1.e7ef429658179p+5, -0x1.58a57459e2113p+1, -0x1.c50012145074dp+2},
178 {0x1.f821bad822a9ep+5, -0x1.8ea06e2a9e1f6p+0, -0x1.9a5cf82ebb612p+3},
179 {0x1.05b4f2f9696abp+6, -0x1.b3645fe7f9294p-1, -0x1.24f471b4e8b62p+4},
180 {0x1.0e4a1f1b1ddcep+6, -0x1.b32bbdf7204c1p+3, 0x1.be3e8e0b04a1fp+3},
181 {0x1.114fcf04f35b3p+6, -0x1.6696d5115c7e4p+3, 0x1.058704ea2708p+3},
182 {0x1.14a2558b5b6c7p+6, -0x1.2c7e211429d81p+3, 0x1.a9f809f8ee4dfp+1},
183 {0x1.195c00cf22a51p+6, -0x1.e58de99c40fb6p+2, -0x1.0e4f6479339a5p+1},
184 {0x1.1f7e4eea78cb7p+6, -0x1.809e6530a25d5p+2, -0x1.ee2cfac349d5ep+2},
185 {0x1.26f9f5da0f33bp+6, -0x1.2ffe0404fe1e4p+2, -0x1.a87af760f19c2p+3},
186 {0x1.37635555b270cp+6, -0x1.17deced6d377ep+4, 0x1.0159387931185p+4},
187 {0x1.39aa8b444a1c7p+6, -0x1.f1b4258b74e35p+3, 0x1.70a1d9ed49333p+3},
188 {0x1.3c30003dc4bdap+6, -0x1.bcf061cd62971p+3, 0x1.d845b8f464806p+2},
189 {0x1.3fcf0a7e4fdb8p+6, -0x1.8316f8fb04f1cp+3, 0x1.3be7d797ab219p+1},
190 {0x1.4492530767fa4p+6, -0x1.4af657f86bc35p+3, -0x1.69ccecfbead6p+1},
191 {0x1.4a78e7a0304fbp+6, -0x1.18be182ded159p+3, -0x1.07ac09ccdfff4p+3},
192 {0x1.5fc9ac083946p+6, -0x1.4f840d59cd9aep+4, 0x1.22ef620ec7775p+4},
193 {0x1.6192b2ae205fp+6, -0x1.361d4509435d5p+4, 0x1.cfe893676e62ep+3},
194 {0x1.638e487d443e1p+6, -0x1.1edcf418396fcp+4, 0x1.5f105a3f7b33p+3},
195 {0x1.666b5164f3799p+6, -0x1.03988ade0159ep+4, 0x1.a6a2e5baac692p+2},
196 {0x1.6a3706fa48d42p+6, -0x1.ce6b98f424c54p+3, 0x1.b67fa4fafc2e8p+0},
197 {0x1.6ef6b7860b53fp+6, -0x1.97ce09961f218p+3, -0x1.b926ed0fbe897p+1},
198 {0x1.3931bb83cb32dp+5, 0x1.c0894426a198dp+3, 0x1.f5ea328bf4058p+2},
199 {0x1.4b9e77eb58ebfp+5, 0x1.108cfd41d7919p+4, -0x1.0eaf04c8d3b35p+2},
200 {0x1.5df2d7bacd40ap+5, 0x1.11e15f9b225acp+4, -0x1.51924b9c514f3p+3},
201 {0x1.756bc7d79519bp+5, 0x1.03a63c750b36bp+4, -0x1.052fc194cf52p+4},
202 {0x1.90b3e1d276c5dp+5, 0x1.d79fd75fb3811p+3, -0x1.58e6a7a1da1fcp+4},
203 {0x1.aea5654d2d631p+5, 0x1.9f14550c88c57p+3, -0x1.a57e86563dbcap+4},
204 {0x1.9b6948efcb1e8p+5, 0x1.dddaa142e7b3ap+0, 0x1.4f83ba256abcfp+3},
205 {0x1.a5f9bfdb796c8p+5, 0x1.3de3647070a5bp+2, 0x1.b416b1e2a3817p+0},
206 {0x1.b1407c7a80b46p+5, 0x1.9d8674f672f17p+2, -0x1.112d7835e0443p+2},
207 {0x1.c0b6552db89b1p+5, 0x1.d8c2a5262b398p+2, -0x1.480f10f6d0b5fp+3},
208 {0x1.d3edc2b5ca1f7p+5, 0x1.edbf49a0778e4p+2, -0x1.fe5ca96caae15p+3},
209 {0x1.ea519f7b4bf8cp+5, 0x1.e35c8bfe38bf9p+2, -0x1.5483ed4b7e5ebp+4},
210 {0x1.e2c36ca30962cp+5, -0x1.1cd1878e91233p+2, 0x1.8bf558e4fbde3p+3},
211 {0x1.ea67769abd5c1p+5, -0x1.c053e5b6c3b66p+0, 0x1.59302161a2865p+2},
212 {0x1.f2ba2dd022991p+5, -0x1.4b64e809e68p-11, -0x1.5fbb8b338b8p-8},
213 {0x1.fe6b844bbf20fp+5, 0x1.8040f07e39554p+0, -0x1.7196ffd7de002p+2},
214 {0x1.06aeef460087dp+6, 0x1.4afa79e390244p+1, -0x1.705a7c8493135p+3},
215 {0x1.0fa5554a5c955p+6, 0x1.9dea7336ee828p+1, -0x1.1089bb9ca046ep+4},
216 {0x1.178e9051b853ep+6, -0x1.3b3b8e6c52f1cp+3, 0x1.cc268b9a4e157p+3},
217 {0x1.1a65db5c4c0d1p+6, -0x1.e697a167b2b86p+2, 0x1.1b4d0d1ca381dp+3},
218 {0x1.1d86bd983524p+6, -0x1.77ccb1bcef226p+2, 0x1.08e1384d16e75p+2},
219 {0x1.21fc7ad985402p+6, -0x1.08e3f099fb00fp+2, -0x1.363e6fbac8902p+0},
220 {0x1.27cb1d6dd9434p+6, -0x1.4f7ef424b1025p+1, -0x1.b1af4c945ce98p+2},
221 {0x1.2ee710ec206cfp+6, -0x1.6ac7f2787bda1p+0, -0x1.89e8c18db3849p+3},
222 {0x1.3e7c86695f695p+6, -0x1.ceac064fd3a97p+3, 0x1.06a67a74ff4cp+4},
223 {0x1.40ac0504d65f2p+6, -0x1.935bda5136fdbp+3, 0x1.7fa8ea5683dffp+3},
224 {0x1.4317a9d652f14p+6, -0x1.608608dcc2607p+3, 0x1.fc21edd271f8bp+2},
225 {0x1.46928cf49114ap+6, -0x1.2883a0410f74bp+3, 0x1.8d4b911a8102bp+1},
226 {0x1.4b27f53f2d1c8p+6, -0x1.e40f8922e26b2p+2, -0x1.11ca0bf0acee9p+1},
227 {0x1.50d83b6f7788bp+6, -0x1.82a0417f98419p+2, -0x1.e18432a6676edp+2},
228 {0x1.6567db05a012cp+6, -0x1.27d55f8b64f16p+4, 0x1.271e9400a42e4p+4},
229 {0x1.6723b3feab73ap+6, -0x1.0f412c5a09d1ap+4, 0x1.dae43f7f7eb6ep+3},
230 {0x1.6910cf423acf1p+6, -0x1.f152d3d18c3b3p+3, 0x1.6c04c44876eb2p+3},
231 {0x1.6bd948eca017fp+6, -0x1.bc29d2c53f57ap+3, 0x1.c44a28d107a62p+2},
232 {0x1.6f8a69cf10b1p+6, -0x1.84b224c6d040cp+3, 0x1.1c910c629db67p+1},
233 {0x1.7429ebc4e406dp+6, -0x1.4f4a0b735c531p+3, -0x1.73a39097eadefp+1},
234 {0x1.7acf7694f8c6p+5, 0x1.0f40ef4bed7e8p+4, 0x1.2f88d81b23f2ep+3},
235 {0x1.87b52573912c8p+5, 0x1.3e9cadbae2c71p+4, -0x1.21c127942ffc2p-1},
236 {0x1.95308092c646cp+5, 0x1.4bd8ec93cbe28p+4, -0x1.b1ad2fc6cd5ccp+2},
237 {0x1.a743d71712a69p+5, 0x1.4b428f09e4704p+4, -0x1.984b766ca527bp+3},
238 {0x1.bd35da1ada54ap+5, 0x1.3ee7b023f1a36p+4, -0x1.252f399063a3p+4},
239 {0x1.d638af110e2bfp+5, 0x1.2a6369728426p+4, -0x1.777a4238ecc9cp+4},
240 {0x1.c5db1e678f93bp+5, 0x1.be23ef0d11b9fp+2, 0x1.706e52e6555aep+3},
241 {0x1.ceab15b1e5e2cp+5, 0x1.376364145a451p+3, 0x1.d7fd2a954eedcp+1},
242 {0x1.d8302a174d63dp+5, 0x1.67a05469bf7c1p+3, -0x1.0236bbe6ffddap+1},
243 {0x1.e56c6a282c6fep+5, 0x1.8915eed9a5994p+3, -0x1.fb2d49a257381p+2},
244 {0x1.f622a3ef65e7fp+5, 0x1.98638aed6156bp+3, -0x1.b57e66e36241ap+3},
245 {0x1.04f5c4d9c25cfp+6, 0x1.9710ff57a7b7ap+3, -0x1.32004fe7bd5b5p+4},
246 {0x1.018127d59826cp+6, 0x1.1e619caaa3a8fp-1, 0x1.a49bd0215a96dp+3},
247 {0x1.04e57659b4cf6p+6, 0x1.8024718692a3cp+1, 0x1.addd1b874609p+2},
248 {0x1.089bd543a0e63p+6, 0x1.2a7652607e02cp+2, 0x1.8d85013677bap+0},
249 {0x1.0ddb424d04fadp+6, 0x1.889c9b8223651p+2, -0x1.05aa1bc86a9d4p+2},
250 {0x1.149da8fbd8909p+6, 0x1.ce4542c130c31p+2, -0x1.3934aac98d184p+3},
251 {0x1.1cca409e32c6dp+6, 0x1.f855300b25ba5p+2, -0x1.eac45e49f86bap+3},
252 {0x1.23f3e081f0e6fp+6, -0x1.587d5d644e818p+2, 0x1.deea03a7e9e2p+3},
253 {0x1.26935d2d5bb58p+6, -0x1.a6ab45ebb79ddp+1, 0x1.38265c4c6d156p+3},
254 {0x1.29783d4927cb6p+6, -0x1.aa081e388f0b6p+0, 0x1.4de28afb99798p+2},
255 {0x1.2d9b5abdd0df6p+6, -0x1.90d2c34c4c8p-11, -0x1.a96c3913736p-8},
256 {0x1.3303704c60227p+6, 0x1.7842d686da2p+0, -0x1.6001098473213p+2},
257 {0x1.39a911d79bf6cp+6, 0x1.51ae39272f6fp+1, -0x1.604eff9e13224p+3},
258 {0x1.483b66bb75f41p+6, -0x1.53e4a65e5bd0ep+3, 0x1.0dfa4f4feec89p+4},
259 {0x1.4a4cab5bdb777p+6, -0x1.1bf0c7950b46ap+3, 0x1.9433415e2e559p+3},
260 {0x1.4c9756fc325a6p+6, -0x1.d6e499fe26166p+2, 0x1.1693b52228314p+3},
261 {0x1.4fe3e8502420ap+6, -0x1.6b29463056a7ep+2, 0x1.fcea504279e1bp+1},
262 {0x1.543e4f84c51c9p+6, -0x1.01c201c3fcfbep+2, -0x1.311b349896504p+0},
263 {0x1.59a86b698fe17p+6, -0x1.4697ac30fd276p+1, -0x1.a218614573a54p+2},
264 {0x1.6d3f94c53849cp+6, -0x1.e750c3b6abf94p+3, 0x1.2cfd8e3a3298cp+4},
265 {0x1.6ee9ffc7c561bp+6, -0x1.b847cb4caca9ap+3, 0x1.ea32a397a5ea3p+3},
266 {0x1.70c3ef56a2364p+6, -0x1.8cc812a446223p+3, 0x1.7e0dc7e1aa4eep+3},
267 {0x1.737125604c02dp+6, -0x1.5959ff3792892p+3, 0x1.ed9e6884d6db8p+2},
268 {0x1.76fef3ccb11e4p+6, -0x1.2379a952d29eap+3, 0x1.77d044e094287p+1},
269 {0x1.7b739668b58adp+6, -0x1.def62d62ac5d3p+2, -0x1.1242c0559f9b9p+1},
270 {0x1.b9af6705b3e1ap+5, 0x1.3c46b4e4aa724p+4, 0x1.61ea416f62116p+3},
271 {0x1.c34652a386648p+5, 0x1.673d5400dac6ap+4, 0x1.575529f864e4ap+1},
272 {0x1.cd90a5a7155efp+5, 0x1.7aac661c86347p+4, -0x1.97f5d2781d1d2p+1},
273 {0x1.dbc2183aadc6dp+5, 0x1.83f34257f81ecp+4, -0x1.24c7f27451716p+3},
274 {0x1.ed84b050fd5fep+5, 0x1.823e0b9a9286fp+4, -0x1.dc10370a896a1p+3},
275 {0x1.012d3f7585d8bp+6, 0x1.772916c92c8cp+4, -0x1.444d46ad4a3f5p+4},
276 {0x1.f498a57d50c8dp+5, 0x1.72c50647a1b01p+3, 0x1.9501b7bc92a26p+3},
277 {0x1.fbec5add8799fp+5, 0x1.c10937ac1ff0cp+3, 0x1.71506b03a0cfcp+2},
278 {0x1.01f4d75996fc6p+6, 0x1.f168c838b27a5p+3, 0x1.a2871b4170f08p-2},
279 {0x1.07934868d42f1p+6, 0x1.0ba82dcee8d5fp+4, -0x1.55f50c12fdb69p+2},
280 {0x1.0ec4c024626fep+6, 0x1.16b4701bb2cep+4, -0x1.627c9a1b01177p+3},
281 {0x1.1768d8b0aa031p+6, 0x1.199f4e2e9e65fp+4, -0x1.09c1c4e924702p+4},
282 {0x1.14522a4a9a7e2p+6, 0x1.6020b0a7ecac7p+2, 0x1.c1a8f99df62d9p+3},
283 {0x1.174b930ef061ap+6, 0x1.ec83068a9839fp+2, 0x1.06f134f7cc07ep+3},
284 {0x1.1a90921a38fe7p+6, 0x1.28d89eb448a2cp+3, 0x1.ab5fe99a94265p+1},
285 {0x1.1f36b9520ad75p+6, 0x1.57ace8397fb96p+3, -0x1.0feb2da7758d4p+1},
286 {0x1.253f2b741784fp+6, 0x1.7c087d08384b1p+3, -0x1.efdb49212f992p+2},
287 {0x1.2c9a998952cf1p+6, 0x1.9366b5a4edd8ap+3, -0x1.a9848b6099745p+3},
288 {0x1.330541ae3e385p+6, -0x1.39e238ea7801p-1, 0x1.f5ec9f058d778p+3},
289 {0x1.3568ff8940412p+6, 0x1.4b2aea6a2b17bp+0, 0x1.5aadb9534e15p+3},
290 {0x1.380d495b09ffp+6, 0x1.6b2260c162acep+1, 0x1.a0b3e40fdedfp+2},
291 {0x1.3bd6db55a86abp+6, 0x1.1c0894632c07ep+2, 0x1.73acfbc73a52cp+0},
292 {0x1.40ced5740b6ecp+6, 0x1.784d8d5bd59bap+2, -0x1.f87f29ae0432ap+1},
293 {0x1.46f1d56d6a627p+6, 0x1.c2acec311d85p+2, -0x1.2d078d1d0ec93p+3},
294 {0x1.54692a261ff77p+6, -0x1.91aafde5841e2p+2, 0x1.1733b7c5acf09p+4},
295 {0x1.5657fb0185f53p+6, -0x1.292fef1c6094ap+2, 0x1.adacb9827ba1ep+3},
296 {0x1.587cf8c168362p+6, -0x1.9aa045411de21p+1, 0x1.34f47fa15abacp+3},
297 {0x1.5b946ca219efdp+6, -0x1.98465c0dc7b2ap+0, 0x1.43ded9d06d2f2p+2},
298 {0x1.5faadb5249c01p+6, -0x1.d35a0bdd6ap-11, -0x1.f008c176226p-8},
299 {0x1.64c3b31613c93p+6, 0x1.6ffd305ac700dp+0, -0x1.52580b551209ep+2},
300 {0x1.773c645e32d2dp+6, -0x1.6c001f7fba478p+3, 0x1.3482f283026fp+4},
301 {0x1.78d215b19332bp+6, -0x1.3f6c1cce8d703p+3, 0x1.fda06ae8dbf53p+3},
302 {0x1.7a9531dc8addap+6, -0x1.15dd42d16c7e4p+3, 0x1.94e8098e96fccp+3},
303 {0x1.7d21e2193d5bcp+6, -0x1.c8c718caa9f8ep+2, 0x1.1105d830d79dp+3},
304 {0x1.808572bc9578ap+6, -0x1.607bf910c57eep+2, 0x1.ebe2b93545493p+1},
305 {0x1.84c6a7914070fp+6, -0x1.f6c2ba3dfc25ap+1, -0x1.2beab2de5e36ep+0},
306 {0x1.f663baac570efp+5, 0x1.67be9f690c994p+4, 0x1.928e76c3750aep+3},
307 {0x1.fdd78bfa0c16bp+5, 0x1.8da11d29326eap+4, 0x1.63128e5e5d16fp+2},
308 {0x1.02fa8211ca545p+6, 0x1.a3a4c44447321p+4, 0x1.04d0a318f0ebp-3},
309 {0x1.08ace6a6b1bbcp+6, 0x1.b32f97fdc6c72p+4, -0x1.69ea7f28a916ap+2},
310 {0x1.0ff3cb8943e81p+6, 0x1.b9bf03db71bbbp+4, -0x1.6cb54bc7e9c6p+3},
311 {0x1.18ac5c68852cdp+6, 0x1.b753a9bd5dbeep+4, -0x1.0ebf0dff35bfbp+4},
312 {0x1.12e57190e4906p+6, 0x1.f7243f8456bc9p+3, 0x1.bbbf019d6f15fp+3},
313 {0x1.15f567ae01685p+6, 0x1.1e238872ebfe1p+4, 0x1.f5db81101607bp+2},
314 {0x1.1952176f81196p+6, 0x1.35eb43e1b3454p+4, 0x1.6f044118da651p+1},
315 {0x1.1e17b3f5be1e9p+6, 0x1.4aa233635e996p+4, -0x1.54536023af51fp+1},
316 {0x1.244540fde90c8p+6, 0x1.590428a4cd957p+4, -0x1.09fd595c81312p+3},
317 {0x1.2bc8d270727cdp+6, 0x1.6002d76c0fae1p+4, -0x1.bbbb8dd0769e1p+3},
318 {0x1.2910051d7f4b8p+6, 0x1.4505f3d8c93bep+3, 0x1.e1f0441f64aep+3},
319 {0x1.2ba848891bba1p+6, 0x1.83d80a13be75dp+3, 0x1.39f759ee811ebp+3},
320 {0x1.2e852380cafc2p+6, 0x1.b3d439de20201p+3, 0x1.5018eb1694a48p+2},
321 {0x1.329c951f395aap+6, 0x1.e28db45c54996p+3, 0x1.689e197414bp-7},
322 {0x1.37f5013da44b7p+6, 0x1.04846845ce376p+4, -0x1.5f9623aa14c25p+2},
323 {0x1.3e86c9cea44c3p+6, 0x1.11f59319394fdp+4, -0x1.6049926fe33dap+3},
324 {0x1.443efb939f1d1p+6, 0x1.0a131d35fab88p+2, 0x1.0838884c6c35ap+4},
325 {0x1.4667729b66dbap+6, 0x1.793a281884d1p+2, 0x1.8155ad5254ba1p+3},
326 {0x1.48cb51f255527p+6, 0x1.d609d14c020d1p+2, 0x1.fd82e0735fdcep+2},
327 {0x1.4c3af36c4bb13p+6, 0x1.1c709781a9fb2p+3, 0x1.8ca66dc4e33fdp+1},
328 {0x1.50c14ed0ba88bp+6, 0x1.4a1d653379591p+3, -0x1.14ee52d3fd0e1p+1},
329 {0x1.565e87fd89a8p+6, 0x1.6fe5c4c37980fp+3, -0x1.e3e3e3d81f648p+2},
330 {0x1.62b687ada6a2dp+6, -0x1.b1a7c98c53b9bp+0, 0x1.221d2fc2be6cp+4},
331 {0x1.6480f342fedfap+6, -0x1.728e49c5a9ba8p-3, 0x1.cb44060a17de8p+3},
332 {0x1.667e081a8e931p+6, 0x1.2c204353d8acp+0, 0x1.582d07a1ac706p+3},
333 {0x1.695d03a4b4ea6p+6, 0x1.5b9dd1e5192c9p+1, 0x1.949cc8da7db3dp+2},
334 {0x1.6d2ad25b49139p+6, 0x1.10c661536b1e3p+2, 0x1.60b9aee667ea2p+0},
335 {0x1.71ec510363cccp+6, 0x1.6b2af260ca3f1p+2, -0x1.e8e3d6769ed61p+1},
336 {0x1.83323c984ee7ap+6, -0x1.c8df58716d4cbp+2, 0x1.3d9335b5d20f9p+4},
337 {0x1.84b109344c92cp+6, -0x1.750134f94569cp+2, 0x1.0a63166d3ca32p+4},
338 {0x1.865ae5967696dp+6, -0x1.260f129da839ep+2, 0x1.b00f6d0ac1f93p+3},
339 {0x1.88c3891dbffdp+6, -0x1.8e7bf5d542ea4p+1, 0x1.30323669c3d67p+3},
340 {0x1.8bf825267af8ep+6, -0x1.89d8c0f2ba1ffp+0, 0x1.3b2af0c9eed76p+2},
341 {0x1.8ffffbb77c76ap+6, -0x1.09cab717214p-10, -0x1.1a1aa7765a7p-7},
342 {0x1.ae1c063cf8075p+3, -0x1.1dcc8d6b21p-13, -0x1.2f56d49352fp-10},
343 {0x1.23869fde6955fp+4, -0x1.836d13c82dp-13, -0x1.9b340cb2926p-10},
344 {0x1.6a51d9755cb1ep+4, -0x1.e1821bf6d08p-13, -0x1.ff0f3c5806ap-10},
345 {0x1.adca073d0c9a1p+4, -0x1.1d961152df8p-12, -0x1.2f1d00745cap-9},
346 {0x1.eeb26a3638306p+4, -0x1.48b751f0a58p-12, -0x1.5ce3e1a3db8p-9},
347 {0x1.16c4868a9dbc4p+5, -0x1.7278906708p-12, -0x1.89352628678p-9},
348 {0x1.3552cb4726ed2p+5, -0x1.9b140ac6fbp-12, -0x1.b44e9f2325p-9},
349 {0x1.53242132979b2p+5, -0x1.c2b46f9c328p-12, -0x1.de5d99b6f9p-9},
350 {0x1.7051013cf5a69p+5, -0x1.e97a44c10a8p-12, -0x1.03c24d5b897p-8},
351 {0x1.8ceca3a0569fdp+5, -0x1.07bf8a7e0fcp-11, -0x1.17ef5f1c441p-8},
352 {0x1.a9067ed63306p+5, -0x1.1a6bb67a6bp-11, -0x1.2bc0e9df0a8p-8},
353 {0x1.c4ab42f91535bp+5, -0x1.2cca14a233p-11, -0x1.3f3fe0662d2p-8},
354 {0x1.dfe5855ae1528p+5, -0x1.3ee1ad40618p-11, -0x1.5273b9784a3p-8},
355 {0x1.fabe397d15c9dp+5, -0x1.50b872fc158p-11, -0x1.6562c531248p-8},
356 {0x1.0a9e8459f8d9ap+6, -0x1.62537d1958p-11, -0x1.78126ad030ep-8},
357 {0x1.17b44990f13f5p+6, -0x1.73b732a42fp-11, -0x1.8a87568ccdp-8},
358 {0x1.24a350705ddf4p+6, -0x1.84e76b1c308p-11, -0x1.9cc59c424aap-8},
359 {0x1.316e23ed9d96ap+6, -0x1.95e7879947p-11, -0x1.aed0d2216dp-8},
360 {0x1.3e1704b29c069p+6, -0x1.a6ba8679e08p-11, -0x1.c0ac258f992p-8},
361 {0x1.4a9ff4d8984e6p+6, -0x1.b76312f3808p-11, -0x1.d25a6bb27acp-8},
362 {0x1.570ac151c1615p+6, -0x1.c7e3919c138p-11, -0x1.e3de2eb684p-8},
363 {0x1.6359098c40c61p+6, -0x1.d83e2a89bbp-11, -0x1.f539b894d66p-8},
364 {0x1.6f8c45b456692p+6, -0x1.e874d1a7f5p-11, -0x1.03378df3804p-7},
365 {0x1.7ba5cbe12c3fcp+6, -0x1.f8894d9602p-11, -0x1.0bc01d99c93p-7},
378 constexpr
double RGB888_to_sRGB_table[] {
379 0x0p+0, 0x1.3e45677c176f7p-12, 0x1.3e45677c176f7p-11, 0x1.dd681b3a23272p-11,
380 0x1.3e45677c176f7p-10, 0x1.8dd6c15b1d4b4p-10, 0x1.dd681b3a23272p-10, 0x1.167cba8c94818p-9,
381 0x1.3e45677c176f7p-9, 0x1.660e146b9a5d6p-9, 0x1.8dd6c15b1d4b4p-9, 0x1.b6a31b5259c99p-9,
382 0x1.e1e31d70c99ddp-9, 0x1.07c38bf8583a9p-8, 0x1.1fcc2beed6421p-8, 0x1.390ffaf95e279p-8,
383 0x1.53936cc7bc928p-8, 0x1.6f5addb50c915p-8, 0x1.8c6a94031b561p-8, 0x1.aac6c0fb97351p-8,
384 0x1.ca7381f9f602bp-8, 0x1.eb74e160978dp-8, 0x1.06e76bbda92b8p-7, 0x1.18c2a5a8a8044p-7,
385 0x1.2b4e09b3f0ae3p-7, 0x1.3e8b7b3bde965p-7, 0x1.527cd60af8b85p-7, 0x1.6723eea8d3709p-7,
386 0x1.7c8292a3db6b3p-7, 0x1.929a88d67b521p-7, 0x1.a96d91a8016bdp-7, 0x1.c0fd67499fab6p-7,
387 0x1.d94bbdefd740ep-7, 0x1.f25a44089883fp-7, 0x1.061551372c694p-6, 0x1.135f3e4c2cce2p-6,
388 0x1.210bb8642b172p-6, 0x1.2f1b8c1ae46bdp-6, 0x1.3d8f839b79c0bp-6, 0x1.4c6866b3e9fa4p-6,
389 0x1.5ba6fae794313p-6, 0x1.6b4c0380d2deep-6, 0x1.7b5841a1bf3acp-6, 0x1.8bcc74542addbp-6,
390 0x1.9ca95898dc8b5p-6, 0x1.adefa9761c02p-6, 0x1.bfa0200597bd9p-6, 0x1.d1bb7381aec1fp-6,
391 0x1.e442595227bcap-6, 0x1.f73585185e1b5p-6, 0x1.054ad45d76878p-5, 0x1.0f31ba386ff26p-5,
392 0x1.194fcb663747bp-5, 0x1.23a55e62a662ap-5, 0x1.2e32c8e148d11p-5, 0x1.38f85fd21eacfp-5,
393 0x1.43f67766310ffp-5, 0x1.4f2d6313fa8dp-5, 0x1.5a9d759ba5edp-5, 0x1.6647010b254eep-5,
394 0x1.722a56c2239eep-5, 0x1.7e47c775d2427p-5, 0x1.8a9fa33494b07p-5, 0x1.973239698b9ccp-5,
395 0x1.a3ffd8e001389p-5, 0x1.b108cfc6b7fbcp-5, 0x1.be4d6bb31d522p-5, 0x1.cbcdf9a4616f2p-5,
396 0x1.d98ac60675833p-5, 0x1.e7841cb4f16dfp-5, 0x1.f5ba48fde2048p-5, 0x1.0216cad240765p-4,
397 0x1.096f2671eb815p-4, 0x1.10e65c38a5192p-4, 0x1.187c90bf8bce2p-4, 0x1.2031e85f5d6dap-4,
398 0x1.28068731a1952p-4, 0x1.2ffa9111cb94bp-4, 0x1.380e299e53f92p-4, 0x1.40417439ca10fp-4,
399 0x1.4894940bddbfbp-4, 0x1.5107ac0261e59p-4, 0x1.599aded247aacp-4, 0x1.624e4ef892ed4p-4,
400 0x1.6b221ebb4817ep-4, 0x1.7416702a539d1p-4, 0x1.7d2b65206b527p-4, 0x1.86611f43e9e6ap-4,
401 0x1.8fb7c007a4a7p-4, 0x1.992f68abbbc89p-4, 0x1.a2c83a3e6566dp-4, 0x1.ac82559cb3644p-4,
402 0x1.b65ddb7354604p-4, 0x1.c05aec3f4fe5ep-4, 0x1.ca79a84ebe03p-4, 0x1.d4ba2fc17a6a5p-4,
403 0x1.df1ca289d34b8p-4, 0x1.e9a1206d34003p-4, 0x1.f447c904cbb4ep-4, 0x1.ff10bbbe302c2p-4,
404 0x1.04fe0bedfe5f1p-3, 0x1.0a84fe3b36d8fp-3, 0x1.101d443dfc06fp-3, 0x1.15c6ed58eefdfp-3,
405 0x1.1b8208da5fefp-3, 0x1.214ea5fc9514ap-3, 0x1.272cd3e610123p-3, 0x1.2d1ca1a9d1cfbp-3,
406 0x1.331e1e479cdf5p-3, 0x1.393158ac3674ep-3, 0x1.3f565fb1a5fd5p-3, 0x1.458d421f735dfp-3,
407 0x1.4bd60eaae3e73p-3, 0x1.5230d3f736034p-3, 0x1.589da095dbaa1p-3, 0x1.5f1c8306b3a3cp-3,
408 0x1.65ad89b841a2bp-3, 0x1.6c50c307e53bfp-3, 0x1.73063d420fc8p-3, 0x1.79ce06a279303p-3,
409 0x1.80a82d5453b5dp-3, 0x1.8794bf727eb3fp-3, 0x1.8e93cb07b8679p-3, 0x1.95a55e0ecec0bp-3,
410 0x1.9cc98672cf47ep-3, 0x1.a400520f3619cp-3, 0x1.ab49ceb01c003p-3, 0x1.b2a60a1263b0ap-3,
411 0x1.ba1511e3e632dp-3, 0x1.c196f3c39e76fp-3, 0x1.c92bbd41d41fep-3, 0x1.d0d37be045851p-3,
412 0x1.d88e3d1250f68p-3, 0x1.e05c0e3d1d3ep-3, 0x1.e83cfcb7c16fp-3, 0x1.f03115cb6bfd3p-3,
413 0x1.f83866b38924dp-3, 0x1.00297e4ef4553p-2, 0x1.044072557177ap-2, 0x1.086115f6beb3ap-2,
414 0x1.0c8b6fb5c735ep-2, 0x1.10bf860ef039ap-2, 0x1.14fd5f782a5a6p-2, 0x1.1945026102997p-2,
415 0x1.1d967532b31b1p-2, 0x1.21f1be50339e7p-2, 0x1.2656e41649ae3p-2, 0x1.2ac5ecdb988f8p-2,
416 0x1.2f3edef0b0ed8p-2, 0x1.33c1c0a020438p-2, 0x1.384e982e800b1p-2, 0x1.3ce56bda84a81p-2,
417 0x1.418641dd0c1bcp-2, 0x1.463120692c7afp-2, 0x1.4ae60dac4229dp-2, 0x1.4fa50fcdfde15p-2,
418 0x1.546e2cf0727a9p-2, 0x1.59416b3022858p-2, 0x1.5e1ed0a40daabp-2, 0x1.6306635dbdd7bp-2,
419 0x1.67f82969543a2p-2, 0x1.6cf428cd96079p-2, 0x1.71fa678bf915dp-2, 0x1.770aeba0b042ap-2,
420 0x1.7c25bb02b7ac5p-2, 0x1.814adba3e0bd9p-2, 0x1.867a5370de0b1p-2, 0x1.8bb428514f067p-2,
421 0x1.90f86027cb84ep-2, 0x1.964700d1ef1b1p-2, 0x1.9ba0102864521p-2, 0x1.a10393feefafdp-2,
422 0x1.a67192247a9bep-2, 0x1.abea10631e195p-2, 0x1.b16d14802d5cap-2, 0x1.b6faa43c403bbp-2,
423 0x1.bc92c5533d785p-2, 0x1.c2357d7c64e5dp-2, 0x1.c7e2d26a596dep-2, 0x1.cd9ac9cb2aef2p-2,
424 0x1.d35d69485ffc5p-2, 0x1.d92ab686ff782p-2, 0x1.df02b7279a10dp-2, 0x1.e4e570c6539c5p-2,
425 0x1.ead2e8faec526p-2, 0x1.f0cb2558c9ea4p-2, 0x1.f6ce2b6f00983p-2, 0x1.fcdc00c85bec2p-2,
426 0x1.017a5575b3cb2p-1, 0x1.048c17ad3c04bp-1, 0x1.07a349c9d9837p-1, 0x1.0abfee888c05p-1,
427 0x1.0de208a4444c8p-1, 0x1.11099ad5e83ebp-1, 0x1.1436a7d456eefp-1, 0x1.176932546ca12p-1,
428 0x1.1aa13d0906bdap-1, 0x1.1ddecaa307b85p-1, 0x1.2121ddd15aecep-1, 0x1.246a7940f86d1p-1,
429 0x1.27b89f9ce8c4bp-1, 0x1.2b0c538e48b07p-1, 0x1.2e6597bc4ccap-1, 0x1.31c46ecc4528dp-1,
430 0x1.3528db61a0f73p-1, 0x1.3892e01df1fccp-1, 0x1.3c027fa0f01ebp-1, 0x1.3f77bc887cd3bp-1,
431 0x1.42f29970a68f8p-1, 0x1.467318f3ac22dp-1, 0x1.49f93daa00113p-1, 0x1.4d850a2a4bde1p-1,
432 0x1.51168109734e5p-1, 0x1.54ada4da97a1bp-1, 0x1.584a782f1ac23p-1, 0x1.5becfd96a2698p-1,
433 0x1.5f95379f1b3edp-1, 0x1.634328d4bbe97p-1, 0x1.66f6d3c2081cfp-1, 0x1.6ab03aefd39aap-1,
434 0x1.6e6f60e5452b1p-1, 0x1.72344827d98f6p-1, 0x1.75fef33b6669bp-1, 0x1.79cf64a21d1e2p-1,
435 0x1.7da59edc8dabp-1, 0x1.8181a469a9787p-1, 0x1.856377c6c6224p-1, 0x1.894b1b6fa0377p-1,
436 0x1.8d3891de5df49p-1, 0x1.912bdd8b91f45p-1, 0x1.952500ee3dda5p-1, 0x1.9923fe7bd4f67p-1,
437 0x1.9d28d8a83edfcp-1, 0x1.a13391e5da09fp-1, 0x1.a5442ca57e52ep-1, 0x1.a95aab567f88fp-1,
438 0x1.ad771066afec2p-1, 0x1.b1995e4262a69p-1, 0x1.b5c197546e3f8p-1, 0x1.b9efbe062f086p-1,
439 0x1.be23d4bf8981bp-1, 0x1.c25ddde6ecbbbp-1, 0x1.c69ddbe154af1p-1, 0x1.cae3d1124c90bp-1,
440 0x1.cf2fbfdbf11f1p-1, 0x1.d381aa9ef2e82p-1, 0x1.d7d993ba988d4p-1, 0x1.dc377d8cc0fd5p-1,
441 0x1.e09b6a71e5aa6p-1, 0x1.e5055cc51cbb4p-1, 0x1.e97556e01b351p-1, 0x1.edeb5b1b37216p-1,
442 0x1.f2676bcd69adep-1, 0x1.f6e98b4c51466p-1, 0x1.fb71bbec33ab2p-1, 0x1p+0,
447 Lab rgbToOklab(QRgb rgb)
449 const double r = RGB888_to_sRGB_table[qRed(rgb)];
450 const double g = RGB888_to_sRGB_table[qGreen(rgb)];
451 const double b = RGB888_to_sRGB_table[qBlue(rgb)];
453 const double l = std::cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
454 const double m = std::cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
455 const double s = std::cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
459 (021.04542553 * l + 079.36177850 * m - 000.40720468 * s),
460 (197.79984951 * l - 242.85922050 * m + 045.05937099 * s),
461 (002.59040371 * l + 078.27717662 * m - 080.86757660 * s),
465 constexpr
double epsilon = 1e-15;
467 inline double sinDegree(
double x)
469 return std::sin(x * M_PI / 180.0);
472 inline double cosDegree(
double x)
474 return std::cos(x * M_PI / 180.0);
477 inline double pow2(
double x)
482 inline double computeHPrime(
double a_prime,
double b)
484 if (std::abs(a_prime) < epsilon && std::abs(b) < epsilon) {
488 const double value = std::atan2(b, a_prime) * 180.0 / M_PI;
489 return (value < 0.0) ? value + 360.0 : value;
492 inline double computeDeltaHPrime(
double C1_prime,
double C2_prime,
double h1_prime,
double h2_prime)
494 if (C1_prime * C2_prime < epsilon) {
498 const double diff = h2_prime - h1_prime;
500 if (std::abs(diff) <= 180.0) {
502 }
else if (diff > 180.0) {
509 inline double computeHPrimeBar(
double C1_prime,
double C2_prime,
double h1_prime,
double h2_prime)
511 const double sum = h1_prime + h2_prime;
513 if (C1_prime * C2_prime < epsilon) {
517 const double dist = std::abs(h1_prime - h2_prime);
521 }
else if (sum < 360.0) {
522 return 0.5 * (sum + 360.0);
524 return 0.5 * (sum - 360.0);
531 double calculate_CIEDE2000(
const Lab &color1,
const Lab &color2)
533 const double L1 =
color1.L;
534 const double a1 =
color1.a;
535 const double b1 =
color1.b;
536 const double L2 = color2.L;
537 const double a2 = color2.a;
538 const double b2 = color2.b;
540 const double _25_pow_7 = 6103515625.0;
542 const double C1_ab = std::sqrt(a1 * a1 + b1 * b1);
543 const double C2_ab = std::sqrt(a2 * a2 + b2 * b2);
544 const double C_ab_bar = 0.5 * (C1_ab + C2_ab);
545 const double c_ab_bar_pow_7 = std::pow(C_ab_bar, 7.0);
546 const double G = 0.5 * (1.0 - std::sqrt(c_ab_bar_pow_7 / (c_ab_bar_pow_7 + _25_pow_7)));
547 const double a1_prime = (1.0 + G) * a1;
548 const double a2_prime = (1.0 + G) * a2;
549 const double C1_prime = std::sqrt(a1_prime * a1_prime + b1 * b1);
550 const double C2_prime = std::sqrt(a2_prime * a2_prime + b2 * b2);
551 const double h1_prime = computeHPrime(a1_prime, b1);
552 const double h2_prime = computeHPrime(a2_prime, b2);
554 const double deltaL_prime = L2 - L1;
555 const double deltaC_prime = C2_prime - C1_prime;
556 const double deltah_prime = computeDeltaHPrime(C1_prime, C2_prime, h1_prime, h2_prime);
557 const double deltaH_prime = 2.0 * std::sqrt(C1_prime * C2_prime) * sinDegree(0.5 * deltah_prime);
559 const double L_primeBar = 0.5 * (L1 + L2);
560 const double C_primeBar = 0.5 * (C1_prime + C2_prime);
561 const double h_primeBar = computeHPrimeBar(C1_prime, C2_prime, h1_prime, h2_prime);
563 const double T = 1.0 - 0.17 * cosDegree(h_primeBar - 30.0) + 0.24 * cosDegree(2.0 * h_primeBar) + 0.32 * cosDegree(3.0 * h_primeBar + 6.0)
564 - 0.20 * cosDegree(4.0 * h_primeBar - 63.0);
566 const double C_primeBar_pow7 = std::pow(C_primeBar, 7.0);
567 const double R_C = 2.0 * std::sqrt(C_primeBar_pow7 / (C_primeBar_pow7 + _25_pow_7));
568 const double S_L = 1.0 + (0.015 * pow2(L_primeBar - 50.0)) / std::sqrt(20.0 + pow2(L_primeBar - 50.0));
569 const double S_C = 1.0 + 0.045 * C_primeBar;
570 const double S_H = 1.0 + 0.015 * C_primeBar * T;
571 const double R_T = -R_C * sinDegree(60.0 * std::exp(-pow2((h_primeBar - 275) / 25.0)));
573 constexpr
double kL = 1.0;
574 constexpr
double kC = 1.0;
575 constexpr
double kH = 1.0;
577 const double deltaL = deltaL_prime / (kL * S_L);
578 const double deltaC = deltaC_prime / (kC * S_C);
579 const double deltaH = deltaH_prime / (kH * S_H);
581 return (deltaL * deltaL + deltaC * deltaC + deltaH * deltaH + R_T * deltaC * deltaH);
589 Q_ASSERT(remaining() >= 1);
596 Q_ASSERT(remaining() >= str.
size());
597 memcpy(m_data + m_size, str.
data(), str.
size());
598 m_size += str.
size();
601 void appendForeground(QRgb rgb,
bool is256Colors, ColorCache &colorCache)
604 append(rgb, is256Colors, colorCache);
607 void appendBackground(QRgb rgb,
bool is256Colors, ColorCache &colorCache)
610 append(rgb, is256Colors, colorCache);
613 void append(QRgb rgb,
bool is256Colors, ColorCache &colorCache)
615 auto appendUInt8 = [&](
int x) {
616 Q_ASSERT(x <= 255 && x >= 0);
626 append(
char(
'0' + x));
631 constexpr
char const* tb2digits =
632 "00" "01" "02" "03" "04" "05" "06" "07" "08" "09"
633 "10" "11" "12" "13" "14" "15" "16" "17" "18" "19"
634 "20" "21" "22" "23" "24" "25" "26" "27" "28" "29"
635 "30" "31" "32" "33" "34" "35" "36" "37" "38" "39"
636 "40" "41" "42" "43" "44" "45" "46" "47" "48" "49"
637 "50" "51" "52" "53" "54" "55" "56" "57" "58" "59"
638 "60" "61" "62" "63" "64" "65" "66" "67" "68" "69"
639 "70" "71" "72" "73" "74" "75" "76" "77" "78" "79"
640 "80" "81" "82" "83" "84" "85" "86" "87" "88" "89"
641 "90" "91" "92" "93" "94" "95" "96" "97" "98" "99";
644 auto *p = tb2digits + x * 2;
652 auto it = colorCache.find(rgb);
653 if (it == colorCache.end()) {
654 const auto lab = rgbToOklab(rgb);
656 for (Lab
const &xtermLab : xterm240_Oklabs) {
657 auto dist2 = calculate_CIEDE2000(lab, xtermLab);
660 idx = &xtermLab - xterm240_Oklabs;
665 colorCache.insert(rgb, idx);
676 appendUInt8(qRed(rgb));
678 appendUInt8(qGreen(rgb));
680 appendUInt8(qBlue(rgb));
688 Q_ASSERT(m_data[m_size - 1] ==
';');
689 m_data[m_size - 1] =
'm';
706 int remaining() const noexcept
715 for (; n > fill.
size(); n -= fill.
size()) {
725 int graphLineLength = 0;
726 int labelLineLength = 0;
727 int nextLabelOffset = 0;
729 template<
class String>
730 void pushLabel(
int offset, String
const &s,
int numberDisplayableChar)
732 Q_ASSERT(offset >= labelLineLength);
733 const int n = offset - labelLineLength;
734 labelLineLength += numberDisplayableChar + n;
735 fillLine(labelLine, n);
737 nextLabelOffset = labelLineLength;
740 template<
class String>
741 void pushGraph(
int offset, String
const &s,
int numberDisplayableChar)
743 Q_ASSERT(offset >= graphLineLength);
744 const int n = offset - graphLineLength;
745 graphLineLength += numberDisplayableChar + n;
746 fillLine(graphLine, n);
747 const int ps1 = graphLine.
size();
749 if (offset >= labelLineLength) {
750 const int n2 = offset - labelLineLength;
751 labelLineLength += n2 + 1;
752 fillLine(labelLine, n2);
758 static void fillLine(
QString &s,
int n)
772 GraphLine &lineAtOffset(std::vector<GraphLine> &graphLines,
int offset)
774 const auto last = graphLines.end();
775 auto p = std::find_if(graphLines.begin(), last, [=](GraphLine
const &line) {
776 return line.nextLabelOffset < offset;
779 graphLines.emplace_back();
780 return graphLines.back();
796 using TraceOption = KSyntaxHighlighting::AnsiHighlighter::TraceOption;
802 m_contextCapture.setDefinition(def);
805 for (
const auto &definition : definitions) {
807 for (
const auto &context : defData->contexts) {
808 m_defDataBycontexts.insert(&context, defData);
818 TraceOptions traceOptions)
820 initRegionStyles(ansiStyles);
822 m_hasFormatTrace = traceOptions.testFlag(TraceOption::Format);
823 m_hasRegionTrace = traceOptions.testFlag(TraceOption::Region);
824 m_hasStackSizeTrace = traceOptions.testFlag(TraceOption::StackSize);
825 m_hasContextTrace = traceOptions.testFlag(TraceOption::Context);
826 const bool hasFormatOrContextTrace = m_hasFormatTrace || m_hasContextTrace || m_hasStackSizeTrace;
828 const bool hasSeparator = hasFormatOrContextTrace && m_hasRegionTrace;
829 const QString resetBgColor = (editorBackground.
isEmpty() ? QStringLiteral(
"\x1b[0m") : editorBackground);
831 bool firstLine =
true;
835 auto oldState = state;
836 state = highlightLine(currentLine, state);
840 out << QStringLiteral(
"\x1b[0m────────────────────────────────────────────────────\x1b[K\n");
845 if (!m_regions.empty()) {
846 printRegions(out, infoStyle, currentLine.
size());
850 for (
const auto &fragment : m_highlightedFragments) {
851 auto const &ansiStyle = ansiStyles[fragment.formatId];
852 out << ansiStyle.first <<
QStringView(currentLine).
mid(fragment.offset, fragment.length) << ansiStyle.second;
855 out << QStringLiteral(
"\x1b[K\n");
857 if (hasFormatOrContextTrace && !m_highlightedFragments.empty()) {
858 if (m_hasContextTrace || m_hasStackSizeTrace) {
859 appendContextNames(oldState, currentLine);
862 printFormats(out, infoStyle, ansiStyles);
866 m_highlightedFragments.
clear();
872 m_highlightedFragments.push_back({m_hasFormatTrace ? format.
name() :
QString(), offset, length, format.
id()});
875 void applyFolding(
int offset,
int ,
FoldingRegion region)
override
877 if (!m_hasRegionTrace) {
881 const auto id = region.
id();
884 m_regions.push_back(Region{m_regionDepth, offset, -1, id, Region::State::Open});
886 if (m_regions.size() >= 2) {
887 auto &previousRegion = m_regions[m_regions.size() - 2];
888 if (previousRegion.state == Region::State::Close && previousRegion.offset == offset) {
889 std::swap(previousRegion, m_regions.back());
890 if (previousRegion.bindIndex != -1) {
891 m_regions[previousRegion.bindIndex].bindIndex = m_regions.size() - 1;
898 auto it = m_regions.rbegin();
899 auto eit = m_regions.rend();
900 for (
int depth = 0; it != eit; ++it) {
901 if (it->regionId ==
id && it->bindIndex < 0) {
902 if (it->state == Region::State::Close) {
904 }
else if (--depth < 0) {
911 it->bindIndex = int(m_regions.size());
912 int bindIndex = int(&*it - m_regions.data());
913 m_regions.push_back(Region{it->depth, offset, bindIndex, id, Region::State::Close});
915 m_regions.push_back(Region{-1, offset, -1, id, Region::State::Close});
918 m_regionDepth = std::max(m_regionDepth - 1, 0);
930 m_regionStyles.resize(ansiStyles.size());
931 for (std::size_t i = 0; i < m_regionStyles.size(); ++i) {
932 m_regionStyles[i] = ansiStyles[i].first;
935 std::sort(m_regionStyles.begin(), m_regionStyles.end());
936 m_regionStyles.erase(std::unique(m_regionStyles.begin(), m_regionStyles.end()), m_regionStyles.end());
944 auto newState = state;
945 for (
auto &fragment : m_highlightedFragments) {
948 m_contextCapture.offsetNext = 0;
949 m_contextCapture.lengthNext = 0;
951 const auto lineFragment = currentLine.
mid(0, fragment.offset + fragment.length + 1);
952 newState = m_contextCapture.highlightLine(lineFragment, state);
957 if (m_contextCapture.offset != fragment.offset && m_contextCapture.length != fragment.length) {
960 fragment.name.
insert(0, contextName);
968 QString extractContextName(StateData *stateData)
const
972 if (m_hasStackSizeTrace) {
976 if (m_hasContextTrace) {
978 if (stateData->isEmpty()) {
979 return label + QStringLiteral(
"[???]");
982 const auto context = stateData->topContext();
983 const auto defDataIt = m_defDataBycontexts.find(context);
994 m_formatGraph.
clear();
995 for (
auto const &fragment : m_highlightedFragments) {
996 GraphLine &line = lineAtOffset(m_formatGraph, fragment.offset);
997 auto const &style = ansiStyles[fragment.formatId].first;
998 line.pushLabel(fragment.offset, style % nameStyle % fragment.name % regionStyle, fragment.name.size());
1000 for (GraphLine *pline = m_formatGraph.data(); pline <= &line; ++pline) {
1001 pline->pushGraph(fragment.offset, style % graphSymbol % regionStyle, 1);
1007 auto first = m_formatGraph.begin();
1008 auto last = m_formatGraph.end();
1010 for (; first != last; ++first) {
1011 out << first->graphLine <<
"\x1b[K\n" << first->labelLine <<
"\x1b[K\n";
1013 out << first->graphLine <<
"\x1b[K\n" << first->labelLine <<
"\x1b[K\x1b[0m\n";
1018 const QString continuationLine = QStringLiteral(
1019 "------------------------------"
1020 "------------------------------"
1021 "------------------------------");
1023 bool hasContinuation =
false;
1025 m_regionGraph.clear();
1030 for (Region ®ion : m_regions) {
1031 if (region.state == Region::State::Continuation) {
1032 hasContinuation =
true;
1036 auto pushGraphs = [&](
int offset,
const GraphLine *endline,
QStringView style) {
1037 for (GraphLine *pline = m_regionGraph.data(); pline <= endline; ++pline) {
1039 if (pline->graphLineLength <= offset) {
1040 pline->pushGraph(offset, style % graphSymbol % regionStyle, 1);
1050 int offsetLabel = region.offset;
1052 numStr.
setNum(region.regionId);
1054 if (region.state == Region::State::Open) {
1056 if (region.bindIndex == -1) {
1057 rpad = lineLength - region.offset - numStr.
size();
1059 rpad = m_regions[region.bindIndex].offset - region.offset - 2;
1063 }
else if (region.bindIndex == -1) {
1066 }
else if (m_regions[region.bindIndex].state == Region::State::Open) {
1067 const auto &openRegion = m_regions[region.bindIndex];
1069 const GraphLine &line = m_regionGraph[openRegion.offset];
1070 const auto &style = m_regionStyles[openRegion.depth % m_regionStyles.size()];
1071 pushGraphs(region.offset, &line, style);
1075 lpad = region.offset - numStr.
size();
1083 fillString(label, lpad, continuationLine);
1085 fillString(label, rpad, continuationLine);
1087 GraphLine &line = lineAtOffset(m_regionGraph, offsetLabel);
1088 const auto &style = m_regionStyles[region.depth % m_regionStyles.size()];
1089 line.pushLabel(offsetLabel, style % nameStyle % openS % label % closeS % regionStyle,
label.
size() + openS.size() + closeS.size());
1090 pushGraphs(region.offset, &line, style);
1093 if (region.state == Region::State::Open && region.bindIndex != -1) {
1094 region.offset = &line - m_regionGraph.data();
1101 if (hasContinuation) {
1103 fillString(label, lineLength ? lineLength : 5, continuationLine);
1104 for (
const auto ®ion : m_regions) {
1105 if (region.state == Region::State::Continuation && region.bindIndex == -1) {
1106 const auto &style = m_regionStyles[region.depth % m_regionStyles.size()];
1107 out << style << nameStyle <<
label << regionStyle <<
"\x1b[K\n";
1113 if (!m_regionGraph.empty()) {
1114 auto first = m_regionGraph.
rbegin();
1115 auto last = m_regionGraph.rend();
1117 for (; first != last; ++first) {
1118 out << first->labelLine <<
"\x1b[K\n" << first->graphLine <<
"\x1b[K\n";
1120 out << first->labelLine <<
"\x1b[K\n" << first->graphLine <<
"\x1b[K\x1b[0m\n";
1124 m_regions.erase(std::remove_if(m_regions.begin(),
1126 [](Region
const ®ion) {
1127 return region.bindIndex != -1 || region.state == Region::State::Close;
1131 for (
auto ®ion : m_regions) {
1133 region.state = Region::State::Continuation;
1137 struct HighlightFragment {
1152 offset = offsetNext;
1153 length = lengthNext;
1154 offsetNext = offset;
1155 lengthNext = length;
1162 enum class State : int8_t {
1175 bool m_hasFormatTrace;
1176 bool m_hasRegionTrace;
1177 bool m_hasStackSizeTrace;
1178 bool m_hasContextTrace;
1180 std::vector<HighlightFragment> m_highlightedFragments;
1181 std::vector<GraphLine> m_formatGraph;
1182 ContextCaptureHighlighter m_contextCapture;
1184 int m_regionDepth = 0;
1185 std::vector<Region> m_regions;
1186 std::vector<GraphLine> m_regionGraph;
1187 std::vector<QStringView> m_regionStyles;
1193 class KSyntaxHighlighting::AnsiHighlighterPrivate
1200 std::vector<QPair<QString, QString>> ansiStyles;
1203 AnsiHighlighter::AnsiHighlighter()
1204 : d(new AnsiHighlighterPrivate())
1208 AnsiHighlighter::~AnsiHighlighter() =
default;
1210 void AnsiHighlighter::setOutputFile(
const QString &fileName)
1212 if (d->file.isOpen()) {
1215 d->file.setFileName(fileName);
1217 qCWarning(
Log) <<
"Failed to open output file" << fileName <<
":" << d->file.errorString();
1220 d->out.setDevice(&d->file);
1221 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1222 d->out.setCodec(
"UTF-8");
1226 void AnsiHighlighter::setOutputFile(FILE *fileHandle)
1229 d->out.setDevice(&d->file);
1230 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1231 d->out.setCodec(
"UTF-8");
1235 void AnsiHighlighter::highlightFile(
const QString &fileName, AnsiFormat format,
bool useEditorBackground, TraceOptions traceOptions)
1240 qCWarning(
Log) <<
"Failed to open input file" << fileName <<
":" << f.errorString();
1244 highlightData(&f, format, useEditorBackground, traceOptions);
1247 void AnsiHighlighter::highlightData(
QIODevice *dev, AnsiFormat format,
bool useEditorBackground, TraceOptions traceOptions)
1249 if (!d->out.device()) {
1250 qCWarning(
Log) <<
"No output stream defined!";
1254 const auto is256Colors = (format == AnsiFormat::XTerm256Color);
1255 const auto theme = this->theme();
1256 const auto definition = this->definition();
1258 auto definitions = definition.includedDefinitions();
1259 definitions.append(definition);
1263 AnsiBuffer foregroundColorBuffer;
1264 AnsiBuffer backgroundColorBuffer;
1270 if (useEditorBackground) {
1271 const QRgb foregroundColor = theme.textColor(
Theme::Normal);
1273 foregroundColorBuffer.appendForeground(foregroundColor, is256Colors, colorCache);
1275 backgroundColorBuffer.appendBackground(backgroundColor, is256Colors, colorCache);
1276 foregroundDefaultColor = foregroundColorBuffer.latin1();
1277 backgroundDefaultColor = backgroundColorBuffer.latin1().mid(2);
1281 if (d->ansiStyles.empty()) {
1282 d->ansiStyles.resize(32);
1284 d->ansiStyles[0].first.clear();
1285 d->ansiStyles[0].second.clear();
1289 for (
auto &&definition : std::as_const(definitions)) {
1291 const auto id = format.id();
1292 if (
id >= d->ansiStyles.size()) {
1294 d->ansiStyles.resize(
id * 2);
1301 const bool hasFg = format.hasTextColor(theme);
1302 const bool hasBg = format.hasBackgroundColor(theme);
1303 const bool hasBold = format.isBold(theme);
1304 const bool hasItalic = format.isItalic(theme);
1305 const bool hasUnderline = format.isUnderline(theme);
1306 const bool hasStrikeThrough = format.isStrikeThrough(theme);
1309 buffer.appendForeground(format.textColor(theme).rgb(), is256Colors, colorCache);
1311 buffer.append(foregroundDefaultColor);
1314 buffer.appendBackground(format.backgroundColor(theme).rgb(), is256Colors, colorCache);
1325 if (hasStrikeThrough) {
1330 if (buffer.latin1().size() > 2) {
1331 buffer.setFinalStyle();
1332 d->ansiStyles[id].first = buffer.latin1();
1334 if (useEditorBackground) {
1336 const bool hasEffect = hasBold || hasItalic || hasUnderline || hasStrikeThrough;
1339 buffer.append(backgroundDefaultColor);
1340 buffer.setFinalStyle();
1341 d->ansiStyles[id].second = buffer.latin1();
1342 }
else if (hasEffect) {
1353 if (hasStrikeThrough) {
1356 buffer.setFinalStyle();
1357 d->ansiStyles[id].second = buffer.latin1();
1360 d->ansiStyles[id].second = QStringLiteral(
"\x1b[0m");
1366 if (useEditorBackground) {
1367 backgroundColorBuffer.setFinalStyle();
1368 backgroundDefaultColor = backgroundColorBuffer.latin1();
1369 d->out << backgroundDefaultColor;
1373 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
1377 if (!traceOptions) {
1381 d->currentLine = currentLine;
1382 state = highlightLine(d->currentLine, state);
1384 if (useEditorBackground) {
1385 d->out << QStringLiteral(
"\x1b[K\n");
1394 buffer.setFinalStyle();
1395 DebugSyntaxHighlighter debugHighlighter;
1396 debugHighlighter.setDefinition(definition);
1397 debugHighlighter.highlightData(in, d->out, buffer.latin1(), backgroundDefaultColor, d->ansiStyles, traceOptions);
1400 if (useEditorBackground) {
1401 d->out << QStringLiteral(
"\x1b[0m");
1404 d->out.setDevice(
nullptr);
1406 d->ansiStyles.clear();
1409 void AnsiHighlighter::applyFormat(
int offset,
int length,
const Format &format)
1411 auto const &ansiStyle = d->ansiStyles[format.
id()];
1412 d->out << ansiStyle.first << d->currentLine.mid(offset, length) << ansiStyle.second;