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

Commit c489d627 authored by Seigo Nonaka's avatar Seigo Nonaka
Browse files

Update TextShaper APIs to address API council feedback

This CL contains followings:
- Rename TextShaper to TextRunShaper, StyledTextShaper to TextShaper
- Renamed getTotalAdvance to getAdvance
- Rename getStyle to getGlyphStyle
- Rename getOriginX/Y to getOffsetX/Y
- Rename getPositionX/Y to getGlyphX/Y
- Fixed some documentation errors.
- Remvoed GlyphStyle. Added GlyphConsumer instead.

Bug: 170255480
Test: atest TextShaperRunTest GlyphStyleTest TextShaperTest

Change-Id: I0ffd7a3374e9cd1e04872240c2d0da26bc530244
parent fad96cd6
Loading
Loading
Loading
Loading
+14 −28
Original line number Diff line number Diff line
@@ -16525,23 +16525,6 @@ package android.graphics.pdf {
package android.graphics.text {
  public class GlyphStyle {
    ctor public GlyphStyle(@ColorInt int, @FloatRange(from=0) float, @FloatRange(from=0) float, @FloatRange(from=0) float, int);
    ctor public GlyphStyle(@NonNull android.graphics.Paint);
    method public void applyToPaint(@NonNull android.graphics.Paint);
    method @ColorInt public int getColor();
    method public int getFlags();
    method @FloatRange(from=0) public float getFontSize();
    method @FloatRange(from=0) public float getScaleX();
    method @FloatRange(from=0) public float getSkewX();
    method public void setColor(@ColorInt int);
    method public void setFlags(int);
    method public void setFontSize(@FloatRange(from=0) float);
    method public void setFromPaint(@NonNull android.graphics.Paint);
    method public void setScaleX(@FloatRange(from=0) float);
    method public void setSkewX(@FloatRange(from=0) float);
  }
  public class LineBreaker {
    method @NonNull public android.graphics.text.LineBreaker.Result computeLineBreaks(@NonNull android.graphics.text.MeasuredText, @NonNull android.graphics.text.LineBreaker.ParagraphConstraints, @IntRange(from=0) int);
    field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2
@@ -16603,20 +16586,19 @@ package android.graphics.text {
  }
  public final class PositionedGlyphs {
    method public float getAdvance();
    method public float getAscent();
    method public float getDescent();
    method @NonNull public android.graphics.fonts.Font getFont(@IntRange(from=0) int);
    method @IntRange(from=0) public int getGlyphId(@IntRange(from=0) int);
    method public float getOriginX();
    method public float getOriginY();
    method public float getPositionX(@IntRange(from=0) int);
    method public float getPositionY(@IntRange(from=0) int);
    method @NonNull public android.graphics.text.GlyphStyle getStyle();
    method public float getTotalAdvance();
    method public float getGlyphX(@IntRange(from=0) int);
    method public float getGlyphY(@IntRange(from=0) int);
    method public float getOffsetX();
    method public float getOffsetY();
    method @IntRange(from=0) public int glyphCount();
  }
  public class TextShaper {
  public class TextRunShaper {
    method @NonNull public static android.graphics.text.PositionedGlyphs shapeTextRun(@NonNull char[], int, int, int, int, float, float, boolean, @NonNull android.graphics.Paint);
    method @NonNull public static android.graphics.text.PositionedGlyphs shapeTextRun(@NonNull CharSequence, int, int, int, int, float, float, boolean, @NonNull android.graphics.Paint);
  }
@@ -50059,10 +50041,6 @@ package android.text {
    method @NonNull public android.text.StaticLayout.Builder setUseLineSpacingFromFallbacks(boolean);
  }
  public class StyledTextShaper {
    method @NonNull public static java.util.List<android.graphics.text.PositionedGlyphs> shapeText(@NonNull CharSequence, int, int, @NonNull android.text.TextDirectionHeuristic, @NonNull android.text.TextPaint);
  }
  public interface TextDirectionHeuristic {
    method public boolean isRtl(char[], int, int);
    method public boolean isRtl(CharSequence, int, int);
@@ -50092,6 +50070,14 @@ package android.text {
    field @Px public float underlineThickness;
  }
  public class TextShaper {
    method public static void shapeText(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @NonNull android.text.TextDirectionHeuristic, @NonNull android.text.TextPaint, @NonNull android.text.TextShaper.GlyphsConsumer);
  }
  public static interface TextShaper.GlyphsConsumer {
    method public void accept(@IntRange(from=0) int, @IntRange(from=0) int, @NonNull android.graphics.text.PositionedGlyphs, @NonNull android.text.TextPaint);
  }
  public class TextUtils {
    method @Deprecated public static CharSequence commaEllipsize(CharSequence, android.text.TextPaint, float, String, String);
    method public static CharSequence concat(java.lang.CharSequence...);
+0 −67
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.text;

import android.annotation.NonNull;
import android.graphics.Paint;
import android.graphics.text.PositionedGlyphs;
import android.graphics.text.TextShaper;

import java.util.List;

/**
 * Provides text shaping for multi-styled text.
 *
 * @see TextShaper#shapeTextRun(char[], int, int, int, int, float, float, boolean, Paint)
 * @see TextShaper#shapeTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint)
 * @see StyledTextShaper#shapeText(CharSequence, int, int, TextDirectionHeuristic, TextPaint)
 */
public class StyledTextShaper {
    private StyledTextShaper() {}


    /**
     * Shape multi-styled text.
     *
     * @param text a styled text.
     * @param start a start index of shaping target in the text.
     * @param count a length of shaping target in the text.
     * @param dir a text direction.
     * @param paint a paint
     * @return a shape result.
     */
    public static @NonNull List<PositionedGlyphs> shapeText(
            @NonNull CharSequence text, int start, int count,
            @NonNull TextDirectionHeuristic dir, @NonNull TextPaint paint) {
        MeasuredParagraph mp = MeasuredParagraph.buildForBidi(
                text, start, start + count, dir, null);
        TextLine tl = TextLine.obtain();
        try {
            tl.set(paint, text, start, start + count,
                    mp.getParagraphDir(),
                    mp.getDirections(start, start + count),
                    false /* tabstop is not supported */,
                    null,
                    -1, -1 // ellipsis is not supported.
            );
            return tl.shape();
        } finally {
            TextLine.recycle(tl);
        }
    }

}
+25 −25
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.text.PositionedGlyphs;
import android.graphics.text.TextShaper;
import android.graphics.text.TextRunShaper;
import android.os.Build;
import android.text.Layout.Directions;
import android.text.Layout.TabStops;
@@ -37,7 +37,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * Represents a line of styled text, for measuring in visual order and
@@ -312,8 +311,7 @@ public class TextLine {
    /**
     * Shape the TextLine.
     */
    List<PositionedGlyphs> shape() {
        List<PositionedGlyphs> glyphs = new ArrayList<>();
    void shape(TextShaper.GlyphsConsumer consumer) {
        float horizontal = 0;
        float x = 0;
        final int runCount = mDirections.getRunCount();
@@ -326,7 +324,7 @@ public class TextLine {
            int segStart = runStart;
            for (int j = mHasTabs ? runStart : runLimit; j <= runLimit; j++) {
                if (j == runLimit || charAt(j) == TAB_CHAR) {
                    horizontal += shapeRun(glyphs, segStart, j, runIsRtl, x + horizontal,
                    horizontal += shapeRun(consumer, segStart, j, runIsRtl, x + horizontal,
                            runIndex != (runCount - 1) || j != mLen);

                    if (j != runLimit) {  // charAt(j) == TAB_CHAR
@@ -336,7 +334,6 @@ public class TextLine {
                }
            }
        }
        return glyphs;
    }

    /**
@@ -546,7 +543,7 @@ public class TextLine {
    /**
     * Shape a unidirectional (but possibly multi-styled) run of text.
     *
     * @param glyphs the output positioned glyphs list
     * @param consumer the consumer of the shape result
     * @param start the line-relative start
     * @param limit the line-relative limit
     * @param runIsRtl true if the run is right-to-left
@@ -555,16 +552,17 @@ public class TextLine {
     * @return the signed width of the run, based on the paragraph direction.
     * Only valid if needWidth is true.
     */
    private float shapeRun(List<PositionedGlyphs> glyphs, int start,
    private float shapeRun(TextShaper.GlyphsConsumer consumer, int start,
            int limit, boolean runIsRtl, float x, boolean needWidth) {

        if ((mDir == Layout.DIR_LEFT_TO_RIGHT) == runIsRtl) {
            float w = -measureRun(start, limit, limit, runIsRtl, null);
            handleRun(start, limit, limit, runIsRtl, null, glyphs, x + w, 0, 0, 0, null, false);
            handleRun(start, limit, limit, runIsRtl, null, consumer, x + w, 0, 0, 0, null, false);
            return w;
        }

        return handleRun(start, limit, limit, runIsRtl, null, glyphs, x, 0, 0, 0, null, needWidth);
        return handleRun(start, limit, limit, runIsRtl, null, consumer, x, 0, 0, 0, null,
                needWidth);
    }


@@ -899,7 +897,7 @@ public class TextLine {
     * @param end the end of the text
     * @param runIsRtl true if the run is right-to-left
     * @param c the canvas, can be null if rendering is not needed
     * @param glyphs the output positioned glyph list, can be null if not necessary
     * @param consumer the output positioned glyph list, can be null if not necessary
     * @param x the edge of the run closest to the leading margin
     * @param top the top of the line
     * @param y the baseline
@@ -913,7 +911,7 @@ public class TextLine {
     */
    private float handleText(TextPaint wp, int start, int end,
            int contextStart, int contextEnd, boolean runIsRtl,
            Canvas c, List<PositionedGlyphs> glyphs, float x, int top, int y, int bottom,
            Canvas c, TextShaper.GlyphsConsumer consumer, float x, int top, int y, int bottom,
            FontMetricsInt fmi, boolean needWidth, int offset,
            @Nullable ArrayList<DecorationInfo> decorations) {

@@ -946,8 +944,8 @@ public class TextLine {
            rightX = x + totalWidth;
        }

        if (glyphs != null) {
            shapeTextRun(glyphs, wp, start, end, contextStart, contextEnd, runIsRtl, leftX);
        if (consumer != null) {
            shapeTextRun(consumer, wp, start, end, contextStart, contextEnd, runIsRtl, leftX);
        }

        if (c != null) {
@@ -1135,7 +1133,7 @@ public class TextLine {
     * @param limit the limit of the run
     * @param runIsRtl true if the run is right-to-left
     * @param c the canvas, can be null
     * @param glyphs the output positioned glyphs, can be null
     * @param consumer the output positioned glyphs, can be null
     * @param x the end of the run closest to the leading margin
     * @param top the top of the line
     * @param y the baseline
@@ -1147,7 +1145,7 @@ public class TextLine {
     */
    private float handleRun(int start, int measureLimit,
            int limit, boolean runIsRtl, Canvas c,
            List<PositionedGlyphs> glyphs, float x, int top, int y,
            TextShaper.GlyphsConsumer consumer, float x, int top, int y,
            int bottom, FontMetricsInt fmi, boolean needWidth) {

        if (measureLimit < start || measureLimit > limit) {
@@ -1180,7 +1178,7 @@ public class TextLine {
            wp.set(mPaint);
            wp.setStartHyphenEdit(adjustStartHyphenEdit(start, wp.getStartHyphenEdit()));
            wp.setEndHyphenEdit(adjustEndHyphenEdit(limit, wp.getEndHyphenEdit()));
            return handleText(wp, start, limit, start, limit, runIsRtl, c, glyphs, x, top,
            return handleText(wp, start, limit, start, limit, runIsRtl, c, consumer, x, top,
                    y, bottom, fmi, needWidth, measureLimit, null);
        }

@@ -1262,7 +1260,7 @@ public class TextLine {
                    activePaint.setEndHyphenEdit(
                            adjustEndHyphenEdit(activeEnd, mPaint.getEndHyphenEdit()));
                    x += handleText(activePaint, activeStart, activeEnd, i, inext, runIsRtl, c,
                            glyphs, x, top, y, bottom, fmi, needWidth || activeEnd < measureLimit,
                            consumer, x, top, y, bottom, fmi, needWidth || activeEnd < measureLimit,
                            Math.min(activeEnd, mlimit), mDecorations);

                    activeStart = j;
@@ -1288,7 +1286,7 @@ public class TextLine {
                    adjustStartHyphenEdit(activeStart, mPaint.getStartHyphenEdit()));
            activePaint.setEndHyphenEdit(
                    adjustEndHyphenEdit(activeEnd, mPaint.getEndHyphenEdit()));
            x += handleText(activePaint, activeStart, activeEnd, i, inext, runIsRtl, c, glyphs, x,
            x += handleText(activePaint, activeStart, activeEnd, i, inext, runIsRtl, c, consumer, x,
                    top, y, bottom, fmi, needWidth || activeEnd < measureLimit,
                    Math.min(activeEnd, mlimit), mDecorations);
        }
@@ -1327,7 +1325,7 @@ public class TextLine {
    /**
     * Shape a text run with the set-up paint.
     *
     * @param glyphs the output positioned glyphs list
     * @param consumer the output positioned glyphs list
     * @param paint the paint used to render the text
     * @param start the start of the run
     * @param end the end of the run
@@ -1336,30 +1334,32 @@ public class TextLine {
     * @param runIsRtl true if the run is right-to-left
     * @param x the x position of the left edge of the run
     */
    private void shapeTextRun(List<PositionedGlyphs> glyphs, TextPaint paint,
    private void shapeTextRun(TextShaper.GlyphsConsumer consumer, TextPaint paint,
            int start, int end, int contextStart, int contextEnd, boolean runIsRtl, float x) {

        int count = end - start;
        int contextCount = contextEnd - contextStart;
        PositionedGlyphs glyphs;
        if (mCharsValid) {
            glyphs.add(TextShaper.shapeTextRun(
            glyphs = TextRunShaper.shapeTextRun(
                    mChars,
                    start, count,
                    contextStart, contextCount,
                    x, 0f,
                    runIsRtl,
                    paint
            ));
            );
        } else {
            glyphs.add(TextShaper.shapeTextRun(
            glyphs = TextRunShaper.shapeTextRun(
                    mText,
                    mStart + start, count,
                    mStart + contextStart, contextCount,
                    x, 0f,
                    runIsRtl,
                    paint
            ));
            );
        }
        consumer.accept(start, count, glyphs, paint);
    }


+229 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.text;

import android.annotation.IntRange;
import android.annotation.NonNull;
import android.graphics.Paint;
import android.graphics.text.PositionedGlyphs;
import android.graphics.text.TextRunShaper;

/**
 * Provides text shaping for multi-styled text.
 *
 * Here is an example of animating text size and letter spacing for simple text.
 * <pre>
 * <code>
 * // In this example, shape the text once for start and end state, then animate between two shape
 * // result without re-shaping in each frame.
 * class SimpleAnimationView @JvmOverloads constructor(
 *         context: Context,
 *         attrs: AttributeSet? = null,
 *         defStyleAttr: Int = 0
 * ) : View(context, attrs, defStyleAttr) {
 *     private val textDir = TextDirectionHeuristics.LOCALE
 *     private val text = "Hello, World."  // The text to be displayed
 *
 *     // Class for keeping drawing parameters.
 *     data class DrawStyle(val textSize: Float, val alpha: Int)
 *
 *     // The start and end text shaping result. This class will animate between these two.
 *     private val start = mutableListOf&lt;Pair&lt;PositionedGlyphs, DrawStyle&gt;&gt;()
 *     private val end = mutableListOf&lt;Pair&lt;PositionedGlyphs, DrawStyle&gt;&gt;()
 *
 *     init {
 *         val startPaint = TextPaint().apply {
 *             alpha = 0 // Alpha only affect text drawing but not text shaping
 *             textSize = 36f // TextSize affect both text shaping and drawing.
 *             letterSpacing = 0f // Letter spacing only affect text shaping but not drawing.
 *         }
 *
 *         val endPaint = TextPaint().apply {
 *             alpha = 255
 *             textSize =128f
 *             letterSpacing = 0.1f
 *         }
 *
 *         TextShaper.shapeText(text, 0, text.length, textDir, startPaint) { _, _, glyphs, paint ->
 *             start.add(Pair(glyphs, DrawStyle(paint.textSize, paint.alpha)))
 *         }
 *         TextShaper.shapeText(text, 0, text.length, textDir, endPaint) { _, _, glyphs, paint ->
 *             end.add(Pair(glyphs, DrawStyle(paint.textSize, paint.alpha)))
 *         }
 *     }
 *
 *     override fun onDraw(canvas: Canvas) {
 *         super.onDraw(canvas)
 *
 *         // Set the baseline to the vertical center of the view.
 *         canvas.translate(0f, height / 2f)
 *
 *         // Assume the number of PositionedGlyphs are the same. If different, you may want to
 *         // animate in a different way, e.g. cross fading.
 *         start.zip(end) { (startGlyphs, startDrawStyle), (endGlyphs, endDrawStyle) ->
 *             // Tween the style and set to paint.
 *             paint.textSize = lerp(startDrawStyle.textSize, endDrawStyle.textSize, progress)
 *             paint.alpha = lerp(startDrawStyle.alpha, endDrawStyle.alpha, progress)
 *
 *             // Assume the number of glyphs are the same. If different, you may want to animate in
 *             // a different way, e.g. cross fading.
 *             require(startGlyphs.glyphCount() == endGlyphs.glyphCount())
 *
 *             if (startGlyphs.glyphCount() == 0) return@zip
 *
 *             var curFont = startGlyphs.getFont(0)
 *             var drawStart = 0
 *             for (i in 1 until startGlyphs.glyphCount()) {
 *                 // Assume the pair of Glyph ID and font is the same. If different, you may want
 *                 // to animate in a different way, e.g. cross fading.
 *                 require(startGlyphs.getGlyphId(i) == endGlyphs.getGlyphId(i))
 *                 require(startGlyphs.getFont(i) === endGlyphs.getFont(i))
 *
 *                 val font = startGlyphs.getFont(i)
 *                 if (curFont != font) {
 *                     drawGlyphs(canvas, startGlyphs, endGlyphs, drawStart, i, curFont, paint)
 *                     curFont = font
 *                     drawStart = i
 *                 }
 *             }
 *             if (drawStart != startGlyphs.glyphCount() - 1) {
 *                 drawGlyphs(canvas, startGlyphs, endGlyphs, drawStart, startGlyphs.glyphCount(),
 *                         curFont, paint)
 *             }
 *         }
 *     }
 *
 *     // Draws Glyphs for the same font run.
 *     private fun drawGlyphs(canvas: Canvas, startGlyph: PositionedGlyphs,
 *                            endGlyph: PositionedGlyphs, start: Int, end: Int, font: Font,
 *                            paint: Paint) {
 *         var cacheIndex = 0
 *         for (i in start until end) {
 *             intArrayCache[cacheIndex] = startGlyph.getGlyphId(i)
 *             // The glyph positions are different from start to end since they are shaped
 *             // with different letter spacing. Use linear interpolation for positions
 *             // during animation.
 *             floatArrayCache[cacheIndex * 2] =
 *                     lerp(startGlyph.getGlyphX(i), endGlyph.getGlyphX(i), progress)
 *             floatArrayCache[cacheIndex * 2 + 1] =
 *                     lerp(startGlyph.getGlyphY(i), endGlyph.getGlyphY(i), progress)
 *             if (cacheIndex == CACHE_SIZE) {  // Cached int array is full. Flashing.
 *                 canvas.drawGlyphs(
 *                         intArrayCache, 0, // glyphID array and its starting offset
 *                         floatArrayCache, 0, // position array and its starting offset
 *                         cacheIndex, // glyph count
 *                         font,
 *                         paint
 *                 )
 *                 cacheIndex = 0
 *             }
 *             cacheIndex++
 *         }
 *         if (cacheIndex != 0) {
 *             canvas.drawGlyphs(
 *                     intArrayCache, 0, // glyphID array and its starting offset
 *                     floatArrayCache, 0, // position array and its starting offset
 *                     cacheIndex, // glyph count
 *                     font,
 *                     paint
 *             )
 *         }
 *     }
 *
 *     // Linear Interpolator
 *     private fun lerp(start: Float, end: Float, t: Float) = start * (1f - t) + end * t
 *     private fun lerp(start: Int, end: Int, t: Float) = (start * (1f - t) + end * t).toInt()
 *
 *     // The animation progress.
 *     var progress: Float = 0f
 *         set(value) {
 *             field = value
 *             invalidate()
 *         }
 *
 *     // working copy of paint.
 *     private val paint = Paint()
 *
 *     // Array cache for reducing allocation during drawing.
 *     private var intArrayCache = IntArray(CACHE_SIZE)
 *     private var floatArrayCache = FloatArray(CACHE_SIZE * 2)
 * }
 * </code>
 * </pre>
 * @see TextRunShaper#shapeTextRun(char[], int, int, int, int, float, float, boolean, Paint)
 * @see TextRunShaper#shapeTextRun(CharSequence, int, int, int, int, float, float, boolean, Paint)
 * @see TextShaper#shapeText(CharSequence, int, int, TextDirectionHeuristic, TextPaint,
 * GlyphsConsumer)
 */
public class TextShaper {
    private TextShaper() {}

    /**
     * An consumer interface for accepting text shape result.
     */
    public interface GlyphsConsumer {
        /**
         * Accept text shape result.
         *
         * The implementation must not keep reference of paint since it will be mutated for the
         * subsequent styles. Also, for saving heap size, keep only necessary members in the
         * {@link TextPaint} instead of copying {@link TextPaint} object.
         *
         * @param start The start index of the shaped text.
         * @param count The length of the shaped text.
         * @param glyphs The shape result.
         * @param paint The paint to be used for drawing.
         */
        void accept(
                @IntRange(from = 0) int start,
                @IntRange(from = 0) int count,
                @NonNull PositionedGlyphs glyphs,
                @NonNull TextPaint paint);
    }

    /**
     * Shape multi-styled text.
     *
     * @param text a styled text.
     * @param start a start index of shaping target in the text.
     * @param count a length of shaping target in the text.
     * @param dir a text direction.
     * @param paint a paint
     * @param consumer a consumer of the shape result.
     */
    public static void shapeText(
            @NonNull CharSequence text, @IntRange(from = 0) int start,
            @IntRange(from = 0) int count, @NonNull TextDirectionHeuristic dir,
            @NonNull TextPaint paint, @NonNull GlyphsConsumer consumer) {
        MeasuredParagraph mp = MeasuredParagraph.buildForBidi(
                text, start, start + count, dir, null);
        TextLine tl = TextLine.obtain();
        try {
            tl.set(paint, text, start, start + count,
                    mp.getParagraphDir(),
                    mp.getDirections(start, start + count),
                    false /* tabstop is not supported */,
                    null,
                    -1, -1 // ellipsis is not supported.
            );
            tl.shape(consumer);
        } finally {
            TextLine.recycle(tl);
        }
    }

}
+5 −10
Original line number Diff line number Diff line
@@ -18,16 +18,12 @@ package android.text;

import static com.google.common.truth.Truth.assertThat;

import android.graphics.text.PositionedGlyphs;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.List;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class TextShaperTest {
@@ -36,11 +32,10 @@ public class TextShaperTest {
    public void testFontWithPath() {
        TextPaint p = new TextPaint();
        p.setFontFeatureSettings("'wght' 900");
        List<PositionedGlyphs> glyphs = StyledTextShaper.shapeText("a", 0, 1,
                TextDirectionHeuristics.LTR, p);
        assertThat(glyphs.size()).isEqualTo(1);
        TextShaper.shapeText("a", 0, 1, TextDirectionHeuristics.LTR, p,
                (start, end, glyphs, paint) -> {
                // This test only passes if the font of the Latin font is variable font.
        assertThat(glyphs.get(0).getFont(0).getFile()).isNotNull();

                assertThat(glyphs.getFont(0).getFile()).isNotNull();
            });
    }
}
Loading