/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/pdf/SkPDFDevice.h"

#include "include/codec/SkCodec.h"
#include "include/core/SkAlphaType.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkClipOp.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorFilter.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkColorType.h"
#include "include/core/SkData.h"
#include "include/core/SkFont.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkM44.h"
#include "include/core/SkMaskFilter.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPathUtils.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkSpan.h"
#include "include/core/SkString.h"
#include "include/core/SkStrokeRec.h"
#include "include/core/SkSurface.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/docs/SkPDFDocument.h"
#include "include/pathops/SkPathOps.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkScopeExit.h"
#include "src/base/SkTLazy.h"
#include "src/base/SkUTF.h"
#include "src/core/SkAdvancedTypefaceMetrics.h"
#include "src/core/SkAnnotationKeys.h"
#include "src/core/SkBitmapDevice.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkDevice.h"
#include "src/core/SkDraw.h"
#include "src/core/SkGlyph.h"
#include "src/core/SkMask.h"
#include "src/core/SkMaskFilterBase.h"
#include "src/core/SkPaintPriv.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkRasterClip.h"
#include "src/core/SkSpecialImage.h"
#include "src/core/SkStrikeSpec.h"
#include "src/pdf/SkBitmapKey.h"
#include "src/pdf/SkClusterator.h"
#include "src/pdf/SkKeyedImage.h"
#include "src/pdf/SkPDFBitmap.h"
#include "src/pdf/SkPDFDocumentPriv.h"
#include "src/pdf/SkPDFFont.h"
#include "src/pdf/SkPDFFormXObject.h"
#include "src/pdf/SkPDFGraphicState.h"
#include "src/pdf/SkPDFResourceDict.h"
#include "src/pdf/SkPDFShader.h"
#include "src/pdf/SkPDFTag.h"
#include "src/pdf/SkPDFTypes.h"
#include "src/pdf/SkPDFUnion.h"
#include "src/pdf/SkPDFUtils.h"
#include "src/shaders/SkColorShader.h"
#include "src/shaders/SkShaderBase.h"
#include "src/text/GlyphRun.h"
#include "src/utils/SkClipStackUtils.h"

#include <algorithm>
#include <cstdint>
#include <cstring>
#include <utility>
#include <vector>

class SkBlender;
class SkMesh;
class SkVertices;

using namespace skia_private;

SkPDFDevice::MarkedContentManager::MarkedContentManager(SkPDFDocument* document,
                                                        SkDynamicMemoryWStream* out)
    : fDoc(document)
    , fOut(out)
    , fCurrentlyActiveMark()
    , fNextMarksElemId(0)
    , fCurrentMarksElemId(0)
    , fMadeMarks(false)
{}

SkPDFDevice::MarkedContentManager::~MarkedContentManager() {
    // This does not close the last open mark, that is done in SkPDFDevice::content.
    SkASSERT(fNextMarksElemId == 0);
}

void SkPDFDevice::MarkedContentManager::setNextMarksElemId(int nextMarksElemId) {
    fNextMarksElemId = nextMarksElemId;
}
int SkPDFDevice::MarkedContentManager::elemId() const { return fNextMarksElemId; }

void SkPDFDevice::MarkedContentManager::beginMark() {
    if (fNextMarksElemId == fCurrentMarksElemId) {
        return;
    }
    if (fCurrentMarksElemId) {
        // End this mark
        fOut->writeText("EMC\n");
        fCurrentlyActiveMark = SkPDFStructTree::Mark();
        fCurrentMarksElemId = 0;
    }
    if (fNextMarksElemId) {
        fCurrentlyActiveMark = fDoc->createMarkForElemId(fNextMarksElemId);
        if (fCurrentlyActiveMark) {
            // Begin this mark
            SkPDFUnion::Name(fCurrentlyActiveMark.structType()).emitObject(fOut);
            fOut->writeText(" <</MCID ");
            fOut->writeDecAsText(fCurrentlyActiveMark.mcid());
            fOut->writeText(" >>BDC\n");
            fCurrentMarksElemId = fCurrentlyActiveMark.elemId();
            fMadeMarks = true;
        } else if (SkPDF::NodeID::BackgroundArtifact <= fNextMarksElemId &&
                   fNextMarksElemId <= SkPDF::NodeID::OtherArtifact &&
                   fDoc->hasCurrentPage())
        {
            fOut->writeText("/Artifact");
            if (fNextMarksElemId == SkPDF::NodeID::OtherArtifact) {
                fOut->writeText(" BMC\n");
            } else if (fNextMarksElemId == SkPDF::NodeID::PaginationArtifact ||
                       fNextMarksElemId == SkPDF::NodeID::PaginationHeaderArtifact ||
                       fNextMarksElemId == SkPDF::NodeID::PaginationFooterArtifact ||
                       fNextMarksElemId == SkPDF::NodeID::PaginationWatermarkArtifact)
            {
                fOut->writeText(" <</Type /Pagination");
                if (fNextMarksElemId == SkPDF::NodeID::PaginationHeaderArtifact) {
                    fOut->writeText(" /Subtype /Header");
                } else if  (fNextMarksElemId == SkPDF::NodeID::PaginationFooterArtifact) {
                    fOut->writeText(" /Subtype /Footer");
                } else if (fNextMarksElemId == SkPDF::NodeID::PaginationWatermarkArtifact) {
                    fOut->writeText(" /Subtype /Watermark");
                }
                fOut->writeText(" >>BDC\n");
            } else if (fNextMarksElemId == SkPDF::NodeID::LayoutArtifact) {
                fOut->writeText(" <</Type /Layout >>BDC\n");
            } else if (fNextMarksElemId == SkPDF::NodeID::PageArtifact) {
                fOut->writeText(" <</Type /Page >>BDC\n");
            } else if (fNextMarksElemId == SkPDF::NodeID::BackgroundArtifact) {
                fOut->writeText(" <</Type /Background >>BDC\n");
            }
            fCurrentMarksElemId = fNextMarksElemId;
        }
    }
}

bool SkPDFDevice::MarkedContentManager::hasActiveMark() const { return bool(fCurrentlyActiveMark); }

void SkPDFDevice::MarkedContentManager::accumulate(const SkPoint& p) {
    SkASSERT(fCurrentlyActiveMark);
    fCurrentlyActiveMark.accumulate(p);
}

// This function destroys the mask and either frees or takes the pixels.
sk_sp<SkImage> mask_to_greyscale_image(SkMaskBuilder* mask, SkPDFDocument* doc) {
    sk_sp<SkImage> img;
    SkPixmap pm(SkImageInfo::Make(mask->fBounds.width(), mask->fBounds.height(),
                                  kGray_8_SkColorType, kOpaque_SkAlphaType),
                mask->fImage, mask->fRowBytes);
    constexpr int imgQuality = SK_PDF_MASK_QUALITY;
    if constexpr (imgQuality <= 100 && imgQuality >= 0) {
        SkPDF::EncodeJpegCallback encodeJPEG = doc->metadata().jpegEncoder;
        SkPDF::DecodeJpegCallback decodeJPEG = doc->metadata().jpegDecoder;
        if (encodeJPEG && decodeJPEG) {
            SkDynamicMemoryWStream buffer;
            // By encoding this into jpeg, it be embedded efficiently during drawImage.
            if (encodeJPEG(&buffer, pm, imgQuality)) {
                std::unique_ptr<SkCodec> codec = decodeJPEG(buffer.detachAsData());
                SkASSERT(codec);
                img = SkCodecs::DeferredImage(std::move(codec));
                SkASSERT(img);
                if (img) {
                    SkMaskBuilder::FreeImage(mask->image());
                }
            }
        }
    }
    if (!img) {
        img = SkImages::RasterFromPixmap(
                pm, [](const void* p, void*) { SkMaskBuilder::FreeImage(const_cast<void*>(p)); }, nullptr);
    }
    *mask = SkMaskBuilder();  // destructive;
    return img;
}

sk_sp<SkImage> alpha_image_to_greyscale_image(const SkImage* mask) {
    int w = mask->width(), h = mask->height();
    SkBitmap greyBitmap;
    greyBitmap.allocPixels(SkImageInfo::Make(w, h, kGray_8_SkColorType, kOpaque_SkAlphaType));
    // TODO: support gpu images in pdf
    if (!mask->readPixels(nullptr, SkImageInfo::MakeA8(w, h),
                          greyBitmap.getPixels(), greyBitmap.rowBytes(), 0, 0)) {
        return nullptr;
    }
    greyBitmap.setImmutable();
    return greyBitmap.asImage();
}

static int add_resource(THashSet<SkPDFIndirectReference>& resources, SkPDFIndirectReference ref) {
    resources.add(ref);
    return ref.fValue;
}

static void draw_points(SkCanvas::PointMode mode,
                        SkSpan<const SkPoint> points,
                        const SkPaint& paint,
                        const SkIRect& bounds,
                        SkDevice* device) {
    SkRasterClip rc(bounds);
    skcpu::Draw draw;
    draw.fDst = SkPixmap(SkImageInfo::MakeUnknown(bounds.right(), bounds.bottom()), nullptr, 0);
    draw.fCTM = &device->localToDevice();
    draw.fRC = &rc;
    draw.drawPoints(mode, points, paint, device);
}

static void transform_shader(SkPaint* paint, const SkMatrix& ctm) {
    SkASSERT(!ctm.isIdentity());
#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
    // A shader's matrix is:  CTM x LocalMatrix x WrappingLocalMatrix.  We want to
    // switch to device space, where CTM = I, while keeping the original behavior.
    //
    //               I * LocalMatrix * NewWrappingMatrix = CTM * LocalMatrix
    //                   LocalMatrix * NewWrappingMatrix = CTM * LocalMatrix
    //  InvLocalMatrix * LocalMatrix * NewWrappingMatrix = InvLocalMatrix * CTM * LocalMatrix
    //                                 NewWrappingMatrix = InvLocalMatrix * CTM * LocalMatrix
    //
    SkMatrix lm = SkPDFUtils::GetShaderLocalMatrix(paint->getShader());
    SkMatrix lmInv;
    if (lm.invert(&lmInv)) {
        SkMatrix m = SkMatrix::Concat(SkMatrix::Concat(lmInv, ctm), lm);
        paint->setShader(paint->getShader()->makeWithLocalMatrix(m));
    }
    return;
#endif
    paint->setShader(paint->getShader()->makeWithLocalMatrix(ctm));
}


