/*
 * Copyright (C) 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "SkPDFDevice.h"

#include "SkColor.h"
#include "SkGlyphCache.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkPDFImage.h"
#include "SkPDFGraphicState.h"
#include "SkPDFFont.h"
#include "SkPDFFormXObject.h"
#include "SkPDFTypes.h"
#include "SkPDFStream.h"
#include "SkRect.h"
#include "SkString.h"
#include "SkTextFormatParams.h"
#include "SkTypeface.h"
#include "SkTypes.h"

#define NOT_IMPLEMENTED(condition, assert)                         \
    do {                                                           \
        if (condition) {                                           \
            fprintf(stderr, "NOT_IMPLEMENTED: " #condition "\n");  \
            SkDEBUGCODE(SkASSERT(!assert);)                        \
        }                                                          \
    } while(0)

// Utility functions

namespace {

SkString toPDFColor(SkColor color) {
    SkASSERT(SkColorGetA(color) == 0xFF);  // We handle alpha elsewhere.
    SkScalar colorMax = SkIntToScalar(0xFF);
    SkString result;
    result.appendScalar(SkScalarDiv(SkIntToScalar(SkColorGetR(color)),
                                    colorMax));
    result.append(" ");
    result.appendScalar(SkScalarDiv(SkIntToScalar(SkColorGetG(color)),
                                    colorMax));
    result.append(" ");
    result.appendScalar(SkScalarDiv(SkIntToScalar(SkColorGetB(color)),
                                    colorMax));
    result.append(" ");
    return result;
}

SkPaint calculateTextPaint(const SkPaint& paint) {
    SkPaint result = paint;
    if (result.isFakeBoldText()) {
        SkScalar fakeBoldScale = SkScalarInterpFunc(result.getTextSize(),
                                                    kStdFakeBoldInterpKeys,
                                                    kStdFakeBoldInterpValues,
                                                    kStdFakeBoldInterpLength);
        SkScalar width = SkScalarMul(result.getTextSize(), fakeBoldScale);
        if (result.getStyle() == SkPaint::kFill_Style)
            result.setStyle(SkPaint::kStrokeAndFill_Style);
        else
            width += result.getStrokeWidth();
        result.setStrokeWidth(width);
    }
    return result;
}

// Stolen from measure_text in SkDraw.cpp and then tweaked.
void alignText(SkDrawCacheProc glyphCacheProc, const SkPaint& paint,
               const uint16_t* glyphs, size_t len, SkScalar* x, SkScalar* y,
               SkScalar* width) {
    if (paint.getTextAlign() == SkPaint::kLeft_Align && width == NULL)
        return;

    SkMatrix ident;
    ident.reset();
    SkAutoGlyphCache autoCache(paint, &ident);
    SkGlyphCache* cache = autoCache.getCache();

    const char* start = (char*)glyphs;
    const char* stop = (char*)(glyphs + len);
    SkFixed xAdv = 0, yAdv = 0;

    // TODO(vandebo) This probably needs to take kerning into account.
    while (start < stop) {
        const SkGlyph& glyph = glyphCacheProc(cache, &start, 0, 0);
        xAdv += glyph.fAdvanceX;
        yAdv += glyph.fAdvanceY;
    };
    if (width)
        *width = SkFixedToScalar(xAdv);
    if (paint.getTextAlign() == SkPaint::kLeft_Align)
        return;

    SkScalar xAdj = SkFixedToScalar(xAdv);
    SkScalar yAdj = SkFixedToScalar(yAdv);
    if (paint.getTextAlign() == SkPaint::kCenter_Align) {
        xAdj = SkScalarHalf(xAdj);
        yAdj = SkScalarHalf(yAdj);
    }
    *x = *x - xAdj;
    *y = *y - yAdj;
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////

SkDevice* SkPDFDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
                                        int width, int height, bool isOpaque,
                                        bool /*isForLayer*/) {
    return SkNEW_ARGS(SkPDFDevice, (width, height));
}

static inline SkBitmap makeABitmap(int width, int height) {
    SkBitmap bitmap;
    bitmap.setConfig(SkBitmap::kNo_Config, width, height);
    return bitmap;
}

