Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb4f5680 authored by Raph Levien's avatar Raph Levien
Browse files

Support for fake bold in Minikin builds

Part of the fix for bug 15436379 Fake bold doesn't fully work (Minikin)

This patch queries the Minikin layout for when fake bold is needed,
and applies that to both shaping and drawing paint.

Also simplifies refcounting (the lifetime of all MinikinFont objects
is subsumed by the enclosing FontCollection).

Note: the fake bold flag set by the user is ignored in this patch.

Fake italics would be possible using the same mechanism, but it's
slightly more complicated (fake and user-set textSkewX values would need
to be combined, and the latter restored after drawing).

Change-Id: Ica2c4604846cbb37e5a783778b18d8993c9d4563
parent f7137209
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -828,13 +828,12 @@ public:
                : layout(layout), canvas(canvas), x(x), y(y), paint(paint), glyphs(glyphs),
                    pos(pos) { }

        void operator()(SkTypeface* t, size_t start, size_t end) {
        void operator()(size_t start, size_t end) {
            for (size_t i = start; i < end; i++) {
                glyphs[i] = layout.getGlyphId(i);
                pos[i].fX = x + layout.getX(i);
                pos[i].fY = y + layout.getY(i);
            }
            paint->setTypeface(t);
            canvas->drawPosText(glyphs + start, (end - start) << 1, pos + start, *paint);
        }
    private:
@@ -857,7 +856,7 @@ public:
        paint->setTextAlign(SkPaint::kLeft_Align);
        paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
        DrawTextFunctor f(layout, canvas, x, y, paint, glyphs, pos);
        MinikinUtils::forFontRun(layout, f);
        MinikinUtils::forFontRun(layout, paint, f);
        doDrawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
        paint->setTextAlign(align);
        delete[] glyphs;
+12 −5
Original line number Diff line number Diff line
@@ -43,13 +43,14 @@ bool MinikinFontSkia::GetGlyph(uint32_t codepoint, uint32_t *glyph) const {
    return !!glyph;
}

static void MinikinFontSkia_SetSkiaPaint(SkTypeface* typeface, SkPaint* skPaint, const MinikinPaint& paint) {
    skPaint->setTypeface(typeface);
static void MinikinFontSkia_SetSkiaPaint(const MinikinFont* font, SkPaint* skPaint, const MinikinPaint& paint) {
    skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    skPaint->setTextSize(paint.size);
    skPaint->setTextScaleX(paint.scaleX);
    skPaint->setTextSkewX(paint.skewX);
    MinikinFontSkia::unpackPaintFlags(skPaint, paint.paintFlags);
    // Apply font fakery on top of user-supplied flags.
    MinikinFontSkia::populateSkPaint(skPaint, font, paint.fakery);
}

float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
@@ -57,7 +58,7 @@ float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
    SkPaint skPaint;
    uint16_t glyph16 = glyph_id;
    SkScalar skWidth;
    MinikinFontSkia_SetSkiaPaint(mTypeface, &skPaint, paint);
    MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint);
    skPaint.getTextWidths(&glyph16, sizeof(glyph16), &skWidth, NULL);
#ifdef VERBOSE
    ALOGD("width for typeface %d glyph %d = %f", mTypeface->uniqueID(), glyph_id, skWidth);
@@ -70,7 +71,7 @@ void MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id,
    SkPaint skPaint;
    uint16_t glyph16 = glyph_id;
    SkRect skBounds;
    MinikinFontSkia_SetSkiaPaint(mTypeface, &skPaint, paint);
    MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint);
    skPaint.getTextWidths(&glyph16, sizeof(glyph16), NULL, &skBounds);
    bounds->mLeft = skBounds.fLeft;
    bounds->mTop = skBounds.fTop;
@@ -90,7 +91,7 @@ bool MinikinFontSkia::GetTable(uint32_t tag, uint8_t *buf, size_t *size) {
    }
}