static SkTCopyOnFirstWrite<SkPaint> clean_paint(const SkPaint& srcPaint) {
    SkTCopyOnFirstWrite<SkPaint> paint(srcPaint);
    // If the paint will definitely draw opaquely, replace kSrc with
    // kSrcOver.  http://crbug.com/473572
    if (!paint->isSrcOver() &&
        SkBlendFastPath::kSrcOver == CheckFastPath(*paint, false))
    {
        paint.writable()->setBlendMode(SkBlendMode::kSrcOver);
    }
    if (paint->getColorFilter()) {
        // We assume here that PDFs all draw in sRGB.
        SkPaintPriv::RemoveColorFilter(paint.writable(), sk_srgb_singleton());
    }
    SkASSERT(!paint->getColorFilter());
    return paint;
}

static void set_style(SkTCopyOnFirstWrite<SkPaint>* paint, SkPaint::Style style) {
    if (paint->get()->getStyle() != style) {
        paint->writable()->setStyle(style);
    }
}

/* Calculate an inverted path's equivalent non-inverted path, given the
 * canvas bounds.
 * outPath may alias with invPath (since this is supported by PathOps).
 */
static bool calculate_inverse_path(const SkRect& bounds, const SkPath& invPath,
                                   SkPath* outPath) {
    SkASSERT(invPath.isInverseFillType());
    if (auto result = Op(SkPath::Rect(bounds), invPath, kIntersect_SkPathOp)) {
        *outPath = *result;
        return true;
    }
    return false;
}

sk_sp<SkDevice> SkPDFDevice::createDevice(const CreateInfo& cinfo, const SkPaint* layerPaint) {
    // PDF does not support image filters, so render them on CPU.
    // Note that this rendering is done at "screen" resolution (100dpi), not
    // printer resolution.

    // TODO: It may be possible to express some filters natively using PDF
    // to improve quality and file size (skbug.com/40034150)
    if ((layerPaint && (layerPaint->getImageFilter() || layerPaint->getColorFilter()))
        || (cinfo.fInfo.colorSpace() && !cinfo.fInfo.colorSpace()->isSRGB())) {
        // need to return a raster device, which we will detect in drawDevice()
        return SkBitmapDevice::Create(cinfo.fInfo,
                                      SkSurfaceProps());
    }
    return sk_make_sp<SkPDFDevice>(cinfo.fInfo.dimensions(), fDocument);
}

// A helper class to automatically finish a ContentEntry at the end of a
// drawing method and maintain the state needed between set up and finish.
class ScopedContentEntry {
public:
    ScopedContentEntry(SkPDFDevice* device,
                       const SkClipStack* clipStack,
                       const SkMatrix& matrix,
                       const SkPaint& paint,
                       SkScalar textScale = 0)
        : fDevice(device)
        , fBlendMode(SkBlendMode::kSrcOver)
        , fClipStack(clipStack)
    {
        if (matrix.hasPerspective()) {
            NOT_IMPLEMENTED(!matrix.hasPerspective(), false);
            return;
        }
        fBlendMode = paint.getBlendMode_or(SkBlendMode::kSrcOver);
        fContentStream =
            fDevice->setUpContentEntry(clipStack, matrix, paint, textScale, &fDstFormXObject);
    }
    ScopedContentEntry(SkPDFDevice* dev, const SkPaint& paint, SkScalar textScale = 0)
        : ScopedContentEntry(dev, &dev->cs(), dev->localToDevice(), paint, textScale) {}

    ~ScopedContentEntry() {
        if (fContentStream) {
            SkPath* shape = &fShape;
            if (shape->isEmpty()) {
                shape = nullptr;
            }
            fDevice->finishContentEntry(fClipStack, fBlendMode, fDstFormXObject, shape);
        }
    }

    explicit operator bool() const { return fContentStream != nullptr; }
    SkDynamicMemoryWStream* stream() { return fContentStream; }

    /* Returns true when we explicitly need the shape of the drawing. */
    bool needShape() {
        switch (fBlendMode) {
            case SkBlendMode::kClear:
            case SkBlendMode::kSrc:
            case SkBlendMode::kSrcIn:
            case SkBlendMode::kSrcOut:
            case SkBlendMode::kDstIn:
            case SkBlendMode::kDstOut:
            case SkBlendMode::kSrcATop:
            case SkBlendMode::kDstATop:
            case SkBlendMode::kModulate:
                return true;
            default:
                return false;
        }
    }

    /* Returns true unless we only need the shape of the drawing. */
    bool needSource() {
        if (fBlendMode == SkBlendMode::kClear) {
            return false;
        }
        return true;
    }

    /* If the shape is different than the alpha component of the content, then
     * setShape should be called with the shape.  In particular, images and
     * devices have rectangular shape.
     */
    void setShape(const SkPath& shape) {
        fShape = shape;
    }

private:
    SkPDFDevice* fDevice = nullptr;
    SkDynamicMemoryWStream* fContentStream = nullptr;
    SkBlendMode fBlendMode;
    SkPDFIndirectReference fDstFormXObject;
    SkPath fShape;
    const SkClipStack* fClipStack;
};

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

SkPDFDevice::SkPDFDevice(SkISize pageSize, SkPDFDocument* doc, const SkMatrix& transform)
        : SkClipStackDevice(SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height()),
                            SkSurfaceProps(SkSurfaceProps::kPreservesTransparentDraws_Flag,
                                           kUnknown_SkPixelGeometry))
        , fInitialTransform(transform)
        , fMarkManager(doc, &fContent)
        , fDocument(doc) {
    SkASSERT(!pageSize.isEmpty());
}

SkPDFDevice::~SkPDFDevice() = default;

void SkPDFDevice::reset() {
    fGraphicStateResources.reset();
    fXObjectResources.reset();
    fShaderResources.reset();
    fFontResources.reset();
    fContent.reset();
    fActiveStackState = SkPDFGraphicStackState();
}

void SkPDFDevice::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
    if (!value || !fDocument->hasCurrentPage()) {
        return;
    }
    // Annotations are specified in absolute coordinates, so the page xform maps from device space
    // to the global space, and applies the document transform.
    SkMatrix pageXform = this->deviceToGlobal().asM33();
    pageXform.postConcat(fDocument->currentPageTransform());
    if (rect.isEmpty()) {
        if (!strcmp(key, SkPDFGetElemIdKey())) {
            int elemId;
            if (value->size() != sizeof(elemId)) { return; }
            memcpy(&elemId, value->data(), sizeof(elemId));
            fMarkManager.setNextMarksElemId(elemId);
            return;
        }
        if (!strcmp(SkAnnotationKeys::Define_Named_Dest_Key(), key)) {
            SkPoint p = this->localToDevice().mapPoint({rect.x(), rect.y()});
            p = pageXform.mapPoint(p);
            auto pg = fDocument->currentPage();
            fDocument->fNamedDestinations.push_back(SkPDFNamedDestination{sk_ref_sp(value), p, pg});
        }
        return;
    }
    // Convert to path to handle non-90-degree rotations.
    SkPath path = SkPath::Rect(rect).makeTransform(this->localToDevice());
    SkPath clip = SkClipStack_AsPath(this->cs());
    if (auto result = Op(clip, path, kIntersect_SkPathOp)) {
        path = *result;
    }
    // PDF wants a rectangle only.
    SkRect transformedRect = pageXform.mapRect(path.getBounds());
    if (transformedRect.isEmpty()) {
        return;
    }

    SkPDFLink::Type linkType = SkPDFLink::Type::kNone;
    if (!strcmp(SkAnnotationKeys::URL_Key(), key)) {
        linkType = SkPDFLink::Type::kUrl;
    } else if (!strcmp(SkAnnotationKeys::Link_Named_Dest_Key(), key)) {
        linkType = SkPDFLink::Type::kNamedDestination;
    }

    if (linkType != SkPDFLink::Type::kNone) {
        std::unique_ptr<SkPDFLink> link = std::make_unique<SkPDFLink>(
            linkType, value, transformedRect, fMarkManager.elemId());
        fDocument->fCurrentPageLinks.push_back(std::move(link));
    }
}

void SkPDFDevice::drawPaint(const SkPaint& srcPaint) {
    if (this->hasEmptyClip()) {
        return;
    }
    // Clip is in device space. Transform shader into device space.
    SkRect bbox = this->cs().bounds(this->bounds());
    bbox.roundOut(&bbox);
    SkPaint newPaint = srcPaint;
    newPaint.setStyle(SkPaint::kFill_Style);
    if (newPaint.getShader()) {
        newPaint.setShader(newPaint.getShader()->makeWithLocalMatrix(this->localToDevice()));
    }
    this->internalDrawPath(this->cs(), SkMatrix::I(), SkPath::Rect(bbox), newPaint, true);
}

