| 1 | /* |
| 2 | * Copyright (c) 2020 - 2023 the ThorVG project. All rights reserved. |
| 3 | |
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 5 | * of this software and associated documentation files (the "Software"), to deal |
| 6 | * in the Software without restriction, including without limitation the rights |
| 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 8 | * copies of the Software, and to permit persons to whom the Software is |
| 9 | * furnished to do so, subject to the following conditions: |
| 10 | |
| 11 | * The above copyright notice and this permission notice shall be included in all |
| 12 | * copies or substantial portions of the Software. |
| 13 | |
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 20 | * SOFTWARE. |
| 21 | */ |
| 22 | |
| 23 | #ifndef _TVG_SW_COMMON_H_ |
| 24 | #define _TVG_SW_COMMON_H_ |
| 25 | |
| 26 | #include "tvgCommon.h" |
| 27 | #include "tvgRender.h" |
| 28 | |
| 29 | #if 0 |
| 30 | #include <sys/time.h> |
| 31 | static double timeStamp() |
| 32 | { |
| 33 | struct timeval tv; |
| 34 | gettimeofday(&tv, NULL); |
| 35 | return (tv.tv_sec + tv.tv_usec / 1000000.0); |
| 36 | } |
| 37 | #endif |
| 38 | |
| 39 | #define SW_CURVE_TYPE_POINT 0 |
| 40 | #define SW_CURVE_TYPE_CUBIC 1 |
| 41 | #define SW_ANGLE_PI (180L << 16) |
| 42 | #define SW_ANGLE_2PI (SW_ANGLE_PI << 1) |
| 43 | #define SW_ANGLE_PI2 (SW_ANGLE_PI >> 1) |
| 44 | #define SW_ANGLE_PI4 (SW_ANGLE_PI >> 2) |
| 45 | |
| 46 | using SwCoord = signed long; |
| 47 | using SwFixed = signed long long; |
| 48 | |
| 49 | struct SwPoint |
| 50 | { |
| 51 | SwCoord x, y; |
| 52 | |
| 53 | SwPoint& operator+=(const SwPoint& rhs) |
| 54 | { |
| 55 | x += rhs.x; |
| 56 | y += rhs.y; |
| 57 | return *this; |
| 58 | } |
| 59 | |
| 60 | SwPoint operator+(const SwPoint& rhs) const |
| 61 | { |
| 62 | return {x + rhs.x, y + rhs.y}; |
| 63 | } |
| 64 | |
| 65 | SwPoint operator-(const SwPoint& rhs) const |
| 66 | { |
| 67 | return {x - rhs.x, y - rhs.y}; |
| 68 | } |
| 69 | |
| 70 | bool operator==(const SwPoint& rhs) const |
| 71 | { |
| 72 | return (x == rhs.x && y == rhs.y); |
| 73 | } |
| 74 | |
| 75 | bool operator!=(const SwPoint& rhs) const |
| 76 | { |
| 77 | return (x != rhs.x || y != rhs.y); |
| 78 | } |
| 79 | |
| 80 | bool zero() const |
| 81 | { |
| 82 | if (x == 0 && y == 0) return true; |
| 83 | else return false; |
| 84 | } |
| 85 | |
| 86 | bool small() const |
| 87 | { |
| 88 | //2 is epsilon... |
| 89 | if (abs(x) < 2 && abs(y) < 2) return true; |
| 90 | else return false; |
| 91 | } |
| 92 | |
| 93 | }; |
| 94 | |
| 95 | struct SwSize |
| 96 | { |
| 97 | SwCoord w, h; |
| 98 | }; |
| 99 | |
| 100 | struct SwOutline |
| 101 | { |
| 102 | Array<SwPoint> pts; //the outline's points |
| 103 | Array<uint32_t> cntrs; //the contour end points |
| 104 | Array<uint8_t> types; //curve type |
| 105 | Array<bool> closed; //opened or closed path? |
| 106 | FillRule fillRule; |
| 107 | }; |
| 108 | |
| 109 | struct SwSpan |
| 110 | { |
| 111 | uint16_t x, y; |
| 112 | uint16_t len; |
| 113 | uint8_t coverage; |
| 114 | }; |
| 115 | |
| 116 | struct SwRleData |
| 117 | { |
| 118 | SwSpan *spans; |
| 119 | uint32_t alloc; |
| 120 | uint32_t size; |
| 121 | }; |
| 122 | |
| 123 | struct SwBBox |
| 124 | { |
| 125 | SwPoint min, max; |
| 126 | |
| 127 | void reset() |
| 128 | { |
| 129 | min.x = min.y = max.x = max.y = 0; |
| 130 | } |
| 131 | }; |
| 132 | |
| 133 | struct SwFill |
| 134 | { |
| 135 | struct SwLinear { |
| 136 | float dx, dy; |
| 137 | float len; |
| 138 | float offset; |
| 139 | }; |
| 140 | |
| 141 | struct SwRadial { |
| 142 | float a11, a12, shiftX; |
| 143 | float a21, a22, shiftY; |
| 144 | float detSecDeriv; |
| 145 | float a; |
| 146 | }; |
| 147 | |
| 148 | union { |
| 149 | SwLinear linear; |
| 150 | SwRadial radial; |
| 151 | }; |
| 152 | |
| 153 | uint32_t* ctable; |
| 154 | FillSpread spread; |
| 155 | |
| 156 | bool translucent; |
| 157 | }; |
| 158 | |
| 159 | struct SwStrokeBorder |
| 160 | { |
| 161 | uint32_t ptsCnt; |
| 162 | uint32_t maxPts; |
| 163 | SwPoint* pts; |
| 164 | uint8_t* tags; |
| 165 | int32_t start; //index of current sub-path start point |
| 166 | bool movable; //true: for ends of lineto borders |
| 167 | }; |
| 168 | |
| 169 | struct SwStroke |
| 170 | { |
| 171 | SwFixed angleIn; |
| 172 | SwFixed angleOut; |
| 173 | SwPoint center; |
| 174 | SwFixed lineLength; |
| 175 | SwFixed subPathAngle; |
| 176 | SwPoint ptStartSubPath; |
| 177 | SwFixed subPathLineLength; |
| 178 | SwFixed width; |
| 179 | SwFixed miterlimit; |
| 180 | |
| 181 | StrokeCap cap; |
| 182 | StrokeJoin join; |
| 183 | StrokeJoin joinSaved; |
| 184 | SwFill* fill = nullptr; |
| 185 | |
| 186 | SwStrokeBorder borders[2]; |
| 187 | |
| 188 | float sx, sy; |
| 189 | |
| 190 | bool firstPt; |
| 191 | bool closedSubPath; |
| 192 | bool handleWideStrokes; |
| 193 | }; |
| 194 | |
| 195 | struct SwDashStroke |
| 196 | { |
| 197 | SwOutline* outline; |
| 198 | float curLen; |
| 199 | int32_t curIdx; |
| 200 | Point ptStart; |
| 201 | Point ptCur; |
| 202 | float* pattern; |
| 203 | uint32_t cnt; |
| 204 | bool curOpGap; |
| 205 | }; |
| 206 | |
| 207 | struct SwShape |
| 208 | { |
| 209 | SwOutline* outline = nullptr; |
| 210 | SwStroke* stroke = nullptr; |
| 211 | SwFill* fill = nullptr; |
| 212 | SwRleData* rle = nullptr; |
| 213 | SwRleData* strokeRle = nullptr; |
| 214 | SwBBox bbox; //Keep it boundary without stroke region. Using for optimal filling. |
| 215 | |
| 216 | bool fastTrack = false; //Fast Track: axis-aligned rectangle without any clips? |
| 217 | }; |
| 218 | |
| 219 | struct SwImage |
| 220 | { |
| 221 | SwOutline* outline = nullptr; |
| 222 | SwRleData* rle = nullptr; |
| 223 | union { |
| 224 | pixel_t* data; //system based data pointer |
| 225 | uint32_t* buf32; //for explicit 32bits channels |
| 226 | uint8_t* buf8; //for explicit 8bits grayscale |
| 227 | }; |
| 228 | uint32_t w, h, stride; |
| 229 | int32_t ox = 0; //offset x |
| 230 | int32_t oy = 0; //offset y |
| 231 | float scale; |
| 232 | uint8_t channelSize; |
| 233 | |
| 234 | bool direct = false; //draw image directly (with offset) |
| 235 | bool scaled = false; //draw scaled image |
| 236 | }; |
| 237 | |
| 238 | typedef uint32_t(*SwBlender)(uint32_t s, uint32_t d, uint8_t a); //src, dst, alpha |
| 239 | typedef uint32_t(*SwJoin)(uint8_t r, uint8_t g, uint8_t b, uint8_t a); //color channel join |
| 240 | typedef uint8_t(*SwAlpha)(uint8_t*); //blending alpha |
| 241 | |
| 242 | struct SwCompositor; |
| 243 | |
| 244 | struct SwSurface : Surface |
| 245 | { |
| 246 | SwJoin join; |
| 247 | SwAlpha alphas[4]; //Alpha:2, InvAlpha:3, Luma:4, InvLuma:5 |
| 248 | SwBlender blender = nullptr; //blender (optional) |
| 249 | SwCompositor* compositor = nullptr; //compositor (optional) |
| 250 | BlendMethod blendMethod; //blending method (uint8_t) |
| 251 | |
| 252 | SwAlpha alpha(CompositeMethod method) |
| 253 | { |
| 254 | auto idx = (int)(method) - 2; //0: None, 1: ClipPath |
| 255 | return alphas[idx > 3 ? 0 : idx]; //CompositeMethod has only four Matting methods. |
| 256 | } |
| 257 | }; |
| 258 | |
| 259 | struct SwCompositor : Compositor |
| 260 | { |
| 261 | SwSurface* recoverSfc; //Recover surface when composition is started |
| 262 | SwCompositor* recoverCmp; //Recover compositor when composition is done |
| 263 | SwImage image; |
| 264 | SwBBox bbox; |
| 265 | bool valid; |
| 266 | }; |
| 267 | |
| 268 | struct SwMpool |
| 269 | { |
| 270 | SwOutline* outline; |
| 271 | SwOutline* strokeOutline; |
| 272 | unsigned allocSize; |
| 273 | }; |
| 274 | |
| 275 | static inline SwCoord TO_SWCOORD(float val) |
| 276 | { |
| 277 | return SwCoord(val * 64.0f); |
| 278 | } |
| 279 | |
| 280 | static inline uint32_t JOIN(uint8_t c0, uint8_t c1, uint8_t c2, uint8_t c3) |
| 281 | { |
| 282 | return (c0 << 24 | c1 << 16 | c2 << 8 | c3); |
| 283 | } |
| 284 | |
| 285 | static inline uint32_t ALPHA_BLEND(uint32_t c, uint32_t a) |
| 286 | { |
| 287 | return (((((c >> 8) & 0x00ff00ff) * a + 0x00ff00ff) & 0xff00ff00) + |
| 288 | ((((c & 0x00ff00ff) * a + 0x00ff00ff) >> 8) & 0x00ff00ff)); |
| 289 | } |
| 290 | |
| 291 | static inline uint32_t INTERPOLATE(uint32_t s, uint32_t d, uint8_t a) |
| 292 | { |
| 293 | return (((((((s >> 8) & 0xff00ff) - ((d >> 8) & 0xff00ff)) * a) + (d & 0xff00ff00)) & 0xff00ff00) + ((((((s & 0xff00ff) - (d & 0xff00ff)) * a) >> 8) + (d & 0xff00ff)) & 0xff00ff)); |
| 294 | } |
| 295 | |
| 296 | static inline uint8_t INTERPOLATE8(uint8_t s, uint8_t d, uint8_t a) |
| 297 | { |
| 298 | return ((s * a + 0xff) >> 8) + ((d * ~a + 0xff) >> 8); |
| 299 | } |
| 300 | |
| 301 | static inline SwCoord HALF_STROKE(float width) |
| 302 | { |
| 303 | return TO_SWCOORD(width * 0.5f); |
| 304 | } |
| 305 | |
| 306 | static inline uint8_t A(uint32_t c) |
| 307 | { |
| 308 | return ((c) >> 24); |
| 309 | } |
| 310 | |
| 311 | static inline uint8_t IA(uint32_t c) |
| 312 | { |
| 313 | return (~(c) >> 24); |
| 314 | } |
| 315 | |
| 316 | static inline uint8_t C1(uint32_t c) |
| 317 | { |
| 318 | return ((c) >> 16); |
| 319 | } |
| 320 | |
| 321 | static inline uint8_t C2(uint32_t c) |
| 322 | { |
| 323 | return ((c) >> 8); |
| 324 | } |
| 325 | |
| 326 | static inline uint8_t C3(uint32_t c) |
| 327 | { |
| 328 | return (c); |
| 329 | } |
| 330 | |
| 331 | static inline uint32_t opBlendInterp(uint32_t s, uint32_t d, uint8_t a) |
| 332 | { |
| 333 | return INTERPOLATE(s, d, a); |
| 334 | } |
| 335 | |
| 336 | static inline uint32_t opBlendNormal(uint32_t s, uint32_t d, uint8_t a) |
| 337 | { |
| 338 | auto t = ALPHA_BLEND(s, a); |
| 339 | return t + ALPHA_BLEND(d, IA(t)); |
| 340 | } |
| 341 | |
| 342 | static inline uint32_t opBlendPreNormal(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 343 | { |
| 344 | return s + ALPHA_BLEND(d, IA(s)); |
| 345 | } |
| 346 | |
| 347 | static inline uint32_t opBlendSrcOver(uint32_t s, TVG_UNUSED uint32_t d, TVG_UNUSED uint8_t a) |
| 348 | { |
| 349 | return s; |
| 350 | } |
| 351 | |
| 352 | //TODO: BlendMethod could remove the alpha parameter. |
| 353 | static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 354 | { |
| 355 | //if (s > d) => s - d |
| 356 | //else => d - s |
| 357 | auto c1 = (C1(s) > C1(d)) ? (C1(s) - C1(d)) : (C1(d) - C1(s)); |
| 358 | auto c2 = (C2(s) > C2(d)) ? (C2(s) - C2(d)) : (C2(d) - C2(s)); |
| 359 | auto c3 = (C3(s) > C3(d)) ? (C3(s) - C3(d)) : (C3(d) - C3(s)); |
| 360 | return JOIN(255, c1, c2, c3); |
| 361 | } |
| 362 | |
| 363 | static inline uint32_t opBlendExclusion(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 364 | { |
| 365 | //A + B - 2AB |
| 366 | auto c1 = min(255, C1(s) + C1(d) - min(255, (C1(s) * C1(d)) << 1)); |
| 367 | auto c2 = min(255, C2(s) + C2(d) - min(255, (C2(s) * C2(d)) << 1)); |
| 368 | auto c3 = min(255, C3(s) + C3(d) - min(255, (C3(s) * C3(d)) << 1)); |
| 369 | return JOIN(255, c1, c2, c3); |
| 370 | } |
| 371 | |
| 372 | static inline uint32_t opBlendAdd(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 373 | { |
| 374 | // s + d |
| 375 | auto c1 = min(C1(s) + C1(d), 255); |
| 376 | auto c2 = min(C2(s) + C2(d), 255); |
| 377 | auto c3 = min(C3(s) + C3(d), 255); |
| 378 | return JOIN(255, c1, c2, c3); |
| 379 | } |
| 380 | |
| 381 | static inline uint32_t opBlendScreen(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 382 | { |
| 383 | // s + d - s * d |
| 384 | auto c1 = C1(s) + C1(d) - MULTIPLY(C1(s), C1(d)); |
| 385 | auto c2 = C2(s) + C2(d) - MULTIPLY(C2(s), C2(d)); |
| 386 | auto c3 = C3(s) + C3(d) - MULTIPLY(C3(s), C3(d)); |
| 387 | return JOIN(255, c1, c2, c3); |
| 388 | } |
| 389 | |
| 390 | |
| 391 | static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 392 | { |
| 393 | // s * d |
| 394 | auto c1 = MULTIPLY(C1(s), C1(d)); |
| 395 | auto c2 = MULTIPLY(C2(s), C2(d)); |
| 396 | auto c3 = MULTIPLY(C3(s), C3(d)); |
| 397 | return JOIN(255, c1, c2, c3); |
| 398 | } |
| 399 | |
| 400 | |
| 401 | static inline uint32_t opBlendOverlay(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 402 | { |
| 403 | // if (2 * d < da) => 2 * s * d, |
| 404 | // else => 1 - 2 * (1 - s) * (1 - d) |
| 405 | auto c1 = (C1(d) < 128) ? min(255, 2 * MULTIPLY(C1(s), C1(d))) : (255 - min(255, 2 * MULTIPLY(255 - C1(s), 255 - C1(d)))); |
| 406 | auto c2 = (C2(d) < 128) ? min(255, 2 * MULTIPLY(C2(s), C2(d))) : (255 - min(255, 2 * MULTIPLY(255 - C2(s), 255 - C2(d)))); |
| 407 | auto c3 = (C3(d) < 128) ? min(255, 2 * MULTIPLY(C3(s), C3(d))) : (255 - min(255, 2 * MULTIPLY(255 - C3(s), 255 - C3(d)))); |
| 408 | return JOIN(255, c1, c2, c3); |
| 409 | } |
| 410 | |
| 411 | static inline uint32_t opBlendDarken(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 412 | { |
| 413 | // min(s, d) |
| 414 | auto c1 = min(C1(s), C1(d)); |
| 415 | auto c2 = min(C2(s), C2(d)); |
| 416 | auto c3 = min(C3(s), C3(d)); |
| 417 | return JOIN(255, c1, c2, c3); |
| 418 | } |
| 419 | |
| 420 | static inline uint32_t opBlendLighten(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 421 | { |
| 422 | // max(s, d) |
| 423 | auto c1 = max(C1(s), C1(d)); |
| 424 | auto c2 = max(C2(s), C2(d)); |
| 425 | auto c3 = max(C3(s), C3(d)); |
| 426 | return JOIN(255, c1, c2, c3); |
| 427 | } |
| 428 | |
| 429 | static inline uint32_t opBlendColorDodge(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 430 | { |
| 431 | // d / (1 - s) |
| 432 | auto is = 0xffffffff - s; |
| 433 | auto c1 = (C1(is) > 0) ? (C1(d) / C1(is)) : C1(d); |
| 434 | auto c2 = (C2(is) > 0) ? (C2(d) / C2(is)) : C2(d); |
| 435 | auto c3 = (C3(is) > 0) ? (C3(d) / C3(is)) : C3(d); |
| 436 | return JOIN(255, c1, c2, c3); |
| 437 | } |
| 438 | |
| 439 | static inline uint32_t opBlendColorBurn(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 440 | { |
| 441 | // 1 - (1 - d) / s |
| 442 | auto id = 0xffffffff - d; |
| 443 | auto c1 = 255 - ((C1(s) > 0) ? (C1(id) / C1(s)) : C1(id)); |
| 444 | auto c2 = 255 - ((C2(s) > 0) ? (C2(id) / C2(s)) : C2(id)); |
| 445 | auto c3 = 255 - ((C3(s) > 0) ? (C3(id) / C3(s)) : C3(id)); |
| 446 | return JOIN(255, c1, c2, c3); |
| 447 | } |
| 448 | |
| 449 | static inline uint32_t opBlendHardLight(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 450 | { |
| 451 | auto c1 = (C1(s) < 128) ? min(255, 2 * MULTIPLY(C1(s), C1(d))) : (255 - min(255, 2 * MULTIPLY(255 - C1(s), 255 - C1(d)))); |
| 452 | auto c2 = (C2(s) < 128) ? min(255, 2 * MULTIPLY(C2(s), C2(d))) : (255 - min(255, 2 * MULTIPLY(255 - C2(s), 255 - C2(d)))); |
| 453 | auto c3 = (C3(s) < 128) ? min(255, 2 * MULTIPLY(C3(s), C3(d))) : (255 - min(255, 2 * MULTIPLY(255 - C3(s), 255 - C3(d)))); |
| 454 | return JOIN(255, c1, c2, c3); |
| 455 | } |
| 456 | |
| 457 | static inline uint32_t opBlendSoftLight(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 458 | { |
| 459 | //(255 - 2 * s) * (d * d) + (2 * s * b) |
| 460 | auto c1 = min(255, MULTIPLY(255 - min(255, 2 * C1(s)), MULTIPLY(C1(d), C1(d))) + 2 * MULTIPLY(C1(s), C1(d))); |
| 461 | auto c2 = min(255, MULTIPLY(255 - min(255, 2 * C2(s)), MULTIPLY(C2(d), C2(d))) + 2 * MULTIPLY(C2(s), C2(d))); |
| 462 | auto c3 = min(255, MULTIPLY(255 - min(255, 2 * C3(s)), MULTIPLY(C3(d), C3(d))) + 2 * MULTIPLY(C3(s), C3(d))); |
| 463 | return JOIN(255, c1, c2, c3); |
| 464 | } |
| 465 | |
| 466 | static inline uint32_t opMaskAdd(uint32_t s, uint32_t d, uint8_t a) |
| 467 | { |
| 468 | return opBlendNormal(s, d, a); |
| 469 | } |
| 470 | |
| 471 | static inline uint32_t opMaskSubtract(uint32_t s, uint32_t d, uint8_t a) |
| 472 | { |
| 473 | return ALPHA_BLEND(d, MULTIPLY(IA(s), a)); |
| 474 | } |
| 475 | |
| 476 | static inline uint32_t opMaskDifference(uint32_t s, uint32_t d, uint8_t a) |
| 477 | { |
| 478 | auto t = ALPHA_BLEND(s, a); |
| 479 | return ALPHA_BLEND(t, IA(d)) + ALPHA_BLEND(d, IA(t)); |
| 480 | } |
| 481 | |
| 482 | static inline uint32_t opMaskIntersect(uint32_t s, uint32_t d, uint8_t a) |
| 483 | { |
| 484 | return ALPHA_BLEND(d, MULTIPLY(IA(s), a)); |
| 485 | } |
| 486 | |
| 487 | static inline uint32_t opMaskPreAdd(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 488 | { |
| 489 | return opBlendPreNormal(s, d, a); |
| 490 | } |
| 491 | |
| 492 | static inline uint32_t opMaskPreSubtract(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 493 | { |
| 494 | return ALPHA_BLEND(d, IA(s)); |
| 495 | } |
| 496 | |
| 497 | static inline uint32_t opMaskPreDifference(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 498 | { |
| 499 | return ALPHA_BLEND(s, IA(d)) + ALPHA_BLEND(d, IA(s)); |
| 500 | } |
| 501 | |
| 502 | static inline uint32_t opMaskPreIntersect(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a) |
| 503 | { |
| 504 | return ALPHA_BLEND(d, MULTIPLY(a, IA(s))); |
| 505 | } |
| 506 | |
| 507 | int64_t mathMultiply(int64_t a, int64_t b); |
| 508 | int64_t mathDivide(int64_t a, int64_t b); |
| 509 | int64_t mathMulDiv(int64_t a, int64_t b, int64_t c); |
| 510 | void mathRotate(SwPoint& pt, SwFixed angle); |
| 511 | SwFixed mathTan(SwFixed angle); |
| 512 | SwFixed mathAtan(const SwPoint& pt); |
| 513 | SwFixed mathCos(SwFixed angle); |
| 514 | SwFixed mathSin(SwFixed angle); |
| 515 | void mathSplitCubic(SwPoint* base); |
| 516 | SwFixed mathDiff(SwFixed angle1, SwFixed angle2); |
| 517 | SwFixed mathLength(const SwPoint& pt); |
| 518 | bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut); |
| 519 | SwFixed mathMean(SwFixed angle1, SwFixed angle2); |
| 520 | SwPoint mathTransform(const Point* to, const Matrix* transform); |
| 521 | bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion, bool fastTrack); |
| 522 | bool mathClipBBox(const SwBBox& clipper, SwBBox& clipee); |
| 523 | |
| 524 | void shapeReset(SwShape* shape); |
| 525 | bool shapePrepare(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid, bool hasComposite); |
| 526 | bool shapePrepared(const SwShape* shape); |
| 527 | bool shapeGenRle(SwShape* shape, const RenderShape* rshape, bool antiAlias); |
| 528 | void shapeDelOutline(SwShape* shape, SwMpool* mpool, uint32_t tid); |
| 529 | void shapeResetStroke(SwShape* shape, const RenderShape* rshape, const Matrix* transform); |
| 530 | bool shapeGenStrokeRle(SwShape* shape, const RenderShape* rshape, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid); |
| 531 | void shapeFree(SwShape* shape); |
| 532 | void shapeDelStroke(SwShape* shape); |
| 533 | bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable); |
| 534 | bool shapeGenStrokeFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable); |
| 535 | void shapeResetFill(SwShape* shape); |
| 536 | void shapeResetStrokeFill(SwShape* shape); |
| 537 | void shapeDelFill(SwShape* shape); |
| 538 | void shapeDelStrokeFill(SwShape* shape); |
| 539 | |
| 540 | void strokeReset(SwStroke* stroke, const RenderShape* shape, const Matrix* transform); |
| 541 | bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline); |
| 542 | SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid); |
| 543 | void strokeFree(SwStroke* stroke); |
| 544 | |
| 545 | bool imagePrepare(SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& clipRegion, SwBBox& renderRegion, SwMpool* mpool, unsigned tid); |
| 546 | bool imageGenRle(SwImage* image, const SwBBox& renderRegion, bool antiAlias); |
| 547 | void imageDelOutline(SwImage* image, SwMpool* mpool, uint32_t tid); |
| 548 | void imageReset(SwImage* image); |
| 549 | void imageFree(SwImage* image); |
| 550 | |
| 551 | bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable); |
| 552 | void fillReset(SwFill* fill); |
| 553 | void fillFree(SwFill* fill); |
| 554 | //OPTIMIZE_ME: Skip the function pointer access |
| 555 | void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a); //blending ver. |
| 556 | void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a); //blending + BlendingMethod(op2) ver. |
| 557 | void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity); //masking ver. |
| 558 | void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a); //blending ver. |
| 559 | void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a); //blending + BlendingMethod(op2) ver. |
| 560 | void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity); //masking ver. |
| 561 | |
| 562 | SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias); |
| 563 | SwRleData* rleRender(const SwBBox* bbox); |
| 564 | void rleFree(SwRleData* rle); |
| 565 | void rleReset(SwRleData* rle); |
| 566 | void rleMerge(SwRleData* rle, SwRleData* clip1, SwRleData* clip2); |
| 567 | void rleClipPath(SwRleData* rle, const SwRleData* clip); |
| 568 | void rleClipRect(SwRleData* rle, const SwBBox* clip); |
| 569 | |
| 570 | SwMpool* mpoolInit(uint32_t threads); |
| 571 | bool mpoolTerm(SwMpool* mpool); |
| 572 | bool mpoolClear(SwMpool* mpool); |
| 573 | SwOutline* mpoolReqOutline(SwMpool* mpool, unsigned idx); |
| 574 | void mpoolRetOutline(SwMpool* mpool, unsigned idx); |
| 575 | SwOutline* mpoolReqStrokeOutline(SwMpool* mpool, unsigned idx); |
| 576 | void mpoolRetStrokeOutline(SwMpool* mpool, unsigned idx); |
| 577 | |
| 578 | bool rasterCompositor(SwSurface* surface); |
| 579 | bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id); |
| 580 | bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); |
| 581 | bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& bbox, uint8_t opacity); |
| 582 | bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); |
| 583 | bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id); |
| 584 | bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h); |
| 585 | void rasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len); |
| 586 | void rasterGrayscale8(uint8_t *dst, uint8_t val, uint32_t offset, int32_t len); |
| 587 | void rasterUnpremultiply(Surface* surface); |
| 588 | void rasterPremultiply(Surface* surface); |
| 589 | bool rasterConvertCS(Surface* surface, ColorSpace to); |
| 590 | |
| 591 | #endif /* _TVG_SW_COMMON_H_ */ |
| 592 | |