Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/fitz/draw-blend.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 // Copyright (C) 2004-2025 Artifex Software, Inc. | |
| 2 // | |
| 3 // This file is part of MuPDF. | |
| 4 // | |
| 5 // MuPDF is free software: you can redistribute it and/or modify it under the | |
| 6 // terms of the GNU Affero General Public License as published by the Free | |
| 7 // Software Foundation, either version 3 of the License, or (at your option) | |
| 8 // any later version. | |
| 9 // | |
| 10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | |
| 13 // details. | |
| 14 // | |
| 15 // You should have received a copy of the GNU Affero General Public License | |
| 16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> | |
| 17 // | |
| 18 // Alternative licensing terms are available from the licensor. | |
| 19 // For commercial licensing, see <https://www.artifex.com/> or contact | |
| 20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, | |
| 21 // CA 94129, USA, for further information. | |
| 22 | |
| 23 #include "mupdf/fitz.h" | |
| 24 | |
| 25 #include "draw-imp.h" | |
| 26 #include "pixmap-imp.h" | |
| 27 | |
| 28 #include <string.h> | |
| 29 #include <math.h> | |
| 30 #include <assert.h> | |
| 31 | |
| 32 /* PDF 1.4 blend modes. These are slow. */ | |
| 33 | |
| 34 /* Define PARANOID_PREMULTIPLY to check premultiplied values are | |
| 35 * properly in range. */ | |
| 36 #undef PARANOID_PREMULTIPLY | |
| 37 | |
| 38 /* | |
| 39 | |
| 40 Some notes on the transparency maths: | |
| 41 | |
| 42 Compositing equation: | |
| 43 ===================== | |
| 44 | |
| 45 In section 7.2.2 (page 517) of pdf_reference17.pdf, it says: | |
| 46 | |
| 47 Cr = (1 - As/Ar) * Cb + As/Ar * [ (1-Ab) * Cs + Ab * B(Cb,Cs) ] | |
| 48 | |
| 49 It says that this is a simplified version of the more general form. | |
| 50 | |
| 51 This equation is then restated in section 7.2.2 and it says: | |
| 52 | |
| 53 The formula shown above is a simplification of the following formula: | |
| 54 | |
| 55 Ar * Cr = [(1-As)*Ab*Cb] + [(1-Ab)*As*Cs] + [Ab*As*B(Cb, Cs)] | |
| 56 | |
| 57 At first glance this always appears to be a mistake to me, as it looks | |
| 58 like they have make a mistake in the division. | |
| 59 | |
| 60 However, if we consider the result alpha equation: | |
| 61 | |
| 62 Ar = Union(Ab, As) = Ab + As - Ab * As | |
| 63 | |
| 64 we can rearrange that to give: | |
| 65 | |
| 66 Ar - As = (1 - As) * Ab | |
| 67 | |
| 68 1 - As/Ar = (1 - As) * Ab / Ar | |
| 69 | |
| 70 So substituting into the first equation above, we get: | |
| 71 | |
| 72 Cr = ((1 - As) * Ab/Ar) * Cb + As/Ar * [ (1-Ab) * Cs + Ab * B(Cb,Cs) ] | |
| 73 | |
| 74 And thus: | |
| 75 | |
| 76 Ar * Cr = (1 - As) * Ab * Cb + As * [ (1-Ab)*Cs + Ab * B(Cb,Cs) ] | |
| 77 | |
| 78 as required. | |
| 79 | |
| 80 Alpha blending on top of compositing: | |
| 81 ===================================== | |
| 82 | |
| 83 Suppose we have a group to blend using blend mode B, and we want | |
| 84 to apply alpha too. Let's apply the blending first to get an | |
| 85 intermediate result (Ir), then apply the alpha to that to get the | |
| 86 result (Cr): | |
| 87 | |
| 88 Ir = (1 - As/Ar) * Cb + As/Ar * [ (1-Ab) * Cs + Ab * B(Cb,Cs) ] | |
| 89 | |
| 90 Cr = (1-alpha) * Cb + alpha * Ir | |
| 91 = Cb - alpha * Cb + alpha * Cb - alpha * Cb * As / Ar + alpha * As / Ar * [ (1 - Ab) * Cs + Ab * B(Cb, Cs) ] | |
| 92 = Cb - alpha * Cb * As / Ar + alpha * As / Ar * [ (1 - Ab) * Cs + Ab * B(Cb, Cs) ] | |
| 93 = Cb * (1 - alpha * As / Ar) + alpha * As / Ar * [ (1 - Ab) * Cs + Ab * B(Cb, Cs) ] | |
| 94 | |
| 95 We want premultiplied results, so: | |
| 96 | |
| 97 Ar*Cr = Cb * (Ar - alpha * As) + alpha * As * (1 - Ab) * Cs + alpha * As * Ab * B(Cb, Cs) ] | |
| 98 | |
| 99 In the same way, for the alpha values: | |
| 100 | |
| 101 Ia = Union(Ab, As) = Ab + As - As*Ab | |
| 102 Ar = (1-alpha) * Ab + alpha * Ia | |
| 103 = Ab - alpha * Ab + alpha * Ab + alpha * As - alpha * As * Ab | |
| 104 = Ab + alpha * As - alpha * As * Ab | |
| 105 = Union(Ab, alpha * As) | |
| 106 | |
| 107 */ | |
| 108 | |
| 109 typedef unsigned char byte; | |
| 110 | |
| 111 static const char *fz_blendmode_names[] = | |
| 112 { | |
| 113 "Normal", | |
| 114 "Multiply", | |
| 115 "Screen", | |
| 116 "Overlay", | |
| 117 "Darken", | |
| 118 "Lighten", | |
| 119 "ColorDodge", | |
| 120 "ColorBurn", | |
| 121 "HardLight", | |
| 122 "SoftLight", | |
| 123 "Difference", | |
| 124 "Exclusion", | |
| 125 "Hue", | |
| 126 "Saturation", | |
| 127 "Color", | |
| 128 "Luminosity", | |
| 129 }; | |
| 130 | |
| 131 int fz_lookup_blendmode(const char *name) | |
| 132 { | |
| 133 int i; | |
| 134 for (i = 0; i < (int)nelem(fz_blendmode_names); i++) | |
| 135 if (!strcmp(name, fz_blendmode_names[i])) | |
| 136 return i; | |
| 137 return FZ_BLEND_NORMAL; | |
| 138 } | |
| 139 | |
| 140 const char *fz_blendmode_name(int blendmode) | |
| 141 { | |
| 142 if (blendmode >= 0 && blendmode < (int)nelem(fz_blendmode_names)) | |
| 143 return fz_blendmode_names[blendmode]; | |
| 144 return "Normal"; | |
| 145 } | |
| 146 | |
| 147 /* Separable blend modes */ | |
| 148 | |
| 149 static inline int fz_screen_byte(int b, int s) | |
| 150 { | |
| 151 return b + s - fz_mul255(b, s); | |
| 152 } | |
| 153 | |
| 154 static inline int fz_hard_light_byte(int b, int s) | |
| 155 { | |
| 156 int s2 = s << 1; | |
| 157 if (s <= 127) | |
| 158 return fz_mul255(b, s2); | |
| 159 else | |
| 160 return fz_screen_byte(b, s2 - 255); | |
| 161 } | |
| 162 | |
| 163 static inline int fz_overlay_byte(int b, int s) | |
| 164 { | |
| 165 return fz_hard_light_byte(s, b); /* note swapped order */ | |
| 166 } | |
| 167 | |
| 168 static inline int fz_darken_byte(int b, int s) | |
| 169 { | |
| 170 return fz_mini(b, s); | |
| 171 } | |
| 172 | |
| 173 static inline int fz_lighten_byte(int b, int s) | |
| 174 { | |
| 175 return fz_maxi(b, s); | |
| 176 } | |
| 177 | |
| 178 static inline int fz_color_dodge_byte(int b, int s) | |
| 179 { | |
| 180 s = 255 - s; | |
| 181 if (b <= 0) | |
| 182 return 0; | |
| 183 else if (b >= s) | |
| 184 return 255; | |
| 185 else | |
| 186 return (0x1fe * b + s) / (s << 1); | |
| 187 } | |
| 188 | |
| 189 static inline int fz_color_burn_byte(int b, int s) | |
| 190 { | |
| 191 b = 255 - b; | |
| 192 if (b <= 0) | |
| 193 return 255; | |
| 194 else if (b >= s) | |
| 195 return 0; | |
| 196 else | |
| 197 return 0xff - (0x1fe * b + s) / (s << 1); | |
| 198 } | |
| 199 | |
| 200 static inline int fz_soft_light_byte(int b, int s) | |
| 201 { | |
| 202 if (s < 128) { | |
| 203 return b - fz_mul255(fz_mul255((255 - (s<<1)), b), 255 - b); | |
| 204 } | |
| 205 else { | |
| 206 int dbd; | |
| 207 if (b < 64) | |
| 208 dbd = fz_mul255(fz_mul255((b << 4) - 3060, b) + 1020, b); | |
| 209 else | |
| 210 dbd = (int)sqrtf(255.0f * b); | |
| 211 return b + fz_mul255(((s<<1) - 255), (dbd - b)); | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 static inline int fz_difference_byte(int b, int s) | |
| 216 { | |
| 217 return fz_absi(b - s); | |
| 218 } | |
| 219 | |
| 220 static inline int fz_exclusion_byte(int b, int s) | |
| 221 { | |
| 222 return b + s - (fz_mul255(b, s)<<1); | |
| 223 } | |
| 224 | |
| 225 /* Non-separable blend modes */ | |
| 226 | |
| 227 static void | |
| 228 fz_luminosity_rgb(unsigned char *rd, unsigned char *gd, unsigned char *bd, int rb, int gb, int bb, int rs, int gs, int bs) | |
| 229 { | |
| 230 int delta, scale; | |
| 231 int r, g, b, y; | |
| 232 | |
| 233 /* 0.3f, 0.59f, 0.11f in fixed point */ | |
| 234 delta = ((rs - rb) * 77 + (gs - gb) * 151 + (bs - bb) * 28 + 0x80) >> 8; | |
| 235 r = rb + delta; | |
| 236 g = gb + delta; | |
| 237 b = bb + delta; | |
| 238 | |
| 239 if ((r | g | b) & 0x100) | |
| 240 { | |
| 241 y = (rs * 77 + gs * 151 + bs * 28 + 0x80) >> 8; | |
| 242 if (delta > 0) | |
| 243 { | |
| 244 int max; | |
| 245 max = fz_maxi(r, fz_maxi(g, b)); | |
| 246 scale = (max == y ? 0 : ((255 - y) << 16) / (max - y)); | |
| 247 } | |
| 248 else | |
| 249 { | |
| 250 int min; | |
| 251 min = fz_mini(r, fz_mini(g, b)); | |
| 252 scale = (y == min ? 0 : (y << 16) / (y - min)); | |
| 253 } | |
| 254 r = y + (((r - y) * scale + 0x8000) >> 16); | |
| 255 g = y + (((g - y) * scale + 0x8000) >> 16); | |
| 256 b = y + (((b - y) * scale + 0x8000) >> 16); | |
| 257 } | |
| 258 | |
| 259 *rd = fz_clampi(r, 0, 255); | |
| 260 *gd = fz_clampi(g, 0, 255); | |
| 261 *bd = fz_clampi(b, 0, 255); | |
| 262 } | |
| 263 | |
| 264 static void | |
| 265 fz_saturation_rgb(unsigned char *rd, unsigned char *gd, unsigned char *bd, int rb, int gb, int bb, int rs, int gs, int bs) | |
| 266 { | |
| 267 int minb, maxb; | |
| 268 int mins, maxs; | |
| 269 int y; | |
| 270 int scale; | |
| 271 int r, g, b; | |
| 272 | |
| 273 minb = fz_mini(rb, fz_mini(gb, bb)); | |
| 274 maxb = fz_maxi(rb, fz_maxi(gb, bb)); | |
| 275 if (minb == maxb) | |
| 276 { | |
| 277 /* backdrop has zero saturation, avoid divide by 0 */ | |
| 278 gb = fz_clampi(gb, 0, 255); | |
| 279 *rd = gb; | |
| 280 *gd = gb; | |
| 281 *bd = gb; | |
| 282 return; | |
| 283 } | |
| 284 | |
| 285 mins = fz_mini(rs, fz_mini(gs, bs)); | |
| 286 maxs = fz_maxi(rs, fz_maxi(gs, bs)); | |
| 287 | |
| 288 scale = ((maxs - mins) << 16) / (maxb - minb); | |
| 289 y = (rb * 77 + gb * 151 + bb * 28 + 0x80) >> 8; | |
| 290 r = y + ((((rb - y) * scale) + 0x8000) >> 16); | |
| 291 g = y + ((((gb - y) * scale) + 0x8000) >> 16); | |
| 292 b = y + ((((bb - y) * scale) + 0x8000) >> 16); | |
| 293 | |
| 294 if ((r | g | b) & 0x100) | |
| 295 { | |
| 296 int scalemin, scalemax; | |
| 297 int min, max; | |
| 298 | |
| 299 min = fz_mini(r, fz_mini(g, b)); | |
| 300 max = fz_maxi(r, fz_maxi(g, b)); | |
| 301 | |
| 302 if (min < 0) | |
| 303 scalemin = (y << 16) / (y - min); | |
| 304 else | |
| 305 scalemin = 0x10000; | |
| 306 | |
| 307 if (max > 255) | |
| 308 scalemax = ((255 - y) << 16) / (max - y); | |
| 309 else | |
| 310 scalemax = 0x10000; | |
| 311 | |
| 312 scale = fz_mini(scalemin, scalemax); | |
| 313 r = y + (((r - y) * scale + 0x8000) >> 16); | |
| 314 g = y + (((g - y) * scale + 0x8000) >> 16); | |
| 315 b = y + (((b - y) * scale + 0x8000) >> 16); | |
| 316 } | |
| 317 | |
| 318 *rd = fz_clampi(r, 0, 255); | |
| 319 *gd = fz_clampi(g, 0, 255); | |
| 320 *bd = fz_clampi(b, 0, 255); | |
| 321 } | |
| 322 | |
| 323 static void | |
| 324 fz_color_rgb(unsigned char *rr, unsigned char *rg, unsigned char *rb, int br, int bg, int bb, int sr, int sg, int sb) | |
| 325 { | |
| 326 fz_luminosity_rgb(rr, rg, rb, sr, sg, sb, br, bg, bb); | |
| 327 } | |
| 328 | |
| 329 static void | |
| 330 fz_hue_rgb(unsigned char *rr, unsigned char *rg, unsigned char *rb, int br, int bg, int bb, int sr, int sg, int sb) | |
| 331 { | |
| 332 unsigned char tr, tg, tb; | |
| 333 fz_luminosity_rgb(&tr, &tg, &tb, sr, sg, sb, br, bg, bb); | |
| 334 fz_saturation_rgb(rr, rg, rb, tr, tg, tb, br, bg, bb); | |
| 335 } | |
| 336 | |
| 337 /* Blending loops */ | |
| 338 | |
| 339 static inline void | |
| 340 fz_blend_separable(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n1, int w, int blendmode, int complement, int first_spot) | |
| 341 { | |
| 342 int k; | |
| 343 do | |
| 344 { | |
| 345 int sa = (sal ? sp[n1] : 255); | |
| 346 | |
| 347 if (sa != 0) | |
| 348 { | |
| 349 int ba = (bal ? bp[n1] : 255); | |
| 350 if (ba == 0) | |
| 351 { | |
| 352 memcpy(bp, sp, n1 + (sal && bal)); | |
| 353 if (bal && !sal) | |
| 354 bp[n1+1] = 255; | |
| 355 } | |
| 356 else | |
| 357 { | |
| 358 int saba = fz_mul255(sa, ba); | |
| 359 | |
| 360 /* ugh, division to get non-premul components */ | |
| 361 int invsa = sa ? 255 * 256 / sa : 0; | |
| 362 int invba = ba ? 255 * 256 / ba : 0; | |
| 363 | |
| 364 /* Process colorants */ | |
| 365 for (k = 0; k < first_spot; k++) | |
| 366 { | |
| 367 int sc = (sp[k] * invsa) >> 8; | |
| 368 int bc = (bp[k] * invba) >> 8; | |
| 369 int rc; | |
| 370 | |
| 371 if (complement) | |
| 372 { | |
| 373 sc = 255 - sc; | |
| 374 bc = 255 - bc; | |
| 375 } | |
| 376 | |
| 377 switch (blendmode) | |
| 378 { | |
| 379 default: | |
| 380 case FZ_BLEND_NORMAL: rc = sc; break; | |
| 381 case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break; | |
| 382 case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break; | |
| 383 case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break; | |
| 384 case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break; | |
| 385 case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break; | |
| 386 case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break; | |
| 387 case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break; | |
| 388 case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break; | |
| 389 case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break; | |
| 390 case FZ_BLEND_DIFFERENCE: rc = fz_difference_byte(bc, sc); break; | |
| 391 case FZ_BLEND_EXCLUSION: rc = fz_exclusion_byte(bc, sc); break; | |
| 392 } | |
| 393 | |
| 394 if (complement) | |
| 395 { | |
| 396 rc = 255 - rc; | |
| 397 } | |
| 398 | |
| 399 bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, rc); | |
| 400 } | |
| 401 | |
| 402 /* spots */ | |
| 403 for (; k < n1; k++) | |
| 404 { | |
| 405 int sc = 255 - ((sp[k] * invsa) >> 8); | |
| 406 int bc = 255 - ((bp[k] * invba) >> 8); | |
| 407 int rc; | |
| 408 | |
| 409 switch (blendmode) | |
| 410 { | |
| 411 default: | |
| 412 case FZ_BLEND_NORMAL: | |
| 413 case FZ_BLEND_DIFFERENCE: | |
| 414 case FZ_BLEND_EXCLUSION: | |
| 415 rc = sc; break; | |
| 416 case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break; | |
| 417 case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break; | |
| 418 case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break; | |
| 419 case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break; | |
| 420 case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break; | |
| 421 case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break; | |
| 422 case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break; | |
| 423 case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break; | |
| 424 case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break; | |
| 425 } | |
| 426 bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, 255 - rc); | |
| 427 } | |
| 428 | |
| 429 if (bal) | |
| 430 bp[k] = ba + sa - saba; | |
| 431 } | |
| 432 } | |
| 433 sp += n1 + sal; | |
| 434 bp += n1 + bal; | |
| 435 } | |
| 436 while (--w); | |
| 437 } | |
| 438 | |
| 439 static inline void | |
| 440 fz_blend_nonseparable_gray(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n, int w, int blendmode, int first_spot) | |
| 441 { | |
| 442 do | |
| 443 { | |
| 444 int sa = (sal ? sp[n] : 255); | |
| 445 | |
| 446 if (sa != 0) | |
| 447 { | |
| 448 int ba = (bal ? bp[n] : 255); | |
| 449 if (ba == 0) | |
| 450 { | |
| 451 memcpy(bp, sp, n + (sal && bal)); | |
| 452 if (bal && !sal) | |
| 453 bp [n + 1] = 255; | |
| 454 } | |
| 455 else | |
| 456 { | |
| 457 int saba = fz_mul255(sa, ba); | |
| 458 | |
| 459 /* ugh, division to get non-premul components */ | |
| 460 int invsa = 255 * 256 / sa; | |
| 461 int invba = 255 * 256 / ba; | |
| 462 int k; | |
| 463 | |
| 464 switch (blendmode) | |
| 465 { | |
| 466 default: | |
| 467 case FZ_BLEND_HUE: | |
| 468 case FZ_BLEND_SATURATION: | |
| 469 case FZ_BLEND_COLOR: | |
| 470 { | |
| 471 int bg = (bp[0] * invba) >> 8; | |
| 472 bp[0] = fz_mul255(255 - sa, bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(saba, bg); | |
| 473 break; | |
| 474 } | |
| 475 case FZ_BLEND_LUMINOSITY: | |
| 476 { | |
| 477 int sg = (sp[0] * invsa) >> 8; | |
| 478 bp[0] = fz_mul255(255 - sa, bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(saba, sg); | |
| 479 break; | |
| 480 } | |
| 481 } | |
| 482 | |
| 483 /* Normal blend for spots */ | |
| 484 for (k = first_spot; k < n; k++) | |
| 485 { | |
| 486 int sc = (sp[k] * invsa) >> 8; | |
| 487 bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, sc); | |
| 488 } | |
| 489 if (bal) | |
| 490 bp[n] = ba + sa - saba; | |
| 491 } | |
| 492 } | |
| 493 sp += n + sal; | |
| 494 bp += n + bal; | |
| 495 } while (--w); | |
| 496 } | |
| 497 | |
| 498 static inline void | |
| 499 fz_blend_nonseparable(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n, int w, int blendmode, int complement, int first_spot) | |
| 500 { | |
| 501 do | |
| 502 { | |
| 503 unsigned char rr, rg, rb; | |
| 504 | |
| 505 int sa = (sal ? sp[n] : 255); | |
| 506 | |
| 507 if (sa != 0) | |
| 508 { | |
| 509 int ba = (bal ? bp[n] : 255); | |
| 510 if (ba == 0) | |
| 511 { | |
| 512 memcpy(bp, sp, n + (sal && bal)); | |
| 513 if (bal && !sal) | |
| 514 bp [n + 1] = 255; | |
| 515 } | |
| 516 else | |
| 517 { | |
| 518 int k; | |
| 519 int saba = fz_mul255(sa, ba); | |
| 520 | |
| 521 /* ugh, division to get non-premul components */ | |
| 522 int invsa = 255 * 256 / sa; | |
| 523 int invba = 255 * 256 / ba; | |
| 524 | |
| 525 int sr = (sp[0] * invsa) >> 8; | |
| 526 int sg = (sp[1] * invsa) >> 8; | |
| 527 int sb = (sp[2] * invsa) >> 8; | |
| 528 | |
| 529 int br = (bp[0] * invba) >> 8; | |
| 530 int bg = (bp[1] * invba) >> 8; | |
| 531 int bb = (bp[2] * invba) >> 8; | |
| 532 | |
| 533 /* CMYK */ | |
| 534 if (complement) | |
| 535 { | |
| 536 sr = 255 - sr; | |
| 537 sg = 255 - sg; | |
| 538 sb = 255 - sb; | |
| 539 br = 255 - br; | |
| 540 bg = 255 - bg; | |
| 541 bb = 255 - bb; | |
| 542 } | |
| 543 | |
| 544 switch (blendmode) | |
| 545 { | |
| 546 default: | |
| 547 case FZ_BLEND_HUE: | |
| 548 fz_hue_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb); | |
| 549 break; | |
| 550 case FZ_BLEND_SATURATION: | |
| 551 fz_saturation_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb); | |
| 552 break; | |
| 553 case FZ_BLEND_COLOR: | |
| 554 fz_color_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb); | |
| 555 break; | |
| 556 case FZ_BLEND_LUMINOSITY: | |
| 557 fz_luminosity_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb); | |
| 558 break; | |
| 559 } | |
| 560 | |
| 561 /* CMYK */ | |
| 562 if (complement) | |
| 563 { | |
| 564 rr = 255 - rr; | |
| 565 rg = 255 - rg; | |
| 566 rb = 255 - rb; | |
| 567 bp[0] = fz_mul255(255 - sa, bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(saba, rr); | |
| 568 bp[1] = fz_mul255(255 - sa, bp[1]) + fz_mul255(255 - ba, sp[1]) + fz_mul255(saba, rg); | |
| 569 bp[2] = fz_mul255(255 - sa, bp[2]) + fz_mul255(255 - ba, sp[2]) + fz_mul255(saba, rb); | |
| 570 | |
| 571 switch (blendmode) | |
| 572 { | |
| 573 default: | |
| 574 case FZ_BLEND_HUE: | |
| 575 case FZ_BLEND_SATURATION: | |
| 576 case FZ_BLEND_COLOR: | |
| 577 k = (bp[3] * invba) >> 8; | |
| 578 break; | |
| 579 case FZ_BLEND_LUMINOSITY: | |
| 580 k = (sp[3] * invsa) >> 8; | |
| 581 break; | |
| 582 } | |
| 583 bp[3] = fz_mul255(255 - sa, bp[3]) + fz_mul255(255 - ba, sp[3]) + fz_mul255(saba, k); | |
| 584 } | |
| 585 else | |
| 586 { | |
| 587 bp[0] = fz_mul255(255 - sa, bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(saba, rr); | |
| 588 bp[1] = fz_mul255(255 - sa, bp[1]) + fz_mul255(255 - ba, sp[1]) + fz_mul255(saba, rg); | |
| 589 bp[2] = fz_mul255(255 - sa, bp[2]) + fz_mul255(255 - ba, sp[2]) + fz_mul255(saba, rb); | |
| 590 } | |
| 591 | |
| 592 if (bal) | |
| 593 bp[n] = ba + sa - saba; | |
| 594 | |
| 595 /* Normal blend for spots */ | |
| 596 for (k = first_spot; k < n; k++) | |
| 597 { | |
| 598 int sc = (sp[k] * invsa) >> 8; | |
| 599 bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, sc); | |
| 600 } | |
| 601 } | |
| 602 } | |
| 603 sp += n + sal; | |
| 604 bp += n + bal; | |
| 605 } | |
| 606 while (--w); | |
| 607 } | |
| 608 | |
| 609 static inline void | |
| 610 fz_blend_separable_nonisolated(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n1, int w, int blendmode, int complement, const byte * FZ_RESTRICT hp, int alpha, int first_spot) | |
| 611 { | |
| 612 int k; | |
| 613 | |
| 614 if (sal == 0 && alpha == 255 && blendmode == 0) | |
| 615 { | |
| 616 /* In this case, the uncompositing and the recompositing | |
| 617 * cancel one another out, and it's just a simple copy. */ | |
| 618 /* FIXME: Maybe we can avoid using the shape plane entirely | |
| 619 * and just copy? */ | |
| 620 do | |
| 621 { | |
| 622 int ha = fz_mul255(*hp++, alpha); /* ha = shape_alpha */ | |
| 623 /* If ha == 0 then leave everything unchanged */ | |
| 624 if (ha != 0) | |
| 625 { | |
| 626 for (k = 0; k < n1; k++) | |
| 627 bp[k] = sp[k]; | |
| 628 if (bal) | |
| 629 bp[k] = 255; | |
| 630 } | |
| 631 | |
| 632 sp += n1; | |
| 633 bp += n1 + bal; | |
| 634 } | |
| 635 while (--w); | |
| 636 return; | |
| 637 } | |
| 638 do | |
| 639 { | |
| 640 int ha = *hp++; | |
| 641 int haa = fz_mul255(ha, alpha); /* ha = shape_alpha */ | |
| 642 /* If haa == 0 then leave everything unchanged */ | |
| 643 while (haa != 0) /* Use while, so we can break out */ | |
| 644 { | |
| 645 int sa, ba, bahaa, ra, ra0, invsa, invba, scale; | |
| 646 sa = (sal ? sp[n1] : 255); | |
| 647 if (sa == 0) | |
| 648 break; /* No change! */ | |
| 649 invsa = 255 * 256 / sa; | |
| 650 ba = (bal ? bp[n1] : 255); | |
| 651 if (ba == 0) | |
| 652 { | |
| 653 /* Just copy pixels (allowing for change in | |
| 654 * premultiplied alphas) */ | |
| 655 for (k = 0; k < n1; k++) | |
| 656 bp[k] = fz_mul255((sp[k] * invsa) >> 8, haa); | |
| 657 if (bal) | |
| 658 bp[n1] = haa; | |
| 659 break; | |
| 660 } | |
| 661 invba = 255 * 256 / ba; | |
| 662 | |
| 663 /* Because we are in a non-isolated group, we need to | |
| 664 * do some 'uncomposition' magic before we blend. | |
| 665 * My attempts to understand what is going on here have | |
| 666 * utterly failed, so I've resorted (after much patient | |
| 667 * help from Michael) to copying what the gs code does. | |
| 668 * This seems to be an implementation of the equations | |
| 669 * given on page 236 (section 7.3.3) of pdf_reference17. | |
| 670 * My understanding is that this is "composition" when | |
| 671 * we actually want to do "decomposition", hence my | |
| 672 * confusion. It appears to work though. | |
| 673 */ | |
| 674 scale = (512 * ba + ha) / (ha*2) - FZ_EXPAND(ba); | |
| 675 | |
| 676 sa = haa; | |
| 677 | |
| 678 /* Calculate result_alpha - a combination of the | |
| 679 * background alpha, and 'shape' */ | |
| 680 bahaa = fz_mul255(ba, haa); | |
| 681 ra0 = ba - bahaa; | |
| 682 ra = ra0 + haa; | |
| 683 if (bal) | |
| 684 bp[n1] = ra; | |
| 685 | |
| 686 if (ra == 0) | |
| 687 break; | |
| 688 | |
| 689 /* Process colorants */ | |
| 690 for (k = 0; k < first_spot; k++) | |
| 691 { | |
| 692 /* Read pixels (and convert to non-premultiplied form) */ | |
| 693 int sc = (sp[k] * invsa) >> 8; | |
| 694 int bc = (bp[k] * invba) >> 8; | |
| 695 int rc; | |
| 696 | |
| 697 if (complement) | |
| 698 { | |
| 699 sc = 255 - sc; | |
| 700 bc = 255 - bc; | |
| 701 } | |
| 702 | |
| 703 /* Uncomposite (see above) */ | |
| 704 sc = sc + (((sc-bc) * scale)>>8); | |
| 705 sc = fz_clampi(sc, 0, 255); | |
| 706 | |
| 707 switch (blendmode) | |
| 708 { | |
| 709 default: | |
| 710 case FZ_BLEND_NORMAL: rc = sc; break; | |
| 711 case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break; | |
| 712 case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break; | |
| 713 case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break; | |
| 714 case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break; | |
| 715 case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break; | |
| 716 case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break; | |
| 717 case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break; | |
| 718 case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break; | |
| 719 case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break; | |
| 720 case FZ_BLEND_DIFFERENCE: rc = fz_difference_byte(bc, sc); break; | |
| 721 case FZ_BLEND_EXCLUSION: rc = fz_exclusion_byte(bc, sc); break; | |
| 722 } | |
| 723 | |
| 724 /* From the notes at the top: | |
| 725 * | |
| 726 * Ar * Cr = Cb * (Ar - alpha * As) + alpha * As * (1 - Ab) * Cs + alpha * As * Ab * B(Cb, Cs) ] | |
| 727 * | |
| 728 * And: | |
| 729 * | |
| 730 * Ar = ba + haa - bahaa | |
| 731 * | |
| 732 * In our 0..255 world, with our current variables: | |
| 733 * | |
| 734 * ra.rc = bc * (ra - haa) + haa * (255 - ba) * sc + bahaa * B(Cb, Cs) | |
| 735 * = bc * ra0 + haa * (255 - ba) * sc + bahaa * B(Cb, Cs) | |
| 736 */ | |
| 737 | |
| 738 if (bahaa != 255) | |
| 739 rc = fz_mul255(bahaa, rc); | |
| 740 if (ba != 255) | |
| 741 { | |
| 742 int t = fz_mul255(255 - ba, haa); | |
| 743 rc += fz_mul255(t, sc); | |
| 744 } | |
| 745 if (ra0 != 0) | |
| 746 rc += fz_mul255(ra0, bc); | |
| 747 | |
| 748 if (complement) | |
| 749 rc = ra - rc; | |
| 750 | |
| 751 bp[k] = fz_clampi(rc, 0, ra); | |
| 752 } | |
| 753 | |
| 754 /* Spots */ | |
| 755 for (; k < n1; k++) | |
| 756 { | |
| 757 int sc = 255 - ((sp[k] * invsa + 128) >> 8); | |
| 758 int bc = 255 - ((bp[k] * invba + 128) >> 8); | |
| 759 int rc; | |
| 760 | |
| 761 sc = sc + (((sc-bc) * scale)>>8); | |
| 762 | |
| 763 /* Non-white preserving use Normal */ | |
| 764 switch (blendmode) | |
| 765 { | |
| 766 default: | |
| 767 case FZ_BLEND_NORMAL: | |
| 768 case FZ_BLEND_DIFFERENCE: | |
| 769 case FZ_BLEND_EXCLUSION: | |
| 770 rc = sc; break; | |
| 771 case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break; | |
| 772 case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break; | |
| 773 case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break; | |
| 774 case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break; | |
| 775 case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break; | |
| 776 case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break; | |
| 777 case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break; | |
| 778 case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break; | |
| 779 case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break; | |
| 780 } | |
| 781 | |
| 782 if (bahaa != 255) | |
| 783 rc = fz_mul255(bahaa, rc); | |
| 784 if (ba != 255) | |
| 785 { | |
| 786 int t = fz_mul255(255 - ba, haa); | |
| 787 rc += fz_mul255(t, sc); | |
| 788 } | |
| 789 if (ra0 != 0) | |
| 790 rc += fz_mul255(ra0, bc); | |
| 791 | |
| 792 bp[k] = ra - rc; | |
| 793 } | |
| 794 break; | |
| 795 } | |
| 796 | |
| 797 sp += n1 + sal; | |
| 798 bp += n1 + bal; | |
| 799 } | |
| 800 while (--w); | |
| 801 } | |
| 802 | |
| 803 static inline void | |
| 804 fz_blend_nonseparable_nonisolated_gray(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n, int w, int blendmode, const byte * FZ_RESTRICT hp, int alpha, int first_spot) | |
| 805 { | |
| 806 do | |
| 807 { | |
| 808 int ha = *hp++; | |
| 809 int haa = fz_mul255(ha, alpha); | |
| 810 if (haa != 0) | |
| 811 { | |
| 812 int ba = (bal ? bp[n] : 255); | |
| 813 | |
| 814 if (ba == 0 && alpha == 255) | |
| 815 { | |
| 816 memcpy(bp, sp, n + (sal && bal)); | |
| 817 if (bal && !sal) | |
| 818 bp[n+1] = 255; | |
| 819 } | |
| 820 else | |
| 821 { | |
| 822 int sa = (sal ? sp[n] : 255); | |
| 823 int bahaa = fz_mul255(ba, haa); | |
| 824 int k; | |
| 825 | |
| 826 /* Calculate result_alpha */ | |
| 827 int ra = ba - bahaa + haa; | |
| 828 if (bal) | |
| 829 bp[n] = ra; | |
| 830 if (ra != 0) | |
| 831 { | |
| 832 int invha = ha ? 255 * 256 / ha : 0; | |
| 833 | |
| 834 /* ugh, division to get non-premul components */ | |
| 835 int invsa = sa ? 255 * 256 / sa : 0; | |
| 836 int invba = ba ? 255 * 256 / ba : 0; | |
| 837 | |
| 838 int sg = (sp[0] * invsa) >> 8; | |
| 839 int bg = (bp[0] * invba) >> 8; | |
| 840 | |
| 841 /* Uncomposite */ | |
| 842 sg = (((sg - bg)*invha) >> 8) + bg; | |
| 843 sg = fz_clampi(sg, 0, 255); | |
| 844 | |
| 845 switch (blendmode) | |
| 846 { | |
| 847 default: | |
| 848 case FZ_BLEND_HUE: | |
| 849 case FZ_BLEND_SATURATION: | |
| 850 case FZ_BLEND_COLOR: | |
| 851 bp[0] = fz_mul255(ra, bg); | |
| 852 break; | |
| 853 case FZ_BLEND_LUMINOSITY: | |
| 854 bp[0] = fz_mul255(ra, sg); | |
| 855 break; | |
| 856 } | |
| 857 | |
| 858 /* Normal blend for spots */ | |
| 859 for (k = first_spot; k < n; k++) | |
| 860 { | |
| 861 int sc = (sp[k] * invsa + 128) >> 8; | |
| 862 int bc = (bp[k] * invba + 128) >> 8; | |
| 863 int rc; | |
| 864 | |
| 865 sc = (((sc - bc) * invha + 128) >> 8) + bc; | |
| 866 sc = fz_clampi(sc, 0, 255); | |
| 867 rc = bc + fz_mul255(sa, fz_mul255(255 - ba, sc) + fz_mul255(ba, sc) - bc); | |
| 868 rc = fz_clampi(rc, 0, 255); | |
| 869 bp[k] = fz_mul255(rc, ra); | |
| 870 } | |
| 871 } | |
| 872 } | |
| 873 } | |
| 874 sp += n + sal; | |
| 875 bp += n + bal; | |
| 876 } while (--w); | |
| 877 } | |
| 878 | |
| 879 static inline void | |
| 880 fz_blend_nonseparable_nonisolated(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n, int w, int blendmode, int complement, const byte * FZ_RESTRICT hp, int alpha, int first_spot) | |
| 881 { | |
| 882 do | |
| 883 { | |
| 884 int ha = *hp++; | |
| 885 int haa = fz_mul255(ha, alpha); | |
| 886 if (haa != 0) | |
| 887 { | |
| 888 int sa = (sal ? sp[n] : 255); | |
| 889 int ba = (bal ? bp[n] : 255); | |
| 890 | |
| 891 if (ba == 0 && alpha == 255) | |
| 892 { | |
| 893 memcpy(bp, sp, n + (sal && bal)); | |
| 894 if (bal && !sal) | |
| 895 bp[n] = 255; | |
| 896 } | |
| 897 else | |
| 898 { | |
| 899 int bahaa = fz_mul255(ba, haa); | |
| 900 | |
| 901 /* Calculate result_alpha */ | |
| 902 int ra0 = ba - bahaa; | |
| 903 int ra = ra0 + haa; | |
| 904 | |
| 905 if (bal) | |
| 906 bp[n] = ra; | |
| 907 | |
| 908 if (ra != 0) | |
| 909 { | |
| 910 /* Because we are a non-isolated group, we | |
| 911 * need to 'uncomposite' before we blend | |
| 912 * (recomposite). We assume that normal | |
| 913 * blending has been done inside the group, | |
| 914 * so: ra.rc = (1-ha).bc + ha.sc | |
| 915 * A bit of rearrangement, and that gives us | |
| 916 * that: sc = (ra.rc - bc)/ha + bc | |
| 917 * Now, the result of the blend was stored in | |
| 918 * src, so: */ | |
| 919 int invha = ha ? 255 * 256 / ha : 0; | |
| 920 int k; | |
| 921 unsigned char rr, rg, rb; | |
| 922 | |
| 923 /* ugh, division to get non-premul components */ | |
| 924 int invsa = sa ? 255 * 256 / sa : 0; | |
| 925 int invba = ba ? 255 * 256 / ba : 0; | |
| 926 | |
| 927 int sr = (sp[0] * invsa) >> 8; | |
| 928 int sg = (sp[1] * invsa) >> 8; | |
| 929 int sb = (sp[2] * invsa) >> 8; | |
| 930 | |
| 931 int br = (bp[0] * invba) >> 8; | |
| 932 int bg = (bp[1] * invba) >> 8; | |
| 933 int bb = (bp[2] * invba) >> 8; | |
| 934 | |
| 935 if (complement) | |
| 936 { | |
| 937 sr = 255 - sr; | |
| 938 sg = 255 - sg; | |
| 939 sb = 255 - sb; | |
| 940 br = 255 - br; | |
| 941 bg = 255 - bg; | |
| 942 bb = 255 - bb; | |
| 943 } | |
| 944 | |
| 945 /* Uncomposite */ | |
| 946 sr = (((sr - br)*invha) >> 8) + br; | |
| 947 sr = fz_clampi(sr, 0, 255); | |
| 948 sg = (((sg - bg)*invha) >> 8) + bg; | |
| 949 sg = fz_clampi(sg, 0, 255); | |
| 950 sb = (((sb - bb)*invha) >> 8) + bb; | |
| 951 sb = fz_clampi(sb, 0, 255); | |
| 952 | |
| 953 switch (blendmode) | |
| 954 { | |
| 955 default: | |
| 956 case FZ_BLEND_HUE: | |
| 957 fz_hue_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb); | |
| 958 break; | |
| 959 case FZ_BLEND_SATURATION: | |
| 960 fz_saturation_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb); | |
| 961 break; | |
| 962 case FZ_BLEND_COLOR: | |
| 963 fz_color_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb); | |
| 964 break; | |
| 965 case FZ_BLEND_LUMINOSITY: | |
| 966 fz_luminosity_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb); | |
| 967 break; | |
| 968 } | |
| 969 | |
| 970 /* From the notes at the top: | |
| 971 * | |
| 972 * Ar * Cr = Cb * (Ar - alpha * As) + alpha * As * (1 - Ab) * Cs + alpha * As * Ab * B(Cb, Cs) ] | |
| 973 * | |
| 974 * And: | |
| 975 * | |
| 976 * Ar = ba + haa - bahaa | |
| 977 * | |
| 978 * In our 0..255 world, with our current variables: | |
| 979 * | |
| 980 * ra.rc = bc * (ra - haa) + haa * (255 - ba) * sc + bahaa * B(Cb, Cs) | |
| 981 * = bc * ra0 + haa * (255 - ba) * sc + bahaa * B(Cb, Cs) | |
| 982 */ | |
| 983 | |
| 984 if (bahaa != 255) | |
| 985 { | |
| 986 rr = fz_mul255(bahaa, rr); | |
| 987 rg = fz_mul255(bahaa, rg); | |
| 988 rb = fz_mul255(bahaa, rb); | |
| 989 } | |
| 990 if (ba != 255) | |
| 991 { | |
| 992 int t = fz_mul255(255 - ba, haa); | |
| 993 rr += fz_mul255(t, sr); | |
| 994 rg += fz_mul255(t, sg); | |
| 995 rb += fz_mul255(t, sb); | |
| 996 } | |
| 997 if (ra0 != 0) | |
| 998 { | |
| 999 rr += fz_mul255(ra0, br); | |
| 1000 rg += fz_mul255(ra0, bg); | |
| 1001 rb += fz_mul255(ra0, bb); | |
| 1002 } | |
| 1003 | |
| 1004 /* CMYK */ | |
| 1005 if (complement) | |
| 1006 { | |
| 1007 int sk, bk, rk; | |
| 1008 | |
| 1009 /* Care must be taking when inverting here, as r = alpha * col. | |
| 1010 * We want to store alpha * (255 - col) = alpha * 255 - alpha * col | |
| 1011 */ | |
| 1012 rr = ra - rr; | |
| 1013 rg = ra - rg; | |
| 1014 rb = ra - rb; | |
| 1015 | |
| 1016 sk = sa ? (sp[3] * invsa) >> 8 : 255; | |
| 1017 bk = ba ? (bp[3] * invba) >> 8 : 255; | |
| 1018 | |
| 1019 bk = fz_clampi(bk, 0, 255); | |
| 1020 sk = fz_clampi(sk, 0, 255); | |
| 1021 | |
| 1022 if (blendmode == FZ_BLEND_LUMINOSITY) | |
| 1023 rk = sk; | |
| 1024 else | |
| 1025 rk = bk; | |
| 1026 | |
| 1027 if (bahaa != 255) | |
| 1028 rk = fz_mul255(bahaa, rk); | |
| 1029 | |
| 1030 if (ba != 255) | |
| 1031 { | |
| 1032 int t = fz_mul255(255 - ba, haa); | |
| 1033 rk += fz_mul255(t, sk); | |
| 1034 } | |
| 1035 | |
| 1036 if (ra0 != 0) | |
| 1037 rk += fz_mul255(ra0, bk); | |
| 1038 | |
| 1039 bp[3] = rk; | |
| 1040 } | |
| 1041 | |
| 1042 bp[0] = rr; | |
| 1043 bp[1] = rg; | |
| 1044 bp[2] = rb; | |
| 1045 | |
| 1046 /* Normal blend for spots */ | |
| 1047 for (k = first_spot; k < n; k++) | |
| 1048 { | |
| 1049 int sc = (sp[k] * invsa + 128) >> 8; | |
| 1050 int bc = (bp[k] * invba + 128) >> 8; | |
| 1051 int rc; | |
| 1052 | |
| 1053 sc = (((sc - bc) * invha + 128) >> 8) + bc; | |
| 1054 sc = fz_clampi(sc, 0, 255); | |
| 1055 rc = bc + fz_mul255(ha, fz_mul255(255 - ba, sc) + fz_mul255(ba, sc) - bc); | |
| 1056 rc = fz_clampi(rc, 0, 255); | |
| 1057 bp[k] = fz_mul255(rc, ra); | |
| 1058 } | |
| 1059 } | |
| 1060 } | |
| 1061 } | |
| 1062 sp += n + sal; | |
| 1063 bp += n + bal; | |
| 1064 } | |
| 1065 while (--w); | |
| 1066 } | |
| 1067 | |
| 1068 #ifdef PARANOID_PREMULTIPLY | |
| 1069 static void | |
| 1070 verify_premultiply(fz_context *ctx, const fz_pixmap * FZ_RESTRICT dst) | |
| 1071 { | |
| 1072 unsigned char *dp = dst->samples; | |
| 1073 int w = dst->w; | |
| 1074 int h = dst->h; | |
| 1075 int n = dst->n; | |
| 1076 int x, y, i; | |
| 1077 int s = dst->stride - n * w; | |
| 1078 | |
| 1079 for (y = h; y > 0; y--) | |
| 1080 { | |
| 1081 for (x = w; x > 0; x--) | |
| 1082 { | |
| 1083 int a = dp[n-1]; | |
| 1084 for (i = n-1; i > 0; i--) | |
| 1085 if (*dp++ > a) | |
| 1086 abort(); | |
| 1087 dp++; | |
| 1088 } | |
| 1089 dp += s; | |
| 1090 } | |
| 1091 } | |
| 1092 #endif | |
| 1093 | |
| 1094 void | |
| 1095 fz_blend_pixmap(fz_context *ctx, fz_pixmap * FZ_RESTRICT dst, fz_pixmap * FZ_RESTRICT src, int alpha, int blendmode, int isolated, const fz_pixmap * FZ_RESTRICT shape) | |
| 1096 { | |
| 1097 unsigned char *sp; | |
| 1098 unsigned char *dp; | |
| 1099 fz_irect bbox; | |
| 1100 int x, y, w, h, n; | |
| 1101 int da, sa; | |
| 1102 int complement; | |
| 1103 | |
| 1104 /* TODO: fix this hack! */ | |
| 1105 if (isolated && alpha < 255) | |
| 1106 { | |
| 1107 unsigned char *sp2; | |
| 1108 int nn; | |
| 1109 h = src->h; | |
| 1110 sp2 = src->samples; | |
| 1111 nn = src->w * src->n; | |
| 1112 while (h--) | |
| 1113 { | |
| 1114 n = nn; | |
| 1115 while (n--) | |
| 1116 { | |
| 1117 *sp2 = fz_mul255(*sp2, alpha); | |
| 1118 sp2++; | |
| 1119 } | |
| 1120 sp2 += src->stride - nn; | |
| 1121 } | |
| 1122 } | |
| 1123 | |
| 1124 bbox = fz_intersect_irect(fz_pixmap_bbox(ctx, src), fz_pixmap_bbox(ctx, dst)); | |
| 1125 | |
| 1126 x = bbox.x0; | |
| 1127 y = bbox.y0; | |
| 1128 w = fz_irect_width(bbox); | |
| 1129 h = fz_irect_height(bbox); | |
| 1130 if (w == 0 || h == 0) | |
| 1131 return; | |
| 1132 | |
| 1133 complement = fz_colorspace_is_subtractive(ctx, src->colorspace); | |
| 1134 n = src->n; | |
| 1135 sp = src->samples + (y - src->y) * (size_t)src->stride + (x - src->x) * (size_t)src->n; | |
| 1136 sa = src->alpha; | |
| 1137 dp = dst->samples + (y - dst->y) * (size_t)dst->stride + (x - dst->x) * (size_t)dst->n; | |
| 1138 da = dst->alpha; | |
| 1139 | |
| 1140 if (n == 1) | |
| 1141 sa = da = 0; | |
| 1142 | |
| 1143 #ifdef PARANOID_PREMULTIPLY | |
| 1144 if (sa) | |
| 1145 verify_premultiply(ctx, src); | |
| 1146 if (da) | |
| 1147 verify_premultiply(ctx, dst); | |
| 1148 #endif | |
| 1149 | |
| 1150 n -= sa; | |
| 1151 assert(n == dst->n - da); | |
| 1152 | |
| 1153 if (!isolated) | |
| 1154 { | |
| 1155 const unsigned char *hp = shape->samples + (y - shape->y) * (size_t)shape->stride + (x - shape->x); | |
| 1156 | |
| 1157 while (h--) | |
| 1158 { | |
| 1159 if (blendmode >= FZ_BLEND_HUE) | |
| 1160 { | |
| 1161 if (complement || src->s > 0) | |
| 1162 if ((n - src->s) == 1) | |
| 1163 fz_blend_nonseparable_nonisolated_gray(dp, da, sp, sa, n, w, blendmode, hp, alpha, 1); | |
| 1164 else | |
| 1165 fz_blend_nonseparable_nonisolated(dp, da, sp, sa, n, w, blendmode, complement, hp, alpha, n - src->s); | |
| 1166 else | |
| 1167 if (da) | |
| 1168 if (sa) | |
| 1169 if (n == 1) | |
| 1170 fz_blend_nonseparable_nonisolated_gray(dp, 1, sp, 1, 1, w, blendmode, hp, alpha, 1); | |
| 1171 else | |
| 1172 fz_blend_nonseparable_nonisolated(dp, 1, sp, 1, n, w, blendmode, complement, hp, alpha, n); | |
| 1173 else | |
| 1174 if (n == 1) | |
| 1175 fz_blend_nonseparable_nonisolated_gray(dp, 1, sp, 0, 1, w, blendmode, hp, alpha, 1); | |
| 1176 else | |
| 1177 fz_blend_nonseparable_nonisolated(dp, 1, sp, 0, n, w, blendmode, complement, hp, alpha, n); | |
| 1178 else | |
| 1179 if (sa) | |
| 1180 if (n == 1) | |
| 1181 fz_blend_nonseparable_nonisolated_gray(dp, 0, sp, 1, 1, w, blendmode, hp, alpha, 1); | |
| 1182 else | |
| 1183 fz_blend_nonseparable_nonisolated(dp, 0, sp, 1, n, w, blendmode, complement, hp, alpha, n); | |
| 1184 else | |
| 1185 if (n == 1) | |
| 1186 fz_blend_nonseparable_nonisolated_gray(dp, 0, sp, 0, 1, w, blendmode, hp, alpha, 1); | |
| 1187 else | |
| 1188 fz_blend_nonseparable_nonisolated(dp, 0, sp, 0, n, w, blendmode, complement, hp, alpha, n); | |
| 1189 } | |
| 1190 else | |
| 1191 { | |
| 1192 if (complement || src->s > 0) | |
| 1193 fz_blend_separable_nonisolated(dp, da, sp, sa, n, w, blendmode, complement, hp, alpha, n - src->s); | |
| 1194 else | |
| 1195 if (da) | |
| 1196 if (sa) | |
| 1197 fz_blend_separable_nonisolated(dp, 1, sp, 1, n, w, blendmode, 0, hp, alpha, n); | |
| 1198 else | |
| 1199 fz_blend_separable_nonisolated(dp, 1, sp, 0, n, w, blendmode, 0, hp, alpha, n); | |
| 1200 else | |
| 1201 if (sa) | |
| 1202 fz_blend_separable_nonisolated(dp, 0, sp, 1, n, w, blendmode, 0, hp, alpha, n); | |
| 1203 else | |
| 1204 fz_blend_separable_nonisolated(dp, 0, sp, 0, n, w, blendmode, 0, hp, alpha, n); | |
| 1205 } | |
| 1206 sp += src->stride; | |
| 1207 dp += dst->stride; | |
| 1208 hp += shape->stride; | |
| 1209 } | |
| 1210 } | |
| 1211 else | |
| 1212 { | |
| 1213 while (h--) | |
| 1214 { | |
| 1215 if (blendmode >= FZ_BLEND_HUE) | |
| 1216 { | |
| 1217 if (complement || src->s > 0) | |
| 1218 if ((n - src->s) == 1) | |
| 1219 fz_blend_nonseparable_gray(dp, da, sp, sa, n, w, blendmode, 1); | |
| 1220 else | |
| 1221 fz_blend_nonseparable(dp, da, sp, sa, n, w, blendmode, complement, n - src->s); | |
| 1222 else | |
| 1223 if (da) | |
| 1224 if (sa) | |
| 1225 if (n == 1) | |
| 1226 fz_blend_nonseparable_gray(dp, 1, sp, 1, 1, w, blendmode, 1); | |
| 1227 else | |
| 1228 fz_blend_nonseparable(dp, 1, sp, 1, n, w, blendmode, complement, n); | |
| 1229 else | |
| 1230 if (n == 1) | |
| 1231 fz_blend_nonseparable_gray(dp, 1, sp, 0, 1, w, blendmode, 1); | |
| 1232 else | |
| 1233 fz_blend_nonseparable(dp, 1, sp, 0, n, w, blendmode, complement, n); | |
| 1234 else | |
| 1235 if (sa) | |
| 1236 if (n == 1) | |
| 1237 fz_blend_nonseparable_gray(dp, 0, sp, 1, 1, w, blendmode, 1); | |
| 1238 else | |
| 1239 fz_blend_nonseparable(dp, 0, sp, 1, n, w, blendmode, complement, n); | |
| 1240 else | |
| 1241 if (n == 1) | |
| 1242 fz_blend_nonseparable_gray(dp, 0, sp, 0, 1, w, blendmode, 1); | |
| 1243 else | |
| 1244 fz_blend_nonseparable(dp, 0, sp, 0, n, w, blendmode, complement, n); | |
| 1245 } | |
| 1246 else | |
| 1247 { | |
| 1248 if (complement || src->s > 0) | |
| 1249 fz_blend_separable(dp, da, sp, sa, n, w, blendmode, complement, n - src->s); | |
| 1250 else | |
| 1251 if (da) | |
| 1252 if (sa) | |
| 1253 fz_blend_separable(dp, 1, sp, 1, n, w, blendmode, 0, n); | |
| 1254 else | |
| 1255 fz_blend_separable(dp, 1, sp, 0, n, w, blendmode, 0, n); | |
| 1256 else | |
| 1257 if (sa) | |
| 1258 fz_blend_separable(dp, 0, sp, 1, n, w, blendmode, 0, n); | |
| 1259 else | |
| 1260 fz_blend_separable(dp, 0, sp, 0, n, w, blendmode, 0, n); | |
| 1261 } | |
| 1262 sp += src->stride; | |
| 1263 dp += dst->stride; | |
| 1264 } | |
| 1265 } | |
| 1266 | |
| 1267 #ifdef PARANOID_PREMULTIPLY | |
| 1268 if (da) | |
| 1269 verify_premultiply(ctx, dst); | |
| 1270 #endif | |
| 1271 } | |
| 1272 | |
| 1273 static inline void | |
| 1274 fz_blend_knockout(byte * FZ_RESTRICT bp, int bal, const byte * FZ_RESTRICT sp, int sal, int n1, int w, const byte * FZ_RESTRICT hp) | |
| 1275 { | |
| 1276 int k; | |
| 1277 do | |
| 1278 { | |
| 1279 int ha = *hp++; | |
| 1280 | |
| 1281 if (ha != 0) | |
| 1282 { | |
| 1283 int sa = (sal ? sp[n1] : 255); | |
| 1284 int ba = (bal ? bp[n1] : 255); | |
| 1285 if (ba == 0 && ha == 0xFF) | |
| 1286 { | |
| 1287 memcpy(bp, sp, n1); | |
| 1288 if (bal) | |
| 1289 bp[n1] = sa; | |
| 1290 } | |
| 1291 else | |
| 1292 { | |
| 1293 int hasa = fz_mul255(ha, sa); | |
| 1294 /* ugh, division to get non-premul components */ | |
| 1295 int invsa = sa ? 255 * 256 / sa : 0; | |
| 1296 int invba = ba ? 255 * 256 / ba : 0; | |
| 1297 int ra = hasa + fz_mul255(255-ha, ba); | |
| 1298 | |
| 1299 /* Process colorants + spots */ | |
| 1300 for (k = 0; k < n1; k++) | |
| 1301 { | |
| 1302 int sc = (sp[k] * invsa) >> 8; | |
| 1303 int bc = (bp[k] * invba) >> 8; | |
| 1304 int rc = fz_mul255(255 - ha, bc) + fz_mul255(ha, sc); | |
| 1305 | |
| 1306 bp[k] = fz_mul255(ra, rc); | |
| 1307 } | |
| 1308 | |
| 1309 if (bal) | |
| 1310 bp[k] = ra; | |
| 1311 } | |
| 1312 } | |
| 1313 sp += n1 + sal; | |
| 1314 bp += n1 + bal; | |
| 1315 } | |
| 1316 while (--w); | |
| 1317 } | |
| 1318 | |
| 1319 void | |
| 1320 fz_blend_pixmap_knockout(fz_context *ctx, fz_pixmap * FZ_RESTRICT dst, fz_pixmap * FZ_RESTRICT src, const fz_pixmap * FZ_RESTRICT shape) | |
| 1321 { | |
| 1322 unsigned char *sp; | |
| 1323 unsigned char *dp; | |
| 1324 fz_irect sbox, dbox, bbox; | |
| 1325 int x, y, w, h, n; | |
| 1326 int da, sa; | |
| 1327 const unsigned char *hp; | |
| 1328 | |
| 1329 dbox = fz_pixmap_bbox_no_ctx(dst); | |
| 1330 sbox = fz_pixmap_bbox_no_ctx(src); | |
| 1331 bbox = fz_intersect_irect(dbox, sbox); | |
| 1332 | |
| 1333 x = bbox.x0; | |
| 1334 y = bbox.y0; | |
| 1335 w = fz_irect_width(bbox); | |
| 1336 h = fz_irect_height(bbox); | |
| 1337 if (w == 0 || h == 0) | |
| 1338 return; | |
| 1339 | |
| 1340 n = src->n; | |
| 1341 sp = src->samples + (y - src->y) * (size_t)src->stride + (x - src->x) * (size_t)src->n; | |
| 1342 sa = src->alpha; | |
| 1343 dp = dst->samples + (y - dst->y) * (size_t)dst->stride + (x - dst->x) * (size_t)dst->n; | |
| 1344 da = dst->alpha; | |
| 1345 hp = shape->samples + (y - shape->y) * (size_t)shape->stride + (x - shape->x); | |
| 1346 | |
| 1347 #ifdef PARANOID_PREMULTIPLY | |
| 1348 if (sa) | |
| 1349 verify_premultiply(ctx, src); | |
| 1350 if (da) | |
| 1351 verify_premultiply(ctx, dst); | |
| 1352 #endif | |
| 1353 | |
| 1354 n -= sa; | |
| 1355 assert(n == dst->n - da); | |
| 1356 | |
| 1357 while (h--) | |
| 1358 { | |
| 1359 fz_blend_knockout(dp, da, sp, sa, n, w, hp); | |
| 1360 sp += src->stride; | |
| 1361 dp += dst->stride; | |
| 1362 hp += shape->stride; | |
| 1363 } | |
| 1364 | |
| 1365 #ifdef PARANOID_PREMULTIPLY | |
| 1366 if (da) | |
| 1367 verify_premultiply(ctx, dst); | |
| 1368 #endif | |
| 1369 } |