void SkPDFDevice::drawPoints(SkCanvas::PointMode mode,
                             SkSpan<const SkPoint> points,
                             const SkPaint& srcPaint) {
    if (this->hasEmptyClip()) {
        return;
    }
    if (points.size() == 0) {
        return;
    }
    SkTCopyOnFirstWrite<SkPaint> paint(clean_paint(srcPaint));



    if (SkCanvas::kPoints_PointMode != mode) {
        set_style(&paint, SkPaint::kStroke_Style);
    }

    // skcpu::Draw::drawPoints converts to multiple calls to fDevice->drawPath.
    // We only use this when there's a path effect or perspective because of the overhead
    // of multiple calls to setUpContentEntry it causes.
    if (paint->getPathEffect() || this->localToDevice().hasPerspective()) {
        draw_points(mode, points, *paint, this->devClipBounds(), this);
        return;
    }


    if (mode == SkCanvas::kPoints_PointMode && paint->getStrokeCap() != SkPaint::kRound_Cap) {
        if (paint->getStrokeWidth()) {
            // PDF won't draw a single point with square/butt caps because the
            // orientation is ambiguous.  Draw a rectangle instead.
            set_style(&paint, SkPaint::kFill_Style);
            SkScalar strokeWidth = paint->getStrokeWidth();
            SkScalar halfStroke = SkScalarHalf(strokeWidth);
            for (auto&& pt : points) {
                SkRect r = SkRect::MakeXYWH(pt.fX, pt.fY, 0, 0);
                r.inset(-halfStroke, -halfStroke);
                this->drawRect(r, *paint);
            }
            return;
        } else {
            if (paint->getStrokeCap() != SkPaint::kRound_Cap) {
                paint.writable()->setStrokeCap(SkPaint::kRound_Cap);
            }
        }
    }

    ScopedContentEntry content(this, *paint);
    if (!content) {
        return;
    }
    SkDynamicMemoryWStream* contentStream = content.stream();
    fMarkManager.beginMark();
    if (fMarkManager.hasActiveMark()) {
        // Destinations are in absolute coordinates.
        SkMatrix pageXform = this->deviceToGlobal().asM33();
        pageXform.postConcat(fDocument->currentPageTransform());
        // The points do not already have localToDevice applied.
        pageXform.preConcat(this->localToDevice());

        for (auto&& userPoint : points) {
            fMarkManager.accumulate(pageXform.mapPoint(userPoint));
        }
    }
    const size_t count = points.size();
    switch (mode) {
        case SkCanvas::kPolygon_PointMode:
            SkPDFUtils::MoveTo(points[0].fX, points[0].fY, contentStream);
            for (size_t i = 1; i < count; i++) {
                SkPDFUtils::AppendLine(points[i].fX, points[i].fY, contentStream);
            }
            SkPDFUtils::StrokePath(contentStream);
            break;
        case SkCanvas::kLines_PointMode:
            for (size_t i = 0; i < count/2; i++) {
                SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY, contentStream);
                SkPDFUtils::AppendLine(points[i * 2 + 1].fX, points[i * 2 + 1].fY, contentStream);
                SkPDFUtils::StrokePath(contentStream);
            }
            break;
        case SkCanvas::kPoints_PointMode:
            SkASSERT(paint->getStrokeCap() == SkPaint::kRound_Cap);
            for (size_t i = 0; i < count; i++) {
                SkPDFUtils::MoveTo(points[i].fX, points[i].fY, contentStream);
                SkPDFUtils::ClosePath(contentStream);
                SkPDFUtils::StrokePath(contentStream);
            }
            break;
        default:
            SkASSERT(false);
    }
}

void SkPDFDevice::drawRect(const SkRect& rect, const SkPaint& paint) {
    SkRect r = rect;
    r.sort();
    this->internalDrawPath(this->cs(), this->localToDevice(), SkPath::Rect(r), paint, true);
}

void SkPDFDevice::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
    this->internalDrawPath(this->cs(), this->localToDevice(), SkPath::RRect(rrect), paint, true);
}

void SkPDFDevice::drawOval(const SkRect& oval, const SkPaint& paint) {
    this->internalDrawPath(this->cs(), this->localToDevice(), SkPath::Oval(oval), paint, true);
}

void SkPDFDevice::drawPath(const SkPath& path, const SkPaint& paint) {
    this->internalDrawPath(this->cs(), this->localToDevice(), path, paint, false);
}

void SkPDFDevice::internalDrawPathWithFilter(const SkClipStack& clipStack,
                                             const SkMatrix& ctm,
                                             const SkPath& origPath,
                                             const SkPaint& origPaint) {
    SkASSERT(origPaint.getMaskFilter());
    SkPathBuilder builder;
    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);

    SkStrokeRec::InitStyle initStyle = skpathutils::FillPathWithPaint(origPath, *paint, &builder)
                                     ? SkStrokeRec::kFill_InitStyle
                                     : SkStrokeRec::kHairline_InitStyle;
    builder.transform(ctm);
    const auto pathRaw = SkPathPriv::Raw(builder, SkResolveConvexity::kYes);
    if (!pathRaw) {
        return;
    }

    SkIRect bounds = clipStack.bounds(this->bounds()).roundOut();
    SkMaskBuilder sourceMask;
    if (!skcpu::DrawToMask(*pathRaw,
                           bounds,
                           paint->getMaskFilter(),
                           &SkMatrix::I(),
                           &sourceMask,
                           SkMaskBuilder::kComputeBoundsAndRenderImage_CreateMode,
                           initStyle)) {
        return;
    }
    SkAutoMaskFreeImage srcAutoMaskFreeImage(sourceMask.image());
    SkMaskBuilder dstMask;
    SkIPoint margin;
    if (!as_MFB(paint->getMaskFilter())->filterMask(&dstMask, sourceMask, ctm, &margin)) {
        return;
    }
    SkIRect dstMaskBounds = dstMask.fBounds;
    sk_sp<SkImage> mask = mask_to_greyscale_image(&dstMask, fDocument);
    // PDF doesn't seem to allow masking vector graphics with an Image XObject.
    // Must mask with a Form XObject.
    sk_sp<SkPDFDevice> maskDevice = this->makeCongruentDevice();
    {
        SkCanvas canvas(maskDevice);
        canvas.drawImage(mask, dstMaskBounds.x(), dstMaskBounds.y());
    }
    if (!ctm.isIdentity() && paint->getShader()) {
        transform_shader(paint.writable(), ctm); // Since we are using identity matrix.
    }
    ScopedContentEntry content(this, &clipStack, SkMatrix::I(), *paint);
    if (!content) {
        return;
    }
    this->setGraphicState(SkPDFGraphicState::GetSMaskGraphicState(
            maskDevice->makeFormXObjectFromDevice(dstMaskBounds, true), false,
            SkPDFGraphicState::kLuminosity_SMaskMode, fDocument), content.stream());
    SkPDFUtils::AppendRectangle(SkRect::Make(dstMaskBounds), content.stream());
    SkPDFUtils::PaintPath(SkPaint::kFill_Style, pathRaw->fillType(), content.stream());
    this->clearMaskOnGraphicState(content.stream());
}

void SkPDFDevice::setGraphicState(SkPDFIndirectReference gs, SkDynamicMemoryWStream* content) {
    SkPDFUtils::ApplyGraphicState(add_resource(fGraphicStateResources, gs), content);
}

void SkPDFDevice::clearMaskOnGraphicState(SkDynamicMemoryWStream* contentStream) {
    // The no-softmask graphic state is used to "turn off" the mask for later draw calls.
    SkPDFIndirectReference& noSMaskGS = fDocument->fNoSmaskGraphicState;
    if (!noSMaskGS) {
        SkPDFDict tmp("ExtGState");
        tmp.insertName("SMask", "None");
        noSMaskGS = fDocument->emit(tmp);
    }
    this->setGraphicState(noSMaskGS, contentStream);
}

void SkPDFDevice::internalDrawPath(const SkClipStack& clipStack,
                                   const SkMatrix& ctm,
                                   const SkPath& origPath,
                                   const SkPaint& srcPaint,
                                   bool pathIsMutable) {
    if (clipStack.isEmpty(this->bounds())) {
        return;
    }
    SkTCopyOnFirstWrite<SkPaint> paint(clean_paint(srcPaint));
    SkPath modifiedPath;
    SkPath* pathPtr = const_cast<SkPath*>(&origPath);

    if (paint->getMaskFilter()) {
        this->internalDrawPathWithFilter(clipStack, ctm, origPath, *paint);
        return;
    }

    SkMatrix matrix = ctm;

    if (paint->getPathEffect()) {
        if (clipStack.isEmpty(this->bounds())) {
            return;
        }
        SkPathBuilder builder;
        if (skpathutils::FillPathWithPaint(*pathPtr, *paint, &builder)) {
            set_style(&paint, SkPaint::kFill_Style);
        } else {
            set_style(&paint, SkPaint::kStroke_Style);
            if (paint->getStrokeWidth() != 0) {
                paint.writable()->setStrokeWidth(0);
            }
        }
        modifiedPath = builder.detach();
        pathPtr = &modifiedPath;
        pathIsMutable = true;
        paint.writable()->setPathEffect(nullptr);
    }

    if (this->handleInversePath(*pathPtr, *paint, pathIsMutable)) {
        return;
    }
    if (matrix.getType() & SkMatrix::kPerspective_Mask) {
        if (!pathIsMutable) {
            modifiedPath = origPath;
            pathPtr = &modifiedPath;
            pathIsMutable = true;
        }
        *pathPtr = pathPtr->makeTransform(matrix);
        if (paint->getShader()) {
            transform_shader(paint.writable(), matrix);
        }
        matrix = SkMatrix::I();
    }

    ScopedContentEntry content(this, &clipStack, matrix, *paint);
    if (!content) {
        return;
    }
    fMarkManager.beginMark();
    if (fMarkManager.hasActiveMark()) {
        // Destinations are in absolute coordinates.
        SkMatrix pageXform = this->deviceToGlobal().asM33();
        pageXform.postConcat(fDocument->currentPageTransform());
        // The path does not already have localToDevice / ctm / matrix applied.
        pageXform.preConcat(matrix);

        SkRect pathBounds = pathPtr->computeTightBounds();
        pageXform.mapRect(&pathBounds);
        fMarkManager.accumulate({pathBounds.fLeft, pathBounds.fBottom}); // y-up
    }
    constexpr SkScalar kToleranceScale = 0.0625f;  // smaller = better conics (circles).
    SkScalar matrixScale = matrix.mapRadius(1.0f);
    SkScalar tolerance = matrixScale > 0.0f ? kToleranceScale / matrixScale : kToleranceScale;
    bool discardEmptyVerbs =
           paint->getStyle() == SkPaint::kFill_Style ||
           (paint->getStrokeCap() != SkPaint::kRound_Cap &&
            paint->getStrokeCap() != SkPaint::kSquare_Cap);
    using SkPDFUtils::EmptyPath, SkPDFUtils::EmptyVerb;
    if (SkPDFUtils::EmitPath(*pathPtr, paint->getStyle(), EmptyPath::Discard,
                             discardEmptyVerbs ? EmptyVerb::Discard : EmptyVerb::Preserve,
                             content.stream(), tolerance))
    {
        SkPDFUtils::PaintPath(paint->getStyle(), pathPtr->getFillType(), content.stream());
    }
}

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

