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
diff --git a/experimental/PdfViewer/SkPdfBasics.cpp b/experimental/PdfViewer/SkPdfBasics.cpp
index e689b14..dc320a5 100644
--- a/experimental/PdfViewer/SkPdfBasics.cpp
+++ b/experimental/PdfViewer/SkPdfBasics.cpp
@@ -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() {
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();
+ }
+ }
+}
diff --git a/experimental/PdfViewer/SkPdfBasics.h b/experimental/PdfViewer/SkPdfBasics.h
index 31fc2cd..752a714 100644
--- a/experimental/PdfViewer/SkPdfBasics.h
+++ b/experimental/PdfViewer/SkPdfBasics.h
@@ -20,8 +20,28 @@
// 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 @@
// 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 @@
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 @@
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 flag 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 flag specifying whether the current soft mask and alpha
+ constant parameters are to be interpreted as shape values (true) or
+ opacity values (false). This flag 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 flag 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.
+ */
+
+
+/*
+flatness 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 @@
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.
diff --git a/experimental/PdfViewer/SkPdfRenderer.cpp b/experimental/PdfViewer/SkPdfRenderer.cpp
index c51c239..a36d363 100644
--- a/experimental/PdfViewer/SkPdfRenderer.cpp
+++ b/experimental/PdfViewer/SkPdfRenderer.cpp
@@ -598,7 +598,7 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
printf("%f ", array[i]);
}
printf("\n");
- SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "cm");
+ SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "cm");
#endif
return kOK_PdfResult;
@@ -889,7 +889,7 @@
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 @@
path.close();
}
- canvas->setMatrix(pdfContext->fGraphicsState.fMatrix);
+ canvas->setMatrix(pdfContext->fGraphicsState.fCTM);
SkPaint paint;
@@ -1131,7 +1131,7 @@
}
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_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 @@
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 @@
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 @@
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 @@
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 @@
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);
diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfObject.h b/experimental/PdfViewer/pdfparser/native/SkPdfObject.h
index c670ac8..5525f7b 100644
--- a/experimental/PdfViewer/pdfparser/native/SkPdfObject.h
+++ b/experimental/PdfViewer/pdfparser/native/SkPdfObject.h
@@ -607,6 +607,17 @@
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;