Loading core/java/android/text/style/TextAppearanceSpan.java +53 −34 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.text.style; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.LeakyTypefaceStorage; import android.graphics.Typeface; import android.os.Parcel; import android.text.ParcelableSpan; Loading @@ -30,11 +31,12 @@ import android.text.TextUtils; * resource. */ public class TextAppearanceSpan extends MetricAffectingSpan implements ParcelableSpan { private final String mTypeface; private final String mFamilyName; private final int mStyle; private final int mTextSize; private final ColorStateList mTextColor; private final ColorStateList mTextColorLink; private final Typeface mTypeface; /** * Uses the specified TextAppearance resource to determine the Loading Loading @@ -68,30 +70,35 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl TextAppearance_textSize, -1); mStyle = a.getInt(com.android.internal.R.styleable.TextAppearance_textStyle, 0); mTypeface = a.getFont(com.android.internal.R.styleable.TextAppearance_fontFamily); if (mTypeface != null) { mFamilyName = null; } else { String family = a.getString(com.android.internal.R.styleable.TextAppearance_fontFamily); if (family != null) { mTypeface = family; mFamilyName = family; } else { int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0); switch (tf) { case 1: mTypeface = "sans"; mFamilyName = "sans"; break; case 2: mTypeface = "serif"; mFamilyName = "serif"; break; case 3: mTypeface = "monospace"; mFamilyName = "monospace"; break; default: mTypeface = null; mFamilyName = null; break; } } } a.recycle(); Loading @@ -112,15 +119,16 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl */ public TextAppearanceSpan(String family, int style, int size, ColorStateList color, ColorStateList linkColor) { mTypeface = family; mFamilyName = family; mStyle = style; mTextSize = size; mTextColor = color; mTextColorLink = linkColor; mTypeface = null; } public TextAppearanceSpan(Parcel src) { mTypeface = src.readString(); mFamilyName = src.readString(); mStyle = src.readInt(); mTextSize = src.readInt(); if (src.readInt() != 0) { Loading @@ -133,6 +141,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl } else { mTextColorLink = null; } mTypeface = LeakyTypefaceStorage.readTypefaceFromParcel(src); } public int getSpanTypeId() { Loading @@ -154,7 +163,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl /** @hide */ public void writeToParcelInternal(Parcel dest, int flags) { dest.writeString(mTypeface); dest.writeString(mFamilyName); dest.writeInt(mStyle); dest.writeInt(mTextSize); if (mTextColor != null) { Loading @@ -169,6 +178,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl } else { dest.writeInt(0); } LeakyTypefaceStorage.writeTypefaceToParcel(mTypeface, dest); } /** Loading @@ -176,7 +186,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl * if it does not specify one. */ public String getFamily() { return mTypeface; return mFamilyName; } /** Loading Loading @@ -226,25 +236,34 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl @Override public void updateMeasureState(TextPaint ds) { if (mTypeface != null || mStyle != 0) { Typeface tf = ds.getTypeface(); final Typeface styledTypeface; int style = 0; if (mTypeface != null) { style = mStyle; styledTypeface = Typeface.create(mTypeface, style); } else if (mFamilyName != null || mStyle != 0) { Typeface tf = ds.getTypeface(); if (tf != null) { style = tf.getStyle(); } style |= mStyle; if (mTypeface != null) { tf = Typeface.create(mTypeface, style); if (mFamilyName != null) { styledTypeface = Typeface.create(mFamilyName, style); } else if (tf == null) { tf = Typeface.defaultFromStyle(style); styledTypeface = Typeface.defaultFromStyle(style); } else { styledTypeface = Typeface.create(tf, style); } } else { tf = Typeface.create(tf, style); styledTypeface = null; } int fake = style & ~tf.getStyle(); if (styledTypeface != null) { int fake = style & ~styledTypeface.getStyle(); if ((fake & Typeface.BOLD) != 0) { ds.setFakeBoldText(true); Loading @@ -254,7 +273,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl ds.setTextSkewX(-0.25f); } ds.setTypeface(tf); ds.setTypeface(styledTypeface); } if (mTextSize > 0) { Loading graphics/java/android/graphics/LeakyTypefaceStorage.java 0 → 100644 +86 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.internal.annotations.GuardedBy; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Process; import android.util.ArrayMap; import java.util.ArrayList; /** * This class is used for Parceling Typeface object. * Note: Typeface object can not be passed over the process boundary. * * @hide */ public class LeakyTypefaceStorage { private static final Object sLock = new Object(); @GuardedBy("sLock") private static final ArrayList<Typeface> sStorage = new ArrayList<>(); @GuardedBy("sLock") private static final ArrayMap<Typeface, Integer> sTypefaceMap = new ArrayMap<>(); /** * Write typeface to parcel. * * You can't transfer Typeface to a different process. {@link readTypefaceFromParcel} will * return {@code null} if the {@link readTypefaceFromParcel} is called in a different process. * * @param typeface A {@link Typeface} to be written. * @param parcel A {@link Parcel} object. */ public static void writeTypefaceToParcel(@Nullable Typeface typeface, @NonNull Parcel parcel) { parcel.writeInt(Process.myPid()); synchronized (sLock) { final int id; final Integer i = sTypefaceMap.get(typeface); if (i != null) { id = i.intValue(); } else { id = sStorage.size(); sStorage.add(typeface); sTypefaceMap.put(typeface, id); } parcel.writeInt(id); } } /** * Read typeface from parcel. * * If the {@link Typeface} was created in another process, this method returns null. * * @param parcel A {@link Parcel} object * @return A {@link Typeface} object. */ public static @Nullable Typeface readTypefaceFromParcel(@NonNull Parcel parcel) { final int pid = parcel.readInt(); final int typefaceId = parcel.readInt(); if (pid != Process.myPid()) { return null; // The Typeface was created and written in another process. } synchronized (sLock) { return sStorage.get(typefaceId); } } } Loading
core/java/android/text/style/TextAppearanceSpan.java +53 −34 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.text.style; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.LeakyTypefaceStorage; import android.graphics.Typeface; import android.os.Parcel; import android.text.ParcelableSpan; Loading @@ -30,11 +31,12 @@ import android.text.TextUtils; * resource. */ public class TextAppearanceSpan extends MetricAffectingSpan implements ParcelableSpan { private final String mTypeface; private final String mFamilyName; private final int mStyle; private final int mTextSize; private final ColorStateList mTextColor; private final ColorStateList mTextColorLink; private final Typeface mTypeface; /** * Uses the specified TextAppearance resource to determine the Loading Loading @@ -68,30 +70,35 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl TextAppearance_textSize, -1); mStyle = a.getInt(com.android.internal.R.styleable.TextAppearance_textStyle, 0); mTypeface = a.getFont(com.android.internal.R.styleable.TextAppearance_fontFamily); if (mTypeface != null) { mFamilyName = null; } else { String family = a.getString(com.android.internal.R.styleable.TextAppearance_fontFamily); if (family != null) { mTypeface = family; mFamilyName = family; } else { int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0); switch (tf) { case 1: mTypeface = "sans"; mFamilyName = "sans"; break; case 2: mTypeface = "serif"; mFamilyName = "serif"; break; case 3: mTypeface = "monospace"; mFamilyName = "monospace"; break; default: mTypeface = null; mFamilyName = null; break; } } } a.recycle(); Loading @@ -112,15 +119,16 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl */ public TextAppearanceSpan(String family, int style, int size, ColorStateList color, ColorStateList linkColor) { mTypeface = family; mFamilyName = family; mStyle = style; mTextSize = size; mTextColor = color; mTextColorLink = linkColor; mTypeface = null; } public TextAppearanceSpan(Parcel src) { mTypeface = src.readString(); mFamilyName = src.readString(); mStyle = src.readInt(); mTextSize = src.readInt(); if (src.readInt() != 0) { Loading @@ -133,6 +141,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl } else { mTextColorLink = null; } mTypeface = LeakyTypefaceStorage.readTypefaceFromParcel(src); } public int getSpanTypeId() { Loading @@ -154,7 +163,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl /** @hide */ public void writeToParcelInternal(Parcel dest, int flags) { dest.writeString(mTypeface); dest.writeString(mFamilyName); dest.writeInt(mStyle); dest.writeInt(mTextSize); if (mTextColor != null) { Loading @@ -169,6 +178,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl } else { dest.writeInt(0); } LeakyTypefaceStorage.writeTypefaceToParcel(mTypeface, dest); } /** Loading @@ -176,7 +186,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl * if it does not specify one. */ public String getFamily() { return mTypeface; return mFamilyName; } /** Loading Loading @@ -226,25 +236,34 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl @Override public void updateMeasureState(TextPaint ds) { if (mTypeface != null || mStyle != 0) { Typeface tf = ds.getTypeface(); final Typeface styledTypeface; int style = 0; if (mTypeface != null) { style = mStyle; styledTypeface = Typeface.create(mTypeface, style); } else if (mFamilyName != null || mStyle != 0) { Typeface tf = ds.getTypeface(); if (tf != null) { style = tf.getStyle(); } style |= mStyle; if (mTypeface != null) { tf = Typeface.create(mTypeface, style); if (mFamilyName != null) { styledTypeface = Typeface.create(mFamilyName, style); } else if (tf == null) { tf = Typeface.defaultFromStyle(style); styledTypeface = Typeface.defaultFromStyle(style); } else { styledTypeface = Typeface.create(tf, style); } } else { tf = Typeface.create(tf, style); styledTypeface = null; } int fake = style & ~tf.getStyle(); if (styledTypeface != null) { int fake = style & ~styledTypeface.getStyle(); if ((fake & Typeface.BOLD) != 0) { ds.setFakeBoldText(true); Loading @@ -254,7 +273,7 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl ds.setTextSkewX(-0.25f); } ds.setTypeface(tf); ds.setTypeface(styledTypeface); } if (mTextSize > 0) { Loading
graphics/java/android/graphics/LeakyTypefaceStorage.java 0 → 100644 +86 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.internal.annotations.GuardedBy; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Process; import android.util.ArrayMap; import java.util.ArrayList; /** * This class is used for Parceling Typeface object. * Note: Typeface object can not be passed over the process boundary. * * @hide */ public class LeakyTypefaceStorage { private static final Object sLock = new Object(); @GuardedBy("sLock") private static final ArrayList<Typeface> sStorage = new ArrayList<>(); @GuardedBy("sLock") private static final ArrayMap<Typeface, Integer> sTypefaceMap = new ArrayMap<>(); /** * Write typeface to parcel. * * You can't transfer Typeface to a different process. {@link readTypefaceFromParcel} will * return {@code null} if the {@link readTypefaceFromParcel} is called in a different process. * * @param typeface A {@link Typeface} to be written. * @param parcel A {@link Parcel} object. */ public static void writeTypefaceToParcel(@Nullable Typeface typeface, @NonNull Parcel parcel) { parcel.writeInt(Process.myPid()); synchronized (sLock) { final int id; final Integer i = sTypefaceMap.get(typeface); if (i != null) { id = i.intValue(); } else { id = sStorage.size(); sStorage.add(typeface); sTypefaceMap.put(typeface, id); } parcel.writeInt(id); } } /** * Read typeface from parcel. * * If the {@link Typeface} was created in another process, this method returns null. * * @param parcel A {@link Parcel} object * @return A {@link Typeface} object. */ public static @Nullable Typeface readTypefaceFromParcel(@NonNull Parcel parcel) { final int pid = parcel.readInt(); final int typefaceId = parcel.readInt(); if (pid != Process.myPid()) { return null; // The Typeface was created and written in another process. } synchronized (sLock) { return sStorage.get(typefaceId); } } }