void SkPDFDevice::drawImageRect(const SkImage* image,
                                const SkRect* src,
                                const SkRect& dst,
                                const SkSamplingOptions& sampling,
                                const SkPaint& paint,
                                SkCanvas::SrcRectConstraint) {
    SkASSERT(image);
    this->internalDrawImageRect(SkKeyedImage(sk_ref_sp(const_cast<SkImage*>(image))),
                                src, dst, sampling, paint, this->localToDevice());
}

void SkPDFDevice::drawSprite(const SkBitmap& bm, int x, int y, const SkPaint& paint) {
    SkASSERT(!bm.drawsNothing());
    auto r = SkRect::MakeXYWH(x, y, bm.width(), bm.height());
    this->internalDrawImageRect(SkKeyedImage(bm), nullptr, r, SkSamplingOptions(), paint,
                                SkMatrix::I());
}

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

namespace {
class GlyphPositioner {
public:
    GlyphPositioner(SkDynamicMemoryWStream* content,
                    SkScalar textSkewX,
                    SkPoint origin)
        : fContent(content)
        , fCurrentMatrixOrigin(origin)
        , fTextSkewX(textSkewX) {
    }
    ~GlyphPositioner() { this->flush(); }
    void flush() {
        if (fInText) {
            fContent->writeText("> Tj\n");
            fInText = false;
        }
    }
    void setFont(SkPDFFont* pdfFont) {
        this->flush();
        fPDFFont = pdfFont;
        // Reader 2020.013.20064 incorrectly advances some Type3 fonts https://crbug.com/1226960
        bool convertedToType3 = fPDFFont->getType() == SkAdvancedTypefaceMetrics::kOther_Font;
        bool thousandEM = fPDFFont->strike().fPath.fUnitsPerEM == 1000;
        fViewersAgreeOnAdvancesInFont = thousandEM || !convertedToType3;
    }
    void writeGlyph(SkGlyphID glyph, SkScalar advanceWidth, SkPoint xy) {
        SkASSERT(fPDFFont);
        if (!fInitialized) {
            // Flip the text about the x-axis to account for origin swap and include
            // the passed parameters.
            fContent->writeText("1 0 ");
            SkPDFUtils::AppendScalar(-fTextSkewX, fContent);
            fContent->writeText(" -1 ");
            SkPDFUtils::AppendScalar(fCurrentMatrixOrigin.x(), fContent);
            fContent->writeText(" ");
            SkPDFUtils::AppendScalar(fCurrentMatrixOrigin.y(), fContent);
            fContent->writeText(" Tm\n");
            fCurrentMatrixOrigin.set(0.0f, 0.0f);
            fInitialized = true;
        }
        SkPoint position = xy - fCurrentMatrixOrigin;
        if (!fViewersAgreeOnXAdvance || position != SkPoint{fXAdvance, 0}) {
            this->flush();
            SkPDFUtils::AppendScalar(position.x() - position.y() * fTextSkewX, fContent);
            fContent->writeText(" ");
            SkPDFUtils::AppendScalar(-position.y(), fContent);
            fContent->writeText(" Td ");
            fCurrentMatrixOrigin = xy;
            fXAdvance = 0;
            fViewersAgreeOnXAdvance = true;
        }
        fXAdvance += advanceWidth;
        if (!fViewersAgreeOnAdvancesInFont) {
            fViewersAgreeOnXAdvance = false;
        }
        if (!fInText) {
            fContent->writeText("<");
            fInText = true;
        }
        if (fPDFFont->multiByteGlyphs()) {
            SkPDFUtils::WriteUInt16BE(fContent, glyph);
        } else {
            SkASSERT(0 == glyph >> 8);
            SkPDFUtils::WriteUInt8(fContent, static_cast<uint8_t>(glyph));
        }
    }

private:
    SkDynamicMemoryWStream* fContent;
    SkPDFFont* fPDFFont = nullptr;
    SkPoint fCurrentMatrixOrigin;
    SkScalar fXAdvance = 0.0f;
    bool fViewersAgreeOnAdvancesInFont = true;
    bool fViewersAgreeOnXAdvance = true;
    SkScalar fTextSkewX;
    bool fInText = false;
    bool fInitialized = false;
};
}  // namespace

namespace {
struct PositionedGlyph {
    SkPoint fPos;
    SkGlyphID fGlyph;
};
}  // namespace

static SkRect get_glyph_bounds_device_space(const SkGlyph* glyph,
                                            SkScalar xScale, SkScalar yScale,
                                            SkPoint xy, const SkMatrix& ctm) {
    SkRect glyphBounds = SkMatrix::Scale(xScale, yScale).mapRect(glyph->rect());
    glyphBounds.offset(xy);
    ctm.mapRect(&glyphBounds); // now in dev space.
    return glyphBounds;
}

static bool contains(const SkRect& r, SkPoint p) {
   return r.left() <= p.x() && p.x() <= r.right() &&
          r.top()  <= p.y() && p.y() <= r.bottom();
}

void SkPDFDevice::drawGlyphRunAsPath(
        const sktext::GlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint) {
    const SkFont& font = glyphRun.font();

    struct Rec {
        SkPathBuilder fBuilder;
        SkPoint fOffset;
        const SkPoint* fPos;
    } rec = {{}, offset, glyphRun.positions().data()};

    font.getPaths(glyphRun.glyphsIDs(),
                  [](const SkPath* path, const SkMatrix& mx, void* ctx) {
                      Rec* rec = reinterpret_cast<Rec*>(ctx);
                      if (path) {
                          SkMatrix total = mx;
                          total.postTranslate(rec->fPos->fX + rec->fOffset.fX,
                                              rec->fPos->fY + rec->fOffset.fY);
                          rec->fBuilder.addPath(*path, total);
                      }
                      rec->fPos += 1; // move to the next glyph's position
                  }, &rec);
    this->internalDrawPath(this->cs(), this->localToDevice(),
                           rec.fBuilder.detach(), runPaint, true);

    SkFont transparentFont = glyphRun.font();
    transparentFont.setEmbolden(false); // Stop Recursion
    sktext::GlyphRun tmpGlyphRun(glyphRun, transparentFont);

    SkPaint transparent;
    transparent.setColor(SK_ColorTRANSPARENT);

    if (this->localToDevice().hasPerspective()) {
        SkAutoDeviceTransformRestore adr(this, SkM44());
        this->internalDrawGlyphRun(tmpGlyphRun, offset, transparent);
    } else {
        this->internalDrawGlyphRun(tmpGlyphRun, offset, transparent);
    }
}

static bool needs_new_font(SkPDFFont* font, const SkGlyph* glyph,
                           SkAdvancedTypefaceMetrics::FontType initialFontType) {
    if (!font || !font->hasGlyph(glyph->getGlyphID())) {
        return true;
    }
    if (initialFontType == SkAdvancedTypefaceMetrics::kOther_Font) {
        return false;
    }
    if (glyph->isEmpty()) {
        return false;
    }

    bool hasUnmodifiedPath = glyph->path() && !glyph->pathIsModified();
    bool convertedToType3 = font->getType() == SkAdvancedTypefaceMetrics::kOther_Font;
    return convertedToType3 == hasUnmodifiedPath;
}

