[PDF] Implement clear() method and a couple fixes.

+ If the clip matches the initial clip, don't set the clip.
+ Don't change the transform for drawPaint.

Review URL: http://codereview.appspot.com/4424041

git-svn-id: http://skia.googlecode.com/svn/trunk@1142 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
vandebo@chromium.org 2011-04-15 20:57:37 +00:00
parent fb0b0edd86
commit 77bcaa324a
2 changed files with 72 additions and 25 deletions

View File

@ -71,6 +71,8 @@ public:
virtual int height() const { return fHeight; };
virtual void clear(SkColor color);
/** Called with the correct matrix and clip before this device is drawn
to using those settings. If your subclass overrides this, be sure to
call through to the base class as well.
@ -175,6 +177,8 @@ private:
SkDynamicMemoryWStream fContent;
void init();
void cleanUp();
void updateGSFromPaint(const SkPaint& newPaint, bool forText);
void updateFont(const SkPaint& paint, uint16_t glyphID);
int getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID);
@ -182,6 +186,8 @@ private:
void pushGS();
void popGS();
void setTextTransform(SkScalar x, SkScalar y, SkScalar textSkewX);
void internalDrawPaint(const SkPaint& paint);
void internalDrawRect(const SkRect& r, const SkPaint& paint);
void internalDrawBitmap(const SkMatrix& matrix, const SkBitmap& bitmap,
const SkIRect* srcRect, const SkPaint& paint);

View File

@ -21,13 +21,13 @@
#include "SkGlyphCache.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkPDFImage.h"
#include "SkPDFGraphicState.h"
#include "SkPDFFont.h"
#include "SkPDFFormXObject.h"
#include "SkPDFTypes.h"
#include "SkPDFGraphicState.h"
#include "SkPDFImage.h"
#include "SkPDFShader.h"
#include "SkPDFStream.h"
#include "SkPDFTypes.h"
#include "SkPDFUtils.h"
#include "SkRect.h"
#include "SkString.h"
@ -135,6 +135,21 @@ SkPDFDevice::SkPDFDevice(int width, int height,
fWidth(width),
fHeight(height),
fGraphicStackIndex(0) {
// 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);
this->init();
}
SkPDFDevice::~SkPDFDevice() {
this->cleanUp();
}
void SkPDFDevice::init() {
fGraphicStack[0].fColor = SK_ColorBLACK;
fGraphicStack[0].fTextSize = SK_ScalarNaN; // This has no default value.
fGraphicStack[0].fTextScaleX = SK_Scalar1;
@ -142,27 +157,41 @@ SkPDFDevice::SkPDFDevice(int width, int height,
fGraphicStack[0].fFont = NULL;
fGraphicStack[0].fShader = NULL;
fGraphicStack[0].fGraphicState = NULL;
fGraphicStack[0].fClip.setRect(0,0, width, height);
fGraphicStack[0].fClip.setRect(0,0, fWidth, fHeight);
fGraphicStack[0].fTransform.reset();
fGraphicStackIndex = 0;
fResourceDict = NULL;
fContent.reset();
// 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);
}
}
SkPDFDevice::~SkPDFDevice() {
void SkPDFDevice::cleanUp() {
fGraphicStateResources.unrefAll();
fXObjectResources.unrefAll();
fFontResources.unrefAll();
fShaderResources.unrefAll();
}
void SkPDFDevice::clear(SkColor color) {
SkMatrix curTransform = fGraphicStack[fGraphicStackIndex].fTransform;
SkRegion curClip = fGraphicStack[fGraphicStackIndex].fClip;
this->cleanUp();
this->init();
SkPaint paint;
paint.setColor(color);
paint.setStyle(SkPaint::kFill_Style);
updateGSFromPaint(paint, false);
internalDrawPaint(paint);
SkClipStack clipStack;
setMatrixClip(curTransform, curClip, clipStack);
}
void SkPDFDevice::setMatrixClip(const SkMatrix& matrix,
const SkRegion& region,
const SkClipStack&) {
@ -180,12 +209,14 @@ void SkPDFDevice::setMatrixClip(const SkMatrix& matrix,
if (region != fGraphicStack[fGraphicStackIndex].fClip) {
while (fGraphicStackIndex > 0)
popGS();
pushGS();
SkPath clipPath;
if (region.getBoundaryPath(&clipPath)) {
if (region != fGraphicStack[fGraphicStackIndex].fClip) {
pushGS();
SkPath clipPath;
SkAssertResult(region.getBoundaryPath(&clipPath));
SkPDFUtils::EmitPath(clipPath, &fContent);
SkPath::FillType clipFill = clipPath.getFillType();
NOT_IMPLEMENTED(clipFill == SkPath::kInverseEvenOdd_FillType,
false);
@ -195,9 +226,9 @@ void SkPDFDevice::setMatrixClip(const SkMatrix& matrix,
fContent.writeText("W* n ");
else
fContent.writeText("W n ");
}
fGraphicStack[fGraphicStackIndex].fClip = region;
fGraphicStack[fGraphicStackIndex].fClip = region;
}
}
setTransform(matrix);
}
@ -207,18 +238,24 @@ void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) {
return;
}
SkMatrix identityTransform;
identityTransform.reset();
SkMatrix curTransform = setTransform(identityTransform);
SkPaint newPaint = paint;
newPaint.setStyle(SkPaint::kFill_Style);
updateGSFromPaint(newPaint, false);
SkRect all = SkRect::MakeWH(SkIntToScalar(this->width()),
SkIntToScalar(this->height()));
drawRect(d, all, newPaint);
setTransform(curTransform);
internalDrawPaint(newPaint);
}
void SkPDFDevice::internalDrawPaint(const SkPaint& paint) {
SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()),
SkIntToScalar(this->height()));
SkMatrix totalTransform = fInitialTransform;
totalTransform.preConcat(fGraphicStack[fGraphicStackIndex].fTransform);
SkMatrix inverse;
inverse.reset();
totalTransform.invert(&inverse);
inverse.mapRect(&bbox);
internalDrawRect(bbox, paint);
}
void SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode,
@ -293,6 +330,10 @@ void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& r,
}
updateGSFromPaint(paint, false);
internalDrawRect(r, paint);
}
void SkPDFDevice::internalDrawRect(const SkRect& r, const SkPaint& paint) {
// Skia has 0,0 at top left, pdf at bottom left. Do the right thing.
SkScalar bottom = r.fBottom < r.fTop ? r.fBottom : r.fTop;
SkPDFUtils::AppendRectangle(r.fLeft, bottom, r.width(), r.height(),