SkPDFDevice::SkPDFDevice(int width, int height)
    : SkDevice(NULL, makeABitmap(width, height), false),
      fWidth(width),
      fHeight(height),
      fGraphicStackIndex(0) {
    fGraphicStack[0].fColor = SK_ColorBLACK;
    fGraphicStack[0].fTextSize = SK_ScalarNaN;  // This has no default value.
    fGraphicStack[0].fTextScaleX = SK_Scalar1;
    fGraphicStack[0].fTextFill = SkPaint::kFill_Style;
    fGraphicStack[0].fFont = NULL;
    fGraphicStack[0].fGraphicState = NULL;
    fGraphicStack[0].fClip.setRect(0,0, width, height);
    fGraphicStack[0].fTransform.reset();
}

SkPDFDevice::~SkPDFDevice() {
    fGraphicStateResources.unrefAll();
    fXObjectResources.unrefAll();
    fFontResources.unrefAll();
}

void SkPDFDevice::setMatrixClip(const SkMatrix& matrix,
                                const SkRegion& region,
                                const SkClipStack&) {
    // See the comment in the header file above GraphicStackEntry.
    if (region != fGraphicStack[fGraphicStackIndex].fClip) {
        while (fGraphicStackIndex > 0)
            popGS();
        pushGS();

        SkPath clipPath;
        if (region.getBoundaryPath(&clipPath)) {
            emitPath(clipPath);

            SkPath::FillType clipFill = clipPath.getFillType();
            NOT_IMPLEMENTED(clipFill == SkPath::kInverseEvenOdd_FillType,
                            false);
            NOT_IMPLEMENTED(clipFill == SkPath::kInverseWinding_FillType,
                            false);
            if (clipFill == SkPath::kEvenOdd_FillType)
                fContent.append("W* n ");
            else
                fContent.append("W n ");
        }

        fGraphicStack[fGraphicStackIndex].fClip = region;
    }
    setTransform(matrix);
}

void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) {
    SkMatrix identityTransform;
    identityTransform.reset();
    SkMatrix curTransform = setTransform(identityTransform);

    SkPaint newPaint = paint;
    newPaint.setStyle(SkPaint::kFill_Style);
    updateGSFromPaint(newPaint, false);

    SkRect all = SkRect::MakeWH(width() + 1, height() + 1);
    drawRect(d, all, newPaint);
    setTransform(curTransform);
}

void SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode,
                             size_t count, const SkPoint* points,
                             const SkPaint& paint) {
    if (count == 0)
        return;

    switch (mode) {
        case SkCanvas::kPolygon_PointMode:
            updateGSFromPaint(paint, false);
            moveTo(points[0].fX, points[0].fY);
            for (size_t i = 1; i < count; i++)
                appendLine(points[i].fX, points[i].fY);
            strokePath();
            break;
        case SkCanvas::kLines_PointMode:
            updateGSFromPaint(paint, false);
            for (size_t i = 0; i < count/2; i++) {
                moveTo(points[i * 2].fX, points[i * 2].fY);
                appendLine(points[i * 2 + 1].fX, points[i * 2 + 1].fY);
                strokePath();
            }
            break;
        case SkCanvas::kPoints_PointMode:
            if (paint.getStrokeCap() == SkPaint::kRound_Cap) {
                updateGSFromPaint(paint, false);
                for (size_t i = 0; i < count; i++) {
                    moveTo(points[i].fX, points[i].fY);
                    strokePath();
                }
            } else {
                // PDF won't draw a single point with square/butt caps because
                // the orientation is ambiguous.  Draw a rectangle instead.
                SkPaint newPaint = paint;
                newPaint.setStyle(SkPaint::kFill_Style);
                SkScalar strokeWidth = paint.getStrokeWidth();
                SkScalar halfStroke = strokeWidth * SK_ScalarHalf;
                for (size_t i = 0; i < count; i++) {
                    SkRect r = SkRect::MakeXYWH(points[i].fX, points[i].fY,
                                                0, 0);
                    r.inset(-halfStroke, -halfStroke);
                    drawRect(d, r, newPaint);
                }
            }
            break;
        default:
            SkASSERT(false);
    }
}

