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