/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkPaint.h"
#include "src/core/SkScalerContext.h"

#include "include/core/SkFontMetrics.h"
#include "include/core/SkMaskFilter.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkStrokeRec.h"
#include "include/private/SkColorData.h"
#include "include/private/SkTo.h"
#include "src/core/SkAutoMalloc.h"
#include "src/core/SkAutoPixmapStorage.h"
#include "src/core/SkDescriptor.h"
#include "src/core/SkDraw.h"
#include "src/core/SkFontPriv.h"
#include "src/core/SkGlyph.h"
#include "src/core/SkMaskGamma.h"
#include "src/core/SkMatrixProvider.h"
#include "src/core/SkPaintPriv.h"
#include "src/core/SkPathPriv.h"
#include "src/core/SkRasterClip.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkRectPriv.h"
#include "src/core/SkStroke.h"
#include "src/core/SkSurfacePriv.h"
#include "src/core/SkTextFormatParams.h"
#include "src/core/SkWriteBuffer.h"
#include "src/utils/SkMatrix22.h"
#include <new>

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

#ifdef SK_DEBUG
    #define DUMP_RECx
#endif

SkScalerContextRec SkScalerContext::PreprocessRec(const SkTypeface& typeface,
                                                  const SkScalerContextEffects& effects,
                                                  const SkDescriptor& desc) {
    SkScalerContextRec rec =
            *static_cast<const SkScalerContextRec*>(desc.findEntry(kRec_SkDescriptorTag, nullptr));

    // Allow the typeface to adjust the rec.
    typeface.onFilterRec(&rec);

    if (effects.fMaskFilter) {
        // Pre-blend is not currently applied to filtered text.
        // The primary filter is blur, for which contrast makes no sense,
        // and for which the destination guess error is more visible.
        // Also, all existing users of blur have calibrated for linear.
        rec.ignorePreBlend();
    }

    SkColor lumColor = rec.getLuminanceColor();

    if (rec.fMaskFormat == SkMask::kA8_Format) {
        U8CPU lum = SkComputeLuminance(SkColorGetR(lumColor),
                                       SkColorGetG(lumColor),
                                       SkColorGetB(lumColor));
        lumColor = SkColorSetRGB(lum, lum, lum);
    }

    // TODO: remove CanonicalColor when we to fix up Chrome layout tests.
    rec.setLuminanceColor(lumColor);

    return rec;
}

SkScalerContext::SkScalerContext(sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
                                 const SkDescriptor* desc)
    : fRec(PreprocessRec(*typeface, effects, *desc))
    , fTypeface(std::move(typeface))
    , fPathEffect(sk_ref_sp(effects.fPathEffect))
    , fMaskFilter(sk_ref_sp(effects.fMaskFilter))
      // Initialize based on our settings. Subclasses can also force this.
    , fGenerateImageFromPath(fRec.fFrameWidth >= 0 || fPathEffect != nullptr)

    , fPreBlend(fMaskFilter ? SkMaskGamma::PreBlend() : SkScalerContext::GetMaskPreBlend(fRec))
{
#ifdef DUMP_REC
    SkDebugf("SkScalerContext checksum %x count %d length %d\n",
             desc->getChecksum(), desc->getCount(), desc->getLength());
    SkDebugf("%s", fRec.dump().c_str());
    SkDebugf("  effects %x\n", desc->findEntry(kEffects_SkDescriptorTag, nullptr));
#endif
}

SkScalerContext::~SkScalerContext() {}

/**
 * In order to call cachedDeviceLuminance, cachedPaintLuminance, or
 * cachedMaskGamma the caller must hold the mask_gamma_cache_mutex and continue
 * to hold it until the returned pointer is refed or forgotten.
 */
static SkMutex& mask_gamma_cache_mutex() {
    static SkMutex& mutex = *(new SkMutex);
    return mutex;
}

static SkMaskGamma* gLinearMaskGamma = nullptr;
static SkMaskGamma* gMaskGamma = nullptr;
static SkScalar gContrast = SK_ScalarMin;
static SkScalar gPaintGamma = SK_ScalarMin;
static SkScalar gDeviceGamma = SK_ScalarMin;

/**
 * The caller must hold the mask_gamma_cache_mutex() and continue to hold it until
 * the returned SkMaskGamma pointer is refed or forgotten.
 */
static const SkMaskGamma& cached_mask_gamma(SkScalar contrast, SkScalar paintGamma,
                                            SkScalar deviceGamma) {
    mask_gamma_cache_mutex().assertHeld();
    if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
        if (nullptr == gLinearMaskGamma) {
            gLinearMaskGamma = new SkMaskGamma;
        }
        return *gLinearMaskGamma;
    }
    if (gContrast != contrast || gPaintGamma != paintGamma || gDeviceGamma != deviceGamma) {
        SkSafeUnref(gMaskGamma);
        gMaskGamma = new SkMaskGamma(contrast, paintGamma, deviceGamma);
        gContrast = contrast;
        gPaintGamma = paintGamma;
        gDeviceGamma = deviceGamma;
    }
    return *gMaskGamma;
}

/**
 * Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
 */
SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContextRec& rec) {
    SkAutoMutexExclusive ama(mask_gamma_cache_mutex());

    const SkMaskGamma& maskGamma = cached_mask_gamma(rec.getContrast(),
                                                     rec.getPaintGamma(),
                                                     rec.getDeviceGamma());

    // TODO: remove CanonicalColor when we to fix up Chrome layout tests.
    return maskGamma.preBlend(rec.getLuminanceColor());
}

size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
                                        SkScalar deviceGamma, int* width, int* height) {
    SkAutoMutexExclusive ama(mask_gamma_cache_mutex());
    const SkMaskGamma& maskGamma = cached_mask_gamma(contrast,
                                                     paintGamma,
                                                     deviceGamma);

    maskGamma.getGammaTableDimensions(width, height);
    size_t size = (*width)*(*height)*sizeof(uint8_t);

    return size;
}

bool SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
                                      uint8_t* data) {
    SkAutoMutexExclusive ama(mask_gamma_cache_mutex());
    const SkMaskGamma& maskGamma = cached_mask_gamma(contrast,
                                                     paintGamma,
                                                     deviceGamma);
    const uint8_t* gammaTables = maskGamma.getGammaTables();
    if (!gammaTables) {
        return false;
    }

    int width, height;
    maskGamma.getGammaTableDimensions(&width, &height);
    size_t size = width*height * sizeof(uint8_t);
    memcpy(data, gammaTables, size);
    return true;
}