void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& r,
                           const SkPaint& paint) {
    if (paint.getPathEffect()) {
        // Create a path for the rectangle and apply the path effect to it.
        SkPath path;
        path.addRect(r);
        paint.getFillPath(path, &path);

        SkPaint noEffectPaint(paint);
        SkSafeUnref(noEffectPaint.setPathEffect(NULL));
        drawPath(d, path, noEffectPaint, NULL, true);
        return;
    }
    updateGSFromPaint(paint, false);

    // Skia has 0,0 at top left, pdf at bottom left.  Do the right thing.
    SkScalar bottom = r.fBottom < r.fTop ? r.fBottom : r.fTop;
    appendRectangle(r.fLeft, bottom, r.width(), r.height());
    paintPath(paint.getStyle(), SkPath::kWinding_FillType);
}

void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& path,
                           const SkPaint& paint, const SkMatrix* prePathMatrix,
                           bool pathIsMutable) {
    NOT_IMPLEMENTED(prePathMatrix != NULL, true);

    if (paint.getPathEffect()) {
        // Apply the path effect to path and draw it that way.
        SkPath noEffectPath;
        paint.getFillPath(path, &noEffectPath);

        SkPaint noEffectPaint(paint);
        SkSafeUnref(noEffectPaint.setPathEffect(NULL));
        drawPath(d, noEffectPath, noEffectPaint, NULL, true);
        return;
    }
    updateGSFromPaint(paint, false);

    emitPath(path);
    paintPath(paint.getStyle(), path.getFillType());
}

void SkPDFDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
                             const SkIRect* srcRect,
                             const SkMatrix& matrix, const SkPaint& paint) {
    SkMatrix transform = matrix;
    transform.postConcat(fGraphicStack[fGraphicStackIndex].fTransform);
    internalDrawBitmap(transform, bitmap, srcRect, paint);
}

void SkPDFDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap,
                             int x, int y, const SkPaint& paint) {
    SkMatrix matrix;
    matrix.setTranslate(x, y);
    internalDrawBitmap(matrix, bitmap, NULL, paint);
}

void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
                           SkScalar x, SkScalar y, const SkPaint& paint) {
    SkPaint textPaint = calculateTextPaint(paint);
    updateGSFromPaint(textPaint, true);

    // Make sure we have a glyph id encoding.
    SkAutoFree glyphStorage;
    uint16_t* glyphIDs;
    size_t numGlyphs;
    if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
        numGlyphs = paint.textToGlyphs(text, len, NULL);
        glyphIDs = (uint16_t*)sk_malloc_flags(numGlyphs * 2,
                                              SK_MALLOC_TEMP | SK_MALLOC_THROW);
        glyphStorage.set(glyphIDs);
        paint.textToGlyphs(text, len, glyphIDs);
        textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    } else {
        SkASSERT((len & 1) == 0);
        numGlyphs = len / 2;
        glyphIDs = (uint16_t*)text;
    }
    SkAutoFree encodedStorage(
            sk_malloc_flags(numGlyphs * 2, SK_MALLOC_TEMP | SK_MALLOC_THROW));

    SkScalar width;
    SkScalar* widthPtr = NULL;
    if (textPaint.isUnderlineText() || textPaint.isStrikeThruText())
        widthPtr = &width;

    SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
    alignText(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y, widthPtr);
    fContent.append("BT\n");
    setTextTransform(x, y, textPaint.getTextSkewX());
    size_t consumedGlyphCount = 0;
    while (numGlyphs > consumedGlyphCount) {
        updateFont(textPaint, glyphIDs[consumedGlyphCount]);
        SkPDFFont* font = fGraphicStack[fGraphicStackIndex].fFont;
        size_t encodedLength = numGlyphs * 2;
        consumedGlyphCount += font->glyphsToPDFFontEncoding(
                glyphIDs + consumedGlyphCount, numGlyphs - consumedGlyphCount,
                encodedStorage.get(), &encodedLength);
        if (font->multiByteGlyphs())
            encodedLength /= 2;
        fContent.append(
                SkPDFString::formatString((const uint16_t*)encodedStorage.get(),
                                          encodedLength,
                                          font->multiByteGlyphs()));
        fContent.append(" Tj\n");
    }
    fContent.append("ET\n");

    // Draw underline and/or strikethrough if the paint has them.
    // drawPosText() and drawTextOnPath() don't draw underline or strikethrough
    // because the raster versions don't.  Use paint instead of textPaint
    // because we may have changed strokeWidth to do fakeBold text.
    if (paint.isUnderlineText() || paint.isStrikeThruText()) {
        SkScalar textSize = paint.getTextSize();
        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);

        if (paint.isUnderlineText()) {
            SkScalar top = SkScalarMulAdd(textSize, kStdUnderline_Offset, y);
            SkRect r = SkRect::MakeXYWH(x, top - height, width, height);
            drawRect(d, r, paint);
        }
        if (paint.isStrikeThruText()) {
            SkScalar top = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, y);
            SkRect r = SkRect::MakeXYWH(x, top - height, width, height);
            drawRect(d, r, paint);
        }
    }
}

