summaryrefslogtreecommitdiff
path: root/tools/layoutlib/bridge/src/android/graphics/Paint.java
diff options
context:
space:
mode:
Diffstat (limited to 'tools/layoutlib/bridge/src/android/graphics/Paint.java')
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Paint.java856
1 files changed, 856 insertions, 0 deletions
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint.java b/tools/layoutlib/bridge/src/android/graphics/Paint.java
new file mode 100644
index 000000000000..27276c55a68b
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint.java
@@ -0,0 +1,856 @@
+/*
+ * 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 android.graphics;
+
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.SpannedString;
+import android.text.TextUtils;
+
+import java.awt.Font;
+import java.awt.Toolkit;
+import java.awt.font.FontRenderContext;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * A paint implementation overridden by the LayoutLib bridge.
+ */
+public class Paint extends _Original_Paint {
+
+ private int mColor = 0xFFFFFFFF;
+ private float mTextSize = 20;
+ private float mScaleX = 1;
+ private float mSkewX = 0;
+ private Align mAlign = Align.LEFT;
+ private Style mStyle = Style.FILL;
+ private int mFlags = 0;
+
+ private Font mFont;
+ private final FontRenderContext mFontContext = new FontRenderContext(
+ new AffineTransform(), true, true);
+ private java.awt.FontMetrics mMetrics;
+
+ public static final int ANTI_ALIAS_FLAG = _Original_Paint.ANTI_ALIAS_FLAG;
+ public static final int FILTER_BITMAP_FLAG = _Original_Paint.FILTER_BITMAP_FLAG;
+ public static final int DITHER_FLAG = _Original_Paint.DITHER_FLAG;
+ public static final int UNDERLINE_TEXT_FLAG = _Original_Paint.UNDERLINE_TEXT_FLAG;
+ public static final int STRIKE_THRU_TEXT_FLAG = _Original_Paint.STRIKE_THRU_TEXT_FLAG;
+ public static final int FAKE_BOLD_TEXT_FLAG = _Original_Paint.FAKE_BOLD_TEXT_FLAG;
+ public static final int LINEAR_TEXT_FLAG = _Original_Paint.LINEAR_TEXT_FLAG;
+ public static final int SUBPIXEL_TEXT_FLAG = _Original_Paint.SUBPIXEL_TEXT_FLAG;
+ 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.
+ */
+ public enum Style {
+ /**
+ * Geometry and text drawn with this style will be filled, ignoring all
+ * stroke-related settings in the paint.
+ */
+ FILL (0),
+ /**
+ * Geometry and text drawn with this style will be stroked, respecting
+ * the stroke-related fields on the paint.
+ */
+ STROKE (1),
+ /**
+ * Geometry and text drawn with this style will be both filled and
+ * stroked at the same time, respecting the stroke-related fields on
+ * the paint.
+ */
+ FILL_AND_STROKE (2);
+
+ Style(int nativeInt) {
+ this.nativeInt = nativeInt;
+ }
+ final int nativeInt;
+ }
+
+ /**
+ * The Cap specifies the treatment for the beginning and ending of
+ * stroked lines and paths. The default is BUTT.
+ */
+ public enum Cap {
+ /**
+ * The stroke ends with the path, and does not project beyond it.
+ */
+ BUTT (0),
+ /**
+ * The stroke projects out as a square, with the center at the end
+ * of the path.
+ */
+ ROUND (1),
+ /**
+ * The stroke projects out as a semicircle, with the center at the
+ * end of the path.
+ */
+ SQUARE (2);
+
+ private Cap(int nativeInt) {
+ this.nativeInt = nativeInt;
+ }
+ final int nativeInt;
+ }
+
+ /**
+ * The Join specifies the treatment where lines and curve segments
+ * join on a stroked path. The default is MITER.
+ */
+ public enum Join {
+ /**
+ * The outer edges of a join meet at a sharp angle
+ */
+ MITER (0),
+ /**
+ * The outer edges of a join meet in a circular arc.
+ */
+ ROUND (1),
+ /**
+ * The outer edges of a join meet with a straight line
+ */
+ BEVEL (2);
+
+ private Join(int nativeInt) {
+ this.nativeInt = nativeInt;
+ }
+ final int nativeInt;
+ }
+
+ /**
+ * Align specifies how drawText aligns its text relative to the
+ * [x,y] coordinates. The default is LEFT.
+ */
+ public enum Align {
+ /**
+ * The text is drawn to the right of the x,y origin
+ */
+ LEFT (0),
+ /**
+ * The text is drawn centered horizontally on the x,y origin
+ */
+ CENTER (1),
+ /**
+ * The text is drawn to the left of the x,y origin
+ */
+ RIGHT (2);
+
+ private Align(int nativeInt) {
+ this.nativeInt = nativeInt;
+ }
+ final int nativeInt;
+ }
+
+ public Paint() {
+ this(0);
+ }
+
+ public Paint(int flags) {
+ setFlags(flags | DEFAULT_PAINT_FLAGS);
+ initFont();
+ }
+
+ public Paint(Paint paint) {
+ set(paint);
+ initFont();
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ // pass
+ }
+
+ /**
+ * Returns the {@link Font} object.
+ */
+ public Font getFont() {
+ return mFont;
+ }
+
+ private void initFont() {
+ mTypeface = Typeface.DEFAULT;
+ updateFontObject();
+ }
+
+ /**
+ * Update the {@link Font} object from the typeface, text size and scaling
+ */
+ 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));
+ }
+
+ mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(mFont);
+ }
+ }
+
+ //----------------------------------------
+
+ public void set(Paint src) {
+ if (this != src) {
+ mColor = src.mColor;
+ mTextSize = src.mTextSize;
+ mScaleX = src.mScaleX;
+ mSkewX = src.mSkewX;
+ mAlign = src.mAlign;
+ mStyle = src.mStyle;
+ mFlags = src.mFlags;
+
+ super.set(src);
+ }
+ }
+
+ @Override
+ public int getFlags() {
+ return mFlags;
+ }
+
+ @Override
+ public void setFlags(int flags) {
+ mFlags = flags;
+ }
+
+ /**
+ * Return the font's recommended interline spacing, given the Paint's
+ * settings for typeface, textSize, etc. If metrics is not null, return the
+ * fontmetric values in it.
+ *
+ * @param metrics If this object is not null, its fields are filled with
+ * the appropriate values given the paint's text attributes.
+ * @return the font's recommended interline spacing.
+ */
+ public float getFontMetrics(FontMetrics metrics) {
+ if (mMetrics != null) {
+ 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();
+ }
+
+ return mMetrics.getHeight();
+ }
+
+ return 0;
+ }
+
+ public int getFontMetricsInt(FontMetricsInt metrics) {
+ if (mMetrics != null) {
+ 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();
+ }
+
+ return mMetrics.getHeight();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Reimplemented to return Paint.FontMetrics instead of _Original_Paint.FontMetrics
+ */
+ public FontMetrics getFontMetrics() {
+ FontMetrics fm = new FontMetrics();
+ getFontMetrics(fm);
+ return fm;
+ }
+
+ /**
+ * Reimplemented to return Paint.FontMetricsInt instead of _Original_Paint.FontMetricsInt
+ */
+ public FontMetricsInt getFontMetricsInt() {
+ FontMetricsInt fm = new FontMetricsInt();
+ getFontMetricsInt(fm);
+ return fm;
+ }
+
+
+
+ @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) {
+ mTypeface = typeface;
+ } else {
+ mTypeface = Typeface.DEFAULT;
+ }
+
+ updateFontObject();
+
+ return typeface;
+ }
+
+ @Override
+ public int getColor() {
+ return mColor;
+ }
+
+ @Override
+ public void setColor(int color) {
+ mColor = color;
+ }
+
+
+ @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 />
+ * Pass null to clear any previous shader.
+ * As a convenience, the parameter passed is also returned.
+ *
+ * @param shader May be null. the new shader to be installed in the paint
+ * @return shader
+ */
+ @Override
+ public Shader setShader(Shader shader) {
+ return mShader = shader;
+ }
+
+ /**
+ * Set or clear the paint's colorfilter, returning the parameter.
+ *
+ * @param filter May be null. The new filter to be installed in the paint
+ * @return filter
+ */
+ @Override
+ public ColorFilter setColorFilter(ColorFilter filter) {
+ int filterNative = 0;
+ if (filter != null)
+ filterNative = filter.native_instance;
+ native_setColorFilter(mNativePaint, filterNative);
+ mColorFilter = filter;
+ return filter;
+ }
+
+ /**
+ * Set or clear the xfermode object.
+ * <p />
+ * Pass null to clear any previous xfermode.
+ * As a convenience, the parameter passed is also returned.
+ *
+ * @param xfermode May be null. The xfermode to be installed in the paint
+ * @return xfermode
+ */
+ @Override
+ public Xfermode setXfermode(Xfermode xfermode) {
+ return mXfermode = xfermode;
+ }
+
+ 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;
+ }
+
+ /**
+ * Return the paint's text size.
+ *
+ * @return the paint's text size.
+ */
+ @Override
+ public float getTextSize() {
+ return mTextSize;
+ }
+
+ /**
+ * Set the paint's text size. This value must be > 0
+ *
+ * @param textSize set the paint's text size.
+ */
+ @Override
+ public void setTextSize(float textSize) {
+ mTextSize = textSize;
+
+ updateFontObject();
+ }
+
+ /**
+ * Return the paint's horizontal scale factor for text. The default value
+ * is 1.0.
+ *
+ * @return the paint's scale factor in X for drawing/measuring text
+ */
+ @Override
+ public float getTextScaleX() {
+ return mScaleX;
+ }
+
+ /**
+ * Set the paint's horizontal scale factor for text. The default value
+ * is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will
+ * stretch the text narrower.
+ *
+ * @param scaleX set the paint's scale in X for drawing/measuring text.
+ */
+ @Override
+ public void setTextScaleX(float scaleX) {
+ mScaleX = scaleX;
+
+ updateFontObject();
+ }
+
+ /**
+ * Return the paint's horizontal skew factor for text. The default value
+ * is 0.
+ *
+ * @return the paint's skew factor in X for drawing text.
+ */
+ @Override
+ public float getTextSkewX() {
+ return mSkewX;
+ }
+
+ /**
+ * Set the paint's horizontal skew factor for text. The default value
+ * is 0. For approximating oblique text, use values around -0.25.
+ *
+ * @param skewX set the paint's skew factor in X for drawing text.
+ */
+ @Override
+ public void setTextSkewX(float skewX) {
+ mSkewX = skewX;
+
+ updateFontObject();
+ }
+
+ /**
+ * Return the distance above (negative) the baseline (ascent) based on the
+ * current typeface and text size.
+ *
+ * @return the distance above (negative) the baseline (ascent) based on the
+ * current typeface and text size.
+ */
+ @Override
+ public float ascent() {
+ if (mMetrics != null) {
+ // ascent stuff should be negatif, but awt returns them as positive.
+ return - mMetrics.getAscent();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Return the distance below (positive) the baseline (descent) based on the
+ * current typeface and text size.
+ *
+ * @return the distance below (positive) the baseline (descent) based on
+ * the current typeface and text size.
+ */
+ @Override
+ public float descent() {
+ if (mMetrics != null) {
+ return mMetrics.getDescent();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Return the width of the text.
+ *
+ * @param text The text to measure
+ * @param index The index of the first character to start measuring
+ * @param count THe number of characters to measure, beginning with start
+ * @return The width of the text
+ */
+ @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();
+ }
+
+ return 0;
+ }
+
+ /**
+ * Return the width of the text.
+ *
+ * @param text The text to measure
+ * @param start The index of the first character to start measuring
+ * @param end 1 beyond the index of the last character to measure
+ * @return The width of the text
+ */
+ @Override
+ public float measureText(String text, int start, int end) {
+ return measureText(text.toCharArray(), start, end - start);
+ }
+
+ /**
+ * Return the width of the text.
+ *
+ * @param text The text to measure
+ * @return The width of the text
+ */
+ @Override
+ 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
+ */
+ @Override
+ public float measureText(CharSequence text, int start, int end) {
+ if (text instanceof String) {
+ return measureText((String)text, start, end);
+ }
+ if (text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ return measureText(text.toString(), start, end);
+ }
+ if (text instanceof SpannableStringBuilder) {
+ return ((SpannableStringBuilder)text).measureText(start, end, this);
+ }
+
+ char[] buf = TemporaryBuffer.obtain(end - start);
+ TextUtils.getChars(text, start, end, buf, 0);
+ float result = measureText(buf, 0, end - start);
+ 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
+ * not null, return in it the actual width measured.
+ *
+ * @param text The text to measure
+ * @param index The offset into text to begin measuring at
+ * @param count The number of maximum number of entries to measure. If count
+ * is negative, then the characters before index are measured
+ * in reverse order. This allows for measuring the end of
+ * string.
+ * @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(count).
+ */
+ @Override
+ 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++) {
+ int start, end;
+ if (i < index) {
+ start = i;
+ end = index;
+ } else {
+ 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;
+ }
+
+ /**
+ * 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 measureForwards If true, measure forwards, starting at index.
+ * Otherwise, measure backwards, starting with the
+ * last character in the string.
+ * @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(count).
+ */
+ @Override
+ public int breakText(String text, boolean measureForwards,
+ float maxWidth, float[] measuredWidth) {
+ // NOTE: javadoc doesn't match. Just a guess.
+ return breakText(text,
+ 0 /* start */, text.length() /* end */,
+ measureForwards, maxWidth, measuredWidth);
+ }
+
+ /**
+ * Return the advance widths for the characters in the string.
+ *
+ * @param text The text to measure
+ * @param index The index of the first char to to measure
+ * @param count The number of chars starting with index to measure
+ * @param widths array to receive the advance widths of the characters.
+ * Must be at least a large as count.
+ * @return the actual number of widths returned.
+ */
+ @Override
+ public int getTextWidths(char[] text, int index, int count,
+ float[] widths) {
+ if (mMetrics != null) {
+ if ((index | count) < 0 || index + count > text.length
+ || count > widths.length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+
+ for (int i = 0; i < count; i++) {
+ widths[i] = mMetrics.charWidth(text[i + index]);
+ }
+
+ return count;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Return the advance widths for the characters in the string.
+ *
+ * @param text The text to measure
+ * @param start The index of the first char to to measure
+ * @param end The end of the text slice to measure
+ * @param widths array to receive the advance widths of the characters.
+ * Must be at least a large as the text.
+ * @return the number of unichars in the specified text.
+ */
+ @Override
+ public int getTextWidths(String text, int start, int end, float[] widths) {
+ if ((start | end | (end - start) | (text.length() - end)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ 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
+ */
+ @Override
+ public int getTextWidths(CharSequence text, int start, int end, float[] widths) {
+ if (text instanceof String) {
+ return getTextWidths((String)text, start, end, widths);
+ }
+ if (text instanceof SpannedString || text instanceof SpannableString) {
+ return getTextWidths(text.toString(), start, end, widths);
+ }
+ if (text instanceof SpannableStringBuilder) {
+ return ((SpannableStringBuilder)text).getTextWidths(start, end, widths, this);
+ }
+
+ char[] buf = TemporaryBuffer.obtain(end - start);
+ TextUtils.getChars(text, start, end, buf, 0);
+ int result = getTextWidths(buf, 0, end - start, widths);
+ TemporaryBuffer.recycle(buf);
+ return result;
+ }
+
+
+ /**
+ * Return the path (outline) for the specified text.
+ * Note: just like Canvas.drawText, this will respect the Align setting in
+ * the paint.
+ *
+ * @param text The text to retrieve the path from
+ * @param index The index of the first character in text
+ * @param count The number of characterss starting with index
+ * @param x The x coordinate of the text's origin
+ * @param y The y coordinate of the text's origin
+ * @param path The path to receive the data describing the text. Must
+ * be allocated by the caller.
+ */
+ @Override
+ public void getTextPath(char[] text, int index, int count,
+ 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");
+ }
+
+ /**
+ * Return the path (outline) for the specified text.
+ * Note: just like Canvas.drawText, this will respect the Align setting
+ * in the paint.
+ *
+ * @param text The text to retrieve the path from
+ * @param start The first character in the text
+ * @param end 1 past the last charcter in the text
+ * @param x The x coordinate of the text's origin
+ * @param y The y coordinate of the text's origin
+ * @param path The path to receive the data describing the text. Must
+ * be allocated by the caller.
+ */
+ @Override
+ public void getTextPath(String text, int start, int end,
+ float x, float y, Path path) {
+ 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).
+ *
+ * @param text String to measure and return its bounds
+ * @param start Index of the first char in the string to measure
+ * @param end 1 past the last char in the string measure
+ * @param bounds Returns the unioned bounds of all the text. Must be
+ * allocated by the caller.
+ */
+ @Override
+ public void getTextBounds(String text, int start, int end, Rect bounds) {
+ if ((start | end | (end - start) | (text.length() - end)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ 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).
+ *
+ * @param text Array of chars to measure and return their unioned bounds
+ * @param index Index of the first char in the array to measure
+ * @param count The number of chars, beginning at index, to measure
+ * @param bounds Returns the unioned bounds of all the text. Must be
+ * allocated by the caller.
+ */
+ @Override
+ public void getTextBounds(char[] text, int index, int count, Rect bounds) {
+ if (mFont != null) {
+ 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);
+ bounds.set(0, 0, (int)rect.getWidth(), (int)rect.getHeight());
+ }
+ }
+}