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