• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkPDFDeviceFlattener.h"
9 
10 #include "SkDraw.h"
11 
SkSizeToISize(const SkSize & size)12 static SkISize SkSizeToISize(const SkSize& size) {
13     return SkISize::Make(SkScalarRoundToInt(size.width()), SkScalarRoundToInt(size.height()));
14 }
15 
SkPDFDeviceFlattener(const SkSize & pageSize,const SkRect * trimBox)16 SkPDFDeviceFlattener::SkPDFDeviceFlattener(const SkSize& pageSize, const SkRect* trimBox)
17             : SkPDFDevice(SkSizeToISize(pageSize),
18                           SkSizeToISize(pageSize),
19                           SkMatrix::I()) {
20     // TODO(edisonn): store the trimbox on emit.
21 }
22 
~SkPDFDeviceFlattener()23 SkPDFDeviceFlattener::~SkPDFDeviceFlattener() {
24 }
25 
flattenPaint(const SkDraw & d,SkPaint * paint)26 static void flattenPaint(const SkDraw& d, SkPaint* paint) {
27     if (paint->getShader()) {
28         SkMatrix local = paint->getShader()->getLocalMatrix();
29         local.preConcat(*d.fMatrix);
30         paint->getShader()->setLocalMatrix(local);
31     }
32 }
33 
drawPoints(const SkDraw & d,SkCanvas::PointMode mode,size_t count,const SkPoint points[],const SkPaint & paint)34 void SkPDFDeviceFlattener::drawPoints(const SkDraw& d, SkCanvas::PointMode mode,
35                                       size_t count, const SkPoint points[],
36                                       const SkPaint& paint) {
37     if (!mustFlatten(d)) {
38         INHERITED::drawPoints(d, mode, count, points, paint);
39         return;
40     }
41 
42     SkPaint paintFlatten(paint);
43     flattenPaint(d, &paintFlatten);
44 
45     SkPoint* flattenedPoints = SkNEW_ARRAY(SkPoint, count);
46     d.fMatrix->mapPoints(flattenedPoints, points, SkToS32(count));
47     SkDraw draw(d);
48     SkMatrix identity = SkMatrix::I();
49     draw.fMatrix = &identity;
50     INHERITED::drawPoints(draw, mode, count, flattenedPoints, paintFlatten);
51     SkDELETE_ARRAY(flattenedPoints);
52 }
53 
drawRect(const SkDraw & d,const SkRect & r,const SkPaint & paint)54 void SkPDFDeviceFlattener::drawRect(const SkDraw& d, const SkRect& r, const SkPaint& paint) {
55     if (!mustFlatten(d)) {
56         INHERITED::drawRect(d, r, paint);
57         return;
58     }
59 
60     SkPath path;
61     path.addRect(r);
62     path.transform(*d.fMatrix);
63     SkDraw draw(d);
64     SkMatrix matrix = SkMatrix::I();
65     draw.fMatrix = &matrix;
66 
67     SkPaint paintFlatten(paint);
68     flattenPaint(d, &paintFlatten);
69 
70     INHERITED::drawPath(draw, path, paintFlatten, NULL, true);
71 }
72 
drawPath(const SkDraw & d,const SkPath & origPath,const SkPaint & paint,const SkMatrix * prePathMatrix,bool pathIsMutable)73 void SkPDFDeviceFlattener::drawPath(const SkDraw& d, const SkPath& origPath,
74                                     const SkPaint& paint, const SkMatrix* prePathMatrix,
75                                     bool pathIsMutable) {
76     if (!mustFlatten(d) && !(prePathMatrix && prePathMatrix->hasPerspective())) {
77         INHERITED::drawPath(d, origPath, paint, prePathMatrix, pathIsMutable);
78         return;
79     }
80 
81     SkPath* pathPtr = (SkPath*)&origPath;
82     SkPath tmpPath;
83 
84     if (!pathIsMutable) {
85         tmpPath = origPath;
86         pathPtr = &tmpPath;
87     }
88 
89     if (prePathMatrix) {
90         pathPtr->transform(*prePathMatrix);
91     }
92 
93     SkPaint paintFlatten(paint);
94     flattenPaint(d, &paintFlatten);
95 
96     bool fill = paintFlatten.getFillPath(*pathPtr, &tmpPath);
97     SkDEBUGCODE(pathPtr = (SkPath*)0x12345678);  // Don't use pathPtr after this point.
98 
99     paintFlatten.setPathEffect(NULL);
100     if (fill) {
101         paintFlatten.setStyle(SkPaint::kFill_Style);
102     } else {
103         paintFlatten.setStyle(SkPaint::kStroke_Style);
104         paintFlatten.setStrokeWidth(0);
105     }
106 
107     tmpPath.transform(*d.fMatrix);
108 
109     SkDraw draw(d);
110     SkMatrix matrix = SkMatrix::I();
111     draw.fMatrix = &matrix;
112 
113     INHERITED::drawPath(draw, tmpPath, paintFlatten, NULL, true);
114 }
115 
drawText(const SkDraw & d,const void * text,size_t len,SkScalar x,SkScalar y,const SkPaint & paint)116 void SkPDFDeviceFlattener::drawText(const SkDraw& d, const void* text, size_t len,
117                                     SkScalar x, SkScalar y, const SkPaint& paint) {
118     if (mustPathText(d, paint)) {
119         d.drawText_asPaths((const char*)text, len, x, y, paint);
120         return;
121     }
122 
123     INHERITED::drawText(d, text, len, x, y, paint);
124 }
125 
drawPosText(const SkDraw & d,const void * text,size_t len,const SkScalar pos[],SkScalar constY,int scalarsPerPos,const SkPaint & paint)126 void SkPDFDeviceFlattener::drawPosText(const SkDraw& d, const void* text, size_t len,
127                                        const SkScalar pos[], SkScalar constY,
128                                        int scalarsPerPos, const SkPaint& paint) {
129     if (mustPathText(d, paint)) {
130         d.drawPosText_asPaths((const char*)text, len, pos, constY, scalarsPerPos, paint);
131         return;
132     }
133     INHERITED::drawPosText(d, text, len, pos, constY,scalarsPerPos, paint);
134 }
135 
drawTextOnPath(const SkDraw & d,const void * text,size_t len,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)136 void SkPDFDeviceFlattener::drawTextOnPath(const SkDraw& d, const void* text, size_t len,
137                                           const SkPath& path, const SkMatrix* matrix,
138                                           const SkPaint& paint) {
139     if (mustPathText(d, paint) || (matrix && matrix->hasPerspective())) {
140         d.drawTextOnPath((const char*)text, len, path, matrix, paint);
141         return;
142     }
143     INHERITED::drawTextOnPath(d, text, len, path, matrix, paint);
144 }
145 
mustFlatten(const SkDraw & d) const146 bool SkPDFDeviceFlattener::mustFlatten(const SkDraw& d) const {
147     // TODO(edisonn): testability, add flag to force return true.
148     return d.fMatrix->hasPerspective();
149 }
150 
mustPathText(const SkDraw & d,const SkPaint &)151 bool SkPDFDeviceFlattener::mustPathText(const SkDraw& d, const SkPaint&) {
152     // TODO(edisonn): testability, add flag to force return true.
153     // TODO(edisonn): TBD: How to flatten MaskFilter.
154     return d.fMatrix->hasPerspective();
155 }
156