SkGlyph SkScalerContext::makeGlyph(SkPackedGlyphID packedID, SkArenaAlloc* alloc) {
    return internalMakeGlyph(packedID, fRec.fMaskFormat, alloc);
}

SkGlyph SkScalerContext::internalMakeGlyph(SkPackedGlyphID packedID, SkMask::Format format,
                                           SkArenaAlloc* alloc) {
    SkGlyph glyph{packedID};
    glyph.fMaskFormat = format;
    // Must call to allow the subclass to determine the glyph representation to use.
    this->generateMetrics(&glyph, alloc);
    SkDEBUGCODE(glyph.fAdvancesBoundsFormatAndInitialPathDone = true;)
    if (fGenerateImageFromPath) {
        this->internalGetPath(glyph, alloc);
        const SkPath* devPath = glyph.path();
        if (devPath) {
            bool hairline = glyph.pathIsHairline();

            // generateMetrics may have modified the glyph fMaskFormat.
            glyph.fMaskFormat = format;

            // Only BW, A8, and LCD16 can be produced from paths.
            if (glyph.fMaskFormat != SkMask::kBW_Format &&
                glyph.fMaskFormat != SkMask::kA8_Format &&
                glyph.fMaskFormat != SkMask::kLCD16_Format)
            {
                glyph.fMaskFormat = SkMask::kA8_Format;
            }

            const SkIRect ir = devPath->getBounds().roundOut();
            if (ir.isEmpty() || !SkRectPriv::Is16Bit(ir)) {
                goto SK_ERROR;
            }
            glyph.fLeft    = ir.fLeft;
            glyph.fTop     = ir.fTop;
            glyph.fWidth   = SkToU16(ir.width());
            glyph.fHeight  = SkToU16(ir.height());

            const bool a8FromLCD = fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag;
            const bool fromLCD = (glyph.fMaskFormat == SkMask::kLCD16_Format) ||
                                 (glyph.fMaskFormat == SkMask::kA8_Format && a8FromLCD);
            const bool notEmptyAndFromLCD = 0 < glyph.fWidth && fromLCD;
            const bool verticalLCD = fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag;

            const bool needExtraWidth  = (notEmptyAndFromLCD && !verticalLCD) || hairline;
            const bool needExtraHeight = (notEmptyAndFromLCD &&  verticalLCD) || hairline;
            if (needExtraWidth) {
                glyph.fWidth += 2;
                glyph.fLeft -= 1;
            }
            if (needExtraHeight) {
                glyph.fHeight += 2;
                glyph.fTop -= 1;
            }
        }
    }

    // if either dimension is empty, zap the image bounds of the glyph
    if (0 == glyph.fWidth || 0 == glyph.fHeight) {
        glyph.fWidth   = 0;
        glyph.fHeight  = 0;
        glyph.fTop     = 0;
        glyph.fLeft    = 0;
        glyph.fMaskFormat = SkMask::kBW_Format;
        return glyph;
    }

    if (fMaskFilter) {
        SkMask      src = glyph.mask(),
                    dst;
        SkMatrix    matrix;

        fRec.getMatrixFrom2x2(&matrix);

        src.fImage = nullptr;  // only want the bounds from the filter
        if (as_MFB(fMaskFilter)->filterMask(&dst, src, matrix, nullptr)) {
            if (dst.fBounds.isEmpty() || !SkRectPriv::Is16Bit(dst.fBounds)) {
                goto SK_ERROR;
            }
            SkASSERT(dst.fImage == nullptr);
            glyph.fLeft    = dst.fBounds.fLeft;
            glyph.fTop     = dst.fBounds.fTop;
            glyph.fWidth   = SkToU16(dst.fBounds.width());
            glyph.fHeight  = SkToU16(dst.fBounds.height());
            glyph.fMaskFormat = dst.fFormat;
        }
    }
    return glyph;

SK_ERROR:
    // draw nothing 'cause we failed
    glyph.fLeft     = 0;
    glyph.fTop      = 0;
    glyph.fWidth    = 0;
    glyph.fHeight   = 0;
    glyph.fMaskFormat = fRec.fMaskFormat;
    return glyph;
}

#define SK_SHOW_TEXT_BLIT_COVERAGE 0

static void applyLUTToA8Mask(const SkMask& mask, const uint8_t* lut) {
    uint8_t* SK_RESTRICT dst = (uint8_t*)mask.fImage;
    unsigned rowBytes = mask.fRowBytes;

    for (int y = mask.fBounds.height() - 1; y >= 0; --y) {
        for (int x = mask.fBounds.width() - 1; x >= 0; --x) {
            dst[x] = lut[dst[x]];
        }
        dst += rowBytes;
    }
}

