7#include "ansihighlighter.h"
8#include "abstracthighlighter_p.h"
10#include "definition.h"
11#include "definition_p.h"
13#include "ksyntaxhighlighting_logging.h"
108 constexpr Lab xterm240_Oklabs[] {
127 {0x0p+0, 0x0p+0, 0x0p+0},
128 {0x1.5f181b2779cap+4, -0x1.930f78e22f09ap+0, -0x1.e41dbddfca08ap+3},
129 {0x1.c2d3be821f882p+4, -0x1.02c70dd8af008p+1, -0x1.36d1623919ffp+4},
130 {0x1.10a39beeb2926p+5, -0x1.38fe38b7dab01p+1, -0x1.77efa95d520b4p+4},
131 {0x1.3de43fe8d92efp+5, -0x1.6cf188320fff2p+1, -0x1.b655790a27192p+4},
132 {0x1.69950098864afp+5, -0x1.9f19c42a8c674p+1, -0x1.f293e325bec2ep+4},
133 {0x1.50853f46a9f9ep+5, -0x1.6b6901a80404fp+3, 0x1.16bdec11e60d8p+3},
134 {0x1.5fa625f2c3fbcp+5, -0x1.d0691ed5aa7ap+2, -0x1.eac16e8cb9241p+0},
135 {0x1.6f4222fc3f0dbp+5, -0x1.61b0e7ffa5e8ap+2, -0x1.05e8906ee23d7p+3},
136 {0x1.83e99e6187f46p+5, -0x1.1a61c98b895p+2, -0x1.c3da094bbcf2fp+3},
137 {0x1.9ca47689a503dp+5, -0x1.e9259e3439104p+1, -0x1.396812c634de3p+4},
138 {0x1.b872b55db6144p+5, -0x1.ccd50a2fd6662p+1, -0x1.89dec898ec996p+4},
139 {0x1.b01d15d276ef1p+5, -0x1.d2a4448f6ccacp+3, 0x1.65ec167dcb488p+3},
140 {0x1.b9760adf5c444p+5, -0x1.6a3760af4b6c4p+3, 0x1.a26bb322495e2p+1},
141 {0x1.c38a22a31944p+5, -0x1.2a2a93c4b741p+3, -0x1.3b14a376ffbecp+1},
142 {0x1.d185a36cfcd6ep+5, -0x1.e760f29e8fcb4p+2, -0x1.0bf936f2a6743p+3},
143 {0x1.e321d754f2b44p+5, -0x1.95a749a95debp+2, -0x1.c3928e31b9cf8p+3},
144 {0x1.f7eb8d9ad84b9p+5, -0x1.5e28b7cc193ddp+2, -0x1.38bda7259441ep+4},
145 {0x1.0552717cdb82p+6, -0x1.1a33f75f67b0fp+4, 0x1.b0e8bd24c3fdep+3},
146 {0x1.08898a5b7805dp+6, -0x1.e29bd3071d97ap+3, 0x1.e0b5994e0238ep+2},
147 {0x1.0c10ad1b87866p+6, -0x1.a54f2215371a5p+3, 0x1.45758e5457898p+1},
148 {0x1.1111e924447e9p+6, -0x1.68a24e1d5efe1p+3, -0x1.7d178a838ea32p+1},
149 {0x1.178bb94d30a5cp+6, -0x1.335d7d75dd017p+3, -0x1.13f78c003ba13p+3},
150 {0x1.1f6aa49fcff2p+6, -0x1.0830d167759a4p+3, -0x1.c578e33f21d88p+3},
151 {0x1.30b236b57ac86p+6, -0x1.490afbe3d8e11p+4, 0x1.f8c35fbb689dap+3},
152 {0x1.331144aae0ad4p+6, -0x1.289bac3eeb83p+4, 0x1.626ea3a63748p+3},
153 {0x1.35b09f5c62a7ap+6, -0x1.0d33e3db59803p+4, 0x1.b66836d6f7ff6p+2},
154 {0x1.3973d5b39baa4p+6, -0x1.de87e61f0c86ap+3, 0x1.de8cf8346969cp+0},
155 {0x1.3e64dbeab2c38p+6, -0x1.a47dea5d85dbbp+3, -0x1.bc586cdcba45p+1},
156 {0x1.44815d7f73a41p+6, -0x1.706c35b4850ecp+3, -0x1.1d13e731dfc5bp+3},
157 {0x1.5a92b1ff8af32p+6, -0x1.76441609cfb3ap+4, 0x1.1f1186319beaap+4},
158 {0x1.5c6885a0ab4cap+6, -0x1.5c0bf4148d03dp+4, 0x1.c5b4a75d0a01ep+3},
159 {0x1.5e72281eb918cp+6, -0x1.4422b7d2ad44bp+4, 0x1.5305a49da3492p+3},
160 {0x1.61631d5752788p+6, -0x1.282b31110d79dp+4, 0x1.8b1a60b561753p+2},
161 {0x1.65488920f4795p+6, -0x1.0b1a0cfacacfbp+4, 0x1.3d72a3bb176fp+0},
162 {0x1.6a27499e4d3d6p+6, -0x1.de4892c062f8p+3, -0x1.f96a59bc9de4cp+1},
163 {0x1.e7d1475ebe201p+4, 0x1.5d4f5ebb6cf8ep+3, 0x1.86e150bac0e61p+2},
164 {0x1.10883ee613f6bp+5, 0x1.aa957aceb4328p+3, -0x1.06e4a6bcf37ep+3},
165 {0x1.2a507c82ee1e7p+5, 0x1.880d450b132c9p+3, -0x1.c81b5ba73664ap+3},
166 {0x1.4902475f20191p+5, 0x1.4f4dfeda4e013p+3, -0x1.38d6c960a7255p+4},
167 {0x1.6aa42ff68fb65p+5, 0x1.1116140836dp+3, -0x1.84f2dbb4bf7b2p+4},
168 {0x1.8def7d6adc3d5p+5, 0x1.ab6406f65a5b9p+2, -0x1.caee116cbc66ep+4},
169 {0x1.77f724f99d0c9p+5, -0x1.bb9ee0e906bf2p+1, 0x1.345d15707c9e4p+3},
170 {0x1.8465d178eda3bp+5, -0x1.021519c6d64p-11, -0x1.11ebea130b3p-8},
171 {0x1.917d476fba08dp+5, 0x1.84e9b4b9a4816p+0, -0x1.89910d2df7414p+2},
172 {0x1.a32d016052029p+5, 0x1.352fbc1045df3p+1, -0x1.847eed4ab1e03p+3},
173 {0x1.b8cfd7baeb72ap+5, 0x1.5d6575ced028ep+1, -0x1.1bff70d82f589p+4},
174 {0x1.d1a20bfd91dbap+5, 0x1.4de285fe39a4dp+1, -0x1.6f381fca63bcep+4},
175 {0x1.c99e943a2d79fp+5, -0x1.219ec15c5de22p+3, 0x1.78f2db7cd8205p+3},
176 {0x1.d20af5c832c06p+5, -0x1.86c31353f2968p+2, 0x1.15f4d958ffb6ep+2},
177 {0x1.db2d2b76b7db4p+5, -0x1.107aa185fa178p+2, -0x1.3a545f6bb32fep+0},
178 {0x1.e7ef429658179p+5, -0x1.58a57459e2113p+1, -0x1.c50012145074dp+2},
179 {0x1.f821bad822a9ep+5, -0x1.8ea06e2a9e1f6p+0, -0x1.9a5cf82ebb612p+3},
180 {0x1.05b4f2f9696abp+6, -0x1.b3645fe7f9294p-1, -0x1.24f471b4e8b62p+4},
181 {0x1.0e4a1f1b1ddcep+6, -0x1.b32bbdf7204c1p+3, 0x1.be3e8e0b04a1fp+3},
182 {0x1.114fcf04f35b3p+6, -0x1.6696d5115c7e4p+3, 0x1.058704ea2708p+3},
183 {0x1.14a2558b5b6c7p+6, -0x1.2c7e211429d81p+3, 0x1.a9f809f8ee4dfp+1},
184 {0x1.195c00cf22a51p+6, -0x1.e58de99c40fb6p+2, -0x1.0e4f6479339a5p+1},
185 {0x1.1f7e4eea78cb7p+6, -0x1.809e6530a25d5p+2, -0x1.ee2cfac349d5ep+2},
186 {0x1.26f9f5da0f33bp+6, -0x1.2ffe0404fe1e4p+2, -0x1.a87af760f19c2p+3},
187 {0x1.37635555b270cp+6, -0x1.17deced6d377ep+4, 0x1.0159387931185p+4},
188 {0x1.39aa8b444a1c7p+6, -0x1.f1b4258b74e35p+3, 0x1.70a1d9ed49333p+3},
189 {0x1.3c30003dc4bdap+6, -0x1.bcf061cd62971p+3, 0x1.d845b8f464806p+2},
190 {0x1.3fcf0a7e4fdb8p+6, -0x1.8316f8fb04f1cp+3, 0x1.3be7d797ab219p+1},
191 {0x1.4492530767fa4p+6, -0x1.4af657f86bc35p+3, -0x1.69ccecfbead6p+1},
192 {0x1.4a78e7a0304fbp+6, -0x1.18be182ded159p+3, -0x1.07ac09ccdfff4p+3},
193 {0x1.5fc9ac083946p+6, -0x1.4f840d59cd9aep+4, 0x1.22ef620ec7775p+4},
194 {0x1.6192b2ae205fp+6, -0x1.361d4509435d5p+4, 0x1.cfe893676e62ep+3},
195 {0x1.638e487d443e1p+6, -0x1.1edcf418396fcp+4, 0x1.5f105a3f7b33p+3},
196 {0x1.666b5164f3799p+6, -0x1.03988ade0159ep+4, 0x1.a6a2e5baac692p+2},
197 {0x1.6a3706fa48d42p+6, -0x1.ce6b98f424c54p+3, 0x1.b67fa4fafc2e8p+0},
198 {0x1.6ef6b7860b53fp+6, -0x1.97ce09961f218p+3, -0x1.b926ed0fbe897p+1},
199 {0x1.3931bb83cb32dp+5, 0x1.c0894426a198dp+3, 0x1.f5ea328bf4058p+2},
200 {0x1.4b9e77eb58ebfp+5, 0x1.108cfd41d7919p+4, -0x1.0eaf04c8d3b35p+2},
201 {0x1.5df2d7bacd40ap+5, 0x1.11e15f9b225acp+4, -0x1.51924b9c514f3p+3},
202 {0x1.756bc7d79519bp+5, 0x1.03a63c750b36bp+4, -0x1.052fc194cf52p+4},
203 {0x1.90b3e1d276c5dp+5, 0x1.d79fd75fb3811p+3, -0x1.58e6a7a1da1fcp+4},
204 {0x1.aea5654d2d631p+5, 0x1.9f14550c88c57p+3, -0x1.a57e86563dbcap+4},
205 {0x1.9b6948efcb1e8p+5, 0x1.dddaa142e7b3ap+0, 0x1.4f83ba256abcfp+3},
206 {0x1.a5f9bfdb796c8p+5, 0x1.3de3647070a5bp+2, 0x1.b416b1e2a3817p+0},
207 {0x1.b1407c7a80b46p+5, 0x1.9d8674f672f17p+2, -0x1.112d7835e0443p+2},
208 {0x1.c0b6552db89b1p+5, 0x1.d8c2a5262b398p+2, -0x1.480f10f6d0b5fp+3},
209 {0x1.d3edc2b5ca1f7p+5, 0x1.edbf49a0778e4p+2, -0x1.fe5ca96caae15p+3},
210 {0x1.ea519f7b4bf8cp+5, 0x1.e35c8bfe38bf9p+2, -0x1.5483ed4b7e5ebp+4},
211 {0x1.e2c36ca30962cp+5, -0x1.1cd1878e91233p+2, 0x1.8bf558e4fbde3p+3},
212 {0x1.ea67769abd5c1p+5, -0x1.c053e5b6c3b66p+0, 0x1.59302161a2865p+2},
213 {0x1.f2ba2dd022991p+5, -0x1.4b64e809e68p-11, -0x1.5fbb8b338b8p-8},
214 {0x1.fe6b844bbf20fp+5, 0x1.8040f07e39554p+0, -0x1.7196ffd7de002p+2},
215 {0x1.06aeef460087dp+6, 0x1.4afa79e390244p+1, -0x1.705a7c8493135p+3},
216 {0x1.0fa5554a5c955p+6, 0x1.9dea7336ee828p+1, -0x1.1089bb9ca046ep+4},
217 {0x1.178e9051b853ep+6, -0x1.3b3b8e6c52f1cp+3, 0x1.cc268b9a4e157p+3},
218 {0x1.1a65db5c4c0d1p+6, -0x1.e697a167b2b86p+2, 0x1.1b4d0d1ca381dp+3},
219 {0x1.1d86bd983524p+6, -0x1.77ccb1bcef226p+2, 0x1.08e1384d16e75p+2},
220 {0x1.21fc7ad985402p+6, -0x1.08e3f099fb00fp+2, -0x1.363e6fbac8902p+0},
221 {0x1.27cb1d6dd9434p+6, -0x1.4f7ef424b1025p+1, -0x1.b1af4c945ce98p+2},
222 {0x1.2ee710ec206cfp+6, -0x1.6ac7f2787bda1p+0, -0x1.89e8c18db3849p+3},
223 {0x1.3e7c86695f695p+6, -0x1.ceac064fd3a97p+3, 0x1.06a67a74ff4cp+4},
224 {0x1.40ac0504d65f2p+6, -0x1.935bda5136fdbp+3, 0x1.7fa8ea5683dffp+3},
225 {0x1.4317a9d652f14p+6, -0x1.608608dcc2607p+3, 0x1.fc21edd271f8bp+2},
226 {0x1.46928cf49114ap+6, -0x1.2883a0410f74bp+3, 0x1.8d4b911a8102bp+1},
227 {0x1.4b27f53f2d1c8p+6, -0x1.e40f8922e26b2p+2, -0x1.11ca0bf0acee9p+1},
228 {0x1.50d83b6f7788bp+6, -0x1.82a0417f98419p+2, -0x1.e18432a6676edp+2},
229 {0x1.6567db05a012cp+6, -0x1.27d55f8b64f16p+4, 0x1.271e9400a42e4p+4},
230 {0x1.6723b3feab73ap+6, -0x1.0f412c5a09d1ap+4, 0x1.dae43f7f7eb6ep+3},
231 {0x1.6910cf423acf1p+6, -0x1.f152d3d18c3b3p+3, 0x1.6c04c44876eb2p+3},
232 {0x1.6bd948eca017fp+6, -0x1.bc29d2c53f57ap+3, 0x1.c44a28d107a62p+2},
233 {0x1.6f8a69cf10b1p+6, -0x1.84b224c6d040cp+3, 0x1.1c910c629db67p+1},
234 {0x1.7429ebc4e406dp+6, -0x1.4f4a0b735c531p+3, -0x1.73a39097eadefp+1},
235 {0x1.7acf7694f8c6p+5, 0x1.0f40ef4bed7e8p+4, 0x1.2f88d81b23f2ep+3},
236 {0x1.87b52573912c8p+5, 0x1.3e9cadbae2c71p+4, -0x1.21c127942ffc2p-1},
237 {0x1.95308092c646cp+5, 0x1.4bd8ec93cbe28p+4, -0x1.b1ad2fc6cd5ccp+2},
238 {0x1.a743d71712a69p+5, 0x1.4b428f09e4704p+4, -0x1.984b766ca527bp+3},
239 {0x1.bd35da1ada54ap+5, 0x1.3ee7b023f1a36p+4, -0x1.252f399063a3p+4},
240 {0x1.d638af110e2bfp+5, 0x1.2a6369728426p+4, -0x1.777a4238ecc9cp+4},
241 {0x1.c5db1e678f93bp+5, 0x1.be23ef0d11b9fp+2, 0x1.706e52e6555aep+3},
242 {0x1.ceab15b1e5e2cp+5, 0x1.376364145a451p+3, 0x1.d7fd2a954eedcp+1},
243 {0x1.d8302a174d63dp+5, 0x1.67a05469bf7c1p+3, -0x1.0236bbe6ffddap+1},
244 {0x1.e56c6a282c6fep+5, 0x1.8915eed9a5994p+3, -0x1.fb2d49a257381p+2},
245 {0x1.f622a3ef65e7fp+5, 0x1.98638aed6156bp+3, -0x1.b57e66e36241ap+3},
246 {0x1.04f5c4d9c25cfp+6, 0x1.9710ff57a7b7ap+3, -0x1.32004fe7bd5b5p+4},
247 {0x1.018127d59826cp+6, 0x1.1e619caaa3a8fp-1, 0x1.a49bd0215a96dp+3},
248 {0x1.04e57659b4cf6p+6, 0x1.8024718692a3cp+1, 0x1.addd1b874609p+2},
249 {0x1.089bd543a0e63p+6, 0x1.2a7652607e02cp+2, 0x1.8d85013677bap+0},
250 {0x1.0ddb424d04fadp+6, 0x1.889c9b8223651p+2, -0x1.05aa1bc86a9d4p+2},
251 {0x1.149da8fbd8909p+6, 0x1.ce4542c130c31p+2, -0x1.3934aac98d184p+3},
252 {0x1.1cca409e32c6dp+6, 0x1.f855300b25ba5p+2, -0x1.eac45e49f86bap+3},
253 {0x1.23f3e081f0e6fp+6, -0x1.587d5d644e818p+2, 0x1.deea03a7e9e2p+3},
254 {0x1.26935d2d5bb58p+6, -0x1.a6ab45ebb79ddp+1, 0x1.38265c4c6d156p+3},
255 {0x1.29783d4927cb6p+6, -0x1.aa081e388f0b6p+0, 0x1.4de28afb99798p+2},
256 {0x1.2d9b5abdd0df6p+6, -0x1.90d2c34c4c8p-11, -0x1.a96c3913736p-8},
257 {0x1.3303704c60227p+6, 0x1.7842d686da2p+0, -0x1.6001098473213p+2},
258 {0x1.39a911d79bf6cp+6, 0x1.51ae39272f6fp+1, -0x1.604eff9e13224p+3},
259 {0x1.483b66bb75f41p+6, -0x1.53e4a65e5bd0ep+3, 0x1.0dfa4f4feec89p+4},
260 {0x1.4a4cab5bdb777p+6, -0x1.1bf0c7950b46ap+3, 0x1.9433415e2e559p+3},
261 {0x1.4c9756fc325a6p+6, -0x1.d6e499fe26166p+2, 0x1.1693b52228314p+3},
262 {0x1.4fe3e8502420ap+6, -0x1.6b29463056a7ep+2, 0x1.fcea504279e1bp+1},
263 {0x1.543e4f84c51c9p+6, -0x1.01c201c3fcfbep+2, -0x1.311b349896504p+0},
264 {0x1.59a86b698fe17p+6, -0x1.4697ac30fd276p+1, -0x1.a218614573a54p+2},
265 {0x1.6d3f94c53849cp+6, -0x1.e750c3b6abf94p+3, 0x1.2cfd8e3a3298cp+4},
266 {0x1.6ee9ffc7c561bp+6, -0x1.b847cb4caca9ap+3, 0x1.ea32a397a5ea3p+3},
267 {0x1.70c3ef56a2364p+6, -0x1.8cc812a446223p+3, 0x1.7e0dc7e1aa4eep+3},
268 {0x1.737125604c02dp+6, -0x1.5959ff3792892p+3, 0x1.ed9e6884d6db8p+2},
269 {0x1.76fef3ccb11e4p+6, -0x1.2379a952d29eap+3, 0x1.77d044e094287p+1},
270 {0x1.7b739668b58adp+6, -0x1.def62d62ac5d3p+2, -0x1.1242c0559f9b9p+1},
271 {0x1.b9af6705b3e1ap+5, 0x1.3c46b4e4aa724p+4, 0x1.61ea416f62116p+3},
272 {0x1.c34652a386648p+5, 0x1.673d5400dac6ap+4, 0x1.575529f864e4ap+1},
273 {0x1.cd90a5a7155efp+5, 0x1.7aac661c86347p+4, -0x1.97f5d2781d1d2p+1},
274 {0x1.dbc2183aadc6dp+5, 0x1.83f34257f81ecp+4, -0x1.24c7f27451716p+3},
275 {0x1.ed84b050fd5fep+5, 0x1.823e0b9a9286fp+4, -0x1.dc10370a896a1p+3},
276 {0x1.012d3f7585d8bp+6, 0x1.772916c92c8cp+4, -0x1.444d46ad4a3f5p+4},
277 {0x1.f498a57d50c8dp+5, 0x1.72c50647a1b01p+3, 0x1.9501b7bc92a26p+3},
278 {0x1.fbec5add8799fp+5, 0x1.c10937ac1ff0cp+3, 0x1.71506b03a0cfcp+2},
279 {0x1.01f4d75996fc6p+6, 0x1.f168c838b27a5p+3, 0x1.a2871b4170f08p-2},
280 {0x1.07934868d42f1p+6, 0x1.0ba82dcee8d5fp+4, -0x1.55f50c12fdb69p+2},
281 {0x1.0ec4c024626fep+6, 0x1.16b4701bb2cep+4, -0x1.627c9a1b01177p+3},
282 {0x1.1768d8b0aa031p+6, 0x1.199f4e2e9e65fp+4, -0x1.09c1c4e924702p+4},
283 {0x1.14522a4a9a7e2p+6, 0x1.6020b0a7ecac7p+2, 0x1.c1a8f99df62d9p+3},
284 {0x1.174b930ef061ap+6, 0x1.ec83068a9839fp+2, 0x1.06f134f7cc07ep+3},
285 {0x1.1a90921a38fe7p+6, 0x1.28d89eb448a2cp+3, 0x1.ab5fe99a94265p+1},
286 {0x1.1f36b9520ad75p+6, 0x1.57ace8397fb96p+3, -0x1.0feb2da7758d4p+1},
287 {0x1.253f2b741784fp+6, 0x1.7c087d08384b1p+3, -0x1.efdb49212f992p+2},
288 {0x1.2c9a998952cf1p+6, 0x1.9366b5a4edd8ap+3, -0x1.a9848b6099745p+3},
289 {0x1.330541ae3e385p+6, -0x1.39e238ea7801p-1, 0x1.f5ec9f058d778p+3},
290 {0x1.3568ff8940412p+6, 0x1.4b2aea6a2b17bp+0, 0x1.5aadb9534e15p+3},
291 {0x1.380d495b09ffp+6, 0x1.6b2260c162acep+1, 0x1.a0b3e40fdedfp+2},
292 {0x1.3bd6db55a86abp+6, 0x1.1c0894632c07ep+2, 0x1.73acfbc73a52cp+0},
293 {0x1.40ced5740b6ecp+6, 0x1.784d8d5bd59bap+2, -0x1.f87f29ae0432ap+1},
294 {0x1.46f1d56d6a627p+6, 0x1.c2acec311d85p+2, -0x1.2d078d1d0ec93p+3},
295 {0x1.54692a261ff77p+6, -0x1.91aafde5841e2p+2, 0x1.1733b7c5acf09p+4},
296 {0x1.5657fb0185f53p+6, -0x1.292fef1c6094ap+2, 0x1.adacb9827ba1ep+3},
297 {0x1.587cf8c168362p+6, -0x1.9aa045411de21p+1, 0x1.34f47fa15abacp+3},
298 {0x1.5b946ca219efdp+6, -0x1.98465c0dc7b2ap+0, 0x1.43ded9d06d2f2p+2},
299 {0x1.5faadb5249c01p+6, -0x1.d35a0bdd6ap-11, -0x1.f008c176226p-8},
300 {0x1.64c3b31613c93p+6, 0x1.6ffd305ac700dp+0, -0x1.52580b551209ep+2},
301 {0x1.773c645e32d2dp+6, -0x1.6c001f7fba478p+3, 0x1.3482f283026fp+4},
302 {0x1.78d215b19332bp+6, -0x1.3f6c1cce8d703p+3, 0x1.fda06ae8dbf53p+3},
303 {0x1.7a9531dc8addap+6, -0x1.15dd42d16c7e4p+3, 0x1.94e8098e96fccp+3},
304 {0x1.7d21e2193d5bcp+6, -0x1.c8c718caa9f8ep+2, 0x1.1105d830d79dp+3},
305 {0x1.808572bc9578ap+6, -0x1.607bf910c57eep+2, 0x1.ebe2b93545493p+1},
306 {0x1.84c6a7914070fp+6, -0x1.f6c2ba3dfc25ap+1, -0x1.2beab2de5e36ep+0},
307 {0x1.f663baac570efp+5, 0x1.67be9f690c994p+4, 0x1.928e76c3750aep+3},
308 {0x1.fdd78bfa0c16bp+5, 0x1.8da11d29326eap+4, 0x1.63128e5e5d16fp+2},
309 {0x1.02fa8211ca545p+6, 0x1.a3a4c44447321p+4, 0x1.04d0a318f0ebp-3},
310 {0x1.08ace6a6b1bbcp+6, 0x1.b32f97fdc6c72p+4, -0x1.69ea7f28a916ap+2},
311 {0x1.0ff3cb8943e81p+6, 0x1.b9bf03db71bbbp+4, -0x1.6cb54bc7e9c6p+3},
312 {0x1.18ac5c68852cdp+6, 0x1.b753a9bd5dbeep+4, -0x1.0ebf0dff35bfbp+4},
313 {0x1.12e57190e4906p+6, 0x1.f7243f8456bc9p+3, 0x1.bbbf019d6f15fp+3},
314 {0x1.15f567ae01685p+6, 0x1.1e238872ebfe1p+4, 0x1.f5db81101607bp+2},
315 {0x1.1952176f81196p+6, 0x1.35eb43e1b3454p+4, 0x1.6f044118da651p+1},
316 {0x1.1e17b3f5be1e9p+6, 0x1.4aa233635e996p+4, -0x1.54536023af51fp+1},
317 {0x1.244540fde90c8p+6, 0x1.590428a4cd957p+4, -0x1.09fd595c81312p+3},
318 {0x1.2bc8d270727cdp+6, 0x1.6002d76c0fae1p+4, -0x1.bbbb8dd0769e1p+3},
319 {0x1.2910051d7f4b8p+6, 0x1.4505f3d8c93bep+3, 0x1.e1f0441f64aep+3},
320 {0x1.2ba848891bba1p+6, 0x1.83d80a13be75dp+3, 0x1.39f759ee811ebp+3},
321 {0x1.2e852380cafc2p+6, 0x1.b3d439de20201p+3, 0x1.5018eb1694a48p+2},
322 {0x1.329c951f395aap+6, 0x1.e28db45c54996p+3, 0x1.689e197414bp-7},
323 {0x1.37f5013da44b7p+6, 0x1.04846845ce376p+4, -0x1.5f9623aa14c25p+2},
324 {0x1.3e86c9cea44c3p+6, 0x1.11f59319394fdp+4, -0x1.6049926fe33dap+3},
325 {0x1.443efb939f1d1p+6, 0x1.0a131d35fab88p+2, 0x1.0838884c6c35ap+4},
326 {0x1.4667729b66dbap+6, 0x1.793a281884d1p+2, 0x1.8155ad5254ba1p+3},
327 {0x1.48cb51f255527p+6, 0x1.d609d14c020d1p+2, 0x1.fd82e0735fdcep+2},
328 {0x1.4c3af36c4bb13p+6, 0x1.1c709781a9fb2p+3, 0x1.8ca66dc4e33fdp+1},
329 {0x1.50c14ed0ba88bp+6, 0x1.4a1d653379591p+3, -0x1.14ee52d3fd0e1p+1},
330 {0x1.565e87fd89a8p+6, 0x1.6fe5c4c37980fp+3, -0x1.e3e3e3d81f648p+2},
331 {0x1.62b687ada6a2dp+6, -0x1.b1a7c98c53b9bp+0, 0x1.221d2fc2be6cp+4},
332 {0x1.6480f342fedfap+6, -0x1.728e49c5a9ba8p-3, 0x1.cb44060a17de8p+3},
333 {0x1.667e081a8e931p+6, 0x1.2c204353d8acp+0, 0x1.582d07a1ac706p+3},
334 {0x1.695d03a4b4ea6p+6, 0x1.5b9dd1e5192c9p+1, 0x1.949cc8da7db3dp+2},
335 {0x1.6d2ad25b49139p+6, 0x1.10c661536b1e3p+2, 0x1.60b9aee667ea2p+0},
336 {0x1.71ec510363cccp+6, 0x1.6b2af260ca3f1p+2, -0x1.e8e3d6769ed61p+1},
337 {0x1.83323c984ee7ap+6, -0x1.c8df58716d4cbp+2, 0x1.3d9335b5d20f9p+4},
338 {0x1.84b109344c92cp+6, -0x1.750134f94569cp+2, 0x1.0a63166d3ca32p+4},
339 {0x1.865ae5967696dp+6, -0x1.260f129da839ep+2, 0x1.b00f6d0ac1f93p+3},
340 {0x1.88c3891dbffdp+6, -0x1.8e7bf5d542ea4p+1, 0x1.30323669c3d67p+3},
341 {0x1.8bf825267af8ep+6, -0x1.89d8c0f2ba1ffp+0, 0x1.3b2af0c9eed76p+2},
342 {0x1.8ffffbb77c76ap+6, -0x1.09cab717214p-10, -0x1.1a1aa7765a7p-7},
343 {0x1.ae1c063cf8075p+3, -0x1.1dcc8d6b21p-13, -0x1.2f56d49352fp-10},
344 {0x1.23869fde6955fp+4, -0x1.836d13c82dp-13, -0x1.9b340cb2926p-10},
345 {0x1.6a51d9755cb1ep+4, -0x1.e1821bf6d08p-13, -0x1.ff0f3c5806ap-10},
346 {0x1.adca073d0c9a1p+4, -0x1.1d961152df8p-12, -0x1.2f1d00745cap-9},
347 {0x1.eeb26a3638306p+4, -0x1.48b751f0a58p-12, -0x1.5ce3e1a3db8p-9},
348 {0x1.16c4868a9dbc4p+5, -0x1.7278906708p-12, -0x1.89352628678p-9},
349 {0x1.3552cb4726ed2p+5, -0x1.9b140ac6fbp-12, -0x1.b44e9f2325p-9},
350 {0x1.53242132979b2p+5, -0x1.c2b46f9c328p-12, -0x1.de5d99b6f9p-9},
351 {0x1.7051013cf5a69p+5, -0x1.e97a44c10a8p-12, -0x1.03c24d5b897p-8},
352 {0x1.8ceca3a0569fdp+5, -0x1.07bf8a7e0fcp-11, -0x1.17ef5f1c441p-8},
353 {0x1.a9067ed63306p+5, -0x1.1a6bb67a6bp-11, -0x1.2bc0e9df0a8p-8},
354 {0x1.c4ab42f91535bp+5, -0x1.2cca14a233p-11, -0x1.3f3fe0662d2p-8},
355 {0x1.dfe5855ae1528p+5, -0x1.3ee1ad40618p-11, -0x1.5273b9784a3p-8},
356 {0x1.fabe397d15c9dp+5, -0x1.50b872fc158p-11, -0x1.6562c531248p-8},
357 {0x1.0a9e8459f8d9ap+6, -0x1.62537d1958p-11, -0x1.78126ad030ep-8},
358 {0x1.17b44990f13f5p+6, -0x1.73b732a42fp-11, -0x1.8a87568ccdp-8},
359 {0x1.24a350705ddf4p+6, -0x1.84e76b1c308p-11, -0x1.9cc59c424aap-8},
360 {0x1.316e23ed9d96ap+6, -0x1.95e7879947p-11, -0x1.aed0d2216dp-8},
361 {0x1.3e1704b29c069p+6, -0x1.a6ba8679e08p-11, -0x1.c0ac258f992p-8},
362 {0x1.4a9ff4d8984e6p+6, -0x1.b76312f3808p-11, -0x1.d25a6bb27acp-8},
363 {0x1.570ac151c1615p+6, -0x1.c7e3919c138p-11, -0x1.e3de2eb684p-8},
364 {0x1.6359098c40c61p+6, -0x1.d83e2a89bbp-11, -0x1.f539b894d66p-8},
365 {0x1.6f8c45b456692p+6, -0x1.e874d1a7f5p-11, -0x1.03378df3804p-7},
366 {0x1.7ba5cbe12c3fcp+6, -0x1.f8894d9602p-11, -0x1.0bc01d99c93p-7},
379 constexpr double RGB888_to_sRGB_table[] {
380 0x0p+0, 0x1.3e45677c176f7p-12, 0x1.3e45677c176f7p-11, 0x1.dd681b3a23272p-11,
381 0x1.3e45677c176f7p-10, 0x1.8dd6c15b1d4b4p-10, 0x1.dd681b3a23272p-10, 0x1.167cba8c94818p-9,
382 0x1.3e45677c176f7p-9, 0x1.660e146b9a5d6p-9, 0x1.8dd6c15b1d4b4p-9, 0x1.b6a31b5259c99p-9,
383 0x1.e1e31d70c99ddp-9, 0x1.07c38bf8583a9p-8, 0x1.1fcc2beed6421p-8, 0x1.390ffaf95e279p-8,
384 0x1.53936cc7bc928p-8, 0x1.6f5addb50c915p-8, 0x1.8c6a94031b561p-8, 0x1.aac6c0fb97351p-8,
385 0x1.ca7381f9f602bp-8, 0x1.eb74e160978dp-8, 0x1.06e76bbda92b8p-7, 0x1.18c2a5a8a8044p-7,
386 0x1.2b4e09b3f0ae3p-7, 0x1.3e8b7b3bde965p-7, 0x1.527cd60af8b85p-7, 0x1.6723eea8d3709p-7,
387 0x1.7c8292a3db6b3p-7, 0x1.929a88d67b521p-7, 0x1.a96d91a8016bdp-7, 0x1.c0fd67499fab6p-7,
388 0x1.d94bbdefd740ep-7, 0x1.f25a44089883fp-7, 0x1.061551372c694p-6, 0x1.135f3e4c2cce2p-6,
389 0x1.210bb8642b172p-6, 0x1.2f1b8c1ae46bdp-6, 0x1.3d8f839b79c0bp-6, 0x1.4c6866b3e9fa4p-6,
390 0x1.5ba6fae794313p-6, 0x1.6b4c0380d2deep-6, 0x1.7b5841a1bf3acp-6, 0x1.8bcc74542addbp-6,
391 0x1.9ca95898dc8b5p-6, 0x1.adefa9761c02p-6, 0x1.bfa0200597bd9p-6, 0x1.d1bb7381aec1fp-6,
392 0x1.e442595227bcap-6, 0x1.f73585185e1b5p-6, 0x1.054ad45d76878p-5, 0x1.0f31ba386ff26p-5,
393 0x1.194fcb663747bp-5, 0x1.23a55e62a662ap-5, 0x1.2e32c8e148d11p-5, 0x1.38f85fd21eacfp-5,
394 0x1.43f67766310ffp-5, 0x1.4f2d6313fa8dp-5, 0x1.5a9d759ba5edp-5, 0x1.6647010b254eep-5,
395 0x1.722a56c2239eep-5, 0x1.7e47c775d2427p-5, 0x1.8a9fa33494b07p-5, 0x1.973239698b9ccp-5,
396 0x1.a3ffd8e001389p-5, 0x1.b108cfc6b7fbcp-5, 0x1.be4d6bb31d522p-5, 0x1.cbcdf9a4616f2p-5,
397 0x1.d98ac60675833p-5, 0x1.e7841cb4f16dfp-5, 0x1.f5ba48fde2048p-5, 0x1.0216cad240765p-4,
398 0x1.096f2671eb815p-4, 0x1.10e65c38a5192p-4, 0x1.187c90bf8bce2p-4, 0x1.2031e85f5d6dap-4,
399 0x1.28068731a1952p-4, 0x1.2ffa9111cb94bp-4, 0x1.380e299e53f92p-4, 0x1.40417439ca10fp-4,
400 0x1.4894940bddbfbp-4, 0x1.5107ac0261e59p-4, 0x1.599aded247aacp-4, 0x1.624e4ef892ed4p-4,
401 0x1.6b221ebb4817ep-4, 0x1.7416702a539d1p-4, 0x1.7d2b65206b527p-4, 0x1.86611f43e9e6ap-4,
402 0x1.8fb7c007a4a7p-4, 0x1.992f68abbbc89p-4, 0x1.a2c83a3e6566dp-4, 0x1.ac82559cb3644p-4,
403 0x1.b65ddb7354604p-4, 0x1.c05aec3f4fe5ep-4, 0x1.ca79a84ebe03p-4, 0x1.d4ba2fc17a6a5p-4,
404 0x1.df1ca289d34b8p-4, 0x1.e9a1206d34003p-4, 0x1.f447c904cbb4ep-4, 0x1.ff10bbbe302c2p-4,
405 0x1.04fe0bedfe5f1p-3, 0x1.0a84fe3b36d8fp-3, 0x1.101d443dfc06fp-3, 0x1.15c6ed58eefdfp-3,
406 0x1.1b8208da5fefp-3, 0x1.214ea5fc9514ap-3, 0x1.272cd3e610123p-3, 0x1.2d1ca1a9d1cfbp-3,
407 0x1.331e1e479cdf5p-3, 0x1.393158ac3674ep-3, 0x1.3f565fb1a5fd5p-3, 0x1.458d421f735dfp-3,
408 0x1.4bd60eaae3e73p-3, 0x1.5230d3f736034p-3, 0x1.589da095dbaa1p-3, 0x1.5f1c8306b3a3cp-3,
409 0x1.65ad89b841a2bp-3, 0x1.6c50c307e53bfp-3, 0x1.73063d420fc8p-3, 0x1.79ce06a279303p-3,
410 0x1.80a82d5453b5dp-3, 0x1.8794bf727eb3fp-3, 0x1.8e93cb07b8679p-3, 0x1.95a55e0ecec0bp-3,
411 0x1.9cc98672cf47ep-3, 0x1.a400520f3619cp-3, 0x1.ab49ceb01c003p-3, 0x1.b2a60a1263b0ap-3,
412 0x1.ba1511e3e632dp-3, 0x1.c196f3c39e76fp-3, 0x1.c92bbd41d41fep-3, 0x1.d0d37be045851p-3,
413 0x1.d88e3d1250f68p-3, 0x1.e05c0e3d1d3ep-3, 0x1.e83cfcb7c16fp-3, 0x1.f03115cb6bfd3p-3,
414 0x1.f83866b38924dp-3, 0x1.00297e4ef4553p-2, 0x1.044072557177ap-2, 0x1.086115f6beb3ap-2,
415 0x1.0c8b6fb5c735ep-2, 0x1.10bf860ef039ap-2, 0x1.14fd5f782a5a6p-2, 0x1.1945026102997p-2,
416 0x1.1d967532b31b1p-2, 0x1.21f1be50339e7p-2, 0x1.2656e41649ae3p-2, 0x1.2ac5ecdb988f8p-2,
417 0x1.2f3edef0b0ed8p-2, 0x1.33c1c0a020438p-2, 0x1.384e982e800b1p-2, 0x1.3ce56bda84a81p-2,
418 0x1.418641dd0c1bcp-2, 0x1.463120692c7afp-2, 0x1.4ae60dac4229dp-2, 0x1.4fa50fcdfde15p-2,
419 0x1.546e2cf0727a9p-2, 0x1.59416b3022858p-2, 0x1.5e1ed0a40daabp-2, 0x1.6306635dbdd7bp-2,
420 0x1.67f82969543a2p-2, 0x1.6cf428cd96079p-2, 0x1.71fa678bf915dp-2, 0x1.770aeba0b042ap-2,
421 0x1.7c25bb02b7ac5p-2, 0x1.814adba3e0bd9p-2, 0x1.867a5370de0b1p-2, 0x1.8bb428514f067p-2,
422 0x1.90f86027cb84ep-2, 0x1.964700d1ef1b1p-2, 0x1.9ba0102864521p-2, 0x1.a10393feefafdp-2,
423 0x1.a67192247a9bep-2, 0x1.abea10631e195p-2, 0x1.b16d14802d5cap-2, 0x1.b6faa43c403bbp-2,
424 0x1.bc92c5533d785p-2, 0x1.c2357d7c64e5dp-2, 0x1.c7e2d26a596dep-2, 0x1.cd9ac9cb2aef2p-2,
425 0x1.d35d69485ffc5p-2, 0x1.d92ab686ff782p-2, 0x1.df02b7279a10dp-2, 0x1.e4e570c6539c5p-2,
426 0x1.ead2e8faec526p-2, 0x1.f0cb2558c9ea4p-2, 0x1.f6ce2b6f00983p-2, 0x1.fcdc00c85bec2p-2,
427 0x1.017a5575b3cb2p-1, 0x1.048c17ad3c04bp-1, 0x1.07a349c9d9837p-1, 0x1.0abfee888c05p-1,
428 0x1.0de208a4444c8p-1, 0x1.11099ad5e83ebp-1, 0x1.1436a7d456eefp-1, 0x1.176932546ca12p-1,
429 0x1.1aa13d0906bdap-1, 0x1.1ddecaa307b85p-1, 0x1.2121ddd15aecep-1, 0x1.246a7940f86d1p-1,
430 0x1.27b89f9ce8c4bp-1, 0x1.2b0c538e48b07p-1, 0x1.2e6597bc4ccap-1, 0x1.31c46ecc4528dp-1,
431 0x1.3528db61a0f73p-1, 0x1.3892e01df1fccp-1, 0x1.3c027fa0f01ebp-1, 0x1.3f77bc887cd3bp-1,
432 0x1.42f29970a68f8p-1, 0x1.467318f3ac22dp-1, 0x1.49f93daa00113p-1, 0x1.4d850a2a4bde1p-1,
433 0x1.51168109734e5p-1, 0x1.54ada4da97a1bp-1, 0x1.584a782f1ac23p-1, 0x1.5becfd96a2698p-1,
434 0x1.5f95379f1b3edp-1, 0x1.634328d4bbe97p-1, 0x1.66f6d3c2081cfp-1, 0x1.6ab03aefd39aap-1,
435 0x1.6e6f60e5452b1p-1, 0x1.72344827d98f6p-1, 0x1.75fef33b6669bp-1, 0x1.79cf64a21d1e2p-1,
436 0x1.7da59edc8dabp-1, 0x1.8181a469a9787p-1, 0x1.856377c6c6224p-1, 0x1.894b1b6fa0377p-1,
437 0x1.8d3891de5df49p-1, 0x1.912bdd8b91f45p-1, 0x1.952500ee3dda5p-1, 0x1.9923fe7bd4f67p-1,
438 0x1.9d28d8a83edfcp-1, 0x1.a13391e5da09fp-1, 0x1.a5442ca57e52ep-1, 0x1.a95aab567f88fp-1,
439 0x1.ad771066afec2p-1, 0x1.b1995e4262a69p-1, 0x1.b5c197546e3f8p-1, 0x1.b9efbe062f086p-1,
440 0x1.be23d4bf8981bp-1, 0x1.c25ddde6ecbbbp-1, 0x1.c69ddbe154af1p-1, 0x1.cae3d1124c90bp-1,
441 0x1.cf2fbfdbf11f1p-1, 0x1.d381aa9ef2e82p-1, 0x1.d7d993ba988d4p-1, 0x1.dc377d8cc0fd5p-1,
442 0x1.e09b6a71e5aa6p-1, 0x1.e5055cc51cbb4p-1, 0x1.e97556e01b351p-1, 0x1.edeb5b1b37216p-1,
443 0x1.f2676bcd69adep-1, 0x1.f6e98b4c51466p-1, 0x1.fb71bbec33ab2p-1, 0x1p+0,
448Lab rgbToOklab(QRgb rgb)
450 const double r = RGB888_to_sRGB_table[qRed(rgb)];
451 const double g = RGB888_to_sRGB_table[qGreen(rgb)];
452 const double b = RGB888_to_sRGB_table[qBlue(rgb)];
454 const double l = std::cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
455 const double m = std::cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
456 const double s = std::cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
460 (021.04542553 * l + 079.36177850 * m - 000.40720468 * s),
461 (197.79984951 * l - 242.85922050 * m + 045.05937099 * s),
462 (002.59040371 * l + 078.27717662 * m - 080.86757660 * s),
466constexpr double epsilon = 1e-15;
468inline double sinDegree(
double x)
470 return std::sin(x * M_PI / 180.0);
473inline double cosDegree(
double x)
475 return std::cos(x * M_PI / 180.0);
478inline double pow2(
double x)
483inline double computeHPrime(
double a_prime,
double b)
485 if (std::abs(a_prime) < epsilon && std::abs(b) < epsilon) {
489 const double value = std::atan2(b, a_prime) * 180.0 / M_PI;
490 return (value < 0.0) ? value + 360.0 : value;
493inline double computeDeltaHPrime(
double C1_prime,
double C2_prime,
double h1_prime,
double h2_prime)
495 if (C1_prime * C2_prime < epsilon) {
499 const double diff = h2_prime - h1_prime;
501 if (std::abs(diff) <= 180.0) {
503 }
else if (diff > 180.0) {
510inline double computeHPrimeBar(
double C1_prime,
double C2_prime,
double h1_prime,
double h2_prime)
512 const double sum = h1_prime + h2_prime;
514 if (C1_prime * C2_prime < epsilon) {
518 const double dist = std::abs(h1_prime - h2_prime);
522 }
else if (sum < 360.0) {
523 return 0.5 * (sum + 360.0);
525 return 0.5 * (sum - 360.0);
532double calculate_CIEDE2000(
const Lab &color1,
const Lab &color2)
534 const double L1 =
color1.L;
535 const double a1 =
color1.a;
536 const double b1 =
color1.b;
537 const double L2 = color2.L;
538 const double a2 = color2.a;
539 const double b2 = color2.b;
541 const double _25_pow_7 = 6103515625.0;
543 const double C1_ab = std::sqrt(a1 * a1 + b1 * b1);
544 const double C2_ab = std::sqrt(a2 * a2 + b2 * b2);
545 const double C_ab_bar = 0.5 * (C1_ab + C2_ab);
546 const double c_ab_bar_pow_7 = std::pow(C_ab_bar, 7.0);
547 const double G = 0.5 * (1.0 - std::sqrt(c_ab_bar_pow_7 / (c_ab_bar_pow_7 + _25_pow_7)));
548 const double a1_prime = (1.0 + G) * a1;
549 const double a2_prime = (1.0 + G) * a2;
550 const double C1_prime = std::sqrt(a1_prime * a1_prime + b1 * b1);
551 const double C2_prime = std::sqrt(a2_prime * a2_prime + b2 * b2);
552 const double h1_prime = computeHPrime(a1_prime, b1);
553 const double h2_prime = computeHPrime(a2_prime, b2);
555 const double deltaL_prime = L2 - L1;
556 const double deltaC_prime = C2_prime - C1_prime;
557 const double deltah_prime = computeDeltaHPrime(C1_prime, C2_prime, h1_prime, h2_prime);
558 const double deltaH_prime = 2.0 * std::sqrt(C1_prime * C2_prime) * sinDegree(0.5 * deltah_prime);
560 const double L_primeBar = 0.5 * (L1 + L2);
561 const double C_primeBar = 0.5 * (C1_prime + C2_prime);
562 const double h_primeBar = computeHPrimeBar(C1_prime, C2_prime, h1_prime, h2_prime);
564 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)
565 - 0.20 * cosDegree(4.0 * h_primeBar - 63.0);
567 const double C_primeBar_pow7 = std::pow(C_primeBar, 7.0);
568 const double R_C = 2.0 * std::sqrt(C_primeBar_pow7 / (C_primeBar_pow7 + _25_pow_7));
569 const double S_L = 1.0 + (0.015 * pow2(L_primeBar - 50.0)) / std::sqrt(20.0 + pow2(L_primeBar - 50.0));
570 const double S_C = 1.0 + 0.045 * C_primeBar;
571 const double S_H = 1.0 + 0.015 * C_primeBar * T;
572 const double R_T = -R_C * sinDegree(60.0 * std::exp(-pow2((h_primeBar - 275) / 25.0)));
574 constexpr double kL = 1.0;
575 constexpr double kC = 1.0;
576 constexpr double kH = 1.0;
578 const double deltaL = deltaL_prime / (kL * S_L);
579 const double deltaC = deltaC_prime / (kC * S_C);
580 const double deltaH = deltaH_prime / (kH * S_H);
582 return (deltaL * deltaL + deltaC * deltaC + deltaH * deltaH + R_T * deltaC * deltaH);
590 Q_ASSERT(remaining() >= 1);
597 Q_ASSERT(remaining() >= str.size());
598 memcpy(m_data + m_size, str.data(), str.size());
599 m_size += str.size();
602 void appendForeground(QRgb rgb,
bool is256Colors, ColorCache &colorCache)
605 append(rgb, is256Colors, colorCache);
608 void appendBackground(QRgb rgb,
bool is256Colors, ColorCache &colorCache)
611 append(rgb, is256Colors, colorCache);
614 void append(QRgb rgb,
bool is256Colors, ColorCache &colorCache)
616 auto appendUInt8 = [&](
int x) {
617 Q_ASSERT(x <= 255 && x >= 0);
627 append(
char(
'0' + x));
632 constexpr char const* tb2digits =
633 "00" "01" "02" "03" "04" "05" "06" "07" "08" "09"
634 "10" "11" "12" "13" "14" "15" "16" "17" "18" "19"
635 "20" "21" "22" "23" "24" "25" "26" "27" "28" "29"
636 "30" "31" "32" "33" "34" "35" "36" "37" "38" "39"
637 "40" "41" "42" "43" "44" "45" "46" "47" "48" "49"
638 "50" "51" "52" "53" "54" "55" "56" "57" "58" "59"
639 "60" "61" "62" "63" "64" "65" "66" "67" "68" "69"
640 "70" "71" "72" "73" "74" "75" "76" "77" "78" "79"
641 "80" "81" "82" "83" "84" "85" "86" "87" "88" "89"
642 "90" "91" "92" "93" "94" "95" "96" "97" "98" "99";
645 auto *p = tb2digits + x * 2;
653 auto it = colorCache.find(rgb);
654 if (it == colorCache.end()) {
655 const auto lab = rgbToOklab(rgb);
657 for (Lab
const &xtermLab : xterm240_Oklabs) {
658 auto dist2 = calculate_CIEDE2000(lab, xtermLab);
661 idx = &xtermLab - xterm240_Oklabs;
666 colorCache.insert(rgb, idx);
677 appendUInt8(qRed(rgb));
679 appendUInt8(qGreen(rgb));
681 appendUInt8(qBlue(rgb));
689 Q_ASSERT(m_data[m_size - 1] ==
';');
690 m_data[m_size - 1] =
'm';
707 int remaining() const noexcept
716 for (; n > fill.
size(); n -= fill.
size()) {
726 int graphLineLength = 0;
727 int labelLineLength = 0;
728 int nextLabelOffset = 0;
730 template<
class StringBuilder>
731 void pushLabel(
int offset, StringBuilder
const &s,
int numberDisplayableChar)
733 Q_ASSERT(offset >= labelLineLength);
734 const int n = offset - labelLineLength;
735 labelLineLength += numberDisplayableChar + n;
736 fillLine(labelLine, n);
738 nextLabelOffset = labelLineLength;
741 template<
class StringBuilder>
742 void pushGraph(
int offset, StringBuilder
const &s,
int numberDisplayableChar)
744 Q_ASSERT(offset >= graphLineLength);
745 const int n = offset - graphLineLength;
746 graphLineLength += numberDisplayableChar + n;
747 fillLine(graphLine, n);
748 const qsizetype ps1 = graphLine.
size();
750 if (offset >= labelLineLength) {
751 const int n2 = offset - labelLineLength;
752 labelLineLength += n2 + 1;
753 fillLine(labelLine, n2);
759 static void fillLine(
QString &s,
int n)
773GraphLine &lineAtOffset(std::vector<GraphLine> &graphLines,
int offset)
775 const auto last = graphLines.end();
776 auto p = std::find_if(graphLines.begin(), last, [=](GraphLine
const &line) {
777 return line.nextLabelOffset < offset;
780 graphLines.emplace_back();
781 return graphLines.back();
797 using Option = KSyntaxHighlighting::AnsiHighlighter::Option;
803 m_contextCapture.setDefinition(def);
806 for (
const auto &definition : definitions) {
807 const auto *defData = DefinitionData::get(definition);
808 for (
const auto &context : defData->contexts) {
809 m_defDataBycontexts.insert(&context, defData);
818 const std::vector<QPair<QString, QString>> &ansiStyles,
821 initRegionStyles(ansiStyles);
823 m_hasFormatTrace = options.testFlag(Option::TraceFormat);
824 m_hasRegionTrace = options.testFlag(Option::TraceRegion);
825 m_hasStackSizeTrace = options.testFlag(Option::TraceStackSize);
826 m_hasContextTrace = options.testFlag(Option::TraceContext);
827 const bool hasFormatOrContextTrace = m_hasFormatTrace || m_hasContextTrace || m_hasStackSizeTrace;
829 const bool hasSeparator = hasFormatOrContextTrace && m_hasRegionTrace;
830 const QString resetBgColor = (editorBackground.isEmpty() ? QStringLiteral(
"\x1b[0m") : editorBackground);
832 bool firstLine =
true;
835 const bool isUnbuffered = options.testFlag(Option::Unbuffered);
837 auto oldState = state;
838 state = highlightLine(currentLine, state);
842 out << QStringLiteral(
"\x1b[0m────────────────────────────────────────────────────\x1b[K\n");
847 if (!m_regions.empty()) {
848 printRegions(out, infoStyle, currentLine.
size());
852 for (
const auto &fragment : m_highlightedFragments) {
853 auto const &ansiStyle = ansiStyles[fragment.formatId];
854 out << ansiStyle.first <<
QStringView(currentLine).
sliced(fragment.offset, fragment.length) << ansiStyle.second;
857 out << QStringLiteral(
"\x1b[K\n");
859 if (hasFormatOrContextTrace && !m_highlightedFragments.empty()) {
860 if (m_hasContextTrace || m_hasStackSizeTrace) {
861 appendContextNames(oldState, currentLine);
864 printFormats(out, infoStyle, ansiStyles);
868 m_highlightedFragments.clear();
878 m_highlightedFragments.push_back({m_hasFormatTrace ? format.
name() :
QString(), offset, length, format.
id()});
881 void applyFolding(
int offset,
int ,
FoldingRegion region)
override
883 if (!m_hasRegionTrace) {
887 const auto id = region.
id();
890 m_regions.push_back(Region{m_regionDepth, offset, -1, id, Region::State::Open});
892 if (m_regions.size() >= 2) {
893 auto &previousRegion = m_regions[m_regions.size() - 2];
894 if (previousRegion.state == Region::State::Close && previousRegion.offset == offset) {
895 std::swap(previousRegion, m_regions.back());
896 if (previousRegion.bindIndex != -1) {
897 m_regions[previousRegion.bindIndex].bindIndex = m_regions.size() - 1;
904 auto it = m_regions.rbegin();
905 auto eit = m_regions.rend();
906 for (
int depth = 0; it != eit; ++it) {
907 if (it->regionId ==
id && it->bindIndex < 0) {
908 if (it->state == Region::State::Close) {
910 }
else if (--depth < 0) {
917 it->bindIndex = int(m_regions.size());
918 int bindIndex = int(&*it - m_regions.data());
919 m_regions.push_back(Region{it->depth, offset, bindIndex, id, Region::State::Close});
921 m_regions.push_back(Region{-1, offset, -1, id, Region::State::Close});
924 m_regionDepth = std::max(m_regionDepth - 1, 0);
934 void initRegionStyles(
const std::vector<QPair<QString, QString>> &ansiStyles)
936 m_regionStyles.resize(ansiStyles.size());
937 for (std::size_t i = 0; i < m_regionStyles.size(); ++i) {
938 m_regionStyles[i] = ansiStyles[i].first;
941 std::sort(m_regionStyles.begin(), m_regionStyles.end());
942 m_regionStyles.erase(std::unique(m_regionStyles.begin(), m_regionStyles.end()), m_regionStyles.end());
950 auto newState = state;
951 for (
auto &fragment : m_highlightedFragments) {
952 QString contextName = extractContextName(StateData::get(newState));
954 m_contextCapture.offsetNext = 0;
955 m_contextCapture.lengthNext = 0;
957 const auto lineFragment = currentLine.
sliced(0, fragment.offset + fragment.length + 1);
958 newState = m_contextCapture.highlightLine(lineFragment, state);
963 if (m_contextCapture.offset != fragment.offset && m_contextCapture.length != fragment.length) {
966 fragment.name.insert(0, contextName);
974 QString extractContextName(StateData *stateData)
const
978 if (m_hasStackSizeTrace) {
980 int stateSize = stateData ? stateData->size() : 0;
984 if (m_hasContextTrace) {
987 return label + QStringLiteral(
"[???]");
990 const auto context = stateData->topContext();
991 const auto defDataIt = m_defDataBycontexts.find(context);
999 void printFormats(
QTextStream &out,
QLatin1String regionStyle,
const std::vector<QPair<QString, QString>> &ansiStyles)
1002 m_formatGraph.
clear();
1003 for (
auto const &fragment : m_highlightedFragments) {
1004 GraphLine &line = lineAtOffset(m_formatGraph, fragment.offset);
1005 auto const &style = ansiStyles[fragment.formatId].first;
1006 line.pushLabel(fragment.offset, style % nameStyle % fragment.name % regionStyle, fragment.name.size());
1008 for (GraphLine *pline = m_formatGraph.data(); pline <= &line; ++pline) {
1009 pline->pushGraph(fragment.offset, style % graphSymbol % regionStyle, 1);
1015 auto first = m_formatGraph.begin();
1016 auto last = m_formatGraph.end();
1018 for (; first != last; ++first) {
1019 out << first->graphLine <<
"\x1b[K\n" << first->labelLine <<
"\x1b[K\n";
1021 out << first->graphLine <<
"\x1b[K\n" << first->labelLine <<
"\x1b[K\x1b[0m\n";
1026 const QString continuationLine = QStringLiteral(
1027 "------------------------------"
1028 "------------------------------"
1029 "------------------------------");
1031 bool hasContinuation =
false;
1033 m_regionGraph.clear();
1038 for (Region ®ion : m_regions) {
1039 if (region.state == Region::State::Continuation) {
1040 hasContinuation =
true;
1044 auto pushGraphs = [&](
int offset,
const GraphLine *endline,
QStringView style) {
1045 for (GraphLine *pline = m_regionGraph.data(); pline <= endline; ++pline) {
1047 if (pline->graphLineLength <= offset) {
1048 pline->pushGraph(offset, style % graphSymbol % regionStyle, 1);
1058 int offsetLabel = region.offset;
1060 numStr.
setNum(region.regionId);
1062 if (region.state == Region::State::Open) {
1064 if (region.bindIndex == -1) {
1065 rpad = lineLength - region.offset - numStr.
size();
1067 rpad = m_regions[region.bindIndex].offset - region.offset - 2;
1071 }
else if (region.bindIndex == -1) {
1074 }
else if (m_regions[region.bindIndex].state == Region::State::Open) {
1075 const auto &openRegion = m_regions[region.bindIndex];
1077 const GraphLine &line = m_regionGraph[openRegion.offset];
1078 const auto &style = m_regionStyles[openRegion.depth % m_regionStyles.size()];
1079 pushGraphs(region.offset, &line, style);
1083 lpad = region.offset - numStr.
size();
1091 fillString(label, lpad, continuationLine);
1093 fillString(label, rpad, continuationLine);
1095 GraphLine &line = lineAtOffset(m_regionGraph, offsetLabel);
1096 const auto &style = m_regionStyles[region.depth % m_regionStyles.size()];
1097 line.pushLabel(offsetLabel, style % nameStyle % openS % label % closeS % regionStyle,
label.
size() + openS.size() + closeS.size());
1098 pushGraphs(region.offset, &line, style);
1101 if (region.state == Region::State::Open && region.bindIndex != -1) {
1102 region.offset = &line - m_regionGraph.data();
1109 if (hasContinuation) {
1111 fillString(label, lineLength ? lineLength : 5, continuationLine);
1112 for (
const auto ®ion : m_regions) {
1113 if (region.state == Region::State::Continuation && region.bindIndex == -1) {
1114 const auto &style = m_regionStyles[region.depth % m_regionStyles.size()];
1115 out << style << nameStyle <<
label << regionStyle <<
"\x1b[K\n";
1121 if (!m_regionGraph.empty()) {
1122 auto first = m_regionGraph.rbegin();
1123 auto last = m_regionGraph.rend();
1125 for (; first != last; ++first) {
1126 out << first->labelLine <<
"\x1b[K\n" << first->graphLine <<
"\x1b[K\n";
1128 out << first->labelLine <<
"\x1b[K\n" << first->graphLine <<
"\x1b[K\x1b[0m\n";
1132 m_regions.erase(std::remove_if(m_regions.begin(),
1134 [](Region
const ®ion) {
1135 return region.bindIndex != -1 || region.state == Region::State::Close;
1139 for (
auto ®ion : m_regions) {
1141 region.state = Region::State::Continuation;
1145 struct HighlightFragment {
1160 offset = offsetNext;
1161 length = lengthNext;
1162 offsetNext = offset;
1163 lengthNext = length;
1170 enum class State : int8_t {
1183 bool m_hasFormatTrace;
1184 bool m_hasRegionTrace;
1185 bool m_hasStackSizeTrace;
1186 bool m_hasContextTrace;
1188 std::vector<HighlightFragment> m_highlightedFragments;
1189 std::vector<GraphLine> m_formatGraph;
1190 ContextCaptureHighlighter m_contextCapture;
1192 int m_regionDepth = 0;
1193 std::vector<Region> m_regions;
1194 std::vector<GraphLine> m_regionGraph;
1195 std::vector<QStringView> m_regionStyles;
1201class KSyntaxHighlighting::AnsiHighlighterPrivate :
public AbstractHighlighterPrivate
1208 std::vector<QPair<QString, QString>> ansiStyles;
1212AnsiHighlighter::AnsiHighlighter()
1217AnsiHighlighter::~AnsiHighlighter() =
default;
1221 Q_D(AnsiHighlighter);
1225void AnsiHighlighter::setOutputFile(
const QString &fileName)
1227 Q_D(AnsiHighlighter);
1228 if (d->file.isOpen()) {
1231 d->file.setFileName(fileName);
1233 qCWarning(
Log) <<
"Failed to open output file" << fileName <<
":" << d->file.errorString();
1236 d->out.setDevice(&d->file);
1239void AnsiHighlighter::setOutputFile(FILE *fileHandle)
1241 Q_D(AnsiHighlighter);
1243 d->out.setDevice(&d->file);
1246void AnsiHighlighter::highlightFile(
const QString &fileName, AnsiFormat format, Options options)
1250 qCWarning(
Log) <<
"Failed to open input file" << fileName <<
":" << f.errorString();
1254 highlightData(&f, format, options);
1257void AnsiHighlighter::highlightData(
QIODevice *dev, AnsiFormat format, Options options)
1259 Q_D(AnsiHighlighter);
1261 if (!d->out.device()) {
1262 qCWarning(
Log) <<
"No output stream defined!";
1266 const auto is256Colors = (format == AnsiFormat::XTerm256Color);
1267 const auto &
theme = d->m_theme;
1275 AnsiBuffer foregroundColorBuffer;
1276 AnsiBuffer backgroundColorBuffer;
1280 const bool useEditorBackground = options.testFlag(Option::UseEditorBackground);
1283 const auto toRGB = [](QRgb argb) {
1284 return argb & 0xff'ff'ffu;
1287 const QRgb foregroundColor = [&] {
1288 if (useSelectedText) {
1296 const QRgb backgroundColor = useEditorBackground ? toRGB(
theme.
editorColor(d->bgRole)) : 0;
1300 if (useEditorBackground) {
1301 foregroundColorBuffer.appendForeground(foregroundColor, is256Colors, colorCache);
1303 backgroundColorBuffer.appendBackground(backgroundColor, is256Colors, colorCache);
1304 foregroundDefaultColor = foregroundColorBuffer.latin1();
1305 backgroundDefaultColor = backgroundColorBuffer.latin1().sliced(2);
1309 for (
const auto &
definition : std::as_const(definitions)) {
1310 for (
const auto &format : std::as_const(DefinitionData::get(
definition)->formats)) {
1311 maxId = qMax(maxId, format.id());
1314 d->ansiStyles.clear();
1316 d->ansiStyles.resize(maxId + 1);
1319 for (
const auto &
definition : std::as_const(definitions)) {
1320 for (
const auto &format : std::as_const(DefinitionData::get(
definition)->formats)) {
1325 const auto fg = useSelectedText ? format.selectedTextColor(
theme).rgba() : format.textColor(
theme).rgba();
1326 const auto bg = useSelectedText ? format.selectedBackgroundColor(
theme).rgba() : format.backgroundColor(
theme).rgba();
1327 const bool hasFg = fg && (!useEditorBackground || toRGB(fg) != foregroundColor);
1328 const bool hasBg = bg && (!useEditorBackground || toRGB(bg) != backgroundColor);
1329 const bool hasBold = format.isBold(
theme);
1330 const bool hasItalic = format.isItalic(
theme);
1331 const bool hasUnderline = format.isUnderline(
theme);
1332 const bool hasStrikeThrough = format.isStrikeThrough(
theme);
1335 buffer.appendForeground(toRGB(fg), is256Colors, colorCache);
1337 buffer.append(foregroundDefaultColor);
1340 buffer.appendBackground(toRGB(bg), is256Colors, colorCache);
1351 if (hasStrikeThrough) {
1356 if (buffer.latin1().size() > 2) {
1357 buffer.setFinalStyle();
1358 auto &style = d->ansiStyles[format.id()];
1359 style.first = buffer.latin1();
1361 if (useEditorBackground) {
1363 const bool hasEffect = hasBold || hasItalic || hasUnderline || hasStrikeThrough;
1366 buffer.append(backgroundDefaultColor);
1367 buffer.setFinalStyle();
1368 style.second = buffer.latin1();
1369 }
else if (hasEffect) {
1380 if (hasStrikeThrough) {
1383 buffer.setFinalStyle();
1384 style.second = buffer.latin1();
1387 style.second = QStringLiteral(
"\x1b[0m");
1393 if (useEditorBackground) {
1394 backgroundColorBuffer.setFinalStyle();
1395 backgroundDefaultColor = backgroundColorBuffer.latin1();
1396 d->out << backgroundDefaultColor;
1401 if (!options.testAnyFlag(Option::TraceAll)) {
1404 const bool isUnbuffered = options.testFlag(Option::Unbuffered);
1406 d->currentLine = currentLine;
1409 if (useEditorBackground) {
1410 d->out << QStringLiteral(
"\x1b[K\n");
1423 buffer.setFinalStyle();
1424 DebugSyntaxHighlighter debugHighlighter;
1426 debugHighlighter.highlightData(in, d->out, buffer.latin1(), backgroundDefaultColor, d->ansiStyles, options);
1429 if (useEditorBackground) {
1430 d->out << QStringLiteral(
"\x1b[0m");
1433 d->out.setDevice(
nullptr);
1435 d->ansiStyles.clear();
1438void AnsiHighlighter::applyFormat(
int offset,
int length,
const Format &format)
1440 Q_D(AnsiHighlighter);
1441 auto const &ansiStyle = d->ansiStyles[format.
id()];
1442 d->out << ansiStyle.first << d->currentLine.sliced(offset, length) << ansiStyle.second;
Abstract base class for highlighters.
virtual void setDefinition(const Definition &def)
Sets the syntax definition used for highlighting.
Theme theme() const
Returns the currently selected theme for highlighting.
Definition definition() const
Returns the syntax definition used for highlighting.
State highlightLine(QStringView text, const State &state)
Highlight the given line.
Represents a syntax definition.
QList< Definition > includedDefinitions() const
Returns a list of Definitions that are referenced with the IncludeRules rule.
Represents a begin or end of a folding region.
@ Begin
Indicates the start of a FoldingRegion.
int id() const
Returns a unique identifier for this folding region.
Type type() const
Returns whether this is the begin or end of a region.
QRgb textColor(TextStyle style) const
Returns the text color to be used for style.
QRgb selectedTextColor(TextStyle style) const
Returns the selected text color to be used for style.
EditorColorRole
Editor color roles, used to paint line numbers, editor background etc.
@ TemplateBackground
Background color for text templates (snippets).
@ BackgroundColor
Background color for the editing area.
@ TextSelection
Background color for selected text.
@ Normal
Default text style for normal text and source code without special highlighting.
QRgb editorColor(EditorColorRole role) const
Returns the editor color for the requested role.
QString name(StandardAction id)
QString label(StandardShortcut id)
Syntax highlighting engine for Kate syntax definitions.
QString & insert(qsizetype position, QChar ch)
QString number(double n, char format, int precision)
QString & setNum(double n, char format, int precision)
qsizetype size() const const
qsizetype size() const const
QStringView sliced(qsizetype pos) const const
bool readLineInto(QString *line, qint64 maxlen)