| 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; | 
| } | 
|  | 
|  |