Chromium Code Reviews| 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(); |