OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkPDFDevice.h" | 8 #include "SkPDFDevice.h" |
9 | 9 |
10 #include "SkAnnotation.h" | 10 #include "SkAnnotation.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 | 36 |
37 #define DPI_FOR_RASTER_SCALE_ONE 72 | 37 #define DPI_FOR_RASTER_SCALE_ONE 72 |
38 | 38 |
39 // Utility functions | 39 // Utility functions |
40 | 40 |
41 // If the paint will definitely draw opaquely, replace kSrc_Mode with | 41 // If the paint will definitely draw opaquely, replace kSrc_Mode with |
42 // kSrcOver_Mode. http://crbug.com/473572 | 42 // kSrcOver_Mode. http://crbug.com/473572 |
43 static void replace_srcmode_on_opaque_paint(SkPaint* paint) { | 43 static void replace_srcmode_on_opaque_paint(SkPaint* paint) { |
44 if (kSrcOver_SkXfermodeInterpretation | 44 if (kSrcOver_SkXfermodeInterpretation |
45 == SkInterpretXfermode(*paint, false)) { | 45 == SkInterpretXfermode(*paint, false)) { |
46 paint->setXfermode(NULL); | 46 paint->setXfermode(nullptr); |
47 } | 47 } |
48 } | 48 } |
49 | 49 |
50 static void emit_pdf_color(SkColor color, SkWStream* result) { | 50 static void emit_pdf_color(SkColor color, SkWStream* result) { |
51 SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere. | 51 SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere. |
52 SkScalar colorScale = SkScalarInvert(0xFF); | 52 SkScalar colorScale = SkScalarInvert(0xFF); |
53 SkPDFUtils::AppendScalar(SkColorGetR(color) * colorScale, result); | 53 SkPDFUtils::AppendScalar(SkColorGetR(color) * colorScale, result); |
54 result->writeText(" "); | 54 result->writeText(" "); |
55 SkPDFUtils::AppendScalar(SkColorGetG(color) * colorScale, result); | 55 SkPDFUtils::AppendScalar(SkColorGetG(color) * colorScale, result); |
56 result->writeText(" "); | 56 result->writeText(" "); |
(...skipping 22 matching lines...) Expand all Loading... |
79 // Stolen from measure_text in SkDraw.cpp and then tweaked. | 79 // Stolen from measure_text in SkDraw.cpp and then tweaked. |
80 static void align_text(SkDrawCacheProc glyphCacheProc, const SkPaint& paint, | 80 static void align_text(SkDrawCacheProc glyphCacheProc, const SkPaint& paint, |
81 const uint16_t* glyphs, size_t len, | 81 const uint16_t* glyphs, size_t len, |
82 SkScalar* x, SkScalar* y) { | 82 SkScalar* x, SkScalar* y) { |
83 if (paint.getTextAlign() == SkPaint::kLeft_Align) { | 83 if (paint.getTextAlign() == SkPaint::kLeft_Align) { |
84 return; | 84 return; |
85 } | 85 } |
86 | 86 |
87 SkMatrix ident; | 87 SkMatrix ident; |
88 ident.reset(); | 88 ident.reset(); |
89 SkAutoGlyphCache autoCache(paint, NULL, &ident); | 89 SkAutoGlyphCache autoCache(paint, nullptr, &ident); |
90 SkGlyphCache* cache = autoCache.getCache(); | 90 SkGlyphCache* cache = autoCache.getCache(); |
91 | 91 |
92 const char* start = reinterpret_cast<const char*>(glyphs); | 92 const char* start = reinterpret_cast<const char*>(glyphs); |
93 const char* stop = reinterpret_cast<const char*>(glyphs + len); | 93 const char* stop = reinterpret_cast<const char*>(glyphs + len); |
94 SkFixed xAdv = 0, yAdv = 0; | 94 SkFixed xAdv = 0, yAdv = 0; |
95 | 95 |
96 // TODO(vandebo): This probably needs to take kerning into account. | 96 // TODO(vandebo): This probably needs to take kerning into account. |
97 while (start < stop) { | 97 while (start < stop) { |
98 const SkGlyph& glyph = glyphCacheProc(cache, &start, 0, 0); | 98 const SkGlyph& glyph = glyphCacheProc(cache, &start, 0, 0); |
99 xAdv += glyph.fAdvanceX; | 99 xAdv += glyph.fAdvanceX; |
(...skipping 19 matching lines...) Expand all Loading... |
119 return typeface->countGlyphs() - 1; | 119 return typeface->countGlyphs() - 1; |
120 } | 120 } |
121 | 121 |
122 typedef SkAutoSTMalloc<128, uint16_t> SkGlyphStorage; | 122 typedef SkAutoSTMalloc<128, uint16_t> SkGlyphStorage; |
123 | 123 |
124 static int force_glyph_encoding(const SkPaint& paint, const void* text, | 124 static int force_glyph_encoding(const SkPaint& paint, const void* text, |
125 size_t len, SkGlyphStorage* storage, | 125 size_t len, SkGlyphStorage* storage, |
126 const uint16_t** glyphIDs) { | 126 const uint16_t** glyphIDs) { |
127 // Make sure we have a glyph id encoding. | 127 // Make sure we have a glyph id encoding. |
128 if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { | 128 if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { |
129 int numGlyphs = paint.textToGlyphs(text, len, NULL); | 129 int numGlyphs = paint.textToGlyphs(text, len, nullptr); |
130 storage->reset(numGlyphs); | 130 storage->reset(numGlyphs); |
131 paint.textToGlyphs(text, len, storage->get()); | 131 paint.textToGlyphs(text, len, storage->get()); |
132 *glyphIDs = storage->get(); | 132 *glyphIDs = storage->get(); |
133 return numGlyphs; | 133 return numGlyphs; |
134 } | 134 } |
135 | 135 |
136 // For user supplied glyph ids we need to validate them. | 136 // For user supplied glyph ids we need to validate them. |
137 SkASSERT((len & 1) == 0); | 137 SkASSERT((len & 1) == 0); |
138 int numGlyphs = SkToInt(len / 2); | 138 int numGlyphs = SkToInt(len / 2); |
139 const uint16_t* input = static_cast<const uint16_t*>(text); | 139 const uint16_t* input = static_cast<const uint16_t*>(text); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
197 | 197 |
198 // When emitting the content entry, we will ensure the graphic state | 198 // When emitting the content entry, we will ensure the graphic state |
199 // is set to these values first. | 199 // is set to these values first. |
200 SkColor fColor; | 200 SkColor fColor; |
201 SkScalar fTextScaleX; // Zero means we don't care what the value is. | 201 SkScalar fTextScaleX; // Zero means we don't care what the value is. |
202 SkPaint::Style fTextFill; // Only if TextScaleX is non-zero. | 202 SkPaint::Style fTextFill; // Only if TextScaleX is non-zero. |
203 int fShaderIndex; | 203 int fShaderIndex; |
204 int fGraphicStateIndex; | 204 int fGraphicStateIndex; |
205 | 205 |
206 // We may change the font (i.e. for Type1 support) within a | 206 // We may change the font (i.e. for Type1 support) within a |
207 // ContentEntry. This is the one currently in effect, or NULL if none. | 207 // ContentEntry. This is the one currently in effect, or nullptr if none. |
208 SkPDFFont* fFont; | 208 SkPDFFont* fFont; |
209 // In PDF, text size has no default value. It is only valid if fFont is | 209 // In PDF, text size has no default value. It is only valid if fFont is |
210 // not NULL. | 210 // not nullptr. |
211 SkScalar fTextSize; | 211 SkScalar fTextSize; |
212 }; | 212 }; |
213 | 213 |
214 GraphicStateEntry::GraphicStateEntry() : fColor(SK_ColorBLACK), | 214 GraphicStateEntry::GraphicStateEntry() : fColor(SK_ColorBLACK), |
215 fTextScaleX(SK_Scalar1), | 215 fTextScaleX(SK_Scalar1), |
216 fTextFill(SkPaint::kFill_Style), | 216 fTextFill(SkPaint::kFill_Style), |
217 fShaderIndex(-1), | 217 fShaderIndex(-1), |
218 fGraphicStateIndex(-1), | 218 fGraphicStateIndex(-1), |
219 fFont(NULL), | 219 fFont(nullptr), |
220 fTextSize(SK_ScalarNaN) { | 220 fTextSize(SK_ScalarNaN) { |
221 fMatrix.reset(); | 221 fMatrix.reset(); |
222 } | 222 } |
223 | 223 |
224 bool GraphicStateEntry::compareInitialState(const GraphicStateEntry& cur) { | 224 bool GraphicStateEntry::compareInitialState(const GraphicStateEntry& cur) { |
225 return fColor == cur.fColor && | 225 return fColor == cur.fColor && |
226 fShaderIndex == cur.fShaderIndex && | 226 fShaderIndex == cur.fShaderIndex && |
227 fGraphicStateIndex == cur.fGraphicStateIndex && | 227 fGraphicStateIndex == cur.fGraphicStateIndex && |
228 fMatrix == cur.fMatrix && | 228 fMatrix == cur.fMatrix && |
229 fClipStack == cur.fClipStack && | 229 fClipStack == cur.fClipStack && |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 SkASSERT(prefixEntry->getOp() == SkRegion::kIntersect_Op); | 302 SkASSERT(prefixEntry->getOp() == SkRegion::kIntersect_Op); |
303 SkASSERT(iterEntry->getOp() == SkRegion::kIntersect_Op); | 303 SkASSERT(iterEntry->getOp() == SkRegion::kIntersect_Op); |
304 SkASSERT(iterEntry->getType() == prefixEntry->getType()); | 304 SkASSERT(iterEntry->getType() == prefixEntry->getType()); |
305 // back up the iterator by one | 305 // back up the iterator by one |
306 iter->prev(); | 306 iter->prev(); |
307 prefixEntry = prefixIter.next(); | 307 prefixEntry = prefixIter.next(); |
308 break; | 308 break; |
309 } | 309 } |
310 } | 310 } |
311 | 311 |
312 SkASSERT(prefixEntry == NULL); | 312 SkASSERT(prefixEntry == nullptr); |
313 } | 313 } |
314 | 314 |
315 static void emit_clip(SkPath* clipPath, SkRect* clipRect, | 315 static void emit_clip(SkPath* clipPath, SkRect* clipRect, |
316 SkWStream* contentStream) { | 316 SkWStream* contentStream) { |
317 SkASSERT(clipPath || clipRect); | 317 SkASSERT(clipPath || clipRect); |
318 | 318 |
319 SkPath::FillType clipFill; | 319 SkPath::FillType clipFill; |
320 if (clipPath) { | 320 if (clipPath) { |
321 SkPDFUtils::EmitPath(*clipPath, SkPaint::kFill_Style, contentStream); | 321 SkPDFUtils::EmitPath(*clipPath, SkPaint::kFill_Style, contentStream); |
322 clipFill = clipPath->getFillType(); | 322 clipFill = clipPath->getFillType(); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 | 437 |
438 currentEntry()->fClipStack = clipStack; | 438 currentEntry()->fClipStack = clipStack; |
439 currentEntry()->fClipRegion = clipRegion; | 439 currentEntry()->fClipRegion = clipRegion; |
440 | 440 |
441 SkMatrix transform; | 441 SkMatrix transform; |
442 transform.setTranslate(translation.fX, translation.fY); | 442 transform.setTranslate(translation.fX, translation.fY); |
443 | 443 |
444 #ifdef SK_PDF_USE_PATHOPS_CLIPPING | 444 #ifdef SK_PDF_USE_PATHOPS_CLIPPING |
445 SkPath clipPath; | 445 SkPath clipPath; |
446 if (get_clip_stack_path(transform, clipStack, clipRegion, &clipPath)) { | 446 if (get_clip_stack_path(transform, clipStack, clipRegion, &clipPath)) { |
447 emit_clip(&clipPath, NULL, fContentStream); | 447 emit_clip(&clipPath, nullptr, fContentStream); |
448 return; | 448 return; |
449 } | 449 } |
450 #endif | 450 #endif |
451 // gsState->initialEntry()->fClipStack/Region specifies the clip that has | 451 // gsState->initialEntry()->fClipStack/Region specifies the clip that has |
452 // already been applied. (If this is a top level device, then it specifies | 452 // already been applied. (If this is a top level device, then it specifies |
453 // a clip to the content area. If this is a layer, then it specifies | 453 // a clip to the content area. If this is a layer, then it specifies |
454 // the clip in effect when the layer was created.) There's no need to | 454 // the clip in effect when the layer was created.) There's no need to |
455 // reapply that clip; SKCanvas's SkDrawIter will draw anything outside the | 455 // reapply that clip; SKCanvas's SkDrawIter will draw anything outside the |
456 // initial clip on the parent layer. (This means there's a bug if the user | 456 // initial clip on the parent layer. (This means there's a bug if the user |
457 // expands the clip and then uses any xfer mode that uses dst: | 457 // expands the clip and then uses any xfer mode that uses dst: |
458 // http://code.google.com/p/skia/issues/detail?id=228 ) | 458 // http://code.google.com/p/skia/issues/detail?id=228 ) |
459 SkClipStack::Iter iter; | 459 SkClipStack::Iter iter; |
460 skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter); | 460 skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter); |
461 | 461 |
462 // If the clip stack does anything other than intersect or if it uses | 462 // If the clip stack does anything other than intersect or if it uses |
463 // an inverse fill type, we have to fall back to the clip region. | 463 // an inverse fill type, we have to fall back to the clip region. |
464 bool needRegion = false; | 464 bool needRegion = false; |
465 const SkClipStack::Element* clipEntry; | 465 const SkClipStack::Element* clipEntry; |
466 for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { | 466 for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { |
467 if (clipEntry->getOp() != SkRegion::kIntersect_Op || | 467 if (clipEntry->getOp() != SkRegion::kIntersect_Op || |
468 clipEntry->isInverseFilled()) { | 468 clipEntry->isInverseFilled()) { |
469 needRegion = true; | 469 needRegion = true; |
470 break; | 470 break; |
471 } | 471 } |
472 } | 472 } |
473 | 473 |
474 if (needRegion) { | 474 if (needRegion) { |
475 SkPath clipPath; | 475 SkPath clipPath; |
476 SkAssertResult(clipRegion.getBoundaryPath(&clipPath)); | 476 SkAssertResult(clipRegion.getBoundaryPath(&clipPath)); |
477 emit_clip(&clipPath, NULL, fContentStream); | 477 emit_clip(&clipPath, nullptr, fContentStream); |
478 } else { | 478 } else { |
479 skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter); | 479 skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter); |
480 const SkClipStack::Element* clipEntry; | 480 const SkClipStack::Element* clipEntry; |
481 for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { | 481 for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { |
482 SkASSERT(clipEntry->getOp() == SkRegion::kIntersect_Op); | 482 SkASSERT(clipEntry->getOp() == SkRegion::kIntersect_Op); |
483 switch (clipEntry->getType()) { | 483 switch (clipEntry->getType()) { |
484 case SkClipStack::Element::kRect_Type: { | 484 case SkClipStack::Element::kRect_Type: { |
485 SkRect translatedClip; | 485 SkRect translatedClip; |
486 transform.mapRect(&translatedClip, clipEntry->getRect()); | 486 transform.mapRect(&translatedClip, clipEntry->getRect()); |
487 emit_clip(NULL, &translatedClip, fContentStream); | 487 emit_clip(nullptr, &translatedClip, fContentStream); |
488 break; | 488 break; |
489 } | 489 } |
490 default: { | 490 default: { |
491 SkPath translatedPath; | 491 SkPath translatedPath; |
492 clipEntry->asPath(&translatedPath); | 492 clipEntry->asPath(&translatedPath); |
493 translatedPath.transform(transform, &translatedPath); | 493 translatedPath.transform(transform, &translatedPath); |
494 emit_clip(&translatedPath, NULL, fContentStream); | 494 emit_clip(&translatedPath, nullptr, fContentStream); |
495 break; | 495 break; |
496 } | 496 } |
497 } | 497 } |
498 } | 498 } |
499 } | 499 } |
500 } | 500 } |
501 | 501 |
502 void GraphicStackState::updateMatrix(const SkMatrix& matrix) { | 502 void GraphicStackState::updateMatrix(const SkMatrix& matrix) { |
503 if (matrix == currentEntry()->fMatrix) { | 503 if (matrix == currentEntry()->fMatrix) { |
504 return; | 504 return; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 } | 565 } |
566 | 566 |
567 static bool not_supported_for_layers(const SkPaint& layerPaint) { | 567 static bool not_supported_for_layers(const SkPaint& layerPaint) { |
568 // PDF does not support image filters, so render them on CPU. | 568 // PDF does not support image filters, so render them on CPU. |
569 // Note that this rendering is done at "screen" resolution (100dpi), not | 569 // Note that this rendering is done at "screen" resolution (100dpi), not |
570 // printer resolution. | 570 // printer resolution. |
571 // FIXME: It may be possible to express some filters natively using PDF | 571 // FIXME: It may be possible to express some filters natively using PDF |
572 // to improve quality and file size (http://skbug.com/3043) | 572 // to improve quality and file size (http://skbug.com/3043) |
573 | 573 |
574 // TODO: should we return true if there is a colorfilter? | 574 // TODO: should we return true if there is a colorfilter? |
575 return layerPaint.getImageFilter() != NULL; | 575 return layerPaint.getImageFilter() != nullptr; |
576 } | 576 } |
577 | 577 |
578 SkBaseDevice* SkPDFDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint
* layerPaint) { | 578 SkBaseDevice* SkPDFDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint
* layerPaint) { |
579 if (cinfo.fForImageFilter || | 579 if (cinfo.fForImageFilter || |
580 (layerPaint && not_supported_for_layers(*layerPaint))) { | 580 (layerPaint && not_supported_for_layers(*layerPaint))) { |
581 return NULL; | 581 return nullptr; |
582 } | 582 } |
583 SkISize size = SkISize::Make(cinfo.fInfo.width(), cinfo.fInfo.height()); | 583 SkISize size = SkISize::Make(cinfo.fInfo.width(), cinfo.fInfo.height()); |
584 return SkPDFDevice::Create(size, fRasterDpi, fCanon); | 584 return SkPDFDevice::Create(size, fRasterDpi, fCanon); |
585 } | 585 } |
586 | 586 |
587 | 587 |
588 struct ContentEntry { | 588 struct ContentEntry { |
589 GraphicStateEntry fState; | 589 GraphicStateEntry fState; |
590 SkDynamicMemoryWStream fContent; | 590 SkDynamicMemoryWStream fContent; |
591 SkAutoTDelete<ContentEntry> fNext; | 591 SkAutoTDelete<ContentEntry> fNext; |
592 | 592 |
593 // If the stack is too deep we could get Stack Overflow. | 593 // If the stack is too deep we could get Stack Overflow. |
594 // So we manually destruct the object. | 594 // So we manually destruct the object. |
595 ~ContentEntry() { | 595 ~ContentEntry() { |
596 ContentEntry* val = fNext.detach(); | 596 ContentEntry* val = fNext.detach(); |
597 while (val != NULL) { | 597 while (val != nullptr) { |
598 ContentEntry* valNext = val->fNext.detach(); | 598 ContentEntry* valNext = val->fNext.detach(); |
599 // When the destructor is called, fNext is NULL and exits. | 599 // When the destructor is called, fNext is nullptr and exits. |
600 delete val; | 600 delete val; |
601 val = valNext; | 601 val = valNext; |
602 } | 602 } |
603 } | 603 } |
604 }; | 604 }; |
605 | 605 |
606 // A helper class to automatically finish a ContentEntry at the end of a | 606 // A helper class to automatically finish a ContentEntry at the end of a |
607 // drawing method and maintain the state needed between set up and finish. | 607 // drawing method and maintain the state needed between set up and finish. |
608 class ScopedContentEntry { | 608 class ScopedContentEntry { |
609 public: | 609 public: |
610 ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw, | 610 ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw, |
611 const SkPaint& paint, bool hasText = false) | 611 const SkPaint& paint, bool hasText = false) |
612 : fDevice(device), | 612 : fDevice(device), |
613 fContentEntry(NULL), | 613 fContentEntry(nullptr), |
614 fXfermode(SkXfermode::kSrcOver_Mode), | 614 fXfermode(SkXfermode::kSrcOver_Mode), |
615 fDstFormXObject(NULL) { | 615 fDstFormXObject(nullptr) { |
616 init(draw.fClipStack, *draw.fClip, *draw.fMatrix, paint, hasText); | 616 init(draw.fClipStack, *draw.fClip, *draw.fMatrix, paint, hasText); |
617 } | 617 } |
618 ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack, | 618 ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack, |
619 const SkRegion& clipRegion, const SkMatrix& matrix, | 619 const SkRegion& clipRegion, const SkMatrix& matrix, |
620 const SkPaint& paint, bool hasText = false) | 620 const SkPaint& paint, bool hasText = false) |
621 : fDevice(device), | 621 : fDevice(device), |
622 fContentEntry(NULL), | 622 fContentEntry(nullptr), |
623 fXfermode(SkXfermode::kSrcOver_Mode), | 623 fXfermode(SkXfermode::kSrcOver_Mode), |
624 fDstFormXObject(NULL) { | 624 fDstFormXObject(nullptr) { |
625 init(clipStack, clipRegion, matrix, paint, hasText); | 625 init(clipStack, clipRegion, matrix, paint, hasText); |
626 } | 626 } |
627 | 627 |
628 ~ScopedContentEntry() { | 628 ~ScopedContentEntry() { |
629 if (fContentEntry) { | 629 if (fContentEntry) { |
630 SkPath* shape = &fShape; | 630 SkPath* shape = &fShape; |
631 if (shape->isEmpty()) { | 631 if (shape->isEmpty()) { |
632 shape = NULL; | 632 shape = nullptr; |
633 } | 633 } |
634 fDevice->finishContentEntry(fXfermode, fDstFormXObject, shape); | 634 fDevice->finishContentEntry(fXfermode, fDstFormXObject, shape); |
635 } | 635 } |
636 SkSafeUnref(fDstFormXObject); | 636 SkSafeUnref(fDstFormXObject); |
637 } | 637 } |
638 | 638 |
639 ContentEntry* entry() { return fContentEntry; } | 639 ContentEntry* entry() { return fContentEntry; } |
640 | 640 |
641 /* Returns true when we explicitly need the shape of the drawing. */ | 641 /* Returns true when we explicitly need the shape of the drawing. */ |
642 bool needShape() { | 642 bool needShape() { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
695 } | 695 } |
696 }; | 696 }; |
697 | 697 |
698 //////////////////////////////////////////////////////////////////////////////// | 698 //////////////////////////////////////////////////////////////////////////////// |
699 | 699 |
700 SkPDFDevice::SkPDFDevice(SkISize pageSize, SkScalar rasterDpi, SkPDFCanon* canon
, bool flip) | 700 SkPDFDevice::SkPDFDevice(SkISize pageSize, SkScalar rasterDpi, SkPDFCanon* canon
, bool flip) |
701 : INHERITED(SkSurfaceProps(0, kUnknown_SkPixelGeometry)) | 701 : INHERITED(SkSurfaceProps(0, kUnknown_SkPixelGeometry)) |
702 , fPageSize(pageSize) | 702 , fPageSize(pageSize) |
703 , fContentSize(pageSize) | 703 , fContentSize(pageSize) |
704 , fExistingClipRegion(SkIRect::MakeSize(pageSize)) | 704 , fExistingClipRegion(SkIRect::MakeSize(pageSize)) |
705 , fAnnotations(NULL) | 705 , fAnnotations(nullptr) |
706 , fLastContentEntry(NULL) | 706 , fLastContentEntry(nullptr) |
707 , fLastMarginContentEntry(NULL) | 707 , fLastMarginContentEntry(nullptr) |
708 , fDrawingArea(kContent_DrawingArea) | 708 , fDrawingArea(kContent_DrawingArea) |
709 , fClipStack(NULL) | 709 , fClipStack(nullptr) |
710 , fFontGlyphUsage(new SkPDFGlyphSetMap) | 710 , fFontGlyphUsage(new SkPDFGlyphSetMap) |
711 , fRasterDpi(rasterDpi) | 711 , fRasterDpi(rasterDpi) |
712 , fCanon(canon) { | 712 , fCanon(canon) { |
713 SkASSERT(pageSize.width() > 0); | 713 SkASSERT(pageSize.width() > 0); |
714 SkASSERT(pageSize.height() > 0); | 714 SkASSERT(pageSize.height() > 0); |
715 fLegacyBitmap.setInfo( | 715 fLegacyBitmap.setInfo( |
716 SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height())); | 716 SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height())); |
717 if (flip) { | 717 if (flip) { |
718 // Skia generally uses the top left as the origin but PDF | 718 // Skia generally uses the top left as the origin but PDF |
719 // natively has the origin at the bottom left. This matrix | 719 // natively has the origin at the bottom left. This matrix |
720 // corrects for that. But that only needs to be done once, we | 720 // corrects for that. But that only needs to be done once, we |
721 // don't do it when layering. | 721 // don't do it when layering. |
722 fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight)); | 722 fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight)); |
723 fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1); | 723 fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1); |
724 } else { | 724 } else { |
725 fInitialTransform.setIdentity(); | 725 fInitialTransform.setIdentity(); |
726 } | 726 } |
727 } | 727 } |
728 | 728 |
729 SkPDFDevice::~SkPDFDevice() { | 729 SkPDFDevice::~SkPDFDevice() { |
730 this->cleanUp(true); | 730 this->cleanUp(true); |
731 } | 731 } |
732 | 732 |
733 void SkPDFDevice::init() { | 733 void SkPDFDevice::init() { |
734 fAnnotations = NULL; | 734 fAnnotations = nullptr; |
735 fContentEntries.free(); | 735 fContentEntries.free(); |
736 fLastContentEntry = NULL; | 736 fLastContentEntry = nullptr; |
737 fMarginContentEntries.free(); | 737 fMarginContentEntries.free(); |
738 fLastMarginContentEntry = NULL; | 738 fLastMarginContentEntry = nullptr; |
739 fDrawingArea = kContent_DrawingArea; | 739 fDrawingArea = kContent_DrawingArea; |
740 if (fFontGlyphUsage.get() == NULL) { | 740 if (fFontGlyphUsage.get() == nullptr) { |
741 fFontGlyphUsage.reset(new SkPDFGlyphSetMap); | 741 fFontGlyphUsage.reset(new SkPDFGlyphSetMap); |
742 } | 742 } |
743 } | 743 } |
744 | 744 |
745 void SkPDFDevice::cleanUp(bool clearFontUsage) { | 745 void SkPDFDevice::cleanUp(bool clearFontUsage) { |
746 fGraphicStateResources.unrefAll(); | 746 fGraphicStateResources.unrefAll(); |
747 fXObjectResources.unrefAll(); | 747 fXObjectResources.unrefAll(); |
748 fFontResources.unrefAll(); | 748 fFontResources.unrefAll(); |
749 fShaderResources.unrefAll(); | 749 fShaderResources.unrefAll(); |
750 SkSafeUnref(fAnnotations); | 750 SkSafeUnref(fAnnotations); |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 SkASSERT(annotation); | 939 SkASSERT(annotation); |
940 SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key()); | 940 SkData* urlData = annotation->find(SkAnnotationKeys::URL_Key()); |
941 if (urlData) { | 941 if (urlData) { |
942 return create_link_to_url(urlData, r); | 942 return create_link_to_url(urlData, r); |
943 } | 943 } |
944 SkData* linkToName = | 944 SkData* linkToName = |
945 annotation->find(SkAnnotationKeys::Link_Named_Dest_Key()); | 945 annotation->find(SkAnnotationKeys::Link_Named_Dest_Key()); |
946 if (linkToName) { | 946 if (linkToName) { |
947 return create_link_named_dest(linkToName, r); | 947 return create_link_named_dest(linkToName, r); |
948 } | 948 } |
949 return NULL; | 949 return nullptr; |
950 } | 950 } |
951 | 951 |
952 void SkPDFDevice::drawRect(const SkDraw& d, | 952 void SkPDFDevice::drawRect(const SkDraw& d, |
953 const SkRect& rect, | 953 const SkRect& rect, |
954 const SkPaint& srcPaint) { | 954 const SkPaint& srcPaint) { |
955 SkPaint paint = srcPaint; | 955 SkPaint paint = srcPaint; |
956 replace_srcmode_on_opaque_paint(&paint); | 956 replace_srcmode_on_opaque_paint(&paint); |
957 SkRect r = rect; | 957 SkRect r = rect; |
958 r.sort(); | 958 r.sort(); |
959 | 959 |
960 if (paint.getPathEffect()) { | 960 if (paint.getPathEffect()) { |
961 if (d.fClip->isEmpty()) { | 961 if (d.fClip->isEmpty()) { |
962 return; | 962 return; |
963 } | 963 } |
964 SkPath path; | 964 SkPath path; |
965 path.addRect(r); | 965 path.addRect(r); |
966 drawPath(d, path, paint, NULL, true); | 966 drawPath(d, path, paint, nullptr, true); |
967 return; | 967 return; |
968 } | 968 } |
969 | 969 |
970 if (SkAnnotation* annotation = paint.getAnnotation()) { | 970 if (SkAnnotation* annotation = paint.getAnnotation()) { |
971 SkPath path; | 971 SkPath path; |
972 path.addRect(rect); | 972 path.addRect(rect); |
973 SkRect transformedRect = | 973 SkRect transformedRect = |
974 transform_and_clip_path(d, path, fInitialTransform).getBounds(); | 974 transform_and_clip_path(d, path, fInitialTransform).getBounds(); |
975 SkAutoTUnref<SkPDFDict> annot( | 975 SkAutoTUnref<SkPDFDict> annot( |
976 create_rect_annotation(transformedRect, annotation)); | 976 create_rect_annotation(transformedRect, annotation)); |
(...skipping 12 matching lines...) Expand all Loading... |
989 &content.entry()->fContent); | 989 &content.entry()->fContent); |
990 } | 990 } |
991 | 991 |
992 void SkPDFDevice::drawRRect(const SkDraw& draw, | 992 void SkPDFDevice::drawRRect(const SkDraw& draw, |
993 const SkRRect& rrect, | 993 const SkRRect& rrect, |
994 const SkPaint& srcPaint) { | 994 const SkPaint& srcPaint) { |
995 SkPaint paint = srcPaint; | 995 SkPaint paint = srcPaint; |
996 replace_srcmode_on_opaque_paint(&paint); | 996 replace_srcmode_on_opaque_paint(&paint); |
997 SkPath path; | 997 SkPath path; |
998 path.addRRect(rrect); | 998 path.addRRect(rrect); |
999 this->drawPath(draw, path, paint, NULL, true); | 999 this->drawPath(draw, path, paint, nullptr, true); |
1000 } | 1000 } |
1001 | 1001 |
1002 void SkPDFDevice::drawOval(const SkDraw& draw, | 1002 void SkPDFDevice::drawOval(const SkDraw& draw, |
1003 const SkRect& oval, | 1003 const SkRect& oval, |
1004 const SkPaint& srcPaint) { | 1004 const SkPaint& srcPaint) { |
1005 SkPaint paint = srcPaint; | 1005 SkPaint paint = srcPaint; |
1006 replace_srcmode_on_opaque_paint(&paint); | 1006 replace_srcmode_on_opaque_paint(&paint); |
1007 SkPath path; | 1007 SkPath path; |
1008 path.addOval(oval); | 1008 path.addOval(oval); |
1009 this->drawPath(draw, path, paint, NULL, true); | 1009 this->drawPath(draw, path, paint, nullptr, true); |
1010 } | 1010 } |
1011 | 1011 |
1012 void SkPDFDevice::drawPath(const SkDraw& d, | 1012 void SkPDFDevice::drawPath(const SkDraw& d, |
1013 const SkPath& origPath, | 1013 const SkPath& origPath, |
1014 const SkPaint& srcPaint, | 1014 const SkPaint& srcPaint, |
1015 const SkMatrix* prePathMatrix, | 1015 const SkMatrix* prePathMatrix, |
1016 bool pathIsMutable) { | 1016 bool pathIsMutable) { |
1017 SkPaint paint = srcPaint; | 1017 SkPaint paint = srcPaint; |
1018 replace_srcmode_on_opaque_paint(&paint); | 1018 replace_srcmode_on_opaque_paint(&paint); |
1019 SkPath modifiedPath; | 1019 SkPath modifiedPath; |
(...skipping 16 matching lines...) Expand all Loading... |
1036 if (d.fClip->isEmpty()) { | 1036 if (d.fClip->isEmpty()) { |
1037 return; | 1037 return; |
1038 } | 1038 } |
1039 if (!pathIsMutable) { | 1039 if (!pathIsMutable) { |
1040 pathPtr = &modifiedPath; | 1040 pathPtr = &modifiedPath; |
1041 pathIsMutable = true; | 1041 pathIsMutable = true; |
1042 } | 1042 } |
1043 bool fill = paint.getFillPath(origPath, pathPtr); | 1043 bool fill = paint.getFillPath(origPath, pathPtr); |
1044 | 1044 |
1045 SkPaint noEffectPaint(paint); | 1045 SkPaint noEffectPaint(paint); |
1046 noEffectPaint.setPathEffect(NULL); | 1046 noEffectPaint.setPathEffect(nullptr); |
1047 if (fill) { | 1047 if (fill) { |
1048 noEffectPaint.setStyle(SkPaint::kFill_Style); | 1048 noEffectPaint.setStyle(SkPaint::kFill_Style); |
1049 } else { | 1049 } else { |
1050 noEffectPaint.setStyle(SkPaint::kStroke_Style); | 1050 noEffectPaint.setStyle(SkPaint::kStroke_Style); |
1051 noEffectPaint.setStrokeWidth(0); | 1051 noEffectPaint.setStrokeWidth(0); |
1052 } | 1052 } |
1053 drawPath(d, *pathPtr, noEffectPaint, NULL, true); | 1053 drawPath(d, *pathPtr, noEffectPaint, nullptr, true); |
1054 return; | 1054 return; |
1055 } | 1055 } |
1056 | 1056 |
1057 if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) { | 1057 if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) { |
1058 return; | 1058 return; |
1059 } | 1059 } |
1060 | 1060 |
1061 if (SkAnnotation* annotation = paint.getAnnotation()) { | 1061 if (SkAnnotation* annotation = paint.getAnnotation()) { |
1062 SkRect transformedRect = | 1062 SkRect transformedRect = |
1063 transform_and_clip_path(d, *pathPtr, fInitialTransform) | 1063 transform_and_clip_path(d, *pathPtr, fInitialTransform) |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1147 if (bitmap.isOpaque()) { | 1147 if (bitmap.isOpaque()) { |
1148 replace_srcmode_on_opaque_paint(&paint); | 1148 replace_srcmode_on_opaque_paint(&paint); |
1149 } | 1149 } |
1150 | 1150 |
1151 if (d.fClip->isEmpty()) { | 1151 if (d.fClip->isEmpty()) { |
1152 return; | 1152 return; |
1153 } | 1153 } |
1154 | 1154 |
1155 SkMatrix transform = matrix; | 1155 SkMatrix transform = matrix; |
1156 transform.postConcat(*d.fMatrix); | 1156 transform.postConcat(*d.fMatrix); |
1157 this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, NULL, | 1157 this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, nullptr, |
1158 paint); | 1158 paint); |
1159 } | 1159 } |
1160 | 1160 |
1161 void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap, | 1161 void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap, |
1162 int x, int y, const SkPaint& srcPaint) { | 1162 int x, int y, const SkPaint& srcPaint) { |
1163 SkPaint paint = srcPaint; | 1163 SkPaint paint = srcPaint; |
1164 if (bitmap.isOpaque()) { | 1164 if (bitmap.isOpaque()) { |
1165 replace_srcmode_on_opaque_paint(&paint); | 1165 replace_srcmode_on_opaque_paint(&paint); |
1166 } | 1166 } |
1167 | 1167 |
1168 if (d.fClip->isEmpty()) { | 1168 if (d.fClip->isEmpty()) { |
1169 return; | 1169 return; |
1170 } | 1170 } |
1171 | 1171 |
1172 SkMatrix matrix; | 1172 SkMatrix matrix; |
1173 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); | 1173 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); |
1174 this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL, | 1174 this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, nullptr, |
1175 paint); | 1175 paint); |
1176 } | 1176 } |
1177 | 1177 |
1178 // Create a PDF string. Maximum length (in bytes) is 65,535. | 1178 // Create a PDF string. Maximum length (in bytes) is 65,535. |
1179 // @param input A string value. | 1179 // @param input A string value. |
1180 // @param len The length of the input array. | 1180 // @param len The length of the input array. |
1181 // @param wideChars True iff the upper byte in each uint16_t is | 1181 // @param wideChars True iff the upper byte in each uint16_t is |
1182 // significant and should be encoded and not | 1182 // significant and should be encoded and not |
1183 // discarded. If true, the upper byte is encoded | 1183 // discarded. If true, the upper byte is encoded |
1184 // first. Otherwise, we assert the upper byte is | 1184 // first. Otherwise, we assert the upper byte is |
(...skipping 23 matching lines...) Expand all Loading... |
1208 } | 1208 } |
1209 return SkPDFUtils::FormatString(tmp.c_str(), tmp.size()); | 1209 return SkPDFUtils::FormatString(tmp.c_str(), tmp.size()); |
1210 } | 1210 } |
1211 } | 1211 } |
1212 | 1212 |
1213 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, | 1213 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, |
1214 SkScalar x, SkScalar y, const SkPaint& srcPaint) { | 1214 SkScalar x, SkScalar y, const SkPaint& srcPaint) { |
1215 SkPaint paint = srcPaint; | 1215 SkPaint paint = srcPaint; |
1216 replace_srcmode_on_opaque_paint(&paint); | 1216 replace_srcmode_on_opaque_paint(&paint); |
1217 | 1217 |
1218 NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false); | 1218 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false); |
1219 if (paint.getMaskFilter() != NULL) { | 1219 if (paint.getMaskFilter() != nullptr) { |
1220 // Don't pretend we support drawing MaskFilters, it makes for artifacts | 1220 // Don't pretend we support drawing MaskFilters, it makes for artifacts |
1221 // making text unreadable (e.g. same text twice when using CSS shadows). | 1221 // making text unreadable (e.g. same text twice when using CSS shadows). |
1222 return; | 1222 return; |
1223 } | 1223 } |
1224 SkPaint textPaint = calculate_text_paint(paint); | 1224 SkPaint textPaint = calculate_text_paint(paint); |
1225 ScopedContentEntry content(this, d, textPaint, true); | 1225 ScopedContentEntry content(this, d, textPaint, true); |
1226 if (!content.entry()) { | 1226 if (!content.entry()) { |
1227 return; | 1227 return; |
1228 } | 1228 } |
1229 | 1229 |
1230 SkGlyphStorage storage(0); | 1230 SkGlyphStorage storage(0); |
1231 const uint16_t* glyphIDs = NULL; | 1231 const uint16_t* glyphIDs = nullptr; |
1232 int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs); | 1232 int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs); |
1233 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 1233 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
1234 | 1234 |
1235 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); | 1235 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); |
1236 align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y); | 1236 align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y); |
1237 content.entry()->fContent.writeText("BT\n"); | 1237 content.entry()->fContent.writeText("BT\n"); |
1238 set_text_transform(x, y, textPaint.getTextSkewX(), | 1238 set_text_transform(x, y, textPaint.getTextSkewX(), |
1239 &content.entry()->fContent); | 1239 &content.entry()->fContent); |
1240 int consumedGlyphCount = 0; | 1240 int consumedGlyphCount = 0; |
1241 | 1241 |
(...skipping 18 matching lines...) Expand all Loading... |
1260 } | 1260 } |
1261 content.entry()->fContent.writeText("ET\n"); | 1261 content.entry()->fContent.writeText("ET\n"); |
1262 } | 1262 } |
1263 | 1263 |
1264 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, | 1264 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, |
1265 const SkScalar pos[], int scalarsPerPos, | 1265 const SkScalar pos[], int scalarsPerPos, |
1266 const SkPoint& offset, const SkPaint& srcPaint) { | 1266 const SkPoint& offset, const SkPaint& srcPaint) { |
1267 SkPaint paint = srcPaint; | 1267 SkPaint paint = srcPaint; |
1268 replace_srcmode_on_opaque_paint(&paint); | 1268 replace_srcmode_on_opaque_paint(&paint); |
1269 | 1269 |
1270 NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false); | 1270 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false); |
1271 if (paint.getMaskFilter() != NULL) { | 1271 if (paint.getMaskFilter() != nullptr) { |
1272 // Don't pretend we support drawing MaskFilters, it makes for artifacts | 1272 // Don't pretend we support drawing MaskFilters, it makes for artifacts |
1273 // making text unreadable (e.g. same text twice when using CSS shadows). | 1273 // making text unreadable (e.g. same text twice when using CSS shadows). |
1274 return; | 1274 return; |
1275 } | 1275 } |
1276 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); | 1276 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); |
1277 SkPaint textPaint = calculate_text_paint(paint); | 1277 SkPaint textPaint = calculate_text_paint(paint); |
1278 ScopedContentEntry content(this, d, textPaint, true); | 1278 ScopedContentEntry content(this, d, textPaint, true); |
1279 if (!content.entry()) { | 1279 if (!content.entry()) { |
1280 return; | 1280 return; |
1281 } | 1281 } |
1282 | 1282 |
1283 SkGlyphStorage storage(0); | 1283 SkGlyphStorage storage(0); |
1284 const uint16_t* glyphIDs = NULL; | 1284 const uint16_t* glyphIDs = nullptr; |
1285 size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphID
s); | 1285 size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphID
s); |
1286 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 1286 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
1287 | 1287 |
1288 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); | 1288 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); |
1289 content.entry()->fContent.writeText("BT\n"); | 1289 content.entry()->fContent.writeText("BT\n"); |
1290 this->updateFont(textPaint, glyphIDs[0], content.entry()); | 1290 this->updateFont(textPaint, glyphIDs[0], content.entry()); |
1291 for (size_t i = 0; i < numGlyphs; i++) { | 1291 for (size_t i = 0; i < numGlyphs; i++) { |
1292 SkPDFFont* font = content.entry()->fState.fFont; | 1292 SkPDFFont* font = content.entry()->fState.fFont; |
1293 uint16_t encodedValue = glyphIDs[i]; | 1293 uint16_t encodedValue = glyphIDs[i]; |
1294 if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { | 1294 if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1367 void SkPDFDevice::onAttachToCanvas(SkCanvas* canvas) { | 1367 void SkPDFDevice::onAttachToCanvas(SkCanvas* canvas) { |
1368 INHERITED::onAttachToCanvas(canvas); | 1368 INHERITED::onAttachToCanvas(canvas); |
1369 | 1369 |
1370 // Canvas promises that this ptr is valid until onDetachFromCanvas is called | 1370 // Canvas promises that this ptr is valid until onDetachFromCanvas is called |
1371 fClipStack = canvas->getClipStack(); | 1371 fClipStack = canvas->getClipStack(); |
1372 } | 1372 } |
1373 | 1373 |
1374 void SkPDFDevice::onDetachFromCanvas() { | 1374 void SkPDFDevice::onDetachFromCanvas() { |
1375 INHERITED::onDetachFromCanvas(); | 1375 INHERITED::onDetachFromCanvas(); |
1376 | 1376 |
1377 fClipStack = NULL; | 1377 fClipStack = nullptr; |
1378 } | 1378 } |
1379 | 1379 |
1380 SkSurface* SkPDFDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps
& props) { | 1380 SkSurface* SkPDFDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps
& props) { |
1381 return SkSurface::NewRaster(info, &props); | 1381 return SkSurface::NewRaster(info, &props); |
1382 } | 1382 } |
1383 | 1383 |
1384 ContentEntry* SkPDFDevice::getLastContentEntry() { | 1384 ContentEntry* SkPDFDevice::getLastContentEntry() { |
1385 if (fDrawingArea == kContent_DrawingArea) { | 1385 if (fDrawingArea == kContent_DrawingArea) { |
1386 return fLastContentEntry; | 1386 return fLastContentEntry; |
1387 } else { | 1387 } else { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1444 SkDynamicMemoryWStream buffer; | 1444 SkDynamicMemoryWStream buffer; |
1445 this->writeContent(&buffer); | 1445 this->writeContent(&buffer); |
1446 return buffer.detachAsStream(); | 1446 return buffer.detachAsStream(); |
1447 } | 1447 } |
1448 | 1448 |
1449 void SkPDFDevice::copyContentEntriesToData(ContentEntry* entry, | 1449 void SkPDFDevice::copyContentEntriesToData(ContentEntry* entry, |
1450 SkWStream* data) const { | 1450 SkWStream* data) const { |
1451 // TODO(ctguil): For margins, I'm not sure fExistingClipStack/Region is the | 1451 // TODO(ctguil): For margins, I'm not sure fExistingClipStack/Region is the |
1452 // right thing to pass here. | 1452 // right thing to pass here. |
1453 GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, data); | 1453 GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, data); |
1454 while (entry != NULL) { | 1454 while (entry != nullptr) { |
1455 SkPoint translation; | 1455 SkPoint translation; |
1456 translation.iset(this->getOrigin()); | 1456 translation.iset(this->getOrigin()); |
1457 translation.negate(); | 1457 translation.negate(); |
1458 gsState.updateClip(entry->fState.fClipStack, entry->fState.fClipRegion, | 1458 gsState.updateClip(entry->fState.fClipStack, entry->fState.fClipRegion, |
1459 translation); | 1459 translation); |
1460 gsState.updateMatrix(entry->fState.fMatrix); | 1460 gsState.updateMatrix(entry->fState.fMatrix); |
1461 gsState.updateDrawingState(entry->fState); | 1461 gsState.updateDrawingState(entry->fState); |
1462 | 1462 |
1463 entry->fContent.writeToStream(data); | 1463 entry->fContent.writeToStream(data); |
1464 entry = entry->fNext.get(); | 1464 entry = entry->fNext.get(); |
(...skipping 13 matching lines...) Expand all Loading... |
1478 // sent across account for that) | 1478 // sent across account for that) |
1479 SkPDFDevice::copyContentEntriesToData(fMarginContentEntries.get(), out); | 1479 SkPDFDevice::copyContentEntriesToData(fMarginContentEntries.get(), out); |
1480 | 1480 |
1481 // If the content area is the entire page, then we don't need to clip | 1481 // If the content area is the entire page, then we don't need to clip |
1482 // the content area (PDF area clips to the page size). Otherwise, | 1482 // the content area (PDF area clips to the page size). Otherwise, |
1483 // we have to clip to the content area; we've already applied the | 1483 // we have to clip to the content area; we've already applied the |
1484 // initial transform, so just clip to the device size. | 1484 // initial transform, so just clip to the device size. |
1485 if (fPageSize != fContentSize) { | 1485 if (fPageSize != fContentSize) { |
1486 SkRect r = SkRect::MakeWH(SkIntToScalar(this->width()), | 1486 SkRect r = SkRect::MakeWH(SkIntToScalar(this->width()), |
1487 SkIntToScalar(this->height())); | 1487 SkIntToScalar(this->height())); |
1488 emit_clip(NULL, &r, out); | 1488 emit_clip(nullptr, &r, out); |
1489 } | 1489 } |
1490 | 1490 |
1491 SkPDFDevice::copyContentEntriesToData(fContentEntries.get(), out); | 1491 SkPDFDevice::copyContentEntriesToData(fContentEntries.get(), out); |
1492 } | 1492 } |
1493 | 1493 |
1494 /* Draws an inverse filled path by using Path Ops to compute the positive | 1494 /* Draws an inverse filled path by using Path Ops to compute the positive |
1495 * inverse using the current clip as the inverse bounds. | 1495 * inverse using the current clip as the inverse bounds. |
1496 * Return true if this was an inverse path and was properly handled, | 1496 * Return true if this was an inverse path and was properly handled, |
1497 * otherwise returns false and the normal drawing routine should continue, | 1497 * otherwise returns false and the normal drawing routine should continue, |
1498 * either as a (incorrect) fallback or because the path was not inverse | 1498 * either as a (incorrect) fallback or because the path was not inverse |
(...skipping 19 matching lines...) Expand all Loading... |
1518 SkPaint::kStrokeAndFill_Style == paint.getStyle()) { | 1518 SkPaint::kStrokeAndFill_Style == paint.getStyle()) { |
1519 bool doFillPath = paint.getFillPath(origPath, &modifiedPath); | 1519 bool doFillPath = paint.getFillPath(origPath, &modifiedPath); |
1520 if (doFillPath) { | 1520 if (doFillPath) { |
1521 noInversePaint.setStyle(SkPaint::kFill_Style); | 1521 noInversePaint.setStyle(SkPaint::kFill_Style); |
1522 noInversePaint.setStrokeWidth(0); | 1522 noInversePaint.setStrokeWidth(0); |
1523 pathPtr = &modifiedPath; | 1523 pathPtr = &modifiedPath; |
1524 } else { | 1524 } else { |
1525 // To be consistent with the raster output, hairline strokes | 1525 // To be consistent with the raster output, hairline strokes |
1526 // are rendered as non-inverted. | 1526 // are rendered as non-inverted. |
1527 modifiedPath.toggleInverseFillType(); | 1527 modifiedPath.toggleInverseFillType(); |
1528 drawPath(d, modifiedPath, paint, NULL, true); | 1528 drawPath(d, modifiedPath, paint, nullptr, true); |
1529 return true; | 1529 return true; |
1530 } | 1530 } |
1531 } | 1531 } |
1532 | 1532 |
1533 // Get bounds of clip in current transform space | 1533 // Get bounds of clip in current transform space |
1534 // (clip bounds are given in device space). | 1534 // (clip bounds are given in device space). |
1535 SkRect bounds; | 1535 SkRect bounds; |
1536 SkMatrix transformInverse; | 1536 SkMatrix transformInverse; |
1537 SkMatrix totalMatrix = *d.fMatrix; | 1537 SkMatrix totalMatrix = *d.fMatrix; |
1538 if (prePathMatrix) { | 1538 if (prePathMatrix) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1577 SkPoint translatedPoint; | 1577 SkPoint translatedPoint; |
1578 transform.mapXY(points[i].x(), points[i].y(), &translatedPoint); | 1578 transform.mapXY(points[i].x(), points[i].y(), &translatedPoint); |
1579 fNamedDestinations.push(new NamedDestination(nameData, translatedPoi
nt)); | 1579 fNamedDestinations.push(new NamedDestination(nameData, translatedPoi
nt)); |
1580 } | 1580 } |
1581 return true; | 1581 return true; |
1582 } | 1582 } |
1583 return false; | 1583 return false; |
1584 } | 1584 } |
1585 | 1585 |
1586 void SkPDFDevice::addAnnotation(SkPDFDict* annotation) { | 1586 void SkPDFDevice::addAnnotation(SkPDFDict* annotation) { |
1587 if (NULL == fAnnotations) { | 1587 if (nullptr == fAnnotations) { |
1588 fAnnotations = new SkPDFArray; | 1588 fAnnotations = new SkPDFArray; |
1589 } | 1589 } |
1590 fAnnotations->appendObject(annotation); | 1590 fAnnotations->appendObject(annotation); |
1591 } | 1591 } |
1592 | 1592 |
1593 | 1593 |
1594 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { | 1594 void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) const { |
1595 int nDest = fNamedDestinations.count(); | 1595 int nDest = fNamedDestinations.count(); |
1596 for (int i = 0; i < nDest; i++) { | 1596 for (int i = 0; i < nDest; i++) { |
1597 NamedDestination* dest = fNamedDestinations[i]; | 1597 NamedDestination* dest = fNamedDestinations[i]; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1646 SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), | 1646 SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), |
1647 &content.entry()->fContent); | 1647 &content.entry()->fContent); |
1648 } | 1648 } |
1649 | 1649 |
1650 ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack, | 1650 ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack, |
1651 const SkRegion& clipRegion, | 1651 const SkRegion& clipRegion, |
1652 const SkMatrix& matrix, | 1652 const SkMatrix& matrix, |
1653 const SkPaint& paint, | 1653 const SkPaint& paint, |
1654 bool hasText, | 1654 bool hasText, |
1655 SkPDFFormXObject** dst) { | 1655 SkPDFFormXObject** dst) { |
1656 *dst = NULL; | 1656 *dst = nullptr; |
1657 if (clipRegion.isEmpty()) { | 1657 if (clipRegion.isEmpty()) { |
1658 return NULL; | 1658 return nullptr; |
1659 } | 1659 } |
1660 | 1660 |
1661 // The clip stack can come from an SkDraw where it is technically optional. | 1661 // The clip stack can come from an SkDraw where it is technically optional. |
1662 SkClipStack synthesizedClipStack; | 1662 SkClipStack synthesizedClipStack; |
1663 if (clipStack == NULL) { | 1663 if (clipStack == nullptr) { |
1664 if (clipRegion == fExistingClipRegion) { | 1664 if (clipRegion == fExistingClipRegion) { |
1665 clipStack = &fExistingClipStack; | 1665 clipStack = &fExistingClipStack; |
1666 } else { | 1666 } else { |
1667 // GraphicStackState::updateClip expects the clip stack to have | 1667 // GraphicStackState::updateClip expects the clip stack to have |
1668 // fExistingClip as a prefix, so start there, then set the clip | 1668 // fExistingClip as a prefix, so start there, then set the clip |
1669 // to the passed region. | 1669 // to the passed region. |
1670 synthesizedClipStack = fExistingClipStack; | 1670 synthesizedClipStack = fExistingClipStack; |
1671 SkPath clipPath; | 1671 SkPath clipPath; |
1672 clipRegion.getBoundaryPath(&clipPath); | 1672 clipRegion.getBoundaryPath(&clipPath); |
1673 synthesizedClipStack.clipDevPath(clipPath, SkRegion::kReplace_Op, | 1673 synthesizedClipStack.clipDevPath(clipPath, SkRegion::kReplace_Op, |
(...skipping 18 matching lines...) Expand all Loading... |
1692 xfermode == SkXfermode::kSrcATop_Mode || | 1692 xfermode == SkXfermode::kSrcATop_Mode || |
1693 xfermode == SkXfermode::kDstATop_Mode || | 1693 xfermode == SkXfermode::kDstATop_Mode || |
1694 xfermode == SkXfermode::kModulate_Mode) { | 1694 xfermode == SkXfermode::kModulate_Mode) { |
1695 if (!isContentEmpty()) { | 1695 if (!isContentEmpty()) { |
1696 *dst = createFormXObjectFromDevice(); | 1696 *dst = createFormXObjectFromDevice(); |
1697 SkASSERT(isContentEmpty()); | 1697 SkASSERT(isContentEmpty()); |
1698 } else if (xfermode != SkXfermode::kSrc_Mode && | 1698 } else if (xfermode != SkXfermode::kSrc_Mode && |
1699 xfermode != SkXfermode::kSrcOut_Mode) { | 1699 xfermode != SkXfermode::kSrcOut_Mode) { |
1700 // Except for Src and SrcOut, if there isn't anything already there, | 1700 // Except for Src and SrcOut, if there isn't anything already there, |
1701 // then we're done. | 1701 // then we're done. |
1702 return NULL; | 1702 return nullptr; |
1703 } | 1703 } |
1704 } | 1704 } |
1705 // TODO(vandebo): Figure out how/if we can handle the following modes: | 1705 // TODO(vandebo): Figure out how/if we can handle the following modes: |
1706 // Xor, Plus. | 1706 // Xor, Plus. |
1707 | 1707 |
1708 // Dst xfer mode doesn't draw source at all. | 1708 // Dst xfer mode doesn't draw source at all. |
1709 if (xfermode == SkXfermode::kDst_Mode) { | 1709 if (xfermode == SkXfermode::kDst_Mode) { |
1710 return NULL; | 1710 return nullptr; |
1711 } | 1711 } |
1712 | 1712 |
1713 ContentEntry* entry; | 1713 ContentEntry* entry; |
1714 SkAutoTDelete<ContentEntry> newEntry; | 1714 SkAutoTDelete<ContentEntry> newEntry; |
1715 | 1715 |
1716 ContentEntry* lastContentEntry = getLastContentEntry(); | 1716 ContentEntry* lastContentEntry = getLastContentEntry(); |
1717 if (lastContentEntry && lastContentEntry->fContent.getOffset() == 0) { | 1717 if (lastContentEntry && lastContentEntry->fContent.getOffset() == 0) { |
1718 entry = lastContentEntry; | 1718 entry = lastContentEntry; |
1719 } else { | 1719 } else { |
1720 newEntry.reset(new ContentEntry); | 1720 newEntry.reset(new ContentEntry); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1791 identity.reset(); | 1791 identity.reset(); |
1792 SkPaint stockPaint; | 1792 SkPaint stockPaint; |
1793 | 1793 |
1794 SkAutoTUnref<SkPDFFormXObject> srcFormXObject; | 1794 SkAutoTUnref<SkPDFFormXObject> srcFormXObject; |
1795 if (isContentEmpty()) { | 1795 if (isContentEmpty()) { |
1796 // If nothing was drawn and there's no shape, then the draw was a | 1796 // If nothing was drawn and there's no shape, then the draw was a |
1797 // no-op, but dst needs to be restored for that to be true. | 1797 // no-op, but dst needs to be restored for that to be true. |
1798 // If there is shape, then an empty source with Src, SrcIn, SrcOut, | 1798 // If there is shape, then an empty source with Src, SrcIn, SrcOut, |
1799 // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop | 1799 // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop |
1800 // reduces to Dst. | 1800 // reduces to Dst. |
1801 if (shape == NULL || xfermode == SkXfermode::kDstOut_Mode || | 1801 if (shape == nullptr || xfermode == SkXfermode::kDstOut_Mode || |
1802 xfermode == SkXfermode::kSrcATop_Mode) { | 1802 xfermode == SkXfermode::kSrcATop_Mode) { |
1803 ScopedContentEntry content(this, &fExistingClipStack, | 1803 ScopedContentEntry content(this, &fExistingClipStack, |
1804 fExistingClipRegion, identity, | 1804 fExistingClipRegion, identity, |
1805 stockPaint); | 1805 stockPaint); |
1806 SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst), | 1806 SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst), |
1807 &content.entry()->fContent); | 1807 &content.entry()->fContent); |
1808 return; | 1808 return; |
1809 } else { | 1809 } else { |
1810 xfermode = SkXfermode::kClear_Mode; | 1810 xfermode = SkXfermode::kClear_Mode; |
1811 } | 1811 } |
1812 } else { | 1812 } else { |
1813 SkASSERT(!fContentEntries->fNext.get()); | 1813 SkASSERT(!fContentEntries->fNext.get()); |
1814 srcFormXObject.reset(createFormXObjectFromDevice()); | 1814 srcFormXObject.reset(createFormXObjectFromDevice()); |
1815 } | 1815 } |
1816 | 1816 |
1817 // TODO(vandebo) srcFormXObject may contain alpha, but here we want it | 1817 // TODO(vandebo) srcFormXObject may contain alpha, but here we want it |
1818 // without alpha. | 1818 // without alpha. |
1819 if (xfermode == SkXfermode::kSrcATop_Mode) { | 1819 if (xfermode == SkXfermode::kSrcATop_Mode) { |
1820 // TODO(vandebo): In order to properly support SrcATop we have to track | 1820 // TODO(vandebo): In order to properly support SrcATop we have to track |
1821 // the shape of what's been drawn at all times. It's the intersection of | 1821 // the shape of what's been drawn at all times. It's the intersection of |
1822 // the non-transparent parts of the device and the outlines (shape) of | 1822 // the non-transparent parts of the device and the outlines (shape) of |
1823 // all images and devices drawn. | 1823 // all images and devices drawn. |
1824 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, | 1824 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, |
1825 &fExistingClipStack, fExistingClipRegion, | 1825 &fExistingClipStack, fExistingClipRegion, |
1826 SkXfermode::kSrcOver_Mode, true); | 1826 SkXfermode::kSrcOver_Mode, true); |
1827 } else { | 1827 } else { |
1828 SkAutoTUnref<SkPDFFormXObject> dstMaskStorage; | 1828 SkAutoTUnref<SkPDFFormXObject> dstMaskStorage; |
1829 SkPDFFormXObject* dstMask = srcFormXObject.get(); | 1829 SkPDFFormXObject* dstMask = srcFormXObject.get(); |
1830 if (shape != NULL) { | 1830 if (shape != nullptr) { |
1831 // Draw shape into a form-xobject. | 1831 // Draw shape into a form-xobject. |
1832 SkDraw d; | 1832 SkDraw d; |
1833 d.fMatrix = &identity; | 1833 d.fMatrix = &identity; |
1834 d.fClip = &clipRegion; | 1834 d.fClip = &clipRegion; |
1835 d.fClipStack = &clipStack; | 1835 d.fClipStack = &clipStack; |
1836 SkPaint filledPaint; | 1836 SkPaint filledPaint; |
1837 filledPaint.setColor(SK_ColorBLACK); | 1837 filledPaint.setColor(SK_ColorBLACK); |
1838 filledPaint.setStyle(SkPaint::kFill_Style); | 1838 filledPaint.setStyle(SkPaint::kFill_Style); |
1839 this->drawPath(d, *shape, filledPaint, NULL, true); | 1839 this->drawPath(d, *shape, filledPaint, nullptr, true); |
1840 | 1840 |
1841 dstMaskStorage.reset(createFormXObjectFromDevice()); | 1841 dstMaskStorage.reset(createFormXObjectFromDevice()); |
1842 dstMask = dstMaskStorage.get(); | 1842 dstMask = dstMaskStorage.get(); |
1843 } | 1843 } |
1844 drawFormXObjectWithMask(addXObjectResource(dst), dstMask, | 1844 drawFormXObjectWithMask(addXObjectResource(dst), dstMask, |
1845 &fExistingClipStack, fExistingClipRegion, | 1845 &fExistingClipStack, fExistingClipRegion, |
1846 SkXfermode::kSrcOver_Mode, true); | 1846 SkXfermode::kSrcOver_Mode, true); |
1847 } | 1847 } |
1848 | 1848 |
1849 if (xfermode == SkXfermode::kClear_Mode) { | 1849 if (xfermode == SkXfermode::kClear_Mode) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1908 return false; | 1908 return false; |
1909 } | 1909 } |
1910 | 1910 |
1911 void SkPDFDevice::populateGraphicStateEntryFromPaint( | 1911 void SkPDFDevice::populateGraphicStateEntryFromPaint( |
1912 const SkMatrix& matrix, | 1912 const SkMatrix& matrix, |
1913 const SkClipStack& clipStack, | 1913 const SkClipStack& clipStack, |
1914 const SkRegion& clipRegion, | 1914 const SkRegion& clipRegion, |
1915 const SkPaint& paint, | 1915 const SkPaint& paint, |
1916 bool hasText, | 1916 bool hasText, |
1917 GraphicStateEntry* entry) { | 1917 GraphicStateEntry* entry) { |
1918 NOT_IMPLEMENTED(paint.getPathEffect() != NULL, false); | 1918 NOT_IMPLEMENTED(paint.getPathEffect() != nullptr, false); |
1919 NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false); | 1919 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false); |
1920 NOT_IMPLEMENTED(paint.getColorFilter() != NULL, false); | 1920 NOT_IMPLEMENTED(paint.getColorFilter() != nullptr, false); |
1921 | 1921 |
1922 entry->fMatrix = matrix; | 1922 entry->fMatrix = matrix; |
1923 entry->fClipStack = clipStack; | 1923 entry->fClipStack = clipStack; |
1924 entry->fClipRegion = clipRegion; | 1924 entry->fClipRegion = clipRegion; |
1925 entry->fColor = SkColorSetA(paint.getColor(), 0xFF); | 1925 entry->fColor = SkColorSetA(paint.getColor(), 0xFF); |
1926 entry->fShaderIndex = -1; | 1926 entry->fShaderIndex = -1; |
1927 | 1927 |
1928 // PDF treats a shader as a color, so we only set one or the other. | 1928 // PDF treats a shader as a color, so we only set one or the other. |
1929 SkAutoTUnref<SkPDFObject> pdfShader; | 1929 SkAutoTUnref<SkPDFObject> pdfShader; |
1930 const SkShader* shader = paint.getShader(); | 1930 const SkShader* shader = paint.getShader(); |
(...skipping 29 matching lines...) Expand all Loading... |
1960 fShaderResources.push(pdfShader.get()); | 1960 fShaderResources.push(pdfShader.get()); |
1961 pdfShader.get()->ref(); | 1961 pdfShader.get()->ref(); |
1962 } | 1962 } |
1963 entry->fShaderIndex = resourceIndex; | 1963 entry->fShaderIndex = resourceIndex; |
1964 } else { | 1964 } else { |
1965 // A color shader is treated as an invalid shader so we don't have | 1965 // A color shader is treated as an invalid shader so we don't have |
1966 // to set a shader just for a color. | 1966 // to set a shader just for a color. |
1967 SkShader::GradientInfo gradientInfo; | 1967 SkShader::GradientInfo gradientInfo; |
1968 SkColor gradientColor; | 1968 SkColor gradientColor; |
1969 gradientInfo.fColors = &gradientColor; | 1969 gradientInfo.fColors = &gradientColor; |
1970 gradientInfo.fColorOffsets = NULL; | 1970 gradientInfo.fColorOffsets = nullptr; |
1971 gradientInfo.fColorCount = 1; | 1971 gradientInfo.fColorCount = 1; |
1972 if (shader->asAGradient(&gradientInfo) == | 1972 if (shader->asAGradient(&gradientInfo) == |
1973 SkShader::kColor_GradientType) { | 1973 SkShader::kColor_GradientType) { |
1974 entry->fColor = SkColorSetA(gradientColor, 0xFF); | 1974 entry->fColor = SkColorSetA(gradientColor, 0xFF); |
1975 color = gradientColor; | 1975 color = gradientColor; |
1976 } | 1976 } |
1977 } | 1977 } |
1978 } | 1978 } |
1979 | 1979 |
1980 SkAutoTUnref<SkPDFGraphicState> newGraphicState; | 1980 SkAutoTUnref<SkPDFGraphicState> newGraphicState; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2018 result = fXObjectResources.count(); | 2018 result = fXObjectResources.count(); |
2019 fXObjectResources.push(xObject); | 2019 fXObjectResources.push(xObject); |
2020 xObject->ref(); | 2020 xObject->ref(); |
2021 } | 2021 } |
2022 return result; | 2022 return result; |
2023 } | 2023 } |
2024 | 2024 |
2025 void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID, | 2025 void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID, |
2026 ContentEntry* contentEntry) { | 2026 ContentEntry* contentEntry) { |
2027 SkTypeface* typeface = paint.getTypeface(); | 2027 SkTypeface* typeface = paint.getTypeface(); |
2028 if (contentEntry->fState.fFont == NULL || | 2028 if (contentEntry->fState.fFont == nullptr || |
2029 contentEntry->fState.fTextSize != paint.getTextSize() || | 2029 contentEntry->fState.fTextSize != paint.getTextSize() || |
2030 !contentEntry->fState.fFont->hasGlyph(glyphID)) { | 2030 !contentEntry->fState.fFont->hasGlyph(glyphID)) { |
2031 int fontIndex = getFontResourceIndex(typeface, glyphID); | 2031 int fontIndex = getFontResourceIndex(typeface, glyphID); |
2032 contentEntry->fContent.writeText("/"); | 2032 contentEntry->fContent.writeText("/"); |
2033 contentEntry->fContent.writeText(SkPDFResourceDict::getResourceName( | 2033 contentEntry->fContent.writeText(SkPDFResourceDict::getResourceName( |
2034 SkPDFResourceDict::kFont_ResourceType, | 2034 SkPDFResourceDict::kFont_ResourceType, |
2035 fontIndex).c_str()); | 2035 fontIndex).c_str()); |
2036 contentEntry->fContent.writeText(" "); | 2036 contentEntry->fContent.writeText(" "); |
2037 SkPDFUtils::AppendScalar(paint.getTextSize(), &contentEntry->fContent); | 2037 SkPDFUtils::AppendScalar(paint.getTextSize(), &contentEntry->fContent); |
2038 contentEntry->fContent.writeText(" Tf\n"); | 2038 contentEntry->fContent.writeText(" Tf\n"); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2073 SkBitmap* subsetBitmap; | 2073 SkBitmap* subsetBitmap; |
2074 if (srcRect) { | 2074 if (srcRect) { |
2075 if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) { | 2075 if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) { |
2076 return; | 2076 return; |
2077 } | 2077 } |
2078 subsetBitmap = &tmpSubsetBitmap; | 2078 subsetBitmap = &tmpSubsetBitmap; |
2079 } else { | 2079 } else { |
2080 subsetBitmap = &tmpSubsetBitmap; | 2080 subsetBitmap = &tmpSubsetBitmap; |
2081 *subsetBitmap = origBitmap; | 2081 *subsetBitmap = origBitmap; |
2082 } | 2082 } |
2083 srcRect = NULL; | 2083 srcRect = nullptr; |
2084 | 2084 |
2085 // Transform the bitmap in the new space, without taking into | 2085 // Transform the bitmap in the new space, without taking into |
2086 // account the initial transform. | 2086 // account the initial transform. |
2087 SkPath perspectiveOutline; | 2087 SkPath perspectiveOutline; |
2088 perspectiveOutline.addRect( | 2088 perspectiveOutline.addRect( |
2089 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), | 2089 SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()), |
2090 SkIntToScalar(subsetBitmap->height()))); | 2090 SkIntToScalar(subsetBitmap->height()))); |
2091 perspectiveOutline.transform(origMatrix); | 2091 perspectiveOutline.transform(origMatrix); |
2092 | 2092 |
2093 // TODO(edisonn): perf - use current clip too. | 2093 // TODO(edisonn): perf - use current clip too. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2149 // and scaled to reflect DPI. | 2149 // and scaled to reflect DPI. |
2150 matrix.setScale(1 / scaleX, 1 / scaleY); | 2150 matrix.setScale(1 / scaleX, 1 / scaleY); |
2151 matrix.postTranslate(deltaX, deltaY); | 2151 matrix.postTranslate(deltaX, deltaY); |
2152 | 2152 |
2153 perspectiveBounds.setRect( | 2153 perspectiveBounds.setRect( |
2154 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), | 2154 SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()), |
2155 SkScalarFloorToInt(bounds.y()), | 2155 SkScalarFloorToInt(bounds.y()), |
2156 SkScalarCeilToInt(bounds.width()), | 2156 SkScalarCeilToInt(bounds.width()), |
2157 SkScalarCeilToInt(bounds.height()))); | 2157 SkScalarCeilToInt(bounds.height()))); |
2158 clipRegion = &perspectiveBounds; | 2158 clipRegion = &perspectiveBounds; |
2159 srcRect = NULL; | 2159 srcRect = nullptr; |
2160 bitmap = &perspectiveBitmap; | 2160 bitmap = &perspectiveBitmap; |
2161 } | 2161 } |
2162 | 2162 |
2163 SkMatrix scaled; | 2163 SkMatrix scaled; |
2164 // Adjust for origin flip. | 2164 // Adjust for origin flip. |
2165 scaled.setScale(SK_Scalar1, -SK_Scalar1); | 2165 scaled.setScale(SK_Scalar1, -SK_Scalar1); |
2166 scaled.postTranslate(0, SK_Scalar1); | 2166 scaled.postTranslate(0, SK_Scalar1); |
2167 // Scale the image up from 1x1 to WxH. | 2167 // Scale the image up from 1x1 to WxH. |
2168 SkIRect subset = bitmap->bounds(); | 2168 SkIRect subset = bitmap->bounds(); |
2169 scaled.postScale(SkIntToScalar(subset.width()), | 2169 scaled.postScale(SkIntToScalar(subset.width()), |
(...skipping 20 matching lines...) Expand all Loading... |
2190 return; | 2190 return; |
2191 } | 2191 } |
2192 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap)); | 2192 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap)); |
2193 if (!image) { | 2193 if (!image) { |
2194 return; | 2194 return; |
2195 } | 2195 } |
2196 | 2196 |
2197 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), | 2197 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), |
2198 &content.entry()->fContent); | 2198 &content.entry()->fContent); |
2199 } | 2199 } |
OLD | NEW |