summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorvandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-05-18 23:06:29 +0000
committervandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-05-18 23:06:29 +0000
commitd4b7293a11e1007e0939d9abd5e9f3f249e0fac9 (patch)
treeccb2d2f835171d25468f65bd952c70258f698956 /pdf
parent305a123576d1b88ca246316fe01794cbf7d50c5e (diff)
downloadsrc-d4b7293a11e1007e0939d9abd5e9f3f249e0fac9.tar.gz
[PDF] Implement clear xfermode with a mask instead of pushing the clip down.
This approach is much less likely to use an SkRegion and ends up working better for Webkit. Review URL: http://codereview.appspot.com/4550057 git-svn-id: http://skia.googlecode.com/svn/trunk/src@1375 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'pdf')
-rw-r--r--pdf/SkPDFDevice.cpp94
1 files changed, 38 insertions, 56 deletions
diff --git a/pdf/SkPDFDevice.cpp b/pdf/SkPDFDevice.cpp
index d55deca8..63cf7028 100644
--- a/pdf/SkPDFDevice.cpp
+++ b/pdf/SkPDFDevice.cpp
@@ -327,56 +327,6 @@ void GraphicStackState::updateClip(const SkClipStack& clipStack,
currentEntry()->fClipRegion = clipRegion;
}
-static void append_clip_stack(const SkClipStack& src, SkClipStack* dst) {
- SkClipStack::B2FIter iter(src);
- const SkClipStack::B2FIter::Clip* clipEntry;
- for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
- if (clipEntry->fRect) {
- dst->clipDevRect(*clipEntry->fRect, clipEntry->fOp);
- } else if (clipEntry->fPath) {
- dst->clipDevPath(*clipEntry->fPath, clipEntry->fOp);
- } else {
- // There's not an easy way to add an empty clip with an arbitrary
- // op, but an empty path (we've already used an empty rect) will
- // work just fine for our purposes.
- SkPath empty;
- dst->clipDevPath(empty, clipEntry->fOp);
- }
- }
-}
-
-static void apply_inverse_clip_to_content_entries(
- const SkClipStack& clipStack,
- const SkRegion& clipRegion,
- SkTScopedPtr<ContentEntry>* entries) {
- // I don't see how to find the inverse of a clip stack and apply it to
- // another clip stack. So until we can do polygon boolean operations,
- // we combine the two clip stacks plus a sentinal with a non-intersect
- // operator to annotate the intent and force use of the clip region while
- // keeping the stacks comparable.
- // Our sentinal is an empty SkRect with kReplace_Op. This sentinal should
- // not appear in any reasonable real clip stack.
- SkRect empty = SkRect::MakeEmpty();
- SkTScopedPtr<ContentEntry>* entry = entries;
- while (entry->get()) {
- entry->get()->fState.fClipRegion.op(clipRegion,
- SkRegion::kDifference_Op);
- if (entry->get()->fState.fClipRegion.isEmpty()) {
- // TODO(vandebo) The content entry we are removing may have been
- // the only one referencing specific resources, we should remove
- // those from our resource lists.
- entry->reset(entry->get()->fNext.release());
- continue;
- }
- entry->get()->fState.fClipStack.save();
- entry->get()->fState.fClipStack.clipDevRect(empty,
- SkRegion::kReplace_Op);
- append_clip_stack(clipStack, &entry->get()->fState.fClipStack);
-
- entry = &entry->get()->fNext;
- }
-}
-
void GraphicStackState::updateMatrix(const SkMatrix& matrix) {
if (matrix == currentEntry()->fMatrix) {
return;
@@ -1082,6 +1032,43 @@ void SkPDFDevice::createFormXObjectFromDevice(
init();
}
+void SkPDFDevice::clearClipFromContent(const SkClipStack* clipStack,
+ const SkRegion& clipRegion) {
+ SkRefPtr<SkPDFFormXObject> curContent;
+ createFormXObjectFromDevice(&curContent);
+
+ // Create the mask.
+ SkMatrix identity;
+ identity.reset();
+ SkDraw draw;
+ draw.fMatrix = &identity;
+ draw.fClip = &clipRegion;
+ draw.fClipStack = clipStack;
+ SkPaint stockPaint;
+ this->drawPaint(draw, stockPaint);
+ SkRefPtr<SkPDFFormXObject> maskFormXObject;
+ createFormXObjectFromDevice(&maskFormXObject);
+ SkRefPtr<SkPDFGraphicState> sMaskGS =
+ SkPDFGraphicState::getSMaskGraphicState(maskFormXObject.get(), false);
+ sMaskGS->unref(); // SkRefPtr and getSMaskGraphicState both took a ref.
+
+ // Redraw what we already had, but with the clip as a mask.
+ setUpContentEntry(&fExistingClipStack, fExistingClipRegion, identity,
+ stockPaint);
+ SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
+ &fCurrentContentEntry->fContent);
+ SkPDFUtils::DrawFormXObject(fXObjectResources.count(),
+ &fCurrentContentEntry->fContent);
+ fXObjectResources.push(curContent.get());
+ curContent->ref();
+
+ sMaskGS = SkPDFGraphicState::getNoSMaskGraphicState();
+ sMaskGS->unref(); // SkRefPtr and getSMaskGraphicState both took a ref.
+ SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
+ &fCurrentContentEntry->fContent);
+ finishContentEntry(stockPaint);
+}
+
bool SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
const SkRegion& clipRegion,
const SkMatrix& matrix,
@@ -1117,12 +1104,7 @@ bool SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
// current clip.
if (xfermode == SkXfermode::kClear_Mode ||
xfermode == SkXfermode::kSrc_Mode) {
- apply_inverse_clip_to_content_entries(*clipStack, clipRegion,
- &fContentEntries);
- // apply_inverse_clip_to_content_entries may have removed entries
- // from fContentEntries and this may have invalidated
- // fCurrentContentEntry. Set it to a known good value.
- fCurrentContentEntry = fContentEntries.get();
+ this->clearClipFromContent(clipStack, clipRegion);
}
// For the following modes, we use both source and destination, but