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