Index: src/pdf/SkPDFDevice.cpp |
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp |
index 387bfe836148b7715c3be37189e3d8e7e64dc670..c332468c05888b2ba378ad57275eb2a6ff729c02 100644 |
--- a/src/pdf/SkPDFDevice.cpp |
+++ b/src/pdf/SkPDFDevice.cpp |
@@ -16,6 +16,7 @@ |
#include "SkGlyphCache.h" |
#include "SkPaint.h" |
#include "SkPath.h" |
+#include "SkPathOps.h" |
#include "SkPDFFont.h" |
#include "SkPDFFormXObject.h" |
#include "SkPDFGraphicState.h" |
@@ -842,6 +843,13 @@ void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath, |
return; |
} |
+#ifdef SK_PDF_USE_PATHOPS |
+ if (origPath.isInverseFillType()) { |
vandebo (ex-Chrome)
2013/07/30 16:50:42
nit: Push this into the handle method...
if (hand
ducky
2013/07/30 22:01:55
Done.
|
+ handleInversePath(d, origPath, paint, pathIsMutable); |
+ return; |
+ } |
+#endif |
+ |
if (handleRectAnnotation(pathPtr->getBounds(), *d.fMatrix, paint)) { |
return; |
} |
@@ -1232,6 +1240,70 @@ SkData* SkPDFDevice::copyContentToData() const { |
return data.copyToData(); |
} |
+/* Calculate an inverted path's equivalent non-inverted path, given the |
+ * canvas bounds. |
+ */ |
+bool calculate_inverse_path(const SkRect& bounds, const SkPath& invPath, |
vandebo (ex-Chrome)
2013/07/30 16:50:42
You can inline this function unless you intend to
ducky
2013/07/30 22:01:55
I probably should have noted that this was to get
|
+ SkPath* outPath) { |
+ SkASSERT(invPath.isInverseFillType()); |
+ |
+ SkPath clipPath; |
+ clipPath.addRect(bounds); |
+ |
+ return Op(clipPath, invPath, kIntersect_PathOp, outPath); |
+} |
+ |
+/* Draws an inverse filled path by using Path Ops to compute the positive |
+ * inverse using the current clip as the inverse bounds. |
+ */ |
+void SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath, |
+ const SkPaint& paint, bool pathIsMutable) { |
+ SkASSERT(origPath.isInverseFillType()); |
+ |
+ if (d.fClip->isEmpty()) { |
+ return; |
+ } |
+ |
+ SkPath modifiedPath; |
+ SkPath* pathPtr = const_cast<SkPath*>(&origPath); |
+ SkPaint noInversePaint(paint); |
+ |
+ // Merge stroking operations into final path. |
+ if (SkPaint::kStroke_Style == paint.getStyle() || |
+ SkPaint::kStrokeAndFill_Style == paint.getStyle()) { |
+ pathPtr = &modifiedPath; |
+ if (paint.getFillPath(origPath, pathPtr)) { |
+ noInversePaint.setStyle(SkPaint::kFill_Style); |
+ noInversePaint.setStrokeWidth(0); |
+ } else { |
+ // To be consistent with the raster output, hairline strokes |
vandebo (ex-Chrome)
2013/07/30 16:50:42
At this point pathPtr points to modifiedPath that
ducky
2013/07/30 22:01:55
I think paint.getFillPath still duplicates the pai
|
+ // are rendered as non-inverted. |
+ pathPtr->toggleInverseFillType(); |
+ drawPath(d, *pathPtr, paint, NULL, true); |
+ return; |
vandebo (ex-Chrome)
2013/07/30 16:50:42
After you've changed this to return a bool though,
ducky
2013/07/30 22:01:55
I can see how that would be faster, but it seems l
|
+ } |
+ } |
+ |
+ // Get bounds of clip in current transform space |
+ // (clip bounds are given in device space). |
+ SkRect bounds; |
+ SkMatrix transformInverse; |
+ if (!d.fMatrix->invert(&transformInverse)) { |
+ return; |
+ } |
+ bounds.set(d.fClip->getBounds()); |
+ transformInverse.mapRect(&bounds); |
+ |
+ // Extend the bounds by the line width (plus some padding) |
+ // so the edge doesn't cause a visible stroke. |
+ bounds.outset(paint.getStrokeWidth() + SK_Scalar1, |
+ paint.getStrokeWidth() + SK_Scalar1); |
+ |
+ if (calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) { |
+ drawPath(d, modifiedPath, noInversePaint, NULL, true); |
+ } |
+} |
+ |
bool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix, |
const SkPaint& p) { |
SkAnnotation* annotationInfo = p.getAnnotation(); |