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