SkPDFDevice.cpp revision 15a140599942f70e47380e3f700a825c7cece3b4
1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkPDFDevice.h"
9
10#include "SkAnnotation.h"
11#include "SkColor.h"
12#include "SkClipStack.h"
13#include "SkData.h"
14#include "SkDraw.h"
15#include "SkFontHost.h"
16#include "SkGlyphCache.h"
17#include "SkPaint.h"
18#include "SkPath.h"
19#include "SkPathOps.h"
20#include "SkPDFFont.h"
21#include "SkPDFFormXObject.h"
22#include "SkPDFGraphicState.h"
23#include "SkPDFImage.h"
24#include "SkPDFResourceDict.h"
25#include "SkPDFShader.h"
26#include "SkPDFStream.h"
27#include "SkPDFTypes.h"
28#include "SkPDFUtils.h"
29#include "SkRect.h"
30#include "SkRRect.h"
31#include "SkString.h"
32#include "SkTextFormatParams.h"
33#include "SkTemplates.h"
34#include "SkTypefacePriv.h"
35#include "SkTSet.h"
36
37#ifdef SK_BUILD_FOR_ANDROID
38#include "SkTypeface_android.h"
39
40struct TypefaceFallbackData {
41    SkTypeface* typeface;
42    int lowerBounds;
43    int upperBounds;
44
45    bool operator==(const TypefaceFallbackData& b) const {
46        return typeface == b.typeface &&
47               lowerBounds == b.lowerBounds &&
48               upperBounds == b.upperBounds;
49    }
50};
51#endif
52
53#define DPI_FOR_RASTER_SCALE_ONE 72
54
55// Utility functions
56
57static void emit_pdf_color(SkColor color, SkWStream* result) {
58    SkASSERT(SkColorGetA(color) == 0xFF);  // We handle alpha elsewhere.
59    SkScalar colorMax = SkIntToScalar(0xFF);
60    SkPDFScalar::Append(
61            SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result);
62    result->writeText(" ");
63    SkPDFScalar::Append(
64            SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result);
65    result->writeText(" ");
66    SkPDFScalar::Append(
67            SkScalarDiv(SkIntToScalar(SkColorGetB(color)), colorMax), result);
68    result->writeText(" ");
69}
70
71static SkPaint calculate_text_paint(const SkPaint& paint) {
72    SkPaint result = paint;
73    if (result.isFakeBoldText()) {
74        SkScalar fakeBoldScale = SkScalarInterpFunc(result.getTextSize(),
75                                                    kStdFakeBoldInterpKeys,
76                                                    kStdFakeBoldInterpValues,
77                                                    kStdFakeBoldInterpLength);
78        SkScalar width = SkScalarMul(result.getTextSize(), fakeBoldScale);
79        if (result.getStyle() == SkPaint::kFill_Style) {
80            result.setStyle(SkPaint::kStrokeAndFill_Style);
81        } else {
82            width += result.getStrokeWidth();
83        }
84        result.setStrokeWidth(width);
85    }
86    return result;
87}
88
89// Stolen from measure_text in SkDraw.cpp and then tweaked.
90static void align_text(SkDrawCacheProc glyphCacheProc, const SkPaint& paint,
91                       const uint16_t* glyphs, size_t len,
92                       SkScalar* x, SkScalar* y) {
93    if (paint.getTextAlign() == SkPaint::kLeft_Align) {
94        return;
95    }
96
97    SkMatrix ident;
98    ident.reset();
99    SkAutoGlyphCache autoCache(paint, NULL, &ident);
100    SkGlyphCache* cache = autoCache.getCache();
101
102    const char* start = reinterpret_cast<const char*>(glyphs);
103    const char* stop = reinterpret_cast<const char*>(glyphs + len);
104    SkFixed xAdv = 0, yAdv = 0;
105
106    // TODO(vandebo): This probably needs to take kerning into account.
107    while (start < stop) {
108        const SkGlyph& glyph = glyphCacheProc(cache, &start, 0, 0);
109        xAdv += glyph.fAdvanceX;
110        yAdv += glyph.fAdvanceY;
111    };
112    if (paint.getTextAlign() == SkPaint::kLeft_Align) {
113        return;
114    }
115
116    SkScalar xAdj = SkFixedToScalar(xAdv);
117    SkScalar yAdj = SkFixedToScalar(yAdv);
118    if (paint.getTextAlign() == SkPaint::kCenter_Align) {
119        xAdj = SkScalarHalf(xAdj);
120        yAdj = SkScalarHalf(yAdj);
121    }
122    *x = *x - xAdj;
123    *y = *y - yAdj;
124}
125
126static int max_glyphid_for_typeface(SkTypeface* typeface) {
127    SkAutoResolveDefaultTypeface autoResolve(typeface);
128    typeface = autoResolve.get();
129    return typeface->countGlyphs() - 1;
130}
131
132typedef SkAutoSTMalloc<128, uint16_t> SkGlyphStorage;
133
134static size_t force_glyph_encoding(const SkPaint& paint, const void* text,
135                                   size_t len, SkGlyphStorage* storage,
136                                   uint16_t** glyphIDs) {
137    // Make sure we have a glyph id encoding.
138    if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
139        size_t numGlyphs = paint.textToGlyphs(text, len, NULL);
140        storage->reset(numGlyphs);
141        paint.textToGlyphs(text, len, storage->get());
142        *glyphIDs = storage->get();
143        return numGlyphs;
144    }
145
146    // For user supplied glyph ids we need to validate them.
147    SkASSERT((len & 1) == 0);
148    size_t numGlyphs = len / 2;
149    const uint16_t* input =
150        reinterpret_cast<uint16_t*>(const_cast<void*>((text)));
151
152    int maxGlyphID = max_glyphid_for_typeface(paint.getTypeface());
153    size_t validated;
154    for (validated = 0; validated < numGlyphs; ++validated) {
155        if (input[validated] > maxGlyphID) {
156            break;
157        }
158    }
159    if (validated >= numGlyphs) {
160        *glyphIDs = reinterpret_cast<uint16_t*>(const_cast<void*>((text)));
161        return numGlyphs;
162    }
163
164    // Silently drop anything out of range.
165    storage->reset(numGlyphs);
166    if (validated > 0) {
167        memcpy(storage->get(), input, validated * sizeof(uint16_t));
168    }
169
170    for (size_t i = validated; i < numGlyphs; ++i) {
171        storage->get()[i] = input[i];
172        if (input[i] > maxGlyphID) {
173            storage->get()[i] = 0;
174        }
175    }
176    *glyphIDs = storage->get();
177    return numGlyphs;
178}
179
180static void set_text_transform(SkScalar x, SkScalar y, SkScalar textSkewX,
181                               SkWStream* content) {
182    // Flip the text about the x-axis to account for origin swap and include
183    // the passed parameters.
184    content->writeText("1 0 ");
185    SkPDFScalar::Append(0 - textSkewX, content);
186    content->writeText(" -1 ");
187    SkPDFScalar::Append(x, content);
188    content->writeText(" ");
189    SkPDFScalar::Append(y, content);
190    content->writeText(" Tm\n");
191}
192
193// It is important to not confuse GraphicStateEntry with SkPDFGraphicState, the
194// later being our representation of an object in the PDF file.
195struct GraphicStateEntry {
196    GraphicStateEntry();
197
198    // Compare the fields we care about when setting up a new content entry.
199    bool compareInitialState(const GraphicStateEntry& b);
200
201    SkMatrix fMatrix;
202    // We can't do set operations on Paths, though PDF natively supports
203    // intersect.  If the clip stack does anything other than intersect,
204    // we have to fall back to the region.  Treat fClipStack as authoritative.
205    // See http://code.google.com/p/skia/issues/detail?id=221
206    SkClipStack fClipStack;
207    SkRegion fClipRegion;
208
209    // When emitting the content entry, we will ensure the graphic state
210    // is set to these values first.
211    SkColor fColor;
212    SkScalar fTextScaleX;  // Zero means we don't care what the value is.
213    SkPaint::Style fTextFill;  // Only if TextScaleX is non-zero.
214    int fShaderIndex;
215    int fGraphicStateIndex;
216
217    // We may change the font (i.e. for Type1 support) within a
218    // ContentEntry.  This is the one currently in effect, or NULL if none.
219    SkPDFFont* fFont;
220    // In PDF, text size has no default value. It is only valid if fFont is
221    // not NULL.
222    SkScalar fTextSize;
223};
224
225GraphicStateEntry::GraphicStateEntry() : fColor(SK_ColorBLACK),
226                                         fTextScaleX(SK_Scalar1),
227                                         fTextFill(SkPaint::kFill_Style),
228                                         fShaderIndex(-1),
229                                         fGraphicStateIndex(-1),
230                                         fFont(NULL),
231                                         fTextSize(SK_ScalarNaN) {
232    fMatrix.reset();
233}
234
235bool GraphicStateEntry::compareInitialState(const GraphicStateEntry& cur) {
236    return fColor == cur.fColor &&
237           fShaderIndex == cur.fShaderIndex &&
238           fGraphicStateIndex == cur.fGraphicStateIndex &&
239           fMatrix == cur.fMatrix &&
240           fClipStack == cur.fClipStack &&
241           (fTextScaleX == 0 ||
242               (fTextScaleX == cur.fTextScaleX && fTextFill == cur.fTextFill));
243}
244
245class GraphicStackState {
246public:
247    GraphicStackState(const SkClipStack& existingClipStack,
248                      const SkRegion& existingClipRegion,
249                      SkWStream* contentStream)
250            : fStackDepth(0),
251              fContentStream(contentStream) {
252        fEntries[0].fClipStack = existingClipStack;
253        fEntries[0].fClipRegion = existingClipRegion;
254    }
255
256    void updateClip(const SkClipStack& clipStack, const SkRegion& clipRegion,
257                    const SkPoint& translation);
258    void updateMatrix(const SkMatrix& matrix);
259    void updateDrawingState(const GraphicStateEntry& state);
260
261    void drainStack();
262
263private:
264    void push();
265    void pop();
266    GraphicStateEntry* currentEntry() { return &fEntries[fStackDepth]; }
267
268    // Conservative limit on save depth, see impl. notes in PDF 1.4 spec.
269    static const int kMaxStackDepth = 12;
270    GraphicStateEntry fEntries[kMaxStackDepth + 1];
271    int fStackDepth;
272    SkWStream* fContentStream;
273};
274
275void GraphicStackState::drainStack() {
276    while (fStackDepth) {
277        pop();
278    }
279}
280
281void GraphicStackState::push() {
282    SkASSERT(fStackDepth < kMaxStackDepth);
283    fContentStream->writeText("q\n");
284    fStackDepth++;
285    fEntries[fStackDepth] = fEntries[fStackDepth - 1];
286}
287
288void GraphicStackState::pop() {
289    SkASSERT(fStackDepth > 0);
290    fContentStream->writeText("Q\n");
291    fStackDepth--;
292}
293
294// This function initializes iter to be an iterator on the "stack" argument
295// and then skips over the leading entries as specified in prefix.  It requires
296// and asserts that "prefix" will be a prefix to "stack."
297static void skip_clip_stack_prefix(const SkClipStack& prefix,
298                                   const SkClipStack& stack,
299                                   SkClipStack::Iter* iter) {
300    SkClipStack::B2TIter prefixIter(prefix);
301    iter->reset(stack, SkClipStack::Iter::kBottom_IterStart);
302
303    const SkClipStack::Element* prefixEntry;
304    const SkClipStack::Element* iterEntry;
305
306    for (prefixEntry = prefixIter.next(); prefixEntry;
307            prefixEntry = prefixIter.next()) {
308        iterEntry = iter->next();
309        SkASSERT(iterEntry);
310        // Because of SkClipStack does internal intersection, the last clip
311        // entry may differ.
312        if (*prefixEntry != *iterEntry) {
313            SkASSERT(prefixEntry->getOp() == SkRegion::kIntersect_Op);
314            SkASSERT(iterEntry->getOp() == SkRegion::kIntersect_Op);
315            SkASSERT(iterEntry->getType() == prefixEntry->getType());
316            // back up the iterator by one
317            iter->prev();
318            prefixEntry = prefixIter.next();
319            break;
320        }
321    }
322
323    SkASSERT(prefixEntry == NULL);
324}
325
326static void emit_clip(SkPath* clipPath, SkRect* clipRect,
327                      SkWStream* contentStream) {
328    SkASSERT(clipPath || clipRect);
329
330    SkPath::FillType clipFill;
331    if (clipPath) {
332        SkPDFUtils::EmitPath(*clipPath, SkPaint::kFill_Style, contentStream);
333        clipFill = clipPath->getFillType();
334    } else {
335        SkPDFUtils::AppendRectangle(*clipRect, contentStream);
336        clipFill = SkPath::kWinding_FillType;
337    }
338
339    NOT_IMPLEMENTED(clipFill == SkPath::kInverseEvenOdd_FillType, false);
340    NOT_IMPLEMENTED(clipFill == SkPath::kInverseWinding_FillType, false);
341    if (clipFill == SkPath::kEvenOdd_FillType) {
342        contentStream->writeText("W* n\n");
343    } else {
344        contentStream->writeText("W n\n");
345    }
346}
347
348#ifdef SK_PDF_USE_PATHOPS
349/* Calculate an inverted path's equivalent non-inverted path, given the
350 * canvas bounds.
351 * outPath may alias with invPath (since this is supported by PathOps).
352 */
353static bool calculate_inverse_path(const SkRect& bounds, const SkPath& invPath,
354                                   SkPath* outPath) {
355    SkASSERT(invPath.isInverseFillType());
356
357    SkPath clipPath;
358    clipPath.addRect(bounds);
359
360    return Op(clipPath, invPath, kIntersect_PathOp, outPath);
361}
362
363// Sanity check the numerical values of the SkRegion ops and PathOps ops
364// enums so region_op_to_pathops_op can do a straight passthrough cast.
365// If these are failing, it may be necessary to make region_op_to_pathops_op
366// do more.
367SK_COMPILE_ASSERT(SkRegion::kDifference_Op == (int)kDifference_PathOp,
368                  region_pathop_mismatch);
369SK_COMPILE_ASSERT(SkRegion::kIntersect_Op == (int)kIntersect_PathOp,
370                  region_pathop_mismatch);
371SK_COMPILE_ASSERT(SkRegion::kUnion_Op == (int)kUnion_PathOp,
372                  region_pathop_mismatch);
373SK_COMPILE_ASSERT(SkRegion::kXOR_Op == (int)kXOR_PathOp,
374                  region_pathop_mismatch);
375SK_COMPILE_ASSERT(SkRegion::kReverseDifference_Op ==
376                  (int)kReverseDifference_PathOp,
377                  region_pathop_mismatch);
378
379static SkPathOp region_op_to_pathops_op(SkRegion::Op op) {
380    SkASSERT(op >= 0);
381    SkASSERT(op <= SkRegion::kReverseDifference_Op);
382    return (SkPathOp)op;
383}
384
385/* Uses Path Ops to calculate a vector SkPath clip from a clip stack.
386 * Returns true if successful, or false if not successful.
387 * If successful, the resulting clip is stored in outClipPath.
388 * If not successful, outClipPath is undefined, and a fallback method
389 * should be used.
390 */
391static bool get_clip_stack_path(const SkMatrix& transform,
392                                const SkClipStack& clipStack,
393                                const SkRegion& clipRegion,
394                                SkPath* outClipPath) {
395    outClipPath->reset();
396    outClipPath->setFillType(SkPath::kInverseWinding_FillType);
397
398    const SkClipStack::Element* clipEntry;
399    SkClipStack::Iter iter;
400    iter.reset(clipStack, SkClipStack::Iter::kBottom_IterStart);
401    for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
402        SkPath entryPath;
403        if (SkClipStack::Element::kEmpty_Type == clipEntry->getType()) {
404            outClipPath->reset();
405            outClipPath->setFillType(SkPath::kInverseWinding_FillType);
406            continue;
407        } else if (SkClipStack::Element::kRect_Type == clipEntry->getType()) {
408            entryPath.addRect(clipEntry->getRect());
409        } else if (SkClipStack::Element::kPath_Type == clipEntry->getType()) {
410            entryPath = clipEntry->getPath();
411        }
412        entryPath.transform(transform);
413
414        if (SkRegion::kReplace_Op == clipEntry->getOp()) {
415            *outClipPath = entryPath;
416        } else {
417            SkPathOp op = region_op_to_pathops_op(clipEntry->getOp());
418            if (!Op(*outClipPath, entryPath, op, outClipPath)) {
419                return false;
420            }
421        }
422    }
423
424    if (outClipPath->isInverseFillType()) {
425        // The bounds are slightly outset to ensure this is correct in the
426        // face of floating-point accuracy and possible SkRegion bitmap
427        // approximations.
428        SkRect clipBounds = SkRect::Make(clipRegion.getBounds());
429        clipBounds.outset(SK_Scalar1, SK_Scalar1);
430        if (!calculate_inverse_path(clipBounds, *outClipPath, outClipPath)) {
431            return false;
432        }
433    }
434    return true;
435}
436#endif
437
438// TODO(vandebo): Take advantage of SkClipStack::getSaveCount(), the PDF
439// graphic state stack, and the fact that we can know all the clips used
440// on the page to optimize this.
441void GraphicStackState::updateClip(const SkClipStack& clipStack,
442                                   const SkRegion& clipRegion,
443                                   const SkPoint& translation) {
444    if (clipStack == currentEntry()->fClipStack) {
445        return;
446    }
447
448    while (fStackDepth > 0) {
449        pop();
450        if (clipStack == currentEntry()->fClipStack) {
451            return;
452        }
453    }
454    push();
455
456    currentEntry()->fClipStack = clipStack;
457    currentEntry()->fClipRegion = clipRegion;
458
459    SkMatrix transform;
460    transform.setTranslate(translation.fX, translation.fY);
461
462#ifdef SK_PDF_USE_PATHOPS
463    SkPath clipPath;
464    if (get_clip_stack_path(transform, clipStack, clipRegion, &clipPath)) {
465        emit_clip(&clipPath, NULL, fContentStream);
466        return;
467    }
468#endif
469    // gsState->initialEntry()->fClipStack/Region specifies the clip that has
470    // already been applied.  (If this is a top level device, then it specifies
471    // a clip to the content area.  If this is a layer, then it specifies
472    // the clip in effect when the layer was created.)  There's no need to
473    // reapply that clip; SKCanvas's SkDrawIter will draw anything outside the
474    // initial clip on the parent layer.  (This means there's a bug if the user
475    // expands the clip and then uses any xfer mode that uses dst:
476    // http://code.google.com/p/skia/issues/detail?id=228 )
477    SkClipStack::Iter iter;
478    skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
479
480    // If the clip stack does anything other than intersect or if it uses
481    // an inverse fill type, we have to fall back to the clip region.
482    bool needRegion = false;
483    const SkClipStack::Element* clipEntry;
484    for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
485        if (clipEntry->getOp() != SkRegion::kIntersect_Op ||
486                clipEntry->isInverseFilled()) {
487            needRegion = true;
488            break;
489        }
490    }
491
492    if (needRegion) {
493        SkPath clipPath;
494        SkAssertResult(clipRegion.getBoundaryPath(&clipPath));
495        emit_clip(&clipPath, NULL, fContentStream);
496    } else {
497        skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
498        const SkClipStack::Element* clipEntry;
499        for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
500            SkASSERT(clipEntry->getOp() == SkRegion::kIntersect_Op);
501            switch (clipEntry->getType()) {
502                case SkClipStack::Element::kRect_Type: {
503                    SkRect translatedClip;
504                    transform.mapRect(&translatedClip, clipEntry->getRect());
505                    emit_clip(NULL, &translatedClip, fContentStream);
506                    break;
507                }
508                case SkClipStack::Element::kPath_Type: {
509                    SkPath translatedPath;
510                    clipEntry->getPath().transform(transform, &translatedPath);
511                    emit_clip(&translatedPath, NULL, fContentStream);
512                    break;
513                }
514                default:
515                    SkASSERT(false);
516            }
517        }
518    }
519}
520
521void GraphicStackState::updateMatrix(const SkMatrix& matrix) {
522    if (matrix == currentEntry()->fMatrix) {
523        return;
524    }
525
526    if (currentEntry()->fMatrix.getType() != SkMatrix::kIdentity_Mask) {
527        SkASSERT(fStackDepth > 0);
528        SkASSERT(fEntries[fStackDepth].fClipStack ==
529                 fEntries[fStackDepth -1].fClipStack);
530        pop();
531
532        SkASSERT(currentEntry()->fMatrix.getType() == SkMatrix::kIdentity_Mask);
533    }
534    if (matrix.getType() == SkMatrix::kIdentity_Mask) {
535        return;
536    }
537
538    push();
539    SkPDFUtils::AppendTransform(matrix, fContentStream);
540    currentEntry()->fMatrix = matrix;
541}
542
543void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) {
544    // PDF treats a shader as a color, so we only set one or the other.
545    if (state.fShaderIndex >= 0) {
546        if (state.fShaderIndex != currentEntry()->fShaderIndex) {
547            SkPDFUtils::ApplyPattern(state.fShaderIndex, fContentStream);
548            currentEntry()->fShaderIndex = state.fShaderIndex;
549        }
550    } else {
551        if (state.fColor != currentEntry()->fColor ||
552                currentEntry()->fShaderIndex >= 0) {
553            emit_pdf_color(state.fColor, fContentStream);
554            fContentStream->writeText("RG ");
555            emit_pdf_color(state.fColor, fContentStream);
556            fContentStream->writeText("rg\n");
557            currentEntry()->fColor = state.fColor;
558            currentEntry()->fShaderIndex = -1;
559        }
560    }
561
562    if (state.fGraphicStateIndex != currentEntry()->fGraphicStateIndex) {
563        SkPDFUtils::ApplyGraphicState(state.fGraphicStateIndex, fContentStream);
564        currentEntry()->fGraphicStateIndex = state.fGraphicStateIndex;
565    }
566
567    if (state.fTextScaleX) {
568        if (state.fTextScaleX != currentEntry()->fTextScaleX) {
569            SkScalar pdfScale = SkScalarMul(state.fTextScaleX,
570                                            SkIntToScalar(100));
571            SkPDFScalar::Append(pdfScale, fContentStream);
572            fContentStream->writeText(" Tz\n");
573            currentEntry()->fTextScaleX = state.fTextScaleX;
574        }
575        if (state.fTextFill != currentEntry()->fTextFill) {
576            SK_COMPILE_ASSERT(SkPaint::kFill_Style == 0, enum_must_match_value);
577            SK_COMPILE_ASSERT(SkPaint::kStroke_Style == 1,
578                              enum_must_match_value);
579            SK_COMPILE_ASSERT(SkPaint::kStrokeAndFill_Style == 2,
580                              enum_must_match_value);
581            fContentStream->writeDecAsText(state.fTextFill);
582            fContentStream->writeText(" Tr\n");
583            currentEntry()->fTextFill = state.fTextFill;
584        }
585    }
586}
587
588SkBaseDevice* SkPDFDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
589    SkMatrix initialTransform;
590    initialTransform.reset();
591    SkISize size = SkISize::Make(info.width(), info.height());
592    return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform));
593}
594
595
596struct ContentEntry {
597    GraphicStateEntry fState;
598    SkDynamicMemoryWStream fContent;
599    SkAutoTDelete<ContentEntry> fNext;
600
601    // If the stack is too deep we could get Stack Overflow.
602    // So we manually destruct the object.
603    ~ContentEntry() {
604        ContentEntry* val = fNext.detach();
605        while (val != NULL) {
606            ContentEntry* valNext = val->fNext.detach();
607            // When the destructor is called, fNext is NULL and exits.
608            delete val;
609            val = valNext;
610        }
611    }
612};
613
614// A helper class to automatically finish a ContentEntry at the end of a
615// drawing method and maintain the state needed between set up and finish.
616class ScopedContentEntry {
617public:
618    ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw,
619                       const SkPaint& paint, bool hasText = false)
620        : fDevice(device),
621          fContentEntry(NULL),
622          fXfermode(SkXfermode::kSrcOver_Mode),
623          fDstFormXObject(NULL) {
624        init(draw.fClipStack, *draw.fClip, *draw.fMatrix, paint, hasText);
625    }
626    ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack,
627                       const SkRegion& clipRegion, const SkMatrix& matrix,
628                       const SkPaint& paint, bool hasText = false)
629        : fDevice(device),
630          fContentEntry(NULL),
631          fXfermode(SkXfermode::kSrcOver_Mode),
632          fDstFormXObject(NULL) {
633        init(clipStack, clipRegion, matrix, paint, hasText);
634    }
635
636    ~ScopedContentEntry() {
637        if (fContentEntry) {
638            SkPath* shape = &fShape;
639            if (shape->isEmpty()) {
640                shape = NULL;
641            }
642            fDevice->finishContentEntry(fXfermode, fDstFormXObject, shape);
643        }
644        SkSafeUnref(fDstFormXObject);
645    }
646
647    ContentEntry* entry() { return fContentEntry; }
648
649    /* Returns true when we explicitly need the shape of the drawing. */
650    bool needShape() {
651        switch (fXfermode) {
652            case SkXfermode::kClear_Mode:
653            case SkXfermode::kSrc_Mode:
654            case SkXfermode::kSrcIn_Mode:
655            case SkXfermode::kSrcOut_Mode:
656            case SkXfermode::kDstIn_Mode:
657            case SkXfermode::kDstOut_Mode:
658            case SkXfermode::kSrcATop_Mode:
659            case SkXfermode::kDstATop_Mode:
660            case SkXfermode::kModulate_Mode:
661                return true;
662            default:
663                return false;
664        }
665    }
666
667    /* Returns true unless we only need the shape of the drawing. */
668    bool needSource() {
669        if (fXfermode == SkXfermode::kClear_Mode) {
670            return false;
671        }
672        return true;
673    }
674
675    /* If the shape is different than the alpha component of the content, then
676     * setShape should be called with the shape.  In particular, images and
677     * devices have rectangular shape.
678     */
679    void setShape(const SkPath& shape) {
680        fShape = shape;
681    }
682
683private:
684    SkPDFDevice* fDevice;
685    ContentEntry* fContentEntry;
686    SkXfermode::Mode fXfermode;
687    SkPDFFormXObject* fDstFormXObject;
688    SkPath fShape;
689
690    void init(const SkClipStack* clipStack, const SkRegion& clipRegion,
691              const SkMatrix& matrix, const SkPaint& paint, bool hasText) {
692        // Shape has to be flatten before we get here.
693        if (matrix.hasPerspective()) {
694            NOT_IMPLEMENTED(!matrix.hasPerspective(), false);
695            return;
696        }
697        if (paint.getXfermode()) {
698            paint.getXfermode()->asMode(&fXfermode);
699        }
700        fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion,
701                                                   matrix, paint, hasText,
702                                                   &fDstFormXObject);
703    }
704};
705
706////////////////////////////////////////////////////////////////////////////////
707
708static inline SkBitmap makeContentBitmap(const SkISize& contentSize,
709                                         const SkMatrix* initialTransform) {
710    SkBitmap bitmap;
711    if (initialTransform) {
712        // Compute the size of the drawing area.
713        SkVector drawingSize;
714        SkMatrix inverse;
715        drawingSize.set(SkIntToScalar(contentSize.fWidth),
716                        SkIntToScalar(contentSize.fHeight));
717        if (!initialTransform->invert(&inverse)) {
718            // This shouldn't happen, initial transform should be invertible.
719            SkASSERT(false);
720            inverse.reset();
721        }
722        inverse.mapVectors(&drawingSize, 1);
723        SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound();
724        bitmap.setConfig(SkBitmap::kNo_Config, abs(size.fWidth),
725                         abs(size.fHeight));
726    } else {
727        bitmap.setConfig(SkBitmap::kNo_Config, abs(contentSize.fWidth),
728                         abs(contentSize.fHeight));
729    }
730
731    return bitmap;
732}
733
734// TODO(vandebo) change pageSize to SkSize.
735SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
736                         const SkMatrix& initialTransform)
737    : SkBitmapDevice(makeContentBitmap(contentSize, &initialTransform)),
738      fPageSize(pageSize),
739      fContentSize(contentSize),
740      fLastContentEntry(NULL),
741      fLastMarginContentEntry(NULL),
742      fClipStack(NULL),
743      fEncoder(NULL),
744      fRasterDpi(72.0f) {
745    // Just report that PDF does not supports perspective in the
746    // initial transform.
747    NOT_IMPLEMENTED(initialTransform.hasPerspective(), true);
748
749    // Skia generally uses the top left as the origin but PDF natively has the
750    // origin at the bottom left. This matrix corrects for that.  But that only
751    // needs to be done once, we don't do it when layering.
752    fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight));
753    fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1);
754    fInitialTransform.preConcat(initialTransform);
755
756    SkIRect existingClip = SkIRect::MakeWH(this->width(), this->height());
757    fExistingClipRegion.setRect(existingClip);
758
759    this->init();
760}
761
762// TODO(vandebo) change layerSize to SkSize.
763SkPDFDevice::SkPDFDevice(const SkISize& layerSize,
764                         const SkClipStack& existingClipStack,
765                         const SkRegion& existingClipRegion)
766    : SkBitmapDevice(makeContentBitmap(layerSize, NULL)),
767      fPageSize(layerSize),
768      fContentSize(layerSize),
769      fExistingClipStack(existingClipStack),
770      fExistingClipRegion(existingClipRegion),
771      fLastContentEntry(NULL),
772      fLastMarginContentEntry(NULL),
773      fClipStack(NULL),
774      fEncoder(NULL),
775      fRasterDpi(72.0f) {
776    fInitialTransform.reset();
777    this->init();
778}
779
780SkPDFDevice::~SkPDFDevice() {
781    this->cleanUp(true);
782}
783
784void SkPDFDevice::init() {
785    fAnnotations = NULL;
786    fResourceDict = NULL;
787    fContentEntries.free();
788    fLastContentEntry = NULL;
789    fMarginContentEntries.free();
790    fLastMarginContentEntry = NULL;
791    fDrawingArea = kContent_DrawingArea;
792    if (fFontGlyphUsage.get() == NULL) {
793        fFontGlyphUsage.reset(new SkPDFGlyphSetMap());
794    }
795}
796
797void SkPDFDevice::cleanUp(bool clearFontUsage) {
798    fGraphicStateResources.unrefAll();
799    fXObjectResources.unrefAll();
800    fFontResources.unrefAll();
801    fShaderResources.unrefAll();
802    SkSafeUnref(fAnnotations);
803    SkSafeUnref(fResourceDict);
804    fNamedDestinations.deleteAll();
805
806    if (clearFontUsage) {
807        fFontGlyphUsage->reset();
808    }
809}
810
811uint32_t SkPDFDevice::getDeviceCapabilities() {
812    return kVector_Capability;
813}
814
815void SkPDFDevice::clear(SkColor color) {
816    this->cleanUp(true);
817    this->init();
818
819    SkPaint paint;
820    paint.setColor(color);
821    paint.setStyle(SkPaint::kFill_Style);
822    SkMatrix identity;
823    identity.reset();
824    ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion,
825                               identity, paint);
826    internalDrawPaint(paint, content.entry());
827}
828
829void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) {
830    SkPaint newPaint = paint;
831    newPaint.setStyle(SkPaint::kFill_Style);
832    ScopedContentEntry content(this, d, newPaint);
833    internalDrawPaint(newPaint, content.entry());
834}
835
836void SkPDFDevice::internalDrawPaint(const SkPaint& paint,
837                                    ContentEntry* contentEntry) {
838    if (!contentEntry) {
839        return;
840    }
841    SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()),
842                                 SkIntToScalar(this->height()));
843    SkMatrix inverse;
844    if (!contentEntry->fState.fMatrix.invert(&inverse)) {
845        return;
846    }
847    inverse.mapRect(&bbox);
848
849    SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent);
850    SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
851                          &contentEntry->fContent);
852}
853
854void SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode,
855                             size_t count, const SkPoint* points,
856                             const SkPaint& passedPaint) {
857    if (count == 0) {
858        return;
859    }
860
861    if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) {
862        return;
863    }
864
865    // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
866    // We only use this when there's a path effect because of the overhead
867    // of multiple calls to setUpContentEntry it causes.
868    if (passedPaint.getPathEffect()) {
869        if (d.fClip->isEmpty()) {
870            return;
871        }
872        SkDraw pointDraw(d);
873        pointDraw.fDevice = this;
874        pointDraw.drawPoints(mode, count, points, passedPaint, true);
875        return;
876    }
877
878    const SkPaint* paint = &passedPaint;
879    SkPaint modifiedPaint;
880
881    if (mode == SkCanvas::kPoints_PointMode &&
882            paint->getStrokeCap() != SkPaint::kRound_Cap) {
883        modifiedPaint = *paint;
884        paint = &modifiedPaint;
885        if (paint->getStrokeWidth()) {
886            // PDF won't draw a single point with square/butt caps because the
887            // orientation is ambiguous.  Draw a rectangle instead.
888            modifiedPaint.setStyle(SkPaint::kFill_Style);
889            SkScalar strokeWidth = paint->getStrokeWidth();
890            SkScalar halfStroke = SkScalarHalf(strokeWidth);
891            for (size_t i = 0; i < count; i++) {
892                SkRect r = SkRect::MakeXYWH(points[i].fX, points[i].fY, 0, 0);
893                r.inset(-halfStroke, -halfStroke);
894                drawRect(d, r, modifiedPaint);
895            }
896            return;
897        } else {
898            modifiedPaint.setStrokeCap(SkPaint::kRound_Cap);
899        }
900    }
901
902    ScopedContentEntry content(this, d, *paint);
903    if (!content.entry()) {
904        return;
905    }
906
907    switch (mode) {
908        case SkCanvas::kPolygon_PointMode:
909            SkPDFUtils::MoveTo(points[0].fX, points[0].fY,
910                               &content.entry()->fContent);
911            for (size_t i = 1; i < count; i++) {
912                SkPDFUtils::AppendLine(points[i].fX, points[i].fY,
913                                       &content.entry()->fContent);
914            }
915            SkPDFUtils::StrokePath(&content.entry()->fContent);
916            break;
917        case SkCanvas::kLines_PointMode:
918            for (size_t i = 0; i < count/2; i++) {
919                SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY,
920                                   &content.entry()->fContent);
921                SkPDFUtils::AppendLine(points[i * 2 + 1].fX,
922                                       points[i * 2 + 1].fY,
923                                       &content.entry()->fContent);
924                SkPDFUtils::StrokePath(&content.entry()->fContent);
925            }
926            break;
927        case SkCanvas::kPoints_PointMode:
928            SkASSERT(paint->getStrokeCap() == SkPaint::kRound_Cap);
929            for (size_t i = 0; i < count; i++) {
930                SkPDFUtils::MoveTo(points[i].fX, points[i].fY,
931                                   &content.entry()->fContent);
932                SkPDFUtils::ClosePath(&content.entry()->fContent);
933                SkPDFUtils::StrokePath(&content.entry()->fContent);
934            }
935            break;
936        default:
937            SkASSERT(false);
938    }
939}
940
941void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& rect,
942                           const SkPaint& paint) {
943    SkRect r = rect;
944    r.sort();
945
946    if (paint.getPathEffect()) {
947        if (d.fClip->isEmpty()) {
948            return;
949        }
950        SkPath path;
951        path.addRect(r);
952        drawPath(d, path, paint, NULL, true);
953        return;
954    }
955
956    if (handleRectAnnotation(r, *d.fMatrix, paint)) {
957        return;
958    }
959
960    ScopedContentEntry content(this, d, paint);
961    if (!content.entry()) {
962        return;
963    }
964    SkPDFUtils::AppendRectangle(r, &content.entry()->fContent);
965    SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
966                          &content.entry()->fContent);
967}
968
969void SkPDFDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect,
970                            const SkPaint& paint) {
971    SkPath  path;
972    path.addRRect(rrect);
973    this->drawPath(draw, path, paint, NULL, true);
974}
975
976void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath,
977                           const SkPaint& paint, const SkMatrix* prePathMatrix,
978                           bool pathIsMutable) {
979    SkPath modifiedPath;
980    SkPath* pathPtr = const_cast<SkPath*>(&origPath);
981
982    SkMatrix matrix = *d.fMatrix;
983    if (prePathMatrix) {
984        if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
985            if (!pathIsMutable) {
986                pathPtr = &modifiedPath;
987                pathIsMutable = true;
988            }
989            origPath.transform(*prePathMatrix, pathPtr);
990        } else {
991            if (!matrix.preConcat(*prePathMatrix)) {
992                // TODO(edisonn): report somehow why we failed?
993                return;
994            }
995        }
996    }
997
998    if (paint.getPathEffect()) {
999        if (d.fClip->isEmpty()) {
1000            return;
1001        }
1002        if (!pathIsMutable) {
1003            pathPtr = &modifiedPath;
1004            pathIsMutable = true;
1005        }
1006        bool fill = paint.getFillPath(origPath, pathPtr);
1007
1008        SkPaint noEffectPaint(paint);
1009        noEffectPaint.setPathEffect(NULL);
1010        if (fill) {
1011            noEffectPaint.setStyle(SkPaint::kFill_Style);
1012        } else {
1013            noEffectPaint.setStyle(SkPaint::kStroke_Style);
1014            noEffectPaint.setStrokeWidth(0);
1015        }
1016        drawPath(d, *pathPtr, noEffectPaint, NULL, true);
1017        return;
1018    }
1019
1020#ifdef SK_PDF_USE_PATHOPS
1021    if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) {
1022        return;
1023    }
1024#endif
1025
1026    if (handleRectAnnotation(pathPtr->getBounds(), matrix, paint)) {
1027        return;
1028    }
1029
1030    ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
1031    if (!content.entry()) {
1032        return;
1033    }
1034    SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(),
1035                         &content.entry()->fContent);
1036    SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
1037                          &content.entry()->fContent);
1038}
1039
1040void SkPDFDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
1041                                 const SkRect* src, const SkRect& dst,
1042                                 const SkPaint& paint,
1043                                 SkCanvas::DrawBitmapRectFlags flags) {
1044    // TODO: this code path must be updated to respect the flags parameter
1045    SkMatrix    matrix;
1046    SkRect      bitmapBounds, tmpSrc, tmpDst;
1047    SkBitmap    tmpBitmap;
1048
1049    bitmapBounds.isetWH(bitmap.width(), bitmap.height());
1050
1051    // Compute matrix from the two rectangles
1052    if (src) {
1053        tmpSrc = *src;
1054    } else {
1055        tmpSrc = bitmapBounds;
1056    }
1057    matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
1058
1059    const SkBitmap* bitmapPtr = &bitmap;
1060
1061    // clip the tmpSrc to the bounds of the bitmap, and recompute dstRect if
1062    // needed (if the src was clipped). No check needed if src==null.
1063    if (src) {
1064        if (!bitmapBounds.contains(*src)) {
1065            if (!tmpSrc.intersect(bitmapBounds)) {
1066                return; // nothing to draw
1067            }
1068            // recompute dst, based on the smaller tmpSrc
1069            matrix.mapRect(&tmpDst, tmpSrc);
1070        }
1071
1072        // since we may need to clamp to the borders of the src rect within
1073        // the bitmap, we extract a subset.
1074        // TODO: make sure this is handled in drawBitmap and remove from here.
1075        SkIRect srcIR;
1076        tmpSrc.roundOut(&srcIR);
1077        if (!bitmap.extractSubset(&tmpBitmap, srcIR)) {
1078            return;
1079        }
1080        bitmapPtr = &tmpBitmap;
1081
1082        // Since we did an extract, we need to adjust the matrix accordingly
1083        SkScalar dx = 0, dy = 0;
1084        if (srcIR.fLeft > 0) {
1085            dx = SkIntToScalar(srcIR.fLeft);
1086        }
1087        if (srcIR.fTop > 0) {
1088            dy = SkIntToScalar(srcIR.fTop);
1089        }
1090        if (dx || dy) {
1091            matrix.preTranslate(dx, dy);
1092        }
1093    }
1094    this->drawBitmap(draw, *bitmapPtr, matrix, paint);
1095}
1096
1097void SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap,
1098                             const SkMatrix& matrix, const SkPaint& paint) {
1099    if (d.fClip->isEmpty()) {
1100        return;
1101    }
1102
1103    SkMatrix transform = matrix;
1104    transform.postConcat(*d.fMatrix);
1105    this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, NULL,
1106                             paint);
1107}
1108
1109void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap,
1110                             int x, int y, const SkPaint& paint) {
1111    if (d.fClip->isEmpty()) {
1112        return;
1113    }
1114
1115    SkMatrix matrix;
1116    matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
1117    this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL,
1118                             paint);
1119}
1120
1121void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
1122                           SkScalar x, SkScalar y, const SkPaint& paint) {
1123    NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
1124    if (paint.getMaskFilter() != NULL) {
1125        // Don't pretend we support drawing MaskFilters, it makes for artifacts
1126        // making text unreadable (e.g. same text twice when using CSS shadows).
1127        return;
1128    }
1129    SkPaint textPaint = calculate_text_paint(paint);
1130    ScopedContentEntry content(this, d, textPaint, true);
1131    if (!content.entry()) {
1132        return;
1133    }
1134
1135    SkGlyphStorage storage(0);
1136    uint16_t* glyphIDs = NULL;
1137    size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage,
1138                                            &glyphIDs);
1139    textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1140
1141    SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
1142    align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y);
1143    content.entry()->fContent.writeText("BT\n");
1144    set_text_transform(x, y, textPaint.getTextSkewX(),
1145                       &content.entry()->fContent);
1146    size_t consumedGlyphCount = 0;
1147    while (numGlyphs > consumedGlyphCount) {
1148        updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry());
1149        SkPDFFont* font = content.entry()->fState.fFont;
1150        size_t availableGlyphs =
1151            font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount,
1152                                          numGlyphs - consumedGlyphCount);
1153        fFontGlyphUsage->noteGlyphUsage(font, glyphIDs + consumedGlyphCount,
1154                                        availableGlyphs);
1155        SkString encodedString =
1156            SkPDFString::FormatString(glyphIDs + consumedGlyphCount,
1157                                      availableGlyphs, font->multiByteGlyphs());
1158        content.entry()->fContent.writeText(encodedString.c_str());
1159        consumedGlyphCount += availableGlyphs;
1160        content.entry()->fContent.writeText(" Tj\n");
1161    }
1162    content.entry()->fContent.writeText("ET\n");
1163}
1164
1165void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
1166                              const SkScalar pos[], SkScalar constY,
1167                              int scalarsPerPos, const SkPaint& paint) {
1168    NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
1169    if (paint.getMaskFilter() != NULL) {
1170        // Don't pretend we support drawing MaskFilters, it makes for artifacts
1171        // making text unreadable (e.g. same text twice when using CSS shadows).
1172        return;
1173    }
1174    SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos);
1175    SkPaint textPaint = calculate_text_paint(paint);
1176    ScopedContentEntry content(this, d, textPaint, true);
1177    if (!content.entry()) {
1178        return;
1179    }
1180
1181#ifdef SK_BUILD_FOR_ANDROID
1182    /*
1183     * In the case that we have enabled fallback fonts on Android we need to
1184     * take the following steps to ensure that the PDF draws all characters,
1185     * regardless of their underlying font file, correctly.
1186     *
1187     * 1. Convert input into GlyphID encoding if it currently is not
1188     * 2. Iterate over the glyphIDs and identify the actual typeface that each
1189     *    glyph resolves to
1190     * 3. Iterate over those typefaces and recursively call this function with
1191     *    only the glyphs (and their positions) that the typeface is capable of
1192     *    resolving.
1193     */
1194    if (paint.getPaintOptionsAndroid().isUsingFontFallbacks()) {
1195        uint16_t* glyphIDs = NULL;
1196        SkGlyphStorage tmpStorage(0);
1197        size_t numGlyphs = 0;
1198
1199        // convert to glyphIDs
1200        if (paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding) {
1201            numGlyphs = len / 2;
1202            glyphIDs = reinterpret_cast<uint16_t*>(const_cast<void*>(text));
1203        } else {
1204            numGlyphs = paint.textToGlyphs(text, len, NULL);
1205            tmpStorage.reset(numGlyphs);
1206            paint.textToGlyphs(text, len, tmpStorage.get());
1207            glyphIDs = tmpStorage.get();
1208        }
1209
1210        // if no typeface is provided in the paint get the default
1211        SkAutoTUnref<SkTypeface> origFace(SkSafeRef(paint.getTypeface()));
1212        if (NULL == origFace.get()) {
1213            origFace.reset(SkTypeface::RefDefault());
1214        }
1215        const uint16_t origGlyphCount = origFace->countGlyphs();
1216
1217        // keep a list of the already visited typefaces and some data about them
1218        SkTDArray<TypefaceFallbackData> visitedTypefaces;
1219
1220        // find all the typefaces needed to resolve this run of text
1221        bool usesOriginalTypeface = false;
1222        for (uint16_t x = 0; x < numGlyphs; ++x) {
1223            // optimization that checks to see if original typeface can resolve
1224            // the glyph
1225            if (glyphIDs[x] < origGlyphCount) {
1226                usesOriginalTypeface = true;
1227                continue;
1228            }
1229
1230            // find the fallback typeface that supports this glyph
1231            TypefaceFallbackData data;
1232            data.typeface =
1233                    SkGetTypefaceForGlyphID(glyphIDs[x], origFace.get(),
1234                                            paint.getPaintOptionsAndroid(),
1235                                            &data.lowerBounds,
1236                                            &data.upperBounds);
1237            // add the typeface and its data if we don't have it
1238            if (data.typeface && !visitedTypefaces.contains(data)) {
1239                visitedTypefaces.push(data);
1240            }
1241        }
1242
1243        // if the original font was used then add it to the list as well
1244        if (usesOriginalTypeface) {
1245            TypefaceFallbackData* data = visitedTypefaces.push();
1246            data->typeface = origFace.get();
1247            data->lowerBounds = 0;
1248            data->upperBounds = origGlyphCount;
1249        }
1250
1251        // keep a scratch glyph and pos storage
1252        SkAutoTMalloc<SkScalar> posStorage(len * scalarsPerPos);
1253        SkScalar* tmpPos = posStorage.get();
1254        SkGlyphStorage glyphStorage(numGlyphs);
1255        uint16_t* tmpGlyphIDs = glyphStorage.get();
1256
1257        // loop through all the valid typefaces, trim the glyphs to only those
1258        // resolved by the typeface, and then draw that run of glyphs
1259        for (int x = 0; x < visitedTypefaces.count(); ++x) {
1260            const TypefaceFallbackData& data = visitedTypefaces[x];
1261
1262            int tmpGlyphCount = 0;
1263            for (uint16_t y = 0; y < numGlyphs; ++y) {
1264                if (glyphIDs[y] >= data.lowerBounds &&
1265                        glyphIDs[y] < data.upperBounds) {
1266                    tmpGlyphIDs[tmpGlyphCount] = glyphIDs[y] - data.lowerBounds;
1267                    memcpy(&(tmpPos[tmpGlyphCount * scalarsPerPos]),
1268                           &(pos[y * scalarsPerPos]),
1269                           scalarsPerPos * sizeof(SkScalar));
1270                    tmpGlyphCount++;
1271                }
1272            }
1273
1274            // recursively call this function with the right typeface
1275            SkPaint tmpPaint = paint;
1276            tmpPaint.setTypeface(data.typeface);
1277            tmpPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1278
1279            // turn off fallback chaining
1280            SkPaintOptionsAndroid paintOpts = tmpPaint.getPaintOptionsAndroid();
1281            paintOpts.setUseFontFallbacks(false);
1282            tmpPaint.setPaintOptionsAndroid(paintOpts);
1283
1284            this->drawPosText(d, tmpGlyphIDs, tmpGlyphCount * 2, tmpPos, constY,
1285                              scalarsPerPos, tmpPaint);
1286        }
1287        return;
1288    }
1289#endif
1290
1291    SkGlyphStorage storage(0);
1292    uint16_t* glyphIDs = NULL;
1293    size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage,
1294                                            &glyphIDs);
1295    textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1296
1297    SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
1298    content.entry()->fContent.writeText("BT\n");
1299    updateFont(textPaint, glyphIDs[0], content.entry());
1300    for (size_t i = 0; i < numGlyphs; i++) {
1301        SkPDFFont* font = content.entry()->fState.fFont;
1302        uint16_t encodedValue = glyphIDs[i];
1303        if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) {
1304            updateFont(textPaint, glyphIDs[i], content.entry());
1305            i--;
1306            continue;
1307        }
1308        fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1);
1309        SkScalar x = pos[i * scalarsPerPos];
1310        SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1];
1311        align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y);
1312        set_text_transform(x, y, textPaint.getTextSkewX(),
1313                           &content.entry()->fContent);
1314        SkString encodedString =
1315            SkPDFString::FormatString(&encodedValue, 1,
1316                                      font->multiByteGlyphs());
1317        content.entry()->fContent.writeText(encodedString.c_str());
1318        content.entry()->fContent.writeText(" Tj\n");
1319    }
1320    content.entry()->fContent.writeText("ET\n");
1321}
1322
1323void SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len,
1324                                 const SkPath& path, const SkMatrix* matrix,
1325                                 const SkPaint& paint) {
1326    if (d.fClip->isEmpty()) {
1327        return;
1328    }
1329    d.drawTextOnPath((const char*)text, len, path, matrix, paint);
1330}
1331
1332void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode,
1333                               int vertexCount, const SkPoint verts[],
1334                               const SkPoint texs[], const SkColor colors[],
1335                               SkXfermode* xmode, const uint16_t indices[],
1336                               int indexCount, const SkPaint& paint) {
1337    if (d.fClip->isEmpty()) {
1338        return;
1339    }
1340    // TODO: implement drawVertices
1341}
1342
1343void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device,
1344                             int x, int y, const SkPaint& paint) {
1345    if ((device->getDeviceCapabilities() & kVector_Capability) == 0) {
1346        // If we somehow get a raster device, do what our parent would do.
1347        INHERITED::drawDevice(d, device, x, y, paint);
1348        return;
1349    }
1350
1351    // Assume that a vector capable device means that it's a PDF Device.
1352    SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device);
1353    if (pdfDevice->isContentEmpty()) {
1354        return;
1355    }
1356
1357    SkMatrix matrix;
1358    matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
1359    ScopedContentEntry content(this, d.fClipStack, *d.fClip, matrix, paint);
1360    if (!content.entry()) {
1361        return;
1362    }
1363    if (content.needShape()) {
1364        SkPath shape;
1365        shape.addRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
1366                                       SkIntToScalar(device->width()),
1367                                       SkIntToScalar(device->height())));
1368        content.setShape(shape);
1369    }
1370    if (!content.needSource()) {
1371        return;
1372    }
1373
1374    SkAutoTUnref<SkPDFFormXObject> xObject(new SkPDFFormXObject(pdfDevice));
1375    SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()),
1376                                &content.entry()->fContent);
1377
1378    // Merge glyph sets from the drawn device.
1379    fFontGlyphUsage->merge(pdfDevice->getFontGlyphUsage());
1380}
1381
1382void SkPDFDevice::onAttachToCanvas(SkCanvas* canvas) {
1383    INHERITED::onAttachToCanvas(canvas);
1384
1385    // Canvas promises that this ptr is valid until onDetachFromCanvas is called
1386    fClipStack = canvas->getClipStack();
1387}
1388
1389void SkPDFDevice::onDetachFromCanvas() {
1390    INHERITED::onDetachFromCanvas();
1391
1392    fClipStack = NULL;
1393}
1394
1395ContentEntry* SkPDFDevice::getLastContentEntry() {
1396    if (fDrawingArea == kContent_DrawingArea) {
1397        return fLastContentEntry;
1398    } else {
1399        return fLastMarginContentEntry;
1400    }
1401}
1402
1403SkAutoTDelete<ContentEntry>* SkPDFDevice::getContentEntries() {
1404    if (fDrawingArea == kContent_DrawingArea) {
1405        return &fContentEntries;
1406    } else {
1407        return &fMarginContentEntries;
1408    }
1409}
1410
1411void SkPDFDevice::setLastContentEntry(ContentEntry* contentEntry) {
1412    if (fDrawingArea == kContent_DrawingArea) {
1413        fLastContentEntry = contentEntry;
1414    } else {
1415        fLastMarginContentEntry = contentEntry;
1416    }
1417}
1418
1419void SkPDFDevice::setDrawingArea(DrawingArea drawingArea) {
1420    // A ScopedContentEntry only exists during the course of a draw call, so
1421    // this can't be called while a ScopedContentEntry exists.
1422    fDrawingArea = drawingArea;
1423}
1424
1425SkPDFResourceDict* SkPDFDevice::getResourceDict() {
1426    if (NULL == fResourceDict) {
1427        fResourceDict = SkNEW(SkPDFResourceDict);
1428
1429        if (fGraphicStateResources.count()) {
1430            for (int i = 0; i < fGraphicStateResources.count(); i++) {
1431                fResourceDict->insertResourceAsReference(
1432                        SkPDFResourceDict::kExtGState_ResourceType,
1433                        i, fGraphicStateResources[i]);
1434            }
1435        }
1436
1437        if (fXObjectResources.count()) {
1438            for (int i = 0; i < fXObjectResources.count(); i++) {
1439                fResourceDict->insertResourceAsReference(
1440                        SkPDFResourceDict::kXObject_ResourceType,
1441                        i, fXObjectResources[i]);
1442            }
1443        }
1444
1445        if (fFontResources.count()) {
1446            for (int i = 0; i < fFontResources.count(); i++) {
1447                fResourceDict->insertResourceAsReference(
1448                        SkPDFResourceDict::kFont_ResourceType,
1449                        i, fFontResources[i]);
1450            }
1451        }
1452
1453        if (fShaderResources.count()) {
1454            SkAutoTUnref<SkPDFDict> patterns(new SkPDFDict());
1455            for (int i = 0; i < fShaderResources.count(); i++) {
1456                fResourceDict->insertResourceAsReference(
1457                        SkPDFResourceDict::kPattern_ResourceType,
1458                        i, fShaderResources[i]);
1459            }
1460        }
1461    }
1462    return fResourceDict;
1463}
1464
1465const SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const {
1466    return fFontResources;
1467}
1468
1469SkPDFArray* SkPDFDevice::copyMediaBox() const {
1470    // should this be a singleton?
1471    SkAutoTUnref<SkPDFInt> zero(SkNEW_ARGS(SkPDFInt, (0)));
1472
1473    SkPDFArray* mediaBox = SkNEW(SkPDFArray);
1474    mediaBox->reserve(4);
1475    mediaBox->append(zero.get());
1476    mediaBox->append(zero.get());
1477    mediaBox->appendInt(fPageSize.fWidth);
1478    mediaBox->appendInt(fPageSize.fHeight);
1479    return mediaBox;
1480}
1481
1482SkStream* SkPDFDevice::content() const {
1483    SkMemoryStream* result = new SkMemoryStream;
1484    result->setData(this->copyContentToData())->unref();
1485    return result;
1486}
1487
1488void SkPDFDevice::copyContentEntriesToData(ContentEntry* entry,
1489        SkWStream* data) const {
1490    // TODO(ctguil): For margins, I'm not sure fExistingClipStack/Region is the
1491    // right thing to pass here.
1492    GraphicStackState gsState(fExistingClipStack, fExistingClipRegion, data);
1493    while (entry != NULL) {
1494        SkPoint translation;
1495        translation.iset(this->getOrigin());
1496        translation.negate();
1497        gsState.updateClip(entry->fState.fClipStack, entry->fState.fClipRegion,
1498                           translation);
1499        gsState.updateMatrix(entry->fState.fMatrix);
1500        gsState.updateDrawingState(entry->fState);
1501
1502        SkAutoDataUnref copy(entry->fContent.copyToData());
1503        data->write(copy->data(), copy->size());
1504        entry = entry->fNext.get();
1505    }
1506    gsState.drainStack();
1507}
1508
1509SkData* SkPDFDevice::copyContentToData() const {
1510    SkDynamicMemoryWStream data;
1511    if (fInitialTransform.getType() != SkMatrix::kIdentity_Mask) {
1512        SkPDFUtils::AppendTransform(fInitialTransform, &data);
1513    }
1514
1515    // TODO(aayushkumar): Apply clip along the margins.  Currently, webkit
1516    // colors the contentArea white before it starts drawing into it and
1517    // that currently acts as our clip.
1518    // Also, think about adding a transform here (or assume that the values
1519    // sent across account for that)
1520    SkPDFDevice::copyContentEntriesToData(fMarginContentEntries.get(), &data);
1521
1522    // If the content area is the entire page, then we don't need to clip
1523    // the content area (PDF area clips to the page size).  Otherwise,
1524    // we have to clip to the content area; we've already applied the
1525    // initial transform, so just clip to the device size.
1526    if (fPageSize != fContentSize) {
1527        SkRect r = SkRect::MakeWH(SkIntToScalar(this->width()),
1528                                  SkIntToScalar(this->height()));
1529        emit_clip(NULL, &r, &data);
1530    }
1531
1532    SkPDFDevice::copyContentEntriesToData(fContentEntries.get(), &data);
1533
1534    // potentially we could cache this SkData, and only rebuild it if we
1535    // see that our state has changed.
1536    return data.copyToData();
1537}
1538
1539#ifdef SK_PDF_USE_PATHOPS
1540/* Draws an inverse filled path by using Path Ops to compute the positive
1541 * inverse using the current clip as the inverse bounds.
1542 * Return true if this was an inverse path and was properly handled,
1543 * otherwise returns false and the normal drawing routine should continue,
1544 * either as a (incorrect) fallback or because the path was not inverse
1545 * in the first place.
1546 */
1547bool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath,
1548                                    const SkPaint& paint, bool pathIsMutable,
1549                                    const SkMatrix* prePathMatrix) {
1550    if (!origPath.isInverseFillType()) {
1551        return false;
1552    }
1553
1554    if (d.fClip->isEmpty()) {
1555        return false;
1556    }
1557
1558    SkPath modifiedPath;
1559    SkPath* pathPtr = const_cast<SkPath*>(&origPath);
1560    SkPaint noInversePaint(paint);
1561
1562    // Merge stroking operations into final path.
1563    if (SkPaint::kStroke_Style == paint.getStyle() ||
1564        SkPaint::kStrokeAndFill_Style == paint.getStyle()) {
1565        bool doFillPath = paint.getFillPath(origPath, &modifiedPath);
1566        if (doFillPath) {
1567            noInversePaint.setStyle(SkPaint::kFill_Style);
1568            noInversePaint.setStrokeWidth(0);
1569            pathPtr = &modifiedPath;
1570        } else {
1571            // To be consistent with the raster output, hairline strokes
1572            // are rendered as non-inverted.
1573            modifiedPath.toggleInverseFillType();
1574            drawPath(d, modifiedPath, paint, NULL, true);
1575            return true;
1576        }
1577    }
1578
1579    // Get bounds of clip in current transform space
1580    // (clip bounds are given in device space).
1581    SkRect bounds;
1582    SkMatrix transformInverse;
1583    SkMatrix totalMatrix = *d.fMatrix;
1584    if (prePathMatrix) {
1585        totalMatrix.preConcat(*prePathMatrix);
1586    }
1587    if (!totalMatrix.invert(&transformInverse)) {
1588        return false;
1589    }
1590    bounds.set(d.fClip->getBounds());
1591    transformInverse.mapRect(&bounds);
1592
1593    // Extend the bounds by the line width (plus some padding)
1594    // so the edge doesn't cause a visible stroke.
1595    bounds.outset(paint.getStrokeWidth() + SK_Scalar1,
1596                  paint.getStrokeWidth() + SK_Scalar1);
1597
1598    if (!calculate_inverse_path(bounds, *pathPtr, &modifiedPath)) {
1599        return false;
1600    }
1601
1602    drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true);
1603    return true;
1604}
1605#endif
1606
1607bool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix,
1608                                       const SkPaint& p) {
1609    SkAnnotation* annotationInfo = p.getAnnotation();
1610    if (!annotationInfo) {
1611        return false;
1612    }
1613    SkData* urlData = annotationInfo->find(SkAnnotationKeys::URL_Key());
1614    if (urlData) {
1615        handleLinkToURL(urlData, r, matrix);
1616        return p.getAnnotation() != NULL;
1617    }
1618    SkData* linkToName = annotationInfo->find(
1619            SkAnnotationKeys::Link_Named_Dest_Key());
1620    if (linkToName) {
1621        handleLinkToNamedDest(linkToName, r, matrix);
1622        return p.getAnnotation() != NULL;
1623    }
1624    return false;
1625}
1626
1627bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count,
1628                                        const SkMatrix& matrix,
1629                                        const SkPaint& paint) {
1630    SkAnnotation* annotationInfo = paint.getAnnotation();
1631    if (!annotationInfo) {
1632        return false;
1633    }
1634    SkData* nameData = annotationInfo->find(
1635            SkAnnotationKeys::Define_Named_Dest_Key());
1636    if (nameData) {
1637        for (size_t i = 0; i < count; i++) {
1638            defineNamedDestination(nameData, points[i], matrix);
1639        }
1640        return paint.getAnnotation() != NULL;
1641    }
1642    return false;
1643}
1644
1645SkPDFDict* SkPDFDevice::createLinkAnnotation(const SkRect& r,
1646                                             const SkMatrix& matrix) {
1647    SkMatrix transform = matrix;
1648    transform.postConcat(fInitialTransform);
1649    SkRect translatedRect;
1650    transform.mapRect(&translatedRect, r);
1651
1652    if (NULL == fAnnotations) {
1653        fAnnotations = SkNEW(SkPDFArray);
1654    }
1655    SkPDFDict* annotation(SkNEW_ARGS(SkPDFDict, ("Annot")));
1656    annotation->insertName("Subtype", "Link");
1657    fAnnotations->append(annotation);
1658
1659    SkAutoTUnref<SkPDFArray> border(SkNEW(SkPDFArray));
1660    border->reserve(3);
1661    border->appendInt(0);  // Horizontal corner radius.
1662    border->appendInt(0);  // Vertical corner radius.
1663    border->appendInt(0);  // Width, 0 = no border.
1664    annotation->insert("Border", border.get());
1665
1666    SkAutoTUnref<SkPDFArray> rect(SkNEW(SkPDFArray));
1667    rect->reserve(4);
1668    rect->appendScalar(translatedRect.fLeft);
1669    rect->appendScalar(translatedRect.fTop);
1670    rect->appendScalar(translatedRect.fRight);
1671    rect->appendScalar(translatedRect.fBottom);
1672    annotation->insert("Rect", rect.get());
1673
1674    return annotation;
1675}
1676
1677void SkPDFDevice::handleLinkToURL(SkData* urlData, const SkRect& r,
1678                                  const SkMatrix& matrix) {
1679    SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix));
1680
1681    SkString url(static_cast<const char *>(urlData->data()),
1682                 urlData->size() - 1);
1683    SkAutoTUnref<SkPDFDict> action(SkNEW_ARGS(SkPDFDict, ("Action")));
1684    action->insertName("S", "URI");
1685    action->insert("URI", SkNEW_ARGS(SkPDFString, (url)))->unref();
1686    annotation->insert("A", action.get());
1687}
1688
1689void SkPDFDevice::handleLinkToNamedDest(SkData* nameData, const SkRect& r,
1690                                        const SkMatrix& matrix) {
1691    SkAutoTUnref<SkPDFDict> annotation(createLinkAnnotation(r, matrix));
1692    SkString name(static_cast<const char *>(nameData->data()),
1693                  nameData->size() - 1);
1694    annotation->insert("Dest", SkNEW_ARGS(SkPDFName, (name)))->unref();
1695}
1696
1697struct NamedDestination {
1698    const SkData* nameData;
1699    SkPoint point;
1700
1701    NamedDestination(const SkData* nameData, const SkPoint& point)
1702        : nameData(nameData), point(point) {
1703        nameData->ref();
1704    }
1705
1706    ~NamedDestination() {
1707        nameData->unref();
1708    }
1709};
1710
1711void SkPDFDevice::defineNamedDestination(SkData* nameData, const SkPoint& point,
1712                                         const SkMatrix& matrix) {
1713    SkMatrix transform = matrix;
1714    transform.postConcat(fInitialTransform);
1715    SkPoint translatedPoint;
1716    transform.mapXY(point.x(), point.y(), &translatedPoint);
1717    fNamedDestinations.push(
1718        SkNEW_ARGS(NamedDestination, (nameData, translatedPoint)));
1719}
1720
1721void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) {
1722    int nDest = fNamedDestinations.count();
1723    for (int i = 0; i < nDest; i++) {
1724        NamedDestination* dest = fNamedDestinations[i];
1725        SkAutoTUnref<SkPDFArray> pdfDest(SkNEW(SkPDFArray));
1726        pdfDest->reserve(5);
1727        pdfDest->append(SkNEW_ARGS(SkPDFObjRef, (page)))->unref();
1728        pdfDest->appendName("XYZ");
1729        pdfDest->appendScalar(dest->point.x());
1730        pdfDest->appendScalar(dest->point.y());
1731        pdfDest->appendInt(0);  // Leave zoom unchanged
1732        dict->insert(static_cast<const char *>(dest->nameData->data()),
1733                     pdfDest);
1734    }
1735}
1736
1737SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() {
1738    SkPDFFormXObject* xobject = SkNEW_ARGS(SkPDFFormXObject, (this));
1739    // We always draw the form xobjects that we create back into the device, so
1740    // we simply preserve the font usage instead of pulling it out and merging
1741    // it back in later.
1742    cleanUp(false);  // Reset this device to have no content.
1743    init();
1744    return xobject;
1745}
1746
1747void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex,
1748                                          SkPDFFormXObject* mask,
1749                                          const SkClipStack* clipStack,
1750                                          const SkRegion& clipRegion,
1751                                          SkXfermode::Mode mode,
1752                                          bool invertClip) {
1753    if (clipRegion.isEmpty() && !invertClip) {
1754        return;
1755    }
1756
1757    SkAutoTUnref<SkPDFGraphicState> sMaskGS(
1758        SkPDFGraphicState::GetSMaskGraphicState(
1759            mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode));
1760
1761    SkMatrix identity;
1762    identity.reset();
1763    SkPaint paint;
1764    paint.setXfermodeMode(mode);
1765    ScopedContentEntry content(this, clipStack, clipRegion, identity, paint);
1766    if (!content.entry()) {
1767        return;
1768    }
1769    SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
1770                                  &content.entry()->fContent);
1771    SkPDFUtils::DrawFormXObject(xObjectIndex, &content.entry()->fContent);
1772
1773    sMaskGS.reset(SkPDFGraphicState::GetNoSMaskGraphicState());
1774    SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
1775                                  &content.entry()->fContent);
1776}
1777
1778ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
1779                                             const SkRegion& clipRegion,
1780                                             const SkMatrix& matrix,
1781                                             const SkPaint& paint,
1782                                             bool hasText,
1783                                             SkPDFFormXObject** dst) {
1784    *dst = NULL;
1785    if (clipRegion.isEmpty()) {
1786        return NULL;
1787    }
1788
1789    // The clip stack can come from an SkDraw where it is technically optional.
1790    SkClipStack synthesizedClipStack;
1791    if (clipStack == NULL) {
1792        if (clipRegion == fExistingClipRegion) {
1793            clipStack = &fExistingClipStack;
1794        } else {
1795            // GraphicStackState::updateClip expects the clip stack to have
1796            // fExistingClip as a prefix, so start there, then set the clip
1797            // to the passed region.
1798            synthesizedClipStack = fExistingClipStack;
1799            SkPath clipPath;
1800            clipRegion.getBoundaryPath(&clipPath);
1801            synthesizedClipStack.clipDevPath(clipPath, SkRegion::kReplace_Op,
1802                                             false);
1803            clipStack = &synthesizedClipStack;
1804        }
1805    }
1806
1807    SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode;
1808    if (paint.getXfermode()) {
1809        paint.getXfermode()->asMode(&xfermode);
1810    }
1811
1812    // For the following modes, we want to handle source and destination
1813    // separately, so make an object of what's already there.
1814    if (xfermode == SkXfermode::kClear_Mode       ||
1815            xfermode == SkXfermode::kSrc_Mode     ||
1816            xfermode == SkXfermode::kSrcIn_Mode   ||
1817            xfermode == SkXfermode::kDstIn_Mode   ||
1818            xfermode == SkXfermode::kSrcOut_Mode  ||
1819            xfermode == SkXfermode::kDstOut_Mode  ||
1820            xfermode == SkXfermode::kSrcATop_Mode ||
1821            xfermode == SkXfermode::kDstATop_Mode ||
1822            xfermode == SkXfermode::kModulate_Mode) {
1823        if (!isContentEmpty()) {
1824            *dst = createFormXObjectFromDevice();
1825            SkASSERT(isContentEmpty());
1826        } else if (xfermode != SkXfermode::kSrc_Mode &&
1827                   xfermode != SkXfermode::kSrcOut_Mode) {
1828            // Except for Src and SrcOut, if there isn't anything already there,
1829            // then we're done.
1830            return NULL;
1831        }
1832    }
1833    // TODO(vandebo): Figure out how/if we can handle the following modes:
1834    // Xor, Plus.
1835
1836    // Dst xfer mode doesn't draw source at all.
1837    if (xfermode == SkXfermode::kDst_Mode) {
1838        return NULL;
1839    }
1840
1841    ContentEntry* entry;
1842    SkAutoTDelete<ContentEntry> newEntry;
1843
1844    ContentEntry* lastContentEntry = getLastContentEntry();
1845    if (lastContentEntry && lastContentEntry->fContent.getOffset() == 0) {
1846        entry = lastContentEntry;
1847    } else {
1848        newEntry.reset(new ContentEntry);
1849        entry = newEntry.get();
1850    }
1851
1852    populateGraphicStateEntryFromPaint(matrix, *clipStack, clipRegion, paint,
1853                                       hasText, &entry->fState);
1854    if (lastContentEntry && xfermode != SkXfermode::kDstOver_Mode &&
1855            entry->fState.compareInitialState(lastContentEntry->fState)) {
1856        return lastContentEntry;
1857    }
1858
1859    SkAutoTDelete<ContentEntry>* contentEntries = getContentEntries();
1860    if (!lastContentEntry) {
1861        contentEntries->reset(entry);
1862        setLastContentEntry(entry);
1863    } else if (xfermode == SkXfermode::kDstOver_Mode) {
1864        entry->fNext.reset(contentEntries->detach());
1865        contentEntries->reset(entry);
1866    } else {
1867        lastContentEntry->fNext.reset(entry);
1868        setLastContentEntry(entry);
1869    }
1870    newEntry.detach();
1871    return entry;
1872}
1873
1874void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
1875                                     SkPDFFormXObject* dst,
1876                                     SkPath* shape) {
1877    if (xfermode != SkXfermode::kClear_Mode       &&
1878            xfermode != SkXfermode::kSrc_Mode     &&
1879            xfermode != SkXfermode::kDstOver_Mode &&
1880            xfermode != SkXfermode::kSrcIn_Mode   &&
1881            xfermode != SkXfermode::kDstIn_Mode   &&
1882            xfermode != SkXfermode::kSrcOut_Mode  &&
1883            xfermode != SkXfermode::kDstOut_Mode  &&
1884            xfermode != SkXfermode::kSrcATop_Mode &&
1885            xfermode != SkXfermode::kDstATop_Mode &&
1886            xfermode != SkXfermode::kModulate_Mode) {
1887        SkASSERT(!dst);
1888        return;
1889    }
1890    if (xfermode == SkXfermode::kDstOver_Mode) {
1891        SkASSERT(!dst);
1892        ContentEntry* firstContentEntry = getContentEntries()->get();
1893        if (firstContentEntry->fContent.getOffset() == 0) {
1894            // For DstOver, an empty content entry was inserted before the rest
1895            // of the content entries. If nothing was drawn, it needs to be
1896            // removed.
1897            SkAutoTDelete<ContentEntry>* contentEntries = getContentEntries();
1898            contentEntries->reset(firstContentEntry->fNext.detach());
1899        }
1900        return;
1901    }
1902    if (!dst) {
1903        SkASSERT(xfermode == SkXfermode::kSrc_Mode ||
1904                 xfermode == SkXfermode::kSrcOut_Mode);
1905        return;
1906    }
1907
1908    ContentEntry* contentEntries = getContentEntries()->get();
1909    SkASSERT(dst);
1910    SkASSERT(!contentEntries->fNext.get());
1911    // Changing the current content into a form-xobject will destroy the clip
1912    // objects which is fine since the xobject will already be clipped. However
1913    // if source has shape, we need to clip it too, so a copy of the clip is
1914    // saved.
1915    SkClipStack clipStack = contentEntries->fState.fClipStack;
1916    SkRegion clipRegion = contentEntries->fState.fClipRegion;
1917
1918    SkMatrix identity;
1919    identity.reset();
1920    SkPaint stockPaint;
1921
1922    SkAutoTUnref<SkPDFFormXObject> srcFormXObject;
1923    if (isContentEmpty()) {
1924        // If nothing was drawn and there's no shape, then the draw was a
1925        // no-op, but dst needs to be restored for that to be true.
1926        // If there is shape, then an empty source with Src, SrcIn, SrcOut,
1927        // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop
1928        // reduces to Dst.
1929        if (shape == NULL || xfermode == SkXfermode::kDstOut_Mode ||
1930                xfermode == SkXfermode::kSrcATop_Mode) {
1931            ScopedContentEntry content(this, &fExistingClipStack,
1932                                       fExistingClipRegion, identity,
1933                                       stockPaint);
1934            SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
1935                                        &content.entry()->fContent);
1936            return;
1937        } else {
1938            xfermode = SkXfermode::kClear_Mode;
1939        }
1940    } else {
1941        SkASSERT(!fContentEntries->fNext.get());
1942        srcFormXObject.reset(createFormXObjectFromDevice());
1943    }
1944
1945    // TODO(vandebo) srcFormXObject may contain alpha, but here we want it
1946    // without alpha.
1947    if (xfermode == SkXfermode::kSrcATop_Mode) {
1948        // TODO(vandebo): In order to properly support SrcATop we have to track
1949        // the shape of what's been drawn at all times. It's the intersection of
1950        // the non-transparent parts of the device and the outlines (shape) of
1951        // all images and devices drawn.
1952        drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
1953                                &fExistingClipStack, fExistingClipRegion,
1954                                SkXfermode::kSrcOver_Mode, true);
1955    } else {
1956        SkAutoTUnref<SkPDFFormXObject> dstMaskStorage;
1957        SkPDFFormXObject* dstMask = srcFormXObject.get();
1958        if (shape != NULL) {
1959            // Draw shape into a form-xobject.
1960            SkDraw d;
1961            d.fMatrix = &identity;
1962            d.fClip = &clipRegion;
1963            d.fClipStack = &clipStack;
1964            SkPaint filledPaint;
1965            filledPaint.setColor(SK_ColorBLACK);
1966            filledPaint.setStyle(SkPaint::kFill_Style);
1967            this->drawPath(d, *shape, filledPaint, NULL, true);
1968
1969            dstMaskStorage.reset(createFormXObjectFromDevice());
1970            dstMask = dstMaskStorage.get();
1971        }
1972        drawFormXObjectWithMask(addXObjectResource(dst), dstMask,
1973                                &fExistingClipStack, fExistingClipRegion,
1974                                SkXfermode::kSrcOver_Mode, true);
1975    }
1976
1977    if (xfermode == SkXfermode::kClear_Mode) {
1978        return;
1979    } else if (xfermode == SkXfermode::kSrc_Mode ||
1980            xfermode == SkXfermode::kDstATop_Mode) {
1981        ScopedContentEntry content(this, &fExistingClipStack,
1982                                   fExistingClipRegion, identity, stockPaint);
1983        if (content.entry()) {
1984            SkPDFUtils::DrawFormXObject(
1985                    this->addXObjectResource(srcFormXObject.get()),
1986                    &content.entry()->fContent);
1987        }
1988        if (xfermode == SkXfermode::kSrc_Mode) {
1989            return;
1990        }
1991    } else if (xfermode == SkXfermode::kSrcATop_Mode) {
1992        ScopedContentEntry content(this, &fExistingClipStack,
1993                                   fExistingClipRegion, identity, stockPaint);
1994        if (content.entry()) {
1995            SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
1996                                        &content.entry()->fContent);
1997        }
1998    }
1999
2000    SkASSERT(xfermode == SkXfermode::kSrcIn_Mode   ||
2001             xfermode == SkXfermode::kDstIn_Mode   ||
2002             xfermode == SkXfermode::kSrcOut_Mode  ||
2003             xfermode == SkXfermode::kDstOut_Mode  ||
2004             xfermode == SkXfermode::kSrcATop_Mode ||
2005             xfermode == SkXfermode::kDstATop_Mode ||
2006             xfermode == SkXfermode::kModulate_Mode);
2007
2008    if (xfermode == SkXfermode::kSrcIn_Mode ||
2009            xfermode == SkXfermode::kSrcOut_Mode ||
2010            xfermode == SkXfermode::kSrcATop_Mode) {
2011        drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
2012                                &fExistingClipStack, fExistingClipRegion,
2013                                SkXfermode::kSrcOver_Mode,
2014                                xfermode == SkXfermode::kSrcOut_Mode);
2015    } else {
2016        SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
2017        if (xfermode == SkXfermode::kModulate_Mode) {
2018            drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()),
2019                                    dst, &fExistingClipStack,
2020                                    fExistingClipRegion,
2021                                    SkXfermode::kSrcOver_Mode, false);
2022            mode = SkXfermode::kMultiply_Mode;
2023        }
2024        drawFormXObjectWithMask(addXObjectResource(dst), srcFormXObject.get(),
2025                                &fExistingClipStack, fExistingClipRegion, mode,
2026                                xfermode == SkXfermode::kDstOut_Mode);
2027    }
2028}
2029
2030bool SkPDFDevice::isContentEmpty() {
2031    ContentEntry* contentEntries = getContentEntries()->get();
2032    if (!contentEntries || contentEntries->fContent.getOffset() == 0) {
2033        SkASSERT(!contentEntries || !contentEntries->fNext.get());
2034        return true;
2035    }
2036    return false;
2037}
2038
2039void SkPDFDevice::populateGraphicStateEntryFromPaint(
2040        const SkMatrix& matrix,
2041        const SkClipStack& clipStack,
2042        const SkRegion& clipRegion,
2043        const SkPaint& paint,
2044        bool hasText,
2045        GraphicStateEntry* entry) {
2046    SkASSERT(paint.getPathEffect() == NULL);
2047
2048    NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
2049    NOT_IMPLEMENTED(paint.getColorFilter() != NULL, false);
2050
2051    entry->fMatrix = matrix;
2052    entry->fClipStack = clipStack;
2053    entry->fClipRegion = clipRegion;
2054    entry->fColor = SkColorSetA(paint.getColor(), 0xFF);
2055    entry->fShaderIndex = -1;
2056
2057    // PDF treats a shader as a color, so we only set one or the other.
2058    SkAutoTUnref<SkPDFObject> pdfShader;
2059    const SkShader* shader = paint.getShader();
2060    SkColor color = paint.getColor();
2061    if (shader) {
2062        // PDF positions patterns relative to the initial transform, so
2063        // we need to apply the current transform to the shader parameters.
2064        SkMatrix transform = matrix;
2065        transform.postConcat(fInitialTransform);
2066
2067        // PDF doesn't support kClamp_TileMode, so we simulate it by making
2068        // a pattern the size of the current clip.
2069        SkIRect bounds = clipRegion.getBounds();
2070
2071        // We need to apply the initial transform to bounds in order to get
2072        // bounds in a consistent coordinate system.
2073        SkRect boundsTemp;
2074        boundsTemp.set(bounds);
2075        fInitialTransform.mapRect(&boundsTemp);
2076        boundsTemp.roundOut(&bounds);
2077
2078        pdfShader.reset(SkPDFShader::GetPDFShader(*shader, transform, bounds));
2079
2080        if (pdfShader.get()) {
2081            // pdfShader has been canonicalized so we can directly compare
2082            // pointers.
2083            int resourceIndex = fShaderResources.find(pdfShader.get());
2084            if (resourceIndex < 0) {
2085                resourceIndex = fShaderResources.count();
2086                fShaderResources.push(pdfShader.get());
2087                pdfShader.get()->ref();
2088            }
2089            entry->fShaderIndex = resourceIndex;
2090        } else {
2091            // A color shader is treated as an invalid shader so we don't have
2092            // to set a shader just for a color.
2093            SkShader::GradientInfo gradientInfo;
2094            SkColor gradientColor;
2095            gradientInfo.fColors = &gradientColor;
2096            gradientInfo.fColorOffsets = NULL;
2097            gradientInfo.fColorCount = 1;
2098            if (shader->asAGradient(&gradientInfo) ==
2099                    SkShader::kColor_GradientType) {
2100                entry->fColor = SkColorSetA(gradientColor, 0xFF);
2101                color = gradientColor;
2102            }
2103        }
2104    }
2105
2106    SkAutoTUnref<SkPDFGraphicState> newGraphicState;
2107    if (color == paint.getColor()) {
2108        newGraphicState.reset(
2109                SkPDFGraphicState::GetGraphicStateForPaint(paint));
2110    } else {
2111        SkPaint newPaint = paint;
2112        newPaint.setColor(color);
2113        newGraphicState.reset(
2114                SkPDFGraphicState::GetGraphicStateForPaint(newPaint));
2115    }
2116    int resourceIndex = addGraphicStateResource(newGraphicState.get());
2117    entry->fGraphicStateIndex = resourceIndex;
2118
2119    if (hasText) {
2120        entry->fTextScaleX = paint.getTextScaleX();
2121        entry->fTextFill = paint.getStyle();
2122    } else {
2123        entry->fTextScaleX = 0;
2124    }
2125}
2126
2127int SkPDFDevice::addGraphicStateResource(SkPDFGraphicState* gs) {
2128    // Assumes that gs has been canonicalized (so we can directly compare
2129    // pointers).
2130    int result = fGraphicStateResources.find(gs);
2131    if (result < 0) {
2132        result = fGraphicStateResources.count();
2133        fGraphicStateResources.push(gs);
2134        gs->ref();
2135    }
2136    return result;
2137}
2138
2139int SkPDFDevice::addXObjectResource(SkPDFObject* xObject) {
2140    // Assumes that xobject has been canonicalized (so we can directly compare
2141    // pointers).
2142    int result = fXObjectResources.find(xObject);
2143    if (result < 0) {
2144        result = fXObjectResources.count();
2145        fXObjectResources.push(xObject);
2146        xObject->ref();
2147    }
2148    return result;
2149}
2150
2151void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID,
2152                             ContentEntry* contentEntry) {
2153    SkTypeface* typeface = paint.getTypeface();
2154    if (contentEntry->fState.fFont == NULL ||
2155            contentEntry->fState.fTextSize != paint.getTextSize() ||
2156            !contentEntry->fState.fFont->hasGlyph(glyphID)) {
2157        int fontIndex = getFontResourceIndex(typeface, glyphID);
2158        contentEntry->fContent.writeText("/");
2159        contentEntry->fContent.writeText(SkPDFResourceDict::getResourceName(
2160                SkPDFResourceDict::kFont_ResourceType,
2161                fontIndex).c_str());
2162        contentEntry->fContent.writeText(" ");
2163        SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent);
2164        contentEntry->fContent.writeText(" Tf\n");
2165        contentEntry->fState.fFont = fFontResources[fontIndex];
2166    }
2167}
2168
2169int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
2170    SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface,
2171                                                               glyphID));
2172    int resourceIndex = fFontResources.find(newFont.get());
2173    if (resourceIndex < 0) {
2174        resourceIndex = fFontResources.count();
2175        fFontResources.push(newFont.get());
2176        newFont.get()->ref();
2177    }
2178    return resourceIndex;
2179}
2180
2181void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
2182                                     const SkClipStack* clipStack,
2183                                     const SkRegion& origClipRegion,
2184                                     const SkBitmap& origBitmap,
2185                                     const SkIRect* srcRect,
2186                                     const SkPaint& paint) {
2187    SkMatrix matrix = origMatrix;
2188    SkRegion perspectiveBounds;
2189    const SkRegion* clipRegion = &origClipRegion;
2190    SkBitmap perspectiveBitmap;
2191    const SkBitmap* bitmap = &origBitmap;
2192    SkBitmap tmpSubsetBitmap;
2193
2194    // Rasterize the bitmap using perspective in a new bitmap.
2195    if (origMatrix.hasPerspective()) {
2196        if (fRasterDpi == 0) {
2197            return;
2198        }
2199        SkBitmap* subsetBitmap;
2200        if (srcRect) {
2201            if (!origBitmap.extractSubset(&tmpSubsetBitmap, *srcRect)) {
2202               return;
2203            }
2204            subsetBitmap = &tmpSubsetBitmap;
2205        } else {
2206            subsetBitmap = &tmpSubsetBitmap;
2207            *subsetBitmap = origBitmap;
2208        }
2209        srcRect = NULL;
2210
2211        // Transform the bitmap in the new space, without taking into
2212        // account the initial transform.
2213        SkPath perspectiveOutline;
2214        perspectiveOutline.addRect(
2215                SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()),
2216                               SkIntToScalar(subsetBitmap->height())));
2217        perspectiveOutline.transform(origMatrix);
2218
2219        // TODO(edisonn): perf - use current clip too.
2220        // Retrieve the bounds of the new shape.
2221        SkRect bounds = perspectiveOutline.getBounds();
2222
2223        // Transform the bitmap in the new space, taking into
2224        // account the initial transform.
2225        SkMatrix total = origMatrix;
2226        total.postConcat(fInitialTransform);
2227        total.postScale(SkIntToScalar(fRasterDpi) /
2228                            SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE),
2229                        SkIntToScalar(fRasterDpi) /
2230                            SkIntToScalar(DPI_FOR_RASTER_SCALE_ONE));
2231        SkPath physicalPerspectiveOutline;
2232        physicalPerspectiveOutline.addRect(
2233                SkRect::MakeWH(SkIntToScalar(subsetBitmap->width()),
2234                               SkIntToScalar(subsetBitmap->height())));
2235        physicalPerspectiveOutline.transform(total);
2236
2237        SkScalar scaleX = physicalPerspectiveOutline.getBounds().width() /
2238                              bounds.width();
2239        SkScalar scaleY = physicalPerspectiveOutline.getBounds().height() /
2240                              bounds.height();
2241
2242        // TODO(edisonn): A better approach would be to use a bitmap shader
2243        // (in clamp mode) and draw a rect over the entire bounding box. Then
2244        // intersect perspectiveOutline to the clip. That will avoid introducing
2245        // alpha to the image while still giving good behavior at the edge of
2246        // the image.  Avoiding alpha will reduce the pdf size and generation
2247        // CPU time some.
2248
2249        const int w = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().width());
2250        const int h = SkScalarCeilToInt(physicalPerspectiveOutline.getBounds().height());
2251        if (!perspectiveBitmap.allocPixels(SkImageInfo::MakeN32Premul(w, h))) {
2252            return;
2253        }
2254        perspectiveBitmap.eraseColor(SK_ColorTRANSPARENT);
2255
2256        SkBitmapDevice device(perspectiveBitmap);
2257        SkCanvas canvas(&device);
2258
2259        SkScalar deltaX = bounds.left();
2260        SkScalar deltaY = bounds.top();
2261
2262        SkMatrix offsetMatrix = origMatrix;
2263        offsetMatrix.postTranslate(-deltaX, -deltaY);
2264        offsetMatrix.postScale(scaleX, scaleY);
2265
2266        // Translate the draw in the new canvas, so we perfectly fit the
2267        // shape in the bitmap.
2268        canvas.setMatrix(offsetMatrix);
2269
2270        canvas.drawBitmap(*subsetBitmap, SkIntToScalar(0), SkIntToScalar(0));
2271
2272        // Make sure the final bits are in the bitmap.
2273        canvas.flush();
2274
2275        // In the new space, we use the identity matrix translated
2276        // and scaled to reflect DPI.
2277        matrix.setScale(1 / scaleX, 1 / scaleY);
2278        matrix.postTranslate(deltaX, deltaY);
2279
2280        perspectiveBounds.setRect(
2281                SkIRect::MakeXYWH(SkScalarFloorToInt(bounds.x()),
2282                                  SkScalarFloorToInt(bounds.y()),
2283                                  SkScalarCeilToInt(bounds.width()),
2284                                  SkScalarCeilToInt(bounds.height())));
2285        clipRegion = &perspectiveBounds;
2286        srcRect = NULL;
2287        bitmap = &perspectiveBitmap;
2288    }
2289
2290    SkMatrix scaled;
2291    // Adjust for origin flip.
2292    scaled.setScale(SK_Scalar1, -SK_Scalar1);
2293    scaled.postTranslate(0, SK_Scalar1);
2294    // Scale the image up from 1x1 to WxH.
2295    SkIRect subset = SkIRect::MakeWH(bitmap->width(), bitmap->height());
2296    scaled.postScale(SkIntToScalar(subset.width()),
2297                     SkIntToScalar(subset.height()));
2298    scaled.postConcat(matrix);
2299    ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint);
2300    if (!content.entry() || (srcRect && !subset.intersect(*srcRect))) {
2301        return;
2302    }
2303    if (content.needShape()) {
2304        SkPath shape;
2305        shape.addRect(SkRect::MakeWH(SkIntToScalar(subset.width()),
2306                                     SkIntToScalar( subset.height())));
2307        shape.transform(matrix);
2308        content.setShape(shape);
2309    }
2310    if (!content.needSource()) {
2311        return;
2312    }
2313
2314    SkAutoTUnref<SkPDFImage> image(
2315        SkPDFImage::CreateImage(*bitmap, subset, fEncoder));
2316    if (!image) {
2317        return;
2318    }
2319
2320    SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
2321                                &content.entry()->fContent);
2322}
2323
2324bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y,
2325                               SkCanvas::Config8888) {
2326    return false;
2327}
2328
2329bool SkPDFDevice::allowImageFilter(const SkImageFilter*) {
2330    return false;
2331}
2332