Bold StyleSpan further for auto-bold

StyleSpan with Typeface.BOLD will only bold if the text doesn't already
have a BOLD style. But auto-bolded text needs to be further bolded.
If the Typeface style is BOLD, bold more for auto-bold.
(The fake bold works for Typefaces with weight < 700)

Test: manual - settings page, example StyleSpans,
atest StyleSpanTest TextViewTests
Bug: 175177807

Change-Id: Iec7db7eadd18ed6a2efc6ee39b49c1d6cb15d870
This commit is contained in:
sallyyuen
2021-12-06 10:02:27 -08:00
parent a9b80a68f3
commit 0a674a8a44
4 changed files with 65 additions and 8 deletions

View File

@@ -45668,8 +45668,10 @@ package android.text.style {
public class StyleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan { public class StyleSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
ctor public StyleSpan(int); ctor public StyleSpan(int);
ctor public StyleSpan(int, int);
ctor public StyleSpan(@NonNull android.os.Parcel); ctor public StyleSpan(@NonNull android.os.Parcel);
method public int describeContents(); method public int describeContents();
method public int getFontWeightAdjustment();
method public int getSpanTypeId(); method public int getSpanTypeId();
method public int getStyle(); method public int getStyle();
method public void updateDrawState(android.text.TextPaint); method public void updateDrawState(android.text.TextPaint);

View File

@@ -16,8 +16,9 @@
package android.content.res; package android.content.res;
import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.app.ActivityThread;
import android.app.Application;
import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
@@ -238,7 +239,10 @@ public final class StringBlock implements Closeable {
if (type == ids.boldId) { if (type == ids.boldId) {
buffer.setSpan(new StyleSpan(Typeface.BOLD), Application application = ActivityThread.currentApplication();
int fontWeightAdjustment =
application.getResources().getConfiguration().fontWeightAdjustment;
buffer.setSpan(new StyleSpan(Typeface.BOLD, fontWeightAdjustment),
style[i+1], style[i+2]+1, style[i+1], style[i+2]+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else if (type == ids.italicId) { } else if (type == ids.italicId) {

View File

@@ -858,9 +858,17 @@ class HtmlToSpannedConverter implements ContentHandler {
} else if (tag.equalsIgnoreCase("span")) { } else if (tag.equalsIgnoreCase("span")) {
endCssStyle(mSpannableStringBuilder); endCssStyle(mSpannableStringBuilder);
} else if (tag.equalsIgnoreCase("strong")) { } else if (tag.equalsIgnoreCase("strong")) {
end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD)); Application application = ActivityThread.currentApplication();
int fontWeightAdjustment =
application.getResources().getConfiguration().fontWeightAdjustment;
end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD,
fontWeightAdjustment));
} else if (tag.equalsIgnoreCase("b")) { } else if (tag.equalsIgnoreCase("b")) {
end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD)); Application application = ActivityThread.currentApplication();
int fontWeightAdjustment =
application.getResources().getConfiguration().fontWeightAdjustment;
end(mSpannableStringBuilder, Bold.class, new StyleSpan(Typeface.BOLD,
fontWeightAdjustment));
} else if (tag.equalsIgnoreCase("em")) { } else if (tag.equalsIgnoreCase("em")) {
end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC)); end(mSpannableStringBuilder, Italic.class, new StyleSpan(Typeface.ITALIC));
} else if (tag.equalsIgnoreCase("cite")) { } else if (tag.equalsIgnoreCase("cite")) {
@@ -1028,8 +1036,11 @@ class HtmlToSpannedConverter implements ContentHandler {
// Their ranges should not include the newlines at the end // Their ranges should not include the newlines at the end
Heading h = getLast(text, Heading.class); Heading h = getLast(text, Heading.class);
if (h != null) { if (h != null) {
Application application = ActivityThread.currentApplication();
int fontWeightAdjustment =
application.getResources().getConfiguration().fontWeightAdjustment;
setSpanFromMark(text, h, new RelativeSizeSpan(HEADING_SIZES[h.mLevel]), setSpanFromMark(text, h, new RelativeSizeSpan(HEADING_SIZES[h.mLevel]),
new StyleSpan(Typeface.BOLD)); new StyleSpan(Typeface.BOLD, fontWeightAdjustment));
} }
endBlockElement(text); endBlockElement(text);

View File

@@ -17,8 +17,10 @@
package android.text.style; package android.text.style;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.content.res.Configuration;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.fonts.FontStyle;
import android.os.Parcel; import android.os.Parcel;
import android.text.ParcelableSpan; import android.text.ParcelableSpan;
import android.text.TextPaint; import android.text.TextPaint;
@@ -45,6 +47,7 @@ import android.text.TextUtils;
public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan { public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
private final int mStyle; private final int mStyle;
private final int mFontWeightAdjustment;
/** /**
* Creates a {@link StyleSpan} from a style. * Creates a {@link StyleSpan} from a style.
@@ -54,7 +57,23 @@ public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
* in {@link Typeface}. * in {@link Typeface}.
*/ */
public StyleSpan(int style) { public StyleSpan(int style) {
this(style, Configuration.FONT_WEIGHT_ADJUSTMENT_UNDEFINED);
}
/**
* Creates a {@link StyleSpan} from a style and font weight adjustment.
*
* @param style An integer constant describing the style for this span. Examples
* include bold, italic, and normal. Values are constants defined
* in {@link Typeface}.
* @param fontWeightAdjustment An integer describing the adjustment to be made to the font
* weight.
* @see Configuration#fontWeightAdjustment This is the adjustment in text font weight
* that is used to reflect the current user's preference for increasing font weight.
*/
public StyleSpan(@Typeface.Style int style, int fontWeightAdjustment) {
mStyle = style; mStyle = style;
mFontWeightAdjustment = fontWeightAdjustment;
} }
/** /**
@@ -64,6 +83,7 @@ public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
*/ */
public StyleSpan(@NonNull Parcel src) { public StyleSpan(@NonNull Parcel src) {
mStyle = src.readInt(); mStyle = src.readInt();
mFontWeightAdjustment = src.readInt();
} }
@Override @Override
@@ -91,6 +111,7 @@ public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
@Override @Override
public void writeToParcelInternal(@NonNull Parcel dest, int flags) { public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
dest.writeInt(mStyle); dest.writeInt(mStyle);
dest.writeInt(mFontWeightAdjustment);
} }
/** /**
@@ -100,17 +121,24 @@ public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
return mStyle; return mStyle;
} }
/**
* Returns the font weight adjustment specified by this span.
*/
public int getFontWeightAdjustment() {
return mFontWeightAdjustment;
}
@Override @Override
public void updateDrawState(TextPaint ds) { public void updateDrawState(TextPaint ds) {
apply(ds, mStyle); apply(ds, mStyle, mFontWeightAdjustment);
} }
@Override @Override
public void updateMeasureState(TextPaint paint) { public void updateMeasureState(TextPaint paint) {
apply(paint, mStyle); apply(paint, mStyle, mFontWeightAdjustment);
} }
private static void apply(Paint paint, int style) { private static void apply(Paint paint, int style, int fontWeightAdjustment) {
int oldStyle; int oldStyle;
Typeface old = paint.getTypeface(); Typeface old = paint.getTypeface();
@@ -129,6 +157,18 @@ public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {
tf = Typeface.create(old, want); tf = Typeface.create(old, want);
} }
// Base typeface may already be bolded by auto bold. Bold further.
if ((style & Typeface.BOLD) != 0) {
if (fontWeightAdjustment != 0
&& fontWeightAdjustment != Configuration.FONT_WEIGHT_ADJUSTMENT_UNDEFINED) {
int newWeight = Math.min(
Math.max(tf.getWeight() + fontWeightAdjustment, FontStyle.FONT_WEIGHT_MIN),
FontStyle.FONT_WEIGHT_MAX);
boolean italic = (want & Typeface.ITALIC) != 0;
tf = Typeface.create(tf, newWeight, italic);
}
}
int fake = want & ~tf.getStyle(); int fake = want & ~tf.getStyle();
if ((fake & Typeface.BOLD) != 0) { if ((fake & Typeface.BOLD) != 0) {