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