void SkPDFDevice::drawPosText(const SkDraw&, const void* text, size_t len,
                              const SkScalar pos[], SkScalar constY,
                              int scalarsPerPos, const SkPaint& paint) {
    SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos);
    SkPaint textPaint = calculateTextPaint(paint);
    updateGSFromPaint(textPaint, true);

    // Make sure we have a glyph id encoding.
    SkAutoFree glyphStorage;
    uint16_t* glyphIDs;
    size_t numGlyphs;
    if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
        numGlyphs = paint.textToGlyphs(text, len, NULL);
        glyphIDs = (uint16_t*)sk_malloc_flags(numGlyphs * 2,
                                              SK_MALLOC_TEMP | SK_MALLOC_THROW);
        glyphStorage.set(glyphIDs);
        paint.textToGlyphs(text, len, glyphIDs);
        textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    } else {
        SkASSERT((len & 1) == 0);
        numGlyphs = len / 2;
        glyphIDs = (uint16_t*)text;
    }

    SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
    fContent.append("BT\n");
    updateFont(textPaint, glyphIDs[0]);
    for (size_t i = 0; i < numGlyphs; i++) {
        SkPDFFont* font = fGraphicStack[fGraphicStackIndex].fFont;
        uint16_t encodedValue;
        size_t encodedLength = 2;
        if (font->glyphsToPDFFontEncoding(glyphIDs + i, 1, &encodedValue,
                                          &encodedLength) == 0) {
            updateFont(textPaint, glyphIDs[i]);
            i--;
            continue;
        }
        SkScalar x = pos[i * scalarsPerPos];
        SkScalar y = scalarsPerPos == 1 ? constY : pos[i * scalarsPerPos + 1];
        alignText(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y, NULL);
        setTextTransform(x, y, textPaint.getTextSkewX());
        fContent.append(SkPDFString::formatString(&encodedValue, 1,
                                                  font->multiByteGlyphs()));
        fContent.append(" Tj\n");
    }
    fContent.append("ET\n");
}

void SkPDFDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len,
                                 const SkPath& path, const SkMatrix* matrix,
                                 const SkPaint& paint) {
    NOT_IMPLEMENTED("drawTextOnPath", true);
}

void SkPDFDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode,
                               int vertexCount, const SkPoint verts[],
                               const SkPoint texs[], const SkColor colors[],
                               SkXfermode* xmode, const uint16_t indices[],
                               int indexCount, const SkPaint& paint) {
    NOT_IMPLEMENTED("drawVerticies", true);
}

void SkPDFDevice::drawDevice(const SkDraw& d, SkDevice* device, int x, int y,
                             const SkPaint& paint) {
    if ((device->getDeviceCapabilities() & kVector_Capability) == 0) {
        // If we somehow get a raster device, do what our parent would do.
        SkDevice::drawDevice(d, device, x, y, paint);
        return;
    }
    // Assume that a vector capable device means that it's a PDF Device.
    SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device);

    SkMatrix matrix;
    matrix.setTranslate(x, y);
    SkMatrix curTransform = setTransform(matrix);
    updateGSFromPaint(paint, false);

    SkPDFFormXObject* xobject = new SkPDFFormXObject(pdfDevice);
    fXObjectResources.push(xobject);  // Transfer reference.
    fContent.append("/X");
    fContent.appendS32(fXObjectResources.count() - 1);
    fContent.append(" Do\n");
    setTransform(curTransform);
}

