| Index: src/pdf/SkPDFDevice.cpp
|
| diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
|
| index 6680ea472e9e534c20fa8a920685f55921a643f4..1c5b4da07065c7a7afc0963fd713f7bd3a47091a 100644
|
| --- a/src/pdf/SkPDFDevice.cpp
|
| +++ b/src/pdf/SkPDFDevice.cpp
|
| @@ -5,6 +5,7 @@
|
| * found in the LICENSE file.
|
| */
|
|
|
| +#include <tuple>
|
| #include "SkPDFDevice.h"
|
|
|
| #include "SkAnnotation.h"
|
| @@ -41,6 +42,23 @@
|
|
|
| // Utility functions
|
|
|
| +static bool excessive_translation(const SkMatrix& m) {
|
| + const SkScalar kExcessiveTranslation = 8192.0f;
|
| + return SkScalarAbs(m.getTranslateX()) > kExcessiveTranslation
|
| + || SkScalarAbs(m.getTranslateY()) > kExcessiveTranslation;
|
| +}
|
| +
|
| +static std::tuple<SkMatrix, SkVector> untranslate(const SkDraw& d) {
|
| + // https://bug.skia.org/257 If the translation is too large,
|
| + // PDF can't exactly represent the float values as numbers.
|
| + SkScalar translateX = d.fMatrix->getTranslateX() / d.fMatrix->getScaleX();
|
| + SkScalar translateY = d.fMatrix->getTranslateY() / d.fMatrix->getScaleY();
|
| + SkMatrix mat = *d.fMatrix;
|
| + mat.preTranslate(-translateX, -translateY);
|
| + SkASSERT(SkScalarAbs(mat.getTranslateX()) <= 1.0);
|
| + return std::make_tuple(mat, SkVector::Make(translateX, translateY));
|
| +}
|
| +
|
| // If the paint will definitely draw opaquely, replace kSrc_Mode with
|
| // kSrcOver_Mode. http://crbug.com/473572
|
| static void replace_srcmode_on_opaque_paint(SkPaint* paint) {
|
| @@ -801,6 +819,16 @@ void SkPDFDevice::drawPoints(const SkDraw& d,
|
| return;
|
| }
|
| }
|
| + if (excessive_translation(*d.fMatrix)) {
|
| + SkVector translate; SkMatrix translateMatrix;
|
| + std::tie(translateMatrix, translate) = untranslate(d);
|
| + SkDraw drawCopy(d);
|
| + drawCopy.fMatrix = &translateMatrix;
|
| + SkTArray<SkPoint> pointsCopy(points, SkToInt(count));
|
| + SkPoint::Offset(&pointsCopy[0], SkToInt(count), translate);
|
| + this->drawPoints(drawCopy, mode, count, &pointsCopy[0], srcPaint);
|
| + return; // NOTE: shader behavior will be off.
|
| + }
|
|
|
| // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
|
| // We only use this when there's a path effect because of the overhead
|
| @@ -929,6 +957,17 @@ void SkPDFDevice::drawRect(const SkDraw& d,
|
| SkRect r = rect;
|
| r.sort();
|
|
|
| + if (excessive_translation(*d.fMatrix)) {
|
| + SkVector translate; SkMatrix translateMatrix;
|
| + std::tie(translateMatrix, translate) = untranslate(d);
|
| + SkDraw drawCopy(d);
|
| + drawCopy.fMatrix = &translateMatrix;
|
| + SkRect rectCopy = rect;
|
| + rectCopy.offset(translate.x(), translate.y());
|
| + this->drawRect(drawCopy, rectCopy, srcPaint);
|
| + return; // NOTE: shader behavior will be off.
|
| + }
|
| +
|
| if (paint.getPathEffect()) {
|
| if (d.fClip->isEmpty()) {
|
| return;
|
| @@ -981,6 +1020,17 @@ void SkPDFDevice::drawPath(const SkDraw& d,
|
| const SkPaint& srcPaint,
|
| const SkMatrix* prePathMatrix,
|
| bool pathIsMutable) {
|
| + if (excessive_translation(*d.fMatrix)) {
|
| + SkVector translate; SkMatrix translateMatrix;
|
| + std::tie(translateMatrix, translate) = untranslate(d);
|
| + SkDraw drawCopy(d);
|
| + drawCopy.fMatrix = &translateMatrix;
|
| + SkPath pathCopy(origPath);
|
| + pathCopy.offset(translate.x(), translate.y());
|
| + this->drawPath(drawCopy, pathCopy, srcPaint, prePathMatrix, true);
|
| + return; // NOTE: shader behavior will be off.
|
| + }
|
| +
|
| SkPaint paint = srcPaint;
|
| replace_srcmode_on_opaque_paint(&paint);
|
| SkPath modifiedPath;
|
| @@ -1273,6 +1323,16 @@ static void draw_transparent_text(SkPDFDevice* device,
|
|
|
| void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
|
| SkScalar x, SkScalar y, const SkPaint& srcPaint) {
|
| + if (excessive_translation(*d.fMatrix)) {
|
| + SkVector translate; SkMatrix translateMatrix;
|
| + std::tie(translateMatrix, translate) = untranslate(d);
|
| + SkDraw drawCopy(d);
|
| + drawCopy.fMatrix = &translateMatrix;
|
| + this->drawText(drawCopy, text, len, x + translate.x(),
|
| + y + translate.y(), srcPaint);
|
| + return; // NOTE: shader behavior will be off.
|
| + }
|
| +
|
| if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) {
|
| // https://bug.skia.org/3866
|
| SkPath path;
|
| @@ -1334,6 +1394,18 @@ void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
|
| void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
|
| const SkScalar pos[], int scalarsPerPos,
|
| const SkPoint& offset, const SkPaint& srcPaint) {
|
| + if (excessive_translation(*d.fMatrix)) {
|
| + SkVector translate; SkMatrix translateMatrix;
|
| + std::tie(translateMatrix, translate) = untranslate(d);
|
| + SkDraw drawCopy(d);
|
| + drawCopy.fMatrix = &translateMatrix;
|
| + SkPoint offsetCopy = offset;
|
| + SkPoint::Offset(&offsetCopy, 1, translate.x(), translate.y());
|
| + this->drawPosText(drawCopy, text, len, pos, scalarsPerPos, offsetCopy,
|
| + srcPaint);
|
| + return; // NOTE: shader behavior will be off.
|
| + }
|
| +
|
| if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) {
|
| const SkPoint* positions = reinterpret_cast<const SkPoint*>(pos);
|
| SkAutoTMalloc<SkPoint> positionsBuffer;
|
|
|