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

Commit 8fb95361 authored by Seigo Nonaka's avatar Seigo Nonaka
Browse files

Update TextRunShaper to be backward compatible

This CL includes followings
- Returns -1 if there is no override
- Instantiate the variation instance.
- Use the same instance for the same FakedFont.

Bug: 361260253
Test: atest CtsTextTestCases
Test: atest CtsWidgetTestCases
Test: atest CtsGraphicsTestCases
Flag: com.android.text.flags.typeface_redesign
Change-Id: I2ea2b1504cb0c9ec67a38c11da411eff6e618e4f
parent 3f38b0dd
Loading
Loading
Loading
Loading
+29 −10
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.graphics.Typeface;
import android.graphics.fonts.Font;

import com.android.internal.util.Preconditions;
import com.android.text.flags.Flags;

import dalvik.annotation.optimization.CriticalNative;

@@ -132,6 +133,9 @@ public final class PositionedGlyphs {
    @NonNull
    public Font getFont(@IntRange(from = 0) int index) {
        Preconditions.checkArgumentInRange(index, 0, glyphCount() - 1, "index");
        if (Flags.typefaceRedesign()) {
            return mFonts.get(nGetFontId(mLayoutPtr, index));
        }
        return mFonts.get(index);
    }

@@ -245,11 +249,19 @@ public final class PositionedGlyphs {
     */
    public PositionedGlyphs(long layoutPtr, float xOffset, float yOffset) {
        mLayoutPtr = layoutPtr;
        int glyphCount = nGetGlyphCount(layoutPtr);
        mFonts = new ArrayList<>(glyphCount);
        mXOffset = xOffset;
        mYOffset = yOffset;

        if (Flags.typefaceRedesign()) {
            int fontCount = nGetFontCount(layoutPtr);
            mFonts = new ArrayList<>(fontCount);
            for (int i = 0; i < fontCount; ++i) {
                mFonts.add(new Font(nGetFontRef(layoutPtr, i)));
            }
        } else {
            int glyphCount = nGetGlyphCount(layoutPtr);
            mFonts = new ArrayList<>(glyphCount);

            long prevPtr = 0;
            Font prevFont = null;
            for (int i = 0; i < glyphCount; ++i) {
@@ -260,6 +272,7 @@ public final class PositionedGlyphs {
                }
                mFonts.add(prevFont);
            }
        }

        NoImagePreloadHolder.REGISTRY.registerNativeAllocation(this, layoutPtr);
    }
@@ -290,6 +303,12 @@ public final class PositionedGlyphs {
    private static native float nGetWeightOverride(long minikinLayout, int i);
    @CriticalNative
    private static native float nGetItalicOverride(long minikinLayout, int i);
    @CriticalNative
    private static native int nGetFontCount(long minikinLayout);
    @CriticalNative
    private static native long nGetFontRef(long minikinLayout, int fontId);
    @CriticalNative
    private static native int nGetFontId(long minikinLayout, int glyphIndex);

    @Override
    public boolean equals(Object o) {
+85 −12
Original line number Diff line number Diff line
@@ -31,12 +31,34 @@

namespace android {

struct FakedFontKey {
    uint32_t operator()(const minikin::FakedFont& fakedFont) const {
        return minikin::Hasher()
                .update(reinterpret_cast<uintptr_t>(fakedFont.font.get()))
                .update(fakedFont.fakery.bits())
                .update(fakedFont.fakery.variationSettings())
                .hash();
    }
};

struct LayoutWrapper {
    LayoutWrapper(minikin::Layout&& layout, float ascent, float descent)
        : layout(std::move(layout)), ascent(ascent), descent(descent)  {}

    LayoutWrapper(minikin::Layout&& layout, float ascent, float descent, std::vector<jlong>&& fonts,
                  std::vector<uint32_t>&& fontIds)
            : layout(std::move(layout))
            , ascent(ascent)
            , descent(descent)
            , fonts(std::move(fonts))
            , fontIds(std::move(fontIds)) {}

    minikin::Layout layout;
    float ascent;
    float descent;

    std::vector<jlong> fonts;
    std::vector<uint32_t> fontIds;  // per glyph
};

static void releaseLayout(jlong ptr) {
@@ -64,6 +86,43 @@ static jlong shapeTextRun(const uint16_t* text, int textSize, int start, int cou
        overallDescent = std::max(overallDescent, extent.descent);
    }

    if (text_feature::typeface_redesign()) {
        uint32_t runCount = layout.getFontRunCount();

        std::unordered_map<minikin::FakedFont, uint32_t, FakedFontKey> fakedToFontIds;
        std::vector<jlong> fonts;
        std::vector<uint32_t> fontIds;

        fontIds.resize(layout.nGlyphs());
        for (uint32_t ri = 0; ri < runCount; ++ri) {
            const minikin::FakedFont& fakedFont = layout.getFontRunFont(ri);

            auto it = fakedToFontIds.find(fakedFont);
            uint32_t fontId;
            if (it != fakedToFontIds.end()) {
                fontId = it->second;  // We've seen it.
            } else {
                fontId = fonts.size();  // This is new to us. Create new one.
                std::shared_ptr<minikin::Font> font = std::make_shared<minikin::Font>(
                        fakedFont.font, fakedFont.fakery.variationSettings());
                fonts.push_back(reinterpret_cast<jlong>(new FontWrapper(std::move(font))));
                fakedToFontIds.insert(std::make_pair(fakedFont, fontId));
            }

            const uint32_t runStart = layout.getFontRunStart(ri);
            const uint32_t runEnd = layout.getFontRunEnd(ri);
            for (uint32_t i = runStart; i < runEnd; ++i) {
                fontIds[i] = fontId;
            }
        }

        std::unique_ptr<LayoutWrapper> ptr =
                std::make_unique<LayoutWrapper>(std::move(layout), overallAscent, overallDescent,
                                                std::move(fonts), std::move(fontIds));

        return reinterpret_cast<jlong>(ptr.release());
    }

    std::unique_ptr<LayoutWrapper> ptr = std::make_unique<LayoutWrapper>(
        std::move(layout), overallAscent, overallDescent
    );
@@ -156,6 +215,8 @@ static jboolean TextShaper_Result_getFakeItalic(CRITICAL_JNI_PARAMS_COMMA jlong
    return layout->layout.getFakery(i).isFakeItalic();
}

constexpr float NO_OVERRIDE = -1;

float findValueFromVariationSettings(const minikin::FontFakery& fakery, minikin::AxisTag tag) {
    for (const minikin::FontVariation& fv : fakery.variationSettings()) {
        if (fv.axisTag == tag) {
@@ -171,12 +232,7 @@ static jfloat TextShaper_Result_getWeightOverride(CRITICAL_JNI_PARAMS_COMMA jlon
    if (text_feature::typeface_redesign()) {
        float value =
                findValueFromVariationSettings(layout->layout.getFakery(i), minikin::TAG_wght);
        if (!std::isnan(value)) {
            return value;
        } else {
            const std::shared_ptr<minikin::Font>& font = layout->layout.getFontRef(i);
            return font->style().weight();
        }
        return std::isnan(value) ? NO_OVERRIDE : value;
    } else {
        return layout->layout.getFakery(i).wghtAdjustment();
    }
@@ -188,12 +244,7 @@ static jfloat TextShaper_Result_getItalicOverride(CRITICAL_JNI_PARAMS_COMMA jlon
    if (text_feature::typeface_redesign()) {
        float value =
                findValueFromVariationSettings(layout->layout.getFakery(i), minikin::TAG_ital);
        if (!std::isnan(value)) {
            return value;
        } else {
            const std::shared_ptr<minikin::Font>& font = layout->layout.getFontRef(i);
            return font->style().isItalic();
        }
        return std::isnan(value) ? NO_OVERRIDE : value;
    } else {
        return layout->layout.getFakery(i).italAdjustment();
    }
@@ -206,6 +257,24 @@ static jlong TextShaper_Result_getFont(CRITICAL_JNI_PARAMS_COMMA jlong ptr, jint
    return reinterpret_cast<jlong>(new FontWrapper(std::move(fontRef)));
}

// CriticalNative
static jint TextShaper_Result_getFontCount(CRITICAL_JNI_PARAMS_COMMA jlong ptr) {
    const LayoutWrapper* layout = reinterpret_cast<LayoutWrapper*>(ptr);
    return layout->fonts.size();
}

// CriticalNative
static jlong TextShaper_Result_getFontRef(CRITICAL_JNI_PARAMS_COMMA jlong ptr, jint fontId) {
    const LayoutWrapper* layout = reinterpret_cast<LayoutWrapper*>(ptr);
    return layout->fonts[fontId];
}

// CriticalNative
static jint TextShaper_Result_getFontId(CRITICAL_JNI_PARAMS_COMMA jlong ptr, jint glyphIdx) {
    const LayoutWrapper* layout = reinterpret_cast<LayoutWrapper*>(ptr);
    return layout->fontIds[glyphIdx];
}

// CriticalNative
static jlong TextShaper_Result_nReleaseFunc(CRITICAL_JNI_PARAMS) {
    return reinterpret_cast<jlong>(releaseLayout);
@@ -250,6 +319,10 @@ static const JNINativeMethod gResultMethods[] = {
        {"nGetWeightOverride", "(JI)F", (void*)TextShaper_Result_getWeightOverride},
        {"nGetItalicOverride", "(JI)F", (void*)TextShaper_Result_getItalicOverride},
        {"nReleaseFunc", "()J", (void*)TextShaper_Result_nReleaseFunc},

        {"nGetFontCount", "(J)I", (void*)TextShaper_Result_getFontCount},
        {"nGetFontRef", "(JI)J", (void*)TextShaper_Result_getFontRef},
        {"nGetFontId", "(JI)I", (void*)TextShaper_Result_getFontId},
};

int register_android_graphics_text_TextShaper(JNIEnv* env) {