const SkRefPtr<SkPDFDict>& SkPDFDevice::getResourceDict() {
    if (fResourceDict.get() == NULL) {
        fResourceDict = new SkPDFDict;
        fResourceDict->unref();  // SkRefPtr and new both took a reference.

        if (fGraphicStateResources.count()) {
            SkRefPtr<SkPDFDict> extGState = new SkPDFDict();
            extGState->unref();  // SkRefPtr and new both took a reference.
            for (int i = 0; i < fGraphicStateResources.count(); i++) {
                SkString nameString("G");
                nameString.appendS32(i);
                extGState->insert(
                        nameString.c_str(),
                        new SkPDFObjRef(fGraphicStateResources[i]))->unref();
            }
            fResourceDict->insert("ExtGState", extGState.get());
        }

        if (fXObjectResources.count()) {
            SkRefPtr<SkPDFDict> xObjects = new SkPDFDict();
            xObjects->unref();  // SkRefPtr and new both took a reference.
            for (int i = 0; i < fXObjectResources.count(); i++) {
                SkString nameString("X");
                nameString.appendS32(i);
                xObjects->insert(
                        nameString.c_str(),
                        new SkPDFObjRef(fXObjectResources[i]))->unref();
            }
            fResourceDict->insert("XObject", xObjects.get());
        }

        if (fFontResources.count()) {
            SkRefPtr<SkPDFDict> fonts = new SkPDFDict();
            fonts->unref();  // SkRefPtr and new both took a reference.
            for (int i = 0; i < fFontResources.count(); i++) {
                SkString nameString("F");
                nameString.appendS32(i);
                fonts->insert(nameString.c_str(),
                              new SkPDFObjRef(fFontResources[i]))->unref();
            }
            fResourceDict->insert("Font", fonts.get());
        }

        // For compatibility, add all proc sets (only used for output to PS
        // devices).
        const char procs[][7] = {"PDF", "Text", "ImageB", "ImageC", "ImageI"};
        SkRefPtr<SkPDFArray> procSets = new SkPDFArray();
        procSets->unref();  // SkRefPtr and new both took a reference.
        procSets->reserve(SK_ARRAY_COUNT(procs));
        for (size_t i = 0; i < SK_ARRAY_COUNT(procs); i++)
            procSets->append(new SkPDFName(procs[i]))->unref();
        fResourceDict->insert("ProcSet", procSets.get());
    }
    return fResourceDict;
}

void SkPDFDevice::getResources(SkTDArray<SkPDFObject*>* resourceList) const {
    resourceList->setReserve(resourceList->count() +
                             fGraphicStateResources.count() +
                             fXObjectResources.count() +
                             fFontResources.count());
    for (int i = 0; i < fGraphicStateResources.count(); i++) {
        resourceList->push(fGraphicStateResources[i]);
        fGraphicStateResources[i]->ref();
        fGraphicStateResources[i]->getResources(resourceList);
    }
    for (int i = 0; i < fXObjectResources.count(); i++) {
        resourceList->push(fXObjectResources[i]);
        fXObjectResources[i]->ref();
        fXObjectResources[i]->getResources(resourceList);
    }
    for (int i = 0; i < fFontResources.count(); i++) {
        resourceList->push(fFontResources[i]);
        fFontResources[i]->ref();
        fFontResources[i]->getResources(resourceList);
    }
}

SkRefPtr<SkPDFArray> SkPDFDevice::getMediaBox() const {
    SkRefPtr<SkPDFInt> zero = new SkPDFInt(0);
    zero->unref();  // SkRefPtr and new both took a reference.

    SkRefPtr<SkPDFArray> mediaBox = new SkPDFArray();
    mediaBox->unref();  // SkRefPtr and new both took a reference.
    mediaBox->reserve(4);
    mediaBox->append(zero.get());
    mediaBox->append(zero.get());
    mediaBox->append(new SkPDFInt(fWidth))->unref();
    mediaBox->append(new SkPDFInt(fHeight))->unref();
    return mediaBox;
}

