pdfviewer: gs operator implementation: dashing and font

Review URL: https://codereview.chromium.org/20810002

git-svn-id: http://skia.googlecode.com/svn/trunk@10403 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
edisonn@google.com 2013-07-28 18:34:14 +00:00
parent 27e21fe577
commit a0cefa18fc
5 changed files with 456 additions and 60 deletions

View File

@ -1,6 +1,8 @@
#include "SkPdfBasics.h"
#include "SkPdfNativeTokenizer.h"
#include "SkDashPathEffect.h"
PdfContext::PdfContext(SkNativeParsedPDF* doc)
: fPdfDoc(doc)
, fTmpPageAllocator(new SkPdfAllocator()) {
@ -9,3 +11,25 @@ PdfContext::PdfContext(SkNativeParsedPDF* doc)
PdfContext::~PdfContext() {
delete fTmpPageAllocator;
}
void SkPdfGraphicsState::applyGraphicsState(SkPaint* paint, bool stroking) {
if (stroking) {
fStroking.applyGraphicsState(paint);
} else {
fNonStroking.applyGraphicsState(paint);
}
// TODO(edisonn): get this from pdfContext->options,
// or pdfContext->addPaintOptions(&paint);
paint->setAntiAlias(true);
// TODO(edisonn): miter, ...
if (stroking) {
paint->setStrokeWidth(SkDoubleToScalar(fLineWidth));
// TODO(edisonn): perf, two sets of allocs, create SkDashPathEffect constr that takes ownership
// of the intervals
if (fDashArrayLength > 0 && fDashPhase > 0) {
paint->setPathEffect(new SkDashPathEffect(fDashArray, fDashArrayLength, fDashPhase))->unref();
}
}
}

View File

@ -20,8 +20,28 @@ class SkPdfAllocator;
// TODO(edisonn): better class design.
struct SkPdfColorOperator {
/*
color space name or array The current color space in which color values are to be interpreted
(see Section 4.5, Color Spaces). There are two separate color space
parameters: one for stroking and one for all other painting opera-
tions. Initial value: DeviceGray.
*/
// TODO(edisonn): implement the array part too
// does not own the char*
NotOwnedString fColorSpace;
/*
color (various) The current color to be used during painting operations (see Section
4.5, Color Spaces). The type and interpretation of this parameter
depend on the current color space; for most color spaces, a color
value consists of one to four numbers. There are two separate color
parameters: one for stroking and one for all other painting opera-
tions. Initial value: black.
*/
SkColor fColor;
double fOpacity; // ca or CA
// TODO(edisonn): add here other color space options.
@ -42,10 +62,7 @@ struct SkPdfColorOperator {
// TODO(edisonn): better class design.
struct SkPdfGraphicsState {
SkMatrix fMatrix;
SkMatrix fMatrixTm;
SkMatrix fMatrixTlm;
// TODO(edisonn): deprecate and remove these!
double fCurPosX;
double fCurPosY;
@ -55,6 +72,35 @@ struct SkPdfGraphicsState {
SkPath fPath;
bool fPathClosed;
double fTextLeading;
double fWordSpace;
double fCharSpace;
SkPdfResourceDictionary* fResources;
// TODO(edisonn): move most of these in canvas/paint?
// we could have some in canvas (matrixes?),
// some in 2 paints (stroking paint and non stroking paint)
// TABLE 4.2 Device-independent graphics state parameters
/*
* CTM array The current transformation matrix, which maps positions from user
coordinates to device coordinates (see Section 4.2, Coordinate Sys-
tems). This matrix is modified by each application of the coordi-
nate transformation operator, cm. Initial value: a matrix that
transforms default user coordinates to device coordinates.
*/
SkMatrix fCTM;
/*
clipping path (internal) The current clipping path, which defines the boundary against
which all output is to be cropped (see Section 4.4.3, Clipping Path
Operators). Initial value: the boundary of the entire imageable
portion of the output page.
*/
// Clip that is applied after the drawing is done!!!
bool fHasClipPathToApply;
SkPath fClipPath;
@ -62,21 +108,208 @@ struct SkPdfGraphicsState {
SkPdfColorOperator fStroking;
SkPdfColorOperator fNonStroking;
/*
text state (various) A set of nine graphics state parameters that pertain only to the
painting of text. These include parameters that select the font, scale
the glyphs to an appropriate size, and accomplish other effects. The
text state parameters are described in Section 5.2, Text State
Parameters and Operators.
*/
// TODO(edisonn): add SkPdfTextState class. remove these two existing fields
SkMatrix fMatrixTm;
SkMatrix fMatrixTlm;
/*
line width number The thickness, in user space units, of paths to be stroked (see Line
Width on page 152). Initial value: 1.0.
*/
double fLineWidth;
double fTextLeading;
double fWordSpace;
double fCharSpace;
SkPdfResourceDictionary* fResources;
/*
line cap integer A code specifying the shape of the endpoints for any open path that
is stroked (see Line Cap Style on page 153). Initial value: 0, for
square butt caps.
*/
// TODO (edisonn): implement defaults - page 153
int fLineCap;
/*
line join integer A code specifying the shape of joints between connected segments
of a stroked path (see Line Join Style on page 153). Initial value: 0,
for mitered joins.
*/
// TODO (edisonn): implement defaults - page 153
int fLineJoin;
/*
miter limit number The maximum length of mitered line joins for stroked paths (see
Miter Limit on page 153). This parameter limits the length of
spikes produced when line segments join at sharp angles. Initial
value: 10.0, for a miter cutoff below approximately 11.5 degrees.
*/
// TODO (edisonn): implement defaults - page 153
double fMiterLimit;
/*
dash pattern array and A description of the dash pattern to be used when paths are
number stroked (see Line Dash Pattern on page 155). Initial value: a solid
line.
*/
SkScalar fDashArray[256]; // TODO(edisonn): allocate array?
int fDashArrayLength;
SkScalar fDashPhase;
/*
rendering intent name The rendering intent to be used when converting CIE-based colors
to device colors (see Rendering Intents on page 197). Default
value: RelativeColorimetric.
*/
// TODO(edisonn): seems paper only. Verify.
/*
stroke adjustment boolean (PDF 1.2) A ag specifying whether to compensate for possible ras-
terization effects when stroking a path with a line width that is
small relative to the pixel resolution of the output device (see Sec-
tion 6.5.4, Automatic Stroke Adjustment). Note that this is con-
sidered a device-independent parameter, even though the details of
its effects are device-dependent. Initial value: false.
*/
// TODO(edisonn): stroke adjustment low priority.
/*
blend mode name or array (PDF 1.4) The current blend mode to be used in the transparent
imaging model (see Sections 7.2.4, Blend Mode, and 7.5.2, Spec-
ifying Blending Color Space and Blend Mode). This parameter is
implicitly reset to its initial value at the beginning of execution of a
transparency group XObject (see Section 7.5.5, Transparency
Group XObjects). Initial value: Normal.
*/
SkXfermode::Mode fBlendMode;
/*
soft mask dictionary (PDF 1.4) A soft-mask dictionary (see Soft-Mask Dictionaries on
or name page 445) specifying the mask shape or mask opacity values to be
used in the transparent imaging model (see Source Shape and
Opacity on page 421 and Mask Shape and Opacity on page 443),
or the name None if no such mask is specified. This parameter is
implicitly reset to its initial value at the beginning of execution of a
transparency group XObject (see Section 7.5.5, Transparency
Group XObjects). Initial value: None.
*/
SkBitmap fSMask;
/*
alpha constant number (PDF 1.4) The constant shape or constant opacity value to be used
in the transparent imaging model (see Source Shape and Opacity
on page 421 and Constant Shape and Opacity on page 444).
There are two separate alpha constant parameters: one for stroking
and one for all other painting operations. This parameter is implic-
itly reset to its initial value at the beginning of execution of a trans-
parency group XObject (see Section 7.5.5, Transparency Group
XObjects). Initial value: 1.0.
*/
double fAphaConstant;
/*
alpha source boolean (PDF 1.4) A ag specifying whether the current soft mask and alpha
constant parameters are to be interpreted as shape values (true) or
opacity values (false). This ag also governs the interpretation of
the SMask entry, if any, in an image dictionary (see Section 4.8.4,
Image Dictionaries). Initial value: false.
*/
bool fAlphaSource;
// TODO(edisonn): Device-dependent seem to be required only on the actual physical printer?
// TABLE 4.3 Device-dependent graphics state parameters
/*
overprint boolean (PDF 1.2) A ag specifying (on output devices that support the
overprint control feature) whether painting in one set of colorants
should cause the corresponding areas of other colorants to be
erased (false) or left unchanged (true); see Section 4.5.6, Over-
print Control. In PDF 1.3, there are two separate overprint param-
eters: one for stroking and one for all other painting operations.
Initial value: false.
*/
/*
overprint mode number (PDF 1.3) A code specifying whether a color component value of 0
in a DeviceCMYK color space should erase that component (0) or
leave it unchanged (1) when overprinting (see Section 4.5.6, Over-
print Control). Initial value: 0.
*/
/*
black generation function (PDF 1.2) A function that calculates the level of the black color
or name component to use when converting RGB colors to CMYK (see Sec-
tion 6.2.3, Conversion from DeviceRGB to DeviceCMYK). Initial
value: installation-dependent.
*/
/*
undercolor removal function (PDF 1.2) A function that calculates the reduction in the levels of
or name the cyan, magenta, and yellow color components to compensate for
the amount of black added by black generation (see Section 6.2.3,
Conversion from DeviceRGB to DeviceCMYK). Initial value: in-
stallation-dependent.
*/
/*
transfer function, (PDF 1.2) A function that adjusts device gray or color component
array, or name levels to compensate for nonlinear response in a particular out-
put device (see Section 6.3, Transfer Functions). Initial value:
installation-dependent.
*/
/*
halftone dictionary, (PDF 1.2) A halftone screen for gray and color rendering, specified
stream, or name as a halftone dictionary or stream (see Section 6.4, Halftones).
Initial value: installation-dependent.
*/
/*
atness number The precision with which curves are to be rendered on the output
device (see Section 6.5.1, Flatness Tolerance). The value of this
parameter gives the maximum error tolerance, measured in output
device pixels; smaller numbers give smoother curves at the expense
of more computation and memory use. Initial value: 1.0.
*/
/*
smoothness number (PDF 1.3) The precision with which color gradients are to be ren-
dered on the output device (see Section 6.5.2, Smoothness Toler-
ance). The value of this parameter gives the maximum error
tolerance, expressed as a fraction of the range of each color compo-
nent; smaller numbers give smoother color transitions at the
expense of more computation and memory use. Initial value:
installation-dependent.
*/
SkPdfGraphicsState() {
fCurPosX = 0.0;
fCurPosY = 0.0;
fCurFontSize = 0.0;
fTextBlock = false;
fMatrix = SkMatrix::I();
fCTM = SkMatrix::I();
fMatrixTm = SkMatrix::I();
fMatrixTlm = SkMatrix::I();
fPathClosed = true;
@ -87,22 +320,18 @@ struct SkPdfGraphicsState {
fHasClipPathToApply = false;
fResources = NULL;
fSkFont = NULL;
fLineCap = 0;
fLineJoin = 0;
fMiterLimit = 10.0;
fAphaConstant = 1.0;
fAlphaSource = false;
fDashArrayLength = 0;
fDashPhase = 0;
fBlendMode = SkXfermode::kSrc_Mode; // PDF: Normal Blend mode
}
void applyGraphicsState(SkPaint* paint, bool stroking) {
if (stroking) {
fStroking.applyGraphicsState(paint);
} else {
fNonStroking.applyGraphicsState(paint);
}
// TODO(edisonn): get this from pdfContext->options,
// or pdfContext->addPaintOptions(&paint);
paint->setAntiAlias(true);
// TODO(edisonn): dashing, miter, ...
paint->setStrokeWidth(SkDoubleToScalar(fLineWidth));
}
// TODO(edisonn): make two functons instead, stroking and non stoking, avoid branching
void applyGraphicsState(SkPaint* paint, bool stroking);
};
// TODO(edisonn): better class design.

View File

@ -598,7 +598,7 @@ static PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, SkPdf
SkBitmap sMask = getSmaskFromObject(pdfContext, skpdfimage);
canvas->save();
canvas->setMatrix(pdfContext->fGraphicsState.fMatrix);
canvas->setMatrix(pdfContext->fGraphicsState.fCTM);
#if 1
SkScalar z = SkIntToScalar(0);
@ -608,7 +608,7 @@ static PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, SkPdf
SkPoint to[4] = {SkPoint::Make(z, one), SkPoint::Make(one, one), SkPoint::Make(one, z), SkPoint::Make(z, z)};
SkMatrix flip;
SkAssertResult(flip.setPolyToPoly(from, to, 4));
SkMatrix solveImageFlip = pdfContext->fGraphicsState.fMatrix;
SkMatrix solveImageFlip = pdfContext->fGraphicsState.fCTM;
solveImageFlip.preConcat(flip);
canvas->setMatrix(solveImageFlip);
#endif
@ -648,18 +648,18 @@ static PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, SkPdfT
pdfContext->fGraphicsState.fResources = skobj->Resources(pdfContext->fPdfDoc);
}
SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "Current matrix");
SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "Current matrix");
if (skobj->has_Matrix()) {
pdfContext->fGraphicsState.fMatrix.preConcat(skobj->Matrix(pdfContext->fPdfDoc));
pdfContext->fGraphicsState.fMatrixTm = pdfContext->fGraphicsState.fMatrix;
pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fMatrix;
pdfContext->fGraphicsState.fCTM.preConcat(skobj->Matrix(pdfContext->fPdfDoc));
pdfContext->fGraphicsState.fMatrixTm = pdfContext->fGraphicsState.fCTM;
pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fCTM;
// TODO(edisonn) reset matrixTm and matricTlm also?
}
SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "Total matrix");
SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "Total matrix");
canvas->setMatrix(pdfContext->fGraphicsState.fMatrix);
canvas->setMatrix(pdfContext->fGraphicsState.fCTM);
if (skobj->has_BBox()) {
canvas->clipRect(skobj->BBox(pdfContext->fPdfDoc), SkRegion::kIntersect_Op, true); // TODO(edisonn): AA from settings.
@ -700,15 +700,15 @@ PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObjec
pdfContext->fGraphicsState.fMatrixTm.preConcat(matrix);
pdfContext->fGraphicsState.fMatrixTm.preScale(SkDoubleToScalar(textSize), SkDoubleToScalar(textSize));
pdfContext->fGraphicsState.fMatrix = pdfContext->fGraphicsState.fMatrixTm;
pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fMatrix;
pdfContext->fGraphicsState.fCTM = pdfContext->fGraphicsState.fMatrixTm;
pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fCTM;
SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "Total matrix");
SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "Total matrix");
canvas->setMatrix(pdfContext->fGraphicsState.fMatrix);
canvas->setMatrix(pdfContext->fGraphicsState.fCTM);
SkRect rm = bBox;
pdfContext->fGraphicsState.fMatrix.mapRect(&rm);
pdfContext->fGraphicsState.fCTM.mapRect(&rm);
SkTraceRect(rm, "bbox mapped");
@ -810,7 +810,7 @@ static PdfResult PdfOp_cm(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoop
// tx ty
SkMatrix matrix = SkMatrixFromPdfMatrix(array);
pdfContext->fGraphicsState.fMatrix.preConcat(matrix);
pdfContext->fGraphicsState.fCTM.preConcat(matrix);
#ifdef PDF_TRACE
printf("cm ");
@ -818,7 +818,7 @@ static PdfResult PdfOp_cm(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoop
printf("%f ", array[i]);
}
printf("\n");
SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "cm");
SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "cm");
#endif
return kOK_PdfResult;
@ -889,7 +889,7 @@ static PdfResult PdfOp_Tm(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoop
array[5] = f;
SkMatrix matrix = SkMatrixFromPdfMatrix(array);
matrix.postConcat(pdfContext->fGraphicsState.fMatrix);
matrix.postConcat(pdfContext->fGraphicsState.fCTM);
// TODO(edisonn): Text positioning.
pdfContext->fGraphicsState.fMatrixTm = matrix;
@ -1044,7 +1044,7 @@ static PdfResult PdfOp_fillAndStroke(PdfContext* pdfContext, SkCanvas* canvas, b
path.close();
}
canvas->setMatrix(pdfContext->fGraphicsState.fMatrix);
canvas->setMatrix(pdfContext->fGraphicsState.fCTM);
SkPaint paint;
@ -1131,7 +1131,7 @@ static PdfResult PdfOp_b_star(PdfContext* pdfContext, SkCanvas* canvas, PdfToken
}
static PdfResult PdfOp_n(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
canvas->setMatrix(pdfContext->fGraphicsState.fMatrix);
canvas->setMatrix(pdfContext->fGraphicsState.fCTM);
if (pdfContext->fGraphicsState.fHasClipPathToApply) {
#ifndef PDF_DEBUG_NO_CLIPING
canvas->clipPath(pdfContext->fGraphicsState.fClipPath, SkRegion::kIntersect_Op, true);
@ -1148,8 +1148,8 @@ static PdfResult PdfOp_n(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoope
static PdfResult PdfOp_BT(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
pdfContext->fGraphicsState.fTextBlock = true;
pdfContext->fGraphicsState.fMatrixTm = pdfContext->fGraphicsState.fMatrix;
pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fMatrix;
pdfContext->fGraphicsState.fMatrixTm = pdfContext->fGraphicsState.fCTM;
pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fCTM;
return kPartial_PdfResult;
}
@ -1162,15 +1162,7 @@ static PdfResult PdfOp_ET(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoop
return kPartial_PdfResult;
}
//font size Tf Set the text font, Tf
//, to font and the text font size, Tfs, to size. font is the name of a
//font resource in the Fontsubdictionary of the current resource dictionary; size is
//a number representing a scale factor. There is no initial value for either font or
//size; they must be specified explicitly using Tf before any text is shown.
static PdfResult PdfOp_Tf(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
pdfContext->fGraphicsState.fCurFontSize = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
SkPdfObject* fontName = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
PdfResult skpdfGraphicsStateApplyFontCore(PdfContext* pdfContext, const SkPdfObject* fontName, double fontSize) {
#ifdef PDF_TRACE
printf("font name: %s\n", fontName->nameValue2().c_str());
#endif
@ -1190,9 +1182,21 @@ static PdfResult PdfOp_Tf(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoop
pdfContext->fGraphicsState.fSkFont = skfont;
}
}
pdfContext->fGraphicsState.fCurFontSize = fontSize;
return kIgnoreError_PdfResult;
}
//font size Tf Set the text font, Tf
//, to font and the text font size, Tfs, to size. font is the name of a
//font resource in the Fontsubdictionary of the current resource dictionary; size is
//a number representing a scale factor. There is no initial value for either font or
//size; they must be specified explicitly using Tf before any text is shown.
static PdfResult PdfOp_Tf(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
double fontSize = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop();
SkPdfObject* fontName = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop();
return skpdfGraphicsStateApplyFontCore(pdfContext, fontName, fontSize);
}
static PdfResult PdfOp_Tj(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
if (!pdfContext->fGraphicsState.fTextBlock) {
// TODO(edisonn): try to recover and draw it any way?
@ -1519,6 +1523,89 @@ static PdfResult PdfOp_i(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoope
return kNYI_PdfResult;
}
// TODO(edisonn): security review here, make sure all parameters are valid, and safe.
void skpdfGraphicsStateApply_ca(PdfContext* pdfContext, double ca) {
pdfContext->fGraphicsState.fNonStroking.fOpacity = ca;
}
void skpdfGraphicsStateApply_CA(PdfContext* pdfContext, double CA) {
pdfContext->fGraphicsState.fStroking.fOpacity = CA;
}
void skpdfGraphicsStateApplyLW(PdfContext* pdfContext, double lineWidth) {
pdfContext->fGraphicsState.fLineWidth = lineWidth;
}
void skpdfGraphicsStateApplyLC(PdfContext* pdfContext, int64_t lineCap) {
pdfContext->fGraphicsState.fLineCap = (int)lineCap;
}
void skpdfGraphicsStateApplyLJ(PdfContext* pdfContext, int64_t lineJoin) {
pdfContext->fGraphicsState.fLineJoin = (int)lineJoin;
}
void skpdfGraphicsStateApplyML(PdfContext* pdfContext, double miterLimit) {
pdfContext->fGraphicsState.fMiterLimit = miterLimit;
}
void skpdfGraphicsStateApplyD(PdfContext* pdfContext, SkPdfArray* dash) {
// TODO(edisonn): verify input
if (!dash || dash->isArray() || dash->size() != 2 || !dash->objAtAIndex(0)->isArray() || !dash->objAtAIndex(1)->isNumber()) {
// TODO(edisonn): report error/warning
return;
}
SkPdfArray* intervals = (SkPdfArray*)dash->objAtAIndex(0);
int cnt = intervals->size();
if (cnt >= 256) {
// TODO(edisonn): report error/warning, unsuported;
// TODO(edisonn): alloc memory
return;
}
for (int i = 0; i < cnt; i++) {
if (!intervals->objAtAIndex(i)->isNumber()) {
// TODO(edisonn): report error/warning
return;
}
}
pdfContext->fGraphicsState.fDashPhase = dash->objAtAIndex(1)->scalarValue();
pdfContext->fGraphicsState.fDashArrayLength = cnt;
for (int i = 0 ; i < cnt; i++) {
pdfContext->fGraphicsState.fDashArray[i] = intervals->objAtAIndex(i)->scalarValue();
}
}
void skpdfGraphicsStateApplyFont(PdfContext* pdfContext, SkPdfArray* fontAndSize) {
if (!fontAndSize || fontAndSize->isArray() || fontAndSize->size() != 2 || !fontAndSize->objAtAIndex(0)->isName() || !fontAndSize->objAtAIndex(1)->isNumber()) {
// TODO(edisonn): report error/warning
return;
}
skpdfGraphicsStateApplyFontCore(pdfContext, fontAndSize->objAtAIndex(0), fontAndSize->objAtAIndex(1)->numberValue());
}
void skpdfGraphicsStateApplyBM_name(PdfContext* pdfContext, const std::string& blendMode) {
// TODO(edisonn): verify input
}
void skpdfGraphicsStateApplyBM_array(PdfContext* pdfContext, SkPdfArray* blendModes) {
// TODO(edisonn): verify input
}
void skpdfGraphicsStateApplySMask_name(PdfContext* pdfContext, const std::string& sMask) {
// TODO(edisonn): verify input
}
void skpdfGraphicsStateApplySMask_dict(PdfContext* pdfContext, SkPdfDictionary* sMask) {
// TODO(edisonn): verify input
}
void skpdfGraphicsStateApplyAIS(PdfContext* pdfContext, bool alphaSource) {
pdfContext->fGraphicsState.fAlphaSource = alphaSource;
}
//dictName gs (PDF 1.2) Set the specified parameters in the graphics state. dictName is
//the name of a graphics state parameter dictionary in the ExtGState subdictionary of the current resource dictionary (see the next section).
static PdfResult PdfOp_gs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
@ -1550,16 +1637,60 @@ static PdfResult PdfOp_gs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoop
return kIgnoreError_PdfResult;
}
if (gs->has_CA()) {
pdfContext->fGraphicsState.fStroking.fOpacity = gs->CA(pdfContext->fPdfDoc);
if (gs->has_LW()) {
skpdfGraphicsStateApplyLW(pdfContext, gs->LW(pdfContext->fPdfDoc));
}
if (gs->has_LC()) {
skpdfGraphicsStateApplyLC(pdfContext, gs->LC(pdfContext->fPdfDoc));
}
if (gs->has_LJ()) {
skpdfGraphicsStateApplyLJ(pdfContext, gs->LJ(pdfContext->fPdfDoc));
}
if (gs->has_ML()) {
skpdfGraphicsStateApplyML(pdfContext, gs->ML(pdfContext->fPdfDoc));
}
if (gs->has_D()) {
skpdfGraphicsStateApplyD(pdfContext, gs->D(pdfContext->fPdfDoc));
}
if (gs->has_Font()) {
skpdfGraphicsStateApplyFont(pdfContext, gs->Font(pdfContext->fPdfDoc));
}
if (gs->has_BM()) {
if (gs->isBMAName(pdfContext->fPdfDoc)) {
skpdfGraphicsStateApplyBM_name(pdfContext, gs->getBMAsName(pdfContext->fPdfDoc));
} else if (gs->isBMAArray(pdfContext->fPdfDoc)) {
skpdfGraphicsStateApplyBM_array(pdfContext, gs->getBMAsArray(pdfContext->fPdfDoc));
} else {
// TODO(edisonn): report/warn
}
}
if (gs->has_SMask()) {
if (gs->isSMaskAName(pdfContext->fPdfDoc)) {
skpdfGraphicsStateApplySMask_name(pdfContext, gs->getSMaskAsName(pdfContext->fPdfDoc));
} else if (gs->isSMaskADictionary(pdfContext->fPdfDoc)) {
skpdfGraphicsStateApplySMask_dict(pdfContext, gs->getSMaskAsDictionary(pdfContext->fPdfDoc));
} else {
// TODO(edisonn): report/warn
}
}
if (gs->has_ca()) {
pdfContext->fGraphicsState.fNonStroking.fOpacity = gs->ca(pdfContext->fPdfDoc);
skpdfGraphicsStateApply_ca(pdfContext, gs->ca(pdfContext->fPdfDoc));
}
if (gs->has_LW()) {
pdfContext->fGraphicsState.fLineWidth = gs->LW(pdfContext->fPdfDoc);
if (gs->has_CA()) {
skpdfGraphicsStateApply_CA(pdfContext, gs->CA(pdfContext->fPdfDoc));
}
if (gs->has_AIS()) {
skpdfGraphicsStateApplyAIS(pdfContext, gs->AIS(pdfContext->fPdfDoc));
}
return kNYI_PdfResult;
@ -1993,9 +2124,9 @@ bool SkPdfRenderer::renderPage(int page, SkCanvas* canvas, const SkRect& dst) co
SkTraceMatrix(pdfContext.fOriginalMatrix, "Original matrix");
pdfContext.fGraphicsState.fMatrix = pdfContext.fOriginalMatrix;
pdfContext.fGraphicsState.fMatrixTm = pdfContext.fGraphicsState.fMatrix;
pdfContext.fGraphicsState.fMatrixTlm = pdfContext.fGraphicsState.fMatrix;
pdfContext.fGraphicsState.fCTM = pdfContext.fOriginalMatrix;
pdfContext.fGraphicsState.fMatrixTm = pdfContext.fGraphicsState.fCTM;
pdfContext.fGraphicsState.fMatrixTlm = pdfContext.fGraphicsState.fCTM;
#ifndef PDF_DEBUG_NO_PAGE_CLIPING
canvas->clipRect(dst, SkRegion::kIntersect_Op, true);

View File

@ -607,6 +607,17 @@ public:
return fObjectType == kReal_PdfObjectType ? fRealValue : fIntegerValue;
}
inline SkScalar scalarValue() const {
SkASSERT(isNumber());
if (!isNumber()) {
// TODO(edisonn): log err
return SkIntToScalar(0);
}
return fObjectType == kReal_PdfObjectType ? SkDoubleToScalar(fRealValue) :
SkIntToScalar(fIntegerValue);
}
int referenceId() const {
SkASSERT(fObjectType == kReference_PdfObjectType);
return fRef.fId;

View File

@ -71,6 +71,7 @@
],
'dependencies': [
'core.gyp:core',
'effects.gyp:effects',
'images.gyp:images',
'zlib.gyp:zlib',
],