static void pack4xHToMask(const SkPixmap& src, const SkMask& dst,
                          const SkMaskGamma::PreBlend& maskPreBlend,
                          const bool doBGR, const bool doVert) {
#define SAMPLES_PER_PIXEL 4
#define LCD_PER_PIXEL 3
    SkASSERT(kAlpha_8_SkColorType == src.colorType());

    const bool toA8 = SkMask::kA8_Format == dst.fFormat;
    SkASSERT(SkMask::kLCD16_Format == dst.fFormat || toA8);

    // doVert in this function means swap x and y when writing to dst.
    if (doVert) {
        SkASSERT(src.width() == (dst.fBounds.height() - 2) * 4);
        SkASSERT(src.height() == dst.fBounds.width());
    } else {
        SkASSERT(src.width() == (dst.fBounds.width() - 2) * 4);
        SkASSERT(src.height() == dst.fBounds.height());
    }

    const int sample_width = src.width();
    const int height = src.height();

    uint8_t* dstImage = dst.fImage;
    size_t dstRB = dst.fRowBytes;
    // An N tap FIR is defined by
    // out[n] = coeff[0]*x[n] + coeff[1]*x[n-1] + ... + coeff[N]*x[n-N]
    // or
    // out[n] = sum(i, 0, N, coeff[i]*x[n-i])

    // The strategy is to use one FIR (different coefficients) for each of r, g, and b.
    // This means using every 4th FIR output value of each FIR and discarding the rest.
    // The FIRs are aligned, and the coefficients reach 5 samples to each side of their 'center'.
    // (For r and b this is technically incorrect, but the coeffs outside round to zero anyway.)

    // These are in some fixed point repesentation.
    // Adding up to more than one simulates ink spread.
    // For implementation reasons, these should never add up to more than two.

    // Coefficients determined by a gausian where 5 samples = 3 std deviations (0x110 'contrast').
    // Calculated using tools/generate_fir_coeff.py
    // With this one almost no fringing is ever seen, but it is imperceptibly blurry.
    // The lcd smoothed text is almost imperceptibly different from gray,
    // but is still sharper on small stems and small rounded corners than gray.
    // This also seems to be about as wide as one can get and only have a three pixel kernel.
    // TODO: calculate these at runtime so parameters can be adjusted (esp contrast).
    static const unsigned int coefficients[LCD_PER_PIXEL][SAMPLES_PER_PIXEL*3] = {
        //The red subpixel is centered inside the first sample (at 1/6 pixel), and is shifted.
        { 0x03, 0x0b, 0x1c, 0x33,  0x40, 0x39, 0x24, 0x10,  0x05, 0x01, 0x00, 0x00, },
        //The green subpixel is centered between two samples (at 1/2 pixel), so is symetric
        { 0x00, 0x02, 0x08, 0x16,  0x2b, 0x3d, 0x3d, 0x2b,  0x16, 0x08, 0x02, 0x00, },
        //The blue subpixel is centered inside the last sample (at 5/6 pixel), and is shifted.
        { 0x00, 0x00, 0x01, 0x05,  0x10, 0x24, 0x39, 0x40,  0x33, 0x1c, 0x0b, 0x03, },
    };

    size_t dstPB = toA8 ? sizeof(uint8_t) : sizeof(uint16_t);
    for (int y = 0; y < height; ++y) {
        uint8_t* dstP;
        size_t dstPDelta;
        if (doVert) {
            dstP = SkTAddOffset<uint8_t>(dstImage, y * dstPB);
            dstPDelta = dstRB;
        } else {
            dstP = SkTAddOffset<uint8_t>(dstImage, y * dstRB);
            dstPDelta = dstPB;
        }

        const uint8_t* srcP = src.addr8(0, y);

        // TODO: this fir filter implementation is straight forward, but slow.
        // It should be possible to make it much faster.
        for (int sample_x = -4; sample_x < sample_width + 4; sample_x += 4) {
            int fir[LCD_PER_PIXEL] = { 0 };
            for (int sample_index = std::max(0, sample_x - 4), coeff_index = sample_index - (sample_x - 4)
                ; sample_index < std::min(sample_x + 8, sample_width)
                ; ++sample_index, ++coeff_index)
            {
                int sample_value = srcP[sample_index];
                for (int subpxl_index = 0; subpxl_index < LCD_PER_PIXEL; ++subpxl_index) {
                    fir[subpxl_index] += coefficients[subpxl_index][coeff_index] * sample_value;
                }
            }
            for (int subpxl_index = 0; subpxl_index < LCD_PER_PIXEL; ++subpxl_index) {
                fir[subpxl_index] /= 0x100;
                fir[subpxl_index] = std::min(fir[subpxl_index], 255);
            }

            U8CPU r, g, b;
            if (doBGR) {
                r = fir[2];
                g = fir[1];
                b = fir[0];
            } else {
                r = fir[0];
                g = fir[1];
                b = fir[2];
            }
#if SK_SHOW_TEXT_BLIT_COVERAGE
            r = std::max(r, 10); g = std::max(g, 10); b = std::max(b, 10);
#endif
            if (toA8) {
                U8CPU a = (r + g + b) / 3;
                if (maskPreBlend.isApplicable()) {
                    a = maskPreBlend.fG[a];
                }
                *dstP = a;
            } else {
                if (maskPreBlend.isApplicable()) {
                    r = maskPreBlend.fR[r];
                    g = maskPreBlend.fG[g];
                    b = maskPreBlend.fB[b];
                }
                *(uint16_t*)dstP = SkPack888ToRGB16(r, g, b);
            }
            dstP = SkTAddOffset<uint8_t>(dstP, dstPDelta);
        }
    }
}

static inline int convert_8_to_1(unsigned byte) {
    SkASSERT(byte <= 0xFF);
    return byte >> 7;
}

static uint8_t pack_8_to_1(const uint8_t alpha[8]) {
    unsigned bits = 0;
    for (int i = 0; i < 8; ++i) {
        bits <<= 1;
        bits |= convert_8_to_1(alpha[i]);
    }
    return SkToU8(bits);
}

static void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
    const int height = mask.fBounds.height();
    const int width = mask.fBounds.width();
    const int octs = width >> 3;
    const int leftOverBits = width & 7;

    uint8_t* dst = mask.fImage;
    const int dstPad = mask.fRowBytes - SkAlign8(width)/8;
    SkASSERT(dstPad >= 0);

    SkASSERT(width >= 0);
    SkASSERT(srcRB >= (size_t)width);
    const size_t srcPad = srcRB - width;

    for (int y = 0; y < height; ++y) {
        for (int i = 0; i < octs; ++i) {
            *dst++ = pack_8_to_1(src);
            src += 8;
        }
        if (leftOverBits > 0) {
            unsigned bits = 0;
            int shift = 7;
            for (int i = 0; i < leftOverBits; ++i, --shift) {
                bits |= convert_8_to_1(*src++) << shift;
            }
            *dst++ = bits;
        }
        src += srcPad;
        dst += dstPad;
    }
}