SkString SkPDFDevice::content(bool flipOrigin) const {
    SkString result;
    // Scale and translate to move the origin from the lower left to the
    // upper left.
    if (flipOrigin)
        result.printf("1 0 0 -1 0 %d cm\n", fHeight);
    result.append(fContent);
    for (int i = 0; i < fGraphicStackIndex; i++)
        result.append("Q\n");
    return result;
}

// Private

// TODO(vandebo) handle these cases.
#define PAINTCHECK(x,y) NOT_IMPLEMENTED(newPaint.x() y, false)

void SkPDFDevice::updateGSFromPaint(const SkPaint& newPaint, bool forText) {
    SkASSERT(newPaint.getPathEffect() == NULL);

    PAINTCHECK(getMaskFilter, != NULL);
    PAINTCHECK(getShader, != NULL);
    PAINTCHECK(getColorFilter, != NULL);

    SkRefPtr<SkPDFGraphicState> newGraphicState =
        SkPDFGraphicState::getGraphicStateForPaint(newPaint);
    newGraphicState->unref();  // getGraphicState and SkRefPtr both took a ref.
    // newGraphicState has been canonicalized so we can directly compare
    // pointers.
    if (fGraphicStack[fGraphicStackIndex].fGraphicState !=
            newGraphicState.get()) {
        int resourceIndex = fGraphicStateResources.find(newGraphicState.get());
        if (resourceIndex < 0) {
            resourceIndex = fGraphicStateResources.count();
            fGraphicStateResources.push(newGraphicState.get());
            newGraphicState->ref();
        }
        fContent.append("/G");
        fContent.appendS32(resourceIndex);
        fContent.append(" gs\n");
        fGraphicStack[fGraphicStackIndex].fGraphicState = newGraphicState.get();
    }

    SkColor newColor = newPaint.getColor();
    newColor = SkColorSetA(newColor, 0xFF);
    if (fGraphicStack[fGraphicStackIndex].fColor != newColor) {
        SkString colorString = toPDFColor(newColor);
        fContent.append(colorString);
        fContent.append("RG ");
        fContent.append(colorString);
        fContent.append("rg\n");
        fGraphicStack[fGraphicStackIndex].fColor = newColor;
    }

    if (forText) {
        if (fGraphicStack[fGraphicStackIndex].fTextScaleX !=
                newPaint.getTextScaleX()) {
            SkScalar scale = newPaint.getTextScaleX();
            SkScalar pdfScale = SkScalarMul(scale, SkIntToScalar(100));
            fContent.appendScalar(pdfScale);
            fContent.append(" Tz\n");
            fGraphicStack[fGraphicStackIndex].fTextScaleX = scale;
        }

        if (fGraphicStack[fGraphicStackIndex].fTextFill !=
                newPaint.getStyle()) {
            SK_COMPILE_ASSERT(SkPaint::kFill_Style == 0, enum_must_match_value);
            SK_COMPILE_ASSERT(SkPaint::kStroke_Style == 1,
                              enum_must_match_value);
            SK_COMPILE_ASSERT(SkPaint::kStrokeAndFill_Style == 2,
                              enum_must_match_value);
            fContent.appendS32(newPaint.getStyle());
            fContent.append(" Tr\n");
            fGraphicStack[fGraphicStackIndex].fTextFill = newPaint.getStyle();
        }
    }
}

void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID) {
    uint32_t fontID = SkTypeface::UniqueID(paint.getTypeface());
    if (fGraphicStack[fGraphicStackIndex].fTextSize != paint.getTextSize() ||
            fGraphicStack[fGraphicStackIndex].fFont == NULL ||
            fGraphicStack[fGraphicStackIndex].fFont->fontID() != fontID ||
            !fGraphicStack[fGraphicStackIndex].fFont->hasGlyph(glyphID)) {
        int fontIndex = getFontResourceIndex(fontID, glyphID);
        fContent.append("/F");
        fContent.appendS32(fontIndex);
        fContent.append(" ");
        fContent.appendScalar(paint.getTextSize());
        fContent.append(" Tf\n");
        fGraphicStack[fGraphicStackIndex].fTextSize = paint.getTextSize();
        fGraphicStack[fGraphicStackIndex].fFont = fFontResources[fontIndex];
    }
}


