1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <algorithm> 6 #include <utility> 7 #include <vector> 8 9 #include "core/fpdfapi/page/cpdf_meshstream.h" 10 #include "core/fpdfapi/page/cpdf_shadingpattern.h" 11 #include "core/fpdfapi/page/pageint.h" 12 #include "core/fpdfapi/parser/cpdf_array.h" 13 #include "core/fpdfapi/parser/cpdf_dictionary.h" 14 #include "core/fpdfapi/parser/cpdf_stream_acc.h" 15 #include "core/fxcodec/fx_codec.h" 16 #include "core/fxcrt/fx_memory.h" 17 #include "core/fxge/cfx_fxgedevice.h" 18 #include "core/fxge/cfx_gemodule.h" 19 #include "core/fxge/cfx_graphstatedata.h" 20 #include "core/fxge/cfx_pathdata.h" 21 #include "core/fxge/cfx_renderdevice.h" 22 #include "core/fxge/skia/fx_skia_device.h" 23 24 #ifdef _SKIA_SUPPORT_PATHS_ 25 #include "core/fxge/ge/cfx_cliprgn.h" 26 #endif // _SKIA_SUPPORT_PATHS_ 27 28 #include "third_party/base/ptr_util.h" 29 30 #include "third_party/skia/include/core/SkCanvas.h" 31 #include "third_party/skia/include/core/SkClipOp.h" 32 #include "third_party/skia/include/core/SkPaint.h" 33 #include "third_party/skia/include/core/SkPath.h" 34 #include "third_party/skia/include/core/SkShader.h" 35 #include "third_party/skia/include/core/SkStream.h" 36 #include "third_party/skia/include/core/SkTypeface.h" 37 #include "third_party/skia/include/effects/SkDashPathEffect.h" 38 #include "third_party/skia/include/effects/SkGradientShader.h" 39 #include "third_party/skia/include/pathops/SkPathOps.h" 40 41 #ifdef _SKIA_SUPPORT_ 42 #include "third_party/skia/include/core/SkColorFilter.h" 43 #include "third_party/skia/include/core/SkColorPriv.h" 44 #include "third_party/skia/include/core/SkMaskFilter.h" 45 #include "third_party/skia/include/core/SkPictureRecorder.h" 46 #endif // _SKIA_SUPPORT_ 47 48 namespace { 49 50 #ifdef _SKIA_SUPPORT_PATHS_ 51 void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap, 52 int dest_left, 53 int dest_top, 54 int width, 55 int height, 56 const CFX_DIBSource* pSrcBitmap, 57 int src_left, 58 int src_top) { 59 if (!pBitmap) 60 return; 61 62 pBitmap->GetOverlapRect(dest_left, dest_top, width, height, 63 pSrcBitmap->GetWidth(), pSrcBitmap->GetHeight(), 64 src_left, src_top, nullptr); 65 if (width == 0 || height == 0) 66 return; 67 68 int Bpp = pBitmap->GetBPP() / 8; 69 FXDIB_Format dest_format = pBitmap->GetFormat(); 70 FXDIB_Format src_format = pSrcBitmap->GetFormat(); 71 int pitch = pBitmap->GetPitch(); 72 uint8_t* buffer = pBitmap->GetBuffer(); 73 if (dest_format == src_format) { 74 for (int row = 0; row < height; row++) { 75 uint8_t* dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp; 76 uint8_t* src_scan = 77 (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp; 78 if (Bpp == 4) { 79 for (int col = 0; col < width; col++) { 80 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_scan[3], src_scan[0], 81 src_scan[1], src_scan[2])); 82 dest_scan += 4; 83 src_scan += 4; 84 } 85 } else { 86 for (int col = 0; col < width; col++) { 87 *dest_scan++ = src_scan[2]; 88 *dest_scan++ = src_scan[1]; 89 *dest_scan++ = src_scan[0]; 90 src_scan += 3; 91 } 92 } 93 } 94 return; 95 } 96 97 uint8_t* dest_buf = buffer + dest_top * pitch + dest_left * Bpp; 98 if (dest_format == FXDIB_Rgb) { 99 if (src_format == FXDIB_Rgb32) { 100 for (int row = 0; row < height; row++) { 101 uint8_t* dest_scan = dest_buf + row * pitch; 102 uint8_t* src_scan = 103 (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 4; 104 for (int col = 0; col < width; col++) { 105 *dest_scan++ = src_scan[2]; 106 *dest_scan++ = src_scan[1]; 107 *dest_scan++ = src_scan[0]; 108 src_scan += 4; 109 } 110 } 111 } else { 112 ASSERT(false); 113 } 114 return; 115 } 116 117 if (dest_format == FXDIB_Argb || dest_format == FXDIB_Rgb32) { 118 if (src_format == FXDIB_Rgb) { 119 for (int row = 0; row < height; row++) { 120 uint8_t* dest_scan = (uint8_t*)(dest_buf + row * pitch); 121 uint8_t* src_scan = 122 (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 3; 123 for (int col = 0; col < width; col++) { 124 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1], 125 src_scan[2])); 126 dest_scan += 4; 127 src_scan += 3; 128 } 129 } 130 } else if (src_format == FXDIB_Rgb32) { 131 ASSERT(dest_format == FXDIB_Argb); 132 for (int row = 0; row < height; row++) { 133 uint8_t* dest_scan = dest_buf + row * pitch; 134 uint8_t* src_scan = 135 (uint8_t*)(pSrcBitmap->GetScanline(src_top + row) + src_left * 4); 136 for (int col = 0; col < width; col++) { 137 FXARGB_SETDIB(dest_scan, FXARGB_MAKE(0xff, src_scan[0], src_scan[1], 138 src_scan[2])); 139 src_scan += 4; 140 dest_scan += 4; 141 } 142 } 143 } 144 return; 145 } 146 147 ASSERT(false); 148 } 149 150 #endif // _SKIA_SUPPORT_PATHS_ 151 152 #define SHOW_SKIA_PATH 0 // set to 1 to print the path contents 153 #define DRAW_SKIA_CLIP 0 // set to 1 to draw a green rectangle around the clip 154 155 #if SHOW_SKIA_PATH 156 void DebugShowSkiaPaint(const SkPaint& paint) { 157 if (SkPaint::kFill_Style == paint.getStyle()) { 158 printf("fill 0x%08x\n", paint.getColor()); 159 } else { 160 printf("stroke 0x%08x width %g\n", paint.getColor(), 161 paint.getStrokeWidth()); 162 } 163 } 164 165 void DebugShowCanvasMatrix(const SkCanvas* canvas) { 166 SkMatrix matrix = canvas->getTotalMatrix(); 167 SkScalar m[9]; 168 matrix.get9(m); 169 printf("matrix (%g,%g,%g) (%g,%g,%g) (%g,%g,%g)\n", m[0], m[1], m[2], m[3], 170 m[4], m[5], m[6], m[7], m[8]); 171 } 172 #endif // SHOW_SKIA_PATH 173 174 void DebugShowSkiaPath(const SkPath& path) { 175 #if SHOW_SKIA_PATH 176 char buffer[4096]; 177 sk_bzero(buffer, sizeof(buffer)); 178 SkMemoryWStream stream(buffer, sizeof(buffer)); 179 path.dump(&stream, false, false); 180 printf("%s", buffer); 181 #endif // SHOW_SKIA_PATH 182 } 183 184 void DebugShowCanvasClip(const SkCanvas* canvas) { 185 #if SHOW_SKIA_PATH 186 SkRect local; 187 SkIRect device; 188 canvas->getClipBounds(&local); 189 printf("local bounds %g %g %g %g\n", local.fLeft, local.fTop, local.fRight, 190 local.fBottom); 191 canvas->getClipDeviceBounds(&device); 192 printf("device bounds %d %d %d %d\n", device.fLeft, device.fTop, 193 device.fRight, device.fBottom); 194 #endif // SHOW_SKIA_PATH 195 } 196 197 #if SHOW_SKIA_PATH 198 void DebugShowSkiaPaint(const SkPaint& paint) { 199 if (SkPaint::kFill_Style == paint.getStyle()) { 200 printf("fill 0x%08x\n", paint.getColor()); 201 } else { 202 printf("stroke 0x%08x width %g\n", paint.getColor(), 203 paint.getStrokeWidth()); 204 } 205 } 206 #endif // SHOW_SKIA_PATH 207 208 void DebugShowSkiaDrawPath(const SkCanvas* canvas, 209 const SkPaint& paint, 210 const SkPath& path) { 211 #if SHOW_SKIA_PATH 212 DebugShowSkiaPaint(paint); 213 DebugShowCanvasMatrix(canvas); 214 DebugShowCanvasClip(canvas); 215 DebugShowSkiaPath(path); 216 printf("\n"); 217 #endif // SHOW_SKIA_PATH 218 } 219 220 void DebugShowSkiaDrawRect(const SkCanvas* canvas, 221 const SkPaint& paint, 222 const SkRect& rect) { 223 #if SHOW_SKIA_PATH 224 DebugShowSkiaPaint(paint); 225 DebugShowCanvasMatrix(canvas); 226 DebugShowCanvasClip(canvas); 227 printf("rect %g %g %g %g\n", rect.fLeft, rect.fTop, rect.fRight, 228 rect.fBottom); 229 #endif // SHOW_SKIA_PATH 230 } 231 232 #if DRAW_SKIA_CLIP 233 234 SkPaint DebugClipPaint() { 235 SkPaint paint; 236 paint.setAntiAlias(true); 237 paint.setColor(SK_ColorGREEN); 238 paint.setStyle(SkPaint::kStroke_Style); 239 return paint; 240 } 241 242 void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) { 243 SkPaint paint = DebugClipPaint(); 244 canvas->drawRect(rect, paint); 245 } 246 247 void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) { 248 SkPaint paint = DebugClipPaint(); 249 canvas->drawPath(path, paint); 250 } 251 252 #else // DRAW_SKIA_CLIP 253 254 void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {} 255 256 void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {} 257 258 #endif // DRAW_SKIA_CLIP 259 260 #ifdef _SKIA_SUPPORT_ 261 static void DebugValidate(const CFX_DIBitmap* bitmap, 262 const CFX_DIBitmap* device) { 263 if (bitmap) { 264 SkASSERT(bitmap->GetBPP() == 8 || bitmap->GetBPP() == 32); 265 if (bitmap->GetBPP() == 32) { 266 bitmap->DebugVerifyBitmapIsPreMultiplied(); 267 } 268 } 269 if (device) { 270 SkASSERT(device->GetBPP() == 8 || device->GetBPP() == 32); 271 if (device->GetBPP() == 32) { 272 device->DebugVerifyBitmapIsPreMultiplied(); 273 } 274 } 275 } 276 #endif // _SKIA_SUPPORT_ 277 278 SkPath BuildPath(const CFX_PathData* pPathData) { 279 SkPath skPath; 280 const CFX_PathData* pFPath = pPathData; 281 const std::vector<FX_PATHPOINT>& pPoints = pFPath->GetPoints(); 282 for (size_t i = 0; i < pPoints.size(); i++) { 283 CFX_PointF point = pPoints[i].m_Point; 284 FXPT_TYPE point_type = pPoints[i].m_Type; 285 if (point_type == FXPT_TYPE::MoveTo) { 286 skPath.moveTo(point.x, point.y); 287 } else if (point_type == FXPT_TYPE::LineTo) { 288 skPath.lineTo(point.x, point.y); 289 } else if (point_type == FXPT_TYPE::BezierTo) { 290 CFX_PointF point2 = pPoints[i + 1].m_Point; 291 CFX_PointF point3 = pPoints[i + 2].m_Point; 292 skPath.cubicTo(point.x, point.y, point2.x, point2.y, point3.x, point3.y); 293 i += 2; 294 } 295 if (pPoints[i].m_CloseFigure) 296 skPath.close(); 297 } 298 return skPath; 299 } 300 301 SkMatrix ToSkMatrix(const CFX_Matrix& m) { 302 SkMatrix skMatrix; 303 skMatrix.setAll(m.a, m.c, m.e, m.b, m.d, m.f, 0, 0, 1); 304 return skMatrix; 305 } 306 307 // use when pdf's y-axis points up instead of down 308 SkMatrix ToFlippedSkMatrix(const CFX_Matrix& m, SkScalar flip) { 309 SkMatrix skMatrix; 310 skMatrix.setAll(m.a * flip, -m.c * flip, m.e, m.b * flip, -m.d * flip, m.f, 0, 311 0, 1); 312 return skMatrix; 313 } 314 315 SkBlendMode GetSkiaBlendMode(int blend_type) { 316 switch (blend_type) { 317 case FXDIB_BLEND_MULTIPLY: 318 return SkBlendMode::kMultiply; 319 case FXDIB_BLEND_SCREEN: 320 return SkBlendMode::kScreen; 321 case FXDIB_BLEND_OVERLAY: 322 return SkBlendMode::kOverlay; 323 case FXDIB_BLEND_DARKEN: 324 return SkBlendMode::kDarken; 325 case FXDIB_BLEND_LIGHTEN: 326 return SkBlendMode::kLighten; 327 case FXDIB_BLEND_COLORDODGE: 328 return SkBlendMode::kColorDodge; 329 case FXDIB_BLEND_COLORBURN: 330 return SkBlendMode::kColorBurn; 331 case FXDIB_BLEND_HARDLIGHT: 332 return SkBlendMode::kHardLight; 333 case FXDIB_BLEND_SOFTLIGHT: 334 return SkBlendMode::kSoftLight; 335 case FXDIB_BLEND_DIFFERENCE: 336 return SkBlendMode::kDifference; 337 case FXDIB_BLEND_EXCLUSION: 338 return SkBlendMode::kExclusion; 339 case FXDIB_BLEND_HUE: 340 return SkBlendMode::kHue; 341 case FXDIB_BLEND_SATURATION: 342 return SkBlendMode::kSaturation; 343 case FXDIB_BLEND_COLOR: 344 return SkBlendMode::kColor; 345 case FXDIB_BLEND_LUMINOSITY: 346 return SkBlendMode::kLuminosity; 347 case FXDIB_BLEND_NORMAL: 348 default: 349 return SkBlendMode::kSrcOver; 350 } 351 } 352 353 bool AddColors(const CPDF_ExpIntFunc* pFunc, SkTDArray<SkColor>* skColors) { 354 if (pFunc->CountInputs() != 1) 355 return false; 356 if (pFunc->m_Exponent != 1) 357 return false; 358 if (pFunc->m_nOrigOutputs != 3) 359 return false; 360 skColors->push( 361 SkColorSetARGB(0xFF, SkUnitScalarClampToByte(pFunc->m_pBeginValues[0]), 362 SkUnitScalarClampToByte(pFunc->m_pBeginValues[1]), 363 SkUnitScalarClampToByte(pFunc->m_pBeginValues[2]))); 364 skColors->push( 365 SkColorSetARGB(0xFF, SkUnitScalarClampToByte(pFunc->m_pEndValues[0]), 366 SkUnitScalarClampToByte(pFunc->m_pEndValues[1]), 367 SkUnitScalarClampToByte(pFunc->m_pEndValues[2]))); 368 return true; 369 } 370 371 uint8_t FloatToByte(FX_FLOAT f) { 372 ASSERT(0 <= f && f <= 1); 373 return (uint8_t)(f * 255.99f); 374 } 375 376 bool AddSamples(const CPDF_SampledFunc* pFunc, 377 SkTDArray<SkColor>* skColors, 378 SkTDArray<SkScalar>* skPos) { 379 if (pFunc->CountInputs() != 1) 380 return false; 381 if (pFunc->CountOutputs() != 3) // expect rgb 382 return false; 383 if (pFunc->GetEncodeInfo().empty()) 384 return false; 385 const CPDF_SampledFunc::SampleEncodeInfo& encodeInfo = 386 pFunc->GetEncodeInfo()[0]; 387 if (encodeInfo.encode_min != 0) 388 return false; 389 if (encodeInfo.encode_max != encodeInfo.sizes - 1) 390 return false; 391 uint32_t sampleSize = pFunc->GetBitsPerSample(); 392 uint32_t sampleCount = encodeInfo.sizes; 393 if (sampleCount != 1U << sampleSize) 394 return false; 395 if (pFunc->GetSampleStream()->GetSize() < sampleCount * 3 * sampleSize / 8) 396 return false; 397 398 FX_FLOAT colorsMin[3]; 399 FX_FLOAT colorsMax[3]; 400 for (int i = 0; i < 3; ++i) { 401 colorsMin[i] = pFunc->GetRange(i * 2); 402 colorsMax[i] = pFunc->GetRange(i * 2 + 1); 403 } 404 const uint8_t* pSampleData = pFunc->GetSampleStream()->GetData(); 405 for (uint32_t i = 0; i < sampleCount; ++i) { 406 FX_FLOAT floatColors[3]; 407 for (uint32_t j = 0; j < 3; ++j) { 408 int sample = GetBits32(pSampleData, (i * 3 + j) * sampleSize, sampleSize); 409 FX_FLOAT interp = (FX_FLOAT)sample / (sampleCount - 1); 410 floatColors[j] = colorsMin[j] + (colorsMax[j] - colorsMin[j]) * interp; 411 } 412 SkColor color = 413 SkPackARGB32(0xFF, FloatToByte(floatColors[0]), 414 FloatToByte(floatColors[1]), FloatToByte(floatColors[2])); 415 skColors->push(color); 416 skPos->push((FX_FLOAT)i / (sampleCount - 1)); 417 } 418 return true; 419 } 420 421 bool AddStitching(const CPDF_StitchFunc* pFunc, 422 SkTDArray<SkColor>* skColors, 423 SkTDArray<SkScalar>* skPos) { 424 FX_FLOAT boundsStart = pFunc->GetDomain(0); 425 426 const auto& subFunctions = pFunc->GetSubFunctions(); 427 int subFunctionCount = subFunctions.size(); 428 for (int i = 0; i < subFunctionCount; ++i) { 429 const CPDF_ExpIntFunc* pSubFunc = subFunctions[i]->ToExpIntFunc(); 430 if (!pSubFunc) 431 return false; 432 if (!AddColors(pSubFunc, skColors)) 433 return false; 434 FX_FLOAT boundsEnd = 435 i < subFunctionCount - 1 ? pFunc->GetBound(i + 1) : pFunc->GetDomain(1); 436 skPos->push(boundsStart); 437 skPos->push(boundsEnd); 438 boundsStart = boundsEnd; 439 } 440 return true; 441 } 442 443 // see https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line 444 SkScalar LineSide(const SkPoint line[2], const SkPoint& pt) { 445 return (line[1].fY - line[0].fY) * pt.fX - (line[1].fX - line[0].fX) * pt.fY + 446 line[1].fX * line[0].fY - line[1].fY * line[0].fX; 447 } 448 449 SkPoint IntersectSides(const SkPoint& parallelPt, 450 const SkVector& paraRay, 451 const SkPoint& perpendicularPt) { 452 SkVector perpRay = {paraRay.fY, -paraRay.fX}; 453 SkScalar denom = perpRay.fY * paraRay.fX - paraRay.fY * perpRay.fX; 454 if (!denom) { 455 SkPoint zeroPt = {0, 0}; 456 return zeroPt; 457 } 458 SkVector ab0 = parallelPt - perpendicularPt; 459 SkScalar numerA = ab0.fY * perpRay.fX - perpRay.fY * ab0.fX; 460 numerA /= denom; 461 SkPoint result = {parallelPt.fX + paraRay.fX * numerA, 462 parallelPt.fY + paraRay.fY * numerA}; 463 return result; 464 } 465 466 void ClipAngledGradient(const SkPoint pts[2], 467 SkPoint rectPts[4], 468 bool clipStart, 469 bool clipEnd, 470 SkPath* clip) { 471 // find the corners furthest from the gradient perpendiculars 472 SkScalar minPerpDist = SK_ScalarMax; 473 SkScalar maxPerpDist = SK_ScalarMin; 474 int minPerpPtIndex = -1; 475 int maxPerpPtIndex = -1; 476 SkVector slope = pts[1] - pts[0]; 477 SkPoint startPerp[2] = {pts[0], {pts[0].fX + slope.fY, pts[0].fY - slope.fX}}; 478 SkPoint endPerp[2] = {pts[1], {pts[1].fX + slope.fY, pts[1].fY - slope.fX}}; 479 for (int i = 0; i < 4; ++i) { 480 SkScalar sDist = LineSide(startPerp, rectPts[i]); 481 SkScalar eDist = LineSide(endPerp, rectPts[i]); 482 if (sDist * eDist <= 0) // if the signs are different, 483 continue; // the point is inside the gradient 484 if (sDist < 0) { 485 SkScalar smaller = SkTMin(sDist, eDist); 486 if (minPerpDist > smaller) { 487 minPerpDist = smaller; 488 minPerpPtIndex = i; 489 } 490 } else { 491 SkScalar larger = SkTMax(sDist, eDist); 492 if (maxPerpDist < larger) { 493 maxPerpDist = larger; 494 maxPerpPtIndex = i; 495 } 496 } 497 } 498 if (minPerpPtIndex < 0 && maxPerpPtIndex < 0) // nothing's outside 499 return; 500 // determine if negative distances are before start or after end 501 SkPoint beforeStart = {pts[0].fX * 2 - pts[1].fX, pts[0].fY * 2 - pts[1].fY}; 502 bool beforeNeg = LineSide(startPerp, beforeStart) < 0; 503 const SkPoint& startEdgePt = 504 clipStart ? pts[0] : beforeNeg ? rectPts[minPerpPtIndex] 505 : rectPts[maxPerpPtIndex]; 506 const SkPoint& endEdgePt = clipEnd ? pts[1] : beforeNeg 507 ? rectPts[maxPerpPtIndex] 508 : rectPts[minPerpPtIndex]; 509 // find the corners that bound the gradient 510 SkScalar minDist = SK_ScalarMax; 511 SkScalar maxDist = SK_ScalarMin; 512 int minBounds = -1; 513 int maxBounds = -1; 514 for (int i = 0; i < 4; ++i) { 515 SkScalar dist = LineSide(pts, rectPts[i]); 516 if (minDist > dist) { 517 minDist = dist; 518 minBounds = i; 519 } 520 if (maxDist < dist) { 521 maxDist = dist; 522 maxBounds = i; 523 } 524 } 525 ASSERT(minBounds >= 0); 526 ASSERT(maxBounds != minBounds && maxBounds >= 0); 527 // construct a clip parallel to the gradient that goes through 528 // rectPts[minBounds] and rectPts[maxBounds] and perpendicular to the 529 // gradient that goes through startEdgePt, endEdgePt. 530 clip->moveTo(IntersectSides(rectPts[minBounds], slope, startEdgePt)); 531 clip->lineTo(IntersectSides(rectPts[minBounds], slope, endEdgePt)); 532 clip->lineTo(IntersectSides(rectPts[maxBounds], slope, endEdgePt)); 533 clip->lineTo(IntersectSides(rectPts[maxBounds], slope, startEdgePt)); 534 } 535 536 #ifdef _SKIA_SUPPORT_ 537 void SetBitmapMatrix(const CFX_Matrix* pMatrix, 538 int width, 539 int height, 540 SkMatrix* skMatrix) { 541 const CFX_Matrix& m = *pMatrix; 542 skMatrix->setAll(m.a / width, -m.c / height, m.c + m.e, m.b / width, 543 -m.d / height, m.d + m.f, 0, 0, 1); 544 } 545 546 void SetBitmapPaint(bool isAlphaMask, 547 uint32_t argb, 548 int bitmap_alpha, 549 int blend_type, 550 SkPaint* paint) { 551 paint->setAntiAlias(true); 552 if (isAlphaMask) { 553 paint->setColorFilter( 554 SkColorFilter::MakeModeFilter(argb, SkBlendMode::kSrc)); 555 } 556 // paint->setFilterQuality(kHigh_SkFilterQuality); 557 paint->setBlendMode(GetSkiaBlendMode(blend_type)); 558 paint->setAlpha(bitmap_alpha); 559 } 560 561 bool Upsample(const CFX_DIBSource* pSource, 562 std::unique_ptr<uint8_t, FxFreeDeleter>& dst8Storage, 563 std::unique_ptr<uint32_t, FxFreeDeleter>& dst32Storage, 564 SkColorTable** ctPtr, 565 SkBitmap* skBitmap, 566 int* widthPtr, 567 int* heightPtr, 568 bool forceAlpha) { 569 void* buffer = pSource->GetBuffer(); 570 if (!buffer) 571 return false; 572 SkColorType colorType = forceAlpha || pSource->IsAlphaMask() 573 ? SkColorType::kAlpha_8_SkColorType 574 : SkColorType::kGray_8_SkColorType; 575 SkAlphaType alphaType = 576 pSource->IsAlphaMask() ? kPremul_SkAlphaType : kOpaque_SkAlphaType; 577 int width = pSource->GetWidth(); 578 int height = pSource->GetHeight(); 579 int rowBytes = pSource->GetPitch(); 580 switch (pSource->GetBPP()) { 581 case 1: { 582 dst8Storage.reset(FX_Alloc2D(uint8_t, width, height)); 583 uint8_t* dst8Pixels = dst8Storage.get(); 584 for (int y = 0; y < height; ++y) { 585 const uint8_t* srcRow = 586 static_cast<const uint8_t*>(buffer) + y * rowBytes; 587 uint8_t* dstRow = dst8Pixels + y * width; 588 for (int x = 0; x < width; ++x) 589 dstRow[x] = srcRow[x >> 3] & (1 << (~x & 0x07)) ? 0xFF : 0x00; 590 } 591 buffer = dst8Storage.get(); 592 rowBytes = width; 593 break; 594 } 595 case 8: 596 if (pSource->GetPalette()) { 597 *ctPtr = 598 new SkColorTable(pSource->GetPalette(), pSource->GetPaletteSize()); 599 colorType = SkColorType::kIndex_8_SkColorType; 600 } 601 break; 602 case 24: { 603 dst32Storage.reset(FX_Alloc2D(uint32_t, width, height)); 604 uint32_t* dst32Pixels = dst32Storage.get(); 605 for (int y = 0; y < height; ++y) { 606 const uint8_t* srcRow = 607 static_cast<const uint8_t*>(buffer) + y * rowBytes; 608 uint32_t* dstRow = dst32Pixels + y * width; 609 for (int x = 0; x < width; ++x) { 610 dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1], 611 srcRow[x * 3 + 0]); 612 } 613 } 614 buffer = dst32Storage.get(); 615 rowBytes = width * sizeof(uint32_t); 616 colorType = SkColorType::kN32_SkColorType; 617 alphaType = kOpaque_SkAlphaType; 618 break; 619 } 620 case 32: 621 colorType = SkColorType::kN32_SkColorType; 622 alphaType = kPremul_SkAlphaType; 623 pSource->DebugVerifyBitmapIsPreMultiplied(buffer); 624 break; 625 default: 626 SkASSERT(0); // TODO(caryclark) ensure that all cases are covered 627 colorType = SkColorType::kUnknown_SkColorType; 628 } 629 SkImageInfo imageInfo = 630 SkImageInfo::Make(width, height, colorType, alphaType); 631 skBitmap->installPixels(imageInfo, buffer, rowBytes, *ctPtr, nullptr, 632 nullptr); 633 *widthPtr = width; 634 *heightPtr = height; 635 return true; 636 } 637 #endif // _SKIA_SUPPORT_ 638 639 } // namespace 640 641 // Encapsulate the state used for successive text and path draws so that 642 // they can be combined. 643 class SkiaState { 644 public: 645 enum class Clip { 646 kSave, 647 kPath, 648 }; 649 650 enum class Accumulator { 651 kNone, 652 kPath, 653 kText, 654 kOther, 655 }; 656 657 // mark all cached state as uninitialized 658 explicit SkiaState(CFX_SkiaDeviceDriver* pDriver) 659 : m_pDriver(pDriver), 660 m_pFont(nullptr), 661 m_fontSize(0), 662 m_fillColor(0), 663 m_strokeColor(0), 664 m_blendType(0), 665 m_commandIndex(0), 666 m_drawIndex(INT_MAX), 667 m_clipIndex(0), 668 m_type(Accumulator::kNone), 669 m_fillFullCover(false), 670 m_fillPath(false), 671 m_groupKnockout(false), 672 m_debugDisable(false) 673 #if SHOW_SKIA_PATH 674 , 675 m_debugSaveCounter(0) 676 #endif 677 { 678 } 679 680 bool DrawPath(const CFX_PathData* pPathData, 681 const CFX_Matrix* pMatrix, 682 const CFX_GraphStateData* pDrawState, 683 uint32_t fill_color, 684 uint32_t stroke_color, 685 int fill_mode, 686 int blend_type) { 687 if (m_debugDisable) 688 return false; 689 Dump(__func__); 690 int drawIndex = SkTMin(m_drawIndex, m_commands.count()); 691 if (Accumulator::kText == m_type || drawIndex != m_commandIndex || 692 (Accumulator::kPath == m_type && 693 DrawChanged(pMatrix, pDrawState, fill_color, stroke_color, fill_mode, 694 blend_type, m_pDriver->m_bGroupKnockout))) { 695 Flush(); 696 } 697 if (Accumulator::kPath != m_type) { 698 m_skPath.reset(); 699 m_fillFullCover = !!(fill_mode & FXFILL_FULLCOVER); 700 m_fillPath = (fill_mode & 3) && fill_color; 701 m_skPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE 702 ? SkPath::kEvenOdd_FillType 703 : SkPath::kWinding_FillType); 704 if (pDrawState) 705 m_drawState.Copy(*pDrawState); 706 m_fillColor = fill_color; 707 m_strokeColor = stroke_color; 708 m_blendType = blend_type; 709 m_groupKnockout = m_pDriver->m_bGroupKnockout; 710 if (pMatrix) 711 m_drawMatrix = *pMatrix; 712 m_drawIndex = m_commandIndex; 713 m_type = Accumulator::kPath; 714 } 715 SkPath skPath = BuildPath(pPathData); 716 SkPoint delta; 717 if (MatrixOffset(pMatrix, &delta)) 718 skPath.offset(delta.fX, delta.fY); 719 m_skPath.addPath(skPath); 720 return true; 721 } 722 723 void FlushPath() { 724 Dump(__func__); 725 SkMatrix skMatrix = ToSkMatrix(m_drawMatrix); 726 SkPaint skPaint; 727 skPaint.setAntiAlias(true); 728 if (m_fillFullCover) 729 skPaint.setBlendMode(SkBlendMode::kPlus); 730 int stroke_alpha = FXARGB_A(m_strokeColor); 731 if (stroke_alpha) 732 m_pDriver->PaintStroke(&skPaint, &m_drawState, skMatrix); 733 SkCanvas* skCanvas = m_pDriver->SkiaCanvas(); 734 skCanvas->save(); 735 skCanvas->concat(skMatrix); 736 if (m_fillPath) { 737 SkPath strokePath; 738 const SkPath* fillPath = &m_skPath; 739 if (stroke_alpha) { 740 if (m_groupKnockout) { 741 skPaint.getFillPath(m_skPath, &strokePath); 742 if (Op(m_skPath, strokePath, SkPathOp::kDifference_SkPathOp, 743 &strokePath)) { 744 fillPath = &strokePath; 745 } 746 } 747 } 748 skPaint.setStyle(SkPaint::kFill_Style); 749 skPaint.setColor(m_fillColor); 750 #ifdef _SKIA_SUPPORT_PATHS_ 751 m_pDriver->PreMultiply(); 752 #endif // _SKIA_SUPPORT_PATHS_ 753 DebugShowSkiaDrawPath(skCanvas, skPaint, *fillPath); 754 skCanvas->drawPath(*fillPath, skPaint); 755 } 756 if (stroke_alpha) { 757 skPaint.setStyle(SkPaint::kStroke_Style); 758 skPaint.setColor(m_strokeColor); 759 #ifdef _SKIA_SUPPORT_PATHS_ 760 m_pDriver->PreMultiply(); 761 #endif // _SKIA_SUPPORT_PATHS_ 762 DebugShowSkiaDrawPath(skCanvas, skPaint, m_skPath); 763 skCanvas->drawPath(m_skPath, skPaint); 764 } 765 skCanvas->restore(); 766 m_drawIndex = INT_MAX; 767 m_type = Accumulator::kNone; 768 } 769 770 bool DrawText(int nChars, 771 const FXTEXT_CHARPOS* pCharPos, 772 CFX_Font* pFont, 773 const CFX_Matrix* pMatrix, 774 FX_FLOAT font_size, 775 uint32_t color) { 776 if (m_debugDisable) 777 return false; 778 Dump(__func__); 779 int drawIndex = SkTMin(m_drawIndex, m_commands.count()); 780 if (Accumulator::kPath == m_type || drawIndex != m_commandIndex || 781 (Accumulator::kText == m_type && 782 FontChanged(pFont, pMatrix, font_size, color))) { 783 Flush(); 784 } 785 if (Accumulator::kText != m_type) { 786 m_positions.setCount(0); 787 m_glyphs.setCount(0); 788 m_pFont = pFont; 789 m_fontSize = font_size; 790 m_fillColor = color; 791 m_drawMatrix = *pMatrix; 792 m_drawIndex = m_commandIndex; 793 m_type = Accumulator::kText; 794 } 795 int count = m_positions.count(); 796 m_positions.setCount(nChars + count); 797 m_glyphs.setCount(nChars + count); 798 SkScalar flip = m_fontSize < 0 ? -1 : 1; 799 SkScalar vFlip = flip; 800 if (pFont->IsVertical()) 801 vFlip *= -1; 802 for (int index = 0; index < nChars; ++index) { 803 const FXTEXT_CHARPOS& cp = pCharPos[index]; 804 m_positions[index + count] = {cp.m_Origin.x * flip, 805 cp.m_Origin.y * vFlip}; 806 m_glyphs[index + count] = static_cast<uint16_t>(cp.m_GlyphIndex); 807 } 808 SkPoint delta; 809 if (MatrixOffset(pMatrix, &delta)) { 810 for (int index = 0; index < nChars; ++index) 811 m_positions[index + count].offset(delta.fX * flip, -delta.fY * flip); 812 } 813 return true; 814 } 815 816 void FlushText() { 817 Dump(__func__); 818 SkPaint skPaint; 819 skPaint.setAntiAlias(true); 820 skPaint.setColor(m_fillColor); 821 if (m_pFont->GetFace()) { // exclude placeholder test fonts 822 sk_sp<SkTypeface> typeface(SkSafeRef(m_pFont->GetDeviceCache())); 823 skPaint.setTypeface(typeface); 824 } 825 skPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 826 skPaint.setHinting(SkPaint::kNo_Hinting); 827 skPaint.setTextSize(SkTAbs(m_fontSize)); 828 skPaint.setSubpixelText(true); 829 SkCanvas* skCanvas = m_pDriver->SkiaCanvas(); 830 skCanvas->save(); 831 SkScalar flip = m_fontSize < 0 ? -1 : 1; 832 SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix, flip); 833 skCanvas->concat(skMatrix); 834 #ifdef _SKIA_SUPPORT_PATHS_ 835 m_pDriver->PreMultiply(); 836 #endif // _SKIA_SUPPORT_PATHS_ 837 skCanvas->drawPosText(m_glyphs.begin(), m_glyphs.count() * 2, 838 m_positions.begin(), skPaint); 839 skCanvas->restore(); 840 m_drawIndex = INT_MAX; 841 m_type = Accumulator::kNone; 842 } 843 844 bool SetClipFill(const CFX_PathData* pPathData, 845 const CFX_Matrix* pMatrix, 846 int fill_mode) { 847 if (m_debugDisable) 848 return false; 849 Dump(__func__); 850 SkPath skClipPath = BuildPath(pPathData); 851 skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE 852 ? SkPath::kEvenOdd_FillType 853 : SkPath::kWinding_FillType); 854 SkMatrix skMatrix = ToSkMatrix(*pMatrix); 855 skClipPath.transform(skMatrix); 856 return SetClip(skClipPath); 857 } 858 859 bool SetClip(const SkPath& skClipPath) { 860 // if a pending draw depends on clip state that is cached, flush it and draw 861 if (m_commandIndex < m_commands.count()) { 862 if (m_commands[m_commandIndex] == Clip::kPath && 863 m_clips[m_commandIndex] == skClipPath) { 864 ++m_commandIndex; 865 return true; 866 } 867 Flush(); 868 } 869 while (m_clipIndex > m_commandIndex) { 870 do { 871 --m_clipIndex; 872 SkASSERT(m_clipIndex >= 0); 873 } while (m_commands[m_clipIndex] != Clip::kSave); 874 m_pDriver->SkiaCanvas()->restore(); 875 } 876 if (m_commandIndex < m_commands.count()) { 877 m_commands[m_commandIndex] = Clip::kPath; 878 m_clips[m_commandIndex] = skClipPath; 879 } else { 880 m_commands.push(Clip::kPath); 881 m_clips.push_back(skClipPath); 882 } 883 ++m_commandIndex; 884 return true; 885 } 886 887 bool SetClipStroke(const CFX_PathData* pPathData, 888 const CFX_Matrix* pMatrix, 889 const CFX_GraphStateData* pGraphState) { 890 if (m_debugDisable) 891 return false; 892 Dump(__func__); 893 SkPath skPath = BuildPath(pPathData); 894 SkMatrix skMatrix = ToSkMatrix(*pMatrix); 895 SkPaint skPaint; 896 m_pDriver->PaintStroke(&skPaint, pGraphState, skMatrix); 897 SkPath dst_path; 898 skPaint.getFillPath(skPath, &dst_path); 899 dst_path.transform(skMatrix); 900 return SetClip(dst_path); 901 } 902 903 bool MatrixOffset(const CFX_Matrix* pMatrix, SkPoint* delta) { 904 CFX_Matrix identityMatrix; 905 if (!pMatrix) 906 pMatrix = &identityMatrix; 907 delta->set(pMatrix->e - m_drawMatrix.e, pMatrix->f - m_drawMatrix.f); 908 if (!delta->fX && !delta->fY) 909 return true; 910 SkMatrix drawMatrix = ToSkMatrix(m_drawMatrix); 911 if (!(drawMatrix.getType() & ~SkMatrix::kTranslate_Mask)) 912 return true; 913 SkMatrix invDrawMatrix; 914 if (!drawMatrix.invert(&invDrawMatrix)) 915 return false; 916 SkMatrix invNewMatrix; 917 SkMatrix newMatrix = ToSkMatrix(*pMatrix); 918 if (!newMatrix.invert(&invNewMatrix)) 919 return false; 920 delta->set(invDrawMatrix.getTranslateX() - invNewMatrix.getTranslateX(), 921 invDrawMatrix.getTranslateY() - invNewMatrix.getTranslateY()); 922 return true; 923 } 924 925 // returns true if caller should apply command to skia canvas 926 bool ClipSave() { 927 if (m_debugDisable) 928 return false; 929 Dump(__func__); 930 int count = m_commands.count(); 931 if (m_commandIndex < count - 1) { 932 if (Clip::kSave == m_commands[m_commandIndex + 1]) { 933 ++m_commandIndex; 934 return true; 935 } 936 Flush(); 937 AdjustClip(m_commandIndex); 938 m_commands[++m_commandIndex] = Clip::kSave; 939 m_clips[m_commandIndex] = m_skEmptyPath; 940 } else { 941 AdjustClip(m_commandIndex); 942 m_commands.push(Clip::kSave); 943 m_clips.push_back(m_skEmptyPath); 944 ++m_commandIndex; 945 } 946 return true; 947 } 948 949 bool ClipRestore() { 950 if (m_debugDisable) 951 return false; 952 Dump(__func__); 953 while (Clip::kSave != m_commands[--m_commandIndex]) { 954 SkASSERT(m_commandIndex > 0); 955 } 956 return true; 957 } 958 959 bool DrawChanged(const CFX_Matrix* pMatrix, 960 const CFX_GraphStateData* pState, 961 uint32_t fill_color, 962 uint32_t stroke_color, 963 int fill_mode, 964 int blend_type, 965 bool group_knockout) const { 966 return MatrixChanged(pMatrix, m_drawMatrix) || 967 StateChanged(pState, m_drawState) || fill_color != m_fillColor || 968 stroke_color != m_strokeColor || 969 ((fill_mode & 3) == FXFILL_ALTERNATE) != 970 (m_skPath.getFillType() == SkPath::kEvenOdd_FillType) || 971 blend_type != m_blendType || group_knockout != m_groupKnockout; 972 } 973 974 bool FontChanged(CFX_Font* pFont, 975 const CFX_Matrix* pMatrix, 976 FX_FLOAT font_size, 977 uint32_t color) const { 978 return pFont != m_pFont || MatrixChanged(pMatrix, m_drawMatrix) || 979 font_size != m_fontSize || color != m_fillColor; 980 } 981 982 bool MatrixChanged(const CFX_Matrix* pMatrix, 983 const CFX_Matrix& refMatrix) const { 984 CFX_Matrix identityMatrix; 985 if (!pMatrix) 986 pMatrix = &identityMatrix; 987 return pMatrix->a != refMatrix.a || pMatrix->b != refMatrix.b || 988 pMatrix->c != refMatrix.c || pMatrix->d != refMatrix.d; 989 } 990 991 bool StateChanged(const CFX_GraphStateData* pState, 992 const CFX_GraphStateData& refState) const { 993 CFX_GraphStateData identityState; 994 if (!pState) 995 pState = &identityState; 996 return pState->m_LineWidth != refState.m_LineWidth || 997 pState->m_LineCap != refState.m_LineCap || 998 pState->m_LineJoin != refState.m_LineJoin || 999 pState->m_MiterLimit != refState.m_MiterLimit || 1000 DashChanged(pState, refState); 1001 } 1002 1003 bool DashChanged(const CFX_GraphStateData* pState, 1004 const CFX_GraphStateData& refState) const { 1005 bool dashArray = pState && pState->m_DashArray; 1006 if (!dashArray && !refState.m_DashArray) 1007 return false; 1008 if (!dashArray || !refState.m_DashArray) 1009 return true; 1010 if (pState->m_DashPhase != refState.m_DashPhase || 1011 pState->m_DashCount != refState.m_DashCount) { 1012 return true; 1013 } 1014 for (int index = 0; index < pState->m_DashCount; ++index) { 1015 if (pState->m_DashArray[index] != refState.m_DashArray[index]) 1016 return true; 1017 } 1018 return true; 1019 } 1020 1021 void AdjustClip(int limit) { 1022 while (m_clipIndex > limit) { 1023 do { 1024 --m_clipIndex; 1025 SkASSERT(m_clipIndex >= 0); 1026 } while (m_commands[m_clipIndex] != Clip::kSave); 1027 m_pDriver->SkiaCanvas()->restore(); 1028 } 1029 while (m_clipIndex < limit) { 1030 if (Clip::kSave == m_commands[m_clipIndex]) { 1031 m_pDriver->SkiaCanvas()->save(); 1032 } else { 1033 SkASSERT(Clip::kPath == m_commands[m_clipIndex]); 1034 m_pDriver->SkiaCanvas()->clipPath(m_clips[m_clipIndex], 1035 SkClipOp::kIntersect, true); 1036 } 1037 ++m_clipIndex; 1038 } 1039 } 1040 1041 void Flush() { 1042 if (m_debugDisable) 1043 return; 1044 Dump(__func__); 1045 if (Accumulator::kPath == m_type || Accumulator::kText == m_type) { 1046 AdjustClip(SkTMin(m_drawIndex, m_commands.count())); 1047 Accumulator::kPath == m_type ? FlushPath() : FlushText(); 1048 } 1049 } 1050 1051 void FlushForDraw() { 1052 if (m_debugDisable) 1053 return; 1054 Flush(); // draw any pending text or path 1055 AdjustClip(m_commandIndex); // set up clip stack with any pending state 1056 } 1057 1058 #if SHOW_SKIA_PATH 1059 void DumpPrefix(int index) const { 1060 if (index != m_commandIndex && index != m_drawIndex && 1061 index != m_clipIndex) { 1062 printf(" "); 1063 return; 1064 } 1065 printf("%c%c%c> ", index == m_commandIndex ? 'x' : '-', 1066 index == m_drawIndex ? 'd' : '-', index == m_clipIndex ? 'c' : '-'); 1067 } 1068 1069 void DumpEndPrefix() const { 1070 int index = m_commands.count(); 1071 if (index != m_commandIndex && index > m_drawIndex && index != m_clipIndex) 1072 return; 1073 printf("%c%c%c>\n", index == m_commandIndex ? 'x' : '-', 1074 index <= m_drawIndex ? 'd' : '-', index == m_clipIndex ? 'c' : '-'); 1075 } 1076 #endif // SHOW_SKIA_PATH 1077 1078 void Dump(const char* where) const { 1079 #if SHOW_SKIA_PATH 1080 printf("\n%s\nSkia Save Count %d:\n", where, 1081 m_pDriver->m_pCanvas->getSaveCount()); 1082 printf("Cache:\n"); 1083 for (int index = 0; index < m_commands.count(); ++index) { 1084 DumpPrefix(index); 1085 switch (m_commands[index]) { 1086 case Clip::kSave: 1087 printf("Save %d\n", ++m_debugSaveCounter); 1088 break; 1089 case Clip::kPath: 1090 m_clips[index].dump(); 1091 break; 1092 default: 1093 printf("unknown\n"); 1094 } 1095 } 1096 DumpEndPrefix(); 1097 #endif // SHOW_SKIA_PATH 1098 #ifdef SK_DEBUG 1099 int skCanvasSaveCount = m_pDriver->m_pCanvas->getSaveCount(); 1100 int cacheSaveCount = 1; 1101 SkASSERT(m_clipIndex <= m_commands.count()); 1102 for (int index = 0; index < m_clipIndex; ++index) 1103 cacheSaveCount += Clip::kSave == m_commands[index]; 1104 SkASSERT(skCanvasSaveCount == cacheSaveCount); 1105 #endif 1106 } 1107 1108 private: 1109 SkTArray<SkPath> m_clips; // stack of clips that may be reused 1110 SkTDArray<Clip> m_commands; // stack of clip-related commands 1111 SkTDArray<SkPoint> m_positions; // accumulator for text positions 1112 SkTDArray<uint16_t> m_glyphs; // accumulator for text glyphs 1113 SkPath m_skPath; // accumulator for path contours 1114 SkPath m_skEmptyPath; // used as placehold in the clips array 1115 CFX_Matrix m_drawMatrix; 1116 CFX_GraphStateData m_clipState; 1117 CFX_GraphStateData m_drawState; 1118 CFX_Matrix m_clipMatrix; 1119 CFX_SkiaDeviceDriver* m_pDriver; 1120 CFX_Font* m_pFont; 1121 FX_FLOAT m_fontSize; 1122 uint32_t m_fillColor; 1123 uint32_t m_strokeColor; 1124 int m_blendType; 1125 int m_commandIndex; // active position in clip command stack 1126 int m_drawIndex; // position of the pending path or text draw 1127 int m_clipIndex; // position reflecting depth of canvas clip stacck 1128 Accumulator m_type; // type of pending draw 1129 bool m_fillFullCover; 1130 bool m_fillPath; 1131 bool m_groupKnockout; 1132 bool m_debugDisable; // turn off cache for debugging 1133 #if SHOW_SKIA_PATH 1134 mutable int m_debugSaveCounter; 1135 #endif 1136 }; 1137 1138 // convert a stroking path to scanlines 1139 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, 1140 const CFX_GraphStateData* pGraphState, 1141 const SkMatrix& matrix) { 1142 SkPaint::Cap cap; 1143 switch (pGraphState->m_LineCap) { 1144 case CFX_GraphStateData::LineCapRound: 1145 cap = SkPaint::kRound_Cap; 1146 break; 1147 case CFX_GraphStateData::LineCapSquare: 1148 cap = SkPaint::kSquare_Cap; 1149 break; 1150 default: 1151 cap = SkPaint::kButt_Cap; 1152 break; 1153 } 1154 SkPaint::Join join; 1155 switch (pGraphState->m_LineJoin) { 1156 case CFX_GraphStateData::LineJoinRound: 1157 join = SkPaint::kRound_Join; 1158 break; 1159 case CFX_GraphStateData::LineJoinBevel: 1160 join = SkPaint::kBevel_Join; 1161 break; 1162 default: 1163 join = SkPaint::kMiter_Join; 1164 break; 1165 } 1166 SkMatrix inverse; 1167 if (!matrix.invert(&inverse)) 1168 return; // give up if the matrix is degenerate, and not invertable 1169 inverse.set(SkMatrix::kMTransX, 0); 1170 inverse.set(SkMatrix::kMTransY, 0); 1171 SkVector deviceUnits[2] = {{0, 1}, {1, 0}}; 1172 inverse.mapPoints(deviceUnits, SK_ARRAY_COUNT(deviceUnits)); 1173 FX_FLOAT width = 1174 SkTMax(pGraphState->m_LineWidth, 1175 SkTMin(deviceUnits[0].length(), deviceUnits[1].length())); 1176 if (pGraphState->m_DashArray) { 1177 int count = (pGraphState->m_DashCount + 1) / 2; 1178 SkScalar* intervals = FX_Alloc2D(SkScalar, count, sizeof(SkScalar)); 1179 // Set dash pattern 1180 for (int i = 0; i < count; i++) { 1181 FX_FLOAT on = pGraphState->m_DashArray[i * 2]; 1182 if (on <= 0.000001f) 1183 on = 1.f / 10; 1184 FX_FLOAT off = i * 2 + 1 == pGraphState->m_DashCount 1185 ? on 1186 : pGraphState->m_DashArray[i * 2 + 1]; 1187 if (off < 0) 1188 off = 0; 1189 intervals[i * 2] = on; 1190 intervals[i * 2 + 1] = off; 1191 } 1192 spaint->setPathEffect( 1193 SkDashPathEffect::Make(intervals, count * 2, pGraphState->m_DashPhase)); 1194 } 1195 spaint->setStyle(SkPaint::kStroke_Style); 1196 spaint->setAntiAlias(true); 1197 spaint->setStrokeWidth(width); 1198 spaint->setStrokeMiter(pGraphState->m_MiterLimit); 1199 spaint->setStrokeCap(cap); 1200 spaint->setStrokeJoin(join); 1201 } 1202 1203 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap, 1204 bool bRgbByteOrder, 1205 CFX_DIBitmap* pOriDevice, 1206 bool bGroupKnockout) 1207 : m_pBitmap(pBitmap), 1208 m_pOriDevice(pOriDevice), 1209 m_pRecorder(nullptr), 1210 m_pCache(new SkiaState(this)), 1211 #ifdef _SKIA_SUPPORT_PATHS_ 1212 m_pClipRgn(nullptr), 1213 m_FillFlags(0), 1214 m_bRgbByteOrder(bRgbByteOrder), 1215 #endif // _SKIA_SUPPORT_PATHS_ 1216 m_bGroupKnockout(bGroupKnockout) { 1217 SkBitmap skBitmap; 1218 SkASSERT(pBitmap->GetBPP() == 8 || pBitmap->GetBPP() == 32); 1219 SkImageInfo imageInfo = SkImageInfo::Make( 1220 pBitmap->GetWidth(), pBitmap->GetHeight(), 1221 pBitmap->GetBPP() == 8 ? kAlpha_8_SkColorType : kN32_SkColorType, 1222 kOpaque_SkAlphaType); 1223 skBitmap.installPixels(imageInfo, pBitmap->GetBuffer(), pBitmap->GetPitch(), 1224 nullptr, // FIXME(caryclark) set color table 1225 nullptr, nullptr); 1226 m_pCanvas = new SkCanvas(skBitmap); 1227 } 1228 1229 #ifdef _SKIA_SUPPORT_ 1230 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(int size_x, int size_y) 1231 : m_pBitmap(nullptr), 1232 m_pOriDevice(nullptr), 1233 m_pRecorder(new SkPictureRecorder), 1234 m_pCache(new SkiaState(this)), 1235 m_bGroupKnockout(false) { 1236 m_pRecorder->beginRecording(SkIntToScalar(size_x), SkIntToScalar(size_y)); 1237 m_pCanvas = m_pRecorder->getRecordingCanvas(); 1238 } 1239 1240 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkPictureRecorder* recorder) 1241 : m_pBitmap(nullptr), 1242 m_pOriDevice(nullptr), 1243 m_pRecorder(recorder), 1244 m_pCache(new SkiaState(this)), 1245 m_bGroupKnockout(false) { 1246 m_pCanvas = m_pRecorder->getRecordingCanvas(); 1247 } 1248 #endif // _SKIA_SUPPORT_ 1249 1250 CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() { 1251 Flush(); 1252 if (!m_pRecorder) 1253 delete m_pCanvas; 1254 } 1255 1256 void CFX_SkiaDeviceDriver::Flush() { 1257 m_pCache->Flush(); 1258 } 1259 1260 bool CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, 1261 const FXTEXT_CHARPOS* pCharPos, 1262 CFX_Font* pFont, 1263 const CFX_Matrix* pObject2Device, 1264 FX_FLOAT font_size, 1265 uint32_t color) { 1266 if (m_pCache->DrawText(nChars, pCharPos, pFont, pObject2Device, font_size, 1267 color)) { 1268 return true; 1269 } 1270 sk_sp<SkTypeface> typeface(SkSafeRef(pFont->GetDeviceCache())); 1271 SkPaint paint; 1272 paint.setAntiAlias(true); 1273 paint.setColor(color); 1274 paint.setTypeface(typeface); 1275 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 1276 paint.setHinting(SkPaint::kNo_Hinting); 1277 paint.setTextSize(SkTAbs(font_size)); 1278 paint.setSubpixelText(true); 1279 m_pCanvas->save(); 1280 SkScalar flip = font_size < 0 ? -1 : 1; 1281 SkScalar vFlip = flip; 1282 if (pFont->IsVertical()) 1283 vFlip *= -1; 1284 SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device, flip); 1285 m_pCanvas->concat(skMatrix); 1286 SkTDArray<SkPoint> positions; 1287 positions.setCount(nChars); 1288 SkTDArray<uint16_t> glyphs; 1289 glyphs.setCount(nChars); 1290 for (int index = 0; index < nChars; ++index) { 1291 const FXTEXT_CHARPOS& cp = pCharPos[index]; 1292 positions[index] = {cp.m_Origin.x * flip, cp.m_Origin.y * vFlip}; 1293 glyphs[index] = static_cast<uint16_t>(cp.m_GlyphIndex); 1294 } 1295 #ifdef _SKIA_SUPPORT_PATHS_ 1296 m_pBitmap->PreMultiply(); 1297 #endif // _SKIA_SUPPORT_PATHS_ 1298 m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint); 1299 m_pCanvas->restore(); 1300 1301 return true; 1302 } 1303 1304 int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const { 1305 switch (caps_id) { 1306 case FXDC_DEVICE_CLASS: 1307 return FXDC_DISPLAY; 1308 #ifdef _SKIA_SUPPORT_ 1309 case FXDC_PIXEL_WIDTH: 1310 return m_pCanvas->imageInfo().width(); 1311 case FXDC_PIXEL_HEIGHT: 1312 return m_pCanvas->imageInfo().height(); 1313 case FXDC_BITS_PIXEL: 1314 return 32; 1315 case FXDC_HORZ_SIZE: 1316 case FXDC_VERT_SIZE: 1317 return 0; 1318 case FXDC_RENDER_CAPS: 1319 return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | 1320 FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT | 1321 FXRC_FILLSTROKE_PATH | FXRC_SHADING; 1322 #endif // _SKIA_SUPPORT_ 1323 1324 #ifdef _SKIA_SUPPORT_PATHS_ 1325 case FXDC_PIXEL_WIDTH: 1326 return m_pBitmap->GetWidth(); 1327 case FXDC_PIXEL_HEIGHT: 1328 return m_pBitmap->GetHeight(); 1329 case FXDC_BITS_PIXEL: 1330 return m_pBitmap->GetBPP(); 1331 case FXDC_HORZ_SIZE: 1332 case FXDC_VERT_SIZE: 1333 return 0; 1334 case FXDC_RENDER_CAPS: { 1335 int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | 1336 FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_SHADING; 1337 if (m_pBitmap->HasAlpha()) { 1338 flags |= FXRC_ALPHA_OUTPUT; 1339 } else if (m_pBitmap->IsAlphaMask()) { 1340 if (m_pBitmap->GetBPP() == 1) { 1341 flags |= FXRC_BITMASK_OUTPUT; 1342 } else { 1343 flags |= FXRC_BYTEMASK_OUTPUT; 1344 } 1345 } 1346 if (m_pBitmap->IsCmykImage()) { 1347 flags |= FXRC_CMYK_OUTPUT; 1348 } 1349 return flags; 1350 } 1351 #endif // _SKIA_SUPPORT_PATHS_ 1352 } 1353 return 0; 1354 } 1355 1356 void CFX_SkiaDeviceDriver::SaveState() { 1357 if (!m_pCache->ClipSave()) 1358 m_pCanvas->save(); 1359 1360 #ifdef _SKIA_SUPPORT_PATHS_ 1361 std::unique_ptr<CFX_ClipRgn> pClip; 1362 if (m_pClipRgn) 1363 pClip = pdfium::MakeUnique<CFX_ClipRgn>(*m_pClipRgn); 1364 m_StateStack.push_back(std::move(pClip)); 1365 #endif // _SKIA_SUPPORT_PATHS_ 1366 } 1367 1368 void CFX_SkiaDeviceDriver::RestoreState(bool bKeepSaved) { 1369 if (!m_pCache->ClipRestore()) 1370 m_pCanvas->restore(); 1371 if (bKeepSaved && !m_pCache->ClipSave()) 1372 m_pCanvas->save(); 1373 #ifdef _SKIA_SUPPORT_PATHS_ 1374 m_pClipRgn.reset(); 1375 1376 if (m_StateStack.empty()) 1377 return; 1378 1379 if (bKeepSaved) { 1380 if (m_StateStack.back()) 1381 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(*m_StateStack.back()); 1382 } else { 1383 m_pClipRgn = std::move(m_StateStack.back()); 1384 m_StateStack.pop_back(); 1385 } 1386 #endif // _SKIA_SUPPORT_PATHS_ 1387 } 1388 1389 #ifdef _SKIA_SUPPORT_PATHS_ 1390 void CFX_SkiaDeviceDriver::SetClipMask(const FX_RECT& clipBox, 1391 const SkPath& path) { 1392 FX_RECT path_rect(clipBox.left, clipBox.top, clipBox.right + 1, 1393 clipBox.bottom + 1); 1394 path_rect.Intersect(m_pClipRgn->GetBox()); 1395 CFX_DIBitmapRef mask; 1396 CFX_DIBitmap* pThisLayer = mask.Emplace(); 1397 pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask); 1398 pThisLayer->Clear(0); 1399 1400 SkImageInfo imageInfo = 1401 SkImageInfo::Make(pThisLayer->GetWidth(), pThisLayer->GetHeight(), 1402 SkColorType::kAlpha_8_SkColorType, kOpaque_SkAlphaType); 1403 SkBitmap bitmap; 1404 bitmap.installPixels(imageInfo, pThisLayer->GetBuffer(), 1405 pThisLayer->GetPitch(), nullptr, nullptr, nullptr); 1406 SkCanvas* canvas = new SkCanvas(bitmap); 1407 canvas->translate( 1408 -path_rect.left, 1409 -path_rect.top); // FIXME(caryclark) wrong sign(s)? upside down? 1410 SkPaint paint; 1411 paint.setAntiAlias((m_FillFlags & FXFILL_NOPATHSMOOTH) == 0); 1412 canvas->drawPath(path, paint); 1413 m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask); 1414 delete canvas; 1415 } 1416 #endif // _SKIA_SUPPORT_PATHS_ 1417 1418 bool CFX_SkiaDeviceDriver::SetClip_PathFill( 1419 const CFX_PathData* pPathData, // path info 1420 const CFX_Matrix* pObject2Device, // flips object's y-axis 1421 int fill_mode // fill mode, WINDING or ALTERNATE 1422 ) { 1423 CFX_Matrix identity; 1424 const CFX_Matrix* deviceMatrix = pObject2Device ? pObject2Device : &identity; 1425 bool cached = m_pCache->SetClipFill(pPathData, deviceMatrix, fill_mode); 1426 1427 #ifdef _SKIA_SUPPORT_PATHS_ 1428 m_FillFlags = fill_mode; 1429 if (!m_pClipRgn) { 1430 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>( 1431 GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); 1432 } 1433 #endif // _SKIA_SUPPORT_PATHS_ 1434 if (pPathData->GetPoints().size() == 5 || 1435 pPathData->GetPoints().size() == 4) { 1436 CFX_FloatRect rectf; 1437 if (pPathData->IsRect(deviceMatrix, &rectf)) { 1438 rectf.Intersect( 1439 CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH), 1440 (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT))); 1441 // note that PDF's y-axis goes up; Skia's y-axis goes down 1442 if (!cached) { 1443 SkRect skClipRect = 1444 SkRect::MakeLTRB(rectf.left, rectf.bottom, rectf.right, rectf.top); 1445 DebugDrawSkiaClipRect(m_pCanvas, skClipRect); 1446 m_pCanvas->clipRect(skClipRect, SkClipOp::kIntersect, true); 1447 } 1448 1449 #ifdef _SKIA_SUPPORT_PATHS_ 1450 FX_RECT rect = rectf.GetOuterRect(); 1451 m_pClipRgn->IntersectRect(rect); 1452 #endif // _SKIA_SUPPORT_PATHS_ 1453 DebugShowCanvasClip(m_pCanvas); 1454 return true; 1455 } 1456 } 1457 SkPath skClipPath = BuildPath(pPathData); 1458 skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE 1459 ? SkPath::kEvenOdd_FillType 1460 : SkPath::kWinding_FillType); 1461 SkMatrix skMatrix = ToSkMatrix(*deviceMatrix); 1462 skClipPath.transform(skMatrix); 1463 DebugShowSkiaPath(skClipPath); 1464 if (!cached) { 1465 DebugDrawSkiaClipPath(m_pCanvas, skClipPath); 1466 m_pCanvas->clipPath(skClipPath, SkClipOp::kIntersect, true); 1467 } 1468 #ifdef _SKIA_SUPPORT_PATHS_ 1469 FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH), 1470 GetDeviceCaps(FXDC_PIXEL_HEIGHT)); 1471 SetClipMask(clipBox, skClipPath); 1472 #endif // _SKIA_SUPPORT_PATHS_ 1473 DebugShowCanvasClip(m_pCanvas); 1474 return true; 1475 } 1476 1477 bool CFX_SkiaDeviceDriver::SetClip_PathStroke( 1478 const CFX_PathData* pPathData, // path info 1479 const CFX_Matrix* pObject2Device, // optional transformation 1480 const CFX_GraphStateData* pGraphState // graphic state, for pen attributes 1481 ) { 1482 bool cached = m_pCache->SetClipStroke(pPathData, pObject2Device, pGraphState); 1483 1484 #ifdef _SKIA_SUPPORT_PATHS_ 1485 if (!m_pClipRgn) { 1486 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>( 1487 GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); 1488 } 1489 #endif // _SKIA_SUPPORT_PATHS_ 1490 // build path data 1491 SkPath skPath = BuildPath(pPathData); 1492 SkMatrix skMatrix = ToSkMatrix(*pObject2Device); 1493 SkPaint skPaint; 1494 PaintStroke(&skPaint, pGraphState, skMatrix); 1495 SkPath dst_path; 1496 skPaint.getFillPath(skPath, &dst_path); 1497 dst_path.transform(skMatrix); 1498 if (!cached) { 1499 DebugDrawSkiaClipPath(m_pCanvas, dst_path); 1500 m_pCanvas->clipPath(dst_path, SkClipOp::kIntersect, true); 1501 } 1502 #ifdef _SKIA_SUPPORT_PATHS_ 1503 FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH), 1504 GetDeviceCaps(FXDC_PIXEL_HEIGHT)); 1505 SetClipMask(clipBox, dst_path); 1506 #endif // _SKIA_SUPPORT_PATHS_ 1507 DebugShowCanvasClip(m_pCanvas); 1508 return true; 1509 } 1510 1511 bool CFX_SkiaDeviceDriver::DrawPath( 1512 const CFX_PathData* pPathData, // path info 1513 const CFX_Matrix* pObject2Device, // optional transformation 1514 const CFX_GraphStateData* pGraphState, // graphic state, for pen attributes 1515 uint32_t fill_color, // fill color 1516 uint32_t stroke_color, // stroke color 1517 int fill_mode, // fill mode, WINDING or ALTERNATE. 0 for not filled 1518 int blend_type) { 1519 if (fill_mode & FX_ZEROAREA_FILL) 1520 return true; 1521 if (m_pCache->DrawPath(pPathData, pObject2Device, pGraphState, fill_color, 1522 stroke_color, fill_mode, blend_type)) { 1523 return true; 1524 } 1525 SkMatrix skMatrix; 1526 if (pObject2Device) 1527 skMatrix = ToSkMatrix(*pObject2Device); 1528 else 1529 skMatrix.setIdentity(); 1530 SkPaint skPaint; 1531 skPaint.setAntiAlias(true); 1532 if (fill_mode & FXFILL_FULLCOVER) 1533 skPaint.setBlendMode(SkBlendMode::kPlus); 1534 int stroke_alpha = FXARGB_A(stroke_color); 1535 if (pGraphState && stroke_alpha) 1536 PaintStroke(&skPaint, pGraphState, skMatrix); 1537 SkPath skPath = BuildPath(pPathData); 1538 m_pCanvas->save(); 1539 m_pCanvas->concat(skMatrix); 1540 if ((fill_mode & 3) && fill_color) { 1541 skPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE 1542 ? SkPath::kEvenOdd_FillType 1543 : SkPath::kWinding_FillType); 1544 SkPath strokePath; 1545 const SkPath* fillPath = &skPath; 1546 if (pGraphState && stroke_alpha) { 1547 if (m_bGroupKnockout) { 1548 skPaint.getFillPath(skPath, &strokePath); 1549 if (Op(skPath, strokePath, SkPathOp::kDifference_SkPathOp, 1550 &strokePath)) { 1551 fillPath = &strokePath; 1552 } 1553 } 1554 } 1555 skPaint.setStyle(SkPaint::kFill_Style); 1556 skPaint.setColor(fill_color); 1557 #ifdef _SKIA_SUPPORT_PATHS_ 1558 m_pBitmap->PreMultiply(); 1559 #endif // _SKIA_SUPPORT_PATHS_ 1560 DebugShowSkiaDrawPath(m_pCanvas, skPaint, *fillPath); 1561 m_pCanvas->drawPath(*fillPath, skPaint); 1562 } 1563 if (pGraphState && stroke_alpha) { 1564 skPaint.setStyle(SkPaint::kStroke_Style); 1565 skPaint.setColor(stroke_color); 1566 #ifdef _SKIA_SUPPORT_PATHS_ 1567 m_pBitmap->PreMultiply(); 1568 #endif // _SKIA_SUPPORT_PATHS_ 1569 DebugShowSkiaDrawPath(m_pCanvas, skPaint, skPath); 1570 m_pCanvas->drawPath(skPath, skPaint); 1571 } 1572 m_pCanvas->restore(); 1573 return true; 1574 } 1575 1576 bool CFX_SkiaDeviceDriver::DrawCosmeticLine(FX_FLOAT x1, 1577 FX_FLOAT y1, 1578 FX_FLOAT x2, 1579 FX_FLOAT y2, 1580 uint32_t color, 1581 int blend_type) { 1582 return false; 1583 } 1584 1585 bool CFX_SkiaDeviceDriver::FillRectWithBlend(const FX_RECT* pRect, 1586 uint32_t fill_color, 1587 int blend_type) { 1588 m_pCache->FlushForDraw(); 1589 SkPaint spaint; 1590 spaint.setAntiAlias(true); 1591 spaint.setColor(fill_color); 1592 spaint.setBlendMode(GetSkiaBlendMode(blend_type)); 1593 SkRect rect = 1594 SkRect::MakeLTRB(pRect->left, SkTMin(pRect->top, pRect->bottom), 1595 pRect->right, SkTMax(pRect->bottom, pRect->top)); 1596 DebugShowSkiaDrawRect(m_pCanvas, spaint, rect); 1597 m_pCanvas->drawRect(rect, spaint); 1598 return true; 1599 } 1600 1601 bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, 1602 const CFX_Matrix* pMatrix, 1603 const FX_RECT& clip_rect, 1604 int alpha, 1605 bool bAlphaMode) { 1606 m_pCache->FlushForDraw(); 1607 ShadingType shadingType = pPattern->GetShadingType(); 1608 if (kAxialShading != shadingType && kRadialShading != shadingType && 1609 kCoonsPatchMeshShading != shadingType) { 1610 // TODO(caryclark) more types 1611 return false; 1612 } 1613 int csFamily = pPattern->GetCS()->GetFamily(); 1614 if (PDFCS_DEVICERGB != csFamily && PDFCS_DEVICEGRAY != csFamily) 1615 return false; 1616 const std::vector<std::unique_ptr<CPDF_Function>>& pFuncs = 1617 pPattern->GetFuncs(); 1618 int nFuncs = pFuncs.size(); 1619 if (nFuncs > 1) // TODO(caryclark) remove this restriction 1620 return false; 1621 CPDF_Dictionary* pDict = pPattern->GetShadingObject()->GetDict(); 1622 CPDF_Array* pCoords = pDict->GetArrayFor("Coords"); 1623 if (!pCoords && kCoonsPatchMeshShading != shadingType) 1624 return false; 1625 // TODO(caryclark) Respect Domain[0], Domain[1]. (Don't know what they do 1626 // yet.) 1627 SkTDArray<SkColor> skColors; 1628 SkTDArray<SkScalar> skPos; 1629 for (int j = 0; j < nFuncs; j++) { 1630 if (!pFuncs[j]) 1631 continue; 1632 1633 if (const CPDF_SampledFunc* pSampledFunc = pFuncs[j]->ToSampledFunc()) { 1634 /* TODO(caryclark) 1635 Type 0 Sampled Functions in PostScript can also have an Order integer 1636 in the dictionary. PDFium doesn't appear to check for this anywhere. 1637 */ 1638 if (!AddSamples(pSampledFunc, &skColors, &skPos)) 1639 return false; 1640 } else if (const CPDF_ExpIntFunc* pExpIntFuc = pFuncs[j]->ToExpIntFunc()) { 1641 if (!AddColors(pExpIntFuc, &skColors)) 1642 return false; 1643 skPos.push(0); 1644 skPos.push(1); 1645 } else if (const CPDF_StitchFunc* pStitchFunc = pFuncs[j]->ToStitchFunc()) { 1646 if (!AddStitching(pStitchFunc, &skColors, &skPos)) 1647 return false; 1648 } else { 1649 return false; 1650 } 1651 } 1652 CPDF_Array* pArray = pDict->GetArrayFor("Extend"); 1653 bool clipStart = !pArray || !pArray->GetIntegerAt(0); 1654 bool clipEnd = !pArray || !pArray->GetIntegerAt(1); 1655 SkPaint paint; 1656 paint.setAntiAlias(true); 1657 paint.setAlpha(alpha); 1658 SkMatrix skMatrix = ToSkMatrix(*pMatrix); 1659 SkRect skRect = SkRect::MakeLTRB(clip_rect.left, clip_rect.top, 1660 clip_rect.right, clip_rect.bottom); 1661 SkPath skClip; 1662 SkPath skPath; 1663 if (kAxialShading == shadingType) { 1664 FX_FLOAT start_x = pCoords->GetNumberAt(0); 1665 FX_FLOAT start_y = pCoords->GetNumberAt(1); 1666 FX_FLOAT end_x = pCoords->GetNumberAt(2); 1667 FX_FLOAT end_y = pCoords->GetNumberAt(3); 1668 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; 1669 skMatrix.mapPoints(pts, SK_ARRAY_COUNT(pts)); 1670 paint.setShader(SkGradientShader::MakeLinear( 1671 pts, skColors.begin(), skPos.begin(), skColors.count(), 1672 SkShader::kClamp_TileMode)); 1673 if (clipStart || clipEnd) { 1674 // if the gradient is horizontal or vertical, modify the draw rectangle 1675 if (pts[0].fX == pts[1].fX) { // vertical 1676 if (pts[0].fY > pts[1].fY) { 1677 SkTSwap(pts[0].fY, pts[1].fY); 1678 SkTSwap(clipStart, clipEnd); 1679 } 1680 if (clipStart) 1681 skRect.fTop = SkTMax(skRect.fTop, pts[0].fY); 1682 if (clipEnd) 1683 skRect.fBottom = SkTMin(skRect.fBottom, pts[1].fY); 1684 } else if (pts[0].fY == pts[1].fY) { // horizontal 1685 if (pts[0].fX > pts[1].fX) { 1686 SkTSwap(pts[0].fX, pts[1].fX); 1687 SkTSwap(clipStart, clipEnd); 1688 } 1689 if (clipStart) 1690 skRect.fLeft = SkTMax(skRect.fLeft, pts[0].fX); 1691 if (clipEnd) 1692 skRect.fRight = SkTMin(skRect.fRight, pts[1].fX); 1693 } else { // if the gradient is angled and contained by the rect, clip 1694 SkPoint rectPts[4] = {{skRect.fLeft, skRect.fTop}, 1695 {skRect.fRight, skRect.fTop}, 1696 {skRect.fRight, skRect.fBottom}, 1697 {skRect.fLeft, skRect.fBottom}}; 1698 ClipAngledGradient(pts, rectPts, clipStart, clipEnd, &skClip); 1699 } 1700 } 1701 skPath.addRect(skRect); 1702 skMatrix.setIdentity(); 1703 } else if (kRadialShading == shadingType) { 1704 FX_FLOAT start_x = pCoords->GetNumberAt(0); 1705 FX_FLOAT start_y = pCoords->GetNumberAt(1); 1706 FX_FLOAT start_r = pCoords->GetNumberAt(2); 1707 FX_FLOAT end_x = pCoords->GetNumberAt(3); 1708 FX_FLOAT end_y = pCoords->GetNumberAt(4); 1709 FX_FLOAT end_r = pCoords->GetNumberAt(5); 1710 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; 1711 1712 paint.setShader(SkGradientShader::MakeTwoPointConical( 1713 pts[0], start_r, pts[1], end_r, skColors.begin(), skPos.begin(), 1714 skColors.count(), SkShader::kClamp_TileMode)); 1715 if (clipStart || clipEnd) { 1716 if (clipStart && start_r) 1717 skClip.addCircle(pts[0].fX, pts[0].fY, start_r); 1718 if (clipEnd) 1719 skClip.addCircle(pts[1].fX, pts[1].fY, end_r, SkPath::kCCW_Direction); 1720 else 1721 skClip.setFillType(SkPath::kInverseWinding_FillType); 1722 skClip.transform(skMatrix); 1723 } 1724 SkMatrix inverse; 1725 if (!skMatrix.invert(&inverse)) 1726 return false; 1727 skPath.addRect(skRect); 1728 skPath.transform(inverse); 1729 } else { 1730 ASSERT(kCoonsPatchMeshShading == shadingType); 1731 CPDF_Stream* pStream = ToStream(pPattern->GetShadingObject()); 1732 if (!pStream) 1733 return false; 1734 CPDF_MeshStream stream(shadingType, pPattern->GetFuncs(), pStream, 1735 pPattern->GetCS()); 1736 if (!stream.Load()) 1737 return false; 1738 SkPoint cubics[12]; 1739 SkColor colors[4]; 1740 m_pCanvas->save(); 1741 if (!skClip.isEmpty()) 1742 m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true); 1743 m_pCanvas->concat(skMatrix); 1744 while (!stream.BitStream()->IsEOF()) { 1745 uint32_t flag = stream.ReadFlag(); 1746 int iStartPoint = flag ? 4 : 0; 1747 int iStartColor = flag ? 2 : 0; 1748 if (flag) { 1749 SkPoint tempCubics[4]; 1750 for (int i = 0; i < (int)SK_ARRAY_COUNT(tempCubics); i++) 1751 tempCubics[i] = cubics[(flag * 3 + i) % 12]; 1752 FXSYS_memcpy(cubics, tempCubics, sizeof(tempCubics)); 1753 SkColor tempColors[2]; 1754 tempColors[0] = colors[flag]; 1755 tempColors[1] = colors[(flag + 1) % 4]; 1756 FXSYS_memcpy(colors, tempColors, sizeof(tempColors)); 1757 } 1758 for (int i = iStartPoint; i < (int)SK_ARRAY_COUNT(cubics); i++) { 1759 CFX_PointF point = stream.ReadCoords(); 1760 cubics[i].fX = point.x; 1761 cubics[i].fY = point.y; 1762 } 1763 for (int i = iStartColor; i < (int)SK_ARRAY_COUNT(colors); i++) { 1764 FX_FLOAT r; 1765 FX_FLOAT g; 1766 FX_FLOAT b; 1767 std::tie(r, g, b) = stream.ReadColor(); 1768 colors[i] = SkColorSetARGBInline(0xFF, (U8CPU)(r * 255), 1769 (U8CPU)(g * 255), (U8CPU)(b * 255)); 1770 } 1771 m_pCanvas->drawPatch(cubics, colors, nullptr, paint); 1772 } 1773 m_pCanvas->restore(); 1774 return true; 1775 } 1776 m_pCanvas->save(); 1777 if (!skClip.isEmpty()) 1778 m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true); 1779 m_pCanvas->concat(skMatrix); 1780 m_pCanvas->drawPath(skPath, paint); 1781 m_pCanvas->restore(); 1782 return true; 1783 } 1784 1785 uint8_t* CFX_SkiaDeviceDriver::GetBuffer() const { 1786 return m_pBitmap->GetBuffer(); 1787 } 1788 1789 bool CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { 1790 // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead 1791 pRect->left = 0; 1792 pRect->top = 0; 1793 const SkImageInfo& canvasSize = m_pCanvas->imageInfo(); 1794 pRect->right = canvasSize.width(); 1795 pRect->bottom = canvasSize.height(); 1796 return true; 1797 } 1798 1799 bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { 1800 if (!m_pBitmap) 1801 return true; 1802 uint8_t* srcBuffer = m_pBitmap->GetBuffer(); 1803 if (!srcBuffer) 1804 return true; 1805 #ifdef _SKIA_SUPPORT_ 1806 m_pCache->FlushForDraw(); 1807 int srcWidth = m_pBitmap->GetWidth(); 1808 int srcHeight = m_pBitmap->GetHeight(); 1809 int srcRowBytes = srcWidth * sizeof(uint32_t); 1810 SkImageInfo srcImageInfo = SkImageInfo::Make( 1811 srcWidth, srcHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType); 1812 SkBitmap skSrcBitmap; 1813 skSrcBitmap.installPixels(srcImageInfo, srcBuffer, srcRowBytes, nullptr, 1814 nullptr, nullptr); 1815 SkASSERT(pBitmap); 1816 uint8_t* dstBuffer = pBitmap->GetBuffer(); 1817 SkASSERT(dstBuffer); 1818 int dstWidth = pBitmap->GetWidth(); 1819 int dstHeight = pBitmap->GetHeight(); 1820 int dstRowBytes = dstWidth * sizeof(uint32_t); 1821 SkImageInfo dstImageInfo = SkImageInfo::Make( 1822 dstWidth, dstHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType); 1823 SkBitmap skDstBitmap; 1824 skDstBitmap.installPixels(dstImageInfo, dstBuffer, dstRowBytes, nullptr, 1825 nullptr, nullptr); 1826 SkCanvas canvas(skDstBitmap); 1827 canvas.drawBitmap(skSrcBitmap, left, top, nullptr); 1828 return true; 1829 #endif // _SKIA_SUPPORT_ 1830 1831 #ifdef _SKIA_SUPPORT_PATHS_ 1832 Flush(); 1833 m_pBitmap->UnPreMultiply(); 1834 FX_RECT rect(left, top, left + pBitmap->GetWidth(), 1835 top + pBitmap->GetHeight()); 1836 std::unique_ptr<CFX_DIBitmap> pBack; 1837 if (m_pOriDevice) { 1838 pBack = m_pOriDevice->Clone(&rect); 1839 if (!pBack) 1840 return true; 1841 1842 pBack->CompositeBitmap(0, 0, pBack->GetWidth(), pBack->GetHeight(), 1843 m_pBitmap, 0, 0); 1844 } else { 1845 pBack = m_pBitmap->Clone(&rect); 1846 if (!pBack) 1847 return true; 1848 } 1849 1850 bool bRet = true; 1851 left = std::min(left, 0); 1852 top = std::min(top, 0); 1853 if (m_bRgbByteOrder) { 1854 RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(), 1855 pBack.get(), left, top); 1856 } else { 1857 bRet = pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), 1858 pBack.get(), left, top); 1859 } 1860 return bRet; 1861 #endif // _SKIA_SUPPORT_PATHS_ 1862 } 1863 1864 CFX_DIBitmap* CFX_SkiaDeviceDriver::GetBackDrop() { 1865 return m_pOriDevice; 1866 } 1867 1868 bool CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, 1869 uint32_t argb, 1870 const FX_RECT* pSrcRect, 1871 int left, 1872 int top, 1873 int blend_type) { 1874 if (!m_pBitmap || !m_pBitmap->GetBuffer()) 1875 return true; 1876 1877 #ifdef _SKIA_SUPPORT_ 1878 CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), left, 1879 top + pBitmap->GetHeight()); 1880 void* dummy; 1881 return StartDIBits(pBitmap, 0xFF, argb, &m, 0, dummy, blend_type); 1882 #endif // _SKIA_SUPPORT_ 1883 1884 #ifdef _SKIA_SUPPORT_PATHS_ 1885 Flush(); 1886 if (pBitmap->IsAlphaMask()) { 1887 return m_pBitmap->CompositeMask( 1888 left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb, 1889 pSrcRect->left, pSrcRect->top, blend_type, m_pClipRgn.get(), 1890 m_bRgbByteOrder, 0, nullptr); 1891 } 1892 return m_pBitmap->CompositeBitmap( 1893 left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, pSrcRect->left, 1894 pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder, nullptr); 1895 #endif // _SKIA_SUPPORT_PATHS_ 1896 } 1897 1898 bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, 1899 uint32_t argb, 1900 int dest_left, 1901 int dest_top, 1902 int dest_width, 1903 int dest_height, 1904 const FX_RECT* pClipRect, 1905 uint32_t flags, 1906 int blend_type) { 1907 #ifdef _SKIA_SUPPORT_ 1908 m_pCache->FlushForDraw(); 1909 if (!m_pBitmap->GetBuffer()) 1910 return true; 1911 CFX_Matrix m(dest_width, 0, 0, -dest_height, dest_left, 1912 dest_top + dest_height); 1913 1914 m_pCanvas->save(); 1915 SkRect skClipRect = SkRect::MakeLTRB(pClipRect->left, pClipRect->bottom, 1916 pClipRect->right, pClipRect->top); 1917 m_pCanvas->clipRect(skClipRect, SkClipOp::kIntersect, true); 1918 void* dummy; 1919 bool result = StartDIBits(pSource, 0xFF, argb, &m, 0, dummy, blend_type); 1920 m_pCanvas->restore(); 1921 1922 return result; 1923 #endif // _SKIA_SUPPORT_ 1924 1925 #ifdef _SKIA_SUPPORT_PATHS_ 1926 if (dest_width == pSource->GetWidth() && 1927 dest_height == pSource->GetHeight()) { 1928 FX_RECT rect(0, 0, dest_width, dest_height); 1929 return SetDIBits(pSource, argb, &rect, dest_left, dest_top, blend_type); 1930 } 1931 Flush(); 1932 FX_RECT dest_rect(dest_left, dest_top, dest_left + dest_width, 1933 dest_top + dest_height); 1934 dest_rect.Normalize(); 1935 FX_RECT dest_clip = dest_rect; 1936 dest_clip.Intersect(*pClipRect); 1937 CFX_BitmapComposer composer; 1938 composer.Compose(m_pBitmap, m_pClipRgn.get(), 255, argb, dest_clip, false, 1939 false, false, m_bRgbByteOrder, 0, nullptr, blend_type); 1940 dest_clip.Offset(-dest_rect.left, -dest_rect.top); 1941 CFX_ImageStretcher stretcher(&composer, pSource, dest_width, dest_height, 1942 dest_clip, flags); 1943 if (stretcher.Start()) 1944 stretcher.Continue(nullptr); 1945 return true; 1946 #endif // _SKIA_SUPPORT_PATHS_ 1947 } 1948 1949 bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, 1950 int bitmap_alpha, 1951 uint32_t argb, 1952 const CFX_Matrix* pMatrix, 1953 uint32_t render_flags, 1954 void*& handle, 1955 int blend_type) { 1956 #ifdef _SKIA_SUPPORT_ 1957 m_pCache->FlushForDraw(); 1958 DebugValidate(m_pBitmap, m_pOriDevice); 1959 SkColorTable* ct = nullptr; 1960 std::unique_ptr<uint8_t, FxFreeDeleter> dst8Storage; 1961 std::unique_ptr<uint32_t, FxFreeDeleter> dst32Storage; 1962 SkBitmap skBitmap; 1963 int width, height; 1964 if (!Upsample(pSource, dst8Storage, dst32Storage, &ct, &skBitmap, &width, 1965 &height, false)) { 1966 return false; 1967 } 1968 m_pCanvas->save(); 1969 SkMatrix skMatrix; 1970 SetBitmapMatrix(pMatrix, width, height, &skMatrix); 1971 m_pCanvas->concat(skMatrix); 1972 SkPaint paint; 1973 SetBitmapPaint(pSource->IsAlphaMask(), argb, bitmap_alpha, blend_type, 1974 &paint); 1975 // TODO(caryclark) Once Skia supports 8 bit src to 8 bit dst remove this 1976 if (m_pBitmap && m_pBitmap->GetBPP() == 8 && pSource->GetBPP() == 8) { 1977 SkMatrix inv; 1978 SkAssertResult(skMatrix.invert(&inv)); 1979 for (int y = 0; y < m_pBitmap->GetHeight(); ++y) { 1980 for (int x = 0; x < m_pBitmap->GetWidth(); ++x) { 1981 SkPoint src = {x + 0.5f, y + 0.5f}; 1982 inv.mapPoints(&src, 1); 1983 // TODO(caryclark) Why does the matrix map require clamping? 1984 src.fX = SkTMax(0.5f, SkTMin(src.fX, width - 0.5f)); 1985 src.fY = SkTMax(0.5f, SkTMin(src.fY, height - 0.5f)); 1986 m_pBitmap->SetPixel(x, y, skBitmap.getColor(src.fX, src.fY)); 1987 } 1988 } 1989 } else { 1990 m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint); 1991 } 1992 m_pCanvas->restore(); 1993 if (ct) 1994 ct->unref(); 1995 DebugValidate(m_pBitmap, m_pOriDevice); 1996 #endif // _SKIA_SUPPORT_ 1997 1998 #ifdef _SKIA_SUPPORT_PATHS_ 1999 Flush(); 2000 if (!m_pBitmap->GetBuffer()) 2001 return true; 2002 m_pBitmap->UnPreMultiply(); 2003 CFX_ImageRenderer* pRenderer = new CFX_ImageRenderer; 2004 pRenderer->Start(m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb, 2005 pMatrix, render_flags, m_bRgbByteOrder, 0, nullptr); 2006 handle = pRenderer; 2007 #endif // _SKIA_SUPPORT_PATHS_ 2008 return true; 2009 } 2010 2011 bool CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) { 2012 #ifdef _SKIA_SUPPORT_ 2013 m_pCache->FlushForDraw(); 2014 return false; 2015 #endif // _SKIA_SUPPORT_ 2016 2017 #ifdef _SKIA_SUPPORT_PATHS_ 2018 Flush(); 2019 if (!m_pBitmap->GetBuffer()) { 2020 return true; 2021 } 2022 return static_cast<CFX_ImageRenderer*>(handle)->Continue(pPause); 2023 #endif // _SKIA_SUPPORT_PATHS_ 2024 } 2025 2026 #if defined _SKIA_SUPPORT_ 2027 void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) { 2028 pDIBitmap->PreMultiply(); 2029 } 2030 #endif // _SKIA_SUPPORT_ 2031 2032 void CFX_DIBitmap::PreMultiply() { 2033 if (this->GetBPP() != 32) 2034 return; 2035 void* buffer = this->GetBuffer(); 2036 if (!buffer) 2037 return; 2038 #if defined _SKIA_SUPPORT_PATHS_ 2039 Format priorFormat = m_nFormat; 2040 m_nFormat = Format::kPreMultiplied; 2041 if (priorFormat != Format::kUnPreMultiplied) 2042 return; 2043 #endif 2044 int height = this->GetHeight(); 2045 int width = this->GetWidth(); 2046 int rowBytes = this->GetPitch(); 2047 SkImageInfo unpremultipliedInfo = 2048 SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType); 2049 SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes); 2050 SkImageInfo premultipliedInfo = 2051 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); 2052 SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes); 2053 unpremultiplied.readPixels(premultiplied); 2054 this->DebugVerifyBitmapIsPreMultiplied(); 2055 } 2056 2057 #ifdef _SKIA_SUPPORT_PATHS_ 2058 void CFX_DIBitmap::UnPreMultiply() { 2059 if (this->GetBPP() != 32) 2060 return; 2061 void* buffer = this->GetBuffer(); 2062 if (!buffer) 2063 return; 2064 Format priorFormat = m_nFormat; 2065 m_nFormat = Format::kUnPreMultiplied; 2066 if (priorFormat != Format::kPreMultiplied) 2067 return; 2068 this->DebugVerifyBitmapIsPreMultiplied(); 2069 int height = this->GetHeight(); 2070 int width = this->GetWidth(); 2071 int rowBytes = this->GetPitch(); 2072 SkImageInfo premultipliedInfo = 2073 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); 2074 SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes); 2075 SkImageInfo unpremultipliedInfo = 2076 SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType); 2077 SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes); 2078 premultiplied.readPixels(unpremultiplied); 2079 } 2080 #endif // _SKIA_SUPPORT_PATHS_ 2081 2082 #ifdef _SKIA_SUPPORT_ 2083 bool CFX_SkiaDeviceDriver::DrawBitsWithMask(const CFX_DIBSource* pSource, 2084 const CFX_DIBSource* pMask, 2085 int bitmap_alpha, 2086 const CFX_Matrix* pMatrix, 2087 int blend_type) { 2088 DebugValidate(m_pBitmap, m_pOriDevice); 2089 SkColorTable* srcCt = nullptr; 2090 SkColorTable* maskCt = nullptr; 2091 std::unique_ptr<uint8_t, FxFreeDeleter> src8Storage, mask8Storage; 2092 std::unique_ptr<uint32_t, FxFreeDeleter> src32Storage, mask32Storage; 2093 SkBitmap skBitmap, skMask; 2094 int srcWidth, srcHeight, maskWidth, maskHeight; 2095 if (!Upsample(pSource, src8Storage, src32Storage, &srcCt, &skBitmap, 2096 &srcWidth, &srcHeight, false)) { 2097 return false; 2098 } 2099 if (!Upsample(pMask, mask8Storage, mask32Storage, &maskCt, &skMask, 2100 &maskWidth, &maskHeight, true)) { 2101 return false; 2102 } 2103 m_pCanvas->save(); 2104 SkMatrix skMatrix; 2105 SetBitmapMatrix(pMatrix, srcWidth, srcHeight, &skMatrix); 2106 m_pCanvas->concat(skMatrix); 2107 SkPaint paint; 2108 SetBitmapPaint(pSource->IsAlphaMask(), 0xFFFFFFFF, bitmap_alpha, blend_type, 2109 &paint); 2110 sk_sp<SkImage> skSrc = SkImage::MakeFromBitmap(skBitmap); 2111 sk_sp<SkShader> skSrcShader = 2112 skSrc->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 2113 sk_sp<SkImage> skMaskImage = SkImage::MakeFromBitmap(skMask); 2114 sk_sp<SkShader> skMaskShader = skMaskImage->makeShader( 2115 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 2116 paint.setShader(SkShader::MakeComposeShader(skMaskShader, skSrcShader, 2117 SkBlendMode::kSrcIn)); 2118 SkRect r = {0, 0, SkIntToScalar(srcWidth), SkIntToScalar(srcHeight)}; 2119 m_pCanvas->drawRect(r, paint); 2120 m_pCanvas->restore(); 2121 if (srcCt) 2122 srcCt->unref(); 2123 DebugValidate(m_pBitmap, m_pOriDevice); 2124 return true; 2125 } 2126 2127 bool CFX_SkiaDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap, 2128 const CFX_DIBSource* pMask, 2129 int dest_left, 2130 int dest_top, 2131 int bitmap_alpha, 2132 int blend_type) { 2133 if (!m_pBitmap || !m_pBitmap->GetBuffer()) 2134 return true; 2135 CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), dest_left, 2136 dest_top + pBitmap->GetHeight()); 2137 return DrawBitsWithMask(pBitmap, pMask, bitmap_alpha, &m, blend_type); 2138 } 2139 2140 void CFX_SkiaDeviceDriver::Clear(uint32_t color) { 2141 m_pCanvas->clear(color); 2142 } 2143 #endif // _SKIA_SUPPORT_ 2144 2145 void CFX_SkiaDeviceDriver::Dump() const { 2146 #if SHOW_SKIA_PATH && defined _SKIA_SUPPORT_ 2147 if (m_pCache) 2148 m_pCache->Dump(this); 2149 #endif // SHOW_SKIA_PATH && defined _SKIA_SUPPORT_ 2150 } 2151 2152 #ifdef _SKIA_SUPPORT_ 2153 void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const { 2154 if (m_pOriDevice) 2155 m_pOriDevice->DebugVerifyBitmapIsPreMultiplied(); 2156 } 2157 #endif // _SKIA_SUPPORT_ 2158 2159 CFX_FxgeDevice::CFX_FxgeDevice() { 2160 #ifdef _SKIA_SUPPORT_ 2161 m_bOwnedBitmap = false; 2162 #endif // _SKIA_SUPPORT_ 2163 } 2164 2165 #ifdef _SKIA_SUPPORT_ 2166 void CFX_FxgeDevice::Clear(uint32_t color) { 2167 CFX_SkiaDeviceDriver* skDriver = 2168 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); 2169 skDriver->Clear(color); 2170 } 2171 2172 SkPictureRecorder* CFX_FxgeDevice::CreateRecorder(int size_x, int size_y) { 2173 CFX_SkiaDeviceDriver* skDriver = new CFX_SkiaDeviceDriver(size_x, size_y); 2174 SetDeviceDriver(pdfium::WrapUnique(skDriver)); 2175 return skDriver->GetRecorder(); 2176 } 2177 #endif // _SKIA_SUPPORT_ 2178 2179 bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap, 2180 bool bRgbByteOrder, 2181 CFX_DIBitmap* pOriDevice, 2182 bool bGroupKnockout) { 2183 if (!pBitmap) 2184 return false; 2185 SetBitmap(pBitmap); 2186 SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>( 2187 pBitmap, bRgbByteOrder, pOriDevice, bGroupKnockout)); 2188 return true; 2189 } 2190 2191 #ifdef _SKIA_SUPPORT_ 2192 bool CFX_FxgeDevice::AttachRecorder(SkPictureRecorder* recorder) { 2193 if (!recorder) 2194 return false; 2195 SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(recorder)); 2196 return true; 2197 } 2198 #endif // _SKIA_SUPPORT_ 2199 2200 bool CFX_FxgeDevice::Create(int width, 2201 int height, 2202 FXDIB_Format format, 2203 CFX_DIBitmap* pOriDevice) { 2204 m_bOwnedBitmap = true; 2205 CFX_DIBitmap* pBitmap = new CFX_DIBitmap; 2206 if (!pBitmap->Create(width, height, format)) { 2207 delete pBitmap; 2208 return false; 2209 } 2210 SetBitmap(pBitmap); 2211 SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(pBitmap, false, 2212 pOriDevice, false)); 2213 return true; 2214 } 2215 2216 CFX_FxgeDevice::~CFX_FxgeDevice() { 2217 #ifdef _SKIA_SUPPORT_ 2218 Flush(); 2219 // call destructor of CFX_RenderDevice / CFX_SkiaDeviceDriver immediately 2220 if (m_bOwnedBitmap && GetBitmap()) 2221 delete GetBitmap(); 2222 #endif // _SKIA_SUPPORT_ 2223 } 2224 2225 #ifdef _SKIA_SUPPORT_ 2226 void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const { 2227 #ifdef SK_DEBUG 2228 CFX_SkiaDeviceDriver* skDriver = 2229 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); 2230 if (skDriver) 2231 skDriver->DebugVerifyBitmapIsPreMultiplied(); 2232 #endif // SK_DEBUG 2233 } 2234 2235 bool CFX_FxgeDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap, 2236 const CFX_DIBSource* pMask, 2237 int left, 2238 int top, 2239 int bitmap_alpha, 2240 int blend_type) { 2241 CFX_SkiaDeviceDriver* skDriver = 2242 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); 2243 if (skDriver) 2244 return skDriver->SetBitsWithMask(pBitmap, pMask, left, top, bitmap_alpha, 2245 blend_type); 2246 return false; 2247 } 2248 #endif // _SKIA_SUPPORT_ 2249 2250 void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const { 2251 #ifdef SK_DEBUG 2252 SkASSERT(32 == GetBPP()); 2253 const uint32_t* buffer = (const uint32_t*)(opt ? opt : GetBuffer()); 2254 int width = GetWidth(); 2255 int height = GetHeight(); 2256 // verify that input is really premultiplied 2257 for (int y = 0; y < height; ++y) { 2258 const uint32_t* srcRow = buffer + y * width; 2259 for (int x = 0; x < width; ++x) { 2260 uint8_t a = SkGetPackedA32(srcRow[x]); 2261 uint8_t r = SkGetPackedR32(srcRow[x]); 2262 uint8_t g = SkGetPackedG32(srcRow[x]); 2263 uint8_t b = SkGetPackedB32(srcRow[x]); 2264 SkA32Assert(a); 2265 SkASSERT(r <= a); 2266 SkASSERT(g <= a); 2267 SkASSERT(b <= a); 2268 } 2269 } 2270 #endif // SK_DEBUG 2271 } 2272 2273 #ifdef _SKIA_SUPPORT_PATHS_ 2274 class CFX_Renderer { 2275 private: 2276 int m_Alpha, m_Red, m_Green, m_Blue, m_Gray; 2277 uint32_t m_Color; 2278 bool m_bFullCover; 2279 bool m_bRgbByteOrder; 2280 CFX_DIBitmap* m_pOriDevice; 2281 FX_RECT m_ClipBox; 2282 const CFX_DIBitmap* m_pClipMask; 2283 CFX_DIBitmap* m_pDevice; 2284 const CFX_ClipRgn* m_pClipRgn; 2285 void (CFX_Renderer::*composite_span)(uint8_t*, 2286 int, 2287 int, 2288 int, 2289 uint8_t*, 2290 int, 2291 int, 2292 uint8_t*, 2293 uint8_t*); 2294 2295 public: 2296 void prepare(unsigned) {} 2297 2298 void CompositeSpan(uint8_t* dest_scan, 2299 uint8_t* ori_scan, 2300 int Bpp, 2301 bool bDestAlpha, 2302 int span_left, 2303 int span_len, 2304 uint8_t* cover_scan, 2305 int clip_left, 2306 int clip_right, 2307 uint8_t* clip_scan) { 2308 ASSERT(!m_pDevice->IsCmykImage()); 2309 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2310 int col_end = (span_left + span_len) < clip_right 2311 ? span_len 2312 : (clip_right - span_left); 2313 if (Bpp) { 2314 dest_scan += col_start * Bpp; 2315 ori_scan += col_start * Bpp; 2316 } else { 2317 dest_scan += col_start / 8; 2318 ori_scan += col_start / 8; 2319 } 2320 if (m_bRgbByteOrder) { 2321 if (Bpp == 4 && bDestAlpha) { 2322 for (int col = col_start; col < col_end; col++) { 2323 int src_alpha; 2324 if (clip_scan) { 2325 src_alpha = m_Alpha * clip_scan[col] / 255; 2326 } else { 2327 src_alpha = m_Alpha; 2328 } 2329 uint8_t dest_alpha = 2330 ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255; 2331 dest_scan[3] = dest_alpha; 2332 int alpha_ratio = src_alpha * 255 / dest_alpha; 2333 if (m_bFullCover) { 2334 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); 2335 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); 2336 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); 2337 dest_scan++; 2338 ori_scan++; 2339 } else { 2340 int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); 2341 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); 2342 int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); 2343 ori_scan++; 2344 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); 2345 dest_scan++; 2346 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); 2347 dest_scan++; 2348 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); 2349 dest_scan += 2; 2350 } 2351 } 2352 return; 2353 } 2354 if (Bpp == 3 || Bpp == 4) { 2355 for (int col = col_start; col < col_end; col++) { 2356 int src_alpha; 2357 if (clip_scan) { 2358 src_alpha = m_Alpha * clip_scan[col] / 255; 2359 } else { 2360 src_alpha = m_Alpha; 2361 } 2362 int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha); 2363 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); 2364 int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha); 2365 ori_scan += Bpp - 2; 2366 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); 2367 dest_scan++; 2368 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); 2369 dest_scan++; 2370 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); 2371 dest_scan += Bpp - 2; 2372 } 2373 } 2374 return; 2375 } 2376 if (Bpp == 4 && bDestAlpha) { 2377 for (int col = col_start; col < col_end; col++) { 2378 int src_alpha; 2379 if (clip_scan) { 2380 src_alpha = m_Alpha * clip_scan[col] / 255; 2381 } else { 2382 src_alpha = m_Alpha; 2383 } 2384 int src_alpha_covered = src_alpha * cover_scan[col] / 255; 2385 if (src_alpha_covered == 0) { 2386 dest_scan += 4; 2387 continue; 2388 } 2389 if (cover_scan[col] == 255) { 2390 dest_scan[3] = src_alpha_covered; 2391 *dest_scan++ = m_Blue; 2392 *dest_scan++ = m_Green; 2393 *dest_scan = m_Red; 2394 dest_scan += 2; 2395 continue; 2396 } else { 2397 if (dest_scan[3] == 0) { 2398 dest_scan[3] = src_alpha_covered; 2399 *dest_scan++ = m_Blue; 2400 *dest_scan++ = m_Green; 2401 *dest_scan = m_Red; 2402 dest_scan += 2; 2403 continue; 2404 } 2405 uint8_t cover = cover_scan[col]; 2406 dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover); 2407 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover); 2408 dest_scan++; 2409 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover); 2410 dest_scan++; 2411 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover); 2412 dest_scan += 2; 2413 } 2414 } 2415 return; 2416 } 2417 if (Bpp == 3 || Bpp == 4) { 2418 for (int col = col_start; col < col_end; col++) { 2419 int src_alpha; 2420 if (clip_scan) { 2421 src_alpha = m_Alpha * clip_scan[col] / 255; 2422 } else { 2423 src_alpha = m_Alpha; 2424 } 2425 if (m_bFullCover) { 2426 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); 2427 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); 2428 *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); 2429 dest_scan += Bpp - 2; 2430 ori_scan += Bpp - 2; 2431 continue; 2432 } 2433 int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); 2434 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); 2435 int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); 2436 ori_scan += Bpp - 2; 2437 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); 2438 dest_scan++; 2439 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); 2440 dest_scan++; 2441 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); 2442 dest_scan += Bpp - 2; 2443 continue; 2444 } 2445 return; 2446 } 2447 if (Bpp == 1) { 2448 for (int col = col_start; col < col_end; col++) { 2449 int src_alpha; 2450 if (clip_scan) { 2451 src_alpha = m_Alpha * clip_scan[col] / 255; 2452 } else { 2453 src_alpha = m_Alpha; 2454 } 2455 if (m_bFullCover) { 2456 *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); 2457 } else { 2458 int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); 2459 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]); 2460 dest_scan++; 2461 } 2462 } 2463 } else { 2464 int index = 0; 2465 if (m_pDevice->GetPalette()) { 2466 for (int i = 0; i < 2; i++) { 2467 if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) { 2468 index = i; 2469 } 2470 } 2471 } else { 2472 index = ((uint8_t)m_Color == 0xff) ? 1 : 0; 2473 } 2474 uint8_t* dest_scan1 = dest_scan; 2475 for (int col = col_start; col < col_end; col++) { 2476 int src_alpha; 2477 if (clip_scan) { 2478 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2479 } else { 2480 src_alpha = m_Alpha * cover_scan[col] / 255; 2481 } 2482 if (src_alpha) { 2483 if (!index) { 2484 *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); 2485 } else { 2486 *dest_scan1 |= 1 << (7 - (col + span_left) % 8); 2487 } 2488 } 2489 dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; 2490 } 2491 } 2492 } 2493 2494 void CompositeSpan1bpp(uint8_t* dest_scan, 2495 int Bpp, 2496 int span_left, 2497 int span_len, 2498 uint8_t* cover_scan, 2499 int clip_left, 2500 int clip_right, 2501 uint8_t* clip_scan, 2502 uint8_t* dest_extra_alpha_scan) { 2503 ASSERT(!m_bRgbByteOrder); 2504 ASSERT(!m_pDevice->IsCmykImage()); 2505 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2506 int col_end = (span_left + span_len) < clip_right 2507 ? span_len 2508 : (clip_right - span_left); 2509 dest_scan += col_start / 8; 2510 int index = 0; 2511 if (m_pDevice->GetPalette()) { 2512 for (int i = 0; i < 2; i++) { 2513 if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) { 2514 index = i; 2515 } 2516 } 2517 } else { 2518 index = ((uint8_t)m_Color == 0xff) ? 1 : 0; 2519 } 2520 uint8_t* dest_scan1 = dest_scan; 2521 for (int col = col_start; col < col_end; col++) { 2522 int src_alpha; 2523 if (clip_scan) { 2524 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2525 } else { 2526 src_alpha = m_Alpha * cover_scan[col] / 255; 2527 } 2528 if (src_alpha) { 2529 if (!index) { 2530 *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); 2531 } else { 2532 *dest_scan1 |= 1 << (7 - (col + span_left) % 8); 2533 } 2534 } 2535 dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; 2536 } 2537 } 2538 2539 void CompositeSpanGray(uint8_t* dest_scan, 2540 int Bpp, 2541 int span_left, 2542 int span_len, 2543 uint8_t* cover_scan, 2544 int clip_left, 2545 int clip_right, 2546 uint8_t* clip_scan, 2547 uint8_t* dest_extra_alpha_scan) { 2548 ASSERT(!m_bRgbByteOrder); 2549 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2550 int col_end = (span_left + span_len) < clip_right 2551 ? span_len 2552 : (clip_right - span_left); 2553 dest_scan += col_start; 2554 if (dest_extra_alpha_scan) { 2555 for (int col = col_start; col < col_end; col++) { 2556 int src_alpha; 2557 if (m_bFullCover) { 2558 if (clip_scan) { 2559 src_alpha = m_Alpha * clip_scan[col] / 255; 2560 } else { 2561 src_alpha = m_Alpha; 2562 } 2563 } else { 2564 if (clip_scan) { 2565 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2566 } else { 2567 src_alpha = m_Alpha * cover_scan[col] / 255; 2568 } 2569 } 2570 if (src_alpha) { 2571 if (src_alpha == 255) { 2572 *dest_scan = m_Gray; 2573 *dest_extra_alpha_scan = m_Alpha; 2574 } else { 2575 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - 2576 (*dest_extra_alpha_scan) * src_alpha / 255; 2577 *dest_extra_alpha_scan++ = dest_alpha; 2578 int alpha_ratio = src_alpha * 255 / dest_alpha; 2579 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); 2580 dest_scan++; 2581 continue; 2582 } 2583 } 2584 dest_extra_alpha_scan++; 2585 dest_scan++; 2586 } 2587 } else { 2588 for (int col = col_start; col < col_end; col++) { 2589 int src_alpha; 2590 if (clip_scan) { 2591 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2592 } else { 2593 src_alpha = m_Alpha * cover_scan[col] / 255; 2594 } 2595 if (src_alpha) { 2596 if (src_alpha == 255) { 2597 *dest_scan = m_Gray; 2598 } else { 2599 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); 2600 } 2601 } 2602 dest_scan++; 2603 } 2604 } 2605 } 2606 2607 void CompositeSpanARGB(uint8_t* dest_scan, 2608 int Bpp, 2609 int span_left, 2610 int span_len, 2611 uint8_t* cover_scan, 2612 int clip_left, 2613 int clip_right, 2614 uint8_t* clip_scan, 2615 uint8_t* dest_extra_alpha_scan) { 2616 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2617 int col_end = (span_left + span_len) < clip_right 2618 ? span_len 2619 : (clip_right - span_left); 2620 dest_scan += col_start * Bpp; 2621 if (m_bRgbByteOrder) { 2622 for (int col = col_start; col < col_end; col++) { 2623 int src_alpha; 2624 if (m_bFullCover) { 2625 if (clip_scan) { 2626 src_alpha = m_Alpha * clip_scan[col] / 255; 2627 } else { 2628 src_alpha = m_Alpha; 2629 } 2630 } else { 2631 if (clip_scan) { 2632 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2633 } else { 2634 src_alpha = m_Alpha * cover_scan[col] / 255; 2635 } 2636 } 2637 if (src_alpha) { 2638 if (src_alpha == 255) { 2639 *(uint32_t*)dest_scan = m_Color; 2640 } else { 2641 uint8_t dest_alpha = 2642 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; 2643 dest_scan[3] = dest_alpha; 2644 int alpha_ratio = src_alpha * 255 / dest_alpha; 2645 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); 2646 dest_scan++; 2647 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); 2648 dest_scan++; 2649 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); 2650 dest_scan += 2; 2651 continue; 2652 } 2653 } 2654 dest_scan += 4; 2655 } 2656 return; 2657 } 2658 for (int col = col_start; col < col_end; col++) { 2659 int src_alpha; 2660 if (m_bFullCover) { 2661 if (clip_scan) { 2662 src_alpha = m_Alpha * clip_scan[col] / 255; 2663 } else { 2664 src_alpha = m_Alpha; 2665 } 2666 } else { 2667 if (clip_scan) { 2668 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2669 } else { 2670 src_alpha = m_Alpha * cover_scan[col] / 255; 2671 } 2672 } 2673 if (src_alpha) { 2674 if (src_alpha == 255) { 2675 *(uint32_t*)dest_scan = m_Color; 2676 } else { 2677 if (dest_scan[3] == 0) { 2678 dest_scan[3] = src_alpha; 2679 *dest_scan++ = m_Blue; 2680 *dest_scan++ = m_Green; 2681 *dest_scan = m_Red; 2682 dest_scan += 2; 2683 continue; 2684 } 2685 uint8_t dest_alpha = 2686 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; 2687 dest_scan[3] = dest_alpha; 2688 int alpha_ratio = src_alpha * 255 / dest_alpha; 2689 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); 2690 dest_scan++; 2691 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); 2692 dest_scan++; 2693 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); 2694 dest_scan += 2; 2695 continue; 2696 } 2697 } 2698 dest_scan += Bpp; 2699 } 2700 } 2701 2702 void CompositeSpanRGB(uint8_t* dest_scan, 2703 int Bpp, 2704 int span_left, 2705 int span_len, 2706 uint8_t* cover_scan, 2707 int clip_left, 2708 int clip_right, 2709 uint8_t* clip_scan, 2710 uint8_t* dest_extra_alpha_scan) { 2711 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2712 int col_end = (span_left + span_len) < clip_right 2713 ? span_len 2714 : (clip_right - span_left); 2715 dest_scan += col_start * Bpp; 2716 if (m_bRgbByteOrder) { 2717 for (int col = col_start; col < col_end; col++) { 2718 int src_alpha; 2719 if (clip_scan) { 2720 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2721 } else { 2722 src_alpha = m_Alpha * cover_scan[col] / 255; 2723 } 2724 if (src_alpha) { 2725 if (src_alpha == 255) { 2726 if (Bpp == 4) { 2727 *(uint32_t*)dest_scan = m_Color; 2728 } else if (Bpp == 3) { 2729 *dest_scan++ = m_Red; 2730 *dest_scan++ = m_Green; 2731 *dest_scan++ = m_Blue; 2732 continue; 2733 } 2734 } else { 2735 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); 2736 dest_scan++; 2737 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); 2738 dest_scan++; 2739 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); 2740 dest_scan += Bpp - 2; 2741 continue; 2742 } 2743 } 2744 dest_scan += Bpp; 2745 } 2746 return; 2747 } 2748 if (Bpp == 3 && dest_extra_alpha_scan) { 2749 for (int col = col_start; col < col_end; col++) { 2750 int src_alpha; 2751 if (m_bFullCover) { 2752 if (clip_scan) { 2753 src_alpha = m_Alpha * clip_scan[col] / 255; 2754 } else { 2755 src_alpha = m_Alpha; 2756 } 2757 } else { 2758 if (clip_scan) { 2759 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2760 } else { 2761 src_alpha = m_Alpha * cover_scan[col] / 255; 2762 } 2763 } 2764 if (src_alpha) { 2765 if (src_alpha == 255) { 2766 *dest_scan++ = (uint8_t)m_Blue; 2767 *dest_scan++ = (uint8_t)m_Green; 2768 *dest_scan++ = (uint8_t)m_Red; 2769 *dest_extra_alpha_scan++ = (uint8_t)m_Alpha; 2770 continue; 2771 } else { 2772 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - 2773 (*dest_extra_alpha_scan) * src_alpha / 255; 2774 *dest_extra_alpha_scan++ = dest_alpha; 2775 int alpha_ratio = src_alpha * 255 / dest_alpha; 2776 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); 2777 dest_scan++; 2778 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); 2779 dest_scan++; 2780 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); 2781 dest_scan++; 2782 continue; 2783 } 2784 } 2785 dest_extra_alpha_scan++; 2786 dest_scan += Bpp; 2787 } 2788 } else { 2789 for (int col = col_start; col < col_end; col++) { 2790 int src_alpha; 2791 if (m_bFullCover) { 2792 if (clip_scan) { 2793 src_alpha = m_Alpha * clip_scan[col] / 255; 2794 } else { 2795 src_alpha = m_Alpha; 2796 } 2797 } else { 2798 if (clip_scan) { 2799 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2800 } else { 2801 src_alpha = m_Alpha * cover_scan[col] / 255; 2802 } 2803 } 2804 if (src_alpha) { 2805 if (src_alpha == 255) { 2806 if (Bpp == 4) { 2807 *(uint32_t*)dest_scan = m_Color; 2808 } else if (Bpp == 3) { 2809 *dest_scan++ = m_Blue; 2810 *dest_scan++ = m_Green; 2811 *dest_scan++ = m_Red; 2812 continue; 2813 } 2814 } else { 2815 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); 2816 dest_scan++; 2817 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); 2818 dest_scan++; 2819 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); 2820 dest_scan += Bpp - 2; 2821 continue; 2822 } 2823 } 2824 dest_scan += Bpp; 2825 } 2826 } 2827 } 2828 2829 void CompositeSpanCMYK(uint8_t* dest_scan, 2830 int Bpp, 2831 int span_left, 2832 int span_len, 2833 uint8_t* cover_scan, 2834 int clip_left, 2835 int clip_right, 2836 uint8_t* clip_scan, 2837 uint8_t* dest_extra_alpha_scan) { 2838 ASSERT(!m_bRgbByteOrder); 2839 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2840 int col_end = (span_left + span_len) < clip_right 2841 ? span_len 2842 : (clip_right - span_left); 2843 dest_scan += col_start * 4; 2844 if (dest_extra_alpha_scan) { 2845 for (int col = col_start; col < col_end; col++) { 2846 int src_alpha; 2847 if (m_bFullCover) { 2848 if (clip_scan) { 2849 src_alpha = m_Alpha * clip_scan[col] / 255; 2850 } else { 2851 src_alpha = m_Alpha; 2852 } 2853 } else { 2854 if (clip_scan) { 2855 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2856 } else { 2857 src_alpha = m_Alpha * cover_scan[col] / 255; 2858 } 2859 } 2860 if (src_alpha) { 2861 if (src_alpha == 255) { 2862 *(FX_CMYK*)dest_scan = m_Color; 2863 *dest_extra_alpha_scan = (uint8_t)m_Alpha; 2864 } else { 2865 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - 2866 (*dest_extra_alpha_scan) * src_alpha / 255; 2867 *dest_extra_alpha_scan++ = dest_alpha; 2868 int alpha_ratio = src_alpha * 255 / dest_alpha; 2869 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); 2870 dest_scan++; 2871 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); 2872 dest_scan++; 2873 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); 2874 dest_scan++; 2875 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); 2876 dest_scan++; 2877 continue; 2878 } 2879 } 2880 dest_extra_alpha_scan++; 2881 dest_scan += 4; 2882 } 2883 } else { 2884 for (int col = col_start; col < col_end; col++) { 2885 int src_alpha; 2886 if (clip_scan) { 2887 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2888 } else { 2889 src_alpha = m_Alpha * cover_scan[col] / 255; 2890 } 2891 if (src_alpha) { 2892 if (src_alpha == 255) { 2893 *(FX_CMYK*)dest_scan = m_Color; 2894 } else { 2895 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); 2896 dest_scan++; 2897 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); 2898 dest_scan++; 2899 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); 2900 dest_scan++; 2901 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); 2902 dest_scan++; 2903 continue; 2904 } 2905 } 2906 dest_scan += 4; 2907 } 2908 } 2909 } 2910 2911 template <class Scanline> 2912 void render(const Scanline& sl) { 2913 if (!m_pOriDevice && !composite_span) { 2914 return; 2915 } 2916 int y = sl.y(); 2917 if (y < m_ClipBox.top || y >= m_ClipBox.bottom) { 2918 return; 2919 } 2920 uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y; 2921 uint8_t* dest_scan_extra_alpha = nullptr; 2922 CFX_DIBitmap* pAlphaMask = m_pDevice->m_pAlphaMask; 2923 if (pAlphaMask) { 2924 dest_scan_extra_alpha = 2925 pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y; 2926 } 2927 uint8_t* ori_scan = nullptr; 2928 if (m_pOriDevice) { 2929 ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y; 2930 } 2931 int Bpp = m_pDevice->GetBPP() / 8; 2932 bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask(); 2933 unsigned num_spans = sl.num_spans(); 2934 typename Scanline::const_iterator span = sl.begin(); 2935 while (1) { 2936 int x = span->x; 2937 ASSERT(span->len > 0); 2938 uint8_t* dest_pos = nullptr; 2939 uint8_t* dest_extra_alpha_pos = nullptr; 2940 uint8_t* ori_pos = nullptr; 2941 if (Bpp) { 2942 ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr; 2943 dest_pos = dest_scan + x * Bpp; 2944 dest_extra_alpha_pos = 2945 dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr; 2946 } else { 2947 dest_pos = dest_scan + x / 8; 2948 ori_pos = ori_scan ? ori_scan + x / 8 : nullptr; 2949 } 2950 uint8_t* clip_pos = nullptr; 2951 if (m_pClipMask) { 2952 clip_pos = m_pClipMask->GetBuffer() + 2953 (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x - 2954 m_ClipBox.left; 2955 } 2956 if (ori_pos) { 2957 CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len, 2958 span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos); 2959 } else { 2960 (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers, 2961 m_ClipBox.left, m_ClipBox.right, clip_pos, 2962 dest_extra_alpha_pos); 2963 } 2964 if (--num_spans == 0) { 2965 break; 2966 } 2967 ++span; 2968 } 2969 } 2970 2971 bool Init(CFX_DIBitmap* pDevice, 2972 CFX_DIBitmap* pOriDevice, 2973 const CFX_ClipRgn* pClipRgn, 2974 uint32_t color, 2975 bool bFullCover, 2976 bool bRgbByteOrder, 2977 int alpha_flag = 0, 2978 void* pIccTransform = nullptr) { 2979 m_pDevice = pDevice; 2980 m_pClipRgn = pClipRgn; 2981 composite_span = nullptr; 2982 m_bRgbByteOrder = bRgbByteOrder; 2983 m_pOriDevice = pOriDevice; 2984 if (m_pClipRgn) { 2985 m_ClipBox = m_pClipRgn->GetBox(); 2986 } else { 2987 m_ClipBox.left = m_ClipBox.top = 0; 2988 m_ClipBox.right = m_pDevice->GetWidth(); 2989 m_ClipBox.bottom = m_pDevice->GetHeight(); 2990 } 2991 m_pClipMask = nullptr; 2992 if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) { 2993 m_pClipMask = m_pClipRgn->GetMask().GetObject(); 2994 } 2995 m_bFullCover = bFullCover; 2996 bool bObjectCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag); 2997 bool bDeviceCMYK = pDevice->IsCmykImage(); 2998 m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color); 2999 CCodec_IccModule* pIccModule = nullptr; 3000 if (!CFX_GEModule::Get()->GetCodecModule() || 3001 !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { 3002 pIccTransform = nullptr; 3003 } else { 3004 pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 3005 } 3006 if (m_pDevice->GetBPP() == 8) { 3007 ASSERT(!m_bRgbByteOrder); 3008 composite_span = &CFX_Renderer::CompositeSpanGray; 3009 if (m_pDevice->IsAlphaMask()) { 3010 m_Gray = 255; 3011 } else { 3012 if (pIccTransform) { 3013 uint8_t gray; 3014 color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); 3015 pIccModule->TranslateScanline(pIccTransform, &gray, 3016 (const uint8_t*)&color, 1); 3017 m_Gray = gray; 3018 } else { 3019 if (bObjectCMYK) { 3020 uint8_t r, g, b; 3021 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), 3022 FXSYS_GetYValue(color), FXSYS_GetKValue(color), 3023 r, g, b); 3024 m_Gray = FXRGB2GRAY(r, g, b); 3025 } else { 3026 m_Gray = 3027 FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color)); 3028 } 3029 } 3030 } 3031 return true; 3032 } 3033 if (bDeviceCMYK) { 3034 ASSERT(!m_bRgbByteOrder); 3035 composite_span = &CFX_Renderer::CompositeSpanCMYK; 3036 if (bObjectCMYK) { 3037 m_Color = FXCMYK_TODIB(color); 3038 if (pIccTransform) { 3039 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, 3040 (const uint8_t*)&m_Color, 1); 3041 } 3042 } else { 3043 if (!pIccTransform) { 3044 return false; 3045 } 3046 color = FXARGB_TODIB(color); 3047 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, 3048 (const uint8_t*)&color, 1); 3049 } 3050 m_Red = ((uint8_t*)&m_Color)[0]; 3051 m_Green = ((uint8_t*)&m_Color)[1]; 3052 m_Blue = ((uint8_t*)&m_Color)[2]; 3053 m_Gray = ((uint8_t*)&m_Color)[3]; 3054 } else { 3055 composite_span = (pDevice->GetFormat() == FXDIB_Argb) 3056 ? &CFX_Renderer::CompositeSpanARGB 3057 : &CFX_Renderer::CompositeSpanRGB; 3058 if (pIccTransform) { 3059 color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); 3060 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, 3061 (const uint8_t*)&color, 1); 3062 ((uint8_t*)&m_Color)[3] = m_Alpha; 3063 m_Red = ((uint8_t*)&m_Color)[2]; 3064 m_Green = ((uint8_t*)&m_Color)[1]; 3065 m_Blue = ((uint8_t*)&m_Color)[0]; 3066 if (m_bRgbByteOrder) { 3067 m_Color = FXARGB_TODIB(m_Color); 3068 m_Color = FXARGB_TOBGRORDERDIB(m_Color); 3069 } 3070 } else { 3071 if (bObjectCMYK) { 3072 uint8_t r, g, b; 3073 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), 3074 FXSYS_GetYValue(color), FXSYS_GetKValue(color), r, 3075 g, b); 3076 m_Color = FXARGB_MAKE(m_Alpha, r, g, b); 3077 if (m_bRgbByteOrder) { 3078 m_Color = FXARGB_TOBGRORDERDIB(m_Color); 3079 } else { 3080 m_Color = FXARGB_TODIB(m_Color); 3081 } 3082 m_Red = r; 3083 m_Green = g; 3084 m_Blue = b; 3085 } else { 3086 if (m_bRgbByteOrder) { 3087 m_Color = FXARGB_TOBGRORDERDIB(color); 3088 } else { 3089 m_Color = FXARGB_TODIB(color); 3090 } 3091 ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue); 3092 } 3093 } 3094 } 3095 if (m_pDevice->GetBPP() == 1) { 3096 composite_span = &CFX_Renderer::CompositeSpan1bpp; 3097 } 3098 return true; 3099 } 3100 }; 3101 3102 #endif // _SKIA_SUPPORT_PATHS_ 3103