static void generateMask(const SkMask& mask, const SkPath& path,
                         const SkMaskGamma::PreBlend& maskPreBlend,
                         const bool doBGR, const bool doVert, const bool a8FromLCD,
                         const bool hairline) {
    SkASSERT(mask.fFormat == SkMask::kBW_Format ||
             mask.fFormat == SkMask::kA8_Format ||
             mask.fFormat == SkMask::kLCD16_Format);

    SkPaint paint;
    SkPath strokePath;
    const SkPath* pathToUse = &path;

    int srcW = mask.fBounds.width();
    int srcH = mask.fBounds.height();
    int dstW = srcW;
    int dstH = srcH;

    SkMatrix matrix;
    matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
                        -SkIntToScalar(mask.fBounds.fTop));

    paint.setStroke(hairline);
    paint.setAntiAlias(SkMask::kBW_Format != mask.fFormat);

    const bool fromLCD = (mask.fFormat == SkMask::kLCD16_Format) ||
                         (mask.fFormat == SkMask::kA8_Format && a8FromLCD);
    const bool intermediateDst = fromLCD || mask.fFormat == SkMask::kBW_Format;
    if (fromLCD) {
        if (doVert) {
            dstW = 4*dstH - 8;
            dstH = srcW;
            matrix.setAll(0, 4, -SkIntToScalar(mask.fBounds.fTop + 1) * 4,
                          1, 0, -SkIntToScalar(mask.fBounds.fLeft),
                          0, 0, 1);
        } else {
            dstW = 4*dstW - 8;
            matrix.setAll(4, 0, -SkIntToScalar(mask.fBounds.fLeft + 1) * 4,
                          0, 1, -SkIntToScalar(mask.fBounds.fTop),
                          0, 0, 1);
        }

        // LCD hairline doesn't line up with the pixels, so do it the expensive way.
        SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);
        if (hairline) {
            rec.setStrokeStyle(1.0f, false);
            rec.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 0.0f);
        }
        if (rec.needToApply() && rec.applyToPath(&strokePath, path)) {
            pathToUse = &strokePath;
            paint.setStyle(SkPaint::kFill_Style);
        }
    }

    SkRasterClip clip;
    clip.setRect(SkIRect::MakeWH(dstW, dstH));

    const SkImageInfo info = SkImageInfo::MakeA8(dstW, dstH);
    SkAutoPixmapStorage dst;

    if (intermediateDst) {
        if (!dst.tryAlloc(info)) {
            // can't allocate offscreen, so empty the mask and return
            sk_bzero(mask.fImage, mask.computeImageSize());
            return;
        }
    } else {
        dst.reset(info, mask.fImage, mask.fRowBytes);
    }
    sk_bzero(dst.writable_addr(), dst.computeByteSize());

    SkDraw  draw;
    SkSimpleMatrixProvider matrixProvider(matrix);
    draw.fDst            = dst;
    draw.fRC             = &clip;
    draw.fMatrixProvider = &matrixProvider;
    draw.drawPath(*pathToUse, paint);

    switch (mask.fFormat) {
        case SkMask::kBW_Format:
            packA8ToA1(mask, dst.addr8(0, 0), dst.rowBytes());
            break;
        case SkMask::kA8_Format:
            if (fromLCD) {
                pack4xHToMask(dst, mask, maskPreBlend, doBGR, doVert);
            } else if (maskPreBlend.isApplicable()) {
                applyLUTToA8Mask(mask, maskPreBlend.fG);
            }
            break;
        case SkMask::kLCD16_Format:
            pack4xHToMask(dst, mask, maskPreBlend, doBGR, doVert);
            break;
        default:
            break;
    }
}

void SkScalerContext::getImage(const SkGlyph& origGlyph) {
    SkASSERT(origGlyph.fAdvancesBoundsFormatAndInitialPathDone);

    const SkGlyph* unfilteredGlyph = &origGlyph;
    // in case we need to call generateImage on a mask-format that is different
    // (i.e. larger) than what our caller allocated by looking at origGlyph.
    SkAutoMalloc tmpGlyphImageStorage;
    SkGlyph tmpGlyph;
    SkSTArenaAlloc<sizeof(SkGlyph::PathData)> tmpGlyphPathDataStorage;
    if (fMaskFilter) {
        // need the original bounds, sans our maskfilter
        sk_sp<SkMaskFilter> mf = std::move(fMaskFilter);
        tmpGlyph = this->makeGlyph(origGlyph.getPackedID(), &tmpGlyphPathDataStorage);
        fMaskFilter = std::move(mf);

        // Use the origGlyph storage for the temporary unfiltered mask if it will fit.
        if (tmpGlyph.fMaskFormat == origGlyph.fMaskFormat &&
            tmpGlyph.imageSize() <= origGlyph.imageSize())
        {
            tmpGlyph.fImage = origGlyph.fImage;
        } else {
            tmpGlyphImageStorage.reset(tmpGlyph.imageSize());
            tmpGlyph.fImage = tmpGlyphImageStorage.get();
        }
        unfilteredGlyph = &tmpGlyph;
    }

    if (!fGenerateImageFromPath) {
        generateImage(*unfilteredGlyph);
    } else {
        SkASSERT(origGlyph.setPathHasBeenCalled());
        const SkPath* devPath = origGlyph.path();
        bool hairline = origGlyph.pathIsHairline();
        SkMask mask = unfilteredGlyph->mask();

        if (!devPath) {
            generateImage(*unfilteredGlyph);
        } else {
            SkASSERT(SkMask::kARGB32_Format != origGlyph.fMaskFormat);
            SkASSERT(SkMask::kARGB32_Format != mask.fFormat);
            const bool doBGR = SkToBool(fRec.fFlags & SkScalerContext::kLCD_BGROrder_Flag);
            const bool doVert = SkToBool(fRec.fFlags & SkScalerContext::kLCD_Vertical_Flag);
            const bool a8LCD = SkToBool(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag);
            generateMask(mask, *devPath, fPreBlend, doBGR, doVert, a8LCD, hairline);
        }
    }

    if (fMaskFilter) {
        // k3D_Format should not be mask filtered.
        SkASSERT(SkMask::k3D_Format != unfilteredGlyph->fMaskFormat);

        SkMask filteredMask;
        SkMask srcMask;
        SkMatrix m;
        fRec.getMatrixFrom2x2(&m);

        if (as_MFB(fMaskFilter)->filterMask(&filteredMask, unfilteredGlyph->mask(), m, nullptr)) {
            // Filter succeeded; filteredMask.fImage was allocated.
            srcMask = filteredMask;
        } else if (unfilteredGlyph->fImage == tmpGlyphImageStorage.get()) {
            // Filter did nothing; unfiltered mask is independent of origGlyph.fImage.
            srcMask = unfilteredGlyph->mask();
        } else if (origGlyph.iRect() == unfilteredGlyph->iRect()) {
            // Filter did nothing; the unfiltered mask is in origGlyph.fImage and matches.
            return;
        } else {
            // Filter did nothing; the unfiltered mask is in origGlyph.fImage and conflicts.
            srcMask = unfilteredGlyph->mask();
            size_t imageSize = unfilteredGlyph->imageSize();
            tmpGlyphImageStorage.reset(imageSize);
            srcMask.fImage = static_cast<uint8_t*>(tmpGlyphImageStorage.get());
            memcpy(srcMask.fImage, unfilteredGlyph->fImage, imageSize);
        }

        SkASSERT_RELEASE(srcMask.fFormat == origGlyph.fMaskFormat);
        SkMask dstMask = origGlyph.mask();
        SkIRect origBounds = dstMask.fBounds;

        // Find the intersection of src and dst while updating the fImages.
        if (srcMask.fBounds.fTop < dstMask.fBounds.fTop) {
            int32_t topDiff = dstMask.fBounds.fTop - srcMask.fBounds.fTop;
            srcMask.fImage += srcMask.fRowBytes * topDiff;
            srcMask.fBounds.fTop = dstMask.fBounds.fTop;
        }
        if (dstMask.fBounds.fTop < srcMask.fBounds.fTop) {
            int32_t topDiff = srcMask.fBounds.fTop - dstMask.fBounds.fTop;
            dstMask.fImage += dstMask.fRowBytes * topDiff;
            dstMask.fBounds.fTop = srcMask.fBounds.fTop;
        }

        if (srcMask.fBounds.fLeft < dstMask.fBounds.fLeft) {
            int32_t leftDiff = dstMask.fBounds.fLeft - srcMask.fBounds.fLeft;
            srcMask.fImage += leftDiff;
            srcMask.fBounds.fLeft = dstMask.fBounds.fLeft;
        }
        if (dstMask.fBounds.fLeft < srcMask.fBounds.fLeft) {
            int32_t leftDiff = srcMask.fBounds.fLeft - dstMask.fBounds.fLeft;
            dstMask.fImage += leftDiff;
            dstMask.fBounds.fLeft = srcMask.fBounds.fLeft;
        }

        if (srcMask.fBounds.fBottom < dstMask.fBounds.fBottom) {
            dstMask.fBounds.fBottom = srcMask.fBounds.fBottom;
        }
        if (dstMask.fBounds.fBottom < srcMask.fBounds.fBottom) {
            srcMask.fBounds.fBottom = dstMask.fBounds.fBottom;
        }

        if (srcMask.fBounds.fRight < dstMask.fBounds.fRight) {
            dstMask.fBounds.fRight = srcMask.fBounds.fRight;
        }
        if (dstMask.fBounds.fRight < srcMask.fBounds.fRight) {
            srcMask.fBounds.fRight = dstMask.fBounds.fRight;
        }

        SkASSERT(srcMask.fBounds == dstMask.fBounds);
        int width = srcMask.fBounds.width();
        int height = srcMask.fBounds.height();
        int dstRB = dstMask.fRowBytes;
        int srcRB = srcMask.fRowBytes;

        const uint8_t* src = srcMask.fImage;
        uint8_t* dst = dstMask.fImage;

        if (SkMask::k3D_Format == filteredMask.fFormat) {
            // we have to copy 3 times as much
            height *= 3;
        }

        // If not filling the full original glyph, clear it out first.
        if (dstMask.fBounds != origBounds) {
            sk_bzero(origGlyph.fImage, origGlyph.fHeight * origGlyph.rowBytes());
        }

        while (--height >= 0) {
            memcpy(dst, src, width);
            src += srcRB;
            dst += dstRB;
        }
        SkMask::FreeImage(filteredMask.fImage);
    }
}

