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