SkPdfGraphicsState.h revision f68aed33819cbc98a95edeadde1da9303eca7fb2
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#ifndef SkPdfGraphicsState_DEFINED
9#define SkPdfGraphicsState_DEFINED
10
11#include "SkCanvas.h"
12#include "SkPaint.h"
13#include "SkPdfConfig.h"
14#include "SkPdfUtils.h"
15
16//#include "SkTDStack.h"
17
18class SkPdfFont;
19class SkPdfDoc;
20class SkPdfNativeObject;
21class SkPdfResourceDictionary;
22class SkPdfSoftMaskDictionary;
23
24class SkPdfNativeDoc;
25class SkPdfAllocator;
26
27// TODO(edisonn): move this class in include/core?
28// Ref objects can't be dealt unless we use a specific class initialization
29// The difference between SkTDStackNew and SkTDStack is that SkTDStackNew uses new/delete
30// to be a manage c++ stuff (like initializations)
31
32// Adobe limits it to 28, so 256 should be more than enough
33#define MAX_NESTING 256
34
35#include "SkTypes.h"
36template <typename T> class SkTDStackNew : SkNoncopyable {
37public:
38    SkTDStackNew() : fCount(0), fTotalCount(0), fLocalCount(0) {
39        fInitialRec.fNext = NULL;
40        fRec = &fInitialRec;
41
42    //  fCount = kSlotCount;
43    }
44
45    ~SkTDStackNew() {
46        Rec* rec = fRec;
47        while (rec != &fInitialRec) {
48            Rec* next = rec->fNext;
49            delete rec;
50            rec = next;
51        }
52    }
53
54    int count() const { return fLocalCount; }
55    int depth() const { return fLocalCount; }
56    bool empty() const { return fLocalCount == 0; }
57
58    bool nests() {
59        return fNestingLevel;
60    }
61
62    void nest() {
63        // We are are past max nesting levels, we will still continue to work, but we might fail
64        // to properly ignore errors. Ideally it should only mean poor rendering in exceptional
65        // cases
66        if (fNestingLevel >= 0 && fNestingLevel < MAX_NESTING) {
67            fNestings[fNestingLevel] = fLocalCount;
68            fLocalCount = 0;
69        }
70        fNestingLevel++;
71    }
72
73    void unnest() {
74        SkASSERT(fNestingLevel > 0);
75        fNestingLevel--;
76        if (fNestingLevel >= 0 && fNestingLevel < MAX_NESTING) {
77            // TODO(edisonn): warn if fLocal > 0
78            while (fLocalCount > 0) {
79                pop();
80            }
81            fLocalCount = fNestings[fNestingLevel];
82        }
83    }
84
85    T* push() {
86        SkASSERT(fCount <= kSlotCount);
87        if (fCount == kSlotCount) {
88            Rec* rec = new Rec();
89            rec->fNext = fRec;
90            fRec = rec;
91            fCount = 0;
92        }
93        ++fTotalCount;
94        ++fLocalCount;
95        return &fRec->fSlots[fCount++];
96    }
97
98    void push(const T& elem) { *this->push() = elem; }
99
100    const T& index(int idx) const {
101        SkASSERT(fRec && fCount > idx);
102        return fRec->fSlots[fCount - idx - 1];
103    }
104
105    T& index(int idx) {
106        SkASSERT(fRec && fCount > idx);
107        return fRec->fSlots[fCount - idx - 1];
108    }
109
110    const T& top() const {
111        SkASSERT(fRec && fCount > 0);
112        return fRec->fSlots[fCount - 1];
113    }
114
115    T& top() {
116        SkASSERT(fRec && fCount > 0);
117        return fRec->fSlots[fCount - 1];
118    }
119
120    void pop(T* elem) {
121        if (elem) {
122            *elem = fRec->fSlots[fCount - 1];
123        }
124        this->pop();
125    }
126
127    void pop() {
128        SkASSERT(fCount > 0 && fRec);
129        --fLocalCount;
130        --fTotalCount;
131        if (--fCount == 0) {
132            if (fRec != &fInitialRec) {
133                Rec* rec = fRec->fNext;
134                delete fRec;
135                fCount = kSlotCount;
136                fRec = rec;
137            } else {
138                SkASSERT(fTotalCount == 0);
139            }
140        }
141    }
142
143private:
144    enum {
145        kSlotCount  = 64
146    };
147
148    struct Rec;
149    friend struct Rec;
150
151    struct Rec {
152        Rec* fNext;
153        T    fSlots[kSlotCount];
154    };
155    Rec     fInitialRec;
156    Rec*    fRec;
157    int     fCount, fTotalCount, fLocalCount;
158    int     fNestings[MAX_NESTING];
159    int     fNestingLevel;
160};
161
162// TODO(edisonn): better class design.
163class SkPdfColorOperator {
164
165    /*
166    color space   name or array     The current color space in which color values are to be interpreted
167                                    (see Section 4.5, “Color Spaces”). There are two separate color space
168                                    parameters: one for stroking and one for all other painting opera-
169                                    tions. Initial value: DeviceGray.
170     */
171
172    // TODO(edisonn): implement the array part too
173    // does not own the char*
174// TODO(edisonn): remove this public, let fields be private
175// TODO(edisonn): make color space an enum!
176public:
177    NotOwnedString fColorSpace;
178    SkPdfNativeObject* fPattern;
179
180    /*
181    color         (various)         The current color to be used during painting operations (see Section
182                                    4.5, “Color Spaces”). The type and interpretation of this parameter
183                                    depend on the current color space; for most color spaces, a color
184                                    value consists of one to four numbers. There are two separate color
185                                    parameters: one for stroking and one for all other painting opera-
186                                    tions. Initial value: black.
187     */
188
189    SkColor fColor;
190    double fOpacity;  // ca or CA
191
192    // TODO(edisonn): add here other color space options.
193
194public:
195    void setRGBColor(SkColor color) {
196        // TODO(edisonn): ASSERT DeviceRGB is the color space.
197        fPattern = NULL;
198        fColor = color;
199    }
200    // TODO(edisonn): double check the default values for all fields.
201    SkPdfColorOperator() : fPattern(NULL), fColor(SK_ColorBLACK), fOpacity(1) {
202        NotOwnedString::init(&fColorSpace, "DeviceRGB");
203    }
204
205    void setColorSpace(NotOwnedString* colorSpace) {
206        fColorSpace = *colorSpace;
207        fPattern = NULL;
208    }
209
210    void setPatternColorSpace(SkPdfNativeObject* pattern) {
211        fColorSpace.fBuffer = (const unsigned char*)"Pattern";
212        fColorSpace.fBytes = 7;  // strlen("Pattern")
213        fPattern = pattern;
214    }
215
216    void applyGraphicsState(SkPaint* paint) {
217        paint->setColor(SkColorSetA(fColor, (U8CPU)(fOpacity * 255)));
218    }
219};
220
221// TODO(edisonn): better class design.
222struct SkPdfGraphicsState {
223    // TODO(edisonn): deprecate and remove these!
224    double              fCurPosX;
225    double              fCurPosY;
226
227    double              fCurFontSize;
228    bool                fTextBlock;
229    SkPdfFont*          fSkFont;
230    SkPath              fPath;
231    bool                fPathClosed;
232
233    double              fTextLeading;
234    double              fWordSpace;
235    double              fCharSpace;
236
237    SkPdfResourceDictionary* fResources;
238
239
240    // TODO(edisonn): move most of these in canvas/paint?
241    // we could have some in canvas (matrixes?),
242    // some in 2 paints (stroking paint and non stroking paint)
243
244//    TABLE 4.2 Device-independent graphics state parameters
245/*
246 * CTM           array             The current transformation matrix, which maps positions from user
247                                coordinates to device coordinates (see Section 4.2, “Coordinate Sys-
248                                tems”). This matrix is modified by each application of the coordi-
249                                nate transformation operator, cm. Initial value: a matrix that
250                                transforms default user coordinates to device coordinates.
251 */
252    SkMatrix fCTM;
253
254    SkMatrix fContentStreamMatrix;
255
256/*
257clipping path (internal)        The current clipping path, which defines the boundary against
258                                which all output is to be cropped (see Section 4.4.3, “Clipping Path
259                                Operators”). Initial value: the boundary of the entire imageable
260                                portion of the output page.
261 */
262    // Clip that is applied after the drawing is done!!!
263    bool                fHasClipPathToApply;
264    SkPath              fClipPath;
265
266    SkPdfColorOperator  fStroking;
267    SkPdfColorOperator  fNonStroking;
268
269/*
270text state    (various)         A set of nine graphics state parameters that pertain only to the
271                                painting of text. These include parameters that select the font, scale
272                                the glyphs to an appropriate size, and accomplish other effects. The
273                                text state parameters are described in Section 5.2, “Text State
274                                Parameters and Operators.”
275 */
276
277    // TODO(edisonn): add SkPdfTextState class. remove these two existing fields
278    SkMatrix            fMatrixTm;
279    SkMatrix            fMatrixTlm;
280
281
282/*
283line width    number            The thickness, in user space units, of paths to be stroked (see “Line
284                                Width” on page 152). Initial value: 1.0.
285 */
286    double              fLineWidth;
287
288
289/*
290line cap      integer           A code specifying the shape of the endpoints for any open path that
291                                is stroked (see “Line Cap Style” on page 153). Initial value: 0, for
292                                square butt caps.
293 */
294    // TODO (edisonn): implement defaults - page 153
295    int fLineCap;
296
297/*
298line join     integer           A code specifying the shape of joints between connected segments
299                                of a stroked path (see “Line Join Style” on page 153). Initial value: 0,
300                                for mitered joins.
301 */
302    // TODO (edisonn): implement defaults - page 153
303    int fLineJoin;
304
305/*
306miter limit   number            The maximum length of mitered line joins for stroked paths (see
307                                “Miter Limit” on page 153). This parameter limits the length of
308                                “spikes” produced when line segments join at sharp angles. Initial
309                                value: 10.0, for a miter cutoff below approximately 11.5 degrees.
310 */
311    // TODO (edisonn): implement defaults - page 153
312    double fMiterLimit;
313
314/*
315dash pattern      array and     A description of the dash pattern to be used when paths are
316                  number        stroked (see “Line Dash Pattern” on page 155). Initial value: a solid
317                                line.
318 */
319    SkScalar fDashArray[256]; // TODO(edisonn): allocate array?
320    int fDashArrayLength;
321    SkScalar fDashPhase;
322
323
324/*
325rendering intent  name          The rendering intent to be used when converting CIE-based colors
326                                to device colors (see “Rendering Intents” on page 197). Default
327                                value: RelativeColorimetric.
328 */
329    // TODO(edisonn): seems paper only. Verify.
330
331/*
332stroke adjustment boolean       (PDF 1.2) A flag specifying whether to compensate for possible ras-
333                                terization effects when stroking a path with a line width that is
334                                small relative to the pixel resolution of the output device (see Sec-
335                                tion 6.5.4, “Automatic Stroke Adjustment”). Note that this is con-
336                                sidered a device-independent parameter, even though the details of
337                                its effects are device-dependent. Initial value: false.
338 */
339    // TODO(edisonn): stroke adjustment low priority.
340
341
342/*
343blend mode        name or array (PDF 1.4) The current blend mode to be used in the transparent
344                                imaging model (see Sections 7.2.4, “Blend Mode,” and 7.5.2, “Spec-
345                                ifying Blending Color Space and Blend Mode”). This parameter is
346                                implicitly reset to its initial value at the beginning of execution of a
347                                transparency group XObject (see Section 7.5.5, “Transparency
348                                Group XObjects”). Initial value: Normal.
349 */
350    SkXfermode::Mode fBlendModes[256];
351    int fBlendModesLength;
352
353/*
354soft mask         dictionary    (PDF 1.4) A soft-mask dictionary (see “Soft-Mask Dictionaries” on
355                  or name       page 445) specifying the mask shape or mask opacity values to be
356                                used in the transparent imaging model (see “Source Shape and
357                                Opacity” on page 421 and “Mask Shape and Opacity” on page 443),
358                                or the name None if no such mask is specified. This parameter is
359                                implicitly reset to its initial value at the beginning of execution of a
360                                transparency group XObject (see Section 7.5.5, “Transparency
361                                Group XObjects”). Initial value: None.
362 */
363    SkPdfSoftMaskDictionary* fSoftMaskDictionary;
364    // TODO(edisonn): make sMask private, add setter and getter, ref/unref/..., at the moment we most likely leask
365    SkBitmap*                fSMask;
366
367
368/*
369alpha constant    number        (PDF 1.4) The constant shape or constant opacity value to be used
370                                in the transparent imaging model (see “Source Shape and Opacity”
371                                on page 421 and “Constant Shape and Opacity” on page 444).
372                                There are two separate alpha constant parameters: one for stroking
373                                and one for all other painting operations. This parameter is implic-
374                                itly reset to its initial value at the beginning of execution of a trans-
375                                parency group XObject (see Section 7.5.5, “Transparency Group
376                                XObjects”). Initial value: 1.0.
377 */
378    double fAphaConstant;
379
380/*
381alpha source      boolean       (PDF 1.4) A flag specifying whether the current soft mask and alpha
382                                constant parameters are to be interpreted as shape values (true) or
383                                opacity values (false). This flag also governs the interpretation of
384                                the SMask entry, if any, in an image dictionary (see Section 4.8.4,
385                                “Image Dictionaries”). Initial value: false.
386 */
387    bool fAlphaSource;
388
389
390// TODO(edisonn): Device-dependent seem to be required only on the actual physical printer?
391//                       TABLE 4.3 Device-dependent graphics state parameters
392/*
393overprint          boolean            (PDF 1.2) A flag specifying (on output devices that support the
394                                      overprint control feature) whether painting in one set of colorants
395                                      should cause the corresponding areas of other colorants to be
396                                      erased (false) or left unchanged (true); see Section 4.5.6, “Over-
397                                      print Control.” In PDF 1.3, there are two separate overprint param-
398                                      eters: one for stroking and one for all other painting operations.
399                                      Initial value: false.
400 */
401
402
403/*
404overprint mode     number             (PDF 1.3) A code specifying whether a color component value of 0
405                                      in a DeviceCMYK color space should erase that component (0) or
406                                      leave it unchanged (1) when overprinting (see Section 4.5.6, “Over-
407                                      print Control”). Initial value: 0.
408 */
409
410
411/*
412black generation   function           (PDF 1.2) A function that calculates the level of the black color
413                   or name            component to use when converting RGB colors to CMYK (see Sec-
414                                      tion 6.2.3, “Conversion from DeviceRGB to DeviceCMYK”). Initial
415                                      value: installation-dependent.
416 */
417
418
419/*
420undercolor removal function           (PDF 1.2) A function that calculates the reduction in the levels of
421                   or name            the cyan, magenta, and yellow color components to compensate for
422                                      the amount of black added by black generation (see Section 6.2.3,
423                                      “Conversion from DeviceRGB to DeviceCMYK”). Initial value: in-
424                                      stallation-dependent.
425 */
426
427
428/*
429transfer           function,          (PDF 1.2) A function that adjusts device gray or color component
430                   array, or name     levels to compensate for nonlinear response in a particular out-
431                                      put device (see Section 6.3, “Transfer Functions”). Initial value:
432                                      installation-dependent.
433 */
434
435
436/*
437halftone           dictionary,        (PDF 1.2) A halftone screen for gray and color rendering, specified
438                   stream, or name    as a halftone dictionary or stream (see Section 6.4, “Halftones”).
439                                      Initial value: installation-dependent.
440 */
441
442
443/*
444flatness            number             The precision with which curves are to be rendered on the output
445                                      device (see Section 6.5.1, “Flatness Tolerance”). The value of this
446                                      parameter gives the maximum error tolerance, measured in output
447                                      device pixels; smaller numbers give smoother curves at the expense
448                                      of more computation and memory use. Initial value: 1.0.
449 */
450
451
452/*
453smoothness             number             (PDF 1.3) The precision with which color gradients are to be ren-
454                                          dered on the output device (see Section 6.5.2, “Smoothness Toler-
455                                          ance”). The value of this parameter gives the maximum error
456                                          tolerance, expressed as a fraction of the range of each color compo-
457                                          nent; smaller numbers give smoother color transitions at the
458                                          expense of more computation and memory use. Initial value:
459                                          installation-dependent.
460 */
461
462
463
464
465
466
467
468    SkPdfGraphicsState() {
469        fCurPosX      = 0.0;
470        fCurPosY      = 0.0;
471        fCurFontSize  = 0.0;
472        fTextBlock    = false;
473        fCTM          = SkMatrix::I();
474        fMatrixTm     = SkMatrix::I();
475        fMatrixTlm    = SkMatrix::I();
476        fPathClosed   = true;
477        fLineWidth    = 0;
478        fTextLeading  = 0;
479        fWordSpace    = 0;
480        fCharSpace    = 0;
481        fHasClipPathToApply = false;
482        fResources    = NULL;
483        fSkFont       = NULL;
484        fLineCap      = 0;
485        fLineJoin     = 0;
486        fMiterLimit   = 10.0;
487        fAphaConstant = 1.0;
488        fAlphaSource  = false;
489        fDashArrayLength = 0;
490        fDashPhase    = 0;
491        fBlendModesLength = 1;
492        fBlendModes[0] = SkXfermode::kSrc_Mode;  // PDF: Normal Blend mode
493        fSMask        = NULL;
494    }
495
496    // TODO(edisonn): make two functons instead, stroking and non stoking, avoid branching
497    void applyGraphicsState(SkPaint* paint, bool stroking);
498};
499
500// TODO(edisonn): better class design.
501// TODO(edisonn): rename to SkPdfContext
502class SkPdfContext {
503public:
504    SkTDStackNew<SkPdfNativeObject*>  fObjectStack;
505    SkTDStackNew<SkPdfGraphicsState>  fStateStack;
506    SkPdfGraphicsState              fGraphicsState;
507    SkPdfNativeDoc*                 fPdfDoc;
508    // TODO(edisonn): the allocator, could be freed after the page is done drawing.
509    SkPdfAllocator*                 fTmpPageAllocator;
510    SkMatrix                        fOriginalMatrix;
511
512    SkPdfContext(SkPdfNativeDoc* doc);
513    ~SkPdfContext();
514};
515
516#endif  // SkPdfGraphicsState_DEFINED
517