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 // we upscale ctables to 32bit. 597 if (pSource->GetPalette()) { 598 dst32Storage.reset(FX_Alloc2D(uint32_t, width, height)); 599 SkPMColor* dst32Pixels = dst32Storage.get(); 600 const SkPMColor* ctable = pSource->GetPalette(); 601 const unsigned ctableSize = pSource->GetPaletteSize(); 602 for (int y = 0; y < height; ++y) { 603 const uint8_t* srcRow = 604 static_cast<const uint8_t*>(buffer) + y * rowBytes; 605 uint32_t* dstRow = dst32Pixels + y * width; 606 for (int x = 0; x < width; ++x) { 607 unsigned index = srcRow[x]; 608 if (index >= ctableSize) { 609 index = 0; 610 } 611 dstRow[x] = ctable[index]; 612 } 613 } 614 buffer = dst32Storage.get(); 615 rowBytes = width * sizeof(uint32_t); 616 colorType = SkColorType::kN32_SkColorType; 617 } 618 break; 619 case 24: { 620 dst32Storage.reset(FX_Alloc2D(uint32_t, width, height)); 621 uint32_t* dst32Pixels = dst32Storage.get(); 622 for (int y = 0; y < height; ++y) { 623 const uint8_t* srcRow = 624 static_cast<const uint8_t*>(buffer) + y * rowBytes; 625 uint32_t* dstRow = dst32Pixels + y * width; 626 for (int x = 0; x < width; ++x) { 627 dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1], 628 srcRow[x * 3 + 0]); 629 } 630 } 631 buffer = dst32Storage.get(); 632 rowBytes = width * sizeof(uint32_t); 633 colorType = SkColorType::kN32_SkColorType; 634 alphaType = kOpaque_SkAlphaType; 635 break; 636 } 637 case 32: 638 colorType = SkColorType::kN32_SkColorType; 639 alphaType = kPremul_SkAlphaType; 640 pSource->DebugVerifyBitmapIsPreMultiplied(buffer); 641 break; 642 default: 643 SkASSERT(0); // TODO(caryclark) ensure that all cases are covered 644 colorType = SkColorType::kUnknown_SkColorType; 645 } 646 SkImageInfo imageInfo = 647 SkImageInfo::Make(width, height, colorType, alphaType); 648 skBitmap->installPixels(imageInfo, buffer, rowBytes, *ctPtr, nullptr, 649 nullptr); 650 *widthPtr = width; 651 *heightPtr = height; 652 return true; 653 } 654 #endif // _SKIA_SUPPORT_ 655 656 } // namespace 657 658 // Encapsulate the state used for successive text and path draws so that 659 // they can be combined. 660 class SkiaState { 661 public: 662 enum class Clip { 663 kSave, 664 kPath, 665 }; 666 667 enum class Accumulator { 668 kNone, 669 kPath, 670 kText, 671 kOther, 672 }; 673 674 // mark all cached state as uninitialized 675 explicit SkiaState(CFX_SkiaDeviceDriver* pDriver) 676 : m_pDriver(pDriver), 677 m_pFont(nullptr), 678 m_fontSize(0), 679 m_fillColor(0), 680 m_strokeColor(0), 681 m_blendType(0), 682 m_commandIndex(0), 683 m_drawIndex(INT_MAX), 684 m_clipIndex(0), 685 m_type(Accumulator::kNone), 686 m_fillFullCover(false), 687 m_fillPath(false), 688 m_groupKnockout(false), 689 m_debugDisable(false) 690 #if SHOW_SKIA_PATH 691 , 692 m_debugSaveCounter(0) 693 #endif 694 { 695 } 696 697 bool DrawPath(const CFX_PathData* pPathData, 698 const CFX_Matrix* pMatrix, 699 const CFX_GraphStateData* pDrawState, 700 uint32_t fill_color, 701 uint32_t stroke_color, 702 int fill_mode, 703 int blend_type) { 704 if (m_debugDisable) 705 return false; 706 Dump(__func__); 707 int drawIndex = SkTMin(m_drawIndex, m_commands.count()); 708 if (Accumulator::kText == m_type || drawIndex != m_commandIndex || 709 (Accumulator::kPath == m_type && 710 DrawChanged(pMatrix, pDrawState, fill_color, stroke_color, fill_mode, 711 blend_type, m_pDriver->m_bGroupKnockout))) { 712 Flush(); 713 } 714 if (Accumulator::kPath != m_type) { 715 m_skPath.reset(); 716 m_fillFullCover = !!(fill_mode & FXFILL_FULLCOVER); 717 m_fillPath = (fill_mode & 3) && fill_color; 718 m_skPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE 719 ? SkPath::kEvenOdd_FillType 720 : SkPath::kWinding_FillType); 721 if (pDrawState) 722 m_drawState.Copy(*pDrawState); 723 m_fillColor = fill_color; 724 m_strokeColor = stroke_color; 725 m_blendType = blend_type; 726 m_groupKnockout = m_pDriver->m_bGroupKnockout; 727 if (pMatrix) 728 m_drawMatrix = *pMatrix; 729 m_drawIndex = m_commandIndex; 730 m_type = Accumulator::kPath; 731 } 732 SkPath skPath = BuildPath(pPathData); 733 SkPoint delta; 734 if (MatrixOffset(pMatrix, &delta)) 735 skPath.offset(delta.fX, delta.fY); 736 m_skPath.addPath(skPath); 737 return true; 738 } 739 740 void FlushPath() { 741 Dump(__func__); 742 SkMatrix skMatrix = ToSkMatrix(m_drawMatrix); 743 SkPaint skPaint; 744 skPaint.setAntiAlias(true); 745 if (m_fillFullCover) 746 skPaint.setBlendMode(SkBlendMode::kPlus); 747 int stroke_alpha = FXARGB_A(m_strokeColor); 748 if (stroke_alpha) 749 m_pDriver->PaintStroke(&skPaint, &m_drawState, skMatrix); 750 SkCanvas* skCanvas = m_pDriver->SkiaCanvas(); 751 skCanvas->save(); 752 skCanvas->concat(skMatrix); 753 if (m_fillPath) { 754 SkPath strokePath; 755 const SkPath* fillPath = &m_skPath; 756 if (stroke_alpha) { 757 if (m_groupKnockout) { 758 skPaint.getFillPath(m_skPath, &strokePath); 759 if (Op(m_skPath, strokePath, SkPathOp::kDifference_SkPathOp, 760 &strokePath)) { 761 fillPath = &strokePath; 762 } 763 } 764 } 765 skPaint.setStyle(SkPaint::kFill_Style); 766 skPaint.setColor(m_fillColor); 767 #ifdef _SKIA_SUPPORT_PATHS_ 768 m_pDriver->PreMultiply(); 769 #endif // _SKIA_SUPPORT_PATHS_ 770 DebugShowSkiaDrawPath(skCanvas, skPaint, *fillPath); 771 skCanvas->drawPath(*fillPath, skPaint); 772 } 773 if (stroke_alpha) { 774 skPaint.setStyle(SkPaint::kStroke_Style); 775 skPaint.setColor(m_strokeColor); 776 #ifdef _SKIA_SUPPORT_PATHS_ 777 m_pDriver->PreMultiply(); 778 #endif // _SKIA_SUPPORT_PATHS_ 779 DebugShowSkiaDrawPath(skCanvas, skPaint, m_skPath); 780 skCanvas->drawPath(m_skPath, skPaint); 781 } 782 skCanvas->restore(); 783 m_drawIndex = INT_MAX; 784 m_type = Accumulator::kNone; 785 } 786 787 bool DrawText(int nChars, 788 const FXTEXT_CHARPOS* pCharPos, 789 CFX_Font* pFont, 790 const CFX_Matrix* pMatrix, 791 FX_FLOAT font_size, 792 uint32_t color) { 793 if (m_debugDisable) 794 return false; 795 Dump(__func__); 796 int drawIndex = SkTMin(m_drawIndex, m_commands.count()); 797 if (Accumulator::kPath == m_type || drawIndex != m_commandIndex || 798 (Accumulator::kText == m_type && 799 FontChanged(pFont, pMatrix, font_size, color))) { 800 Flush(); 801 } 802 if (Accumulator::kText != m_type) { 803 m_positions.setCount(0); 804 m_glyphs.setCount(0); 805 m_pFont = pFont; 806 m_fontSize = font_size; 807 m_fillColor = color; 808 m_drawMatrix = *pMatrix; 809 m_drawIndex = m_commandIndex; 810 m_type = Accumulator::kText; 811 } 812 int count = m_positions.count(); 813 m_positions.setCount(nChars + count); 814 m_glyphs.setCount(nChars + count); 815 SkScalar flip = m_fontSize < 0 ? -1 : 1; 816 SkScalar vFlip = flip; 817 if (pFont->IsVertical()) 818 vFlip *= -1; 819 for (int index = 0; index < nChars; ++index) { 820 const FXTEXT_CHARPOS& cp = pCharPos[index]; 821 m_positions[index + count] = {cp.m_Origin.x * flip, 822 cp.m_Origin.y * vFlip}; 823 m_glyphs[index + count] = static_cast<uint16_t>(cp.m_GlyphIndex); 824 } 825 SkPoint delta; 826 if (MatrixOffset(pMatrix, &delta)) { 827 for (int index = 0; index < nChars; ++index) 828 m_positions[index + count].offset(delta.fX * flip, -delta.fY * flip); 829 } 830 return true; 831 } 832 833 void FlushText() { 834 Dump(__func__); 835 SkPaint skPaint; 836 skPaint.setAntiAlias(true); 837 skPaint.setColor(m_fillColor); 838 if (m_pFont->GetFace()) { // exclude placeholder test fonts 839 sk_sp<SkTypeface> typeface(SkSafeRef(m_pFont->GetDeviceCache())); 840 skPaint.setTypeface(typeface); 841 } 842 skPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 843 skPaint.setHinting(SkPaint::kNo_Hinting); 844 skPaint.setTextSize(SkTAbs(m_fontSize)); 845 skPaint.setSubpixelText(true); 846 SkCanvas* skCanvas = m_pDriver->SkiaCanvas(); 847 skCanvas->save(); 848 SkScalar flip = m_fontSize < 0 ? -1 : 1; 849 SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix, flip); 850 skCanvas->concat(skMatrix); 851 #ifdef _SKIA_SUPPORT_PATHS_ 852 m_pDriver->PreMultiply(); 853 #endif // _SKIA_SUPPORT_PATHS_ 854 skCanvas->drawPosText(m_glyphs.begin(), m_glyphs.count() * 2, 855 m_positions.begin(), skPaint); 856 skCanvas->restore(); 857 m_drawIndex = INT_MAX; 858 m_type = Accumulator::kNone; 859 } 860 861 bool SetClipFill(const CFX_PathData* pPathData, 862 const CFX_Matrix* pMatrix, 863 int fill_mode) { 864 if (m_debugDisable) 865 return false; 866 Dump(__func__); 867 SkPath skClipPath = BuildPath(pPathData); 868 skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE 869 ? SkPath::kEvenOdd_FillType 870 : SkPath::kWinding_FillType); 871 SkMatrix skMatrix = ToSkMatrix(*pMatrix); 872 skClipPath.transform(skMatrix); 873 return SetClip(skClipPath); 874 } 875 876 bool SetClip(const SkPath& skClipPath) { 877 // if a pending draw depends on clip state that is cached, flush it and draw 878 if (m_commandIndex < m_commands.count()) { 879 if (m_commands[m_commandIndex] == Clip::kPath && 880 m_clips[m_commandIndex] == skClipPath) { 881 ++m_commandIndex; 882 return true; 883 } 884 Flush(); 885 } 886 while (m_clipIndex > m_commandIndex) { 887 do { 888 --m_clipIndex; 889 SkASSERT(m_clipIndex >= 0); 890 } while (m_commands[m_clipIndex] != Clip::kSave); 891 m_pDriver->SkiaCanvas()->restore(); 892 } 893 if (m_commandIndex < m_commands.count()) { 894 m_commands[m_commandIndex] = Clip::kPath; 895 m_clips[m_commandIndex] = skClipPath; 896 } else { 897 m_commands.push(Clip::kPath); 898 m_clips.push_back(skClipPath); 899 } 900 ++m_commandIndex; 901 return true; 902 } 903 904 bool SetClipStroke(const CFX_PathData* pPathData, 905 const CFX_Matrix* pMatrix, 906 const CFX_GraphStateData* pGraphState) { 907 if (m_debugDisable) 908 return false; 909 Dump(__func__); 910 SkPath skPath = BuildPath(pPathData); 911 SkMatrix skMatrix = ToSkMatrix(*pMatrix); 912 SkPaint skPaint; 913 m_pDriver->PaintStroke(&skPaint, pGraphState, skMatrix); 914 SkPath dst_path; 915 skPaint.getFillPath(skPath, &dst_path); 916 dst_path.transform(skMatrix); 917 return SetClip(dst_path); 918 } 919 920 bool MatrixOffset(const CFX_Matrix* pMatrix, SkPoint* delta) { 921 CFX_Matrix identityMatrix; 922 if (!pMatrix) 923 pMatrix = &identityMatrix; 924 delta->set(pMatrix->e - m_drawMatrix.e, pMatrix->f - m_drawMatrix.f); 925 if (!delta->fX && !delta->fY) 926 return true; 927 SkMatrix drawMatrix = ToSkMatrix(m_drawMatrix); 928 if (!(drawMatrix.getType() & ~SkMatrix::kTranslate_Mask)) 929 return true; 930 SkMatrix invDrawMatrix; 931 if (!drawMatrix.invert(&invDrawMatrix)) 932 return false; 933 SkMatrix invNewMatrix; 934 SkMatrix newMatrix = ToSkMatrix(*pMatrix); 935 if (!newMatrix.invert(&invNewMatrix)) 936 return false; 937 delta->set(invDrawMatrix.getTranslateX() - invNewMatrix.getTranslateX(), 938 invDrawMatrix.getTranslateY() - invNewMatrix.getTranslateY()); 939 return true; 940 } 941 942 // returns true if caller should apply command to skia canvas 943 bool ClipSave() { 944 if (m_debugDisable) 945 return false; 946 Dump(__func__); 947 int count = m_commands.count(); 948 if (m_commandIndex < count - 1) { 949 if (Clip::kSave == m_commands[m_commandIndex + 1]) { 950 ++m_commandIndex; 951 return true; 952 } 953 Flush(); 954 AdjustClip(m_commandIndex); 955 m_commands[++m_commandIndex] = Clip::kSave; 956 m_clips[m_commandIndex] = m_skEmptyPath; 957 } else { 958 AdjustClip(m_commandIndex); 959 m_commands.push(Clip::kSave); 960 m_clips.push_back(m_skEmptyPath); 961 ++m_commandIndex; 962 } 963 return true; 964 } 965 966 bool ClipRestore() { 967 if (m_debugDisable) 968 return false; 969 Dump(__func__); 970 while (Clip::kSave != m_commands[--m_commandIndex]) { 971 SkASSERT(m_commandIndex > 0); 972 } 973 return true; 974 } 975 976 bool DrawChanged(const CFX_Matrix* pMatrix, 977 const CFX_GraphStateData* pState, 978 uint32_t fill_color, 979 uint32_t stroke_color, 980 int fill_mode, 981 int blend_type, 982 bool group_knockout) const { 983 return MatrixChanged(pMatrix, m_drawMatrix) || 984 StateChanged(pState, m_drawState) || fill_color != m_fillColor || 985 stroke_color != m_strokeColor || 986 ((fill_mode & 3) == FXFILL_ALTERNATE) != 987 (m_skPath.getFillType() == SkPath::kEvenOdd_FillType) || 988 blend_type != m_blendType || group_knockout != m_groupKnockout; 989 } 990 991 bool FontChanged(CFX_Font* pFont, 992 const CFX_Matrix* pMatrix, 993 FX_FLOAT font_size, 994 uint32_t color) const { 995 return pFont != m_pFont || MatrixChanged(pMatrix, m_drawMatrix) || 996 font_size != m_fontSize || color != m_fillColor; 997 } 998 999 bool MatrixChanged(const CFX_Matrix* pMatrix, 1000 const CFX_Matrix& refMatrix) const { 1001 CFX_Matrix identityMatrix; 1002 if (!pMatrix) 1003 pMatrix = &identityMatrix; 1004 return pMatrix->a != refMatrix.a || pMatrix->b != refMatrix.b || 1005 pMatrix->c != refMatrix.c || pMatrix->d != refMatrix.d; 1006 } 1007 1008 bool StateChanged(const CFX_GraphStateData* pState, 1009 const CFX_GraphStateData& refState) const { 1010 CFX_GraphStateData identityState; 1011 if (!pState) 1012 pState = &identityState; 1013 return pState->m_LineWidth != refState.m_LineWidth || 1014 pState->m_LineCap != refState.m_LineCap || 1015 pState->m_LineJoin != refState.m_LineJoin || 1016 pState->m_MiterLimit != refState.m_MiterLimit || 1017 DashChanged(pState, refState); 1018 } 1019 1020 bool DashChanged(const CFX_GraphStateData* pState, 1021 const CFX_GraphStateData& refState) const { 1022 bool dashArray = pState && pState->m_DashArray; 1023 if (!dashArray && !refState.m_DashArray) 1024 return false; 1025 if (!dashArray || !refState.m_DashArray) 1026 return true; 1027 if (pState->m_DashPhase != refState.m_DashPhase || 1028 pState->m_DashCount != refState.m_DashCount) { 1029 return true; 1030 } 1031 for (int index = 0; index < pState->m_DashCount; ++index) { 1032 if (pState->m_DashArray[index] != refState.m_DashArray[index]) 1033 return true; 1034 } 1035 return true; 1036 } 1037 1038 void AdjustClip(int limit) { 1039 while (m_clipIndex > limit) { 1040 do { 1041 --m_clipIndex; 1042 SkASSERT(m_clipIndex >= 0); 1043 } while (m_commands[m_clipIndex] != Clip::kSave); 1044 m_pDriver->SkiaCanvas()->restore(); 1045 } 1046 while (m_clipIndex < limit) { 1047 if (Clip::kSave == m_commands[m_clipIndex]) { 1048 m_pDriver->SkiaCanvas()->save(); 1049 } else { 1050 SkASSERT(Clip::kPath == m_commands[m_clipIndex]); 1051 m_pDriver->SkiaCanvas()->clipPath(m_clips[m_clipIndex], 1052 SkClipOp::kIntersect, true); 1053 } 1054 ++m_clipIndex; 1055 } 1056 } 1057 1058 void Flush() { 1059 if (m_debugDisable) 1060 return; 1061 Dump(__func__); 1062 if (Accumulator::kPath == m_type || Accumulator::kText == m_type) { 1063 AdjustClip(SkTMin(m_drawIndex, m_commands.count())); 1064 Accumulator::kPath == m_type ? FlushPath() : FlushText(); 1065 } 1066 } 1067 1068 void FlushForDraw() { 1069 if (m_debugDisable) 1070 return; 1071 Flush(); // draw any pending text or path 1072 AdjustClip(m_commandIndex); // set up clip stack with any pending state 1073 } 1074 1075 #if SHOW_SKIA_PATH 1076 void DumpPrefix(int index) const { 1077 if (index != m_commandIndex && index != m_drawIndex && 1078 index != m_clipIndex) { 1079 printf(" "); 1080 return; 1081 } 1082 printf("%c%c%c> ", index == m_commandIndex ? 'x' : '-', 1083 index == m_drawIndex ? 'd' : '-', index == m_clipIndex ? 'c' : '-'); 1084 } 1085 1086 void DumpEndPrefix() const { 1087 int index = m_commands.count(); 1088 if (index != m_commandIndex && index > m_drawIndex && index != m_clipIndex) 1089 return; 1090 printf("%c%c%c>\n", index == m_commandIndex ? 'x' : '-', 1091 index <= m_drawIndex ? 'd' : '-', index == m_clipIndex ? 'c' : '-'); 1092 } 1093 #endif // SHOW_SKIA_PATH 1094 1095 void Dump(const char* where) const { 1096 #if SHOW_SKIA_PATH 1097 printf("\n%s\nSkia Save Count %d:\n", where, 1098 m_pDriver->m_pCanvas->getSaveCount()); 1099 printf("Cache:\n"); 1100 for (int index = 0; index < m_commands.count(); ++index) { 1101 DumpPrefix(index); 1102 switch (m_commands[index]) { 1103 case Clip::kSave: 1104 printf("Save %d\n", ++m_debugSaveCounter); 1105 break; 1106 case Clip::kPath: 1107 m_clips[index].dump(); 1108 break; 1109 default: 1110 printf("unknown\n"); 1111 } 1112 } 1113 DumpEndPrefix(); 1114 #endif // SHOW_SKIA_PATH 1115 #ifdef SK_DEBUG 1116 int skCanvasSaveCount = m_pDriver->m_pCanvas->getSaveCount(); 1117 int cacheSaveCount = 1; 1118 SkASSERT(m_clipIndex <= m_commands.count()); 1119 for (int index = 0; index < m_clipIndex; ++index) 1120 cacheSaveCount += Clip::kSave == m_commands[index]; 1121 SkASSERT(skCanvasSaveCount == cacheSaveCount); 1122 #endif 1123 } 1124 1125 private: 1126 SkTArray<SkPath> m_clips; // stack of clips that may be reused 1127 SkTDArray<Clip> m_commands; // stack of clip-related commands 1128 SkTDArray<SkPoint> m_positions; // accumulator for text positions 1129 SkTDArray<uint16_t> m_glyphs; // accumulator for text glyphs 1130 SkPath m_skPath; // accumulator for path contours 1131 SkPath m_skEmptyPath; // used as placehold in the clips array 1132 CFX_Matrix m_drawMatrix; 1133 CFX_GraphStateData m_clipState; 1134 CFX_GraphStateData m_drawState; 1135 CFX_Matrix m_clipMatrix; 1136 CFX_SkiaDeviceDriver* m_pDriver; 1137 CFX_Font* m_pFont; 1138 FX_FLOAT m_fontSize; 1139 uint32_t m_fillColor; 1140 uint32_t m_strokeColor; 1141 int m_blendType; 1142 int m_commandIndex; // active position in clip command stack 1143 int m_drawIndex; // position of the pending path or text draw 1144 int m_clipIndex; // position reflecting depth of canvas clip stacck 1145 Accumulator m_type; // type of pending draw 1146 bool m_fillFullCover; 1147 bool m_fillPath; 1148 bool m_groupKnockout; 1149 bool m_debugDisable; // turn off cache for debugging 1150 #if SHOW_SKIA_PATH 1151 mutable int m_debugSaveCounter; 1152 #endif 1153 }; 1154 1155 // convert a stroking path to scanlines 1156 void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, 1157 const CFX_GraphStateData* pGraphState, 1158 const SkMatrix& matrix) { 1159 SkPaint::Cap cap; 1160 switch (pGraphState->m_LineCap) { 1161 case CFX_GraphStateData::LineCapRound: 1162 cap = SkPaint::kRound_Cap; 1163 break; 1164 case CFX_GraphStateData::LineCapSquare: 1165 cap = SkPaint::kSquare_Cap; 1166 break; 1167 default: 1168 cap = SkPaint::kButt_Cap; 1169 break; 1170 } 1171 SkPaint::Join join; 1172 switch (pGraphState->m_LineJoin) { 1173 case CFX_GraphStateData::LineJoinRound: 1174 join = SkPaint::kRound_Join; 1175 break; 1176 case CFX_GraphStateData::LineJoinBevel: 1177 join = SkPaint::kBevel_Join; 1178 break; 1179 default: 1180 join = SkPaint::kMiter_Join; 1181 break; 1182 } 1183 SkMatrix inverse; 1184 if (!matrix.invert(&inverse)) 1185 return; // give up if the matrix is degenerate, and not invertable 1186 inverse.set(SkMatrix::kMTransX, 0); 1187 inverse.set(SkMatrix::kMTransY, 0); 1188 SkVector deviceUnits[2] = {{0, 1}, {1, 0}}; 1189 inverse.mapPoints(deviceUnits, SK_ARRAY_COUNT(deviceUnits)); 1190 FX_FLOAT width = 1191 SkTMax(pGraphState->m_LineWidth, 1192 SkTMin(deviceUnits[0].length(), deviceUnits[1].length())); 1193 if (pGraphState->m_DashArray) { 1194 int count = (pGraphState->m_DashCount + 1) / 2; 1195 SkScalar* intervals = FX_Alloc2D(SkScalar, count, sizeof(SkScalar)); 1196 // Set dash pattern 1197 for (int i = 0; i < count; i++) { 1198 FX_FLOAT on = pGraphState->m_DashArray[i * 2]; 1199 if (on <= 0.000001f) 1200 on = 1.f / 10; 1201 FX_FLOAT off = i * 2 + 1 == pGraphState->m_DashCount 1202 ? on 1203 : pGraphState->m_DashArray[i * 2 + 1]; 1204 if (off < 0) 1205 off = 0; 1206 intervals[i * 2] = on; 1207 intervals[i * 2 + 1] = off; 1208 } 1209 spaint->setPathEffect( 1210 SkDashPathEffect::Make(intervals, count * 2, pGraphState->m_DashPhase)); 1211 } 1212 spaint->setStyle(SkPaint::kStroke_Style); 1213 spaint->setAntiAlias(true); 1214 spaint->setStrokeWidth(width); 1215 spaint->setStrokeMiter(pGraphState->m_MiterLimit); 1216 spaint->setStrokeCap(cap); 1217 spaint->setStrokeJoin(join); 1218 } 1219 1220 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap, 1221 bool bRgbByteOrder, 1222 CFX_DIBitmap* pOriDevice, 1223 bool bGroupKnockout) 1224 : m_pBitmap(pBitmap), 1225 m_pOriDevice(pOriDevice), 1226 m_pRecorder(nullptr), 1227 m_pCache(new SkiaState(this)), 1228 #ifdef _SKIA_SUPPORT_PATHS_ 1229 m_pClipRgn(nullptr), 1230 m_FillFlags(0), 1231 m_bRgbByteOrder(bRgbByteOrder), 1232 #endif // _SKIA_SUPPORT_PATHS_ 1233 m_bGroupKnockout(bGroupKnockout) { 1234 SkBitmap skBitmap; 1235 SkASSERT(pBitmap->GetBPP() == 8 || pBitmap->GetBPP() == 32); 1236 SkImageInfo imageInfo = SkImageInfo::Make( 1237 pBitmap->GetWidth(), pBitmap->GetHeight(), 1238 pBitmap->GetBPP() == 8 ? kAlpha_8_SkColorType : kN32_SkColorType, 1239 kOpaque_SkAlphaType); 1240 skBitmap.installPixels(imageInfo, pBitmap->GetBuffer(), pBitmap->GetPitch(), 1241 nullptr, // FIXME(caryclark) set color table 1242 nullptr, nullptr); 1243 m_pCanvas = new SkCanvas(skBitmap); 1244 } 1245 1246 #ifdef _SKIA_SUPPORT_ 1247 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(int size_x, int size_y) 1248 : m_pBitmap(nullptr), 1249 m_pOriDevice(nullptr), 1250 m_pRecorder(new SkPictureRecorder), 1251 m_pCache(new SkiaState(this)), 1252 m_bGroupKnockout(false) { 1253 m_pRecorder->beginRecording(SkIntToScalar(size_x), SkIntToScalar(size_y)); 1254 m_pCanvas = m_pRecorder->getRecordingCanvas(); 1255 } 1256 1257 CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkPictureRecorder* recorder) 1258 : m_pBitmap(nullptr), 1259 m_pOriDevice(nullptr), 1260 m_pRecorder(recorder), 1261 m_pCache(new SkiaState(this)), 1262 m_bGroupKnockout(false) { 1263 m_pCanvas = m_pRecorder->getRecordingCanvas(); 1264 } 1265 #endif // _SKIA_SUPPORT_ 1266 1267 CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() { 1268 Flush(); 1269 if (!m_pRecorder) 1270 delete m_pCanvas; 1271 } 1272 1273 void CFX_SkiaDeviceDriver::Flush() { 1274 m_pCache->Flush(); 1275 } 1276 1277 bool CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, 1278 const FXTEXT_CHARPOS* pCharPos, 1279 CFX_Font* pFont, 1280 const CFX_Matrix* pObject2Device, 1281 FX_FLOAT font_size, 1282 uint32_t color) { 1283 if (m_pCache->DrawText(nChars, pCharPos, pFont, pObject2Device, font_size, 1284 color)) { 1285 return true; 1286 } 1287 sk_sp<SkTypeface> typeface(SkSafeRef(pFont->GetDeviceCache())); 1288 SkPaint paint; 1289 paint.setAntiAlias(true); 1290 paint.setColor(color); 1291 paint.setTypeface(typeface); 1292 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 1293 paint.setHinting(SkPaint::kNo_Hinting); 1294 paint.setTextSize(SkTAbs(font_size)); 1295 paint.setSubpixelText(true); 1296 m_pCanvas->save(); 1297 SkScalar flip = font_size < 0 ? -1 : 1; 1298 SkScalar vFlip = flip; 1299 if (pFont->IsVertical()) 1300 vFlip *= -1; 1301 SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device, flip); 1302 m_pCanvas->concat(skMatrix); 1303 SkTDArray<SkPoint> positions; 1304 positions.setCount(nChars); 1305 SkTDArray<uint16_t> glyphs; 1306 glyphs.setCount(nChars); 1307 for (int index = 0; index < nChars; ++index) { 1308 const FXTEXT_CHARPOS& cp = pCharPos[index]; 1309 positions[index] = {cp.m_Origin.x * flip, cp.m_Origin.y * vFlip}; 1310 glyphs[index] = static_cast<uint16_t>(cp.m_GlyphIndex); 1311 } 1312 #ifdef _SKIA_SUPPORT_PATHS_ 1313 m_pBitmap->PreMultiply(); 1314 #endif // _SKIA_SUPPORT_PATHS_ 1315 m_pCanvas->drawPosText(glyphs.begin(), nChars * 2, positions.begin(), paint); 1316 m_pCanvas->restore(); 1317 1318 return true; 1319 } 1320 1321 int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const { 1322 switch (caps_id) { 1323 case FXDC_DEVICE_CLASS: 1324 return FXDC_DISPLAY; 1325 #ifdef _SKIA_SUPPORT_ 1326 case FXDC_PIXEL_WIDTH: 1327 return m_pCanvas->imageInfo().width(); 1328 case FXDC_PIXEL_HEIGHT: 1329 return m_pCanvas->imageInfo().height(); 1330 case FXDC_BITS_PIXEL: 1331 return 32; 1332 case FXDC_HORZ_SIZE: 1333 case FXDC_VERT_SIZE: 1334 return 0; 1335 case FXDC_RENDER_CAPS: 1336 return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | 1337 FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT | 1338 FXRC_FILLSTROKE_PATH | FXRC_SHADING; 1339 #endif // _SKIA_SUPPORT_ 1340 1341 #ifdef _SKIA_SUPPORT_PATHS_ 1342 case FXDC_PIXEL_WIDTH: 1343 return m_pBitmap->GetWidth(); 1344 case FXDC_PIXEL_HEIGHT: 1345 return m_pBitmap->GetHeight(); 1346 case FXDC_BITS_PIXEL: 1347 return m_pBitmap->GetBPP(); 1348 case FXDC_HORZ_SIZE: 1349 case FXDC_VERT_SIZE: 1350 return 0; 1351 case FXDC_RENDER_CAPS: { 1352 int flags = FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE | 1353 FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_SHADING; 1354 if (m_pBitmap->HasAlpha()) { 1355 flags |= FXRC_ALPHA_OUTPUT; 1356 } else if (m_pBitmap->IsAlphaMask()) { 1357 if (m_pBitmap->GetBPP() == 1) { 1358 flags |= FXRC_BITMASK_OUTPUT; 1359 } else { 1360 flags |= FXRC_BYTEMASK_OUTPUT; 1361 } 1362 } 1363 if (m_pBitmap->IsCmykImage()) { 1364 flags |= FXRC_CMYK_OUTPUT; 1365 } 1366 return flags; 1367 } 1368 #endif // _SKIA_SUPPORT_PATHS_ 1369 } 1370 return 0; 1371 } 1372 1373 void CFX_SkiaDeviceDriver::SaveState() { 1374 if (!m_pCache->ClipSave()) 1375 m_pCanvas->save(); 1376 1377 #ifdef _SKIA_SUPPORT_PATHS_ 1378 std::unique_ptr<CFX_ClipRgn> pClip; 1379 if (m_pClipRgn) 1380 pClip = pdfium::MakeUnique<CFX_ClipRgn>(*m_pClipRgn); 1381 m_StateStack.push_back(std::move(pClip)); 1382 #endif // _SKIA_SUPPORT_PATHS_ 1383 } 1384 1385 void CFX_SkiaDeviceDriver::RestoreState(bool bKeepSaved) { 1386 if (!m_pCache->ClipRestore()) 1387 m_pCanvas->restore(); 1388 if (bKeepSaved && !m_pCache->ClipSave()) 1389 m_pCanvas->save(); 1390 #ifdef _SKIA_SUPPORT_PATHS_ 1391 m_pClipRgn.reset(); 1392 1393 if (m_StateStack.empty()) 1394 return; 1395 1396 if (bKeepSaved) { 1397 if (m_StateStack.back()) 1398 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>(*m_StateStack.back()); 1399 } else { 1400 m_pClipRgn = std::move(m_StateStack.back()); 1401 m_StateStack.pop_back(); 1402 } 1403 #endif // _SKIA_SUPPORT_PATHS_ 1404 } 1405 1406 #ifdef _SKIA_SUPPORT_PATHS_ 1407 void CFX_SkiaDeviceDriver::SetClipMask(const FX_RECT& clipBox, 1408 const SkPath& path) { 1409 FX_RECT path_rect(clipBox.left, clipBox.top, clipBox.right + 1, 1410 clipBox.bottom + 1); 1411 path_rect.Intersect(m_pClipRgn->GetBox()); 1412 CFX_DIBitmapRef mask; 1413 CFX_DIBitmap* pThisLayer = mask.Emplace(); 1414 pThisLayer->Create(path_rect.Width(), path_rect.Height(), FXDIB_8bppMask); 1415 pThisLayer->Clear(0); 1416 1417 SkImageInfo imageInfo = 1418 SkImageInfo::Make(pThisLayer->GetWidth(), pThisLayer->GetHeight(), 1419 SkColorType::kAlpha_8_SkColorType, kOpaque_SkAlphaType); 1420 SkBitmap bitmap; 1421 bitmap.installPixels(imageInfo, pThisLayer->GetBuffer(), 1422 pThisLayer->GetPitch(), nullptr, nullptr, nullptr); 1423 SkCanvas* canvas = new SkCanvas(bitmap); 1424 canvas->translate( 1425 -path_rect.left, 1426 -path_rect.top); // FIXME(caryclark) wrong sign(s)? upside down? 1427 SkPaint paint; 1428 paint.setAntiAlias((m_FillFlags & FXFILL_NOPATHSMOOTH) == 0); 1429 canvas->drawPath(path, paint); 1430 m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top, mask); 1431 delete canvas; 1432 } 1433 #endif // _SKIA_SUPPORT_PATHS_ 1434 1435 bool CFX_SkiaDeviceDriver::SetClip_PathFill( 1436 const CFX_PathData* pPathData, // path info 1437 const CFX_Matrix* pObject2Device, // flips object's y-axis 1438 int fill_mode // fill mode, WINDING or ALTERNATE 1439 ) { 1440 CFX_Matrix identity; 1441 const CFX_Matrix* deviceMatrix = pObject2Device ? pObject2Device : &identity; 1442 bool cached = m_pCache->SetClipFill(pPathData, deviceMatrix, fill_mode); 1443 1444 #ifdef _SKIA_SUPPORT_PATHS_ 1445 m_FillFlags = fill_mode; 1446 if (!m_pClipRgn) { 1447 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>( 1448 GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); 1449 } 1450 #endif // _SKIA_SUPPORT_PATHS_ 1451 if (pPathData->GetPoints().size() == 5 || 1452 pPathData->GetPoints().size() == 4) { 1453 CFX_FloatRect rectf; 1454 if (pPathData->IsRect(deviceMatrix, &rectf)) { 1455 rectf.Intersect( 1456 CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH), 1457 (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT))); 1458 // note that PDF's y-axis goes up; Skia's y-axis goes down 1459 if (!cached) { 1460 SkRect skClipRect = 1461 SkRect::MakeLTRB(rectf.left, rectf.bottom, rectf.right, rectf.top); 1462 DebugDrawSkiaClipRect(m_pCanvas, skClipRect); 1463 m_pCanvas->clipRect(skClipRect, SkClipOp::kIntersect, true); 1464 } 1465 1466 #ifdef _SKIA_SUPPORT_PATHS_ 1467 FX_RECT rect = rectf.GetOuterRect(); 1468 m_pClipRgn->IntersectRect(rect); 1469 #endif // _SKIA_SUPPORT_PATHS_ 1470 DebugShowCanvasClip(m_pCanvas); 1471 return true; 1472 } 1473 } 1474 SkPath skClipPath = BuildPath(pPathData); 1475 skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE 1476 ? SkPath::kEvenOdd_FillType 1477 : SkPath::kWinding_FillType); 1478 SkMatrix skMatrix = ToSkMatrix(*deviceMatrix); 1479 skClipPath.transform(skMatrix); 1480 DebugShowSkiaPath(skClipPath); 1481 if (!cached) { 1482 DebugDrawSkiaClipPath(m_pCanvas, skClipPath); 1483 m_pCanvas->clipPath(skClipPath, SkClipOp::kIntersect, true); 1484 } 1485 #ifdef _SKIA_SUPPORT_PATHS_ 1486 FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH), 1487 GetDeviceCaps(FXDC_PIXEL_HEIGHT)); 1488 SetClipMask(clipBox, skClipPath); 1489 #endif // _SKIA_SUPPORT_PATHS_ 1490 DebugShowCanvasClip(m_pCanvas); 1491 return true; 1492 } 1493 1494 bool CFX_SkiaDeviceDriver::SetClip_PathStroke( 1495 const CFX_PathData* pPathData, // path info 1496 const CFX_Matrix* pObject2Device, // optional transformation 1497 const CFX_GraphStateData* pGraphState // graphic state, for pen attributes 1498 ) { 1499 bool cached = m_pCache->SetClipStroke(pPathData, pObject2Device, pGraphState); 1500 1501 #ifdef _SKIA_SUPPORT_PATHS_ 1502 if (!m_pClipRgn) { 1503 m_pClipRgn = pdfium::MakeUnique<CFX_ClipRgn>( 1504 GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT)); 1505 } 1506 #endif // _SKIA_SUPPORT_PATHS_ 1507 // build path data 1508 SkPath skPath = BuildPath(pPathData); 1509 SkMatrix skMatrix = ToSkMatrix(*pObject2Device); 1510 SkPaint skPaint; 1511 PaintStroke(&skPaint, pGraphState, skMatrix); 1512 SkPath dst_path; 1513 skPaint.getFillPath(skPath, &dst_path); 1514 dst_path.transform(skMatrix); 1515 if (!cached) { 1516 DebugDrawSkiaClipPath(m_pCanvas, dst_path); 1517 m_pCanvas->clipPath(dst_path, SkClipOp::kIntersect, true); 1518 } 1519 #ifdef _SKIA_SUPPORT_PATHS_ 1520 FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH), 1521 GetDeviceCaps(FXDC_PIXEL_HEIGHT)); 1522 SetClipMask(clipBox, dst_path); 1523 #endif // _SKIA_SUPPORT_PATHS_ 1524 DebugShowCanvasClip(m_pCanvas); 1525 return true; 1526 } 1527 1528 bool CFX_SkiaDeviceDriver::DrawPath( 1529 const CFX_PathData* pPathData, // path info 1530 const CFX_Matrix* pObject2Device, // optional transformation 1531 const CFX_GraphStateData* pGraphState, // graphic state, for pen attributes 1532 uint32_t fill_color, // fill color 1533 uint32_t stroke_color, // stroke color 1534 int fill_mode, // fill mode, WINDING or ALTERNATE. 0 for not filled 1535 int blend_type) { 1536 if (fill_mode & FX_ZEROAREA_FILL) 1537 return true; 1538 if (m_pCache->DrawPath(pPathData, pObject2Device, pGraphState, fill_color, 1539 stroke_color, fill_mode, blend_type)) { 1540 return true; 1541 } 1542 SkMatrix skMatrix; 1543 if (pObject2Device) 1544 skMatrix = ToSkMatrix(*pObject2Device); 1545 else 1546 skMatrix.setIdentity(); 1547 SkPaint skPaint; 1548 skPaint.setAntiAlias(true); 1549 if (fill_mode & FXFILL_FULLCOVER) 1550 skPaint.setBlendMode(SkBlendMode::kPlus); 1551 int stroke_alpha = FXARGB_A(stroke_color); 1552 if (pGraphState && stroke_alpha) 1553 PaintStroke(&skPaint, pGraphState, skMatrix); 1554 SkPath skPath = BuildPath(pPathData); 1555 m_pCanvas->save(); 1556 m_pCanvas->concat(skMatrix); 1557 if ((fill_mode & 3) && fill_color) { 1558 skPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE 1559 ? SkPath::kEvenOdd_FillType 1560 : SkPath::kWinding_FillType); 1561 SkPath strokePath; 1562 const SkPath* fillPath = &skPath; 1563 if (pGraphState && stroke_alpha) { 1564 if (m_bGroupKnockout) { 1565 skPaint.getFillPath(skPath, &strokePath); 1566 if (Op(skPath, strokePath, SkPathOp::kDifference_SkPathOp, 1567 &strokePath)) { 1568 fillPath = &strokePath; 1569 } 1570 } 1571 } 1572 skPaint.setStyle(SkPaint::kFill_Style); 1573 skPaint.setColor(fill_color); 1574 #ifdef _SKIA_SUPPORT_PATHS_ 1575 m_pBitmap->PreMultiply(); 1576 #endif // _SKIA_SUPPORT_PATHS_ 1577 DebugShowSkiaDrawPath(m_pCanvas, skPaint, *fillPath); 1578 m_pCanvas->drawPath(*fillPath, skPaint); 1579 } 1580 if (pGraphState && stroke_alpha) { 1581 skPaint.setStyle(SkPaint::kStroke_Style); 1582 skPaint.setColor(stroke_color); 1583 #ifdef _SKIA_SUPPORT_PATHS_ 1584 m_pBitmap->PreMultiply(); 1585 #endif // _SKIA_SUPPORT_PATHS_ 1586 DebugShowSkiaDrawPath(m_pCanvas, skPaint, skPath); 1587 m_pCanvas->drawPath(skPath, skPaint); 1588 } 1589 m_pCanvas->restore(); 1590 return true; 1591 } 1592 1593 bool CFX_SkiaDeviceDriver::DrawCosmeticLine(FX_FLOAT x1, 1594 FX_FLOAT y1, 1595 FX_FLOAT x2, 1596 FX_FLOAT y2, 1597 uint32_t color, 1598 int blend_type) { 1599 return false; 1600 } 1601 1602 bool CFX_SkiaDeviceDriver::FillRectWithBlend(const FX_RECT* pRect, 1603 uint32_t fill_color, 1604 int blend_type) { 1605 m_pCache->FlushForDraw(); 1606 SkPaint spaint; 1607 spaint.setAntiAlias(true); 1608 spaint.setColor(fill_color); 1609 spaint.setBlendMode(GetSkiaBlendMode(blend_type)); 1610 SkRect rect = 1611 SkRect::MakeLTRB(pRect->left, SkTMin(pRect->top, pRect->bottom), 1612 pRect->right, SkTMax(pRect->bottom, pRect->top)); 1613 DebugShowSkiaDrawRect(m_pCanvas, spaint, rect); 1614 m_pCanvas->drawRect(rect, spaint); 1615 return true; 1616 } 1617 1618 bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern, 1619 const CFX_Matrix* pMatrix, 1620 const FX_RECT& clip_rect, 1621 int alpha, 1622 bool bAlphaMode) { 1623 m_pCache->FlushForDraw(); 1624 ShadingType shadingType = pPattern->GetShadingType(); 1625 if (kAxialShading != shadingType && kRadialShading != shadingType && 1626 kCoonsPatchMeshShading != shadingType) { 1627 // TODO(caryclark) more types 1628 return false; 1629 } 1630 int csFamily = pPattern->GetCS()->GetFamily(); 1631 if (PDFCS_DEVICERGB != csFamily && PDFCS_DEVICEGRAY != csFamily) 1632 return false; 1633 const std::vector<std::unique_ptr<CPDF_Function>>& pFuncs = 1634 pPattern->GetFuncs(); 1635 int nFuncs = pFuncs.size(); 1636 if (nFuncs > 1) // TODO(caryclark) remove this restriction 1637 return false; 1638 CPDF_Dictionary* pDict = pPattern->GetShadingObject()->GetDict(); 1639 CPDF_Array* pCoords = pDict->GetArrayFor("Coords"); 1640 if (!pCoords && kCoonsPatchMeshShading != shadingType) 1641 return false; 1642 // TODO(caryclark) Respect Domain[0], Domain[1]. (Don't know what they do 1643 // yet.) 1644 SkTDArray<SkColor> skColors; 1645 SkTDArray<SkScalar> skPos; 1646 for (int j = 0; j < nFuncs; j++) { 1647 if (!pFuncs[j]) 1648 continue; 1649 1650 if (const CPDF_SampledFunc* pSampledFunc = pFuncs[j]->ToSampledFunc()) { 1651 /* TODO(caryclark) 1652 Type 0 Sampled Functions in PostScript can also have an Order integer 1653 in the dictionary. PDFium doesn't appear to check for this anywhere. 1654 */ 1655 if (!AddSamples(pSampledFunc, &skColors, &skPos)) 1656 return false; 1657 } else if (const CPDF_ExpIntFunc* pExpIntFuc = pFuncs[j]->ToExpIntFunc()) { 1658 if (!AddColors(pExpIntFuc, &skColors)) 1659 return false; 1660 skPos.push(0); 1661 skPos.push(1); 1662 } else if (const CPDF_StitchFunc* pStitchFunc = pFuncs[j]->ToStitchFunc()) { 1663 if (!AddStitching(pStitchFunc, &skColors, &skPos)) 1664 return false; 1665 } else { 1666 return false; 1667 } 1668 } 1669 CPDF_Array* pArray = pDict->GetArrayFor("Extend"); 1670 bool clipStart = !pArray || !pArray->GetIntegerAt(0); 1671 bool clipEnd = !pArray || !pArray->GetIntegerAt(1); 1672 SkPaint paint; 1673 paint.setAntiAlias(true); 1674 paint.setAlpha(alpha); 1675 SkMatrix skMatrix = ToSkMatrix(*pMatrix); 1676 SkRect skRect = SkRect::MakeLTRB(clip_rect.left, clip_rect.top, 1677 clip_rect.right, clip_rect.bottom); 1678 SkPath skClip; 1679 SkPath skPath; 1680 if (kAxialShading == shadingType) { 1681 FX_FLOAT start_x = pCoords->GetNumberAt(0); 1682 FX_FLOAT start_y = pCoords->GetNumberAt(1); 1683 FX_FLOAT end_x = pCoords->GetNumberAt(2); 1684 FX_FLOAT end_y = pCoords->GetNumberAt(3); 1685 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; 1686 skMatrix.mapPoints(pts, SK_ARRAY_COUNT(pts)); 1687 paint.setShader(SkGradientShader::MakeLinear( 1688 pts, skColors.begin(), skPos.begin(), skColors.count(), 1689 SkShader::kClamp_TileMode)); 1690 if (clipStart || clipEnd) { 1691 // if the gradient is horizontal or vertical, modify the draw rectangle 1692 if (pts[0].fX == pts[1].fX) { // vertical 1693 if (pts[0].fY > pts[1].fY) { 1694 SkTSwap(pts[0].fY, pts[1].fY); 1695 SkTSwap(clipStart, clipEnd); 1696 } 1697 if (clipStart) 1698 skRect.fTop = SkTMax(skRect.fTop, pts[0].fY); 1699 if (clipEnd) 1700 skRect.fBottom = SkTMin(skRect.fBottom, pts[1].fY); 1701 } else if (pts[0].fY == pts[1].fY) { // horizontal 1702 if (pts[0].fX > pts[1].fX) { 1703 SkTSwap(pts[0].fX, pts[1].fX); 1704 SkTSwap(clipStart, clipEnd); 1705 } 1706 if (clipStart) 1707 skRect.fLeft = SkTMax(skRect.fLeft, pts[0].fX); 1708 if (clipEnd) 1709 skRect.fRight = SkTMin(skRect.fRight, pts[1].fX); 1710 } else { // if the gradient is angled and contained by the rect, clip 1711 SkPoint rectPts[4] = {{skRect.fLeft, skRect.fTop}, 1712 {skRect.fRight, skRect.fTop}, 1713 {skRect.fRight, skRect.fBottom}, 1714 {skRect.fLeft, skRect.fBottom}}; 1715 ClipAngledGradient(pts, rectPts, clipStart, clipEnd, &skClip); 1716 } 1717 } 1718 skPath.addRect(skRect); 1719 skMatrix.setIdentity(); 1720 } else if (kRadialShading == shadingType) { 1721 FX_FLOAT start_x = pCoords->GetNumberAt(0); 1722 FX_FLOAT start_y = pCoords->GetNumberAt(1); 1723 FX_FLOAT start_r = pCoords->GetNumberAt(2); 1724 FX_FLOAT end_x = pCoords->GetNumberAt(3); 1725 FX_FLOAT end_y = pCoords->GetNumberAt(4); 1726 FX_FLOAT end_r = pCoords->GetNumberAt(5); 1727 SkPoint pts[] = {{start_x, start_y}, {end_x, end_y}}; 1728 1729 paint.setShader(SkGradientShader::MakeTwoPointConical( 1730 pts[0], start_r, pts[1], end_r, skColors.begin(), skPos.begin(), 1731 skColors.count(), SkShader::kClamp_TileMode)); 1732 if (clipStart || clipEnd) { 1733 if (clipStart && start_r) 1734 skClip.addCircle(pts[0].fX, pts[0].fY, start_r); 1735 if (clipEnd) 1736 skClip.addCircle(pts[1].fX, pts[1].fY, end_r, SkPath::kCCW_Direction); 1737 else 1738 skClip.setFillType(SkPath::kInverseWinding_FillType); 1739 skClip.transform(skMatrix); 1740 } 1741 SkMatrix inverse; 1742 if (!skMatrix.invert(&inverse)) 1743 return false; 1744 skPath.addRect(skRect); 1745 skPath.transform(inverse); 1746 } else { 1747 ASSERT(kCoonsPatchMeshShading == shadingType); 1748 CPDF_Stream* pStream = ToStream(pPattern->GetShadingObject()); 1749 if (!pStream) 1750 return false; 1751 CPDF_MeshStream stream(shadingType, pPattern->GetFuncs(), pStream, 1752 pPattern->GetCS()); 1753 if (!stream.Load()) 1754 return false; 1755 SkPoint cubics[12]; 1756 SkColor colors[4]; 1757 m_pCanvas->save(); 1758 if (!skClip.isEmpty()) 1759 m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true); 1760 m_pCanvas->concat(skMatrix); 1761 while (!stream.BitStream()->IsEOF()) { 1762 uint32_t flag = stream.ReadFlag(); 1763 int iStartPoint = flag ? 4 : 0; 1764 int iStartColor = flag ? 2 : 0; 1765 if (flag) { 1766 SkPoint tempCubics[4]; 1767 for (int i = 0; i < (int)SK_ARRAY_COUNT(tempCubics); i++) 1768 tempCubics[i] = cubics[(flag * 3 + i) % 12]; 1769 FXSYS_memcpy(cubics, tempCubics, sizeof(tempCubics)); 1770 SkColor tempColors[2]; 1771 tempColors[0] = colors[flag]; 1772 tempColors[1] = colors[(flag + 1) % 4]; 1773 FXSYS_memcpy(colors, tempColors, sizeof(tempColors)); 1774 } 1775 for (int i = iStartPoint; i < (int)SK_ARRAY_COUNT(cubics); i++) { 1776 CFX_PointF point = stream.ReadCoords(); 1777 cubics[i].fX = point.x; 1778 cubics[i].fY = point.y; 1779 } 1780 for (int i = iStartColor; i < (int)SK_ARRAY_COUNT(colors); i++) { 1781 FX_FLOAT r; 1782 FX_FLOAT g; 1783 FX_FLOAT b; 1784 std::tie(r, g, b) = stream.ReadColor(); 1785 colors[i] = SkColorSetARGBInline(0xFF, (U8CPU)(r * 255), 1786 (U8CPU)(g * 255), (U8CPU)(b * 255)); 1787 } 1788 m_pCanvas->drawPatch(cubics, colors, nullptr, paint); 1789 } 1790 m_pCanvas->restore(); 1791 return true; 1792 } 1793 m_pCanvas->save(); 1794 if (!skClip.isEmpty()) 1795 m_pCanvas->clipPath(skClip, SkClipOp::kIntersect, true); 1796 m_pCanvas->concat(skMatrix); 1797 m_pCanvas->drawPath(skPath, paint); 1798 m_pCanvas->restore(); 1799 return true; 1800 } 1801 1802 uint8_t* CFX_SkiaDeviceDriver::GetBuffer() const { 1803 return m_pBitmap->GetBuffer(); 1804 } 1805 1806 bool CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) { 1807 // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead 1808 pRect->left = 0; 1809 pRect->top = 0; 1810 const SkImageInfo& canvasSize = m_pCanvas->imageInfo(); 1811 pRect->right = canvasSize.width(); 1812 pRect->bottom = canvasSize.height(); 1813 return true; 1814 } 1815 1816 bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) { 1817 if (!m_pBitmap) 1818 return true; 1819 uint8_t* srcBuffer = m_pBitmap->GetBuffer(); 1820 if (!srcBuffer) 1821 return true; 1822 #ifdef _SKIA_SUPPORT_ 1823 m_pCache->FlushForDraw(); 1824 int srcWidth = m_pBitmap->GetWidth(); 1825 int srcHeight = m_pBitmap->GetHeight(); 1826 int srcRowBytes = srcWidth * sizeof(uint32_t); 1827 SkImageInfo srcImageInfo = SkImageInfo::Make( 1828 srcWidth, srcHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType); 1829 SkBitmap skSrcBitmap; 1830 skSrcBitmap.installPixels(srcImageInfo, srcBuffer, srcRowBytes, nullptr, 1831 nullptr, nullptr); 1832 SkASSERT(pBitmap); 1833 uint8_t* dstBuffer = pBitmap->GetBuffer(); 1834 SkASSERT(dstBuffer); 1835 int dstWidth = pBitmap->GetWidth(); 1836 int dstHeight = pBitmap->GetHeight(); 1837 int dstRowBytes = dstWidth * sizeof(uint32_t); 1838 SkImageInfo dstImageInfo = SkImageInfo::Make( 1839 dstWidth, dstHeight, SkColorType::kN32_SkColorType, kPremul_SkAlphaType); 1840 SkBitmap skDstBitmap; 1841 skDstBitmap.installPixels(dstImageInfo, dstBuffer, dstRowBytes, nullptr, 1842 nullptr, nullptr); 1843 SkCanvas canvas(skDstBitmap); 1844 canvas.drawBitmap(skSrcBitmap, left, top, nullptr); 1845 return true; 1846 #endif // _SKIA_SUPPORT_ 1847 1848 #ifdef _SKIA_SUPPORT_PATHS_ 1849 Flush(); 1850 m_pBitmap->UnPreMultiply(); 1851 FX_RECT rect(left, top, left + pBitmap->GetWidth(), 1852 top + pBitmap->GetHeight()); 1853 std::unique_ptr<CFX_DIBitmap> pBack; 1854 if (m_pOriDevice) { 1855 pBack = m_pOriDevice->Clone(&rect); 1856 if (!pBack) 1857 return true; 1858 1859 pBack->CompositeBitmap(0, 0, pBack->GetWidth(), pBack->GetHeight(), 1860 m_pBitmap, 0, 0); 1861 } else { 1862 pBack = m_pBitmap->Clone(&rect); 1863 if (!pBack) 1864 return true; 1865 } 1866 1867 bool bRet = true; 1868 left = std::min(left, 0); 1869 top = std::min(top, 0); 1870 if (m_bRgbByteOrder) { 1871 RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(), 1872 pBack.get(), left, top); 1873 } else { 1874 bRet = pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), 1875 pBack.get(), left, top); 1876 } 1877 return bRet; 1878 #endif // _SKIA_SUPPORT_PATHS_ 1879 } 1880 1881 CFX_DIBitmap* CFX_SkiaDeviceDriver::GetBackDrop() { 1882 return m_pOriDevice; 1883 } 1884 1885 bool CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap, 1886 uint32_t argb, 1887 const FX_RECT* pSrcRect, 1888 int left, 1889 int top, 1890 int blend_type) { 1891 if (!m_pBitmap || !m_pBitmap->GetBuffer()) 1892 return true; 1893 1894 #ifdef _SKIA_SUPPORT_ 1895 CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), left, 1896 top + pBitmap->GetHeight()); 1897 void* dummy; 1898 return StartDIBits(pBitmap, 0xFF, argb, &m, 0, dummy, blend_type); 1899 #endif // _SKIA_SUPPORT_ 1900 1901 #ifdef _SKIA_SUPPORT_PATHS_ 1902 Flush(); 1903 if (pBitmap->IsAlphaMask()) { 1904 return m_pBitmap->CompositeMask( 1905 left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb, 1906 pSrcRect->left, pSrcRect->top, blend_type, m_pClipRgn.get(), 1907 m_bRgbByteOrder, 0, nullptr); 1908 } 1909 return m_pBitmap->CompositeBitmap( 1910 left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, pSrcRect->left, 1911 pSrcRect->top, blend_type, m_pClipRgn.get(), m_bRgbByteOrder, nullptr); 1912 #endif // _SKIA_SUPPORT_PATHS_ 1913 } 1914 1915 bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource, 1916 uint32_t argb, 1917 int dest_left, 1918 int dest_top, 1919 int dest_width, 1920 int dest_height, 1921 const FX_RECT* pClipRect, 1922 uint32_t flags, 1923 int blend_type) { 1924 #ifdef _SKIA_SUPPORT_ 1925 m_pCache->FlushForDraw(); 1926 if (!m_pBitmap->GetBuffer()) 1927 return true; 1928 CFX_Matrix m(dest_width, 0, 0, -dest_height, dest_left, 1929 dest_top + dest_height); 1930 1931 m_pCanvas->save(); 1932 SkRect skClipRect = SkRect::MakeLTRB(pClipRect->left, pClipRect->bottom, 1933 pClipRect->right, pClipRect->top); 1934 m_pCanvas->clipRect(skClipRect, SkClipOp::kIntersect, true); 1935 void* dummy; 1936 bool result = StartDIBits(pSource, 0xFF, argb, &m, 0, dummy, blend_type); 1937 m_pCanvas->restore(); 1938 1939 return result; 1940 #endif // _SKIA_SUPPORT_ 1941 1942 #ifdef _SKIA_SUPPORT_PATHS_ 1943 if (dest_width == pSource->GetWidth() && 1944 dest_height == pSource->GetHeight()) { 1945 FX_RECT rect(0, 0, dest_width, dest_height); 1946 return SetDIBits(pSource, argb, &rect, dest_left, dest_top, blend_type); 1947 } 1948 Flush(); 1949 FX_RECT dest_rect(dest_left, dest_top, dest_left + dest_width, 1950 dest_top + dest_height); 1951 dest_rect.Normalize(); 1952 FX_RECT dest_clip = dest_rect; 1953 dest_clip.Intersect(*pClipRect); 1954 CFX_BitmapComposer composer; 1955 composer.Compose(m_pBitmap, m_pClipRgn.get(), 255, argb, dest_clip, false, 1956 false, false, m_bRgbByteOrder, 0, nullptr, blend_type); 1957 dest_clip.Offset(-dest_rect.left, -dest_rect.top); 1958 CFX_ImageStretcher stretcher(&composer, pSource, dest_width, dest_height, 1959 dest_clip, flags); 1960 if (stretcher.Start()) 1961 stretcher.Continue(nullptr); 1962 return true; 1963 #endif // _SKIA_SUPPORT_PATHS_ 1964 } 1965 1966 bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, 1967 int bitmap_alpha, 1968 uint32_t argb, 1969 const CFX_Matrix* pMatrix, 1970 uint32_t render_flags, 1971 void*& handle, 1972 int blend_type) { 1973 #ifdef _SKIA_SUPPORT_ 1974 m_pCache->FlushForDraw(); 1975 DebugValidate(m_pBitmap, m_pOriDevice); 1976 SkColorTable* ct = nullptr; 1977 std::unique_ptr<uint8_t, FxFreeDeleter> dst8Storage; 1978 std::unique_ptr<uint32_t, FxFreeDeleter> dst32Storage; 1979 SkBitmap skBitmap; 1980 int width, height; 1981 if (!Upsample(pSource, dst8Storage, dst32Storage, &ct, &skBitmap, &width, 1982 &height, false)) { 1983 return false; 1984 } 1985 m_pCanvas->save(); 1986 SkMatrix skMatrix; 1987 SetBitmapMatrix(pMatrix, width, height, &skMatrix); 1988 m_pCanvas->concat(skMatrix); 1989 SkPaint paint; 1990 SetBitmapPaint(pSource->IsAlphaMask(), argb, bitmap_alpha, blend_type, 1991 &paint); 1992 // TODO(caryclark) Once Skia supports 8 bit src to 8 bit dst remove this 1993 if (m_pBitmap && m_pBitmap->GetBPP() == 8 && pSource->GetBPP() == 8) { 1994 SkMatrix inv; 1995 SkAssertResult(skMatrix.invert(&inv)); 1996 for (int y = 0; y < m_pBitmap->GetHeight(); ++y) { 1997 for (int x = 0; x < m_pBitmap->GetWidth(); ++x) { 1998 SkPoint src = {x + 0.5f, y + 0.5f}; 1999 inv.mapPoints(&src, 1); 2000 // TODO(caryclark) Why does the matrix map require clamping? 2001 src.fX = SkTMax(0.5f, SkTMin(src.fX, width - 0.5f)); 2002 src.fY = SkTMax(0.5f, SkTMin(src.fY, height - 0.5f)); 2003 m_pBitmap->SetPixel(x, y, skBitmap.getColor(src.fX, src.fY)); 2004 } 2005 } 2006 } else { 2007 m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint); 2008 } 2009 m_pCanvas->restore(); 2010 if (ct) 2011 ct->unref(); 2012 DebugValidate(m_pBitmap, m_pOriDevice); 2013 #endif // _SKIA_SUPPORT_ 2014 2015 #ifdef _SKIA_SUPPORT_PATHS_ 2016 Flush(); 2017 if (!m_pBitmap->GetBuffer()) 2018 return true; 2019 m_pBitmap->UnPreMultiply(); 2020 CFX_ImageRenderer* pRenderer = new CFX_ImageRenderer; 2021 pRenderer->Start(m_pBitmap, m_pClipRgn.get(), pSource, bitmap_alpha, argb, 2022 pMatrix, render_flags, m_bRgbByteOrder, 0, nullptr); 2023 handle = pRenderer; 2024 #endif // _SKIA_SUPPORT_PATHS_ 2025 return true; 2026 } 2027 2028 bool CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) { 2029 #ifdef _SKIA_SUPPORT_ 2030 m_pCache->FlushForDraw(); 2031 return false; 2032 #endif // _SKIA_SUPPORT_ 2033 2034 #ifdef _SKIA_SUPPORT_PATHS_ 2035 Flush(); 2036 if (!m_pBitmap->GetBuffer()) { 2037 return true; 2038 } 2039 return static_cast<CFX_ImageRenderer*>(handle)->Continue(pPause); 2040 #endif // _SKIA_SUPPORT_PATHS_ 2041 } 2042 2043 #if defined _SKIA_SUPPORT_ 2044 void CFX_SkiaDeviceDriver::PreMultiply(CFX_DIBitmap* pDIBitmap) { 2045 pDIBitmap->PreMultiply(); 2046 } 2047 #endif // _SKIA_SUPPORT_ 2048 2049 void CFX_DIBitmap::PreMultiply() { 2050 if (this->GetBPP() != 32) 2051 return; 2052 void* buffer = this->GetBuffer(); 2053 if (!buffer) 2054 return; 2055 #if defined _SKIA_SUPPORT_PATHS_ 2056 Format priorFormat = m_nFormat; 2057 m_nFormat = Format::kPreMultiplied; 2058 if (priorFormat != Format::kUnPreMultiplied) 2059 return; 2060 #endif 2061 int height = this->GetHeight(); 2062 int width = this->GetWidth(); 2063 int rowBytes = this->GetPitch(); 2064 SkImageInfo unpremultipliedInfo = 2065 SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType); 2066 SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes); 2067 SkImageInfo premultipliedInfo = 2068 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); 2069 SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes); 2070 unpremultiplied.readPixels(premultiplied); 2071 this->DebugVerifyBitmapIsPreMultiplied(); 2072 } 2073 2074 #ifdef _SKIA_SUPPORT_PATHS_ 2075 void CFX_DIBitmap::UnPreMultiply() { 2076 if (this->GetBPP() != 32) 2077 return; 2078 void* buffer = this->GetBuffer(); 2079 if (!buffer) 2080 return; 2081 Format priorFormat = m_nFormat; 2082 m_nFormat = Format::kUnPreMultiplied; 2083 if (priorFormat != Format::kPreMultiplied) 2084 return; 2085 this->DebugVerifyBitmapIsPreMultiplied(); 2086 int height = this->GetHeight(); 2087 int width = this->GetWidth(); 2088 int rowBytes = this->GetPitch(); 2089 SkImageInfo premultipliedInfo = 2090 SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); 2091 SkPixmap premultiplied(premultipliedInfo, buffer, rowBytes); 2092 SkImageInfo unpremultipliedInfo = 2093 SkImageInfo::Make(width, height, kN32_SkColorType, kUnpremul_SkAlphaType); 2094 SkPixmap unpremultiplied(unpremultipliedInfo, buffer, rowBytes); 2095 premultiplied.readPixels(unpremultiplied); 2096 } 2097 #endif // _SKIA_SUPPORT_PATHS_ 2098 2099 #ifdef _SKIA_SUPPORT_ 2100 bool CFX_SkiaDeviceDriver::DrawBitsWithMask(const CFX_DIBSource* pSource, 2101 const CFX_DIBSource* pMask, 2102 int bitmap_alpha, 2103 const CFX_Matrix* pMatrix, 2104 int blend_type) { 2105 DebugValidate(m_pBitmap, m_pOriDevice); 2106 SkColorTable* srcCt = nullptr; 2107 SkColorTable* maskCt = nullptr; 2108 std::unique_ptr<uint8_t, FxFreeDeleter> src8Storage, mask8Storage; 2109 std::unique_ptr<uint32_t, FxFreeDeleter> src32Storage, mask32Storage; 2110 SkBitmap skBitmap, skMask; 2111 int srcWidth, srcHeight, maskWidth, maskHeight; 2112 if (!Upsample(pSource, src8Storage, src32Storage, &srcCt, &skBitmap, 2113 &srcWidth, &srcHeight, false)) { 2114 return false; 2115 } 2116 if (!Upsample(pMask, mask8Storage, mask32Storage, &maskCt, &skMask, 2117 &maskWidth, &maskHeight, true)) { 2118 return false; 2119 } 2120 m_pCanvas->save(); 2121 SkMatrix skMatrix; 2122 SetBitmapMatrix(pMatrix, srcWidth, srcHeight, &skMatrix); 2123 m_pCanvas->concat(skMatrix); 2124 SkPaint paint; 2125 SetBitmapPaint(pSource->IsAlphaMask(), 0xFFFFFFFF, bitmap_alpha, blend_type, 2126 &paint); 2127 sk_sp<SkImage> skSrc = SkImage::MakeFromBitmap(skBitmap); 2128 sk_sp<SkShader> skSrcShader = 2129 skSrc->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 2130 sk_sp<SkImage> skMaskImage = SkImage::MakeFromBitmap(skMask); 2131 sk_sp<SkShader> skMaskShader = skMaskImage->makeShader( 2132 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 2133 paint.setShader(SkShader::MakeComposeShader(skMaskShader, skSrcShader, 2134 SkBlendMode::kSrcIn)); 2135 SkRect r = {0, 0, SkIntToScalar(srcWidth), SkIntToScalar(srcHeight)}; 2136 m_pCanvas->drawRect(r, paint); 2137 m_pCanvas->restore(); 2138 if (srcCt) 2139 srcCt->unref(); 2140 DebugValidate(m_pBitmap, m_pOriDevice); 2141 return true; 2142 } 2143 2144 bool CFX_SkiaDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap, 2145 const CFX_DIBSource* pMask, 2146 int dest_left, 2147 int dest_top, 2148 int bitmap_alpha, 2149 int blend_type) { 2150 if (!m_pBitmap || !m_pBitmap->GetBuffer()) 2151 return true; 2152 CFX_Matrix m(pBitmap->GetWidth(), 0, 0, -pBitmap->GetHeight(), dest_left, 2153 dest_top + pBitmap->GetHeight()); 2154 return DrawBitsWithMask(pBitmap, pMask, bitmap_alpha, &m, blend_type); 2155 } 2156 2157 void CFX_SkiaDeviceDriver::Clear(uint32_t color) { 2158 m_pCanvas->clear(color); 2159 } 2160 #endif // _SKIA_SUPPORT_ 2161 2162 void CFX_SkiaDeviceDriver::Dump() const { 2163 #if SHOW_SKIA_PATH && defined _SKIA_SUPPORT_ 2164 if (m_pCache) 2165 m_pCache->Dump(this); 2166 #endif // SHOW_SKIA_PATH && defined _SKIA_SUPPORT_ 2167 } 2168 2169 #ifdef _SKIA_SUPPORT_ 2170 void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const { 2171 if (m_pOriDevice) 2172 m_pOriDevice->DebugVerifyBitmapIsPreMultiplied(); 2173 } 2174 #endif // _SKIA_SUPPORT_ 2175 2176 CFX_FxgeDevice::CFX_FxgeDevice() { 2177 #ifdef _SKIA_SUPPORT_ 2178 m_bOwnedBitmap = false; 2179 #endif // _SKIA_SUPPORT_ 2180 } 2181 2182 #ifdef _SKIA_SUPPORT_ 2183 void CFX_FxgeDevice::Clear(uint32_t color) { 2184 CFX_SkiaDeviceDriver* skDriver = 2185 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); 2186 skDriver->Clear(color); 2187 } 2188 2189 SkPictureRecorder* CFX_FxgeDevice::CreateRecorder(int size_x, int size_y) { 2190 CFX_SkiaDeviceDriver* skDriver = new CFX_SkiaDeviceDriver(size_x, size_y); 2191 SetDeviceDriver(pdfium::WrapUnique(skDriver)); 2192 return skDriver->GetRecorder(); 2193 } 2194 #endif // _SKIA_SUPPORT_ 2195 2196 bool CFX_FxgeDevice::Attach(CFX_DIBitmap* pBitmap, 2197 bool bRgbByteOrder, 2198 CFX_DIBitmap* pOriDevice, 2199 bool bGroupKnockout) { 2200 if (!pBitmap) 2201 return false; 2202 SetBitmap(pBitmap); 2203 SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>( 2204 pBitmap, bRgbByteOrder, pOriDevice, bGroupKnockout)); 2205 return true; 2206 } 2207 2208 #ifdef _SKIA_SUPPORT_ 2209 bool CFX_FxgeDevice::AttachRecorder(SkPictureRecorder* recorder) { 2210 if (!recorder) 2211 return false; 2212 SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(recorder)); 2213 return true; 2214 } 2215 #endif // _SKIA_SUPPORT_ 2216 2217 bool CFX_FxgeDevice::Create(int width, 2218 int height, 2219 FXDIB_Format format, 2220 CFX_DIBitmap* pOriDevice) { 2221 m_bOwnedBitmap = true; 2222 CFX_DIBitmap* pBitmap = new CFX_DIBitmap; 2223 if (!pBitmap->Create(width, height, format)) { 2224 delete pBitmap; 2225 return false; 2226 } 2227 SetBitmap(pBitmap); 2228 SetDeviceDriver(pdfium::MakeUnique<CFX_SkiaDeviceDriver>(pBitmap, false, 2229 pOriDevice, false)); 2230 return true; 2231 } 2232 2233 CFX_FxgeDevice::~CFX_FxgeDevice() { 2234 #ifdef _SKIA_SUPPORT_ 2235 Flush(); 2236 // call destructor of CFX_RenderDevice / CFX_SkiaDeviceDriver immediately 2237 if (m_bOwnedBitmap && GetBitmap()) 2238 delete GetBitmap(); 2239 #endif // _SKIA_SUPPORT_ 2240 } 2241 2242 #ifdef _SKIA_SUPPORT_ 2243 void CFX_FxgeDevice::DebugVerifyBitmapIsPreMultiplied() const { 2244 #ifdef SK_DEBUG 2245 CFX_SkiaDeviceDriver* skDriver = 2246 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); 2247 if (skDriver) 2248 skDriver->DebugVerifyBitmapIsPreMultiplied(); 2249 #endif // SK_DEBUG 2250 } 2251 2252 bool CFX_FxgeDevice::SetBitsWithMask(const CFX_DIBSource* pBitmap, 2253 const CFX_DIBSource* pMask, 2254 int left, 2255 int top, 2256 int bitmap_alpha, 2257 int blend_type) { 2258 CFX_SkiaDeviceDriver* skDriver = 2259 static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver()); 2260 if (skDriver) 2261 return skDriver->SetBitsWithMask(pBitmap, pMask, left, top, bitmap_alpha, 2262 blend_type); 2263 return false; 2264 } 2265 #endif // _SKIA_SUPPORT_ 2266 2267 void CFX_DIBSource::DebugVerifyBitmapIsPreMultiplied(void* opt) const { 2268 #ifdef SK_DEBUG 2269 SkASSERT(32 == GetBPP()); 2270 const uint32_t* buffer = (const uint32_t*)(opt ? opt : GetBuffer()); 2271 int width = GetWidth(); 2272 int height = GetHeight(); 2273 // verify that input is really premultiplied 2274 for (int y = 0; y < height; ++y) { 2275 const uint32_t* srcRow = buffer + y * width; 2276 for (int x = 0; x < width; ++x) { 2277 uint8_t a = SkGetPackedA32(srcRow[x]); 2278 uint8_t r = SkGetPackedR32(srcRow[x]); 2279 uint8_t g = SkGetPackedG32(srcRow[x]); 2280 uint8_t b = SkGetPackedB32(srcRow[x]); 2281 SkA32Assert(a); 2282 SkASSERT(r <= a); 2283 SkASSERT(g <= a); 2284 SkASSERT(b <= a); 2285 } 2286 } 2287 #endif // SK_DEBUG 2288 } 2289 2290 #ifdef _SKIA_SUPPORT_PATHS_ 2291 class CFX_Renderer { 2292 private: 2293 int m_Alpha, m_Red, m_Green, m_Blue, m_Gray; 2294 uint32_t m_Color; 2295 bool m_bFullCover; 2296 bool m_bRgbByteOrder; 2297 CFX_DIBitmap* m_pOriDevice; 2298 FX_RECT m_ClipBox; 2299 const CFX_DIBitmap* m_pClipMask; 2300 CFX_DIBitmap* m_pDevice; 2301 const CFX_ClipRgn* m_pClipRgn; 2302 void (CFX_Renderer::*composite_span)(uint8_t*, 2303 int, 2304 int, 2305 int, 2306 uint8_t*, 2307 int, 2308 int, 2309 uint8_t*, 2310 uint8_t*); 2311 2312 public: 2313 void prepare(unsigned) {} 2314 2315 void CompositeSpan(uint8_t* dest_scan, 2316 uint8_t* ori_scan, 2317 int Bpp, 2318 bool bDestAlpha, 2319 int span_left, 2320 int span_len, 2321 uint8_t* cover_scan, 2322 int clip_left, 2323 int clip_right, 2324 uint8_t* clip_scan) { 2325 ASSERT(!m_pDevice->IsCmykImage()); 2326 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2327 int col_end = (span_left + span_len) < clip_right 2328 ? span_len 2329 : (clip_right - span_left); 2330 if (Bpp) { 2331 dest_scan += col_start * Bpp; 2332 ori_scan += col_start * Bpp; 2333 } else { 2334 dest_scan += col_start / 8; 2335 ori_scan += col_start / 8; 2336 } 2337 if (m_bRgbByteOrder) { 2338 if (Bpp == 4 && bDestAlpha) { 2339 for (int col = col_start; col < col_end; col++) { 2340 int src_alpha; 2341 if (clip_scan) { 2342 src_alpha = m_Alpha * clip_scan[col] / 255; 2343 } else { 2344 src_alpha = m_Alpha; 2345 } 2346 uint8_t dest_alpha = 2347 ori_scan[3] + src_alpha - ori_scan[3] * src_alpha / 255; 2348 dest_scan[3] = dest_alpha; 2349 int alpha_ratio = src_alpha * 255 / dest_alpha; 2350 if (m_bFullCover) { 2351 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); 2352 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); 2353 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); 2354 dest_scan++; 2355 ori_scan++; 2356 } else { 2357 int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, alpha_ratio); 2358 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, alpha_ratio); 2359 int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, alpha_ratio); 2360 ori_scan++; 2361 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); 2362 dest_scan++; 2363 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); 2364 dest_scan++; 2365 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); 2366 dest_scan += 2; 2367 } 2368 } 2369 return; 2370 } 2371 if (Bpp == 3 || Bpp == 4) { 2372 for (int col = col_start; col < col_end; col++) { 2373 int src_alpha; 2374 if (clip_scan) { 2375 src_alpha = m_Alpha * clip_scan[col] / 255; 2376 } else { 2377 src_alpha = m_Alpha; 2378 } 2379 int r = FXDIB_ALPHA_MERGE(*ori_scan++, m_Red, src_alpha); 2380 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); 2381 int b = FXDIB_ALPHA_MERGE(*ori_scan, m_Blue, src_alpha); 2382 ori_scan += Bpp - 2; 2383 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); 2384 dest_scan++; 2385 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); 2386 dest_scan++; 2387 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); 2388 dest_scan += Bpp - 2; 2389 } 2390 } 2391 return; 2392 } 2393 if (Bpp == 4 && bDestAlpha) { 2394 for (int col = col_start; col < col_end; col++) { 2395 int src_alpha; 2396 if (clip_scan) { 2397 src_alpha = m_Alpha * clip_scan[col] / 255; 2398 } else { 2399 src_alpha = m_Alpha; 2400 } 2401 int src_alpha_covered = src_alpha * cover_scan[col] / 255; 2402 if (src_alpha_covered == 0) { 2403 dest_scan += 4; 2404 continue; 2405 } 2406 if (cover_scan[col] == 255) { 2407 dest_scan[3] = src_alpha_covered; 2408 *dest_scan++ = m_Blue; 2409 *dest_scan++ = m_Green; 2410 *dest_scan = m_Red; 2411 dest_scan += 2; 2412 continue; 2413 } else { 2414 if (dest_scan[3] == 0) { 2415 dest_scan[3] = src_alpha_covered; 2416 *dest_scan++ = m_Blue; 2417 *dest_scan++ = m_Green; 2418 *dest_scan = m_Red; 2419 dest_scan += 2; 2420 continue; 2421 } 2422 uint8_t cover = cover_scan[col]; 2423 dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover); 2424 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover); 2425 dest_scan++; 2426 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover); 2427 dest_scan++; 2428 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover); 2429 dest_scan += 2; 2430 } 2431 } 2432 return; 2433 } 2434 if (Bpp == 3 || Bpp == 4) { 2435 for (int col = col_start; col < col_end; col++) { 2436 int src_alpha; 2437 if (clip_scan) { 2438 src_alpha = m_Alpha * clip_scan[col] / 255; 2439 } else { 2440 src_alpha = m_Alpha; 2441 } 2442 if (m_bFullCover) { 2443 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); 2444 *dest_scan++ = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); 2445 *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); 2446 dest_scan += Bpp - 2; 2447 ori_scan += Bpp - 2; 2448 continue; 2449 } 2450 int b = FXDIB_ALPHA_MERGE(*ori_scan++, m_Blue, src_alpha); 2451 int g = FXDIB_ALPHA_MERGE(*ori_scan++, m_Green, src_alpha); 2452 int r = FXDIB_ALPHA_MERGE(*ori_scan, m_Red, src_alpha); 2453 ori_scan += Bpp - 2; 2454 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]); 2455 dest_scan++; 2456 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, g, cover_scan[col]); 2457 dest_scan++; 2458 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]); 2459 dest_scan += Bpp - 2; 2460 continue; 2461 } 2462 return; 2463 } 2464 if (Bpp == 1) { 2465 for (int col = col_start; col < col_end; col++) { 2466 int src_alpha; 2467 if (clip_scan) { 2468 src_alpha = m_Alpha * clip_scan[col] / 255; 2469 } else { 2470 src_alpha = m_Alpha; 2471 } 2472 if (m_bFullCover) { 2473 *dest_scan = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); 2474 } else { 2475 int gray = FXDIB_ALPHA_MERGE(*ori_scan++, m_Gray, src_alpha); 2476 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]); 2477 dest_scan++; 2478 } 2479 } 2480 } else { 2481 int index = 0; 2482 if (m_pDevice->GetPalette()) { 2483 for (int i = 0; i < 2; i++) { 2484 if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) { 2485 index = i; 2486 } 2487 } 2488 } else { 2489 index = ((uint8_t)m_Color == 0xff) ? 1 : 0; 2490 } 2491 uint8_t* dest_scan1 = dest_scan; 2492 for (int col = col_start; col < col_end; col++) { 2493 int src_alpha; 2494 if (clip_scan) { 2495 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2496 } else { 2497 src_alpha = m_Alpha * cover_scan[col] / 255; 2498 } 2499 if (src_alpha) { 2500 if (!index) { 2501 *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); 2502 } else { 2503 *dest_scan1 |= 1 << (7 - (col + span_left) % 8); 2504 } 2505 } 2506 dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; 2507 } 2508 } 2509 } 2510 2511 void CompositeSpan1bpp(uint8_t* dest_scan, 2512 int Bpp, 2513 int span_left, 2514 int span_len, 2515 uint8_t* cover_scan, 2516 int clip_left, 2517 int clip_right, 2518 uint8_t* clip_scan, 2519 uint8_t* dest_extra_alpha_scan) { 2520 ASSERT(!m_bRgbByteOrder); 2521 ASSERT(!m_pDevice->IsCmykImage()); 2522 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2523 int col_end = (span_left + span_len) < clip_right 2524 ? span_len 2525 : (clip_right - span_left); 2526 dest_scan += col_start / 8; 2527 int index = 0; 2528 if (m_pDevice->GetPalette()) { 2529 for (int i = 0; i < 2; i++) { 2530 if (FXARGB_TODIB(m_pDevice->GetPalette()[i]) == m_Color) { 2531 index = i; 2532 } 2533 } 2534 } else { 2535 index = ((uint8_t)m_Color == 0xff) ? 1 : 0; 2536 } 2537 uint8_t* dest_scan1 = dest_scan; 2538 for (int col = col_start; col < col_end; col++) { 2539 int src_alpha; 2540 if (clip_scan) { 2541 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2542 } else { 2543 src_alpha = m_Alpha * cover_scan[col] / 255; 2544 } 2545 if (src_alpha) { 2546 if (!index) { 2547 *dest_scan1 &= ~(1 << (7 - (col + span_left) % 8)); 2548 } else { 2549 *dest_scan1 |= 1 << (7 - (col + span_left) % 8); 2550 } 2551 } 2552 dest_scan1 = dest_scan + (span_left % 8 + col - col_start + 1) / 8; 2553 } 2554 } 2555 2556 void CompositeSpanGray(uint8_t* dest_scan, 2557 int Bpp, 2558 int span_left, 2559 int span_len, 2560 uint8_t* cover_scan, 2561 int clip_left, 2562 int clip_right, 2563 uint8_t* clip_scan, 2564 uint8_t* dest_extra_alpha_scan) { 2565 ASSERT(!m_bRgbByteOrder); 2566 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2567 int col_end = (span_left + span_len) < clip_right 2568 ? span_len 2569 : (clip_right - span_left); 2570 dest_scan += col_start; 2571 if (dest_extra_alpha_scan) { 2572 for (int col = col_start; col < col_end; col++) { 2573 int src_alpha; 2574 if (m_bFullCover) { 2575 if (clip_scan) { 2576 src_alpha = m_Alpha * clip_scan[col] / 255; 2577 } else { 2578 src_alpha = m_Alpha; 2579 } 2580 } else { 2581 if (clip_scan) { 2582 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2583 } else { 2584 src_alpha = m_Alpha * cover_scan[col] / 255; 2585 } 2586 } 2587 if (src_alpha) { 2588 if (src_alpha == 255) { 2589 *dest_scan = m_Gray; 2590 *dest_extra_alpha_scan = m_Alpha; 2591 } else { 2592 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - 2593 (*dest_extra_alpha_scan) * src_alpha / 255; 2594 *dest_extra_alpha_scan++ = dest_alpha; 2595 int alpha_ratio = src_alpha * 255 / dest_alpha; 2596 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); 2597 dest_scan++; 2598 continue; 2599 } 2600 } 2601 dest_extra_alpha_scan++; 2602 dest_scan++; 2603 } 2604 } else { 2605 for (int col = col_start; col < col_end; col++) { 2606 int src_alpha; 2607 if (clip_scan) { 2608 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2609 } else { 2610 src_alpha = m_Alpha * cover_scan[col] / 255; 2611 } 2612 if (src_alpha) { 2613 if (src_alpha == 255) { 2614 *dest_scan = m_Gray; 2615 } else { 2616 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); 2617 } 2618 } 2619 dest_scan++; 2620 } 2621 } 2622 } 2623 2624 void CompositeSpanARGB(uint8_t* dest_scan, 2625 int Bpp, 2626 int span_left, 2627 int span_len, 2628 uint8_t* cover_scan, 2629 int clip_left, 2630 int clip_right, 2631 uint8_t* clip_scan, 2632 uint8_t* dest_extra_alpha_scan) { 2633 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2634 int col_end = (span_left + span_len) < clip_right 2635 ? span_len 2636 : (clip_right - span_left); 2637 dest_scan += col_start * Bpp; 2638 if (m_bRgbByteOrder) { 2639 for (int col = col_start; col < col_end; col++) { 2640 int src_alpha; 2641 if (m_bFullCover) { 2642 if (clip_scan) { 2643 src_alpha = m_Alpha * clip_scan[col] / 255; 2644 } else { 2645 src_alpha = m_Alpha; 2646 } 2647 } else { 2648 if (clip_scan) { 2649 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2650 } else { 2651 src_alpha = m_Alpha * cover_scan[col] / 255; 2652 } 2653 } 2654 if (src_alpha) { 2655 if (src_alpha == 255) { 2656 *(uint32_t*)dest_scan = m_Color; 2657 } else { 2658 uint8_t dest_alpha = 2659 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; 2660 dest_scan[3] = dest_alpha; 2661 int alpha_ratio = src_alpha * 255 / dest_alpha; 2662 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); 2663 dest_scan++; 2664 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); 2665 dest_scan++; 2666 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); 2667 dest_scan += 2; 2668 continue; 2669 } 2670 } 2671 dest_scan += 4; 2672 } 2673 return; 2674 } 2675 for (int col = col_start; col < col_end; col++) { 2676 int src_alpha; 2677 if (m_bFullCover) { 2678 if (clip_scan) { 2679 src_alpha = m_Alpha * clip_scan[col] / 255; 2680 } else { 2681 src_alpha = m_Alpha; 2682 } 2683 } else { 2684 if (clip_scan) { 2685 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2686 } else { 2687 src_alpha = m_Alpha * cover_scan[col] / 255; 2688 } 2689 } 2690 if (src_alpha) { 2691 if (src_alpha == 255) { 2692 *(uint32_t*)dest_scan = m_Color; 2693 } else { 2694 if (dest_scan[3] == 0) { 2695 dest_scan[3] = src_alpha; 2696 *dest_scan++ = m_Blue; 2697 *dest_scan++ = m_Green; 2698 *dest_scan = m_Red; 2699 dest_scan += 2; 2700 continue; 2701 } 2702 uint8_t dest_alpha = 2703 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255; 2704 dest_scan[3] = dest_alpha; 2705 int alpha_ratio = src_alpha * 255 / dest_alpha; 2706 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); 2707 dest_scan++; 2708 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); 2709 dest_scan++; 2710 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); 2711 dest_scan += 2; 2712 continue; 2713 } 2714 } 2715 dest_scan += Bpp; 2716 } 2717 } 2718 2719 void CompositeSpanRGB(uint8_t* dest_scan, 2720 int Bpp, 2721 int span_left, 2722 int span_len, 2723 uint8_t* cover_scan, 2724 int clip_left, 2725 int clip_right, 2726 uint8_t* clip_scan, 2727 uint8_t* dest_extra_alpha_scan) { 2728 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2729 int col_end = (span_left + span_len) < clip_right 2730 ? span_len 2731 : (clip_right - span_left); 2732 dest_scan += col_start * Bpp; 2733 if (m_bRgbByteOrder) { 2734 for (int col = col_start; col < col_end; col++) { 2735 int src_alpha; 2736 if (clip_scan) { 2737 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2738 } else { 2739 src_alpha = m_Alpha * cover_scan[col] / 255; 2740 } 2741 if (src_alpha) { 2742 if (src_alpha == 255) { 2743 if (Bpp == 4) { 2744 *(uint32_t*)dest_scan = m_Color; 2745 } else if (Bpp == 3) { 2746 *dest_scan++ = m_Red; 2747 *dest_scan++ = m_Green; 2748 *dest_scan++ = m_Blue; 2749 continue; 2750 } 2751 } else { 2752 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); 2753 dest_scan++; 2754 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); 2755 dest_scan++; 2756 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); 2757 dest_scan += Bpp - 2; 2758 continue; 2759 } 2760 } 2761 dest_scan += Bpp; 2762 } 2763 return; 2764 } 2765 if (Bpp == 3 && dest_extra_alpha_scan) { 2766 for (int col = col_start; col < col_end; col++) { 2767 int src_alpha; 2768 if (m_bFullCover) { 2769 if (clip_scan) { 2770 src_alpha = m_Alpha * clip_scan[col] / 255; 2771 } else { 2772 src_alpha = m_Alpha; 2773 } 2774 } else { 2775 if (clip_scan) { 2776 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2777 } else { 2778 src_alpha = m_Alpha * cover_scan[col] / 255; 2779 } 2780 } 2781 if (src_alpha) { 2782 if (src_alpha == 255) { 2783 *dest_scan++ = (uint8_t)m_Blue; 2784 *dest_scan++ = (uint8_t)m_Green; 2785 *dest_scan++ = (uint8_t)m_Red; 2786 *dest_extra_alpha_scan++ = (uint8_t)m_Alpha; 2787 continue; 2788 } else { 2789 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - 2790 (*dest_extra_alpha_scan) * src_alpha / 255; 2791 *dest_extra_alpha_scan++ = dest_alpha; 2792 int alpha_ratio = src_alpha * 255 / dest_alpha; 2793 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); 2794 dest_scan++; 2795 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); 2796 dest_scan++; 2797 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); 2798 dest_scan++; 2799 continue; 2800 } 2801 } 2802 dest_extra_alpha_scan++; 2803 dest_scan += Bpp; 2804 } 2805 } else { 2806 for (int col = col_start; col < col_end; col++) { 2807 int src_alpha; 2808 if (m_bFullCover) { 2809 if (clip_scan) { 2810 src_alpha = m_Alpha * clip_scan[col] / 255; 2811 } else { 2812 src_alpha = m_Alpha; 2813 } 2814 } else { 2815 if (clip_scan) { 2816 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2817 } else { 2818 src_alpha = m_Alpha * cover_scan[col] / 255; 2819 } 2820 } 2821 if (src_alpha) { 2822 if (src_alpha == 255) { 2823 if (Bpp == 4) { 2824 *(uint32_t*)dest_scan = m_Color; 2825 } else if (Bpp == 3) { 2826 *dest_scan++ = m_Blue; 2827 *dest_scan++ = m_Green; 2828 *dest_scan++ = m_Red; 2829 continue; 2830 } 2831 } else { 2832 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); 2833 dest_scan++; 2834 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); 2835 dest_scan++; 2836 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); 2837 dest_scan += Bpp - 2; 2838 continue; 2839 } 2840 } 2841 dest_scan += Bpp; 2842 } 2843 } 2844 } 2845 2846 void CompositeSpanCMYK(uint8_t* dest_scan, 2847 int Bpp, 2848 int span_left, 2849 int span_len, 2850 uint8_t* cover_scan, 2851 int clip_left, 2852 int clip_right, 2853 uint8_t* clip_scan, 2854 uint8_t* dest_extra_alpha_scan) { 2855 ASSERT(!m_bRgbByteOrder); 2856 int col_start = span_left < clip_left ? clip_left - span_left : 0; 2857 int col_end = (span_left + span_len) < clip_right 2858 ? span_len 2859 : (clip_right - span_left); 2860 dest_scan += col_start * 4; 2861 if (dest_extra_alpha_scan) { 2862 for (int col = col_start; col < col_end; col++) { 2863 int src_alpha; 2864 if (m_bFullCover) { 2865 if (clip_scan) { 2866 src_alpha = m_Alpha * clip_scan[col] / 255; 2867 } else { 2868 src_alpha = m_Alpha; 2869 } 2870 } else { 2871 if (clip_scan) { 2872 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2873 } else { 2874 src_alpha = m_Alpha * cover_scan[col] / 255; 2875 } 2876 } 2877 if (src_alpha) { 2878 if (src_alpha == 255) { 2879 *(FX_CMYK*)dest_scan = m_Color; 2880 *dest_extra_alpha_scan = (uint8_t)m_Alpha; 2881 } else { 2882 uint8_t dest_alpha = (*dest_extra_alpha_scan) + src_alpha - 2883 (*dest_extra_alpha_scan) * src_alpha / 255; 2884 *dest_extra_alpha_scan++ = dest_alpha; 2885 int alpha_ratio = src_alpha * 255 / dest_alpha; 2886 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio); 2887 dest_scan++; 2888 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio); 2889 dest_scan++; 2890 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio); 2891 dest_scan++; 2892 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, alpha_ratio); 2893 dest_scan++; 2894 continue; 2895 } 2896 } 2897 dest_extra_alpha_scan++; 2898 dest_scan += 4; 2899 } 2900 } else { 2901 for (int col = col_start; col < col_end; col++) { 2902 int src_alpha; 2903 if (clip_scan) { 2904 src_alpha = m_Alpha * cover_scan[col] * clip_scan[col] / 255 / 255; 2905 } else { 2906 src_alpha = m_Alpha * cover_scan[col] / 255; 2907 } 2908 if (src_alpha) { 2909 if (src_alpha == 255) { 2910 *(FX_CMYK*)dest_scan = m_Color; 2911 } else { 2912 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha); 2913 dest_scan++; 2914 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha); 2915 dest_scan++; 2916 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha); 2917 dest_scan++; 2918 *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha); 2919 dest_scan++; 2920 continue; 2921 } 2922 } 2923 dest_scan += 4; 2924 } 2925 } 2926 } 2927 2928 template <class Scanline> 2929 void render(const Scanline& sl) { 2930 if (!m_pOriDevice && !composite_span) { 2931 return; 2932 } 2933 int y = sl.y(); 2934 if (y < m_ClipBox.top || y >= m_ClipBox.bottom) { 2935 return; 2936 } 2937 uint8_t* dest_scan = m_pDevice->GetBuffer() + m_pDevice->GetPitch() * y; 2938 uint8_t* dest_scan_extra_alpha = nullptr; 2939 CFX_DIBitmap* pAlphaMask = m_pDevice->m_pAlphaMask; 2940 if (pAlphaMask) { 2941 dest_scan_extra_alpha = 2942 pAlphaMask->GetBuffer() + pAlphaMask->GetPitch() * y; 2943 } 2944 uint8_t* ori_scan = nullptr; 2945 if (m_pOriDevice) { 2946 ori_scan = m_pOriDevice->GetBuffer() + m_pOriDevice->GetPitch() * y; 2947 } 2948 int Bpp = m_pDevice->GetBPP() / 8; 2949 bool bDestAlpha = m_pDevice->HasAlpha() || m_pDevice->IsAlphaMask(); 2950 unsigned num_spans = sl.num_spans(); 2951 typename Scanline::const_iterator span = sl.begin(); 2952 while (1) { 2953 int x = span->x; 2954 ASSERT(span->len > 0); 2955 uint8_t* dest_pos = nullptr; 2956 uint8_t* dest_extra_alpha_pos = nullptr; 2957 uint8_t* ori_pos = nullptr; 2958 if (Bpp) { 2959 ori_pos = ori_scan ? ori_scan + x * Bpp : nullptr; 2960 dest_pos = dest_scan + x * Bpp; 2961 dest_extra_alpha_pos = 2962 dest_scan_extra_alpha ? dest_scan_extra_alpha + x : nullptr; 2963 } else { 2964 dest_pos = dest_scan + x / 8; 2965 ori_pos = ori_scan ? ori_scan + x / 8 : nullptr; 2966 } 2967 uint8_t* clip_pos = nullptr; 2968 if (m_pClipMask) { 2969 clip_pos = m_pClipMask->GetBuffer() + 2970 (y - m_ClipBox.top) * m_pClipMask->GetPitch() + x - 2971 m_ClipBox.left; 2972 } 2973 if (ori_pos) { 2974 CompositeSpan(dest_pos, ori_pos, Bpp, bDestAlpha, x, span->len, 2975 span->covers, m_ClipBox.left, m_ClipBox.right, clip_pos); 2976 } else { 2977 (this->*composite_span)(dest_pos, Bpp, x, span->len, span->covers, 2978 m_ClipBox.left, m_ClipBox.right, clip_pos, 2979 dest_extra_alpha_pos); 2980 } 2981 if (--num_spans == 0) { 2982 break; 2983 } 2984 ++span; 2985 } 2986 } 2987 2988 bool Init(CFX_DIBitmap* pDevice, 2989 CFX_DIBitmap* pOriDevice, 2990 const CFX_ClipRgn* pClipRgn, 2991 uint32_t color, 2992 bool bFullCover, 2993 bool bRgbByteOrder, 2994 int alpha_flag = 0, 2995 void* pIccTransform = nullptr) { 2996 m_pDevice = pDevice; 2997 m_pClipRgn = pClipRgn; 2998 composite_span = nullptr; 2999 m_bRgbByteOrder = bRgbByteOrder; 3000 m_pOriDevice = pOriDevice; 3001 if (m_pClipRgn) { 3002 m_ClipBox = m_pClipRgn->GetBox(); 3003 } else { 3004 m_ClipBox.left = m_ClipBox.top = 0; 3005 m_ClipBox.right = m_pDevice->GetWidth(); 3006 m_ClipBox.bottom = m_pDevice->GetHeight(); 3007 } 3008 m_pClipMask = nullptr; 3009 if (m_pClipRgn && m_pClipRgn->GetType() == CFX_ClipRgn::MaskF) { 3010 m_pClipMask = m_pClipRgn->GetMask().GetObject(); 3011 } 3012 m_bFullCover = bFullCover; 3013 bool bObjectCMYK = !!FXGETFLAG_COLORTYPE(alpha_flag); 3014 bool bDeviceCMYK = pDevice->IsCmykImage(); 3015 m_Alpha = bObjectCMYK ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color); 3016 CCodec_IccModule* pIccModule = nullptr; 3017 if (!CFX_GEModule::Get()->GetCodecModule() || 3018 !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { 3019 pIccTransform = nullptr; 3020 } else { 3021 pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 3022 } 3023 if (m_pDevice->GetBPP() == 8) { 3024 ASSERT(!m_bRgbByteOrder); 3025 composite_span = &CFX_Renderer::CompositeSpanGray; 3026 if (m_pDevice->IsAlphaMask()) { 3027 m_Gray = 255; 3028 } else { 3029 if (pIccTransform) { 3030 uint8_t gray; 3031 color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); 3032 pIccModule->TranslateScanline(pIccTransform, &gray, 3033 (const uint8_t*)&color, 1); 3034 m_Gray = gray; 3035 } else { 3036 if (bObjectCMYK) { 3037 uint8_t r, g, b; 3038 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), 3039 FXSYS_GetYValue(color), FXSYS_GetKValue(color), 3040 r, g, b); 3041 m_Gray = FXRGB2GRAY(r, g, b); 3042 } else { 3043 m_Gray = 3044 FXRGB2GRAY(FXARGB_R(color), FXARGB_G(color), FXARGB_B(color)); 3045 } 3046 } 3047 } 3048 return true; 3049 } 3050 if (bDeviceCMYK) { 3051 ASSERT(!m_bRgbByteOrder); 3052 composite_span = &CFX_Renderer::CompositeSpanCMYK; 3053 if (bObjectCMYK) { 3054 m_Color = FXCMYK_TODIB(color); 3055 if (pIccTransform) { 3056 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, 3057 (const uint8_t*)&m_Color, 1); 3058 } 3059 } else { 3060 if (!pIccTransform) { 3061 return false; 3062 } 3063 color = FXARGB_TODIB(color); 3064 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, 3065 (const uint8_t*)&color, 1); 3066 } 3067 m_Red = ((uint8_t*)&m_Color)[0]; 3068 m_Green = ((uint8_t*)&m_Color)[1]; 3069 m_Blue = ((uint8_t*)&m_Color)[2]; 3070 m_Gray = ((uint8_t*)&m_Color)[3]; 3071 } else { 3072 composite_span = (pDevice->GetFormat() == FXDIB_Argb) 3073 ? &CFX_Renderer::CompositeSpanARGB 3074 : &CFX_Renderer::CompositeSpanRGB; 3075 if (pIccTransform) { 3076 color = bObjectCMYK ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); 3077 pIccModule->TranslateScanline(pIccTransform, (uint8_t*)&m_Color, 3078 (const uint8_t*)&color, 1); 3079 ((uint8_t*)&m_Color)[3] = m_Alpha; 3080 m_Red = ((uint8_t*)&m_Color)[2]; 3081 m_Green = ((uint8_t*)&m_Color)[1]; 3082 m_Blue = ((uint8_t*)&m_Color)[0]; 3083 if (m_bRgbByteOrder) { 3084 m_Color = FXARGB_TODIB(m_Color); 3085 m_Color = FXARGB_TOBGRORDERDIB(m_Color); 3086 } 3087 } else { 3088 if (bObjectCMYK) { 3089 uint8_t r, g, b; 3090 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), 3091 FXSYS_GetYValue(color), FXSYS_GetKValue(color), r, 3092 g, b); 3093 m_Color = FXARGB_MAKE(m_Alpha, r, g, b); 3094 if (m_bRgbByteOrder) { 3095 m_Color = FXARGB_TOBGRORDERDIB(m_Color); 3096 } else { 3097 m_Color = FXARGB_TODIB(m_Color); 3098 } 3099 m_Red = r; 3100 m_Green = g; 3101 m_Blue = b; 3102 } else { 3103 if (m_bRgbByteOrder) { 3104 m_Color = FXARGB_TOBGRORDERDIB(color); 3105 } else { 3106 m_Color = FXARGB_TODIB(color); 3107 } 3108 ArgbDecode(color, m_Alpha, m_Red, m_Green, m_Blue); 3109 } 3110 } 3111 } 3112 if (m_pDevice->GetBPP() == 1) { 3113 composite_span = &CFX_Renderer::CompositeSpan1bpp; 3114 } 3115 return true; 3116 } 3117 }; 3118 3119 #endif // _SKIA_SUPPORT_PATHS_ 3120