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