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