From a9f1dd021f8f6ee777bc4d27913bd40c42e753af Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Wed, 12 Aug 2009 15:00:10 -0700 Subject: Make and in string resources respect density. This unfortunately requires API changes because the existing text markup classes had no access to the screen density. TextPaint gains a "density" field so that TextView can pass the density along. AbsoluteSizeSpan gains a new flag to indicate that its argument is in dip instead of in physical pixels. LineHeightSpan gains an inner interface whose chooseHeight() method includes a TextPaint argument so it can get at the density. And when StringBlock creates the markup objects, it now uses the density-aware versions. Bug 1976971, Bug 2031746 --- core/java/android/content/res/StringBlock.java | 34 +++++++++++++++------- core/java/android/text/StaticLayout.java | 8 ++++- core/java/android/text/TextPaint.java | 2 ++ core/java/android/text/style/AbsoluteSizeSpan.java | 32 ++++++++++++++++++-- core/java/android/text/style/LineHeightSpan.java | 7 +++++ core/java/android/widget/TextView.java | 1 + 6 files changed, 70 insertions(+), 14 deletions(-) (limited to 'core') diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java index e684cb8..8fb82be 100644 --- a/core/java/android/content/res/StringBlock.java +++ b/core/java/android/content/res/StringBlock.java @@ -202,7 +202,7 @@ final class StringBlock { sub = subtag(tag, ";size="); if (sub != null) { int size = Integer.parseInt(sub); - buffer.setSpan(new AbsoluteSizeSpan(size), + buffer.setSpan(new AbsoluteSizeSpan(size, true), style[i+1], style[i+2]+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } @@ -310,7 +310,7 @@ final class StringBlock { * the ascent if possible, or the descent if shrinking the ascent further * will make the text unreadable. */ - private static class Height implements LineHeightSpan { + private static class Height implements LineHeightSpan.WithDensity { private int mSize; private static float sProportion = 0; @@ -321,9 +321,21 @@ final class StringBlock { public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int v, Paint.FontMetricsInt fm) { - if (fm.bottom - fm.top < mSize) { - fm.top = fm.bottom - mSize; - fm.ascent = fm.ascent - mSize; + // Should not get called, at least not by StaticLayout. + chooseHeight(text, start, end, spanstartv, v, fm, null); + } + + public void chooseHeight(CharSequence text, int start, int end, + int spanstartv, int v, + Paint.FontMetricsInt fm, TextPaint paint) { + int size = mSize; + if (paint != null) { + size *= paint.density; + } + + if (fm.bottom - fm.top < size) { + fm.top = fm.bottom - size; + fm.ascent = fm.ascent - size; } else { if (sProportion == 0) { /* @@ -343,27 +355,27 @@ final class StringBlock { int need = (int) Math.ceil(-fm.top * sProportion); - if (mSize - fm.descent >= need) { + if (size - fm.descent >= need) { /* * It is safe to shrink the ascent this much. */ - fm.top = fm.bottom - mSize; - fm.ascent = fm.descent - mSize; - } else if (mSize >= need) { + fm.top = fm.bottom - size; + fm.ascent = fm.descent - size; + } else if (size >= need) { /* * We can't show all the descent, but we can at least * show all the ascent. */ fm.top = fm.ascent = -need; - fm.bottom = fm.descent = fm.top + mSize; + fm.bottom = fm.descent = fm.top + size; } else { /* * Show as much of the ascent as we can, and no descent. */ - fm.top = fm.ascent = -mSize; + fm.top = fm.ascent = -size; fm.bottom = fm.descent = 0; } } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index c133cf2..f0a5ffd 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -968,7 +968,13 @@ extends Layout fm.bottom = bottom; for (int i = 0; i < chooseht.length; i++) { - chooseht[i].chooseHeight(text, start, end, choosehtv[i], v, fm); + if (chooseht[i] instanceof LineHeightSpan.WithDensity) { + ((LineHeightSpan.WithDensity) chooseht[i]). + chooseHeight(text, start, end, choosehtv[i], v, fm, paint); + + } else { + chooseht[i].chooseHeight(text, start, end, choosehtv[i], v, fm); + } } above = fm.ascent; diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java index f13820d..f9e7cac 100644 --- a/core/java/android/text/TextPaint.java +++ b/core/java/android/text/TextPaint.java @@ -27,6 +27,7 @@ public class TextPaint extends Paint { public int baselineShift; public int linkColor; public int[] drawableState; + public float density = 1.0f; public TextPaint() { super(); @@ -51,5 +52,6 @@ public class TextPaint extends Paint { baselineShift = tp.baselineShift; linkColor = tp.linkColor; drawableState = tp.drawableState; + density = tp.density; } } diff --git a/core/java/android/text/style/AbsoluteSizeSpan.java b/core/java/android/text/style/AbsoluteSizeSpan.java index 484f8ce..1214040 100644 --- a/core/java/android/text/style/AbsoluteSizeSpan.java +++ b/core/java/android/text/style/AbsoluteSizeSpan.java @@ -24,13 +24,28 @@ import android.text.TextUtils; public class AbsoluteSizeSpan extends MetricAffectingSpan implements ParcelableSpan { private final int mSize; + private boolean mDip; + /** + * Set the text size to size physical pixels. + */ public AbsoluteSizeSpan(int size) { mSize = size; } + /** + * Set the text size to size physical pixels, + * or to size device-independent pixels if + * dip is true. + */ + public AbsoluteSizeSpan(int size, boolean dip) { + mSize = size; + mDip = dip; + } + public AbsoluteSizeSpan(Parcel src) { mSize = src.readInt(); + mDip = src.readInt() != 0; } public int getSpanTypeId() { @@ -43,19 +58,32 @@ public class AbsoluteSizeSpan extends MetricAffectingSpan implements ParcelableS public void writeToParcel(Parcel dest, int flags) { dest.writeInt(mSize); + dest.writeInt(mDip ? 1 : 0); } public int getSize() { return mSize; } + public boolean getDip() { + return mDip; + } + @Override public void updateDrawState(TextPaint ds) { - ds.setTextSize(mSize); + if (mDip) { + ds.setTextSize(mSize * ds.density); + } else { + ds.setTextSize(mSize); + } } @Override public void updateMeasureState(TextPaint ds) { - ds.setTextSize(mSize); + if (mDip) { + ds.setTextSize(mSize * ds.density); + } else { + ds.setTextSize(mSize); + } } } diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java index c0ef97c..44a1706 100644 --- a/core/java/android/text/style/LineHeightSpan.java +++ b/core/java/android/text/style/LineHeightSpan.java @@ -19,6 +19,7 @@ package android.text.style; import android.graphics.Paint; import android.graphics.Canvas; import android.text.Layout; +import android.text.TextPaint; public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan @@ -26,4 +27,10 @@ extends ParagraphStyle, WrapTogetherSpan public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int v, Paint.FontMetricsInt fm); + + public interface WithDensity extends LineHeightSpan { + public void chooseHeight(CharSequence text, int start, int end, + int spanstartv, int v, + Paint.FontMetricsInt fm, TextPaint paint); + } } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 591f9bb..e0a268e 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -327,6 +327,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mText = ""; mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + mTextPaint.density = getResources().getDisplayMetrics().density; // If we get the paint from the skin, we should set it to left, since // the layout always wants it to be left. // mTextPaint.setTextAlign(Paint.Align.LEFT); -- cgit v1.1