void SkPDFDevice::internalDrawGlyphRun(
        const sktext::GlyphRun& glyphRun, SkPoint offset, const SkPaint& runPaint) {

    const SkGlyphID* glyphIDs = glyphRun.glyphsIDs().data();
    uint32_t glyphCount = SkToU32(glyphRun.glyphsIDs().size());
    const SkFont& glyphRunFont = glyphRun.font();

    if (!glyphCount || !glyphIDs || glyphRunFont.getSize() <= 0 || this->hasEmptyClip()) {
        return;
    }

    // TODO: SkPDFFont has code to handle paints with mask filters, but the viewers do not.
    // See https://crbug.com/362796158 for Pdfium and b/325266484 for Preview
    if (this->localToDevice().hasPerspective() || runPaint.getMaskFilter()) {
        this->drawGlyphRunAsPath(glyphRun, offset, runPaint);
        return;
    }

    sk_sp<SkPDFStrike> pdfStrike = SkPDFStrike::Make(fDocument, glyphRunFont, runPaint);
    if (!pdfStrike) {
        return;
    }
    const SkTypeface& typeface = pdfStrike->fPath.fStrikeSpec.typeface();

    const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, fDocument);
    if (!metrics) {
        return;
    }

    const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(typeface, fDocument);
    THashMap<SkGlyphID, SkString>& glyphToUnicodeEx=SkPDFFont::GetUnicodeMapEx(typeface, fDocument);

    // TODO: FontType should probably be on SkPDFStrike?
    SkAdvancedTypefaceMetrics::FontType initialFontType = SkPDFFont::FontType(*pdfStrike, *metrics);

    SkClusterator clusterator(glyphRun);

    // The size, skewX, and scaleX are applied here.
    SkScalar textSize = glyphRunFont.getSize();
    SkScalar advanceScale = textSize * glyphRunFont.getScaleX() / pdfStrike->fPath.fUnitsPerEM;

    // textScaleX and textScaleY are used to get a conservative bounding box for glyphs.
    SkScalar textScaleY = textSize / pdfStrike->fPath.fUnitsPerEM;
    SkScalar textScaleX = advanceScale + glyphRunFont.getSkewX() * textScaleY;

    SkRect clipStackBounds = this->cs().bounds(this->bounds());

    // Clear everything from the runPaint that will be applied by the strike.
    SkPaint fillPaint(runPaint);
    if (fillPaint.getStrokeWidth() > 0) {
        fillPaint.setStroke(false);
    }
    fillPaint.setPathEffect(nullptr);
    fillPaint.setMaskFilter(nullptr);
    SkTCopyOnFirstWrite<SkPaint> paint(clean_paint(fillPaint));
    ScopedContentEntry content(this, *paint, glyphRunFont.getScaleX());
    if (!content) {
        return;
    }
    SkDynamicMemoryWStream* out = content.stream();

    // Destinations are in absolute coordinates.
    // The glyphs bounds go through the localToDevice separately for clipping.
    SkMatrix pageXform = this->deviceToGlobal().asM33();
    pageXform.postConcat(fDocument->currentPageTransform());

    fMarkManager.beginMark();
    if (!glyphRun.text().empty()) {
        fDocument->addStructElemTitle(fMarkManager.elemId(), glyphRun.text());
    }

    out->writeText("BT\n");
    SK_AT_SCOPE_EXIT(out->writeText("ET\n"));

    const int numGlyphs = typeface.countGlyphs();

    if (clusterator.reversedChars()) {
        out->writeText("/ReversedChars BMC\n");
    }
    SK_AT_SCOPE_EXIT(if (clusterator.reversedChars()) { out->writeText("EMC\n"); } );
    GlyphPositioner glyphPositioner(out, glyphRunFont.getSkewX(), offset);
    SkPDFFont* font = nullptr;

    SkBulkGlyphMetricsAndPaths paths{pdfStrike->fPath.fStrikeSpec};
    auto glyphs = paths.glyphs(glyphRun.glyphsIDs());

    while (SkClusterator::Cluster c = clusterator.next()) {
        int glyphIndex = c.fGlyphIndex;
        int glyphLimit = glyphIndex + c.fGlyphCount;

        bool actualText = false;
        SK_AT_SCOPE_EXIT(if (actualText) {
                             glyphPositioner.flush();
                             out->writeText("EMC\n");
                         });
        if (c.fUtf8Text) {
            bool toUnicode = false;
            const char* textPtr = c.fUtf8Text;
            const char* textEnd = c.fUtf8Text + c.fTextByteLength;
            SkUnichar clusterUnichar = SkUTF::NextUTF8(&textPtr, textEnd);
            // ToUnicode can only handle one glyph in a cluster.
            if (clusterUnichar >= 0 && c.fGlyphCount == 1) {
                SkGlyphID gid = glyphIDs[glyphIndex];
                SkUnichar fontUnichar = gid < glyphToUnicode.size() ? glyphToUnicode[gid] : 0;

                // The regular cmap can handle this if there is one glyph in the cluster,
                // one code point in the cluster, and the glyph maps to the code point.
                toUnicode = textPtr == textEnd && clusterUnichar == fontUnichar;

                // The extended cmap can handle this if there is one glyph in the cluster,
                // the font has no code point for the glyph,
                // there are less than 512 bytes in the UTF-16,
                // and the mapping matches or can be added.
                // UTF-16 uses at most 2x space of UTF-8; 64 code points seems enough.
                if (!toUnicode && fontUnichar <= 0 && c.fTextByteLength < 256) {
                    SkString* unicodes = glyphToUnicodeEx.find(gid);
                    if (!unicodes) {
                        glyphToUnicodeEx.set(gid, SkString(c.fUtf8Text, c.fTextByteLength));
                        toUnicode = true;
                    } else if (unicodes->equals(c.fUtf8Text, c.fTextByteLength)) {
                        toUnicode = true;
                    }
                }
            }
            if (!toUnicode) {
                glyphPositioner.flush();
                // Begin marked-content sequence with associated property list.
                out->writeText("/Span<</ActualText ");
                SkPDFWriteTextString(out, c.fUtf8Text, c.fTextByteLength);
                out->writeText(" >> BDC\n");
                actualText = true;
            }
        }
        for (; glyphIndex < glyphLimit; ++glyphIndex) {
            SkGlyphID gid = glyphIDs[glyphIndex];
            if (numGlyphs <= gid) {
                continue;
            }
            SkPoint xy = glyphRun.positions()[glyphIndex];
            // Do a glyph-by-glyph bounds-reject if positions are absolute.
            SkRect glyphBounds = get_glyph_bounds_device_space(
                    glyphs[glyphIndex], textScaleX, textScaleY,
                    xy + offset, this->localToDevice());
            if (glyphBounds.isEmpty()) {
                if (!contains(clipStackBounds, {glyphBounds.x(), glyphBounds.y()})) {
                    continue;
                }
            } else {
                if (!clipStackBounds.intersects(glyphBounds)) {
                    continue;  // reject glyphs as out of bounds
                }
            }
            if (needs_new_font(font, glyphs[glyphIndex], initialFontType)) {
                // Not yet specified font or need to switch font.
                font = pdfStrike->getFontResource(glyphs[glyphIndex]);
                SkASSERT(font);  // All preconditions for SkPDFFont::GetFontResource are met.
                glyphPositioner.setFont(font);
                SkPDFWriteResourceName(out, SkPDFResourceType::kFont,
                                       add_resource(fFontResources, font->indirectReference()));
                out->writeText(" ");
                SkPDFUtils::AppendScalar(textSize, out);
                out->writeText(" Tf\n");

            }
            font->noteGlyphUsage(gid);
            SkGlyphID encodedGlyph = font->glyphToPDFFontEncoding(gid);
            SkScalar advance = advanceScale * glyphs[glyphIndex]->advanceX();
            if (fMarkManager.hasActiveMark()) {
                SkRect pageGlyphBounds = pageXform.mapRect(glyphBounds);
                fMarkManager.accumulate({pageGlyphBounds.fLeft, pageGlyphBounds.fBottom}); // y-up
            }
            glyphPositioner.writeGlyph(encodedGlyph, advance, xy);
        }
    }
}

void SkPDFDevice::onDrawGlyphRunList(SkCanvas*,
                                     const sktext::GlyphRunList& glyphRunList,
                                     const SkPaint& paint) {
    SkASSERT(!glyphRunList.hasRSXForm());
    for (const sktext::GlyphRun& glyphRun : glyphRunList) {
        this->internalDrawGlyphRun(glyphRun, glyphRunList.origin(), paint);
    }
}

void SkPDFDevice::drawVertices(const SkVertices*, sk_sp<SkBlender>, const SkPaint&, bool) {
    if (this->hasEmptyClip()) {
        return;
    }
    // TODO: implement drawVertices
}

void SkPDFDevice::drawMesh(const SkMesh&, sk_sp<SkBlender>, const SkPaint&) {
    if (this->hasEmptyClip()) {
        return;
    }
    // TODO: implement drawMesh
}

void SkPDFDevice::drawFormXObject(SkPDFIndirectReference xObject, SkDynamicMemoryWStream* content,
                                  SkPath* shape) {
    fMarkManager.beginMark();
    if (fMarkManager.hasActiveMark() && shape) {
        // Destinations are in absolute coordinates.
        SkMatrix pageXform = this->deviceToGlobal().asM33();
        pageXform.postConcat(fDocument->currentPageTransform());
        // The shape already has localToDevice applied.

        SkRect shapeBounds = shape->computeTightBounds();
        pageXform.mapRect(&shapeBounds);
        fMarkManager.accumulate({shapeBounds.fLeft, shapeBounds.fBottom}); // y-up
    }

    SkASSERT(xObject);
    SkPDFWriteResourceName(content, SkPDFResourceType::kXObject,
                           add_resource(fXObjectResources, xObject));
    content->writeText(" Do\n");
}

sk_sp<SkSurface> SkPDFDevice::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
    return SkSurfaces::Raster(info, &props);
}

static std::vector<SkPDFIndirectReference> sort(const THashSet<SkPDFIndirectReference>& src) {
    std::vector<SkPDFIndirectReference> dst;
    dst.reserve(src.count());
    for (SkPDFIndirectReference ref : src) {
        dst.push_back(ref);
    }
    std::sort(dst.begin(), dst.end(),
            [](SkPDFIndirectReference a, SkPDFIndirectReference b) { return a.fValue < b.fValue; });
    return dst;
}

std::unique_ptr<SkPDFDict> SkPDFDevice::makeResourceDict() {
    return SkPDFMakeResourceDict(sort(fGraphicStateResources),
                                 sort(fShaderResources),
                                 sort(fXObjectResources),
                                 sort(fFontResources));
}

std::unique_ptr<SkStreamAsset> SkPDFDevice::content() {
    if (fActiveStackState.fContentStream) {
        fActiveStackState.drainStack();
        fActiveStackState = SkPDFGraphicStackState();
    }
    if (fContent.bytesWritten() == 0) {
        return std::make_unique<SkMemoryStream>();
    }

    // Implicitly close any still active marked-content sequence.
    // Must do this before fContent is written to buffer.
    fMarkManager.setNextMarksElemId(0);
    fMarkManager.beginMark();

    SkDynamicMemoryWStream buffer;
    if (fInitialTransform.getType() != SkMatrix::kIdentity_Mask) {
        SkPDFUtils::AppendTransform(fInitialTransform, &buffer);
    }
    if (fNeedsExtraSave) {
        buffer.writeText("q\n");
    }
    fContent.writeToAndReset(&buffer);
    if (fNeedsExtraSave) {
        buffer.writeText("Q\n");
    }
    fNeedsExtraSave = false;
    return std::unique_ptr<SkStreamAsset>(buffer.detachAsStream());
}

