Chromium Code Reviews| Index: src/pdf/SkPDFDevice.cpp |
| diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp |
| index 387bfe836148b7715c3be37189e3d8e7e64dc670..5e6d2c98bd17815761c322ec270c1da1a50c055e 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,12 @@ void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath, |
| return; |
| } |
| +#ifdef SK_PDF_USE_PATHOPS |
| + if (handleInversePath(d, origPath, paint, pathIsMutable)) { |
| + return; |
| + } |
| +#endif |
| + |
| if (handleRectAnnotation(pathPtr->getBounds(), *d.fMatrix, paint)) { |
| return; |
| } |
| @@ -1232,6 +1239,80 @@ 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, |
| + 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. |
| + * Return true if this was an inverse path and was properly handled, |
| + * otherwise returns false and the normal drawing routine should continue, |
| + * either as a (incorrect) fallback or because the path was not inverse |
| + * in the first place. |
| + */ |
| +bool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath, |
| + const SkPaint& paint, bool pathIsMutable) { |
| + if (!origPath.isInverseFillType()) { |
| + return false; |
| + } |
| + |
| + if (d.fClip->isEmpty()) { |
| + return false; |
| + } |
| + |
| + 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; |
| + bool doFillPath = paint.getFillPath(origPath, pathPtr); |
| + if (doFillPath) { |
| + noInversePaint.setStyle(SkPaint::kFill_Style); |
| + noInversePaint.setStrokeWidth(0); |
| + } else { |
| + // To be consistent with the raster output, hairline strokes |
| + // are rendered as non-inverted. |
| + pathPtr->toggleInverseFillType(); |
| + drawPath(d, *pathPtr, paint, NULL, true); |
|
vandebo (ex-Chrome)
2013/07/30 22:27:15
nit: *pathPtr -> modifiedPath
ducky
2013/07/30 22:45:44
Ehh, I think this is slightly cleaner, as paint.ge
vandebo (ex-Chrome)
2013/07/30 22:52:02
getFillPath could write to modifiedPath if you lik
ducky
2013/07/30 23:18:26
Done.
|
| + return true; |
| + } |
| + } |
| + |
| + // 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 false; |
| + } |
| + 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)) { |
| + return false; |
| + } |
| + |
| + drawPath(d, modifiedPath, noInversePaint, NULL, true); |
| + return true; |
| +} |
| + |
| bool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix, |
| const SkPaint& p) { |
| SkAnnotation* annotationInfo = p.getAnnotation(); |