summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java7
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java6
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java58
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java11
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java225
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java10
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java92
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java143
-rw-r--r--tools/layoutlib/bridge/src/android/util/Xml_Delegate.java49
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java15
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java398
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java5
12 files changed, 419 insertions, 600 deletions
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
index 31d1594..f4a9f52 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
@@ -97,6 +97,13 @@ public class Resources_Theme_Delegate {
return found;
}
+ @LayoutlibDelegate
+ /*package*/ static TypedArray resolveAttributes(Resources thisResources, Theme thisTheme,
+ int[] values, int[] attrs) {
+ // FIXME
+ return null;
+ }
+
// ---- private helper methods ----
private static boolean setupResources(Theme thisTheme) {
diff --git a/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java
index 0a7899a..5d89f83 100644
--- a/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java
@@ -27,4 +27,10 @@ public class TypedArray_Delegate {
// pass
return false;
}
+
+ @LayoutlibDelegate
+ /*package*/ static TypedArray obtain(Resources res, int len) {
+ // FIXME
+ return null;
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
index 802cf1c..33813d1 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
@@ -18,9 +18,11 @@ package android.graphics;
import java.awt.Font;
import java.awt.Graphics2D;
+import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@@ -36,12 +38,12 @@ import android.graphics.Paint_Delegate.FontInfo;
@SuppressWarnings("deprecation")
public class BidiRenderer {
- /* package */ static class ScriptRun {
+ /*package*/ static class ScriptRun {
int start;
int limit;
boolean isRtl;
int scriptCode;
- FontInfo font;
+ Font font;
public ScriptRun(int start, int limit, boolean isRtl) {
this.start = start;
@@ -51,9 +53,10 @@ public class BidiRenderer {
}
}
- private Graphics2D mGraphics;
- private Paint_Delegate mPaint;
+ private final Graphics2D mGraphics;
+ private final Paint_Delegate mPaint;
private char[] mText;
+ private List<Font> mFonts;
// Bounds of the text drawn so far.
private RectF mBounds;
private float mBaseline;
@@ -63,11 +66,15 @@ public class BidiRenderer {
* @param paint The Paint to use to get the fonts. Should not be null.
* @param text Unidirectional text. Should not be null.
*/
- /* package */ BidiRenderer(Graphics2D graphics, Paint_Delegate paint, char[] text) {
+ /*package*/ BidiRenderer(Graphics2D graphics, Paint_Delegate paint, char[] text) {
assert (paint != null);
mGraphics = graphics;
mPaint = paint;
mText = text;
+ mFonts = new ArrayList<Font>(paint.getFonts().size());
+ for (FontInfo fontInfo : paint.getFonts()) {
+ mFonts.add(fontInfo.mFont);
+ }
}
/**
@@ -94,7 +101,7 @@ public class BidiRenderer {
// the script runs.
mBounds = new RectF(x, y, x, y);
mBaseline = y;
- for (ScriptRun run : getScriptRuns(mText, start, limit, isRtl, mPaint.getFonts())) {
+ for (ScriptRun run : getScriptRuns(mText, start, limit, isRtl, mFonts)) {
int flag = Font.LAYOUT_NO_LIMIT_CONTEXT | Font.LAYOUT_NO_START_CONTEXT;
flag |= isRtl ? Font.LAYOUT_RIGHT_TO_LEFT : Font.LAYOUT_LEFT_TO_RIGHT;
renderScript(run.start, run.limit, run.font, flag, advances, advancesIndex, draw);
@@ -108,16 +115,15 @@ public class BidiRenderer {
* much as possible. This also implements a fallback mechanism to render characters that cannot
* be drawn using the preferred font.
*/
- private void renderScript(int start, int limit, FontInfo preferredFont, int flag,
+ private void renderScript(int start, int limit, Font preferredFont, int flag,
float[] advances, int advancesIndex, boolean draw) {
- List<FontInfo> fonts = mPaint.getFonts();
- if (fonts == null || preferredFont == null) {
+ if (mFonts.size() == 0 || preferredFont == null) {
return;
}
while (start < limit) {
boolean foundFont = false;
- int canDisplayUpTo = preferredFont.mFont.canDisplayUpTo(mText, start, limit);
+ int canDisplayUpTo = preferredFont.canDisplayUpTo(mText, start, limit);
if (canDisplayUpTo == -1) {
// We can draw all characters in the text.
render(start, limit, preferredFont, flag, advances, advancesIndex, draw);
@@ -133,8 +139,8 @@ public class BidiRenderer {
// The current character cannot be drawn with the preferred font. Cycle through all the
// fonts to check which one can draw it.
int charCount = Character.isHighSurrogate(mText[start]) ? 2 : 1;
- for (FontInfo font : fonts) {
- canDisplayUpTo = font.mFont.canDisplayUpTo(mText, start, start + charCount);
+ for (Font font : mFonts) {
+ canDisplayUpTo = font.canDisplayUpTo(mText, start, start + charCount);
if (canDisplayUpTo == -1) {
render(start, start+charCount, font, flag, advances, advancesIndex, draw);
start += charCount;
@@ -160,15 +166,19 @@ public class BidiRenderer {
* Renders the text to the right of the bounds with the given font.
* @param font The font to render the text with.
*/
- private void render(int start, int limit, FontInfo font, int flag, float[] advances,
+ private void render(int start, int limit, Font font, int flag, float[] advances,
int advancesIndex, boolean draw) {
- // Since the metrics don't have anti-aliasing set, we create a new FontRenderContext with
- // the anti-aliasing set.
- FontRenderContext f = font.mMetrics.getFontRenderContext();
- FontRenderContext frc = new FontRenderContext(f.getTransform(), mPaint.isAntiAliased(),
- f.usesFractionalMetrics());
- GlyphVector gv = font.mFont.layoutGlyphVector(frc, mText, start, limit, flag);
+ FontRenderContext frc;
+ if (mGraphics != null) {
+ frc = mGraphics.getFontRenderContext();
+ } else {
+ frc = Toolkit.getDefaultToolkit().getFontMetrics(font).getFontRenderContext();
+ // Metrics obtained this way don't have anti-aliasing set. So,
+ // we create a new FontRenderContext with anti-aliasing set.
+ frc = new FontRenderContext(font.getTransform(), mPaint.isAntiAliased(), frc.usesFractionalMetrics());
+ }
+ GlyphVector gv = font.layoutGlyphVector(frc, mText, start, limit, flag);
int ng = gv.getNumGlyphs();
int[] ci = gv.getGlyphCharIndices(0, ng, null);
if (advances != null) {
@@ -206,7 +216,7 @@ public class BidiRenderer {
}
/* package */ static List<ScriptRun> getScriptRuns(char[] text, int start, int limit,
- boolean isRtl, List<FontInfo> fonts) {
+ boolean isRtl, List<Font> fonts) {
LinkedList<ScriptRun> scriptRuns = new LinkedList<ScriptRun>();
int count = limit - start;
@@ -225,10 +235,10 @@ public class BidiRenderer {
// TODO: Replace this method with one which returns the font based on the scriptCode.
private static void setScriptFont(char[] text, ScriptRun run,
- List<FontInfo> fonts) {
- for (FontInfo fontInfo : fonts) {
- if (fontInfo.mFont.canDisplayUpTo(text, run.start, run.limit) == -1) {
- run.font = fontInfo;
+ List<Font> fonts) {
+ for (Font font : fonts) {
+ if (font.canDisplayUpTo(text, run.start, run.limit) == -1) {
+ run.font = font;
return;
}
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 56c0de9..e9daffd 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -979,7 +979,6 @@ public final class Canvas_Delegate {
final float startX, final float startY, final int flags, long paint,
long typeface) {
- // TODO: use typeface.
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
@Override
@@ -1097,7 +1096,7 @@ public final class Canvas_Delegate {
/**
* Executes a {@link GcSnapshot.Drawable} with a given canvas and paint.
* <p>Note that the drawable may actually be executed several times if there are
- * layers involved (see {@link #saveLayer(RectF, int, int)}.
+ * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
*/
private static void draw(long nCanvas, long nPaint, boolean compositeOnly, boolean forceSrcMode,
GcSnapshot.Drawable drawable) {
@@ -1117,7 +1116,7 @@ public final class Canvas_Delegate {
* Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided
* to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}.
* <p>Note that the drawable may actually be executed several times if there are
- * layers involved (see {@link #saveLayer(RectF, int, int)}.
+ * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
*/
private static void draw(long nCanvas, GcSnapshot.Drawable drawable) {
// get the delegate from the native int.
@@ -1190,12 +1189,6 @@ public final class Canvas_Delegate {
return mSnapshot.clipRect(left, top, right, bottom, regionOp);
}
- private void setBitmap(Bitmap_Delegate bitmap) {
- mBitmap = bitmap;
- assert mSnapshot.size() == 1;
- mSnapshot.setBitmap(mBitmap);
- }
-
private static void drawBitmap(
long nativeCanvas,
Bitmap_Delegate bitmap,
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
new file mode 100644
index 0000000..5e7543a
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2014 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.graphics;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import java.awt.Font;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.graphics.Typeface_Delegate.SYSTEM_FONTS;
+
+/**
+ * Delegate implementing the native methods of android.graphics.FontFamily
+ *
+ * Through the layoutlib_create tool, the original native methods of FontFamily have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original FontFamily class.
+ *
+ * @see DelegateManager
+ */
+public class FontFamily_Delegate {
+
+ // FONT_SUFFIX_ITALIC will always match FONT_SUFFIX_BOLDITALIC and hence it must be checked
+ // separately.
+ private static final String FONT_SUFFIX_BOLDITALIC = "BoldItalic.ttf";
+ private static final String FONT_SUFFIX_BOLD = "Bold.ttf";
+ private static final String FONT_SUFFIX_ITALIC = "Italic.ttf";
+ private static final String FONT_SUBSTRING_COMPACT = "UI";
+
+ /**
+ * A class associating {@link Font} with its metadata.
+ */
+ private static final class FontInfo {
+ Font mFont;
+ /** Regular, Bold, Italic, or BoldItalic. */
+ int mStyle;
+ /**
+ * The variant of the Font - compact or elegant.
+ * @see Paint#setElegantTextHeight(boolean)
+ */
+ boolean mIsCompact;
+ }
+
+ // ---- delegate manager ----
+ private static final DelegateManager<FontFamily_Delegate> sManager =
+ new DelegateManager<FontFamily_Delegate>(FontFamily_Delegate.class);
+
+ // ---- delegate helper data ----
+ private static String sFontLocation;
+ private static final List<FontFamily_Delegate> sPostInitDelegate = new
+ ArrayList<FontFamily_Delegate>();
+
+
+ // ---- delegate data ----
+ private List<FontInfo> mFonts = new ArrayList<FontInfo>();
+ // Path of fonts that haven't been created since sFontLoader hasn't been initialized.
+ private List<String> mPath = new ArrayList<String>();
+
+
+ // ---- Public Helper methods ----
+
+ public static FontFamily_Delegate getDelegate(long nativeFontFamily) {
+ return sManager.getDelegate(nativeFontFamily);
+ }
+
+ public static synchronized void setFontLocation(String fontLocation) {
+ sFontLocation = fontLocation;
+ for (FontFamily_Delegate fontFamily : sPostInitDelegate) {
+ fontFamily.init();
+ }
+ sPostInitDelegate.clear();
+ }
+
+ public Font getFont(int style, boolean isCompact) {
+ FontInfo plainFont = null;
+ FontInfo styledFont = null; // Font matching the style but not isCompact
+ for (FontInfo font : mFonts) {
+ if (font.mStyle == style) {
+ if (font.mIsCompact == isCompact) {
+ return font.mFont;
+ }
+ styledFont = font;
+ }
+ if (font.mStyle == Font.PLAIN) {
+ if (plainFont == null) {
+ plainFont = font;
+ continue;
+ }
+ if (font.mIsCompact == isCompact) {
+ // Override the previous selection of plain font since we've found a better one.
+ plainFont = font;
+ }
+ }
+ }
+ if (styledFont != null) {
+ return styledFont.mFont;
+ }
+
+ // No font with the mentioned style is found. Try to derive one.
+ if (plainFont != null && style > 0 && style < 4) {
+ styledFont = new FontInfo();
+ styledFont.mFont = plainFont.mFont.deriveFont(style);
+ styledFont.mStyle = style;
+ styledFont.mIsCompact = plainFont.mIsCompact;
+ // Add the font to the list of fonts so that we don't have to derive it the next time.
+ mFonts.add(styledFont);
+ return styledFont.mFont;
+ }
+ return null;
+ }
+
+ // ---- native methods ----
+
+ @LayoutlibDelegate
+ /*package*/ static long nCreateFamily() {
+ FontFamily_Delegate delegate = new FontFamily_Delegate();
+ if (sFontLocation != null) {
+ delegate.init();
+ } else {
+ sPostInitDelegate.add(delegate);
+ }
+ return sManager.addNewDelegate(delegate);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nUnrefFamily(long nativePtr) {
+ sManager.removeJavaReferenceFor(nativePtr);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static boolean nAddFont(long nativeFamily, String path) {
+ FontFamily_Delegate delegate = getDelegate(nativeFamily);
+ if (delegate != null) {
+ if (sFontLocation == null) {
+ delegate.mPath.add(path);
+ return true;
+ }
+ return delegate.addFont(path);
+ }
+ return false;
+ }
+
+ private void init() {
+ for (String path : mPath) {
+ addFont(path);
+ }
+ mPath = null;
+ }
+
+ private boolean addFont(String path) {
+ Font font = loadFont(path);
+ if (font == null) {
+ return false;
+ }
+ FontInfo fontInfo = new FontInfo();
+ fontInfo.mFont = font;
+ addFontMetadata(fontInfo, path);
+ // TODO ensure that mFonts doesn't have the font with this style already.
+ mFonts.add(fontInfo);
+ return true;
+ }
+
+ private static void addFontMetadata(FontInfo fontInfo, String path) {
+ int style = Font.PLAIN;
+ String fontName = path.substring(path.lastIndexOf('/'), path.length());
+ if (fontName.endsWith(FONT_SUFFIX_BOLDITALIC)) {
+ style = Font.BOLD | Font.ITALIC;
+ } else if (fontName.endsWith(FONT_SUFFIX_BOLD)) {
+ style = Font.BOLD;
+ } else if (fontName.endsWith(FONT_SUFFIX_ITALIC)) {
+ style = Font.ITALIC;
+ }
+ fontInfo.mStyle = style;
+
+ // Names of compact fonts end with UI-<style>.ttf. For example, NotoNakshUI-Regular.ttf.
+ // This should go away when this info is passed on by nAddFont().
+ int hyphenIndex = fontName.lastIndexOf('-');
+ fontInfo.mIsCompact = hyphenIndex > 0 &&
+ fontName.substring(0, hyphenIndex).endsWith(FONT_SUBSTRING_COMPACT);
+
+ }
+
+ private static Font loadFont(String path) {
+ if (path.startsWith(SYSTEM_FONTS) ) {
+ String relativePath = path.substring(SYSTEM_FONTS.length());
+ File f = new File(sFontLocation, relativePath);
+
+ try {
+ return Font.createFont(Font.TRUETYPE_FONT, f);
+ } catch (Exception e) {
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
+ String.format("Unable to load font %1$s", relativePath),
+ null /*throwable*/, null /*data*/);
+ }
+ } else {
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "Only platform fonts located in " + SYSTEM_FONTS + "can be loaded.",
+ null /*throwable*/, null /*data*/);
+ }
+
+ return null;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index 8862f5b..f42f48f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -203,6 +203,16 @@ public final class Matrix_Delegate {
}
@LayoutlibDelegate
+ /*package*/ static boolean native_isAffine(long native_object) {
+ Matrix_Delegate d = sManager.getDelegate(native_object);
+ if (d == null) {
+ return true;
+ }
+
+ return (d.computeTypeMask() & kPerspective_Mask) == 0;
+ }
+
+ @LayoutlibDelegate
/*package*/ static boolean native_rectStaysRect(long native_object) {
Matrix_Delegate d = sManager.getDelegate(native_object);
if (d == null) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 83df745..911f4e7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -53,7 +53,7 @@ import java.util.Locale;
public class Paint_Delegate {
/**
- * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}.
+ * Class associating a {@link Font} and its {@link java.awt.FontMetrics}.
*/
/*package*/ static final class FontInfo {
Font mFont;
@@ -66,8 +66,6 @@ public class Paint_Delegate {
// ---- delegate helper data ----
private List<FontInfo> mFonts;
- private final FontRenderContext mFontContext = new FontRenderContext(
- new AffineTransform(), true, true);
// ---- delegate data ----
private int mFlags;
@@ -83,6 +81,7 @@ public class Paint_Delegate {
private float mTextScaleX;
private float mTextSkewX;
private int mHintingMode = Paint.HINTING_ON;
+ private boolean mIsCompact = true;
private Xfermode_Delegate mXfermode;
private ColorFilter_Delegate mColorFilter;
@@ -101,8 +100,7 @@ public class Paint_Delegate {
}
/**
- * Returns the list of {@link Font} objects. The first item is the main font, the rest
- * are fall backs for characters not present in the main font.
+ * Returns the list of {@link Font} objects.
*/
public List<FontInfo> getFonts() {
return mFonts;
@@ -437,12 +435,20 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static boolean isElegantTextHeight(Paint thisPaint) {
- return false;
+ // get the delegate from the native int.
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ return delegate != null && !delegate.mIsCompact;
}
@LayoutlibDelegate
/*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) {
- // TODO
+ // get the delegate from the native int.
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ if (delegate == null) {
+ return;
+ }
+
+ delegate.mIsCompact = !elegant;
}
@LayoutlibDelegate
@@ -621,7 +627,6 @@ public class Paint_Delegate {
int inc = count > 0 ? 1 : -1;
int measureIndex = 0;
- float measureAcc = 0;
for (int i = index; i != index + count; i += inc, measureIndex++) {
int start, end;
if (i < index) {
@@ -640,7 +645,6 @@ public class Paint_Delegate {
measuredWidth[measureIndex] = res;
}
- measureAcc += res;
if (res > maxWidth) {
// we should not return this char index, but since it's 0-based
// and we need to return a count, we simply return measureIndex;
@@ -818,7 +822,7 @@ public class Paint_Delegate {
return filter;
}
- delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);;
+ delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);
// since none of those are supported, display a fidelity warning right away
if (delegate.mColorFilter != null && delegate.mColorFilter.isSupported() == false) {
@@ -940,52 +944,17 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
- /*package*/ static int native_getTextWidths(long native_object, char[] text, int index,
- int count, int bidiFlags, float[] widths) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return 0;
- }
-
- if (delegate.mFonts.size() > 0) {
- // FIXME: handle multi-char characters (see measureText)
- float totalAdvance = 0;
- for (int i = 0; i < count; i++) {
- char c = text[i + index];
- boolean found = false;
- for (FontInfo info : delegate.mFonts) {
- if (info.mFont.canDisplay(c)) {
- float adv = info.mMetrics.charWidth(c);
- totalAdvance += adv;
- if (widths != null) {
- widths[i] = adv;
- }
-
- found = true;
- break;
- }
- }
-
- if (found == false) {
- // no advance for this char.
- if (widths != null) {
- widths[i] = 0.f;
- }
- }
- }
-
- return (int) totalAdvance;
- }
-
- return 0;
+ /*package*/ static int native_getTextWidths(long native_object, long native_typeface,
+ char[] text, int index, int count, int bidiFlags, float[] widths) {
+ return (int) native_getTextRunAdvances(native_object, native_typeface, text, index, count,
+ index, count, bidiFlags, widths, 0);
}
@LayoutlibDelegate
- /*package*/ static int native_getTextWidths(long native_object, String text, int start,
- int end, int bidiFlags, float[] widths) {
- return native_getTextWidths(native_object, text.toCharArray(), start, end - start,
- bidiFlags, widths);
+ /*package*/ static int native_getTextWidths(long native_object, long native_typeface,
+ String text, int start, int end, int bidiFlags, float[] widths) {
+ return native_getTextWidths(native_object, native_typeface, text.toCharArray(), start,
+ end - start, bidiFlags, widths);
}
@LayoutlibDelegate
@@ -997,15 +966,20 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float native_getTextRunAdvances(long native_object,
+ long native_typeface /*ignored*/,
char[] text, int index, int count, int contextIndex, int contextCount,
int flags, float[] advances, int advancesIndex) {
+ // native_typeface is passed here since Framework's old implementation did not have the
+ // typeface object associated with the Paint. Since, we follow the new framework way,
+ // we store the typeface with the paint and use it directly.
+
if (advances != null)
for (int i = advancesIndex; i< advancesIndex+count; i++)
advances[i]=0;
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null || delegate.mFonts == null || delegate.mFonts.size() == 0) {
+ if (delegate == null) {
return 0.f;
}
boolean isRtl = isRtl(flags);
@@ -1017,7 +991,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
- /*package*/ static float native_getTextRunAdvances(long native_object,
+ /*package*/ static float native_getTextRunAdvances(long native_object, long native_typeface,
String text, int start, int end, int contextStart, int contextEnd,
int flags, float[] advances, int advancesIndex) {
// FIXME: support contextStart and contextEnd
@@ -1025,8 +999,8 @@ public class Paint_Delegate {
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
- return native_getTextRunAdvances(native_object, buffer, 0, count, contextStart,
- contextEnd - contextStart, flags, advances, advancesIndex);
+ return native_getTextRunAdvances(native_object, native_typeface, buffer, 0, count,
+ contextStart, contextEnd - contextStart, flags, advances, advancesIndex);
}
@LayoutlibDelegate
@@ -1076,7 +1050,7 @@ public class Paint_Delegate {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null || delegate.mFonts == null || delegate.mFonts.size() == 0) {
+ if (delegate == null) {
return;
}
delegate.measureText(text, index, count, isRtl(bidiFlags)).roundOut(bounds);
@@ -1150,7 +1124,7 @@ public class Paint_Delegate {
private void updateFontObject() {
if (mTypeface != null) {
// Get the fonts from the TypeFace object.
- List<Font> fonts = mTypeface.getFonts();
+ List<Font> fonts = mTypeface.getFonts(mIsCompact);
// create new font objects as well as FontMetrics, based on the current text size
// and skew info.
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 60cd157..ed8f3b4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -19,7 +19,6 @@ package android.graphics;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.impl.FontLoader;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.content.res.AssetManager;
@@ -44,100 +43,67 @@ import java.util.List;
*/
public final class Typeface_Delegate {
- private static final String SYSTEM_FONTS = "/system/fonts/";
+ public static final String SYSTEM_FONTS = "/system/fonts/";
// ---- delegate manager ----
private static final DelegateManager<Typeface_Delegate> sManager =
new DelegateManager<Typeface_Delegate>(Typeface_Delegate.class);
// ---- delegate helper data ----
- private static final String DEFAULT_FAMILY = "sans-serif";
-
- private static FontLoader sFontLoader;
- private static final List<Typeface_Delegate> sPostInitDelegate =
- new ArrayList<Typeface_Delegate>();
+ private static String sFontLocation;
// ---- delegate data ----
- private final String mFamily;
+ private final long[] mFontFamilies; // the reference to FontFamily_Delegate.
private int mStyle;
- private List<Font> mFonts;
+ private static long sDefaultTypeface;
// ---- Public Helper methods ----
-
- public static synchronized void init(FontLoader fontLoader) {
- sFontLoader = fontLoader;
-
- for (Typeface_Delegate delegate : sPostInitDelegate) {
- delegate.init();
- }
- sPostInitDelegate.clear();
+ public static synchronized void setFontLocation(String fontLocation) {
+ sFontLocation = fontLocation;
+ FontFamily_Delegate.setFontLocation(fontLocation);
}
public static Typeface_Delegate getDelegate(long nativeTypeface) {
return sManager.getDelegate(nativeTypeface);
}
- public static List<Font> getFonts(Typeface typeface) {
- return getFonts(typeface.native_instance);
- }
-
- public static List<Font> getFonts(long native_int) {
- Typeface_Delegate delegate = sManager.getDelegate(native_int);
- if (delegate == null) {
- return null;
+ public List<Font> getFonts(boolean compact) {
+ List<Font> fonts = new ArrayList<Font>(mFontFamilies.length);
+ for (long fontFamily : mFontFamilies) {
+ FontFamily_Delegate ffd = FontFamily_Delegate.getDelegate(fontFamily);
+ if (ffd != null) {
+ Font font = ffd.getFont(mStyle, compact);
+ if (font != null) {
+ fonts.add(font);
+ }
+ }
}
-
- return delegate.getFonts();
- }
-
- public List<Font> getFonts() {
- return mFonts;
+ return fonts;
}
// ---- native methods ----
@LayoutlibDelegate
/*package*/ static synchronized long nativeCreate(String familyName, int style) {
- if (familyName == null) {
- familyName = DEFAULT_FAMILY;
- }
- if (style < 0) {
- style = Typeface.NORMAL;
- }
-
- Typeface_Delegate newDelegate = new Typeface_Delegate(familyName, style);
- if (sFontLoader != null) {
- newDelegate.init();
- } else {
- // font loader has not been initialized yet, add the delegate to a list of delegates
- // to init when the font loader is initialized.
- // There won't be any rendering before this happens anyway.
- sPostInitDelegate.add(newDelegate);
- }
-
- return sManager.addNewDelegate(newDelegate);
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "Could not find font with family \"" + familyName + "\".",
+ null /*throwable*/, null /*data*/);
+ return 0;
}
@LayoutlibDelegate
/*package*/ static synchronized long nativeCreateFromTypeface(long native_instance, int style) {
Typeface_Delegate delegate = sManager.getDelegate(native_instance);
if (delegate == null) {
- return 0;
+ delegate = sManager.getDelegate(sDefaultTypeface);
}
-
- Typeface_Delegate newDelegate = new Typeface_Delegate(delegate.mFamily, style);
- if (sFontLoader != null) {
- newDelegate.init();
- } else {
- // font loader has not been initialized yet, add the delegate to a list of delegates
- // to init when the font loader is initialized.
- // There won't be any rendering before this happens anyway.
- sPostInitDelegate.add(newDelegate);
+ if (delegate == null) {
+ return 0;
}
- return sManager.addNewDelegate(newDelegate);
+ return sManager.addNewDelegate(new Typeface_Delegate(delegate.mFontFamilies, style));
}
@LayoutlibDelegate
@@ -149,31 +115,15 @@ public final class Typeface_Delegate {
@LayoutlibDelegate
/*package*/ static synchronized long nativeCreateFromFile(String path) {
- if (path.startsWith(SYSTEM_FONTS) ) {
- String relativePath = path.substring(SYSTEM_FONTS.length());
- File f = new File(sFontLoader.getOsFontsLocation(), relativePath);
-
- try {
- Font font = Font.createFont(Font.TRUETYPE_FONT, f);
- if (font != null) {
- Typeface_Delegate newDelegate = new Typeface_Delegate(font);
- return sManager.addNewDelegate(newDelegate);
- }
- } catch (Exception e) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
- String.format("Unable to load font %1$s", relativePath),
- null /*throwable*/, null /*data*/);
- }
- } else {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Typeface.createFromFile() can only work with platform fonts located in " +
- SYSTEM_FONTS,
- null /*throwable*/, null /*data*/);
- }
-
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "Typeface.createFromFile() is not supported.,", null, null);
+ return 0;
+ }
- // return a copy of the base font
- return nativeCreate(null, 0);
+ @LayoutlibDelegate
+ /*package*/ static synchronized long nativeCreateFromArray(long[] familyArray) {
+ Typeface_Delegate delegate = new Typeface_Delegate(familyArray, Typeface.NORMAL);
+ return sManager.addNewDelegate(delegate);
}
@LayoutlibDelegate
@@ -191,24 +141,21 @@ public final class Typeface_Delegate {
return delegate.mStyle;
}
- // ---- Private delegate/helper methods ----
-
- private Typeface_Delegate(String family, int style) {
- mFamily = family;
- mStyle = style;
+ @LayoutlibDelegate
+ /*package*/ static void nativeSetDefault(long native_instance) {
+ sDefaultTypeface = native_instance;
}
- private Typeface_Delegate(Font font) {
- mFamily = font.getFamily();
- mStyle = Typeface.NORMAL;
+ @LayoutlibDelegate
+ /*package*/ static File getSystemFontConfigLocation() {
+ return new File(sFontLocation);
+ }
- mFonts = sFontLoader.getFallbackFonts(mStyle);
+ // ---- Private delegate/helper methods ----
- // insert the font glyph first.
- mFonts.add(0, font);
+ private Typeface_Delegate(long[] fontFamilies, int style) {
+ mFontFamilies = fontFamilies;
+ mStyle = style;
}
- private void init() {
- mFonts = sFontLoader.getFont(mFamily, mStyle);
- }
}
diff --git a/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java b/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java
new file mode 100644
index 0000000..a193330
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2014 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.util;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import org.kxml2.io.KXmlParser;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+/**
+ * Delegate overriding some methods of android.util.Xml
+ *
+ * Through the layoutlib_create tool, the original methods of Xml have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
+ * around to map int to instance of the delegate.
+ */
+public class Xml_Delegate {
+
+ @LayoutlibDelegate
+ /*package*/ static XmlPullParser newPullParser() {
+ try {
+ KXmlParser parser = new KXmlParser();
+ // The prebuilt kxml2 library with the IDE doesn't support DOCECL.
+// parser.setFeature(XmlPullParser.FEATURE_PROCESS_DOCDECL, true);
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ return parser;
+ } catch (XmlPullParserException e) {
+ throw new AssertionError();
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index fa8050f..ffab4de 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -26,7 +26,6 @@ import com.android.ide.common.rendering.api.RenderSession;
import com.android.ide.common.rendering.api.Result;
import com.android.ide.common.rendering.api.Result.Status;
import com.android.ide.common.rendering.api.SessionParams;
-import com.android.layoutlib.bridge.impl.FontLoader;
import com.android.layoutlib.bridge.impl.RenderDrawable;
import com.android.layoutlib.bridge.impl.RenderSessionImpl;
import com.android.layoutlib.bridge.util.DynamicIdMap;
@@ -61,7 +60,7 @@ import java.util.concurrent.locks.ReentrantLock;
/**
* Main entry point of the LayoutLib Bridge.
* <p/>To use this bridge, simply instantiate an object of type {@link Bridge} and call
- * {@link #createScene(SceneParams)}
+ * {@link #createSession(SessionParams)}
*/
public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
@@ -147,8 +146,7 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
if (getClass() != obj.getClass()) return false;
IntArray other = (IntArray) obj;
- if (!Arrays.equals(mArray, other.mArray)) return false;
- return true;
+ return Arrays.equals(mArray, other.mArray);
}
}
@@ -251,14 +249,7 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
}
// load the fonts.
- FontLoader fontLoader = FontLoader.create(fontLocation.getAbsolutePath());
- if (fontLoader != null) {
- Typeface_Delegate.init(fontLoader);
- } else {
- log.error(LayoutLog.TAG_BROKEN,
- "Failed create FontLoader in layout lib.", null);
- return false;
- }
+ Typeface_Delegate.setFontLocation(fontLocation.getAbsolutePath());
// now parse com.android.internal.R (and only this one as android.R is a subset of
// the internal version), and put the content in the maps.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java
deleted file mode 100644
index cc7338a..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Copyright (C) 2008 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 com.android.layoutlib.bridge.impl;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import android.graphics.Typeface;
-
-import java.awt.Font;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-/**
- * Provides {@link Font} object to the layout lib.
- * <p/>
- * The fonts are loaded from the SDK directory. Family/style mapping is done by parsing the
- * fonts.xml file located alongside the ttf files.
- */
-public final class FontLoader {
- private static final String FONTS_SYSTEM = "system_fonts.xml";
- private static final String FONTS_VENDOR = "vendor_fonts.xml";
- private static final String FONTS_FALLBACK = "fallback_fonts.xml";
-
- private static final String NODE_FAMILYSET = "familyset";
- private static final String NODE_FAMILY = "family";
- private static final String NODE_NAME = "name";
- private static final String NODE_FILE = "file";
-
- private static final String ATTRIBUTE_VARIANT = "variant";
- private static final String ATTRIBUTE_VALUE_ELEGANT = "elegant";
- private static final String FONT_SUFFIX_NONE = ".ttf";
- private static final String FONT_SUFFIX_REGULAR = "-Regular.ttf";
- private static final String FONT_SUFFIX_BOLD = "-Bold.ttf";
- // FONT_SUFFIX_ITALIC will always match FONT_SUFFIX_BOLDITALIC and hence it must be checked
- // separately.
- private static final String FONT_SUFFIX_ITALIC = "Italic.ttf";
- private static final String FONT_SUFFIX_BOLDITALIC = "-BoldItalic.ttf";
-
- // This must match the values of Typeface styles so that we can use them for indices in this
- // array.
- private static final int[] AWT_STYLES = new int[] {
- Font.PLAIN,
- Font.BOLD,
- Font.ITALIC,
- Font.BOLD | Font.ITALIC
- };
- private static int[] DERIVE_BOLD_ITALIC = new int[] {
- Typeface.ITALIC, Typeface.BOLD, Typeface.NORMAL
- };
- private static int[] DERIVE_ITALIC = new int[] { Typeface.NORMAL };
- private static int[] DERIVE_BOLD = new int[] { Typeface.NORMAL };
-
- private static final List<FontInfo> mMainFonts = new ArrayList<FontInfo>();
- private static final List<FontInfo> mFallbackFonts = new ArrayList<FontInfo>();
-
- private final String mOsFontsLocation;
-
- public static FontLoader create(String fontOsLocation) {
- try {
- SAXParserFactory parserFactory = SAXParserFactory.newInstance();
- parserFactory.setNamespaceAware(true);
-
- // parse the system fonts
- FontHandler handler = parseFontFile(parserFactory, fontOsLocation, FONTS_SYSTEM);
- List<FontInfo> systemFonts = handler.getFontList();
-
-
- // parse the fallback fonts
- handler = parseFontFile(parserFactory, fontOsLocation, FONTS_FALLBACK);
- List<FontInfo> fallbackFonts = handler.getFontList();
-
- return new FontLoader(fontOsLocation, systemFonts, fallbackFonts);
- } catch (ParserConfigurationException e) {
- // return null below
- } catch (SAXException e) {
- // return null below
- } catch (FileNotFoundException e) {
- // return null below
- } catch (IOException e) {
- // return null below
- }
-
- return null;
- }
-
- private static FontHandler parseFontFile(SAXParserFactory parserFactory,
- String fontOsLocation, String fontFileName)
- throws ParserConfigurationException, SAXException, IOException, FileNotFoundException {
-
- SAXParser parser = parserFactory.newSAXParser();
- File f = new File(fontOsLocation, fontFileName);
-
- FontHandler definitionParser = new FontHandler(
- fontOsLocation + File.separator);
- parser.parse(new FileInputStream(f), definitionParser);
- return definitionParser;
- }
-
- private FontLoader(String fontOsLocation,
- List<FontInfo> fontList, List<FontInfo> fallBackList) {
- mOsFontsLocation = fontOsLocation;
- mMainFonts.addAll(fontList);
- mFallbackFonts.addAll(fallBackList);
- }
-
-
- public String getOsFontsLocation() {
- return mOsFontsLocation;
- }
-
- /**
- * Returns a {@link Font} object given a family name and a style value (constant in
- * {@link Typeface}).
- * @param family the family name
- * @param style a 1-item array containing the requested style. Based on the font being read
- * the actual style may be different. The array contains the actual style after
- * the method returns.
- * @return the font object or null if no match could be found.
- */
- public synchronized List<Font> getFont(String family, int style) {
- List<Font> result = new ArrayList<Font>();
-
- if (family == null) {
- return result;
- }
-
-
- // get the font objects from the main list based on family.
- for (FontInfo info : mMainFonts) {
- if (info.families.contains(family)) {
- result.add(info.font[style]);
- break;
- }
- }
-
- // add all the fallback fonts for the given style
- for (FontInfo info : mFallbackFonts) {
- result.add(info.font[style]);
- }
-
- return result;
- }
-
-
- public synchronized List<Font> getFallbackFonts(int style) {
- List<Font> result = new ArrayList<Font>();
- // add all the fallback fonts
- for (FontInfo info : mFallbackFonts) {
- result.add(info.font[style]);
- }
- return result;
- }
-
-
- private final static class FontInfo {
- final Font[] font = new Font[4]; // Matches the 4 type-face styles.
- final Set<String> families;
-
- FontInfo() {
- families = new HashSet<String>();
- }
- }
-
- private final static class FontHandler extends DefaultHandler {
- private final String mOsFontsLocation;
-
- private FontInfo mFontInfo = null;
- private final StringBuilder mBuilder = new StringBuilder();
- private List<FontInfo> mFontList = new ArrayList<FontInfo>();
- private boolean isCompactFont = true;
-
- private FontHandler(String osFontsLocation) {
- super();
- mOsFontsLocation = osFontsLocation;
- }
-
- public List<FontInfo> getFontList() {
- return mFontList;
- }
-
- /* (non-Javadoc)
- * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
- */
- @Override
- public void startElement(String uri, String localName, String name, Attributes attributes)
- throws SAXException {
- if (NODE_FAMILYSET.equals(localName)) {
- mFontList = new ArrayList<FontInfo>();
- } else if (NODE_FAMILY.equals(localName)) {
- if (mFontList != null) {
- mFontInfo = null;
- }
- } else if (NODE_NAME.equals(localName)) {
- if (mFontList != null && mFontInfo == null) {
- mFontInfo = new FontInfo();
- }
- } else if (NODE_FILE.equals(localName)) {
- if (mFontList != null && mFontInfo == null) {
- mFontInfo = new FontInfo();
- }
- if (ATTRIBUTE_VALUE_ELEGANT.equals(attributes.getValue(ATTRIBUTE_VARIANT))) {
- isCompactFont = false;
- } else {
- isCompactFont = true;
- }
- }
-
- mBuilder.setLength(0);
-
- super.startElement(uri, localName, name, attributes);
- }
-
- /* (non-Javadoc)
- * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
- */
- @Override
- public void characters(char[] ch, int start, int length) throws SAXException {
- if (isCompactFont) {
- mBuilder.append(ch, start, length);
- }
- }
-
- /* (non-Javadoc)
- * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
- */
- @Override
- public void endElement(String uri, String localName, String name) throws SAXException {
- if (NODE_FAMILY.equals(localName)) {
- if (mFontInfo != null) {
- // if has a normal font file, add to the list
- if (mFontInfo.font[Typeface.NORMAL] != null) {
- mFontList.add(mFontInfo);
-
- // create missing font styles, order is important.
- if (mFontInfo.font[Typeface.BOLD_ITALIC] == null) {
- computeDerivedFont(Typeface.BOLD_ITALIC, DERIVE_BOLD_ITALIC);
- }
- if (mFontInfo.font[Typeface.ITALIC] == null) {
- computeDerivedFont(Typeface.ITALIC, DERIVE_ITALIC);
- }
- if (mFontInfo.font[Typeface.BOLD] == null) {
- computeDerivedFont(Typeface.BOLD, DERIVE_BOLD);
- }
- }
-
- mFontInfo = null;
- }
- } else if (NODE_NAME.equals(localName)) {
- // handle a new name for an existing Font Info
- if (mFontInfo != null) {
- String family = trimXmlWhitespaces(mBuilder.toString());
- mFontInfo.families.add(family);
- }
- } else if (NODE_FILE.equals(localName)) {
- // handle a new file for an existing Font Info
- if (isCompactFont && mFontInfo != null) {
- String fileName = trimXmlWhitespaces(mBuilder.toString());
- Font font = getFont(fileName);
- if (font != null) {
- if (fileName.endsWith(FONT_SUFFIX_REGULAR)) {
- mFontInfo.font[Typeface.NORMAL] = font;
- } else if (fileName.endsWith(FONT_SUFFIX_BOLD)) {
- mFontInfo.font[Typeface.BOLD] = font;
- } else if (fileName.endsWith(FONT_SUFFIX_BOLDITALIC)) {
- mFontInfo.font[Typeface.BOLD_ITALIC] = font;
- } else if (fileName.endsWith(FONT_SUFFIX_ITALIC)) {
- mFontInfo.font[Typeface.ITALIC] = font;
- } else if (fileName.endsWith(FONT_SUFFIX_NONE)) {
- mFontInfo.font[Typeface.NORMAL] = font;
- }
- }
- }
- }
- }
-
- private Font getFont(String fileName) {
- try {
- File file = new File(mOsFontsLocation, fileName);
- if (file.exists()) {
- return Font.createFont(Font.TRUETYPE_FONT, file);
- }
- } catch (Exception e) {
-
- }
-
- return null;
- }
-
- private void computeDerivedFont( int toCompute, int[] basedOnList) {
- for (int basedOn : basedOnList) {
- if (mFontInfo.font[basedOn] != null) {
- mFontInfo.font[toCompute] =
- mFontInfo.font[basedOn].deriveFont(AWT_STYLES[toCompute]);
- return;
- }
- }
-
- // we really shouldn't stop there. This means we don't have a NORMAL font...
- assert false;
- }
-
- private String trimXmlWhitespaces(String value) {
- if (value == null) {
- return null;
- }
-
- // look for carriage return and replace all whitespace around it by just 1 space.
- int index;
-
- while ((index = value.indexOf('\n')) != -1) {
- // look for whitespace on each side
- int left = index - 1;
- while (left >= 0) {
- if (Character.isWhitespace(value.charAt(left))) {
- left--;
- } else {
- break;
- }
- }
-
- int right = index + 1;
- int count = value.length();
- while (right < count) {
- if (Character.isWhitespace(value.charAt(right))) {
- right++;
- } else {
- break;
- }
- }
-
- // remove all between left and right (non inclusive) and replace by a single space.
- String leftString = null;
- if (left >= 0) {
- leftString = value.substring(0, left + 1);
- }
- String rightString = null;
- if (right < count) {
- rightString = value.substring(right);
- }
-
- if (leftString != null) {
- value = leftString;
- if (rightString != null) {
- value += " " + rightString;
- }
- } else {
- value = rightString != null ? rightString : "";
- }
- }
-
- // now we un-escape the string
- int length = value.length();
- char[] buffer = value.toCharArray();
-
- for (int i = 0 ; i < length ; i++) {
- if (buffer[i] == '\\') {
- if (buffer[i+1] == 'n') {
- // replace the char with \n
- buffer[i+1] = '\n';
- }
-
- // offset the rest of the buffer since we go from 2 to 1 char
- System.arraycopy(buffer, i+1, buffer, i, length - i - 1);
- length--;
- }
- }
-
- return new String(buffer, 0, length);
- }
-
- }
-}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index bb72a1e..1f7a28e 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -125,15 +125,19 @@ public final class CreateInfo implements ICreateInfo {
"android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
"android.content.res.Resources$Theme#obtainStyledAttributes",
"android.content.res.Resources$Theme#resolveAttribute",
+ "android.content.res.Resources$Theme#resolveAttributes",
"android.content.res.Resources#localeToLanguageTag",
"android.content.res.AssetManager#newTheme",
"android.content.res.AssetManager#deleteTheme",
"android.content.res.AssetManager#applyThemeStyle",
"android.content.res.TypedArray#getValueAt",
+ "android.content.res.TypedArray#obtain",
"android.graphics.BitmapFactory#finishDecode",
+ "android.graphics.Typeface#getSystemFontConfigLocation",
"android.os.Handler#sendMessageAtTime",
"android.os.HandlerThread#run",
"android.text.format.DateFormat#is24HourFormat",
+ "android.util.Xml#newPullParser",
"android.view.Choreographer#getRefreshRate",
"android.view.Display#updateDisplayInfoLocked",
"android.view.Display#getWindowManager",
@@ -170,6 +174,7 @@ public final class CreateInfo implements ICreateInfo {
"android.graphics.DiscretePathEffect",
"android.graphics.DrawFilter",
"android.graphics.EmbossMaskFilter",
+ "android.graphics.FontFamily",
"android.graphics.LayerRasterizer",
"android.graphics.LightingColorFilter",
"android.graphics.LinearGradient",