blob: 3a3646b99bdfc80261c517398aa2dbcbfccebc83 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.text.style;
18
19import android.content.Context;
20import android.content.res.ColorStateList;
21import android.content.res.TypedArray;
Seigo Nonakac49ee3b2017-07-13 13:34:00 -070022import android.graphics.LeakyTypefaceStorage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.graphics.Typeface;
24import android.os.Parcel;
25import android.text.ParcelableSpan;
26import android.text.TextPaint;
27import android.text.TextUtils;
28
29/**
30 * Sets the text color, size, style, and typeface to match a TextAppearance
31 * resource.
32 */
33public class TextAppearanceSpan extends MetricAffectingSpan implements ParcelableSpan {
Seigo Nonakac49ee3b2017-07-13 13:34:00 -070034 private final String mFamilyName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035 private final int mStyle;
36 private final int mTextSize;
37 private final ColorStateList mTextColor;
38 private final ColorStateList mTextColorLink;
Seigo Nonakac49ee3b2017-07-13 13:34:00 -070039 private final Typeface mTypeface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040
41 /**
42 * Uses the specified TextAppearance resource to determine the
43 * text appearance. The <code>appearance</code> should be, for example,
44 * <code>android.R.style.TextAppearance_Small</code>.
45 */
46 public TextAppearanceSpan(Context context, int appearance) {
47 this(context, appearance, -1);
48 }
49
50 /**
51 * Uses the specified TextAppearance resource to determine the
52 * text appearance, and the specified text color resource
53 * to determine the color. The <code>appearance</code> should be,
54 * for example, <code>android.R.style.TextAppearance_Small</code>,
55 * and the <code>colorList</code> should be, for example,
Gilles Debunne0f9ae272011-04-27 14:25:54 -070056 * <code>android.R.styleable.Theme_textColorPrimary</code>.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057 */
Gilles Debunne0f9ae272011-04-27 14:25:54 -070058 public TextAppearanceSpan(Context context, int appearance, int colorList) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059 ColorStateList textColor;
Seigo Nonakac49ee3b2017-07-13 13:34:00 -070060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 TypedArray a =
62 context.obtainStyledAttributes(appearance,
63 com.android.internal.R.styleable.TextAppearance);
64
65 textColor = a.getColorStateList(com.android.internal.R.styleable.
66 TextAppearance_textColor);
67 mTextColorLink = a.getColorStateList(com.android.internal.R.styleable.
68 TextAppearance_textColorLink);
69 mTextSize = a.getDimensionPixelSize(com.android.internal.R.styleable.
70 TextAppearance_textSize, -1);
71
72 mStyle = a.getInt(com.android.internal.R.styleable.TextAppearance_textStyle, 0);
Seigo Nonakac49ee3b2017-07-13 13:34:00 -070073 mTypeface = a.getFont(com.android.internal.R.styleable.TextAppearance_fontFamily);
74 if (mTypeface != null) {
75 mFamilyName = null;
Raph Leviend570e892012-05-09 11:45:34 -070076 } else {
Seigo Nonakac49ee3b2017-07-13 13:34:00 -070077 String family = a.getString(com.android.internal.R.styleable.TextAppearance_fontFamily);
78 if (family != null) {
79 mFamilyName = family;
80 } else {
81 int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082
Seigo Nonakac49ee3b2017-07-13 13:34:00 -070083 switch (tf) {
84 case 1:
85 mFamilyName = "sans";
86 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087
Seigo Nonakac49ee3b2017-07-13 13:34:00 -070088 case 2:
89 mFamilyName = "serif";
90 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091
Seigo Nonakac49ee3b2017-07-13 13:34:00 -070092 case 3:
93 mFamilyName = "monospace";
94 break;
Raph Leviend570e892012-05-09 11:45:34 -070095
Seigo Nonakac49ee3b2017-07-13 13:34:00 -070096 default:
97 mFamilyName = null;
98 break;
99 }
Raph Leviend570e892012-05-09 11:45:34 -0700100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 }
102
103 a.recycle();
104
105 if (colorList >= 0) {
106 a = context.obtainStyledAttributes(com.android.internal.R.style.Theme,
107 com.android.internal.R.styleable.Theme);
108
109 textColor = a.getColorStateList(colorList);
110 a.recycle();
111 }
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 mTextColor = textColor;
114 }
115
116 /**
117 * Makes text be drawn with the specified typeface, size, style,
118 * and colors.
119 */
120 public TextAppearanceSpan(String family, int style, int size,
121 ColorStateList color, ColorStateList linkColor) {
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700122 mFamilyName = family;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800123 mStyle = style;
124 mTextSize = size;
125 mTextColor = color;
126 mTextColorLink = linkColor;
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700127 mTypeface = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 }
129
130 public TextAppearanceSpan(Parcel src) {
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700131 mFamilyName = src.readString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 mStyle = src.readInt();
133 mTextSize = src.readInt();
134 if (src.readInt() != 0) {
135 mTextColor = ColorStateList.CREATOR.createFromParcel(src);
136 } else {
137 mTextColor = null;
138 }
139 if (src.readInt() != 0) {
140 mTextColorLink = ColorStateList.CREATOR.createFromParcel(src);
141 } else {
142 mTextColorLink = null;
143 }
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700144 mTypeface = LeakyTypefaceStorage.readTypefaceFromParcel(src);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 }
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 public int getSpanTypeId() {
Alan Viverettea70d4a92015-06-02 16:11:00 -0700148 return getSpanTypeIdInternal();
149 }
150
151 /** @hide */
152 public int getSpanTypeIdInternal() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 return TextUtils.TEXT_APPEARANCE_SPAN;
154 }
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 public int describeContents() {
157 return 0;
158 }
159
160 public void writeToParcel(Parcel dest, int flags) {
Alan Viverettea70d4a92015-06-02 16:11:00 -0700161 writeToParcelInternal(dest, flags);
162 }
163
164 /** @hide */
165 public void writeToParcelInternal(Parcel dest, int flags) {
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700166 dest.writeString(mFamilyName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167 dest.writeInt(mStyle);
168 dest.writeInt(mTextSize);
169 if (mTextColor != null) {
170 dest.writeInt(1);
171 mTextColor.writeToParcel(dest, flags);
172 } else {
173 dest.writeInt(0);
174 }
175 if (mTextColorLink != null) {
176 dest.writeInt(1);
177 mTextColorLink.writeToParcel(dest, flags);
178 } else {
179 dest.writeInt(0);
180 }
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700181 LeakyTypefaceStorage.writeTypefaceToParcel(mTypeface, dest);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 }
183
184 /**
185 * Returns the typeface family specified by this span, or <code>null</code>
186 * if it does not specify one.
187 */
188 public String getFamily() {
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700189 return mFamilyName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 }
191
192 /**
193 * Returns the text color specified by this span, or <code>null</code>
194 * if it does not specify one.
195 */
196 public ColorStateList getTextColor() {
197 return mTextColor;
198 }
199
200 /**
201 * Returns the link color specified by this span, or <code>null</code>
202 * if it does not specify one.
203 */
204 public ColorStateList getLinkTextColor() {
205 return mTextColorLink;
206 }
207
208 /**
209 * Returns the text size specified by this span, or <code>-1</code>
210 * if it does not specify one.
211 */
212 public int getTextSize() {
213 return mTextSize;
214 }
215
216 /**
217 * Returns the text style specified by this span, or <code>0</code>
218 * if it does not specify one.
219 */
220 public int getTextStyle() {
221 return mStyle;
222 }
223
224 @Override
225 public void updateDrawState(TextPaint ds) {
226 updateMeasureState(ds);
227
228 if (mTextColor != null) {
229 ds.setColor(mTextColor.getColorForState(ds.drawableState, 0));
230 }
231
232 if (mTextColorLink != null) {
Fabrice Di Megliob8503eb2011-08-09 18:18:27 -0700233 ds.linkColor = mTextColorLink.getColorForState(ds.drawableState, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 }
235 }
236
237 @Override
238 public void updateMeasureState(TextPaint ds) {
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700239 final Typeface styledTypeface;
240 int style = 0;
241
242 if (mTypeface != null) {
243 style = mStyle;
244 styledTypeface = Typeface.create(mTypeface, style);
245 } else if (mFamilyName != null || mStyle != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 Typeface tf = ds.getTypeface();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247
248 if (tf != null) {
249 style = tf.getStyle();
250 }
251
252 style |= mStyle;
253
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700254 if (mFamilyName != null) {
255 styledTypeface = Typeface.create(mFamilyName, style);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 } else if (tf == null) {
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700257 styledTypeface = Typeface.defaultFromStyle(style);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 } else {
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700259 styledTypeface = Typeface.create(tf, style);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 }
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700261 } else {
262 styledTypeface = null;
263 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700265 if (styledTypeface != null) {
266 int fake = style & ~styledTypeface.getStyle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
268 if ((fake & Typeface.BOLD) != 0) {
269 ds.setFakeBoldText(true);
270 }
271
272 if ((fake & Typeface.ITALIC) != 0) {
273 ds.setTextSkewX(-0.25f);
274 }
275
Seigo Nonakac49ee3b2017-07-13 13:34:00 -0700276 ds.setTypeface(styledTypeface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 }
278
279 if (mTextSize > 0) {
280 ds.setTextSize(mTextSize);
281 }
282 }
283}