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