void SkScalerContext::getPath(SkGlyph& glyph, SkArenaAlloc* alloc) {
    this->internalGetPath(glyph, alloc);
}

void SkScalerContext::getFontMetrics(SkFontMetrics* fm) {
    SkASSERT(fm);
    this->generateFontMetrics(fm);
}

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

void SkScalerContext::internalGetPath(SkGlyph& glyph, SkArenaAlloc* alloc) {
    SkASSERT(glyph.fAdvancesBoundsFormatAndInitialPathDone);

    if (glyph.setPathHasBeenCalled()) {
        return;
    }

    SkPath path;
    SkPath devPath;
    bool hairline = false;

    SkPackedGlyphID glyphID = glyph.getPackedID();
    if (!generatePath(glyph, &path)) {
        glyph.setPath(alloc, (SkPath*)nullptr, hairline);
        return;
    }

    if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
        SkFixed dx = glyphID.getSubXFixed();
        SkFixed dy = glyphID.getSubYFixed();
        if (dx | dy) {
            path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy));
        }
    }

    if (fRec.fFrameWidth < 0 && fPathEffect == nullptr) {
        devPath.swap(path);
    } else {
        // need the path in user-space, with only the point-size applied
        // so that our stroking and effects will operate the same way they
        // would if the user had extracted the path themself, and then
        // called drawPath
        SkPath localPath;
        SkMatrix matrix;
        SkMatrix inverse;

        fRec.getMatrixFrom2x2(&matrix);
        if (!matrix.invert(&inverse)) {
            glyph.setPath(alloc, &devPath, hairline);
        }
        path.transform(inverse, &localPath);
        // now localPath is only affected by the paint settings, and not the canvas matrix

        SkStrokeRec rec(SkStrokeRec::kFill_InitStyle);

        if (fRec.fFrameWidth > 0) {
            rec.setStrokeStyle(fRec.fFrameWidth,
                               SkToBool(fRec.fFlags & kFrameAndFill_Flag));
            // glyphs are always closed contours, so cap type is ignored,
            // so we just pass something.
            rec.setStrokeParams((SkPaint::Cap)fRec.fStrokeCap,
                                (SkPaint::Join)fRec.fStrokeJoin,
                                fRec.fMiterLimit);
        }

        if (fPathEffect) {
            SkPath effectPath;
            if (fPathEffect->filterPath(&effectPath, localPath, &rec, nullptr, matrix)) {
                localPath.swap(effectPath);
            }
        }

        if (rec.needToApply()) {
            SkPath strokePath;
            if (rec.applyToPath(&strokePath, localPath)) {
                localPath.swap(strokePath);
            }
        }

        // The path effect may have modified 'rec', so wait to here to check hairline status.
        if (rec.isHairlineStyle()) {
            hairline = true;
        }

        localPath.transform(matrix, &devPath);
    }
    glyph.setPath(alloc, &devPath, hairline);
}


void SkScalerContextRec::getMatrixFrom2x2(SkMatrix* dst) const {
    dst->setAll(fPost2x2[0][0], fPost2x2[0][1], 0,
                fPost2x2[1][0], fPost2x2[1][1], 0,
                0,              0,              1);
}

