Index: experimental/PdfViewer/SkPdfRenderer.cpp |
=================================================================== |
--- experimental/PdfViewer/SkPdfRenderer.cpp (revision 10498) |
+++ experimental/PdfViewer/SkPdfRenderer.cpp (working copy) |
@@ -739,6 +739,64 @@ |
return kPartial_PdfResult; |
} |
+ |
+// TODO(edisonn): Extract a class like ObjWithStream |
+static PdfResult doXObject_Pattern(PdfContext* pdfContext, SkCanvas* canvas, SkPdfType1PatternDictionary* skobj) { |
+ if (!skobj || !skobj->hasStream()) { |
+ return kIgnoreError_PdfResult; |
+ } |
+ |
+ if (!skobj->has_BBox()) { |
+ return kIgnoreError_PdfResult; |
+ } |
+ |
+ PdfOp_q(pdfContext, canvas, NULL); |
+ |
+ canvas->save(); |
+ |
+ |
+ if (skobj->Resources(pdfContext->fPdfDoc)) { |
+ pdfContext->fGraphicsState.fResources = skobj->Resources(pdfContext->fPdfDoc); |
+ } |
+ |
+ SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "Current matrix"); |
+ |
+ if (skobj->has_Matrix()) { |
+ 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.fCTM, "Total matrix"); |
+ |
+ canvas->setMatrix(pdfContext->fGraphicsState.fCTM); |
+ |
+ SkRect bbox = skobj->BBox(pdfContext->fPdfDoc); |
+ canvas->clipRect(bbox, SkRegion::kIntersect_Op, true); // TODO(edisonn): AA from settings. |
+ |
+ // TODO(edisonn): iterate smart on the stream even if it is compressed, tokenize it as we go. |
+ // For this PdfContentsTokenizer needs to be extended. |
+ |
+ SkPdfStream* stream = (SkPdfStream*)skobj; |
+ |
+ SkPdfNativeTokenizer* tokenizer = |
+ pdfContext->fPdfDoc->tokenizerOfStream(stream, pdfContext->fTmpPageAllocator); |
+ if (tokenizer != NULL) { |
+ PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas); |
+ looper.loop(); |
+ delete tokenizer; |
+ } |
+ |
+ // TODO(edisonn): should we restore the variable stack at the same state? |
+ // There could be operands left, that could be consumed by a parent tokenizer when we pop. |
+ |
+ canvas->restore(); |
+ PdfOp_Q(pdfContext, canvas, NULL); |
+ return kPartial_PdfResult; |
+} |
+ |
+ |
//static PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObject* obj) { |
// return kNYI_PdfResult; |
//} |
@@ -826,9 +884,14 @@ |
return doXObject_Form(pdfContext, canvas, (SkPdfType1FormDictionary*)obj); |
//case kObjectDictionaryXObjectPS_SkPdfObjectType: |
//return doXObject_PS(skxobj.asPS()); |
- default: |
- return kIgnoreError_PdfResult; |
+ default: { |
+ if (pdfContext->fPdfDoc->mapper()->mapType1PatternDictionary(obj) != kNone_SkPdfObjectType) { |
+ SkPdfType1PatternDictionary* pattern = (SkPdfType1PatternDictionary*)obj; |
+ return doXObject_Pattern(pdfContext, canvas, pattern); |
+ } |
+ } |
} |
+ return kIgnoreError_PdfResult; |
} |
static PdfResult doPage(PdfContext* pdfContext, SkCanvas* canvas, SkPdfPageObjectDictionary* skobj) { |
@@ -1165,29 +1228,100 @@ |
if (fill && !stroke && path.isLine(line)) { |
paint.setStyle(SkPaint::kStroke_Style); |
+ // TODO(edisonn): implement this with patterns |
pdfContext->fGraphicsState.applyGraphicsState(&paint, false); |
paint.setStrokeWidth(SkDoubleToScalar(0)); |
canvas->drawPath(path, paint); |
} else { |
if (fill) { |
- paint.setStyle(SkPaint::kFill_Style); |
- if (evenOdd) { |
- path.setFillType(SkPath::kEvenOdd_FillType); |
- } |
+ if (strncmp((char*)pdfContext->fGraphicsState.fNonStroking.fColorSpace.fBuffer, "Pattern", strlen("Pattern")) == 0 && |
+ pdfContext->fGraphicsState.fNonStroking.fPattern != NULL) { |
- pdfContext->fGraphicsState.applyGraphicsState(&paint, false); |
+ // TODO(edisonn): we can use a shader here, like imageshader to draw fast. ultimately, |
+ // if this is not possible, and we are in rasper mode, and the cells don't intersect, we could even have multiple cpus. |
- canvas->drawPath(path, paint); |
+ canvas->save(); |
+ PdfOp_q(pdfContext, canvas, NULL); |
+ |
+ if (evenOdd) { |
+ path.setFillType(SkPath::kEvenOdd_FillType); |
+ } |
+ canvas->clipPath(path); |
+ |
+ if (pdfContext->fPdfDoc->mapper()->mapType1PatternDictionary(pdfContext->fGraphicsState.fNonStroking.fPattern) != kNone_SkPdfObjectType) { |
+ SkPdfType1PatternDictionary* pattern = (SkPdfType1PatternDictionary*)pdfContext->fGraphicsState.fNonStroking.fPattern; |
+ |
+ // TODO(edisonn): constants |
+ // TODO(edisonn): colored |
+ if (pattern->PaintType(pdfContext->fPdfDoc) == 1) { |
+ int xStep = (int)pattern->XStep(pdfContext->fPdfDoc); |
+ int yStep = (int)pattern->YStep(pdfContext->fPdfDoc); |
+ |
+ SkRect bounds = path.getBounds(); |
+ SkScalar x; |
+ SkScalar y; |
+ |
+ // TODO(edisonn): xstep and ystep can be negative, and we need to iterate in reverse |
+ |
+ y = bounds.top(); |
+ int totalx = 0; |
+ int totaly = 0; |
+ while (y < bounds.bottom()) { |
+ x = bounds.left(); |
+ totalx = 0; |
+ |
+ while (x < bounds.right()) { |
+ doXObject(pdfContext, canvas, pattern); |
+ |
+ pdfContext->fGraphicsState.fCTM.preTranslate(SkIntToScalar(xStep), SkIntToScalar(0)); |
+ totalx += xStep; |
+ x += SkIntToScalar(xStep); |
+ } |
+ pdfContext->fGraphicsState.fCTM.preTranslate(SkIntToScalar(-totalx), SkIntToScalar(0)); |
+ |
+ pdfContext->fGraphicsState.fCTM.preTranslate(SkIntToScalar(0), SkIntToScalar(-yStep)); |
+ totaly += yStep; |
+ y += SkIntToScalar(yStep); |
+ } |
+ pdfContext->fGraphicsState.fCTM.preTranslate(SkIntToScalar(0), SkIntToScalar(totaly)); |
+ } |
+ } |
+ |
+ // apply matrix |
+ // get xstep, y step, bbox ... for cliping, and bos of the path |
+ |
+ PdfOp_Q(pdfContext, canvas, NULL); |
+ canvas->restore(); |
+ } else { |
+ paint.setStyle(SkPaint::kFill_Style); |
+ if (evenOdd) { |
+ path.setFillType(SkPath::kEvenOdd_FillType); |
+ } |
+ |
+ pdfContext->fGraphicsState.applyGraphicsState(&paint, false); |
+ |
+ canvas->drawPath(path, paint); |
+ } |
} |
if (stroke) { |
- paint.setStyle(SkPaint::kStroke_Style); |
+ if (false && strncmp((char*)pdfContext->fGraphicsState.fNonStroking.fColorSpace.fBuffer, "Pattern", strlen("Pattern")) == 0) { |
+ // TODO(edisonn): implement Pattern for strokes |
+ paint.setStyle(SkPaint::kStroke_Style); |
- pdfContext->fGraphicsState.applyGraphicsState(&paint, true); |
+ paint.setColor(SK_ColorGREEN); |
- path.setFillType(SkPath::kWinding_FillType); // reset it, just in case it messes up the stroke |
- canvas->drawPath(path, paint); |
+ path.setFillType(SkPath::kWinding_FillType); // reset it, just in case it messes up the stroke |
+ canvas->drawPath(path, paint); |
+ } else { |
+ paint.setStyle(SkPaint::kStroke_Style); |
+ |
+ pdfContext->fGraphicsState.applyGraphicsState(&paint, true); |
+ |
+ path.setFillType(SkPath::kWinding_FillType); // reset it, just in case it messes up the stroke |
+ canvas->drawPath(path, paint); |
+ } |
} |
} |
@@ -1459,16 +1593,16 @@ |
SkPdfObject* name = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop(); |
//Next, get the ExtGState Dictionary from the Resource Dictionary: |
- SkPdfDictionary* extGStateDictionary = pdfContext->fGraphicsState.fResources->Pattern(pdfContext->fPdfDoc); |
+ SkPdfDictionary* patternResources = pdfContext->fGraphicsState.fResources->Pattern(pdfContext->fPdfDoc); |
- if (extGStateDictionary == NULL) { |
+ if (patternResources == NULL) { |
#ifdef PDF_TRACE |
printf("ExtGState is NULL!\n"); |
#endif |
return kIgnoreError_PdfResult; |
} |
- /*SkPdfObject* value = */pdfContext->fPdfDoc->resolveReference(extGStateDictionary->get(name)); |
+ colorOperator->setPatternColorSpace(pdfContext->fPdfDoc->resolveReference(patternResources->get(name))); |
} |
// TODO(edisonn): SCN supports more color spaces than SCN. Read and implement spec. |
@@ -2262,21 +2396,6 @@ |
} |
PdfResult PdfInlineImageLooper::done() { |
- |
- // TODO(edisonn): long to short names |
- // TODO(edisonn): set properties in a map |
- // TODO(edisonn): extract bitmap stream, check if PoDoFo has public utilities to uncompress |
- // the stream. |
- |
- SkBitmap bitmap; |
- setup_bitmap(&bitmap, 50, 50, SK_ColorRED); |
- |
- // TODO(edisonn): matrix use. |
- // Draw dummy red square, to show the prezence of the inline image. |
- fCanvas->drawBitmap(bitmap, |
- SkDoubleToScalar(0), |
- SkDoubleToScalar(0), |
- NULL); |
return kNYI_PdfResult; |
} |