From 75f97e452e8f2ee55cd2b283df7d7734f48bc2bf Mon Sep 17 00:00:00 2001 From: "vandebo@chromium.org" Date: Mon, 11 Apr 2011 23:24:18 +0000 Subject: Generalize the flip origin argument to the PDF device constructor. The argument still has a default value that does what most users will want, but provides more flexibility. Chrome will use this change to support an initial translation of the origin to simulate a margin and to scale the entire content (needed on Windows). When landing to Chrome, this will need http://codereview.chromium.org/6820038 Review URL: http://codereview.appspot.com/4373052 git-svn-id: http://skia.googlecode.com/svn/trunk@1111 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/pdf/SkPDFDevice.cpp | 39 ++++++++++++++++++--------------------- src/pdf/SkPDFFont.cpp | 10 +--------- src/pdf/SkPDFShader.cpp | 6 ++++-- src/pdf/SkPDFUtils.cpp | 11 +++++++++++ 4 files changed, 34 insertions(+), 32 deletions(-) (limited to 'src/pdf') diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 3665dd8781..4a255112fc 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -113,11 +113,13 @@ void alignText(SkDrawCacheProc glyphCacheProc, const SkPaint& paint, SkDevice* SkPDFDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, int width, int height, bool isOpaque, bool isForLayer) { - SkPDFDevice::OriginTransform flip = SkPDFDevice::kFlip_OriginTransform; + SkMatrix initialTransform; + initialTransform.reset(); if (isForLayer) { - flip = SkPDFDevice::kNoFlip_OriginTransform; + initialTransform.setTranslate(0, height); + initialTransform.preScale(1, -1); } - return SkNEW_ARGS(SkPDFDevice, (width, height, flip)); + return SkNEW_ARGS(SkPDFDevice, (width, height, initialTransform)); } static inline SkBitmap makeABitmap(int width, int height) { @@ -126,11 +128,11 @@ static inline SkBitmap makeABitmap(int width, int height) { return bitmap; } -SkPDFDevice::SkPDFDevice(int width, int height, OriginTransform flipOrigin) +SkPDFDevice::SkPDFDevice(int width, int height, + const SkMatrix& initialTransform) : SkDevice(NULL, makeABitmap(width, height), false), fWidth(width), fHeight(height), - fFlipOrigin(flipOrigin), fGraphicStackIndex(0) { fGraphicStack[0].fColor = SK_ColorBLACK; fGraphicStack[0].fTextSize = SK_ScalarNaN; // This has no default value. @@ -142,10 +144,14 @@ SkPDFDevice::SkPDFDevice(int width, int height, OriginTransform flipOrigin) fGraphicStack[0].fClip.setRect(0,0, width, height); fGraphicStack[0].fTransform.reset(); - if (flipOrigin == kFlip_OriginTransform) { - fContent.writeText("1 0 0 -1 0 "); - fContent.writeDecAsText(fHeight); - fContent.writeText(" cm\n"); + // Skia generally uses the top left as the origin but PDF natively has the + // origin at the bottom left. This matrix corrects for that. When layering, + // we specify an inverse correction to cancel this out. + fInitialTransform.setTranslate(0, height); + fInitialTransform.preScale(1, -1); + fInitialTransform.preConcat(initialTransform); + if (fInitialTransform.getType() != SkMatrix::kIdentity_Mask) { + SkPDFUtils::AppendTransform(fInitialTransform, &fContent); } } @@ -601,13 +607,10 @@ void SkPDFDevice::updateGSFromPaint(const SkPaint& paint, bool forText) { // PDF positions patterns relative to the initial transform, so // we need to apply the current transform to the shader parameters. SkMatrix transform = fGraphicStack[fGraphicStackIndex].fTransform; - if (fFlipOrigin == kFlip_OriginTransform) { - transform.postScale(1, -1); - transform.postTranslate(0, fHeight); - } + transform.postConcat(fInitialTransform); // PDF doesn't support kClamp_TileMode, so we simulate it by making - // a pattern the size of the drawing service. + // a pattern the size of the drawing surface. SkIRect bounds = fGraphicStack[fGraphicStackIndex].fClip.getBounds(); pdfShader = SkPDFShader::getPDFShader(*shader, transform, bounds); SkSafeUnref(pdfShader.get()); // getShader and SkRefPtr both took a ref @@ -808,13 +811,7 @@ SkMatrix SkPDFDevice::setTransform(const SkMatrix& m) { fGraphicStack[fGraphicStackIndex - 1].fClip) pushGS(); - SkScalar transform[6]; - SkAssertResult(m.pdfTransform(transform)); - for (size_t i = 0; i < SK_ARRAY_COUNT(transform); i++) { - SkPDFScalar::Append(transform[i], &fContent); - fContent.writeText(" "); - } - fContent.writeText("cm\n"); + SkPDFUtils::AppendTransform(m, &fContent); fGraphicStack[fGraphicStackIndex].fTransform = m; return old; diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp index 9a2180d8c1..3e363f7a90 100644 --- a/src/pdf/SkPDFFont.cpp +++ b/src/pdf/SkPDFFont.cpp @@ -251,15 +251,7 @@ void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box, content->writeText(" d1\n"); } -SkPDFArray* makeFontBBox( - SkIRect glyphBBox, uint16_t emSize, - SkPDFDevice::OriginTransform flipOrigin = - SkPDFDevice::kNoFlip_OriginTransform) { - if (flipOrigin == SkPDFDevice::kFlip_OriginTransform) { - int32_t temp = -glyphBBox.fTop; - glyphBBox.fTop = -glyphBBox.fBottom; - glyphBBox.fBottom = temp; - } +SkPDFArray* makeFontBBox(SkIRect glyphBBox, uint16_t emSize) { SkPDFArray* bbox = new SkPDFArray; bbox->reserve(4); bbox->append(new SkPDFScalar(scaleFromFontUnits(glyphBBox.fLeft, diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp index c833c5d77d..3f383e5de1 100644 --- a/src/pdf/SkPDFShader.cpp +++ b/src/pdf/SkPDFShader.cpp @@ -495,8 +495,10 @@ void SkPDFShader::doImageShader() { surfaceBBox.set(fState.get()->fBBox); transformBBox(finalMatrix, &surfaceBBox); - SkPDFDevice pattern(surfaceBBox.fRight, surfaceBBox.fBottom, - SkPDFDevice::kNoFlip_OriginTransform); + SkMatrix unflip; + unflip.setTranslate(0, surfaceBBox.fBottom); + unflip.preScale(1, -1); + SkPDFDevice pattern(surfaceBBox.fRight, surfaceBBox.fBottom, unflip); SkCanvas canvas(&pattern); canvas.clipRect(surfaceBBox, SkRegion::kReplace_Op); diff --git a/src/pdf/SkPDFUtils.cpp b/src/pdf/SkPDFUtils.cpp index 8bd9c8f9c8..57e0cb7244 100644 --- a/src/pdf/SkPDFUtils.cpp +++ b/src/pdf/SkPDFUtils.cpp @@ -34,6 +34,17 @@ SkPDFArray* SkPDFUtils::MatrixToArray(const SkMatrix& matrix) { return result; } +// static +void SkPDFUtils::AppendTransform(const SkMatrix& matrix, SkWStream* content) { + SkScalar values[6]; + SkAssertResult(matrix.pdfTransform(values)); + for (size_t i = 0; i < SK_ARRAY_COUNT(values); i++) { + SkPDFScalar::Append(values[i], content); + content->writeText(" "); + } + content->writeText("cm\n"); +} + // static void SkPDFUtils::MoveTo(SkScalar x, SkScalar y, SkWStream* content) { SkPDFScalar::Append(x, content); -- cgit v1.2.3