int SkPDFDevice::getFontResourceIndex(uint32_t fontID, uint16_t glyphID) {
    SkRefPtr<SkPDFFont> newFont = SkPDFFont::getFontResource(fontID, glyphID);
    newFont->unref();  // getFontResource and SkRefPtr both took a ref.
    int resourceIndex = fFontResources.find(newFont.get());
    if (resourceIndex < 0) {
        resourceIndex = fFontResources.count();
        fFontResources.push(newFont.get());
        newFont->ref();
    }
    return resourceIndex;
}

void SkPDFDevice::moveTo(SkScalar x, SkScalar y) {
    fContent.appendScalar(x);
    fContent.append(" ");
    fContent.appendScalar(y);
    fContent.append(" m\n");
}

void SkPDFDevice::appendLine(SkScalar x, SkScalar y) {
    fContent.appendScalar(x);
    fContent.append(" ");
    fContent.appendScalar(y);
    fContent.append(" l\n");
}

void SkPDFDevice::appendCubic(SkScalar ctl1X, SkScalar ctl1Y,
                              SkScalar ctl2X, SkScalar ctl2Y,
                              SkScalar dstX, SkScalar dstY) {
    SkString cmd("y\n");
    fContent.appendScalar(ctl1X);
    fContent.append(" ");
    fContent.appendScalar(ctl1Y);
    fContent.append(" ");
    if (ctl2X != dstX || ctl2Y != dstY) {
        cmd.set("c\n");
        fContent.appendScalar(ctl2X);
        fContent.append(" ");
        fContent.appendScalar(ctl2Y);
        fContent.append(" ");
    }
    fContent.appendScalar(dstX);
    fContent.append(" ");
    fContent.appendScalar(dstY);
    fContent.append(" ");
    fContent.append(cmd);
}

void SkPDFDevice::appendRectangle(SkScalar x, SkScalar y,
                                  SkScalar w, SkScalar h) {
    fContent.appendScalar(x);
    fContent.append(" ");
    fContent.appendScalar(y);
    fContent.append(" ");
    fContent.appendScalar(w);
    fContent.append(" ");
    fContent.appendScalar(h);
    fContent.append(" re\n");
}

void SkPDFDevice::emitPath(const SkPath& path) {
    SkPoint args[4];
    SkPath::Iter iter(path, false);
    for (SkPath::Verb verb = iter.next(args);
         verb != SkPath::kDone_Verb;
         verb = iter.next(args)) {
        // args gets all the points, even the implicit first point.
        switch (verb) {
            case SkPath::kMove_Verb:
                moveTo(args[0].fX, args[0].fY);
                break;
            case SkPath::kLine_Verb:
                appendLine(args[1].fX, args[1].fY);
                break;
            case SkPath::kQuad_Verb: {
                // Convert quad to cubic (degree elevation). http://goo.gl/vS4i
                const SkScalar three = SkIntToScalar(3);
                args[1].scale(SkIntToScalar(2));
                SkScalar ctl1X = SkScalarDiv(args[0].fX + args[1].fX, three);
                SkScalar ctl1Y = SkScalarDiv(args[0].fY + args[1].fY, three);
                SkScalar ctl2X = SkScalarDiv(args[2].fX + args[1].fX, three);
                SkScalar ctl2Y = SkScalarDiv(args[2].fY + args[1].fY, three);
                appendCubic(ctl1X, ctl1Y, ctl2X, ctl2Y, args[2].fX, args[2].fY);
                break;
            }
            case SkPath::kCubic_Verb:
                appendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY,
                            args[3].fX, args[3].fY);
                break;
            case SkPath::kClose_Verb:
                closePath();
                break;
            case SkPath::kDone_Verb:
                break;
            default:
                SkASSERT(false);
                break;
        }
    }
}

void SkPDFDevice::closePath() {
    fContent.append("h\n");
}

