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 "include/core/SkTypes.h"
12 
13 #ifdef SK_BUILD_FOR_WIN
14 
15 #include <ObjBase.h>
16 #include <XpsObjectModel.h>
17 
18 #include "include/core/SkCanvas.h"
19 #include "include/core/SkColor.h"
20 #include "include/core/SkPaint.h"
21 #include "include/core/SkPath.h"
22 #include "include/core/SkPoint.h"
23 #include "include/core/SkShader.h"
24 #include "include/core/SkSize.h"
25 #include "include/core/SkTypeface.h"
26 #include "include/private/SkTArray.h"
27 #include "src/core/SkBitmapDevice.h"
28 #include "src/core/SkClipStackDevice.h"
29 #include "src/utils/SkBitSet.h"
30 #include "src/utils/win/SkAutoCoInitialize.h"
31 #include "src/utils/win/SkTScopedComPtr.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;
97     void drawGlyphRunList(const SkGlyphRunList& glyphRunList) override;
98     void drawVertices(const SkVertices*, const SkVertices::Bone bones[], int boneCount, SkBlendMode,
99                       const SkPaint&) override;
100     void drawDevice(SkBaseDevice*, int x, int y,
101                     const SkPaint&) override;
102 
103 private:
104     class TypefaceUse {
105     public:
TypefaceUse(SkFontID id,int index,std::unique_ptr<SkStream> data,SkTScopedComPtr<IXpsOMFontResource> xps,size_t numGlyphs)106         TypefaceUse(SkFontID id, int index, std::unique_ptr<SkStream> data,
107                     SkTScopedComPtr<IXpsOMFontResource> xps, size_t numGlyphs)
108             : typefaceId(id), ttcIndex(index), fontData(std::move(data))
109             , xpsFont(std::move(xps)), glyphsUsed(numGlyphs) {}
110         const SkFontID typefaceId;
111         const int ttcIndex;
112         const std::unique_ptr<SkStream> fontData;
113         const SkTScopedComPtr<IXpsOMFontResource> xpsFont;
114         SkBitSet glyphsUsed;
115     };
116     friend HRESULT subset_typeface(const TypefaceUse& current);
117 
118     bool createCanvasForLayer();
119 
120     SkTScopedComPtr<IXpsOMObjectFactory> fXpsFactory;
121     SkTScopedComPtr<IStream> fOutputStream;
122     SkTScopedComPtr<IXpsOMPackageWriter> fPackageWriter;
123 
124     unsigned int fCurrentPage;
125     SkTScopedComPtr<IXpsOMCanvas> fCurrentXpsCanvas;
126     SkSize fCurrentCanvasSize;
127     SkVector fCurrentUnitsPerMeter;
128     SkVector fCurrentPixelsPerMeter;
129 
130     SkTArray<TypefaceUse, true> fTypefaces;
131 
132     /** Creates a GUID based id and places it into buffer.
133         buffer should have space for at least GUID_ID_LEN wide characters.
134         The string will always be wchar null terminated.
135         XXXXXXXXsXXXXsXXXXsXXXXsXXXXXXXXXXXX0
136         The string may begin with a digit,
137         and so may not be suitable as a bare resource key.
138      */
139     HRESULT createId(wchar_t* buffer, size_t bufferSize, wchar_t sep = '-');
140 #ifdef SK_XPS_USE_DETERMINISTIC_IDS
141     decltype(GUID::Data1) fNextId = 0;
142 #endif
143 
144     HRESULT initXpsDocumentWriter(IXpsOMImageResource* image);
145 
146     HRESULT createXpsPage(
147         const XPS_SIZE& pageSize,
148         IXpsOMPage** page);
149 
150     HRESULT createXpsThumbnail(
151         IXpsOMPage* page, const unsigned int pageNumber,
152         IXpsOMImageResource** image);
153 
154     void internalDrawRect(
155         const SkRect& r,
156         bool transformRect,
157         const SkPaint& paint);
158 
159     HRESULT createXpsBrush(
160         const SkPaint& skPaint,
161         IXpsOMBrush** xpsBrush,
162         const SkMatrix* parentTransform = NULL);
163 
164     HRESULT createXpsSolidColorBrush(
165         const SkColor skColor, const SkAlpha alpha,
166         IXpsOMBrush** xpsBrush);
167 
168     HRESULT createXpsImageBrush(
169         const SkBitmap& bitmap,
170         const SkMatrix& localMatrix,
171         const SkTileMode (&xy)[2],
172         const SkAlpha alpha,
173         IXpsOMTileBrush** xpsBrush);
174 
175     HRESULT createXpsLinearGradient(
176         SkShader::GradientInfo info,
177         const SkAlpha alpha,
178         const SkMatrix& localMatrix,
179         IXpsOMMatrixTransform* xpsMatrixToUse,
180         IXpsOMBrush** xpsBrush);
181 
182     HRESULT createXpsRadialGradient(
183         SkShader::GradientInfo info,
184         const SkAlpha alpha,
185         const SkMatrix& localMatrix,
186         IXpsOMMatrixTransform* xpsMatrixToUse,
187         IXpsOMBrush** xpsBrush);
188 
189     HRESULT createXpsGradientStop(
190         const SkColor skColor,
191         const SkScalar offset,
192         IXpsOMGradientStop** xpsGradStop);
193 
194     HRESULT createXpsTransform(
195         const SkMatrix& matrix,
196         IXpsOMMatrixTransform ** xpsTransform);
197 
198     HRESULT createXpsRect(
199         const SkRect& rect,
200         BOOL stroke, BOOL fill,
201         IXpsOMGeometryFigure** xpsRect);
202 
203     HRESULT createXpsQuad(
204         const SkPoint (&points)[4],
205         BOOL stroke, BOOL fill,
206         IXpsOMGeometryFigure** xpsQuad);
207 
208     HRESULT CreateTypefaceUse(
209         const SkFont& font,
210         TypefaceUse** fontResource);
211 
212     HRESULT AddGlyphs(
213         IXpsOMObjectFactory* xpsFactory,
214         IXpsOMCanvas* canvas,
215         const TypefaceUse* font,
216         LPCWSTR text,
217         XPS_GLYPH_INDEX* xpsGlyphs,
218         UINT32 xpsGlyphsLen,
219         XPS_POINT *origin,
220         FLOAT fontSize,
221         XPS_STYLE_SIMULATION sims,
222         const SkMatrix& transform,
223         const SkPaint& paint);
224 
225     HRESULT addXpsPathGeometry(
226         IXpsOMGeometryFigureCollection* figures,
227         BOOL stroke, BOOL fill, const SkPath& path);
228 
229     HRESULT createPath(
230         IXpsOMGeometryFigure* figure,
231         IXpsOMVisualCollection* visuals,
232         IXpsOMPath** path);
233 
234     HRESULT sideOfClamp(
235         const SkRect& leftPoints, const XPS_RECT& left,
236         IXpsOMImageResource* imageResource,
237         IXpsOMVisualCollection* visuals);
238 
239     HRESULT cornerOfClamp(
240         const SkRect& tlPoints,
241         const SkColor color,
242         IXpsOMVisualCollection* visuals);
243 
244     HRESULT clip(IXpsOMVisual* xpsVisual);
245 
246     HRESULT clipToPath(
247         IXpsOMVisual* xpsVisual,
248         const SkPath& clipPath,
249         XPS_FILL_RULE fillRule);
250 
251     HRESULT drawInverseWindingPath(
252         const SkPath& devicePath,
253         IXpsOMPath* xpsPath);
254 
255     HRESULT shadePath(
256         IXpsOMPath* shadedPath,
257         const SkPaint& shaderPaint,
258         const SkMatrix& matrix,
259         BOOL* fill, BOOL* stroke);
260 
261     void convertToPpm(
262         const SkMaskFilter* filter,
263         SkMatrix* matrix,
264         SkVector* ppuScale,
265         const SkIRect& clip, SkIRect* clipIRect);
266 
267     HRESULT applyMask(
268         const SkMask& mask,
269         const SkVector& ppuScale,
270         IXpsOMPath* shadedPath);
271 
272     SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) override;
273 
274     // Disable the default copy and assign implementation.
275     SkXPSDevice(const SkXPSDevice&);
276     void operator=(const SkXPSDevice&);
277 
278     typedef SkClipStackDevice INHERITED;
279 };
280 
281 #endif  // SK_BUILD_FOR_WIN
282 #endif  // SkXPSDevice_DEFINED
283