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