/* Draws an inverse filled path by using Path Ops to compute the positive
 * inverse using the current clip as the inverse bounds.
 * Return true if this was an inverse path and was properly handled,
 * otherwise returns false and the normal drawing routine should continue,
 * either as a (incorrect) fallback or because the path was not inverse
 * in the first place.
 */
bool SkPDFDevice::handleInversePath(const SkPath& origPath,
                                    const SkPaint& srcPaint,
                                    bool pathIsMutable) {
    // Assume the caller has already applied the path effect.
    SkASSERT(!srcPaint.getPathEffect());

    if (!origPath.isInverseFillType()) {
        return false;
    }

    if (this->hasEmptyClip()) {
        return false;
    }

    SkTCopyOnFirstWrite<SkPaint> paint(srcPaint);
    SkPath modifiedPath;
    const SkPath* pathPtr = &origPath;

    // Merge stroking operations into final path.
    if (SkPaint::kStroke_Style == paint->getStyle() ||
        SkPaint::kStrokeAndFill_Style == paint->getStyle())
    {
        SkPathBuilder builder;
        bool doFillPath = skpathutils::FillPathWithPaint(origPath, *paint, &builder);
        modifiedPath = builder.detach();
        pathPtr = &modifiedPath;

        if (doFillPath) {
            SkPaint* modifiedPaint = paint.writable();
            modifiedPaint->setStyle(SkPaint::kFill_Style);
            modifiedPaint->setStrokeWidth(0);
        } else {
            // Hairline strokes are rendered non-inverted.
            modifiedPath.toggleInverseFillType();
            this->internalDrawPath(this->cs(), this->localToDevice(), modifiedPath, *paint, true);
            return true;
        }
    }

    // Clip is in device space. Transform path and shader into device space.
    SkRect bounds = this->cs().bounds(this->bounds());
    modifiedPath = pathPtr->makeTransform(this->localToDevice());
    if (!calculate_inverse_path(bounds, modifiedPath, &modifiedPath)) {
        return false;
    }
    if (paint->getShader()) {
        paint.writable()->setShader(paint->getShader()->makeWithLocalMatrix(this->localToDevice()));
    }
    this->internalDrawPath(this->cs(), SkMatrix::I(), modifiedPath, *paint, true);
    return true;
}

SkPDFIndirectReference SkPDFDevice::makeFormXObjectFromDevice(SkIRect bounds, bool alpha) {
    SkMatrix inverseTransform = SkMatrix::I();
    if (auto inv = fInitialTransform.invert()) {
        inverseTransform = *inv;
    } else {
        SkDEBUGFAIL("Layer initial transform should be invertible.");
    }
    const char* colorSpace = alpha ? "DeviceGray" : nullptr;

    SkPDFIndirectReference xobject =
        SkPDFMakeFormXObject(fDocument, this->content(),
                             SkPDFMakeArray(bounds.left(), bounds.top(),
                                            bounds.right(), bounds.bottom()),
                             this->makeResourceDict(), inverseTransform, colorSpace);
    // We always draw the form xobjects that we create back into the device, so
    // we simply preserve the font usage instead of pulling it out and merging
    // it back in later.
    this->reset();
    return xobject;
}

SkPDFIndirectReference SkPDFDevice::makeFormXObjectFromDevice(bool alpha) {
    return this->makeFormXObjectFromDevice(SkIRect{0, 0, this->width(), this->height()}, alpha);
}

void SkPDFDevice::drawFormXObjectWithMask(SkPDFIndirectReference xObject,
                                          SkPDFIndirectReference sMask,
                                          SkBlendMode mode,
                                          bool invertClip) {
    SkASSERT(sMask);
    SkPaint paint;
    paint.setBlendMode(mode);
    ScopedContentEntry content(this, nullptr, SkMatrix::I(), paint);
    if (!content) {
        return;
    }
    this->setGraphicState(SkPDFGraphicState::GetSMaskGraphicState(
            sMask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode,
            fDocument), content.stream());
    this->drawFormXObject(xObject, content.stream(), nullptr);
    this->clearMaskOnGraphicState(content.stream());
}


static bool treat_as_regular_pdf_blend_mode(SkBlendMode blendMode) {
    return nullptr != SkPDFUtils::BlendModeName(blendMode);
}

static void populate_graphic_state_entry_from_paint(
        SkPDFDocument* doc,
        const SkMatrix& matrix,
        const SkClipStack* clipStack,
        SkIRect deviceBounds,
        const SkPaint& paint,
        const SkMatrix& initialTransform,
        SkScalar textScale,
        SkPDFGraphicStackState::Entry* entry,
        THashSet<SkPDFIndirectReference>* shaderResources,
        THashSet<SkPDFIndirectReference>* graphicStateResources) {
    NOT_IMPLEMENTED(paint.getPathEffect() != nullptr, false);
    NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false);
    NOT_IMPLEMENTED(paint.getColorFilter() != nullptr, false);

    entry->fMatrix = matrix;
    entry->fClipStackGenID = clipStack ? clipStack->getTopmostGenID()
                                       : SkClipStack::kWideOpenGenID;
    SkColor4f color = paint.getColor4f();
    entry->fColor = {color.fR, color.fG, color.fB, 1};
    entry->fShaderIndex = -1;

    // PDF treats a shader as a color, so we only set one or the other.
    SkShader* shader = paint.getShader();
    if (shader) {
        if (as_SB(shader)->type() == SkShaderBase::ShaderType::kColor) {
            auto colorShader = static_cast<SkColorShader*>(shader);
            // We don't have to set a shader just for a color.
            color = colorShader->color();
            color.fA *= paint.getAlphaf();
            entry->fColor = colorShader->color().makeOpaque();
        } else {
            // PDF positions patterns relative to the initial transform, so
            // we need to apply the current transform to the shader parameters.
            SkMatrix transform = matrix;
            transform.postConcat(initialTransform);

            // PDF doesn't support kClamp_TileMode, so we simulate it by making
            // a pattern the size of the current clip.
            SkRect clipStackBounds = clipStack ? clipStack->bounds(deviceBounds)
                                               : SkRect::Make(deviceBounds);

            // We need to apply the initial transform to bounds in order to get
            // bounds in a consistent coordinate system.
            initialTransform.mapRect(&clipStackBounds);
            SkIRect bounds;
            clipStackBounds.roundOut(&bounds);

            // Use alpha 1 for the shader, the paint alpha is applied with newGraphicsState (below)
            auto c = paint.getColor4f();
            SkPDFIndirectReference pdfShader = SkPDFMakeShader(doc, shader, transform, bounds,
                                                               {c.fR, c.fG, c.fB, 1.0f});

            if (pdfShader) {
                // pdfShader has been canonicalized so we can directly compare pointers.
                entry->fShaderIndex = add_resource(*shaderResources, pdfShader);
            }
        }
    }

    SkPDFIndirectReference newGraphicState;
    if (color == paint.getColor4f()) {
        newGraphicState = SkPDFGraphicState::GetGraphicStateForPaint(doc, paint);
    } else {
        SkPaint newPaint = paint;
        newPaint.setColor4f(color, nullptr);
        newGraphicState = SkPDFGraphicState::GetGraphicStateForPaint(doc, newPaint);
    }
    entry->fGraphicStateIndex = add_resource(*graphicStateResources, newGraphicState);
    entry->fTextScaleX = textScale;
}

SkDynamicMemoryWStream* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
                                                       const SkMatrix& matrix,
                                                       const SkPaint& paint,
                                                       SkScalar textScale,
                                                       SkPDFIndirectReference* dst) {
    SkASSERT(!*dst);
    SkBlendMode blendMode = paint.getBlendMode_or(SkBlendMode::kSrcOver);

    // Dst xfer mode doesn't draw source at all.
    if (blendMode == SkBlendMode::kDst) {
        return nullptr;
    }

    // For the following modes, we want to handle source and destination
    // separately, so make an object of what's already there.
    if (!treat_as_regular_pdf_blend_mode(blendMode) && blendMode != SkBlendMode::kDstOver) {
        if (!isContentEmpty()) {
            *dst = this->makeFormXObjectFromDevice();
            SkASSERT(isContentEmpty());
        } else if (blendMode != SkBlendMode::kSrc &&
                   blendMode != SkBlendMode::kSrcOut) {
            // Except for Src and SrcOut, if there isn't anything already there,
            // then we're done.
            return nullptr;
        }
    }
    // TODO(vandebo): Figure out how/if we can handle the following modes:
    // Xor, Plus.  For now, we treat them as SrcOver/Normal.

    if (treat_as_regular_pdf_blend_mode(blendMode)) {
        if (!fActiveStackState.fContentStream) {
            if (fContent.bytesWritten() != 0) {
                fContent.writeText("Q\nq\n");
                fNeedsExtraSave = true;
            }
            fActiveStackState = SkPDFGraphicStackState(&fContent);
        } else {
            SkASSERT(fActiveStackState.fContentStream = &fContent);
        }
    } else {
        fActiveStackState.drainStack();
        fActiveStackState = SkPDFGraphicStackState(&fContentBuffer);
    }
    SkASSERT(fActiveStackState.fContentStream);
    SkPDFGraphicStackState::Entry entry;
    populate_graphic_state_entry_from_paint(
            fDocument,
            matrix,
            clipStack,
            this->bounds(),
            paint,
            fInitialTransform,
            textScale,
            &entry,
            &fShaderResources,
            &fGraphicStateResources);
    fActiveStackState.updateClip(clipStack, this->bounds());
    fActiveStackState.updateMatrix(entry.fMatrix);
    fActiveStackState.updateDrawingState(entry);

    return fActiveStackState.fContentStream;
}

