10d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta/*
20d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * Copyright (C) 2013 The Android Open Source Project
30d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta *
40d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * Licensed under the Apache License, Version 2.0 (the "License");
50d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * you may not use this file except in compliance with the License.
60d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * You may obtain a copy of the License at
70d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta *
80d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta *      http://www.apache.org/licenses/LICENSE-2.0
90d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta *
100d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * Unless required by applicable law or agreed to in writing, software
110d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * distributed under the License is distributed on an "AS IS" BASIS,
120d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * See the License for the specific language governing permissions and
140d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * limitations under the License.
150d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta */
160d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
170d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptapackage android.graphics;
180d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
190d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptaimport java.awt.Font;
200d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptaimport java.awt.Graphics2D;
210d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptaimport java.awt.font.FontRenderContext;
220d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptaimport java.awt.font.GlyphVector;
230d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptaimport java.util.LinkedList;
240d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptaimport java.util.List;
250d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
260d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptaimport com.ibm.icu.lang.UScript;
270d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptaimport com.ibm.icu.lang.UScriptRun;
280d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
290d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptaimport android.graphics.Paint_Delegate.FontInfo;
300d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
310d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta/**
320d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * Render the text by breaking it into various scripts and using the right font for each script.
330d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta * Can be used to measure the text without actually drawing it.
340d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta */
350d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta@SuppressWarnings("deprecation")
360d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Guptapublic class BidiRenderer {
370d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
380d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /* package */ static class ScriptRun {
390d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        int start;
400d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        int limit;
410d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        boolean isRtl;
420d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        int scriptCode;
430d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        FontInfo font;
440d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
450d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        public ScriptRun(int start, int limit, boolean isRtl) {
460d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            this.start = start;
470d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            this.limit = limit;
480d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            this.isRtl = isRtl;
490d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            this.scriptCode = UScript.INVALID_CODE;
500d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        }
510d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    }
520d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
530d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /* package */ Graphics2D graphics;
540d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /* package */ Paint_Delegate paint;
550d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /* package */ char[] text;
560d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
570d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /**
580d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param graphics May be null.
590d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param paint The Paint to use to get the fonts. Should not be null.
600d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param text Unidirectional text. Should not be null.
610d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     */
620d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /* package */ BidiRenderer(Graphics2D graphics, Paint_Delegate paint, char[] text) {
630d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        assert (paint != null);
640d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        this.graphics = graphics;
650d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        this.paint = paint;
660d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        this.text = text;
670d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    }
680d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
690d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /**
700d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * Render unidirectional text.
710d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     *
720d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * This method can also be used to measure the width of the text without actually drawing it.
730d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     *
740d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param start index of the first character
750d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param limit index of the first character that should not be rendered.
760d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param isRtl is the text right-to-left
770d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param advances If not null, then advances for each character to be rendered are returned
780d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     *            here.
790d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param advancesIndex index into advances from where the advances need to be filled.
800d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param draw If true and {@link graphics} is not null, draw the rendered text on the graphics
810d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     *            at the given co-ordinates
820d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param x The x-coordinate of the left edge of where the text should be drawn on the given
830d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     *            graphics.
840d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @param y The y-coordinate at which to draw the text on the given graphics.
850d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @return The x-coordinate of the right edge of the drawn text. In other words,
860d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     *            x + the width of the text.
870d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     */
880d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /* package */ float renderText(int start, int limit, boolean isRtl, float advances[],
890d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            int advancesIndex, boolean draw, float x, float y) {
900d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        // We break the text into scripts and then select font based on it and then render each of
910d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        // the script runs.
920d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        for (ScriptRun run : getScriptRuns(text, start, limit, isRtl, paint.getFonts())) {
930d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            int flag = Font.LAYOUT_NO_LIMIT_CONTEXT | Font.LAYOUT_NO_START_CONTEXT;
940d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            flag |= isRtl ? Font.LAYOUT_RIGHT_TO_LEFT : Font.LAYOUT_LEFT_TO_RIGHT;
950d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            x = renderScript(run.start, run.limit, run.font, flag, advances, advancesIndex, draw,
960d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                    x, y);
970d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            advancesIndex += run.limit - run.start;
980d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        }
990d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        return x;
1000d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    }
1010d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
1020d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /**
1030d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * Render a script run. Use the preferred font to render as much as possible. This also
1040d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * implements a fallback mechanism to render characters that cannot be drawn using the
1050d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * preferred font.
1060d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     *
1070d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * @return x + width of the text drawn.
1080d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     */
1090d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    private float renderScript(int start, int limit, FontInfo preferredFont, int flag,
1100d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            float advances[], int advancesIndex, boolean draw, float x, float y) {
1110d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        List<FontInfo> fonts = paint.getFonts();
1120d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        if (fonts == null || preferredFont == null) {
1130d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            return x;
1140d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        }
1150d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
1160d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        while (start < limit) {
1170d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            boolean foundFont = false;
1180d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            int canDisplayUpTo = preferredFont.mFont.canDisplayUpTo(text, start, limit);
1190d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            if (canDisplayUpTo == -1) {
1200d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                return render(start, limit, preferredFont, flag, advances, advancesIndex, draw,
1210d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                        x, y);
1220d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            } else if (canDisplayUpTo > start) { // can draw something
1230d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                x = render(start, canDisplayUpTo, preferredFont, flag, advances, advancesIndex,
1240d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                        draw, x, y);
1250d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                advancesIndex += canDisplayUpTo - start;
1260d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                start = canDisplayUpTo;
1270d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            }
1280d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
1290d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            int charCount = Character.isHighSurrogate(text[start]) ? 2 : 1;
1300d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            for (FontInfo font : fonts) {
1310d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                canDisplayUpTo = font.mFont.canDisplayUpTo(text, start, start + charCount);
1320d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                if (canDisplayUpTo == -1) {
1330d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                    x = render(start, start+charCount, font, flag, advances, advancesIndex, draw,
1340d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                            x, y);
1350d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                    start += charCount;
1360d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                    advancesIndex += charCount;
1370d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                    foundFont = true;
1380d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                    break;
1390d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                }
1400d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            }
1410d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            if (!foundFont) {
1420d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                // No font can display this char. Use the preferred font. The char will most
1430d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                // probably appear as a box or a blank space. We could, probably, use some
1440d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                // heuristics and break the character into the base character and diacritics and
1450d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                // then draw it, but it's probably not worth the effort.
1460d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                x = render(start, start + charCount, preferredFont, flag, advances, advancesIndex,
1470d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                        draw, x, y);
1480d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                start += charCount;
1490d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                advancesIndex += charCount;
1500d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            }
1510d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        }
1520d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        return x;
1530d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    }
1540d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
1550d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /**
1560d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     * Render the text with the given font.
1570d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta     */
1580d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    private float render(int start, int limit, FontInfo font, int flag, float advances[],
1590d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            int advancesIndex, boolean draw, float x, float y) {
1600d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
1610d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        float totalAdvance = 0;
1620d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        // Since the metrics don't have anti-aliasing set, we create a new FontRenderContext with
1630d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        // the anti-aliasing set.
1640d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        FontRenderContext f = font.mMetrics.getFontRenderContext();
1650d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        FontRenderContext frc = new FontRenderContext(f.getTransform(), paint.isAntiAliased(),
1660d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                f.usesFractionalMetrics());
1670d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        GlyphVector gv = font.mFont.layoutGlyphVector(frc, text, start, limit, flag);
1680d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        int ng = gv.getNumGlyphs();
1690d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        int[] ci = gv.getGlyphCharIndices(0, ng, null);
1700d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        for (int i = 0; i < ng; i++) {
1710d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            float adv = gv.getGlyphMetrics(i).getAdvanceX();
1720d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            if (advances != null) {
1730d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                int adv_idx = advancesIndex + ci[i];
1740d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                advances[adv_idx] += adv;
1750d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            }
1760d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            totalAdvance += adv;
1770d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        }
1780d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        if (draw && graphics != null) {
1790d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            graphics.drawGlyphVector(gv, x, y);
1800d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        }
1810d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        return x + totalAdvance;
1820d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    }
1830d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
1840d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    // --- Static helper methods ---
1850d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
1860d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    /* package */  static List<ScriptRun> getScriptRuns(char[] text, int start, int limit,
1870d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            boolean isRtl, List<FontInfo> fonts) {
1880d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        LinkedList<ScriptRun> scriptRuns = new LinkedList<ScriptRun>();
1890d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
1900d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        int count = limit - start;
1910d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        UScriptRun uScriptRun = new UScriptRun(text, start, count);
1920d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        while (uScriptRun.next()) {
1930d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            int scriptStart = uScriptRun.getScriptStart();
1940d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            int scriptLimit = uScriptRun.getScriptLimit();
1950d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            ScriptRun run = new ScriptRun(scriptStart, scriptLimit, isRtl);
1960d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            run.scriptCode = uScriptRun.getScriptCode();
1970d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            setScriptFont(text, run, fonts);
1980d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            scriptRuns.add(run);
1990d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        }
2000d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
2010d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        return scriptRuns;
2020d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    }
2030d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta
2040d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    // TODO: Replace this method with one which returns the font based on the scriptCode.
2050d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    private static void setScriptFont(char[] text, ScriptRun run,
2060d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            List<FontInfo> fonts) {
2070d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        for (FontInfo fontInfo : fonts) {
2080d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            if (fontInfo.mFont.canDisplayUpTo(text, run.start, run.limit) == -1) {
2090d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                run.font = fontInfo;
2100d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta                return;
2110d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta            }
2120d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        }
2130d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta        run.font = fonts.get(0);
2140d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta    }
2150d9c922c9614147d1277cb36cfb7296774415d15Deepanshu Gupta}
216