void SkScalerContextRec::getLocalMatrix(SkMatrix* m) const {
    *m = SkFontPriv::MakeTextMatrix(fTextSize, fPreScaleX, fPreSkewX);
}

void SkScalerContextRec::getSingleMatrix(SkMatrix* m) const {
    this->getLocalMatrix(m);

    //  now concat the device matrix
    SkMatrix    deviceMatrix;
    this->getMatrixFrom2x2(&deviceMatrix);
    m->postConcat(deviceMatrix);
}

bool SkScalerContextRec::computeMatrices(PreMatrixScale preMatrixScale, SkVector* s, SkMatrix* sA,
                                         SkMatrix* GsA, SkMatrix* G_inv, SkMatrix* A_out)
{
    // A is the 'total' matrix.
    SkMatrix A;
    this->getSingleMatrix(&A);

    // The caller may find the 'total' matrix useful when dealing directly with EM sizes.
    if (A_out) {
        *A_out = A;
    }

    // GA is the matrix A with rotation removed.
    SkMatrix GA;
    bool skewedOrFlipped = A.getSkewX() || A.getSkewY() || A.getScaleX() < 0 || A.getScaleY() < 0;
    if (skewedOrFlipped) {
        // QR by Givens rotations. G is Q^T and GA is R. G is rotational (no reflections).
        // h is where A maps the horizontal baseline.
        SkPoint h = SkPoint::Make(SK_Scalar1, 0);
        A.mapPoints(&h, 1);

        // G is the Givens Matrix for A (rotational matrix where GA[0][1] == 0).
        SkMatrix G;
        SkComputeGivensRotation(h, &G);

        GA = G;
        GA.preConcat(A);

        // The 'remainingRotation' is G inverse, which is fairly simple since G is 2x2 rotational.
        if (G_inv) {
            G_inv->setAll(
                G.get(SkMatrix::kMScaleX), -G.get(SkMatrix::kMSkewX), G.get(SkMatrix::kMTransX),
                -G.get(SkMatrix::kMSkewY), G.get(SkMatrix::kMScaleY), G.get(SkMatrix::kMTransY),
                G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(SkMatrix::kMPersp2));
        }
    } else {
        GA = A;
        if (G_inv) {
            G_inv->reset();
        }
    }

    // If the 'total' matrix is singular, set the 'scale' to something finite and zero the matrices.
    // All underlying ports have issues with zero text size, so use the matricies to zero.
    // If one of the scale factors is less than 1/256 then an EM filling square will
    // never affect any pixels.
    // If there are any nonfinite numbers in the matrix, bail out and set the matrices to zero.
    if (SkScalarAbs(GA.get(SkMatrix::kMScaleX)) <= SK_ScalarNearlyZero ||
        SkScalarAbs(GA.get(SkMatrix::kMScaleY)) <= SK_ScalarNearlyZero ||
        !GA.isFinite())
    {
        s->fX = SK_Scalar1;
        s->fY = SK_Scalar1;
        sA->setScale(0, 0);
        if (GsA) {
            GsA->setScale(0, 0);
        }
        if (G_inv) {
            G_inv->reset();
        }
        return false;
    }

    // At this point, given GA, create s.
    switch (preMatrixScale) {
        case kFull_PreMatrixScale:
            s->fX = SkScalarAbs(GA.get(SkMatrix::kMScaleX));
            s->fY = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
            break;
        case kVertical_PreMatrixScale: {
            SkScalar yScale = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
            s->fX = yScale;
            s->fY = yScale;
            break;
        }
        case kVerticalInteger_PreMatrixScale: {
            SkScalar realYScale = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
            SkScalar intYScale = SkScalarRoundToScalar(realYScale);
            if (intYScale == 0) {
                intYScale = SK_Scalar1;
            }
            s->fX = intYScale;
            s->fY = intYScale;
            break;
        }
    }

    // The 'remaining' matrix sA is the total matrix A without the scale.
    if (!skewedOrFlipped && (
            (kFull_PreMatrixScale == preMatrixScale) ||
            (kVertical_PreMatrixScale == preMatrixScale && A.getScaleX() == A.getScaleY())))
    {
        // If GA == A and kFull_PreMatrixScale, sA is identity.
        // If GA == A and kVertical_PreMatrixScale and A.scaleX == A.scaleY, sA is identity.
        sA->reset();
    } else if (!skewedOrFlipped && kVertical_PreMatrixScale == preMatrixScale) {
        // If GA == A and kVertical_PreMatrixScale, sA.scaleY is SK_Scalar1.
        sA->reset();
        sA->setScaleX(A.getScaleX() / s->fY);
    } else {
        // TODO: like kVertical_PreMatrixScale, kVerticalInteger_PreMatrixScale with int scales.
        *sA = A;
        sA->preScale(SkScalarInvert(s->fX), SkScalarInvert(s->fY));
    }

    // The 'remainingWithoutRotation' matrix GsA is the non-rotational part of A without the scale.
    if (GsA) {
        *GsA = GA;
         // G is rotational so reorders with the scale.
        GsA->preScale(SkScalarInvert(s->fX), SkScalarInvert(s->fY));
    }

    return true;
}

SkAxisAlignment SkScalerContext::computeAxisAlignmentForHText() const {
    return fRec.computeAxisAlignmentForHText();
}

SkAxisAlignment SkScalerContextRec::computeAxisAlignmentForHText() const {
    // Why fPost2x2 can be used here.
    // getSingleMatrix multiplies in getLocalMatrix, which consists of
    // * fTextSize (a scale, which has no effect)
    // * fPreScaleX (a scale in x, which has no effect)
    // * fPreSkewX (has no effect, but would on vertical text alignment).
    // In other words, making the text bigger, stretching it along the
    // horizontal axis, or fake italicizing it does not move the baseline.
    if (!SkToBool(fFlags & SkScalerContext::kBaselineSnap_Flag)) {
        return kNone_SkAxisAlignment;
    }

    if (0 == fPost2x2[1][0]) {
        // The x axis is mapped onto the x axis.
        return kX_SkAxisAlignment;
    }
    if (0 == fPost2x2[0][0]) {
        // The x axis is mapped onto the y axis.
        return kY_SkAxisAlignment;
    }
    return kNone_SkAxisAlignment;
}

void SkScalerContextRec::setLuminanceColor(SkColor c) {
    fLumBits = SkMaskGamma::CanonicalColor(
            SkColorSetRGB(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)));
}

