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 "SkAdvancedTypefaceMetrics.h" | 10 #include "SkAdvancedTypefaceMetrics.h" |
(...skipping 29 matching lines...) Expand all Loading... |
40 #include "SkTemplates.h" | 40 #include "SkTemplates.h" |
41 #include "SkTextBlobRunIterator.h" | 41 #include "SkTextBlobRunIterator.h" |
42 #include "SkTextFormatParams.h" | 42 #include "SkTextFormatParams.h" |
43 #include "SkUtils.h" | 43 #include "SkUtils.h" |
44 #include "SkXfermodeInterpretation.h" | 44 #include "SkXfermodeInterpretation.h" |
45 | 45 |
46 #define DPI_FOR_RASTER_SCALE_ONE 72 | 46 #define DPI_FOR_RASTER_SCALE_ONE 72 |
47 | 47 |
48 // Utility functions | 48 // Utility functions |
49 | 49 |
50 // If the paint will definitely draw opaquely, replace kSrc_Mode with | 50 // If the paint will definitely draw opaquely, replace kSrc with |
51 // kSrcOver_Mode. http://crbug.com/473572 | 51 // kSrcOver. http://crbug.com/473572 |
52 static void replace_srcmode_on_opaque_paint(SkPaint* paint) { | 52 static void replace_srcmode_on_opaque_paint(SkPaint* paint) { |
53 if (kSrcOver_SkXfermodeInterpretation | 53 if (kSrcOver_SkXfermodeInterpretation == SkInterpretXfermode(*paint, false))
{ |
54 == SkInterpretXfermode(*paint, false)) { | 54 paint->setBlendMode(SkBlendMode::kSrcOver); |
55 paint->setXfermode(nullptr); | |
56 } | 55 } |
57 } | 56 } |
58 | 57 |
59 static void emit_pdf_color(SkColor color, SkWStream* result) { | 58 static void emit_pdf_color(SkColor color, SkWStream* result) { |
60 SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere. | 59 SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere. |
61 SkPDFUtils::AppendColorComponent(SkColorGetR(color), result); | 60 SkPDFUtils::AppendColorComponent(SkColorGetR(color), result); |
62 result->writeText(" "); | 61 result->writeText(" "); |
63 SkPDFUtils::AppendColorComponent(SkColorGetG(color), result); | 62 SkPDFUtils::AppendColorComponent(SkColorGetG(color), result); |
64 result->writeText(" "); | 63 result->writeText(" "); |
65 SkPDFUtils::AppendColorComponent(SkColorGetB(color), result); | 64 SkPDFUtils::AppendColorComponent(SkColorGetB(color), result); |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 | 384 |
386 | 385 |
387 // A helper class to automatically finish a ContentEntry at the end of a | 386 // A helper class to automatically finish a ContentEntry at the end of a |
388 // drawing method and maintain the state needed between set up and finish. | 387 // drawing method and maintain the state needed between set up and finish. |
389 class ScopedContentEntry { | 388 class ScopedContentEntry { |
390 public: | 389 public: |
391 ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw, | 390 ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw, |
392 const SkPaint& paint, bool hasText = false) | 391 const SkPaint& paint, bool hasText = false) |
393 : fDevice(device), | 392 : fDevice(device), |
394 fContentEntry(nullptr), | 393 fContentEntry(nullptr), |
395 fXfermode(SkXfermode::kSrcOver_Mode), | 394 fBlendMode(SkBlendMode::kSrcOver), |
396 fDstFormXObject(nullptr) { | 395 fDstFormXObject(nullptr) { |
397 init(draw.fClipStack, draw.fRC->bwRgn(), *draw.fMatrix, paint, hasText); | 396 init(draw.fClipStack, draw.fRC->bwRgn(), *draw.fMatrix, paint, hasText); |
398 } | 397 } |
399 ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack, | 398 ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack, |
400 const SkRegion& clipRegion, const SkMatrix& matrix, | 399 const SkRegion& clipRegion, const SkMatrix& matrix, |
401 const SkPaint& paint, bool hasText = false) | 400 const SkPaint& paint, bool hasText = false) |
402 : fDevice(device), | 401 : fDevice(device), |
403 fContentEntry(nullptr), | 402 fContentEntry(nullptr), |
404 fXfermode(SkXfermode::kSrcOver_Mode), | 403 fBlendMode(SkBlendMode::kSrcOver), |
405 fDstFormXObject(nullptr) { | 404 fDstFormXObject(nullptr) { |
406 init(clipStack, clipRegion, matrix, paint, hasText); | 405 init(clipStack, clipRegion, matrix, paint, hasText); |
407 } | 406 } |
408 | 407 |
409 ~ScopedContentEntry() { | 408 ~ScopedContentEntry() { |
410 if (fContentEntry) { | 409 if (fContentEntry) { |
411 SkPath* shape = &fShape; | 410 SkPath* shape = &fShape; |
412 if (shape->isEmpty()) { | 411 if (shape->isEmpty()) { |
413 shape = nullptr; | 412 shape = nullptr; |
414 } | 413 } |
415 fDevice->finishContentEntry(fXfermode, std::move(fDstFormXObject), s
hape); | 414 fDevice->finishContentEntry(fBlendMode, std::move(fDstFormXObject),
shape); |
416 } | 415 } |
417 } | 416 } |
418 | 417 |
419 SkPDFDevice::ContentEntry* entry() { return fContentEntry; } | 418 SkPDFDevice::ContentEntry* entry() { return fContentEntry; } |
420 | 419 |
421 /* Returns true when we explicitly need the shape of the drawing. */ | 420 /* Returns true when we explicitly need the shape of the drawing. */ |
422 bool needShape() { | 421 bool needShape() { |
423 switch (fXfermode) { | 422 switch (fBlendMode) { |
424 case SkXfermode::kClear_Mode: | 423 case SkBlendMode::kClear: |
425 case SkXfermode::kSrc_Mode: | 424 case SkBlendMode::kSrc: |
426 case SkXfermode::kSrcIn_Mode: | 425 case SkBlendMode::kSrcIn: |
427 case SkXfermode::kSrcOut_Mode: | 426 case SkBlendMode::kSrcOut: |
428 case SkXfermode::kDstIn_Mode: | 427 case SkBlendMode::kDstIn: |
429 case SkXfermode::kDstOut_Mode: | 428 case SkBlendMode::kDstOut: |
430 case SkXfermode::kSrcATop_Mode: | 429 case SkBlendMode::kSrcATop: |
431 case SkXfermode::kDstATop_Mode: | 430 case SkBlendMode::kDstATop: |
432 case SkXfermode::kModulate_Mode: | 431 case SkBlendMode::kModulate: |
433 return true; | 432 return true; |
434 default: | 433 default: |
435 return false; | 434 return false; |
436 } | 435 } |
437 } | 436 } |
438 | 437 |
439 /* Returns true unless we only need the shape of the drawing. */ | 438 /* Returns true unless we only need the shape of the drawing. */ |
440 bool needSource() { | 439 bool needSource() { |
441 if (fXfermode == SkXfermode::kClear_Mode) { | 440 if (fBlendMode == SkBlendMode::kClear) { |
442 return false; | 441 return false; |
443 } | 442 } |
444 return true; | 443 return true; |
445 } | 444 } |
446 | 445 |
447 /* If the shape is different than the alpha component of the content, then | 446 /* If the shape is different than the alpha component of the content, then |
448 * setShape should be called with the shape. In particular, images and | 447 * setShape should be called with the shape. In particular, images and |
449 * devices have rectangular shape. | 448 * devices have rectangular shape. |
450 */ | 449 */ |
451 void setShape(const SkPath& shape) { | 450 void setShape(const SkPath& shape) { |
452 fShape = shape; | 451 fShape = shape; |
453 } | 452 } |
454 | 453 |
455 private: | 454 private: |
456 SkPDFDevice* fDevice; | 455 SkPDFDevice* fDevice; |
457 SkPDFDevice::ContentEntry* fContentEntry; | 456 SkPDFDevice::ContentEntry* fContentEntry; |
458 SkXfermode::Mode fXfermode; | 457 SkBlendMode fBlendMode; |
459 sk_sp<SkPDFObject> fDstFormXObject; | 458 sk_sp<SkPDFObject> fDstFormXObject; |
460 SkPath fShape; | 459 SkPath fShape; |
461 | 460 |
462 void init(const SkClipStack* clipStack, const SkRegion& clipRegion, | 461 void init(const SkClipStack* clipStack, const SkRegion& clipRegion, |
463 const SkMatrix& matrix, const SkPaint& paint, bool hasText) { | 462 const SkMatrix& matrix, const SkPaint& paint, bool hasText) { |
464 // Shape has to be flatten before we get here. | 463 // Shape has to be flatten before we get here. |
465 if (matrix.hasPerspective()) { | 464 if (matrix.hasPerspective()) { |
466 NOT_IMPLEMENTED(!matrix.hasPerspective(), false); | 465 NOT_IMPLEMENTED(!matrix.hasPerspective(), false); |
467 return; | 466 return; |
468 } | 467 } |
469 if (paint.getXfermode()) { | 468 fBlendMode = paint.getBlendMode(); |
470 paint.getXfermode()->asMode(&fXfermode); | |
471 } | |
472 fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion, | 469 fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion, |
473 matrix, paint, hasText, | 470 matrix, paint, hasText, |
474 &fDstFormXObject); | 471 &fDstFormXObject); |
475 } | 472 } |
476 }; | 473 }; |
477 | 474 |
478 //////////////////////////////////////////////////////////////////////////////// | 475 //////////////////////////////////////////////////////////////////////////////// |
479 | 476 |
480 SkPDFDevice::SkPDFDevice(SkISize pageSize, SkScalar rasterDpi, SkPDFDocument* do
c, bool flip) | 477 SkPDFDevice::SkPDFDevice(SkISize pageSize, SkScalar rasterDpi, SkPDFDocument* do
c, bool flip) |
481 : INHERITED(SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height()), | 478 : INHERITED(SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height()), |
(...skipping 1218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1700 // it back in later. | 1697 // it back in later. |
1701 this->cleanUp(); // Reset this device to have no content. | 1698 this->cleanUp(); // Reset this device to have no content. |
1702 this->init(); | 1699 this->init(); |
1703 return xobject; | 1700 return xobject; |
1704 } | 1701 } |
1705 | 1702 |
1706 void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, | 1703 void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, |
1707 sk_sp<SkPDFObject> mask, | 1704 sk_sp<SkPDFObject> mask, |
1708 const SkClipStack* clipStack, | 1705 const SkClipStack* clipStack, |
1709 const SkRegion& clipRegion, | 1706 const SkRegion& clipRegion, |
1710 SkXfermode::Mode mode, | 1707 SkBlendMode mode, |
1711 bool invertClip) { | 1708 bool invertClip) { |
1712 if (clipRegion.isEmpty() && !invertClip) { | 1709 if (clipRegion.isEmpty() && !invertClip) { |
1713 return; | 1710 return; |
1714 } | 1711 } |
1715 | 1712 |
1716 sk_sp<SkPDFDict> sMaskGS = SkPDFGraphicState::GetSMaskGraphicState( | 1713 sk_sp<SkPDFDict> sMaskGS = SkPDFGraphicState::GetSMaskGraphicState( |
1717 std::move(mask), invertClip, | 1714 std::move(mask), invertClip, |
1718 SkPDFGraphicState::kAlpha_SMaskMode, fDocument->canon()); | 1715 SkPDFGraphicState::kAlpha_SMaskMode, fDocument->canon()); |
1719 | 1716 |
1720 SkMatrix identity; | 1717 SkMatrix identity; |
1721 identity.reset(); | 1718 identity.reset(); |
1722 SkPaint paint; | 1719 SkPaint paint; |
1723 paint.setXfermodeMode(mode); | 1720 paint.setBlendMode(mode); |
1724 ScopedContentEntry content(this, clipStack, clipRegion, identity, paint); | 1721 ScopedContentEntry content(this, clipStack, clipRegion, identity, paint); |
1725 if (!content.entry()) { | 1722 if (!content.entry()) { |
1726 return; | 1723 return; |
1727 } | 1724 } |
1728 SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), | 1725 SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), |
1729 &content.entry()->fContent); | 1726 &content.entry()->fContent); |
1730 SkPDFUtils::DrawFormXObject(xObjectIndex, &content.entry()->fContent); | 1727 SkPDFUtils::DrawFormXObject(xObjectIndex, &content.entry()->fContent); |
1731 | 1728 |
1732 // Call makeNoSmaskGraphicState() instead of | 1729 // Call makeNoSmaskGraphicState() instead of |
1733 // SkPDFGraphicState::MakeNoSmaskGraphicState so that the canon | 1730 // SkPDFGraphicState::MakeNoSmaskGraphicState so that the canon |
(...skipping 24 matching lines...) Expand all Loading... |
1758 // fExistingClip as a prefix, so start there, then set the clip | 1755 // fExistingClip as a prefix, so start there, then set the clip |
1759 // to the passed region. | 1756 // to the passed region. |
1760 synthesizedClipStack = fExistingClipStack; | 1757 synthesizedClipStack = fExistingClipStack; |
1761 SkPath clipPath; | 1758 SkPath clipPath; |
1762 clipRegion.getBoundaryPath(&clipPath); | 1759 clipRegion.getBoundaryPath(&clipPath); |
1763 synthesizedClipStack.clipPath(clipPath, SkMatrix::I(), SkCanvas::kRe
place_Op, false); | 1760 synthesizedClipStack.clipPath(clipPath, SkMatrix::I(), SkCanvas::kRe
place_Op, false); |
1764 clipStack = &synthesizedClipStack; | 1761 clipStack = &synthesizedClipStack; |
1765 } | 1762 } |
1766 } | 1763 } |
1767 | 1764 |
1768 SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode; | 1765 SkBlendMode blendMode = paint.getBlendMode(); |
1769 if (paint.getXfermode()) { | |
1770 paint.getXfermode()->asMode(&xfermode); | |
1771 } | |
1772 | 1766 |
1773 // For the following modes, we want to handle source and destination | 1767 // For the following modes, we want to handle source and destination |
1774 // separately, so make an object of what's already there. | 1768 // separately, so make an object of what's already there. |
1775 if (xfermode == SkXfermode::kClear_Mode || | 1769 if (blendMode == SkBlendMode::kClear || |
1776 xfermode == SkXfermode::kSrc_Mode || | 1770 blendMode == SkBlendMode::kSrc || |
1777 xfermode == SkXfermode::kSrcIn_Mode || | 1771 blendMode == SkBlendMode::kSrcIn || |
1778 xfermode == SkXfermode::kDstIn_Mode || | 1772 blendMode == SkBlendMode::kDstIn || |
1779 xfermode == SkXfermode::kSrcOut_Mode || | 1773 blendMode == SkBlendMode::kSrcOut || |
1780 xfermode == SkXfermode::kDstOut_Mode || | 1774 blendMode == SkBlendMode::kDstOut || |
1781 xfermode == SkXfermode::kSrcATop_Mode || | 1775 blendMode == SkBlendMode::kSrcATop || |
1782 xfermode == SkXfermode::kDstATop_Mode || | 1776 blendMode == SkBlendMode::kDstATop || |
1783 xfermode == SkXfermode::kModulate_Mode) { | 1777 blendMode == SkBlendMode::kModulate) { |
1784 if (!isContentEmpty()) { | 1778 if (!isContentEmpty()) { |
1785 *dst = this->makeFormXObjectFromDevice(); | 1779 *dst = this->makeFormXObjectFromDevice(); |
1786 SkASSERT(isContentEmpty()); | 1780 SkASSERT(isContentEmpty()); |
1787 } else if (xfermode != SkXfermode::kSrc_Mode && | 1781 } else if (blendMode != SkBlendMode::kSrc && |
1788 xfermode != SkXfermode::kSrcOut_Mode) { | 1782 blendMode != SkBlendMode::kSrcOut) { |
1789 // Except for Src and SrcOut, if there isn't anything already there, | 1783 // Except for Src and SrcOut, if there isn't anything already there, |
1790 // then we're done. | 1784 // then we're done. |
1791 return nullptr; | 1785 return nullptr; |
1792 } | 1786 } |
1793 } | 1787 } |
1794 // TODO(vandebo): Figure out how/if we can handle the following modes: | 1788 // TODO(vandebo): Figure out how/if we can handle the following modes: |
1795 // Xor, Plus. | 1789 // Xor, Plus. |
1796 | 1790 |
1797 // Dst xfer mode doesn't draw source at all. | 1791 // Dst xfer mode doesn't draw source at all. |
1798 if (xfermode == SkXfermode::kDst_Mode) { | 1792 if (blendMode == SkBlendMode::kDst) { |
1799 return nullptr; | 1793 return nullptr; |
1800 } | 1794 } |
1801 | 1795 |
1802 SkPDFDevice::ContentEntry* entry; | 1796 SkPDFDevice::ContentEntry* entry; |
1803 if (fContentEntries.back() && fContentEntries.back()->fContent.getOffset() =
= 0) { | 1797 if (fContentEntries.back() && fContentEntries.back()->fContent.getOffset() =
= 0) { |
1804 entry = fContentEntries.back(); | 1798 entry = fContentEntries.back(); |
1805 } else if (xfermode != SkXfermode::kDstOver_Mode) { | 1799 } else if (blendMode != SkBlendMode::kDstOver) { |
1806 entry = fContentEntries.emplace_back(); | 1800 entry = fContentEntries.emplace_back(); |
1807 } else { | 1801 } else { |
1808 entry = fContentEntries.emplace_front(); | 1802 entry = fContentEntries.emplace_front(); |
1809 } | 1803 } |
1810 populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint, | 1804 populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint, |
1811 hasText, &entry->fState); | 1805 hasText, &entry->fState); |
1812 return entry; | 1806 return entry; |
1813 } | 1807 } |
1814 | 1808 |
1815 void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode, | 1809 void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, |
1816 sk_sp<SkPDFObject> dst, | 1810 sk_sp<SkPDFObject> dst, |
1817 SkPath* shape) { | 1811 SkPath* shape) { |
1818 if (xfermode != SkXfermode::kClear_Mode && | 1812 if (blendMode != SkBlendMode::kClear && |
1819 xfermode != SkXfermode::kSrc_Mode && | 1813 blendMode != SkBlendMode::kSrc && |
1820 xfermode != SkXfermode::kDstOver_Mode && | 1814 blendMode != SkBlendMode::kDstOver && |
1821 xfermode != SkXfermode::kSrcIn_Mode && | 1815 blendMode != SkBlendMode::kSrcIn && |
1822 xfermode != SkXfermode::kDstIn_Mode && | 1816 blendMode != SkBlendMode::kDstIn && |
1823 xfermode != SkXfermode::kSrcOut_Mode && | 1817 blendMode != SkBlendMode::kSrcOut && |
1824 xfermode != SkXfermode::kDstOut_Mode && | 1818 blendMode != SkBlendMode::kDstOut && |
1825 xfermode != SkXfermode::kSrcATop_Mode && | 1819 blendMode != SkBlendMode::kSrcATop && |
1826 xfermode != SkXfermode::kDstATop_Mode && | 1820 blendMode != SkBlendMode::kDstATop && |
1827 xfermode != SkXfermode::kModulate_Mode) { | 1821 blendMode != SkBlendMode::kModulate) { |
1828 SkASSERT(!dst); | 1822 SkASSERT(!dst); |
1829 return; | 1823 return; |
1830 } | 1824 } |
1831 if (xfermode == SkXfermode::kDstOver_Mode) { | 1825 if (blendMode == SkBlendMode::kDstOver) { |
1832 SkASSERT(!dst); | 1826 SkASSERT(!dst); |
1833 if (fContentEntries.front()->fContent.getOffset() == 0) { | 1827 if (fContentEntries.front()->fContent.getOffset() == 0) { |
1834 // For DstOver, an empty content entry was inserted before the rest | 1828 // For DstOver, an empty content entry was inserted before the rest |
1835 // of the content entries. If nothing was drawn, it needs to be | 1829 // of the content entries. If nothing was drawn, it needs to be |
1836 // removed. | 1830 // removed. |
1837 fContentEntries.pop_front(); | 1831 fContentEntries.pop_front(); |
1838 } | 1832 } |
1839 return; | 1833 return; |
1840 } | 1834 } |
1841 if (!dst) { | 1835 if (!dst) { |
1842 SkASSERT(xfermode == SkXfermode::kSrc_Mode || | 1836 SkASSERT(blendMode == SkBlendMode::kSrc || |
1843 xfermode == SkXfermode::kSrcOut_Mode); | 1837 blendMode == SkBlendMode::kSrcOut); |
1844 return; | 1838 return; |
1845 } | 1839 } |
1846 | 1840 |
1847 SkASSERT(dst); | 1841 SkASSERT(dst); |
1848 SkASSERT(fContentEntries.count() == 1); | 1842 SkASSERT(fContentEntries.count() == 1); |
1849 // Changing the current content into a form-xobject will destroy the clip | 1843 // Changing the current content into a form-xobject will destroy the clip |
1850 // objects which is fine since the xobject will already be clipped. However | 1844 // objects which is fine since the xobject will already be clipped. However |
1851 // if source has shape, we need to clip it too, so a copy of the clip is | 1845 // if source has shape, we need to clip it too, so a copy of the clip is |
1852 // saved. | 1846 // saved. |
1853 | 1847 |
1854 SkClipStack clipStack = fContentEntries.front()->fState.fClipStack; | 1848 SkClipStack clipStack = fContentEntries.front()->fState.fClipStack; |
1855 SkRegion clipRegion = fContentEntries.front()->fState.fClipRegion; | 1849 SkRegion clipRegion = fContentEntries.front()->fState.fClipRegion; |
1856 | 1850 |
1857 SkMatrix identity; | 1851 SkMatrix identity; |
1858 identity.reset(); | 1852 identity.reset(); |
1859 SkPaint stockPaint; | 1853 SkPaint stockPaint; |
1860 | 1854 |
1861 sk_sp<SkPDFObject> srcFormXObject; | 1855 sk_sp<SkPDFObject> srcFormXObject; |
1862 if (isContentEmpty()) { | 1856 if (isContentEmpty()) { |
1863 // If nothing was drawn and there's no shape, then the draw was a | 1857 // If nothing was drawn and there's no shape, then the draw was a |
1864 // no-op, but dst needs to be restored for that to be true. | 1858 // no-op, but dst needs to be restored for that to be true. |
1865 // If there is shape, then an empty source with Src, SrcIn, SrcOut, | 1859 // If there is shape, then an empty source with Src, SrcIn, SrcOut, |
1866 // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop | 1860 // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop |
1867 // reduces to Dst. | 1861 // reduces to Dst. |
1868 if (shape == nullptr || xfermode == SkXfermode::kDstOut_Mode || | 1862 if (shape == nullptr || blendMode == SkBlendMode::kDstOut || |
1869 xfermode == SkXfermode::kSrcATop_Mode) { | 1863 blendMode == SkBlendMode::kSrcATop) { |
1870 ScopedContentEntry content(this, &fExistingClipStack, | 1864 ScopedContentEntry content(this, &fExistingClipStack, |
1871 fExistingClipRegion, identity, | 1865 fExistingClipRegion, identity, |
1872 stockPaint); | 1866 stockPaint); |
1873 // TODO: addXObjectResource take sk_sp | 1867 // TODO: addXObjectResource take sk_sp |
1874 SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()), | 1868 SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()), |
1875 &content.entry()->fContent); | 1869 &content.entry()->fContent); |
1876 return; | 1870 return; |
1877 } else { | 1871 } else { |
1878 xfermode = SkXfermode::kClear_Mode; | 1872 blendMode = SkBlendMode::kClear; |
1879 } | 1873 } |
1880 } else { | 1874 } else { |
1881 SkASSERT(fContentEntries.count() == 1); | 1875 SkASSERT(fContentEntries.count() == 1); |
1882 srcFormXObject = this->makeFormXObjectFromDevice(); | 1876 srcFormXObject = this->makeFormXObjectFromDevice(); |
1883 } | 1877 } |
1884 | 1878 |
1885 // TODO(vandebo) srcFormXObject may contain alpha, but here we want it | 1879 // TODO(vandebo) srcFormXObject may contain alpha, but here we want it |
1886 // without alpha. | 1880 // without alpha. |
1887 if (xfermode == SkXfermode::kSrcATop_Mode) { | 1881 if (blendMode == SkBlendMode::kSrcATop) { |
1888 // TODO(vandebo): In order to properly support SrcATop we have to track | 1882 // TODO(vandebo): In order to properly support SrcATop we have to track |
1889 // the shape of what's been drawn at all times. It's the intersection of | 1883 // the shape of what's been drawn at all times. It's the intersection of |
1890 // the non-transparent parts of the device and the outlines (shape) of | 1884 // the non-transparent parts of the device and the outlines (shape) of |
1891 // all images and devices drawn. | 1885 // all images and devices drawn. |
1892 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, | 1886 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, |
1893 &fExistingClipStack, fExistingClipRegion, | 1887 &fExistingClipStack, fExistingClipRegion, |
1894 SkXfermode::kSrcOver_Mode, true); | 1888 SkBlendMode::kSrcOver, true); |
1895 } else { | 1889 } else { |
1896 if (shape != nullptr) { | 1890 if (shape != nullptr) { |
1897 // Draw shape into a form-xobject. | 1891 // Draw shape into a form-xobject. |
1898 SkRasterClip rc(clipRegion); | 1892 SkRasterClip rc(clipRegion); |
1899 SkDraw d; | 1893 SkDraw d; |
1900 d.fMatrix = &identity; | 1894 d.fMatrix = &identity; |
1901 d.fRC = &rc; | 1895 d.fRC = &rc; |
1902 d.fClipStack = &clipStack; | 1896 d.fClipStack = &clipStack; |
1903 SkPaint filledPaint; | 1897 SkPaint filledPaint; |
1904 filledPaint.setColor(SK_ColorBLACK); | 1898 filledPaint.setColor(SK_ColorBLACK); |
1905 filledPaint.setStyle(SkPaint::kFill_Style); | 1899 filledPaint.setStyle(SkPaint::kFill_Style); |
1906 this->drawPath(d, *shape, filledPaint, nullptr, true); | 1900 this->drawPath(d, *shape, filledPaint, nullptr, true); |
1907 drawFormXObjectWithMask(addXObjectResource(dst.get()), | 1901 drawFormXObjectWithMask(addXObjectResource(dst.get()), |
1908 this->makeFormXObjectFromDevice(), | 1902 this->makeFormXObjectFromDevice(), |
1909 &fExistingClipStack, fExistingClipRegion, | 1903 &fExistingClipStack, fExistingClipRegion, |
1910 SkXfermode::kSrcOver_Mode, true); | 1904 SkBlendMode::kSrcOver, true); |
1911 | 1905 |
1912 } else { | 1906 } else { |
1913 drawFormXObjectWithMask(addXObjectResource(dst.get()), srcFormXObjec
t, | 1907 drawFormXObjectWithMask(addXObjectResource(dst.get()), srcFormXObjec
t, |
1914 &fExistingClipStack, fExistingClipRegion, | 1908 &fExistingClipStack, fExistingClipRegion, |
1915 SkXfermode::kSrcOver_Mode, true); | 1909 SkBlendMode::kSrcOver, true); |
1916 } | 1910 } |
1917 } | 1911 } |
1918 | 1912 |
1919 if (xfermode == SkXfermode::kClear_Mode) { | 1913 if (blendMode == SkBlendMode::kClear) { |
1920 return; | 1914 return; |
1921 } else if (xfermode == SkXfermode::kSrc_Mode || | 1915 } else if (blendMode == SkBlendMode::kSrc || |
1922 xfermode == SkXfermode::kDstATop_Mode) { | 1916 blendMode == SkBlendMode::kDstATop) { |
1923 ScopedContentEntry content(this, &fExistingClipStack, | 1917 ScopedContentEntry content(this, &fExistingClipStack, |
1924 fExistingClipRegion, identity, stockPaint); | 1918 fExistingClipRegion, identity, stockPaint); |
1925 if (content.entry()) { | 1919 if (content.entry()) { |
1926 SkPDFUtils::DrawFormXObject( | 1920 SkPDFUtils::DrawFormXObject( |
1927 this->addXObjectResource(srcFormXObject.get()), | 1921 this->addXObjectResource(srcFormXObject.get()), |
1928 &content.entry()->fContent); | 1922 &content.entry()->fContent); |
1929 } | 1923 } |
1930 if (xfermode == SkXfermode::kSrc_Mode) { | 1924 if (blendMode == SkBlendMode::kSrc) { |
1931 return; | 1925 return; |
1932 } | 1926 } |
1933 } else if (xfermode == SkXfermode::kSrcATop_Mode) { | 1927 } else if (blendMode == SkBlendMode::kSrcATop) { |
1934 ScopedContentEntry content(this, &fExistingClipStack, | 1928 ScopedContentEntry content(this, &fExistingClipStack, |
1935 fExistingClipRegion, identity, stockPaint); | 1929 fExistingClipRegion, identity, stockPaint); |
1936 if (content.entry()) { | 1930 if (content.entry()) { |
1937 SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()), | 1931 SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()), |
1938 &content.entry()->fContent); | 1932 &content.entry()->fContent); |
1939 } | 1933 } |
1940 } | 1934 } |
1941 | 1935 |
1942 SkASSERT(xfermode == SkXfermode::kSrcIn_Mode || | 1936 SkASSERT(blendMode == SkBlendMode::kSrcIn || |
1943 xfermode == SkXfermode::kDstIn_Mode || | 1937 blendMode == SkBlendMode::kDstIn || |
1944 xfermode == SkXfermode::kSrcOut_Mode || | 1938 blendMode == SkBlendMode::kSrcOut || |
1945 xfermode == SkXfermode::kDstOut_Mode || | 1939 blendMode == SkBlendMode::kDstOut || |
1946 xfermode == SkXfermode::kSrcATop_Mode || | 1940 blendMode == SkBlendMode::kSrcATop || |
1947 xfermode == SkXfermode::kDstATop_Mode || | 1941 blendMode == SkBlendMode::kDstATop || |
1948 xfermode == SkXfermode::kModulate_Mode); | 1942 blendMode == SkBlendMode::kModulate); |
1949 | 1943 |
1950 if (xfermode == SkXfermode::kSrcIn_Mode || | 1944 if (blendMode == SkBlendMode::kSrcIn || |
1951 xfermode == SkXfermode::kSrcOut_Mode || | 1945 blendMode == SkBlendMode::kSrcOut || |
1952 xfermode == SkXfermode::kSrcATop_Mode) { | 1946 blendMode == SkBlendMode::kSrcATop) { |
1953 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), | 1947 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), |
1954 std::move(dst), | 1948 std::move(dst), |
1955 &fExistingClipStack, fExistingClipRegion, | 1949 &fExistingClipStack, fExistingClipRegion, |
1956 SkXfermode::kSrcOver_Mode, | 1950 SkBlendMode::kSrcOver, |
1957 xfermode == SkXfermode::kSrcOut_Mode); | 1951 blendMode == SkBlendMode::kSrcOut); |
1958 return; | 1952 return; |
1959 } else { | 1953 } else { |
1960 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode; | 1954 SkBlendMode mode = SkBlendMode::kSrcOver; |
1961 int resourceID = addXObjectResource(dst.get()); | 1955 int resourceID = addXObjectResource(dst.get()); |
1962 if (xfermode == SkXfermode::kModulate_Mode) { | 1956 if (blendMode == SkBlendMode::kModulate) { |
1963 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), | 1957 drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), |
1964 std::move(dst), &fExistingClipStack, | 1958 std::move(dst), &fExistingClipStack, |
1965 fExistingClipRegion, | 1959 fExistingClipRegion, |
1966 SkXfermode::kSrcOver_Mode, false); | 1960 SkBlendMode::kSrcOver, false); |
1967 mode = SkXfermode::kMultiply_Mode; | 1961 mode = SkBlendMode::kMultiply; |
1968 } | 1962 } |
1969 drawFormXObjectWithMask(resourceID, std::move(srcFormXObject), | 1963 drawFormXObjectWithMask(resourceID, std::move(srcFormXObject), |
1970 &fExistingClipStack, fExistingClipRegion, mode, | 1964 &fExistingClipStack, fExistingClipRegion, mode, |
1971 xfermode == SkXfermode::kDstOut_Mode); | 1965 blendMode == SkBlendMode::kDstOut); |
1972 return; | 1966 return; |
1973 } | 1967 } |
1974 } | 1968 } |
1975 | 1969 |
1976 bool SkPDFDevice::isContentEmpty() { | 1970 bool SkPDFDevice::isContentEmpty() { |
1977 if (!fContentEntries.front() || fContentEntries.front()->fContent.getOffset(
) == 0) { | 1971 if (!fContentEntries.front() || fContentEntries.front()->fContent.getOffset(
) == 0) { |
1978 SkASSERT(fContentEntries.count() <= 1); | 1972 SkASSERT(fContentEntries.count() <= 1); |
1979 return true; | 1973 return true; |
1980 } | 1974 } |
1981 return false; | 1975 return false; |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2322 | 2316 |
2323 sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() { | 2317 sk_sp<SkSpecialImage> SkPDFDevice::snapSpecial() { |
2324 return nullptr; | 2318 return nullptr; |
2325 } | 2319 } |
2326 | 2320 |
2327 SkImageFilterCache* SkPDFDevice::getImageFilterCache() { | 2321 SkImageFilterCache* SkPDFDevice::getImageFilterCache() { |
2328 // We always return a transient cache, so it is freed after each | 2322 // We always return a transient cache, so it is freed after each |
2329 // filter traversal. | 2323 // filter traversal. |
2330 return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize)
; | 2324 return SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize)
; |
2331 } | 2325 } |
OLD | NEW |