SkTypeface *MinikinFontSkia::GetSkTypeface() {
SkTypeface *MinikinFontSkia::GetSkTypeface() const {
    return mTypeface;
}

@@ -115,4 +116,10 @@ void MinikinFontSkia::unpackPaintFlags(SkPaint* paint, uint32_t paintFlags) {
    paint->setHinting(static_cast<SkPaint::Hinting>(paintFlags >> 16));
}

void MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery) {
    paint->setTypeface(reinterpret_cast<const MinikinFontSkia*>(font)->GetSkTypeface());
    paint->setFakeBoldText(fakery.isFakeBold());
    // TODO: fake italics
}

}
+4 −1
Original line number Diff line number Diff line
@@ -36,10 +36,13 @@ public:

    int32_t GetUniqueId() const;

    SkTypeface *GetSkTypeface();
    SkTypeface* GetSkTypeface() const;

    static uint32_t packPaintFlags(const SkPaint* paint);
    static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags);

    // set typeface and fake bold/italic parameters
    static void populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery);
private:
    SkTypeface *mTypeface;
};
+10 −9
Original line number Diff line number Diff line
@@ -36,23 +36,24 @@ public:

    static float xOffsetForTextAlign(SkPaint* paint, const Layout& layout);

    // f is a functor of type void f(SkTypeface *, size_t start, size_t end);
    // f is a functor of type void f(size_t start, size_t end);
    template <typename F>
    static void forFontRun(const Layout& layout, F& f) {
        SkTypeface* lastFace = NULL;
    static void forFontRun(const Layout& layout, SkPaint* paint, F& f) {
        MinikinFont* curFont = NULL;
        size_t start = 0;
        size_t nGlyphs = layout.nGlyphs();
        for (size_t i = 0; i < nGlyphs; i++) {
            MinikinFontSkia* mfs = static_cast<MinikinFontSkia*>(layout.getFont(i));
            SkTypeface* skFace = mfs->GetSkTypeface();
            if (i > 0 && skFace != lastFace) {
                f(lastFace, start, i);
            MinikinFont* nextFont = layout.getFont(i);
            if (i > 0 && nextFont != curFont) {
                MinikinFontSkia::populateSkPaint(paint, curFont, layout.getFakery(start));
                f(start, i);
                start = i;
            }
            lastFace = skFace;
            curFont = nextFont;
        }
        if (nGlyphs > start) {
            f(lastFace, start, nGlyphs);
            MinikinFontSkia::populateSkPaint(paint, curFont, layout.getFakery(start));
            f(start, nGlyphs);
        }
    }
};
+4 −5
Original line number Diff line number Diff line
@@ -439,8 +439,8 @@ public:
#ifdef USE_MINIKIN
        TypefaceImpl* typeface = GraphicsJNI::getNativeTypeface(env, jpaint);
        typeface = TypefaceImpl_resolveDefault(typeface);
        MinikinFont* baseFont = typeface->fFontCollection->baseFont(typeface->fStyle);
        paint->setTypeface(reinterpret_cast<MinikinFontSkia*>(baseFont)->GetSkTypeface());
        FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle);
        MinikinFontSkia::populateSkPaint(paint, baseFont.font, baseFont.fakery);
#endif
        SkScalar spacing = paint->getFontMetrics(metrics);
        SkPaintOptionsAndroid paintOpts = paint->getPaintOptionsAndroid();
@@ -837,13 +837,12 @@ public:
                : layout(layout), path(path), x(x), y(y), paint(paint), glyphs(glyphs), pos(pos) {
        }

        void operator()(SkTypeface* t, size_t start, size_t end) {
        void operator()(size_t start, size_t end) {
            for (size_t i = start; i < end; i++) {
                glyphs[i] = layout.getGlyphId(i);
                pos[i].fX = x + layout.getX(i);
                pos[i].fY = y + layout.getY(i);
            }
            paint->setTypeface(t);
            if (start == 0) {
                paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, path);
            } else {
@@ -878,7 +877,7 @@ public:
        paint->setTextAlign(SkPaint::kLeft_Align);
        paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
        GetTextFunctor f(layout, path, x, y, paint, glyphs, pos);
        MinikinUtils::forFontRun(layout, f);
        MinikinUtils::forFontRun(layout, paint, f);
        paint->setTextAlign(align);
        delete[] glyphs;
        delete[] pos;
Loading