/*
 *  Return the scalar with only limited fractional precision. Used to consolidate matrices
 *  that vary only slightly when we create our key into the font cache, since the font scaler
 *  typically returns the same looking resuts for tiny changes in the matrix.
 */
static SkScalar sk_relax(SkScalar x) {
    SkScalar n = SkScalarRoundToScalar(x * 1024);
    return n / 1024.0f;
}

static SkMask::Format compute_mask_format(const SkFont& font) {
    switch (font.getEdging()) {
        case SkFont::Edging::kAlias:
            return SkMask::kBW_Format;
        case SkFont::Edging::kAntiAlias:
            return SkMask::kA8_Format;
        case SkFont::Edging::kSubpixelAntiAlias:
            return SkMask::kLCD16_Format;
    }
    SkASSERT(false);
    return SkMask::kA8_Format;
}

// Beyond this size, LCD doesn't appreciably improve quality, but it always
// cost more RAM and draws slower, so we set a cap.
#ifndef SK_MAX_SIZE_FOR_LCDTEXT
    #define SK_MAX_SIZE_FOR_LCDTEXT    48
#endif

const SkScalar gMaxSize2ForLCDText = SK_MAX_SIZE_FOR_LCDTEXT * SK_MAX_SIZE_FOR_LCDTEXT;

static bool too_big_for_lcd(const SkScalerContextRec& rec, bool checkPost2x2) {
    if (checkPost2x2) {
        SkScalar area = rec.fPost2x2[0][0] * rec.fPost2x2[1][1] -
                        rec.fPost2x2[1][0] * rec.fPost2x2[0][1];
        area *= rec.fTextSize * rec.fTextSize;
        return area > gMaxSize2ForLCDText;
    } else {
        return rec.fTextSize > SK_MAX_SIZE_FOR_LCDTEXT;
    }
}

// The only reason this is not file static is because it needs the context of SkScalerContext to
// access SkPaint::computeLuminanceColor.
void SkScalerContext::MakeRecAndEffects(const SkFont& font, const SkPaint& paint,
                                        const SkSurfaceProps& surfaceProps,
                                        SkScalerContextFlags scalerContextFlags,
                                        const SkMatrix& deviceMatrix,
                                        SkScalerContextRec* rec,
                                        SkScalerContextEffects* effects) {
    SkASSERT(!deviceMatrix.hasPerspective());

    sk_bzero(rec, sizeof(SkScalerContextRec));

    SkTypeface* typeface = font.getTypefaceOrDefault();

    rec->fFontID = typeface->uniqueID();
    rec->fTextSize = font.getSize();
    rec->fPreScaleX = font.getScaleX();
    rec->fPreSkewX  = font.getSkewX();

    bool checkPost2x2 = false;

    const SkMatrix::TypeMask mask = deviceMatrix.getType();
    if (mask & SkMatrix::kScale_Mask) {
        rec->fPost2x2[0][0] = sk_relax(deviceMatrix.getScaleX());
        rec->fPost2x2[1][1] = sk_relax(deviceMatrix.getScaleY());
        checkPost2x2 = true;
    } else {
        rec->fPost2x2[0][0] = rec->fPost2x2[1][1] = SK_Scalar1;
    }
    if (mask & SkMatrix::kAffine_Mask) {
        rec->fPost2x2[0][1] = sk_relax(deviceMatrix.getSkewX());
        rec->fPost2x2[1][0] = sk_relax(deviceMatrix.getSkewY());
        checkPost2x2 = true;
    } else {
        rec->fPost2x2[0][1] = rec->fPost2x2[1][0] = 0;
    }

    SkPaint::Style  style = paint.getStyle();
    SkScalar        strokeWidth = paint.getStrokeWidth();

    unsigned flags = 0;

    if (font.isEmbolden()) {
#ifdef SK_USE_FREETYPE_EMBOLDEN
        flags |= SkScalerContext::kEmbolden_Flag;
#else
        SkScalar fakeBoldScale = SkScalarInterpFunc(font.getSize(),
                                                    kStdFakeBoldInterpKeys,
                                                    kStdFakeBoldInterpValues,
                                                    kStdFakeBoldInterpLength);
        SkScalar extra = font.getSize() * fakeBoldScale;

        if (style == SkPaint::kFill_Style) {
            style = SkPaint::kStrokeAndFill_Style;
            strokeWidth = extra;    // ignore paint's strokeWidth if it was "fill"
        } else {
            strokeWidth += extra;
        }
#endif
    }

    if (style != SkPaint::kFill_Style && strokeWidth >= 0) {
        rec->fFrameWidth = strokeWidth;
        rec->fMiterLimit = paint.getStrokeMiter();
        rec->fStrokeJoin = SkToU8(paint.getStrokeJoin());
        rec->fStrokeCap = SkToU8(paint.getStrokeCap());

        if (style == SkPaint::kStrokeAndFill_Style) {
            flags |= SkScalerContext::kFrameAndFill_Flag;
        }
    } else {
        rec->fFrameWidth = -1;
        rec->fMiterLimit = 0;
        rec->fStrokeJoin = 0;
        rec->fStrokeCap = 0;
    }

    rec->fMaskFormat = compute_mask_format(font);

    if (SkMask::kLCD16_Format == rec->fMaskFormat) {
        if (too_big_for_lcd(*rec, checkPost2x2)) {
            rec->fMaskFormat = SkMask::kA8_Format;
            flags |= SkScalerContext::kGenA8FromLCD_Flag;
        } else {
            SkPixelGeometry geometry = surfaceProps.pixelGeometry();

            switch (geometry) {
                case kUnknown_SkPixelGeometry:
                    // eeek, can't support LCD
                    rec->fMaskFormat = SkMask::kA8_Format;
                    flags |= SkScalerContext::kGenA8FromLCD_Flag;
                    break;
                case kRGB_H_SkPixelGeometry:
                    // our default, do nothing.
                    break;
                case kBGR_H_SkPixelGeometry:
                    flags |= SkScalerContext::kLCD_BGROrder_Flag;
                    break;
                case kRGB_V_SkPixelGeometry:
                    flags |= SkScalerContext::kLCD_Vertical_Flag;
                    break;
                case kBGR_V_SkPixelGeometry:
                    flags |= SkScalerContext::kLCD_Vertical_Flag;
                    flags |= SkScalerContext::kLCD_BGROrder_Flag;
                    break;
            }
        }
    }

    if (font.isEmbeddedBitmaps()) {
        flags |= SkScalerContext::kEmbeddedBitmapText_Flag;
    }
    if (font.isSubpixel()) {
        flags |= SkScalerContext::kSubpixelPositioning_Flag;
    }
    if (font.isForceAutoHinting()) {
        flags |= SkScalerContext::kForceAutohinting_Flag;
    }
    if (font.isLinearMetrics()) {
        flags |= SkScalerContext::kLinearMetrics_Flag;
    }
    if (font.isBaselineSnap()) {
        flags |= SkScalerContext::kBaselineSnap_Flag;
    }
    if (typeface->glyphMaskNeedsCurrentColor()) {
        flags |= SkScalerContext::kNeedsForegroundColor_Flag;
        rec->fForegroundColor = paint.getColor();
    }
    rec->fFlags = SkToU16(flags);

    // these modify fFlags, so do them after assigning fFlags
    rec->setHinting(font.getHinting());
    rec->setLuminanceColor(SkPaintPriv::ComputeLuminanceColor(paint));

    // For now always set the paint gamma equal to the device gamma.
    // The math in SkMaskGamma can handle them being different,
    // but it requires superluminous masks when
    // Ex : deviceGamma(x) < paintGamma(x) and x is sufficiently large.
    rec->setDeviceGamma(SK_GAMMA_EXPONENT);
    rec->setPaintGamma(SK_GAMMA_EXPONENT);

#ifdef SK_GAMMA_CONTRAST
    rec->setContrast(SK_GAMMA_CONTRAST);
#else
    // A value of 0.5 for SK_GAMMA_CONTRAST appears to be a good compromise.
    // With lower values small text appears washed out (though correctly so).
    // With higher values lcd fringing is worse and the smoothing effect of
    // partial coverage is diminished.
    rec->setContrast(0.5f);
#endif

    if (!SkToBool(scalerContextFlags & SkScalerContextFlags::kFakeGamma)) {
        rec->ignoreGamma();
    }
    if (!SkToBool(scalerContextFlags & SkScalerContextFlags::kBoostContrast)) {
        rec->setContrast(0);
    }

    new (effects) SkScalerContextEffects{paint};
}