void SkPDFDevice::finishContentEntry(const SkClipStack* clipStack,
                                     SkBlendMode blendMode,
                                     SkPDFIndirectReference dst,
                                     SkPath* shape) {
    SkASSERT(blendMode != SkBlendMode::kDst);
    if (treat_as_regular_pdf_blend_mode(blendMode)) {
        SkASSERT(!dst);
        return;
    }

    SkASSERT(fActiveStackState.fContentStream);

    fActiveStackState.drainStack();
    fActiveStackState = SkPDFGraphicStackState();

    if (blendMode == SkBlendMode::kDstOver) {
        SkASSERT(!dst);
        if (fContentBuffer.bytesWritten() != 0) {
            if (fContent.bytesWritten() != 0) {
                fContentBuffer.writeText("Q\nq\n");
                fNeedsExtraSave = true;
            }
            fContentBuffer.prependToAndReset(&fContent);
            SkASSERT(fContentBuffer.bytesWritten() == 0);
        }
        return;
    }
    if (fContentBuffer.bytesWritten() != 0) {
        if (fContent.bytesWritten() != 0) {
            fContent.writeText("Q\nq\n");
            fNeedsExtraSave = true;
        }
        fContentBuffer.writeToAndReset(&fContent);
        SkASSERT(fContentBuffer.bytesWritten() == 0);
    }

    if (!dst) {
        SkASSERT(blendMode == SkBlendMode::kSrc ||
                 blendMode == SkBlendMode::kSrcOut);
        return;
    }

    SkASSERT(dst);
    // Changing the current content into a form-xobject will destroy the clip
    // objects which is fine since the xobject will already be clipped. However
    // if source has shape, we need to clip it too, so a copy of the clip is
    // saved.

    SkPaint stockPaint;

    SkPDFIndirectReference srcFormXObject;
    if (this->isContentEmpty()) {
        // If nothing was drawn and there's no shape, then the draw was a
        // no-op, but dst needs to be restored for that to be true.
        // If there is shape, then an empty source with Src, SrcIn, SrcOut,
        // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop
        // reduces to Dst.
        if (shape == nullptr || blendMode == SkBlendMode::kDstOut ||
                blendMode == SkBlendMode::kSrcATop) {
            ScopedContentEntry content(this, nullptr, SkMatrix::I(), stockPaint);
            this->drawFormXObject(dst, content.stream(), nullptr);
            return;
        } else {
            blendMode = SkBlendMode::kClear;
        }
    } else {
        srcFormXObject = this->makeFormXObjectFromDevice();
    }

    // TODO(vandebo) srcFormXObject may contain alpha, but here we want it
    // without alpha.
    if (blendMode == SkBlendMode::kSrcATop) {
        // TODO(vandebo): In order to properly support SrcATop we have to track
        // the shape of what's been drawn at all times. It's the intersection of
        // the non-transparent parts of the device and the outlines (shape) of
        // all images and devices drawn.
        this->drawFormXObjectWithMask(srcFormXObject, dst, SkBlendMode::kSrcOver, true);
    } else {
        if (shape != nullptr) {
            // Draw shape into a form-xobject.
            SkPaint filledPaint;
            filledPaint.setColor(SK_ColorBLACK);
            filledPaint.setStyle(SkPaint::kFill_Style);
            SkClipStack empty;
            SkPDFDevice shapeDev(this->size(), fDocument, fInitialTransform);
            shapeDev.internalDrawPath(clipStack ? *clipStack : empty,
                                      SkMatrix::I(), *shape, filledPaint, true);
            this->drawFormXObjectWithMask(dst, shapeDev.makeFormXObjectFromDevice(),
                                          SkBlendMode::kSrcOver, true);
        } else {
            this->drawFormXObjectWithMask(dst, srcFormXObject, SkBlendMode::kSrcOver, true);
        }
    }

    if (blendMode == SkBlendMode::kClear) {
        return;
    } else if (blendMode == SkBlendMode::kSrc ||
            blendMode == SkBlendMode::kDstATop) {
        ScopedContentEntry content(this, nullptr, SkMatrix::I(), stockPaint);
        if (content) {
            this->drawFormXObject(srcFormXObject, content.stream(), nullptr);
        }
        if (blendMode == SkBlendMode::kSrc) {
            return;
        }
    } else if (blendMode == SkBlendMode::kSrcATop) {
        ScopedContentEntry content(this, nullptr, SkMatrix::I(), stockPaint);
        if (content) {
            this->drawFormXObject(dst, content.stream(), nullptr);
        }
    }

    SkASSERT(blendMode == SkBlendMode::kSrcIn   ||
             blendMode == SkBlendMode::kDstIn   ||
             blendMode == SkBlendMode::kSrcOut  ||
             blendMode == SkBlendMode::kDstOut  ||
             blendMode == SkBlendMode::kSrcATop ||
             blendMode == SkBlendMode::kDstATop ||
             blendMode == SkBlendMode::kModulate);

    if (blendMode == SkBlendMode::kSrcIn ||
            blendMode == SkBlendMode::kSrcOut ||
            blendMode == SkBlendMode::kSrcATop) {
        this->drawFormXObjectWithMask(srcFormXObject, dst, SkBlendMode::kSrcOver,
                                      blendMode == SkBlendMode::kSrcOut);
        return;
    } else {
        SkBlendMode mode = SkBlendMode::kSrcOver;
        if (blendMode == SkBlendMode::kModulate) {
            this->drawFormXObjectWithMask(srcFormXObject, dst, SkBlendMode::kSrcOver, false);
            mode = SkBlendMode::kMultiply;
        }
        this->drawFormXObjectWithMask(dst, srcFormXObject, mode, blendMode == SkBlendMode::kDstOut);
        return;
    }
}

bool SkPDFDevice::isContentEmpty() {
    return fContent.bytesWritten() == 0 && fContentBuffer.bytesWritten() == 0;
}

static SkSize rect_to_size(const SkRect& r) { return {r.width(), r.height()}; }

static sk_sp<SkImage> color_filter(const SkImage* image,
                                   SkColorFilter* colorFilter) {
    auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(image->dimensions()));
    SkASSERT(surface);
    SkCanvas* canvas = surface->getCanvas();
    canvas->clear(SK_ColorTRANSPARENT);
    SkPaint paint;
    paint.setColorFilter(sk_ref_sp(colorFilter));
    canvas->drawImage(image, 0, 0, SkSamplingOptions(), &paint);
    return surface->makeImageSnapshot();
}

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

static bool is_integer(SkScalar x) {
    return x == SkScalarTruncToScalar(x);
}

static bool is_integral(const SkRect& r) {
    return is_integer(r.left()) &&
           is_integer(r.top()) &&
           is_integer(r.right()) &&
           is_integer(r.bottom());
}

