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.IntRange; 20 import android.annotation.NonNull; 21 import android.annotation.Px; 22 import android.graphics.Paint; 23 import android.os.Parcel; 24 import android.text.ParcelableSpan; 25 import android.text.TextPaint; 26 import android.text.TextUtils; 27 28 import com.android.internal.util.Preconditions; 29 30 /** 31 * The classes that affect the line height of paragraph should implement this interface. 32 */ 33 @android.ravenwood.annotation.RavenwoodKeepWholeClass 34 public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan { 35 /** 36 * Classes that implement this should define how the height is being calculated. 37 * 38 * @param text the text 39 * @param start the start of the line 40 * @param end the end of the line 41 * @param spanstartv the start of the span 42 * @param lineHeight the line height 43 * @param fm font metrics of the paint, in integers 44 */ chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm)45 public void chooseHeight(CharSequence text, int start, int end, 46 int spanstartv, int lineHeight, 47 Paint.FontMetricsInt fm); 48 49 /** 50 * The classes that affect the line height of paragraph with respect to density, 51 * should implement this interface. 52 */ 53 public interface WithDensity extends LineHeightSpan { 54 55 /** 56 * Classes that implement this should define how the height is being calculated. 57 * 58 * @param text the text 59 * @param start the start of the line 60 * @param end the end of the line 61 * @param spanstartv the start of the span 62 * @param lineHeight the line height 63 * @param paint the paint 64 */ chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm, TextPaint paint)65 public void chooseHeight(CharSequence text, int start, int end, 66 int spanstartv, int lineHeight, 67 Paint.FontMetricsInt fm, TextPaint paint); 68 } 69 70 /** 71 * Default implementation of the {@link LineHeightSpan}, which changes the line height of the 72 * attached paragraph. 73 * <p> 74 * For example, a paragraph with its line height equal to 100px can be set like this: 75 * <pre> 76 * SpannableString string = new SpannableString("This is a multiline paragraph. This is a multiline paragraph."); 77 * string.setSpan(new LineHeightSpan.Standard(100), 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 78 * </pre> 79 * <img src="{@docRoot}reference/android/images/text/style/lineheightspan.png" /> 80 * <figcaption>Text with line height set to 100 pixels.</figcaption> 81 * <p> 82 * Notice that LineHeightSpan will change the line height of the entire paragraph, even though it 83 * covers only part of the paragraph. 84 * </p> 85 */ 86 class Standard implements LineHeightSpan, ParcelableSpan { 87 88 private final @Px int mHeight; 89 /** 90 * Set the line height of the paragraph to <code>height</code> physical pixels. 91 */ Standard(@x @ntRangefrom = 1) int height)92 public Standard(@Px @IntRange(from = 1) int height) { 93 Preconditions.checkArgument(height > 0, "Height: %d must be positive", height); 94 mHeight = height; 95 } 96 97 /** 98 * Constructor called from {@link TextUtils} to restore the span from a parcel 99 */ Standard(@onNull Parcel src)100 public Standard(@NonNull Parcel src) { 101 mHeight = src.readInt(); 102 } 103 104 /** 105 * Returns the line height specified by this span. 106 */ 107 @Px getHeight()108 public int getHeight() { 109 return mHeight; 110 } 111 112 @Override getSpanTypeId()113 public int getSpanTypeId() { 114 return getSpanTypeIdInternal(); 115 } 116 117 /** @hide */ 118 @Override getSpanTypeIdInternal()119 public int getSpanTypeIdInternal() { 120 return TextUtils.LINE_HEIGHT_SPAN; 121 } 122 123 @Override describeContents()124 public int describeContents() { 125 return 0; 126 } 127 128 @Override writeToParcel(Parcel dest, int flags)129 public void writeToParcel(Parcel dest, int flags) { 130 writeToParcelInternal(dest, flags); 131 } 132 133 /** @hide */ 134 @Override writeToParcelInternal(@onNull Parcel dest, int flags)135 public void writeToParcelInternal(@NonNull Parcel dest, int flags) { 136 dest.writeInt(mHeight); 137 } 138 139 @Override chooseHeight(@onNull CharSequence text, int start, int end, int spanstartv, int lineHeight, @NonNull Paint.FontMetricsInt fm)140 public void chooseHeight(@NonNull CharSequence text, int start, int end, 141 int spanstartv, int lineHeight, 142 @NonNull Paint.FontMetricsInt fm) { 143 final int originHeight = fm.descent - fm.ascent; 144 // If original height is not positive, do nothing. 145 if (originHeight <= 0) { 146 return; 147 } 148 final float ratio = mHeight * 1.0f / originHeight; 149 fm.descent = Math.round(fm.descent * ratio); 150 fm.ascent = fm.descent - mHeight; 151 } 152 } 153 } 154