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