| 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 |