/* * Copyright (C) 2006 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.text.style; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Px; import android.graphics.Paint; import android.os.Parcel; import android.text.ParcelableSpan; import android.text.TextPaint; import android.text.TextUtils; import com.android.internal.util.Preconditions; /** * The classes that affect the line height of paragraph should implement this interface. */ public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan { /** * Classes that implement this should define how the height is being calculated. * * @param text the text * @param start the start of the line * @param end the end of the line * @param spanstartv the start of the span * @param lineHeight the line height * @param fm font metrics of the paint, in integers */ public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm); /** * The classes that affect the line height of paragraph with respect to density, * should implement this interface. */ public interface WithDensity extends LineHeightSpan { /** * Classes that implement this should define how the height is being calculated. * * @param text the text * @param start the start of the line * @param end the end of the line * @param spanstartv the start of the span * @param lineHeight the line height * @param paint the paint */ public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm, TextPaint paint); } /** * Default implementation of the {@link LineHeightSpan}, which changes the line height of the * attached paragraph. *
* For example, a paragraph with its line height equal to 100px can be set like this: *
* SpannableString string = new SpannableString("This is a multiline paragraph. This is a multiline paragraph."); * string.setSpan(new LineHeightSpan.Standard(100), 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); **
* Notice that LineHeightSpan will change the line height of the entire paragraph, even though it * covers only part of the paragraph. *
*/ class Standard implements LineHeightSpan, ParcelableSpan { private final @Px int mHeight; /** * Set the line height of the paragraph toheight
physical pixels.
*/
public Standard(@Px @IntRange(from = 1) int height) {
Preconditions.checkArgument(height > 0, "Height: %d must be positive", height);
mHeight = height;
}
/**
* Constructor called from {@link TextUtils} to restore the span from a parcel
*/
public Standard(@NonNull Parcel src) {
mHeight = src.readInt();
}
/**
* Returns the line height specified by this span.
*/
@Px
public int getHeight() {
return mHeight;
}
@Override
public int getSpanTypeId() {
return getSpanTypeIdInternal();
}
/** @hide */
@Override
public int getSpanTypeIdInternal() {
return TextUtils.LINE_HEIGHT_SPAN;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
writeToParcelInternal(dest, flags);
}
/** @hide */
@Override
public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
dest.writeInt(mHeight);
}
@Override
public void chooseHeight(@NonNull CharSequence text, int start, int end,
int spanstartv, int lineHeight,
@NonNull Paint.FontMetricsInt fm) {
final int originHeight = fm.descent - fm.ascent;
// If original height is not positive, do nothing.
if (originHeight <= 0) {
return;
}
final float ratio = mHeight * 1.0f / originHeight;
fm.descent = Math.round(fm.descent * ratio);
fm.ascent = fm.descent - mHeight;
}
}
}