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