void SkPDFDevice::internalDrawImageRect(SkKeyedImage imageSubset,
                                        const SkRect* src,
                                        const SkRect& dst,
                                        const SkSamplingOptions& sampling,
                                        const SkPaint& srcPaint,
                                        const SkMatrix& ctm) {
    if (this->hasEmptyClip()) {
        return;
    }
    if (!imageSubset) {
        return;
    }

    SkKeyedImage originalImage = imageSubset;
    bool canUseOriginal = true;
    bool didSubset = false;

    // First, figure out the src->dst transform and subset the image if needed.
    SkIRect bounds = imageSubset.image()->bounds();
    SkRect srcRect = src ? *src : SkRect::Make(bounds);
    SkMatrix transform = SkMatrix::RectToRectOrIdentity(srcRect, dst);
    SkMatrix originalTransform = transform;
    if (src && *src != SkRect::Make(bounds)) {
        if (!srcRect.intersect(SkRect::Make(bounds))) {
            return;
        }
        srcRect.roundOut(&bounds);
        transform.preTranslate(SkIntToScalar(bounds.x()),
                               SkIntToScalar(bounds.y()));
        if (bounds != imageSubset.image()->bounds()) {
            imageSubset = imageSubset.subset(bounds);
            didSubset = true;
        }
        if (!imageSubset) {
            return;
        }
    }

    // If the image is opaque and the paint's alpha is too, replace
    // kSrc blendmode with kSrcOver.  http://crbug.com/473572
    SkTCopyOnFirstWrite<SkPaint> paint(srcPaint);
    if (!paint->isSrcOver() &&
        imageSubset.image()->isOpaque() &&
        SkBlendFastPath::kSrcOver == CheckFastPath(*paint, false))
    {
        paint.writable()->setBlendMode(SkBlendMode::kSrcOver);
    }

    // Alpha-only images need to get their color from the shader, before
    // applying the colorfilter.
    if (imageSubset.image()->isAlphaOnly() && paint->getColorFilter()) {
        // must blend alpha image and shader before applying colorfilter.
        auto surface =
                SkSurfaces::Raster(SkImageInfo::MakeN32Premul(imageSubset.image()->dimensions()));
        SkCanvas* canvas = surface->getCanvas();
        SkPaint tmpPaint;
        // In the case of alpha images with shaders, the shader's coordinate
        // system is the image's coordiantes.
        tmpPaint.setShader(sk_ref_sp(paint->getShader()));
        tmpPaint.setColor4f(paint->getColor4f(), nullptr);
        canvas->clear(0x00000000);
        canvas->drawImage(imageSubset.image().get(), 0, 0, sampling, &tmpPaint);
        if (paint->getShader() != nullptr) {
            paint.writable()->setShader(nullptr);
        }
        imageSubset = SkKeyedImage(surface->makeImageSnapshot());
        canUseOriginal = false;
        SkASSERT(!imageSubset.image()->isAlphaOnly());
    }

    if (imageSubset.image()->isAlphaOnly()) {
        // The ColorFilter applies to the paint color/shader, not the alpha layer.
        SkASSERT(nullptr == paint->getColorFilter());

        sk_sp<SkImage> mask = alpha_image_to_greyscale_image(imageSubset.image().get());
        if (!mask) {
            return;
        }
        // PDF doesn't seem to allow masking vector graphics with an Image XObject.
        // Must mask with a Form XObject.
        sk_sp<SkPDFDevice> maskDevice = this->makeCongruentDevice();
        {
            SkCanvas canvas(maskDevice);
            // This clip prevents the mask image shader from covering
            // entire device if unnecessary.
            canvas.clipRect(this->cs().bounds(this->bounds()));
            canvas.concat(ctm);
            if (paint->getMaskFilter()) {
                SkPaint tmpPaint;
                tmpPaint.setShader(mask->makeShader(SkSamplingOptions(), transform));
                tmpPaint.setMaskFilter(sk_ref_sp(paint->getMaskFilter()));
                canvas.drawRect(dst, tmpPaint);
            } else {
                if (src && !is_integral(*src)) {
                    canvas.clipRect(dst);
                }
                canvas.concat(transform);
                canvas.drawImage(mask, 0, 0);
            }
        }
        SkIRect maskDeviceBounds = maskDevice->cs().bounds(maskDevice->bounds()).roundOut();
        if (!ctm.isIdentity() && paint->getShader()) {
            transform_shader(paint.writable(), ctm); // Since we are using identity matrix.
        }
        ScopedContentEntry content(this, &this->cs(), SkMatrix::I(), *paint);
        if (!content) {
            return;
        }
        this->setGraphicState(SkPDFGraphicState::GetSMaskGraphicState(
                maskDevice->makeFormXObjectFromDevice(maskDeviceBounds, true), false,
                SkPDFGraphicState::kLuminosity_SMaskMode, fDocument), content.stream());
        SkPDFUtils::AppendRectangle(SkRect::Make(this->size()), content.stream());
        SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPathFillType::kWinding, content.stream());
        this->clearMaskOnGraphicState(content.stream());
        return;
    }
    if (paint->getMaskFilter()) {
        paint.writable()->setShader(imageSubset.image()->makeShader(SkSamplingOptions(),
                                                                    transform));
        SkPath path = SkPath::Rect(dst); // handles non-integral clipping.
        this->internalDrawPath(this->cs(), this->localToDevice(), path, *paint, true);
        return;
    }
    transform.postConcat(ctm);
    originalTransform.postConcat(ctm);

    SkMatrix matrix = transform;

    // Rasterize the bitmap using perspective in a new bitmap.
    if (transform.hasPerspective()) {
        // Transform the bitmap in the new space, without taking into
        // account the initial transform.
        SkRect imageBounds = SkRect::Make(imageSubset.image()->bounds());
        SkPath perspectiveOutline = SkPath::Rect(imageBounds).makeTransform(transform);

        // Retrieve the bounds of the new shape.
        SkRect outlineBounds = perspectiveOutline.getBounds();
        if (!outlineBounds.intersect(SkRect::Make(this->devClipBounds()))) {
            return;
        }

        // Transform the bitmap in the new space to the final space, to account for DPI
        SkRect physicalBounds = fInitialTransform.mapRect(outlineBounds);
        SkScalar scaleX = physicalBounds.width() / outlineBounds.width();
        SkScalar scaleY = physicalBounds.height() / outlineBounds.height();

        // TODO(edisonn): A better approach would be to use a bitmap shader
        // (in clamp mode) and draw a rect over the entire bounding box. Then
        // intersect perspectiveOutline to the clip. That will avoid introducing
        // alpha to the image while still giving good behavior at the edge of
        // the image.  Avoiding alpha will reduce the pdf size and generation
        // CPU time some.

        SkISize wh = rect_to_size(physicalBounds).toCeil();

        auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(wh));
        if (!surface) {
            return;
        }
        SkCanvas* canvas = surface->getCanvas();
        canvas->clear(SK_ColorTRANSPARENT);

        SkScalar deltaX = outlineBounds.left();
        SkScalar deltaY = outlineBounds.top();

        SkMatrix offsetMatrix = transform;
        offsetMatrix.postTranslate(-deltaX, -deltaY);
        offsetMatrix.postScale(scaleX, scaleY);

        // Translate the draw in the new canvas, so we perfectly fit the
        // shape in the bitmap.
        canvas->setMatrix(offsetMatrix);
        canvas->drawImage(imageSubset.image(), 0, 0);

        // In the new space, we use the identity matrix translated
        // and scaled to reflect DPI.
        matrix.setScale(1 / scaleX, 1 / scaleY);
        matrix.postTranslate(deltaX, deltaY);

        imageSubset = SkKeyedImage(surface->makeImageSnapshot());
        canUseOriginal = false;
        if (!imageSubset) {
            return;
        }
    }

    if (SkColorFilter* colorFilter = paint->getColorFilter()) {
        sk_sp<SkImage> img = color_filter(imageSubset.image().get(), colorFilter);
        imageSubset = SkKeyedImage(std::move(img));
        canUseOriginal = false;
        if (!imageSubset) {
            return;
        }
        // TODO(halcanary): de-dupe this by caching filtered images.
        // (maybe in the resource cache?)
    }

    bool useCroppedOriginal = false;
    if (didSubset && canUseOriginal) {
        size_t originalSize = SkPDFSerializeImageSize(
            originalImage.image().get(), fDocument, fDocument->metadata().fEncodingQuality);
        size_t subsetSize = SkPDFSerializeImageSize(
            imageSubset.image().get(), fDocument, fDocument->metadata().fEncodingQuality);
        if (originalSize <= subsetSize) {
            matrix = originalTransform;
            imageSubset = originalImage;
            useCroppedOriginal = true;
        }
    }

    // Need sub-pixel clipping to fix skbug.com/40035524
    SkClipStack::AutoRestore ar(&this->cs(), false);
    if ((src && !is_integral(*src)) || useCroppedOriginal) {
        this->cs().save();
        this->cs().clipRect(dst, ctm, SkClipOp::kIntersect, true);
    }

    SkMatrix scaled;
    // Adjust for origin flip.
    scaled.setScale(SK_Scalar1, -SK_Scalar1);
    scaled.postTranslate(0, SK_Scalar1);
    // Scale the image up from 1x1 to WxH.
    SkIRect subset = imageSubset.image()->bounds();
    scaled.postScale(SkIntToScalar(subset.width()),
                     SkIntToScalar(subset.height()));
    scaled.postConcat(matrix);
    ScopedContentEntry content(this, &this->cs(), scaled, *paint);
    if (!content) {
        return;
    }
    SkPath shape = SkPath::Rect(SkRect::Make(subset)).makeTransform(matrix);
    if (content.needShape()) {
        content.setShape(shape);
    }
    if (!content.needSource()) {
        return;
    }

    SkBitmapKey key = imageSubset.key();
    SkPDFIndirectReference* pdfimagePtr = fDocument->fPDFBitmapMap.find(key);
    SkPDFIndirectReference pdfimage = pdfimagePtr ? *pdfimagePtr : SkPDFIndirectReference();
    if (!pdfimagePtr) {
        SkASSERT(imageSubset);
        pdfimage = SkPDFSerializeImage(imageSubset.image().get(), fDocument,
                                       fDocument->metadata().fEncodingQuality);
        SkASSERT((key != SkBitmapKey{{0, 0, 0, 0}, 0}));
        fDocument->fPDFBitmapMap.set(key, pdfimage);
    }
    SkASSERT(pdfimage != SkPDFIndirectReference());
    this->drawFormXObject(pdfimage, content.stream(), &shape);
}

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


void SkPDFDevice::drawDevice(SkDevice* device, const SkSamplingOptions& sampling,
                             const SkPaint& paint) {
    SkASSERT(!paint.getImageFilter());
    SkASSERT(!paint.getMaskFilter());

    // Check if SkPDFDevice::createDevice returned an SkBitmapDevice.
    // SkPDFDevice::createDevice creates SkBitmapDevice for color filters.
    // Image filters generally go through makeSpecial and drawSpecial.
    SkPixmap pmap;
    if (device->peekPixels(&pmap)) {
        this->SkClipStackDevice::drawDevice(device, sampling, paint);
        return;
    }

    // Otherwise SkPDFDevice::createDevice() creates SkPDFDevice subclasses.
    SkPDFDevice* pdfDevice = static_cast<SkPDFDevice*>(device);

    if (pdfDevice->isContentEmpty()) {
        return;
    }

    SkMatrix matrix = device->getRelativeTransform(*this).asM33();
    ScopedContentEntry content(this, &this->cs(), matrix, paint);
    if (!content) {
        return;
    }
    SkPath shape = SkPath::Rect(SkRect::Make(device->imageInfo().dimensions()))
                   .makeTransform(matrix);
    if (content.needShape()) {
        content.setShape(shape);
    }
    if (!content.needSource()) {
        return;
    }
    // This XObject may contain its own marks, which are hidden if emitted inside an outer mark.
    // If it does have its own marks we need to pause the current mark and then re-set it after.
    int currentStructElemId = fMarkManager.elemId();
    if (pdfDevice->fMarkManager.madeMarks()) {
        fMarkManager.setNextMarksElemId(0);
        fMarkManager.beginMark();
    }
    this->drawFormXObject(pdfDevice->makeFormXObjectFromDevice(), content.stream(), &shape);
    fMarkManager.setNextMarksElemId(currentStructElemId);
}

void SkPDFDevice::drawSpecial(SkSpecialImage* srcImg, const SkMatrix& localToDevice,
                              const SkSamplingOptions& sampling, const SkPaint& paint,
                              SkCanvas::SrcRectConstraint) {
    if (this->hasEmptyClip()) {
        return;
    }
    SkASSERT(!srcImg->isGaneshBacked() && !srcImg->isGraphiteBacked());
    SkASSERT(!paint.getMaskFilter() && !paint.getImageFilter());

    SkBitmap resultBM;
    if (SkSpecialImages::AsBitmap(srcImg, &resultBM)) {
        auto r = SkRect::MakeWH(resultBM.width(), resultBM.height());
        this->internalDrawImageRect(SkKeyedImage(resultBM), nullptr, r, sampling, paint,
                                    localToDevice);
    }
}