void SkPDFDevice::paintPath(SkPaint::Style style, SkPath::FillType fill) {
    if (style == SkPaint::kFill_Style)
        fContent.append("f");
    else if (style == SkPaint::kStrokeAndFill_Style)
        fContent.append("B");
    else if (style == SkPaint::kStroke_Style)
        fContent.append("S");

    if (style != SkPaint::kStroke_Style) {
        // Not supported yet.
        NOT_IMPLEMENTED(fill == SkPath::kInverseEvenOdd_FillType, false);
        NOT_IMPLEMENTED(fill == SkPath::kInverseWinding_FillType, false);
        if (fill == SkPath::kEvenOdd_FillType)
            fContent.append("*");
    }
    fContent.append("\n");
}

void SkPDFDevice::strokePath() {
    paintPath(SkPaint::kStroke_Style, SkPath::kWinding_FillType);
}

void SkPDFDevice::pushGS() {
    SkASSERT(fGraphicStackIndex < 2);
    fContent.append("q\n");
    fGraphicStackIndex++;
    fGraphicStack[fGraphicStackIndex] = fGraphicStack[fGraphicStackIndex - 1];
}

void SkPDFDevice::popGS() {
    SkASSERT(fGraphicStackIndex > 0);
    fContent.append("Q\n");
    fGraphicStackIndex--;
}

void SkPDFDevice::setTextTransform(SkScalar x, SkScalar y, SkScalar textSkewX) {
    // Flip the text about the x-axis to account for origin swap and include
    // the passed parameters.
    fContent.append("1 0 ");
    fContent.appendScalar(0 - textSkewX);
    fContent.append(" -1 ");
    fContent.appendScalar(x);
    fContent.append(" ");
    fContent.appendScalar(y);
    fContent.append(" Tm\n");
}

void SkPDFDevice::internalDrawBitmap(const SkMatrix& matrix,
                                     const SkBitmap& bitmap,
                                     const SkIRect* srcRect,
                                     const SkPaint& paint) {
    SkIRect subset = SkIRect::MakeWH(bitmap.width(), bitmap.height());
    if (srcRect && !subset.intersect(*srcRect))
        return;

    SkPDFImage* image = SkPDFImage::CreateImage(bitmap, subset, paint);
    if (!image)
        return;

    SkMatrix scaled;
    // Adjust for origin flip.
    scaled.setScale(1, -1);
    scaled.postTranslate(0, 1);
    // Scale the image up from 1x1 to WxH.
    scaled.postScale(subset.width(), subset.height());
    scaled.postConcat(matrix);
    SkMatrix curTransform = setTransform(scaled);
    updateGSFromPaint(paint, false);

    fXObjectResources.push(image);  // Transfer reference.
    fContent.append("/X");
    fContent.appendS32(fXObjectResources.count() - 1);
    fContent.append(" Do\n");
    setTransform(curTransform);
}

SkMatrix SkPDFDevice::setTransform(const SkMatrix& m) {
    SkMatrix old = fGraphicStack[fGraphicStackIndex].fTransform;
    if (old == m)
        return old;

    if (old.getType() != SkMatrix::kIdentity_Mask) {
        SkASSERT(fGraphicStackIndex > 0);
        SkASSERT(fGraphicStack[fGraphicStackIndex - 1].fTransform.getType() ==
                 SkMatrix::kIdentity_Mask);
        SkASSERT(fGraphicStack[fGraphicStackIndex].fClip ==
                 fGraphicStack[fGraphicStackIndex - 1].fClip);
        popGS();
    }
    if (m.getType() == SkMatrix::kIdentity_Mask)
        return old;

    if (fGraphicStackIndex == 0 || fGraphicStack[fGraphicStackIndex].fClip !=
            fGraphicStack[fGraphicStackIndex - 1].fClip)
        pushGS();

    SkScalar transform[6];
    SkAssertResult(m.pdfTransform(transform));
    for (size_t i = 0; i < SK_ARRAY_COUNT(transform); i++) {
        fContent.appendScalar(transform[i]);
        fContent.append(" ");
    }
    fContent.append("cm\n");
    fGraphicStack[fGraphicStackIndex].fTransform = m;

    return old;
}
