1 /* 2 * Copyright (C) 2006 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 17 package android.text.style; 18 19 import android.annotation.NonNull; 20 import android.graphics.Paint; 21 import android.graphics.Typeface; 22 import android.os.Parcel; 23 import android.text.ParcelableSpan; 24 import android.text.TextPaint; 25 import android.text.TextUtils; 26 27 /** 28 * Span that allows setting the style of the text it's attached to. 29 * Possible styles are: {@link Typeface#NORMAL}, {@link Typeface#BOLD}, {@link Typeface#ITALIC} and 30 * {@link Typeface#BOLD_ITALIC}. 31 * <p> 32 * Note that styles are cumulative -- if both bold and italic are set in 33 * separate spans, or if the base style is bold and a span calls for italic, 34 * you get bold italic. You can't turn off a style from the base style. 35 * <p> 36 * For example, the <code>StyleSpan</code> can be used like this: 37 * <pre> 38 * SpannableString string = new SpannableString("Bold and italic text"); 39 * string.setSpan(new StyleSpan(Typeface.BOLD), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 40 * string.setSpan(new StyleSpan(Typeface.ITALIC), 9, 15, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 41 * </pre> 42 * <img src="{@docRoot}reference/android/images/text/style/stylespan.png" /> 43 * <figcaption>Text styled bold and italic with the <code>StyleSpan</code>.</figcaption> 44 */ 45 public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan { 46 47 private final int mStyle; 48 49 /** 50 * Creates a {@link StyleSpan} from a style. 51 * 52 * @param style An integer constant describing the style for this span. Examples 53 * include bold, italic, and normal. Values are constants defined 54 * in {@link Typeface}. 55 */ StyleSpan(int style)56 public StyleSpan(int style) { 57 mStyle = style; 58 } 59 60 /** 61 * Creates a {@link StyleSpan} from a parcel. 62 * 63 * @param src the parcel 64 */ StyleSpan(@onNull Parcel src)65 public StyleSpan(@NonNull Parcel src) { 66 mStyle = src.readInt(); 67 } 68 69 @Override getSpanTypeId()70 public int getSpanTypeId() { 71 return getSpanTypeIdInternal(); 72 } 73 74 /** @hide */ 75 @Override getSpanTypeIdInternal()76 public int getSpanTypeIdInternal() { 77 return TextUtils.STYLE_SPAN; 78 } 79 80 @Override describeContents()81 public int describeContents() { 82 return 0; 83 } 84 85 @Override writeToParcel(Parcel dest, int flags)86 public void writeToParcel(Parcel dest, int flags) { 87 writeToParcelInternal(dest, flags); 88 } 89 90 /** @hide */ 91 @Override writeToParcelInternal(@onNull Parcel dest, int flags)92 public void writeToParcelInternal(@NonNull Parcel dest, int flags) { 93 dest.writeInt(mStyle); 94 } 95 96 /** 97 * Returns the style constant defined in {@link Typeface}. 98 */ getStyle()99 public int getStyle() { 100 return mStyle; 101 } 102 103 @Override updateDrawState(TextPaint ds)104 public void updateDrawState(TextPaint ds) { 105 apply(ds, mStyle); 106 } 107 108 @Override updateMeasureState(TextPaint paint)109 public void updateMeasureState(TextPaint paint) { 110 apply(paint, mStyle); 111 } 112 apply(Paint paint, int style)113 private static void apply(Paint paint, int style) { 114 int oldStyle; 115 116 Typeface old = paint.getTypeface(); 117 if (old == null) { 118 oldStyle = 0; 119 } else { 120 oldStyle = old.getStyle(); 121 } 122 123 int want = oldStyle | style; 124 125 Typeface tf; 126 if (old == null) { 127 tf = Typeface.defaultFromStyle(want); 128 } else { 129 tf = Typeface.create(old, want); 130 } 131 132 int fake = want & ~tf.getStyle(); 133 134 if ((fake & Typeface.BOLD) != 0) { 135 paint.setFakeBoldText(true); 136 } 137 138 if ((fake & Typeface.ITALIC) != 0) { 139 paint.setTextSkewX(-0.25f); 140 } 141 142 paint.setTypeface(tf); 143 } 144 } 145