diff options
Diffstat (limited to 'src/pdf')
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 1 | ||||
-rw-r--r-- | src/pdf/SkPDFDeviceFlattener.cpp | 155 | ||||
-rw-r--r-- | src/pdf/SkPDFDeviceFlattener.h | 53 | ||||
-rw-r--r-- | src/pdf/SkPDFShader.cpp | 3 |
4 files changed, 211 insertions, 1 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 538422c510..43117a2b2f 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -2034,6 +2034,7 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix, const SkBitmap& bitmap, const SkIRect* srcRect, const SkPaint& paint) { + // TODO(edisonn): Perspective matrix support implemented here SkMatrix scaled; // Adjust for origin flip. scaled.setScale(SK_Scalar1, -SK_Scalar1); diff --git a/src/pdf/SkPDFDeviceFlattener.cpp b/src/pdf/SkPDFDeviceFlattener.cpp new file mode 100644 index 0000000000..9c0bf41db2 --- /dev/null +++ b/src/pdf/SkPDFDeviceFlattener.cpp @@ -0,0 +1,155 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkPDFDeviceFlattener.h" + +#include "SkDraw.h" + +static SkISize SkSizeToISize(const SkSize& size) { + return SkISize::Make(SkScalarRoundToInt(size.width()), SkScalarRoundToInt(size.height())); +} + +SkPDFDeviceFlattener::SkPDFDeviceFlattener(const SkSize& pageSize, const SkRect* trimBox) + : SkPDFDevice(SkSizeToISize(pageSize), + SkSizeToISize(pageSize), + SkMatrix::I()) { + // TODO(edisonn): store the trimbox on emit. +} + +SkPDFDeviceFlattener::~SkPDFDeviceFlattener() { +} + +static void flattenPaint(const SkDraw& d, SkPaint* paint) { + if (paint->getShader()) { + SkMatrix local = paint->getShader()->getLocalMatrix(); + local.preConcat(*d.fMatrix); + paint->getShader()->setLocalMatrix(local); + } +} + +void SkPDFDeviceFlattener::drawPoints(const SkDraw& d, SkCanvas::PointMode mode, + size_t count, const SkPoint points[], + const SkPaint& paint) { + if (!mustFlatten(d)) { + INHERITED::drawPoints(d, mode, count, points, paint); + return; + } + + SkPaint paintFlatten(paint); + flattenPaint(d, &paintFlatten); + + SkPoint* flattenedPoints = SkNEW_ARRAY(SkPoint, count); + d.fMatrix->mapPoints(flattenedPoints, points, count); + SkDraw draw(d); + SkMatrix identity = SkMatrix::I(); + draw.fMatrix = &identity; + INHERITED::drawPoints(draw, mode, count, flattenedPoints, paintFlatten); + SkDELETE_ARRAY(flattenedPoints); +} + +void SkPDFDeviceFlattener::drawRect(const SkDraw& d, const SkRect& r, const SkPaint& paint) { + if (!mustFlatten(d)) { + INHERITED::drawRect(d, r, paint); + return; + } + + SkPath path; + path.addRect(r); + path.transform(*d.fMatrix); + SkDraw draw(d); + SkMatrix matrix = SkMatrix::I(); + draw.fMatrix = &matrix; + + SkPaint paintFlatten(paint); + flattenPaint(d, &paintFlatten); + + INHERITED::drawPath(draw, path, paintFlatten, NULL, true); +} + +void SkPDFDeviceFlattener::drawPath(const SkDraw& d, const SkPath& origPath, + const SkPaint& paint, const SkMatrix* prePathMatrix, + bool pathIsMutable) { + if (!mustFlatten(d) && !(prePathMatrix && prePathMatrix->hasPerspective())) { + INHERITED::drawPath(d, origPath, paint, prePathMatrix, pathIsMutable); + return; + } + + SkPath* pathPtr = (SkPath*)&origPath; + SkPath tmpPath; + + if (!pathIsMutable) { + tmpPath = origPath; + pathPtr = &tmpPath; + } + + if (prePathMatrix) { + pathPtr->transform(*prePathMatrix); + } + + SkPaint paintFlatten(paint); + flattenPaint(d, &paintFlatten); + + bool fill = paintFlatten.getFillPath(*pathPtr, &tmpPath); + SkDEBUGCODE(pathPtr = (SkPath*)0x12345678); // Don't use pathPtr after this point. + + paintFlatten.setPathEffect(NULL); + if (fill) { + paintFlatten.setStyle(SkPaint::kFill_Style); + } else { + paintFlatten.setStyle(SkPaint::kStroke_Style); + paintFlatten.setStrokeWidth(0); + } + + tmpPath.transform(*d.fMatrix); + + SkDraw draw(d); + SkMatrix matrix = SkMatrix::I(); + draw.fMatrix = &matrix; + + INHERITED::drawPath(draw, tmpPath, paintFlatten, NULL, true); +} + +void SkPDFDeviceFlattener::drawText(const SkDraw& d, const void* text, size_t len, + SkScalar x, SkScalar y, const SkPaint& paint) { + if (mustPathText(d, paint)) { + d.drawText_asPaths((const char*)text, len, x, y, paint); + return; + } + + INHERITED::drawText(d, text, len, x, y, paint); +} + +void SkPDFDeviceFlattener::drawPosText(const SkDraw& d, const void* text, size_t len, + const SkScalar pos[], SkScalar constY, + int scalarsPerPos, const SkPaint& paint) { + if (mustPathText(d, paint)) { + d.drawPosText_asPaths((const char*)text, len, pos, constY, scalarsPerPos, paint); + return; + } + INHERITED::drawPosText(d, text, len, pos, constY,scalarsPerPos, paint); +} + +void SkPDFDeviceFlattener::drawTextOnPath(const SkDraw& d, const void* text, size_t len, + const SkPath& path, const SkMatrix* matrix, + const SkPaint& paint) { + if (mustPathText(d, paint) || (matrix && matrix->hasPerspective())) { + d.drawTextOnPath((const char*)text, len, path, matrix, paint); + return; + } + INHERITED::drawTextOnPath(d, text, len, path, matrix, paint); +} + +bool SkPDFDeviceFlattener::mustFlatten(const SkDraw& d) const { + // TODO(edisonn): testability, add flag to force return true. + return d.fMatrix->hasPerspective(); +} + +bool SkPDFDeviceFlattener::mustPathText(const SkDraw& d, const SkPaint&) { + // TODO(edisonn): testability, add flag to force return true. + // TODO(edisonn): TBD: How to flatten MaskFilter. + return d.fMatrix->hasPerspective(); +} diff --git a/src/pdf/SkPDFDeviceFlattener.h b/src/pdf/SkPDFDeviceFlattener.h new file mode 100644 index 0000000000..f1047db3fc --- /dev/null +++ b/src/pdf/SkPDFDeviceFlattener.h @@ -0,0 +1,53 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkPDFDeviceFlattener_DEFINED +#define SkPDFDeviceFlattener_DEFINED + +#include "SkPDFDevice.h" + + +/** \class SkPDFDeviceFlattener + + The PDF Device Flattener is used to flatten features without native support in PDF. + For now, the only one implemented is Perspective. + + TODO(edisonn): Rename the class once we know all the things it will do. +*/ +class SkPDFDeviceFlattener : public SkPDFDevice { +private: + typedef SkPDFDevice INHERITED; + + SK_API SkPDFDeviceFlattener(const SkSize& pageSize, const SkRect* trimBox = NULL); + +public: + SK_API virtual ~SkPDFDeviceFlattener(); + + virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, + size_t count, const SkPoint[], + const SkPaint& paint) SK_OVERRIDE; + virtual void drawRect(const SkDraw&, const SkRect& r, const SkPaint& paint); + virtual void drawPath(const SkDraw&, const SkPath& origpath, + const SkPaint& paint, const SkMatrix* prePathMatrix, + bool pathIsMutable) SK_OVERRIDE; + virtual void drawText(const SkDraw&, const void* text, size_t len, + SkScalar x, SkScalar y, const SkPaint&) SK_OVERRIDE; + virtual void drawPosText(const SkDraw&, const void* text, size_t len, + const SkScalar pos[], SkScalar constY, + int scalarsPerPos, const SkPaint&) SK_OVERRIDE; + virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, + const SkPath& path, const SkMatrix* matrix, + const SkPaint& paint) SK_OVERRIDE; +private: + + bool mustFlatten(const SkDraw& d) const; + bool mustPathText(const SkDraw& d, const SkPaint& paint); + + friend class SkDocument_PDF; +}; + +#endif // SkPDFDeviceFlattener_DEFINED diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp index 80ea2f2ce7..70fb616a24 100644 --- a/src/pdf/SkPDFShader.cpp +++ b/src/pdf/SkPDFShader.cpp @@ -9,7 +9,6 @@ #include "SkPDFShader.h" -#include "SkCanvas.h" #include "SkData.h" #include "SkPDFCatalog.h" #include "SkPDFDevice.h" @@ -870,6 +869,8 @@ SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { unflip.preScale(SK_Scalar1, -SK_Scalar1); SkISize size = SkISize::Make(SkScalarRound(deviceBounds.width()), SkScalarRound(deviceBounds.height())); + // TODO(edisonn): should we pass here the DCT encoder of the destination device? + // TODO(edisonn): NYI Perspective, use SkPDFDeviceFlattener. SkPDFDevice pattern(size, size, unflip); SkCanvas canvas(&pattern); |