• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_
RgbByteOrderTransferBitmap(const RetainPtr<CFX_DIBitmap> & pBitmap,int dest_left,int dest_top,int width,int height,const RetainPtr<CFX_DIBSource> & pSrcBitmap,int src_left,int src_top)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
DebugShowSkiaPaint(const SkPaint & paint)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 
DebugShowSkiaPath(const SkPath & path)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 
DebugShowCanvasClip(CFX_SkiaDeviceDriver * driver,const SkCanvas * canvas)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 
DebugShowSkiaDrawPath(CFX_SkiaDeviceDriver * driver,const SkCanvas * canvas,const SkPaint & paint,const SkPath & path)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 
DebugShowSkiaDrawRect(CFX_SkiaDeviceDriver * driver,const SkCanvas * canvas,const SkPaint & paint,const SkRect & rect)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 
DebugClipPaint()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 
DebugDrawSkiaClipRect(SkCanvas * canvas,const SkRect & rect)247 void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {
248   SkPaint paint = DebugClipPaint();
249   canvas->drawRect(rect, paint);
250 }
251 
DebugDrawSkiaClipPath(SkCanvas * canvas,const SkPath & path)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 
DebugDrawSkiaClipRect(SkCanvas * canvas,const SkRect & rect)259 void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {}
260 
DebugDrawSkiaClipPath(SkCanvas * canvas,const SkPath & path)261 void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {}
262 
263 #endif  // DRAW_SKIA_CLIP
264 
265 #ifdef _SKIA_SUPPORT_
DebugValidate(const RetainPtr<CFX_DIBitmap> & bitmap,const RetainPtr<CFX_DIBitmap> & device)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 
BuildPath(const CFX_PathData * pPathData)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 
ToSkMatrix(const CFX_Matrix & m)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
ToFlippedSkMatrix(const CFX_Matrix & m,SkScalar flip)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 
GetSkiaBlendMode(int blend_type)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 
AddColors(const CPDF_ExpIntFunc * pFunc,SkTDArray<SkColor> * skColors)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 
FloatToByte(float f)376 uint8_t FloatToByte(float f) {
377   ASSERT(0 <= f && f <= 1);
378   return (uint8_t)(f * 255.99f);
379 }
380 
AddSamples(const CPDF_SampledFunc * pFunc,SkTDArray<SkColor> * skColors,SkTDArray<SkScalar> * skPos)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 
AddStitching(const CPDF_StitchFunc * pFunc,SkTDArray<SkColor> * skColors,SkTDArray<SkScalar> * skPos)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
LineSide(const SkPoint line[2],const SkPoint & pt)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 
IntersectSides(const SkPoint & parallelPt,const SkVector & paraRay,const SkPoint & perpendicularPt)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 
ClipAngledGradient(const SkPoint pts[2],SkPoint rectPts[4],bool clipStart,bool clipEnd,SkPath * clip)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_
SetBitmapMatrix(const CFX_Matrix * pMatrix,int width,int height,SkMatrix * skMatrix)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 
SetBitmapPaint(bool isAlphaMask,uint32_t argb,int bitmap_alpha,int blend_type,SkPaint * paint)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 
Upsample(const RetainPtr<CFX_DIBSource> & pSource,std::unique_ptr<uint8_t,FxFreeDeleter> & dst8Storage,std::unique_ptr<uint32_t,FxFreeDeleter> & dst32Storage,SkBitmap * skBitmap,int * widthPtr,int * heightPtr,bool forceAlpha)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
SkiaState(CFX_SkiaDeviceDriver * pDriver)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 
DrawPath(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,const CFX_GraphStateData * pDrawState,uint32_t fill_color,uint32_t stroke_color,int fill_mode,int blend_type)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 
FlushPath()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 
HasRSX(int nChars,const FXTEXT_CHARPOS * pCharPos,float * scaleXPtr,bool * oneAtATimePtr)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 
DrawText(int nChars,const FXTEXT_CHARPOS * pCharPos,CFX_Font * pFont,const CFX_Matrix * pMatrix,float font_size,uint32_t color)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 
FlushText()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 
IsEmpty()946   bool IsEmpty() { return !m_commands.count(); }
947 
SetClipFill(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,int fill_mode)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 
SetClip(const SkPath & skClipPath)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 
SetClipStroke(const CFX_PathData * pPathData,const CFX_Matrix * pMatrix,const CFX_GraphStateData * pGraphState)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 
MatrixOffset(const CFX_Matrix * pMatrix,SkPoint * delta)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
ClipSave()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 
ClipRestore()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 
DrawChanged(const CFX_Matrix * pMatrix,const CFX_GraphStateData * pState,uint32_t fill_color,uint32_t stroke_color,int fill_mode,int blend_type,bool group_knockout) const1080   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 
FontChanged(CFX_Font * pFont,const CFX_Matrix * pMatrix,float font_size,float scaleX,uint32_t color) const1095   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 
MatrixChanged(const CFX_Matrix * pMatrix,const CFX_Matrix & refMatrix) const1107   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 
StateChanged(const CFX_GraphStateData * pState,const CFX_GraphStateData & refState) const1116   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 
DashChanged(const CFX_GraphStateData * pState,const CFX_GraphStateData & refState) const1128   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 
AdjustClip(int limit)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 
Flush()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 
FlushForDraw()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
DumpPrefix(int index) const1184   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 
DumpEndPrefix() const1194   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 
Dump(const char * where) const1203   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
AggSaveCount(const UnownedPtr<CFX_SkiaDeviceDriver> driver)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 
CacheSaveCount(const SkTDArray<SkiaState::Clip> & commands,int commandIndex)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 
DebugCheckClip()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
DumpClipStacks() const1347   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
PaintStroke(SkPaint * spaint,const CFX_GraphStateData * pGraphState,const SkMatrix & matrix)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 
CFX_SkiaDeviceDriver(const RetainPtr<CFX_DIBitmap> & pBitmap,bool bRgbByteOrder,const RetainPtr<CFX_DIBitmap> & pOriDevice,bool bGroupKnockout)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_
CFX_SkiaDeviceDriver(int size_x,int size_y)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 
CFX_SkiaDeviceDriver(SkPictureRecorder * recorder)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 
~CFX_SkiaDeviceDriver()1541 CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() {
1542   Flush();
1543   if (!m_pRecorder)
1544     delete m_pCanvas;
1545 }
1546 
Flush()1547 void CFX_SkiaDeviceDriver::Flush() {
1548   m_pCache->Flush();
1549 }
1550 
PreMultiply()1551 void CFX_SkiaDeviceDriver::PreMultiply() {
1552   m_pBitmap->PreMultiply();
1553 }
1554 
DrawDeviceText(int nChars,const FXTEXT_CHARPOS * pCharPos,CFX_Font * pFont,const CFX_Matrix * pObject2Device,float font_size,uint32_t color)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 
GetDeviceCaps(int caps_id) const1673 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 
SaveState()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 
RestoreState(bool bKeepSaved)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_
SetClipMask(const FX_RECT & clipBox,const SkPath & path)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 
SetClip_PathFill(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,int fill_mode)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 
SetClip_PathStroke(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState)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 
DrawPath(const CFX_PathData * pPathData,const CFX_Matrix * pObject2Device,const CFX_GraphStateData * pGraphState,uint32_t fill_color,uint32_t stroke_color,int fill_mode,int blend_type)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 
DrawCosmeticLine(const CFX_PointF & ptMoveTo,const CFX_PointF & ptLineTo,uint32_t color,int blend_type)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 
FillRectWithBlend(const FX_RECT * pRect,uint32_t fill_color,int blend_type)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 
DrawShading(const CPDF_ShadingPattern * pPattern,const CFX_Matrix * pMatrix,const FX_RECT & clip_rect,int alpha,bool bAlphaMode)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 
GetBuffer() const2163 uint8_t* CFX_SkiaDeviceDriver::GetBuffer() const {
2164   return m_pBitmap->GetBuffer();
2165 }
2166 
GetClipBox(FX_RECT * pRect)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 
GetDIBits(const RetainPtr<CFX_DIBitmap> & pBitmap,int left,int top)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 
GetBackDrop()2252 RetainPtr<CFX_DIBitmap> CFX_SkiaDeviceDriver::GetBackDrop() {
2253   return m_pOriDevice;
2254 }
2255 
SetDIBits(const RetainPtr<CFX_DIBSource> & pBitmap,uint32_t argb,const FX_RECT * pSrcRect,int left,int top,int blend_type)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 
StretchDIBits(const RetainPtr<CFX_DIBSource> & pSource,uint32_t argb,int dest_left,int dest_top,int dest_width,int dest_height,const FX_RECT * pClipRect,uint32_t flags,int blend_type)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 
StartDIBits(const RetainPtr<CFX_DIBSource> & pSource,int bitmap_alpha,uint32_t argb,const CFX_Matrix * pMatrix,uint32_t render_flags,std::unique_ptr<CFX_ImageRenderer> * handle,int blend_type)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 
ContinueDIBits(CFX_ImageRenderer * handle,IFX_PauseIndicator * pPause)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_
PreMultiply(const RetainPtr<CFX_DIBitmap> & pDIBitmap)2414 void CFX_SkiaDeviceDriver::PreMultiply(
2415     const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
2416   pDIBitmap->PreMultiply();
2417 }
2418 #endif  // _SKIA_SUPPORT_
2419 
PreMultiply()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_
UnPreMultiply()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_
DrawBitsWithMask(const RetainPtr<CFX_DIBSource> & pSource,const RetainPtr<CFX_DIBSource> & pMask,int bitmap_alpha,const CFX_Matrix * pMatrix,int blend_type)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 
SetBitsWithMask(const RetainPtr<CFX_DIBSource> & pBitmap,const RetainPtr<CFX_DIBSource> & pMask,int dest_left,int dest_top,int bitmap_alpha,int blend_type)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 
Clear(uint32_t color)2526 void CFX_SkiaDeviceDriver::Clear(uint32_t color) {
2527   m_pCanvas->clear(color);
2528 }
2529 #endif  // _SKIA_SUPPORT_
2530 
Dump() const2531 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_
DebugVerifyBitmapIsPreMultiplied() const2539 void CFX_SkiaDeviceDriver::DebugVerifyBitmapIsPreMultiplied() const {
2540   if (m_pOriDevice)
2541     m_pOriDevice->DebugVerifyBitmapIsPreMultiplied(nullptr);
2542 }
2543 #endif  // _SKIA_SUPPORT_
2544 
CFX_DefaultRenderDevice()2545 CFX_DefaultRenderDevice::CFX_DefaultRenderDevice() {}
2546 
2547 #ifdef _SKIA_SUPPORT_
Clear(uint32_t color)2548 void CFX_DefaultRenderDevice::Clear(uint32_t color) {
2549   CFX_SkiaDeviceDriver* skDriver =
2550       static_cast<CFX_SkiaDeviceDriver*>(GetDeviceDriver());
2551   skDriver->Clear(color);
2552 }
2553 
CreateRecorder(int size_x,int size_y)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 
Attach(const RetainPtr<CFX_DIBitmap> & pBitmap,bool bRgbByteOrder,const RetainPtr<CFX_DIBitmap> & pOriDevice,bool bGroupKnockout)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_
AttachRecorder(SkPictureRecorder * recorder)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 
Create(int width,int height,FXDIB_Format format,const RetainPtr<CFX_DIBitmap> & pOriDevice)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 
~CFX_DefaultRenderDevice()2598 CFX_DefaultRenderDevice::~CFX_DefaultRenderDevice() {
2599   Flush(true);
2600 }
2601 
2602 #ifdef _SKIA_SUPPORT_
DebugVerifyBitmapIsPreMultiplied() const2603 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 
SetBitsWithMask(const RetainPtr<CFX_DIBSource> & pBitmap,const RetainPtr<CFX_DIBSource> & pMask,int left,int top,int bitmap_alpha,int blend_type)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 
DebugVerifyBitmapIsPreMultiplied(void * opt) const2628 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