diff options
Diffstat (limited to 'tools/layoutlib/bridge/src/android')
5 files changed, 540 insertions, 143 deletions
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap.java index 7dde634..ff1b295 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap.java @@ -28,13 +28,13 @@ public final class Bitmap extends _Original_Bitmap { private BufferedImage mImage; public Bitmap(File input) throws IOException { - super(1, true, null); + super(1, true, null, -1); mImage = ImageIO.read(input); } Bitmap(BufferedImage image) { - super(1, true, null); + super(1, true, null, -1); mImage = image; } diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas.java b/tools/layoutlib/bridge/src/android/graphics/Canvas.java index 3fa1d1d..4986c77 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas.java @@ -26,6 +26,7 @@ import android.graphics.RectF; import android.graphics.Region; import android.graphics.Xfermode; import android.graphics.Paint.Align; +import android.graphics.Paint.FontInfo; import android.graphics.Paint.Style; import android.graphics.Region.Op; @@ -37,6 +38,7 @@ import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; +import java.util.List; import java.util.Stack; import javax.microedition.khronos.opengles.GL; @@ -620,19 +622,21 @@ public class Canvas extends _Original_Canvas { */ @Override public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { + // WARNING: the logic in this method is similar to Paint.measureText. + // Any change to this method should be reflected in Paint.measureText Graphics2D g = getGraphics2d(); g = (Graphics2D)g.create(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g.setFont(paint.getFont()); - - // set the color. because this only handles RGB we have to handle the alpha separately + // set the color. because this only handles RGB, the alpha channel is handled + // as a composite. g.setColor(new Color(paint.getColor())); int alpha = paint.getAlpha(); float falpha = alpha / 255.f; g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); + // Paint.TextAlign indicates how the text is positioned relative to X. // LEFT is the default and there's nothing to do. if (paint.getTextAlign() != Align.LEFT) { @@ -644,9 +648,83 @@ public class Canvas extends _Original_Canvas { } } - g.drawChars(text, index, count, (int)x, (int)y); - - g.dispose(); + List<FontInfo> fonts = paint.getFonts(); + try { + if (fonts.size() > 0) { + FontInfo mainFont = fonts.get(0); + int i = index; + int lastIndex = index + count; + while (i < lastIndex) { + // always start with the main font. + int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex); + if (upTo == -1) { + // draw all the rest and exit. + g.setFont(mainFont.mFont); + g.drawChars(text, i, lastIndex - i, (int)x, (int)y); + return; + } else if (upTo > 0) { + // draw what's possible + g.setFont(mainFont.mFont); + g.drawChars(text, i, upTo - i, (int)x, (int)y); + + // compute the width that was drawn to increase x + x += mainFont.mMetrics.charsWidth(text, i, upTo - i); + + // move index to the first non displayed char. + i = upTo; + + // don't call continue at this point. Since it is certain the main font + // cannot display the font a index upTo (now ==i), we move on to the + // fallback fonts directly. + } + + // no char supported, attempt to read the next char(s) with the + // fallback font. In this case we only test the first character + // and then go back to test with the main font. + // Special test for 2-char characters. + boolean foundFont = false; + for (int f = 1 ; f < fonts.size() ; f++) { + FontInfo fontInfo = fonts.get(f); + + // need to check that the font can display the character. We test + // differently if the char is a high surrogate. + int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; + upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount); + if (upTo == -1) { + // draw that char + g.setFont(fontInfo.mFont); + g.drawChars(text, i, charCount, (int)x, (int)y); + + // update x + x += fontInfo.mMetrics.charsWidth(text, i, charCount); + + // update the index in the text, and move on + i += charCount; + foundFont = true; + break; + + } + } + + // in case no font can display the char, display it with the main font. + // (it'll put a square probably) + if (foundFont == false) { + int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; + + g.setFont(mainFont.mFont); + g.drawChars(text, i, charCount, (int)x, (int)y); + + // measure it to advance x + x += mainFont.mMetrics.charsWidth(text, i, charCount); + + // and move to the next chars. + i += charCount; + } + } + } + } finally { + g.dispose(); + } } /* (non-Javadoc) diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint.java b/tools/layoutlib/bridge/src/android/graphics/Paint.java index ade07d6..86de56b 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint.java @@ -26,6 +26,9 @@ import java.awt.Toolkit; import java.awt.font.FontRenderContext; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** * A paint implementation overridden by the LayoutLib bridge. @@ -33,17 +36,28 @@ import java.awt.geom.Rectangle2D; public class Paint extends _Original_Paint { private int mColor = 0xFFFFFFFF; + private float mStrokeWidth = 1.f; private float mTextSize = 20; private float mScaleX = 1; private float mSkewX = 0; private Align mAlign = Align.LEFT; private Style mStyle = Style.FILL; + private float mStrokeMiter = 4.0f; + private Cap mCap = Cap.BUTT; + private Join mJoin = Join.MITER; private int mFlags = 0; - - private Font mFont; + + /** + * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}. + */ + public static final class FontInfo { + Font mFont; + java.awt.FontMetrics mMetrics; + } + + private List<FontInfo> mFonts; private final FontRenderContext mFontContext = new FontRenderContext( new AffineTransform(), true, true); - private java.awt.FontMetrics mMetrics; @SuppressWarnings("hiding") public static final int ANTI_ALIAS_FLAG = _Original_Paint.ANTI_ALIAS_FLAG; @@ -65,11 +79,11 @@ public class Paint extends _Original_Paint { public static final int DEV_KERN_TEXT_FLAG = _Original_Paint.DEV_KERN_TEXT_FLAG; public static class FontMetrics extends _Original_Paint.FontMetrics { - } + } public static class FontMetricsInt extends _Original_Paint.FontMetricsInt { } - + /** * The Style specifies if the primitive being drawn is filled, * stroked, or both (in the same color). The default is FILL. @@ -91,7 +105,7 @@ public class Paint extends _Original_Paint { * the paint. */ FILL_AND_STROKE (2); - + Style(int nativeInt) { this.nativeInt = nativeInt; } @@ -117,7 +131,7 @@ public class Paint extends _Original_Paint { * end of the path. */ SQUARE (2); - + private Cap(int nativeInt) { this.nativeInt = nativeInt; } @@ -141,7 +155,7 @@ public class Paint extends _Original_Paint { * The outer edges of a join meet with a straight line */ BEVEL (2); - + private Join(int nativeInt) { this.nativeInt = nativeInt; } @@ -165,7 +179,7 @@ public class Paint extends _Original_Paint { * The text is drawn to the left of the x,y origin */ RIGHT (2); - + private Align(int nativeInt) { this.nativeInt = nativeInt; } @@ -185,43 +199,61 @@ public class Paint extends _Original_Paint { set(paint); initFont(); } - + @Override public void finalize() throws Throwable { // pass } - + + @Override + public void reset() { + super.reset(); + } + /** - * Returns the {@link Font} object. + * 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. */ - public Font getFont() { - return mFont; + public List<FontInfo> getFonts() { + return mFonts; } - + private void initFont() { mTypeface = Typeface.DEFAULT; updateFontObject(); } - + /** * Update the {@link Font} object from the typeface, text size and scaling */ + @SuppressWarnings("deprecation") private void updateFontObject() { if (mTypeface != null) { - // get the typeface font object, and get our font object from it, based on the current size - mFont = mTypeface.getFont().deriveFont(mTextSize); - if (mScaleX != 1.0 || mSkewX != 0) { - // TODO: support skew - mFont = mFont.deriveFont(new AffineTransform( - mScaleX, mSkewX, 0, 0, 1, 0)); + // Get the fonts from the TypeFace object. + List<Font> fonts = mTypeface.getFonts(); + + // create new font objects as well as FontMetrics, based on the current text size + // and skew info. + ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(fonts.size()); + for (Font font : fonts) { + FontInfo info = new FontInfo(); + info.mFont = font.deriveFont(mTextSize); + if (mScaleX != 1.0 || mSkewX != 0) { + // TODO: support skew + info.mFont = info.mFont.deriveFont(new AffineTransform( + mScaleX, mSkewX, 0, 0, 1, 0)); + } + info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont); + + infoList.add(info); } - - mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(mFont); + + mFonts = Collections.unmodifiableList(infoList); } } - + //---------------------------------------- - + public void set(Paint src) { if (this != src) { mColor = src.mColor; @@ -237,6 +269,11 @@ public class Paint extends _Original_Paint { } @Override + public void setCompatibilityScaling(float factor) { + super.setCompatibilityScaling(factor); + } + + @Override public int getFlags() { return mFlags; } @@ -245,7 +282,47 @@ public class Paint extends _Original_Paint { public void setFlags(int flags) { mFlags = flags; } - + + @Override + public boolean isAntiAlias() { + return super.isAntiAlias(); + } + + @Override + public boolean isDither() { + return super.isDither(); + } + + @Override + public boolean isLinearText() { + return super.isLinearText(); + } + + @Override + public boolean isStrikeThruText() { + return super.isStrikeThruText(); + } + + @Override + public boolean isUnderlineText() { + return super.isUnderlineText(); + } + + @Override + public boolean isFakeBoldText() { + return super.isFakeBoldText(); + } + + @Override + public boolean isSubpixelText() { + return super.isSubpixelText(); + } + + @Override + public boolean isFilterBitmap() { + return super.isFilterBitmap(); + } + /** * Return the font's recommended interline spacing, given the Paint's * settings for typeface, textSize, etc. If metrics is not null, return the @@ -256,39 +333,41 @@ public class Paint extends _Original_Paint { * @return the font's recommended interline spacing. */ public float getFontMetrics(FontMetrics metrics) { - if (mMetrics != null) { + if (mFonts.size() > 0) { + java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; if (metrics != null) { - // ascent stuff should be negatif, but awt returns them as positive. - metrics.top = - mMetrics.getMaxAscent(); - metrics.ascent = - mMetrics.getAscent(); - metrics.descent = mMetrics.getDescent(); - metrics.bottom = mMetrics.getMaxDescent(); - metrics.leading = mMetrics.getLeading(); + // Android expects negative ascent so we invert the value from Java. + metrics.top = - javaMetrics.getMaxAscent(); + metrics.ascent = - javaMetrics.getAscent(); + metrics.descent = javaMetrics.getDescent(); + metrics.bottom = javaMetrics.getMaxDescent(); + metrics.leading = javaMetrics.getLeading(); } - - return mMetrics.getHeight(); + + return javaMetrics.getHeight(); } - + return 0; } public int getFontMetricsInt(FontMetricsInt metrics) { - if (mMetrics != null) { + if (mFonts.size() > 0) { + java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; if (metrics != null) { - // ascent stuff should be negatif, but awt returns them as positive. - metrics.top = - mMetrics.getMaxAscent(); - metrics.ascent = - mMetrics.getAscent(); - metrics.descent = mMetrics.getDescent(); - metrics.bottom = mMetrics.getMaxDescent(); - metrics.leading = mMetrics.getLeading(); + // Android expects negative ascent so we invert the value from Java. + metrics.top = - javaMetrics.getMaxAscent(); + metrics.ascent = - javaMetrics.getAscent(); + metrics.descent = javaMetrics.getDescent(); + metrics.bottom = javaMetrics.getMaxDescent(); + metrics.leading = javaMetrics.getLeading(); } - - return mMetrics.getHeight(); + + return javaMetrics.getHeight(); } - + return 0; } - + /** * Reimplemented to return Paint.FontMetrics instead of _Original_Paint.FontMetrics */ @@ -297,7 +376,7 @@ public class Paint extends _Original_Paint { getFontMetrics(fm); return fm; } - + /** * Reimplemented to return Paint.FontMetricsInt instead of _Original_Paint.FontMetricsInt */ @@ -311,16 +390,14 @@ public class Paint extends _Original_Paint { @Override public float getFontMetrics(_Original_Paint.FontMetrics metrics) { - // TODO implement if needed throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); } @Override public int getFontMetricsInt(_Original_Paint.FontMetricsInt metrics) { - // TODO implement if needed throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); } - + @Override public Typeface setTypeface(Typeface typeface) { if (typeface != null) { @@ -328,12 +405,17 @@ public class Paint extends _Original_Paint { } else { mTypeface = Typeface.DEFAULT; } - + updateFontObject(); return typeface; } - + + @Override + public Typeface getTypeface() { + return super.getTypeface(); + } + @Override public int getColor() { return mColor; @@ -344,17 +426,21 @@ public class Paint extends _Original_Paint { mColor = color; } + @Override + public void setARGB(int a, int r, int g, int b) { + super.setARGB(a, r, g, b); + } @Override public void setAlpha(int alpha) { mColor = (alpha << 24) | (mColor & 0x00FFFFFF); } - + @Override public int getAlpha() { return mColor >>> 24; } - + /** * Set or clear the shader object. * <p /> @@ -369,6 +455,11 @@ public class Paint extends _Original_Paint { return mShader = shader; } + @Override + public Shader getShader() { + return super.getShader(); + } + /** * Set or clear the paint's colorfilter, returning the parameter. * @@ -377,13 +468,15 @@ public class Paint extends _Original_Paint { */ @Override public ColorFilter setColorFilter(ColorFilter filter) { - int filterNative = 0; - if (filter != null) - filterNative = filter.native_instance; mColorFilter = filter; return filter; } + @Override + public ColorFilter getColorFilter() { + return super.getColorFilter(); + } + /** * Set or clear the xfermode object. * <p /> @@ -397,50 +490,172 @@ public class Paint extends _Original_Paint { public Xfermode setXfermode(Xfermode xfermode) { return mXfermode = xfermode; } - + + @Override + public Xfermode getXfermode() { + return super.getXfermode(); + } + + @Override + public Rasterizer setRasterizer(Rasterizer rasterizer) { + mRasterizer = rasterizer; + return rasterizer; + } + + @Override + public Rasterizer getRasterizer() { + return super.getRasterizer(); + } + + @Override + public void setShadowLayer(float radius, float dx, float dy, int color) { + // TODO Auto-generated method stub + } + + @Override + public void clearShadowLayer() { + super.clearShadowLayer(); + } + public void setTextAlign(Align align) { mAlign = align; } - + @Override public void setTextAlign(android.graphics._Original_Paint.Align align) { - // TODO implement if needed throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); } - + public Align getTextAlign() { return mAlign; } - + public void setStyle(Style style) { mStyle = style; } @Override public void setStyle(android.graphics._Original_Paint.Style style) { - // TODO implement if needed throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); } public Style getStyle() { return mStyle; } - + @Override public void setDither(boolean dither) { mFlags |= dither ? DITHER_FLAG : ~DITHER_FLAG; } - + @Override public void setAntiAlias(boolean aa) { mFlags |= aa ? ANTI_ALIAS_FLAG : ~ANTI_ALIAS_FLAG; } - + @Override public void setFakeBoldText(boolean flag) { mFlags |= flag ? FAKE_BOLD_TEXT_FLAG : ~FAKE_BOLD_TEXT_FLAG; } + @Override + public void setLinearText(boolean flag) { + mFlags |= flag ? LINEAR_TEXT_FLAG : ~LINEAR_TEXT_FLAG; + } + + @Override + public void setSubpixelText(boolean flag) { + mFlags |= flag ? SUBPIXEL_TEXT_FLAG : ~SUBPIXEL_TEXT_FLAG; + } + + @Override + public void setUnderlineText(boolean flag) { + mFlags |= flag ? UNDERLINE_TEXT_FLAG : ~UNDERLINE_TEXT_FLAG; + } + + @Override + public void setStrikeThruText(boolean flag) { + mFlags |= flag ? STRIKE_THRU_TEXT_FLAG : ~STRIKE_THRU_TEXT_FLAG; + } + + @Override + public void setFilterBitmap(boolean flag) { + mFlags |= flag ? FILTER_BITMAP_FLAG : ~FILTER_BITMAP_FLAG; + } + + @Override + public float getStrokeWidth() { + return mStrokeWidth; + } + + @Override + public void setStrokeWidth(float width) { + mStrokeWidth = width; + } + + @Override + public float getStrokeMiter() { + return mStrokeMiter; + } + + @Override + public void setStrokeMiter(float miter) { + mStrokeMiter = miter; + } + + @Override + public void setStrokeCap(android.graphics._Original_Paint.Cap cap) { + throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); + } + + public void setStrokeCap(Cap cap) { + mCap = cap; + } + + public Cap getStrokeCap() { + return mCap; + } + + @Override + public void setStrokeJoin(android.graphics._Original_Paint.Join join) { + throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); + } + + public void setStrokeJoin(Join join) { + mJoin = join; + } + + public Join getStrokeJoin() { + return mJoin; + } + + @Override + public boolean getFillPath(Path src, Path dst) { + return super.getFillPath(src, dst); + } + + @Override + public PathEffect setPathEffect(PathEffect effect) { + mPathEffect = effect; + return effect; + } + + @Override + public PathEffect getPathEffect() { + return super.getPathEffect(); + } + + @Override + public MaskFilter setMaskFilter(MaskFilter maskfilter) { + mMaskFilter = maskfilter; + return maskfilter; + } + + @Override + public MaskFilter getMaskFilter() { + return super.getMaskFilter(); + } + /** * Return the paint's text size. * @@ -459,7 +674,7 @@ public class Paint extends _Original_Paint { @Override public void setTextSize(float textSize) { mTextSize = textSize; - + updateFontObject(); } @@ -484,7 +699,7 @@ public class Paint extends _Original_Paint { @Override public void setTextScaleX(float scaleX) { mScaleX = scaleX; - + updateFontObject(); } @@ -508,10 +723,15 @@ public class Paint extends _Original_Paint { @Override public void setTextSkewX(float skewX) { mSkewX = skewX; - + updateFontObject(); } + @Override + public float getFontSpacing() { + return super.getFontSpacing(); + } + /** * Return the distance above (negative) the baseline (ascent) based on the * current typeface and text size. @@ -521,11 +741,12 @@ public class Paint extends _Original_Paint { */ @Override public float ascent() { - if (mMetrics != null) { - // ascent stuff should be negatif, but awt returns them as positive. - return - mMetrics.getAscent(); + if (mFonts.size() > 0) { + java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; + // Android expects negative ascent so we invert the value from Java. + return - javaMetrics.getAscent(); } - + return 0; } @@ -538,13 +759,14 @@ public class Paint extends _Original_Paint { */ @Override public float descent() { - if (mMetrics != null) { - return mMetrics.getDescent(); + if (mFonts.size() > 0) { + java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; + return javaMetrics.getDescent(); } - + return 0; } - + /** * Return the width of the text. * @@ -555,12 +777,57 @@ public class Paint extends _Original_Paint { */ @Override public float measureText(char[] text, int index, int count) { - if (mFont != null && text != null && text.length > 0) { - Rectangle2D bounds = mFont.getStringBounds(text, index, index + count, mFontContext); - - return (float)bounds.getWidth(); + // WARNING: the logic in this method is similar to Canvas.drawText. + // Any change to this method should be reflected in Canvas.drawText + if (mFonts.size() > 0) { + FontInfo mainFont = mFonts.get(0); + int i = index; + int lastIndex = index + count; + float total = 0f; + while (i < lastIndex) { + // always start with the main font. + int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex); + if (upTo == -1) { + // shortcut to exit + return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i); + } else if (upTo > 0) { + total += mainFont.mMetrics.charsWidth(text, i, upTo - i); + i = upTo; + // don't call continue at this point. Since it is certain the main font + // cannot display the font a index upTo (now ==i), we move on to the + // fallback fonts directly. + } + + // no char supported, attempt to read the next char(s) with the + // fallback font. In this case we only test the first character + // and then go back to test with the main font. + // Special test for 2-char characters. + boolean foundFont = false; + for (int f = 1 ; f < mFonts.size() ; f++) { + FontInfo fontInfo = mFonts.get(f); + + // need to check that the font can display the character. We test + // differently if the char is a high surrogate. + int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; + upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount); + if (upTo == -1) { + total += fontInfo.mMetrics.charsWidth(text, i, charCount); + i += charCount; + foundFont = true; + break; + + } + } + + // in case no font can display the char, measure it with the main font. + if (foundFont == false) { + int size = Character.isHighSurrogate(text[i]) ? 2 : 1; + total += mainFont.mMetrics.charsWidth(text, i, size); + i += size; + } + } } - + return 0; } @@ -587,7 +854,7 @@ public class Paint extends _Original_Paint { public float measureText(String text) { return measureText(text.toCharArray(), 0, text.length()); } - + /* * re-implement to call SpannableStringBuilder.measureText with a Paint object * instead of an _Original_Paint @@ -611,7 +878,7 @@ public class Paint extends _Original_Paint { TemporaryBuffer.recycle(buf); return result; } - + /** * Measure the text, stopping early if the measured width exceeds maxWidth. * Return the number of chars that were measured, and if measuredWidth is @@ -633,7 +900,7 @@ public class Paint extends _Original_Paint { public int breakText(char[] text, int index, int count, float maxWidth, float[] measuredWidth) { int inc = count > 0 ? 1 : -1; - + int measureIndex = 0; float measureAcc = 0; for (int i = index ; i != index + count ; i += inc, measureIndex++) { @@ -645,23 +912,23 @@ public class Paint extends _Original_Paint { start = index; end = i; } - + // measure from start to end float res = measureText(text, start, end - start + 1); - + if (measuredWidth != null) { 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; return measureIndex; } - + } - + return measureIndex; } @@ -690,6 +957,28 @@ public class Paint extends _Original_Paint { } /** + * Measure the text, stopping early if the measured width exceeds maxWidth. + * Return the number of chars that were measured, and if measuredWidth is + * not null, return in it the actual width measured. + * + * @param text The text to measure + * @param start The offset into text to begin measuring at + * @param end The end of the text slice to measure. + * @param measureForwards If true, measure forwards, starting at start. + * Otherwise, measure backwards, starting with end. + * @param maxWidth The maximum width to accumulate. + * @param measuredWidth Optional. If not null, returns the actual width + * measured. + * @return The number of chars that were measured. Will always be <= + * abs(end - start). + */ + @Override + public int breakText(CharSequence text, int start, int end, boolean measureForwards, + float maxWidth, float[] measuredWidth) { + return super.breakText(text, start, end, measureForwards, maxWidth, measuredWidth); + } + + /** * Return the advance widths for the characters in the string. * * @param text The text to measure @@ -702,19 +991,35 @@ public class Paint extends _Original_Paint { @Override public int getTextWidths(char[] text, int index, int count, float[] widths) { - if (mMetrics != null) { + if (mFonts.size() > 0) { if ((index | count) < 0 || index + count > text.length || count > widths.length) { throw new ArrayIndexOutOfBoundsException(); } - + + // FIXME: handle multi-char characters. + // Need to figure out if the lengths of the width array takes into account + // multi-char characters. for (int i = 0; i < count; i++) { - widths[i] = mMetrics.charWidth(text[i + index]); + char c = text[i + index]; + boolean found = false; + for (FontInfo info : mFonts) { + if (info.mFont.canDisplay(c)) { + widths[i] = info.mMetrics.charWidth(c); + found = true; + break; + } + } + + if (found == false) { + // we stop there. + return i; + } } - + return count; } - + return 0; } @@ -736,10 +1041,10 @@ public class Paint extends _Original_Paint { if (end - start > widths.length) { throw new ArrayIndexOutOfBoundsException(); } - + return getTextWidths(text.toCharArray(), start, end - start, widths); } - + /* * re-implement to call SpannableStringBuilder.getTextWidths with a Paint object * instead of an _Original_Paint @@ -763,6 +1068,10 @@ public class Paint extends _Original_Paint { return result; } + @Override + public int getTextWidths(String text, float[] widths) { + return super.getTextWidths(text, widths); + } /** * Return the path (outline) for the specified text. @@ -782,13 +1091,13 @@ public class Paint extends _Original_Paint { float x, float y, Path path) { // TODO this is the ORIGINAL implementation. REPLACE AS NEEDED OR REMOVE - + if ((index | count) < 0 || index + count > text.length) { throw new ArrayIndexOutOfBoundsException(); } - + // TODO native_getTextPath(mNativePaint, text, index, count, x, y, path.ni()); - + throw new UnsupportedOperationException("IMPLEMENT AS NEEDED"); } @@ -811,10 +1120,10 @@ public class Paint extends _Original_Paint { if ((start | end | (end - start) | (text.length() - end)) < 0) { throw new IndexOutOfBoundsException(); } - + getTextPath(text.toCharArray(), start, end - start, x, y, path); } - + /** * Return in bounds (allocated by the caller) the smallest rectangle that * encloses all of the characters, with an implied origin at (0,0). @@ -833,10 +1142,10 @@ public class Paint extends _Original_Paint { if (bounds == null) { throw new NullPointerException("need bounds Rect"); } - + getTextBounds(text.toCharArray(), start, end - start, bounds); } - + /** * Return in bounds (allocated by the caller) the smallest rectangle that * encloses all of the characters, with an implied origin at (0,0). @@ -849,16 +1158,23 @@ public class Paint extends _Original_Paint { */ @Override public void getTextBounds(char[] text, int index, int count, Rect bounds) { - if (mFont != null) { + // FIXME + if (mFonts.size() > 0) { if ((index | count) < 0 || index + count > text.length) { throw new ArrayIndexOutOfBoundsException(); } if (bounds == null) { throw new NullPointerException("need bounds Rect"); } - - Rectangle2D rect = mFont.getStringBounds(text, index, index + count, mFontContext); + + FontInfo mainInfo = mFonts.get(0); + + Rectangle2D rect = mainInfo.mFont.getStringBounds(text, index, index + count, mFontContext); bounds.set(0, 0, (int)rect.getWidth(), (int)rect.getHeight()); } } + + public static void finalizer(int foo) { + // pass + } } diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface.java b/tools/layoutlib/bridge/src/android/graphics/Typeface.java index e878b04..af3adb5 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface.java +++ b/tools/layoutlib/bridge/src/android/graphics/Typeface.java @@ -21,9 +21,12 @@ import com.android.layoutlib.bridge.FontLoader; import android.content.res.AssetManager; import java.awt.Font; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** - * Re-implementation of Typeface over java.awt + * Re-implementation of Typeface over java.awt */ public class Typeface { private static final String DEFAULT_FAMILY = "sans-serif"; @@ -46,11 +49,11 @@ public class Typeface { private static Typeface[] sDefaults; private static FontLoader mFontLoader; - + private final int mStyle; - private final Font mFont; + private final List<Font> mFonts; private final String mFamily; - + // Style public static final int NORMAL = _Original_Typeface.NORMAL; public static final int BOLD = _Original_Typeface.BOLD; @@ -58,12 +61,13 @@ public class Typeface { public static final int BOLD_ITALIC = _Original_Typeface.BOLD_ITALIC; /** - * Returns the underlying {@link Font} object. + * Returns the underlying {@link Font} objects. The first item in the list is the real + * font. Any other items are fallback fonts for characters not found in the first one. */ - public Font getFont() { - return mFont; + public List<Font> getFonts() { + return mFonts; } - + /** Returns the typeface's intrinsic style attributes */ public int getStyle() { return mStyle; @@ -94,9 +98,12 @@ public class Typeface { styleBuffer[0] = style; Font font = mFontLoader.getFont(familyName, styleBuffer); if (font != null) { - return new Typeface(familyName, styleBuffer[0], font); + ArrayList<Font> list = new ArrayList<Font>(); + list.add(font); + list.addAll(mFontLoader.getFallBackFonts()); + return new Typeface(familyName, styleBuffer[0], list); } - + return null; } @@ -115,7 +122,10 @@ public class Typeface { styleBuffer[0] = style; Font font = mFontLoader.getFont(family.mFamily, styleBuffer); if (font != null) { - return new Typeface(family.mFamily, styleBuffer[0], font); + ArrayList<Font> list = new ArrayList<Font>(); + list.add(font); + list.addAll(mFontLoader.getFallBackFonts()); + return new Typeface(family.mFamily, styleBuffer[0], list); } return null; @@ -129,7 +139,7 @@ public class Typeface { public static Typeface defaultFromStyle(int style) { return sDefaults[style]; } - + /** * Create a new typeface from the specified font data. * @param mgr The application's asset manager @@ -140,17 +150,17 @@ public class Typeface { return null; //return new Typeface(nativeCreateFromAsset(mgr, path)); } - + // don't allow clients to call this directly - private Typeface(String family, int style, Font f) { + private Typeface(String family, int style, List<Font> fonts) { mFamily = family; - mFont = f; + mFonts = Collections.unmodifiableList(fonts); mStyle = style; } - + public static void init(FontLoader fontLoader) { mFontLoader = fontLoader; - + DEFAULT = create(DEFAULT_FAMILY, NORMAL); DEFAULT_BOLD = create(DEFAULT_FAMILY, BOLD); SANS_SERIF = create("sans-serif", NORMAL); @@ -162,14 +172,14 @@ public class Typeface { create(DEFAULT_FAMILY, ITALIC), create(DEFAULT_FAMILY, BOLD_ITALIC), }; - + /* DEFAULT = create((String)null, 0); DEFAULT_BOLD = create((String)null, Typeface.BOLD); SANS_SERIF = create("sans-serif", 0); SERIF = create("serif", 0); MONOSPACE = create("monospace", 0); - + sDefaults = new Typeface[] { DEFAULT, DEFAULT_BOLD, diff --git a/tools/layoutlib/bridge/src/android/webkit/WebView.java b/tools/layoutlib/bridge/src/android/webkit/WebView.java index 42e4dfa..3b66188 100644 --- a/tools/layoutlib/bridge/src/android/webkit/WebView.java +++ b/tools/layoutlib/bridge/src/android/webkit/WebView.java @@ -240,13 +240,6 @@ public class WebView extends MockView { return null; } - public static synchronized PluginList getPluginList() { - return null; - } - - public void refreshPlugins(boolean reloadOpenPages) { - } - public View getZoomControls() { return null; } |