void SkGScalerContext::generateMetrics(SkGlyph* glyph) {
    fProxy->getMetrics(glyph);

    SkVector advance;
    fMatrix.mapXY(SkFloatToScalar(glyph->fAdvanceX),
                  SkFloatToScalar(glyph->fAdvanceY), &advance);
    glyph->fAdvanceX = SkScalarToFloat(advance.fX);
    glyph->fAdvanceY = SkScalarToFloat(advance.fY);

    SkPath path;
    fProxy->getPath(*glyph, &path);
    path.transform(fMatrix);

    SkRect storage;
    const SkPaint& paint = fFace->paint();
    const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
                                                        &storage,
                                                        SkPaint::kFill_Style);
    SkIRect ibounds;
    newBounds.roundOut(&ibounds);
    glyph->fLeft = ibounds.fLeft;
    glyph->fTop = ibounds.fTop;
    glyph->fWidth = ibounds.width();
    glyph->fHeight = ibounds.height();
    glyph->fMaskFormat = SkMask::kARGB32_Format;
}
void SkRandomScalerContext::generateMetrics(SkGlyph* glyph) {
    fProxy->getAdvance(glyph);

    SkVector advance;
    fMatrix.mapXY(SkFixedToScalar(glyph->fAdvanceX),
                  SkFixedToScalar(glyph->fAdvanceY), &advance);
    glyph->fAdvanceX = SkScalarToFixed(advance.fX);
    glyph->fAdvanceY = SkScalarToFixed(advance.fY);

    SkPath path;
    fProxy->getPath(*glyph, &path);
    path.transform(fMatrix);

    SkRect storage;
    const SkPaint& paint = fFace->paint();
    const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
                                                        &storage,
                                                        SkPaint::kFill_Style);
    SkIRect ibounds;
    newBounds.roundOut(&ibounds);
    glyph->fLeft = ibounds.fLeft;
    glyph->fTop = ibounds.fTop;
    glyph->fWidth = ibounds.width();
    glyph->fHeight = ibounds.height();

    // Here we will change the mask format of the glyph
    // NOTE this is being overridden by the base class
    SkMask::Format format;
    switch (glyph->getGlyphID() % 6) {
        case 0:
            format = SkMask::kLCD16_Format;
            break;
        case 1:
            format = SkMask::kA8_Format;
            break;
        case 2:
            format = SkMask::kARGB32_Format;
            break;
        default:
            // we will fiddle with these in generate image
            format = (SkMask::Format)MASK_FORMAT_UNKNOWN;
    }

    glyph->fMaskFormat = format;
}
void SkRandomScalerContext::generateImage(const SkGlyph& glyph) {
    SkMask::Format format = (SkMask::Format)glyph.fMaskFormat;
    switch (glyph.getGlyphID() % 4) {
        case 0:
            format = SkMask::kLCD16_Format;
            break;
        case 1:
            format = SkMask::kA8_Format;
            break;
        case 2:
            format = SkMask::kARGB32_Format;
            break;
        case 3:
            format = SkMask::kBW_Format;
            break;
    }
    const_cast<SkGlyph&>(glyph).fMaskFormat = format;

    // if the format is ARGB, we just draw the glyph from path ourselves.  Otherwise, we force
    // our proxy context to generate the image from paths.
    if (!fFakeIt) {
        if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
            SkPath path;
            fProxy->getPath(glyph, &path);

            SkBitmap bm;
            bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
                             glyph.fImage, glyph.rowBytes());
            bm.eraseColor(0);

            SkCanvas canvas(bm);
            canvas.translate(-SkIntToScalar(glyph.fLeft),
                             -SkIntToScalar(glyph.fTop));
            canvas.drawPath(path, fFace->paint());
        } else {
            fProxy->forceGenerateImageFromPath();
            fProxy->getImage(glyph);
            fProxy->forceOffGenerateImageFromPath();
        }
    } else {
        sk_bzero(glyph.fImage, glyph.computeImageSize());
    }
}
void SkGScalerContext::generateImage(const SkGlyph& glyph) {
    if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
        SkPath path;
        fProxy->getPath(glyph, &path);

        SkBitmap bm;
        bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
                         glyph.fImage, glyph.rowBytes());
        bm.eraseColor(0);

        SkCanvas canvas(bm);
        canvas.translate(-SkIntToScalar(glyph.fLeft),
                         -SkIntToScalar(glyph.fTop));
        canvas.concat(fMatrix);
        canvas.drawPath(path, fFace->paint());
    } else {
        fProxy->getImage(glyph);
    }
}
void SkRandomScalerContext::generateMetrics(SkGlyph* glyph) {
    // Here we will change the mask format of the glyph
    // NOTE this is being overridden by the base class
    SkMask::Format format = SkMask::kARGB32_Format; // init to handle defective compilers
    switch (glyph->getGlyphID() % 4) {
        case 0:
            format = SkMask::kLCD16_Format;
            break;
        case 1:
            format = SkMask::kA8_Format;
            break;
        case 2:
            format = SkMask::kARGB32_Format;
            break;
        case 3:
            format = SkMask::kBW_Format;
            break;
    }

    fProxy->getMetrics(glyph);

    glyph->fMaskFormat = format;
    if (fFakeIt) {
        return;
    }
    if (SkMask::kARGB32_Format == format) {
        SkPath path;
        fProxy->getPath(*glyph, &path);

        SkRect storage;
        const SkPaint& paint = fFace->paint();
        const SkRect& newBounds = paint.doComputeFastBounds(path.getBounds(),
                                                            &storage,
                                                            SkPaint::kFill_Style);
        SkIRect ibounds;
        newBounds.roundOut(&ibounds);
        glyph->fLeft = ibounds.fLeft;
        glyph->fTop = ibounds.fTop;
        glyph->fWidth = ibounds.width();
        glyph->fHeight = ibounds.height();
    } else {
        SkPath      devPath, fillPath;
        SkMatrix    fillToDevMatrix;

        this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);

        // just use devPath
        const SkIRect ir = devPath.getBounds().roundOut();

        if (ir.isEmpty() || !ir.is16Bit()) {
            glyph->fLeft    = 0;
            glyph->fTop     = 0;
            glyph->fWidth   = 0;
            glyph->fHeight  = 0;
            return;
        }
        glyph->fLeft    = ir.fLeft;
        glyph->fTop     = ir.fTop;
        glyph->fWidth   = SkToU16(ir.width());
        glyph->fHeight  = SkToU16(ir.height());

        if (glyph->fWidth > 0) {
            switch (glyph->fMaskFormat) {
            case SkMask::kLCD16_Format:
                glyph->fWidth += 2;
                glyph->fLeft -= 1;
                break;
            default:
                break;
            }
        }
    }
}
void SkRandomScalerContext::generatePath(const SkGlyph& glyph, SkPath* path) {
    fProxy->getPath(glyph, path);
}
void SkGScalerContext::generatePath(const SkGlyph& glyph, SkPath* path) {
    fProxy->getPath(glyph, path);
    path->transform(fMatrix);
}