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