SkDescriptor* SkScalerContext::CreateDescriptorAndEffectsUsingPaint(
    const SkFont& font, const SkPaint& paint, const SkSurfaceProps& surfaceProps,
    SkScalerContextFlags scalerContextFlags, const SkMatrix& deviceMatrix, SkAutoDescriptor* ad,
    SkScalerContextEffects* effects)
{
    SkScalerContextRec rec;
    MakeRecAndEffects(font, paint, surfaceProps, scalerContextFlags, deviceMatrix, &rec, effects);
    return AutoDescriptorGivenRecAndEffects(rec, *effects, ad);
}

static size_t calculate_size_and_flatten(const SkScalerContextRec& rec,
                                         const SkScalerContextEffects& effects,
                                         SkBinaryWriteBuffer* effectBuffer) {
    size_t descSize = sizeof(rec);
    int entryCount = 1;

    if (effects.fPathEffect || effects.fMaskFilter) {
        if (effects.fPathEffect) { effectBuffer->writeFlattenable(effects.fPathEffect); }
        if (effects.fMaskFilter) { effectBuffer->writeFlattenable(effects.fMaskFilter); }
        entryCount += 1;
        descSize += effectBuffer->bytesWritten();
    }

    descSize += SkDescriptor::ComputeOverhead(entryCount);
    return descSize;
}

static void generate_descriptor(const SkScalerContextRec& rec,
                                const SkBinaryWriteBuffer& effectBuffer,
                                SkDescriptor* desc) {
    desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);

    if (effectBuffer.bytesWritten() > 0) {
        effectBuffer.writeToMemory(desc->addEntry(kEffects_SkDescriptorTag,
                                                  effectBuffer.bytesWritten(),
                                                  nullptr));
    }

    desc->computeChecksum();
}

SkDescriptor* SkScalerContext::AutoDescriptorGivenRecAndEffects(
    const SkScalerContextRec& rec,
    const SkScalerContextEffects& effects,
    SkAutoDescriptor* ad)
{
    SkBinaryWriteBuffer buf;

    ad->reset(calculate_size_and_flatten(rec, effects, &buf));
    generate_descriptor(rec, buf, ad->getDesc());

    return ad->getDesc();
}

std::unique_ptr<SkDescriptor> SkScalerContext::DescriptorGivenRecAndEffects(
    const SkScalerContextRec& rec,
    const SkScalerContextEffects& effects)
{
    SkBinaryWriteBuffer buf;

    auto desc = SkDescriptor::Alloc(calculate_size_and_flatten(rec, effects, &buf));
    generate_descriptor(rec, buf, desc.get());

    return desc;
}

void SkScalerContext::DescriptorBufferGiveRec(const SkScalerContextRec& rec, void* buffer) {
    generate_descriptor(rec, SkBinaryWriteBuffer{}, (SkDescriptor*)buffer);
}

bool SkScalerContext::CheckBufferSizeForRec(const SkScalerContextRec& rec,
                                            const SkScalerContextEffects& effects,
                                            size_t size) {
    SkBinaryWriteBuffer buf;
    return size >= calculate_size_and_flatten(rec, effects, &buf);
}

std::unique_ptr<SkScalerContext> SkScalerContext::MakeEmpty(
        sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
        const SkDescriptor* desc) {
    class SkScalerContext_Empty : public SkScalerContext {
    public:
        SkScalerContext_Empty(sk_sp<SkTypeface> typeface, const SkScalerContextEffects& effects,
                              const SkDescriptor* desc)
                : SkScalerContext(std::move(typeface), effects, desc) {}

    protected:
        bool generateAdvance(SkGlyph* glyph) override {
            glyph->zeroMetrics();
            return true;
        }
        void generateMetrics(SkGlyph* glyph, SkArenaAlloc*) override {
            glyph->fMaskFormat = fRec.fMaskFormat;
            glyph->zeroMetrics();
        }
        void generateImage(const SkGlyph& glyph) override {}
        bool generatePath(const SkGlyph& glyph, SkPath* path) override {
            path->reset();
            return false;
        }
        void generateFontMetrics(SkFontMetrics* metrics) override {
            if (metrics) {
                sk_bzero(metrics, sizeof(*metrics));
            }
        }
    };

    return std::make_unique<SkScalerContext_Empty>(std::move(typeface), effects, desc);
}




