1 /*
2  * Copyright 2011 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 #ifndef SkXPSDevice_DEFINED
9 #define SkXPSDevice_DEFINED
10 
11 #include "SkTypes.h"
12 
13 #ifdef SK_BUILD_FOR_WIN
14 
15 #include <ObjBase.h>
16 #include <XpsObjectModel.h>
17 
18 #include "SkAutoCoInitialize.h"
19 #include "SkBitSet.h"
20 #include "SkBitmapDevice.h"
21 #include "SkCanvas.h"
22 #include "SkClipStackDevice.h"
23 #include "SkColor.h"
24 #include "SkPaint.h"
25 #include "SkPath.h"
26 #include "SkPoint.h"
27 #include "SkShader.h"
28 #include "SkSize.h"
29 #include "SkTArray.h"
30 #include "SkTScopedComPtr.h"
31 #include "SkTypeface.h"
32 
33 class SkGlyphRunList;
34 
35 //#define SK_XPS_USE_DETERMINISTIC_IDS
36 
37 /** \class SkXPSDevice
38 
39     The drawing context for the XPS backend.
40 */
41 class SkXPSDevice : public SkClipStackDevice {
42 public:
43     SK_API SkXPSDevice(SkISize);
44     SK_API ~SkXPSDevice() override;
45 
46     bool beginPortfolio(SkWStream* outputStream, IXpsOMObjectFactory*);
47     /**
48       @param unitsPerMeter converts geometry units into physical units.
49       @param pixelsPerMeter resolution to use when geometry must be rasterized.
50       @param trimSize final page size in physical units.
51                       The top left of the trim is the origin of physical space.
52       @param mediaBox The size of the physical media in physical units.
53                       The top and left must be less than zero.
54                       The bottom and right must be greater than the trimSize.
55                       The default is to coincide with the trimSize.
56       @param bleedBox The size of the bleed box in physical units.
57                       Must be contained within the mediaBox.
58                       The default is to coincide with the mediaBox.
59       @param artBox The size of the content box in physical units.
60                     Must be contained within the trimSize.
61                     The default is to coincide with the trimSize.
62       @param cropBox The size of the recommended view port in physical units.
63                      Must be contained within the mediaBox.
64                      The default is to coincide with the mediaBox.
65      */
66     bool beginSheet(
67         const SkVector& unitsPerMeter,
68         const SkVector& pixelsPerMeter,
69         const SkSize& trimSize,
70         const SkRect* mediaBox = NULL,
71         const SkRect* bleedBox = NULL,
72         const SkRect* artBox = NULL,
73         const SkRect* cropBox = NULL);
74 
75     bool endSheet();
76     bool endPortfolio();
77 
78 protected:
79     void drawPaint(const SkPaint& paint) override;
80     void drawPoints(SkCanvas::PointMode mode, size_t count,
81                     const SkPoint[], const SkPaint& paint) override;
82     void drawRect(const SkRect& r,
83                   const SkPaint& paint) override;
84     void drawOval(const SkRect& oval,
85                   const SkPaint& paint) override;
86     void drawRRect(const SkRRect& rr,
87                    const SkPaint& paint) override;
88     void drawPath(const SkPath& path,
89                   const SkPaint& paint,
90                   bool pathIsMutable = false) override;
91     void drawSprite(const SkBitmap& bitmap,
92                     int x, int y, const SkPaint& paint) override;
93     void drawBitmapRect(const SkBitmap&,
94                         const SkRect* srcOrNull, const SkRect& dst,
95                         const SkPaint& paint,
96                         SkCanvas::SrcRectConstraint) override;
drawGlyphRunList(const SkGlyphRunList & glyphRunList)97     void drawGlyphRunList(const SkGlyphRunList& glyphRunList) override {
98         SK_ABORT("Needs an implementation");
99     }
100     void drawVertices(const SkVertices*, const SkVertices::Bone bones[], int boneCount, SkBlendMode,
101                       const SkPaint&) override;
102     void drawDevice(SkBaseDevice*, int x, int y,
103                     const SkPaint&) override;
104 
105 private:
106     class TypefaceUse : ::SkNoncopyable {
107     public:
108         SkFontID typefaceId;
109         int ttcIndex;
110         SkStream* fontData;
111         IXpsOMFontResource* xpsFont;
112         SkBitSet* glyphsUsed;
113 
114         explicit TypefaceUse();
115         ~TypefaceUse();
116     };
117     friend HRESULT subset_typeface(TypefaceUse* current);
118 
119     bool createCanvasForLayer();
120 
121     SkTScopedComPtr<IXpsOMObjectFactory> fXpsFactory;
122     SkTScopedComPtr<IStream> fOutputStream;
123     SkTScopedComPtr<IXpsOMPackageWriter> fPackageWriter;
124 
125     unsigned int fCurrentPage;
126     SkTScopedComPtr<IXpsOMCanvas> fCurrentXpsCanvas;
127     SkSize fCurrentCanvasSize;
128     SkVector fCurrentUnitsPerMeter;
129     SkVector fCurrentPixelsPerMeter;
130 
131     SkTArray<TypefaceUse, true> fTypefaces;
132 
133     /** Creates a GUID based id and places it into buffer.
134         buffer should have space for at least GUID_ID_LEN wide characters.
135         The string will always be wchar null terminated.
136         XXXXXXXXsXXXXsXXXXsXXXXsXXXXXXXXXXXX0
137         The string may begin with a digit,
138         and so may not be suitable as a bare resource key.
139      */
140     HRESULT createId(wchar_t* buffer, size_t bufferSize, wchar_t sep = '-');
141 #ifdef SK_XPS_USE_DETERMINISTIC_IDS
142     decltype(GUID::Data1) fNextId = 0;
143 #endif
144 
145     HRESULT initXpsDocumentWriter(IXpsOMImageResource* image);
146 
147     HRESULT createXpsPage(
148         const XPS_SIZE& pageSize,
149         IXpsOMPage** page);
150 
151     HRESULT createXpsThumbnail(
152         IXpsOMPage* page, const unsigned int pageNumber,
153         IXpsOMImageResource** image);
154 
155     void internalDrawRect(
156         const SkRect& r,
157         bool transformRect,
158         const SkPaint& paint);
159 
160     HRESULT createXpsBrush(
161         const SkPaint& skPaint,
162         IXpsOMBrush** xpsBrush,
163         const SkMatrix* parentTransform = NULL);
164 
165     HRESULT createXpsSolidColorBrush(
166         const SkColor skColor, const SkAlpha alpha,
167         IXpsOMBrush** xpsBrush);
168 
169     HRESULT createXpsImageBrush(
170         const SkBitmap& bitmap,
171         const SkMatrix& localMatrix,
172         const SkShader::TileMode (&xy)[2],
173         const SkAlpha alpha,
174         IXpsOMTileBrush** xpsBrush);
175 
176     HRESULT createXpsLinearGradient(
177         SkShader::GradientInfo info,
178         const SkAlpha alpha,
179         const SkMatrix& localMatrix,
180         IXpsOMMatrixTransform* xpsMatrixToUse,
181         IXpsOMBrush** xpsBrush);
182 
183     HRESULT createXpsRadialGradient(
184         SkShader::GradientInfo info,
185         const SkAlpha alpha,
186         const SkMatrix& localMatrix,
187         IXpsOMMatrixTransform* xpsMatrixToUse,
188         IXpsOMBrush** xpsBrush);
189 
190     HRESULT createXpsGradientStop(
191         const SkColor skColor,
192         const SkScalar offset,
193         IXpsOMGradientStop** xpsGradStop);
194 
195     HRESULT createXpsTransform(
196         const SkMatrix& matrix,
197         IXpsOMMatrixTransform ** xpsTransform);
198 
199     HRESULT createXpsRect(
200         const SkRect& rect,
201         BOOL stroke, BOOL fill,
202         IXpsOMGeometryFigure** xpsRect);
203 
204     HRESULT createXpsQuad(
205         const SkPoint (&points)[4],
206         BOOL stroke, BOOL fill,
207         IXpsOMGeometryFigure** xpsQuad);
208 
209     HRESULT CreateTypefaceUse(
210         const SkPaint& paint,
211         TypefaceUse** fontResource);
212 
213     HRESULT AddGlyphs(
214         IXpsOMObjectFactory* xpsFactory,
215         IXpsOMCanvas* canvas,
216         TypefaceUse* font,
217         LPCWSTR text,
218         XPS_GLYPH_INDEX* xpsGlyphs,
219         UINT32 xpsGlyphsLen,
220         XPS_POINT *origin,
221         FLOAT fontSize,
222         XPS_STYLE_SIMULATION sims,
223         const SkMatrix& transform,
224         const SkPaint& paint);
225 
226     HRESULT addXpsPathGeometry(
227         IXpsOMGeometryFigureCollection* figures,
228         BOOL stroke, BOOL fill, const SkPath& path);
229 
230     HRESULT createPath(
231         IXpsOMGeometryFigure* figure,
232         IXpsOMVisualCollection* visuals,
233         IXpsOMPath** path);
234 
235     HRESULT sideOfClamp(
236         const SkRect& leftPoints, const XPS_RECT& left,
237         IXpsOMImageResource* imageResource,
238         IXpsOMVisualCollection* visuals);
239 
240     HRESULT cornerOfClamp(
241         const SkRect& tlPoints,
242         const SkColor color,
243         IXpsOMVisualCollection* visuals);
244 
245     HRESULT clip(IXpsOMVisual* xpsVisual);
246 
247     HRESULT clipToPath(
248         IXpsOMVisual* xpsVisual,
249         const SkPath& clipPath,
250         XPS_FILL_RULE fillRule);
251 
252     HRESULT drawInverseWindingPath(
253         const SkPath& devicePath,
254         IXpsOMPath* xpsPath);
255 
256     HRESULT shadePath(
257         IXpsOMPath* shadedPath,
258         const SkPaint& shaderPaint,
259         const SkMatrix& matrix,
260         BOOL* fill, BOOL* stroke);
261 
262     void convertToPpm(
263         const SkMaskFilter* filter,
264         SkMatrix* matrix,
265         SkVector* ppuScale,
266         const SkIRect& clip, SkIRect* clipIRect);
267 
268     HRESULT applyMask(
269         const SkMask& mask,
270         const SkVector& ppuScale,
271         IXpsOMPath* shadedPath);
272 
273     SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
274 
275     // Disable the default copy and assign implementation.
276     SkXPSDevice(const SkXPSDevice&);
277     void operator=(const SkXPSDevice&);
278 
279     typedef SkClipStackDevice INHERITED;
280 };
281 
282 #endif  // SK_BUILD_FOR_WIN
283 #endif  // SkXPSDevice_DEFINED
284