19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.text.style; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescuimport android.annotation.IntRange; 20139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescuimport android.annotation.NonNull; 21139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescuimport android.annotation.Px; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 244037d51b132a85dcfe37a95f9d2d91ad23d162fdAurimas Liutikasimport android.graphics.Paint; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Layout; 264037d51b132a85dcfe37a95f9d2d91ad23d162fdAurimas Liutikasimport android.text.Spanned; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu/** 29139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * Paragraph affecting span, that draws a bitmap at the beginning of a text. The span also allows 30139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * setting a padding between the bitmap and the text. The default value of the padding is 0px. The 31139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * span should be attached from the first character of the text. 32139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * <p> 33139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * For example, an <code>IconMarginSpan</code> with a bitmap and a padding of 30px can be set 34139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * like this: 35139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * <pre> 36139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * SpannableString string = new SpannableString("Text with icon and padding"); 37139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * string.setSpan(new IconMarginSpan(bitmap, 30), 0, string.length(), 38139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 39139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * </pre> 40139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * <img src="{@docRoot}reference/android/images/text/style/iconmarginspan.png" /> 41139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * <figcaption>Text with <code>IconMarginSpan</code></figcaption> 42139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * <p> 43139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * 44139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * @see DrawableMarginSpan for working with a {@link android.graphics.drawable.Drawable} instead of 45139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * a {@link Bitmap}. 46139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu */ 47139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescupublic class IconMarginSpan implements LeadingMarginSpan, LineHeightSpan { 48139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu 49139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu @NonNull 50139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu private final Bitmap mBitmap; 51139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu @Px 52139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu private final int mPad; 53139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu 54139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu /** 55139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * Creates an {@link IconMarginSpan} from a {@link Bitmap}. 56139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * 57139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * @param bitmap bitmap to be rendered at the beginning of the text 58139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu */ 59139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu public IconMarginSpan(@NonNull Bitmap bitmap) { 60139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu this(bitmap, 0); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 63139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu /** 64139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * Creates an {@link IconMarginSpan} from a {@link Bitmap}. 65139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * 66139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * @param bitmap bitmap to be rendered at the beginning of the text 67139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu * @param pad padding width, in pixels, between the bitmap and the text 68139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu */ 69139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu public IconMarginSpan(@NonNull Bitmap bitmap, @IntRange(from = 0) int pad) { 70139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu mBitmap = bitmap; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPad = pad; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 74139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu @Override 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getLeadingMargin(boolean first) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mBitmap.getWidth() + mPad; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 79139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu @Override 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, 81139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu int top, int baseline, int bottom, 82139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu CharSequence text, int start, int end, 83139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu boolean first, Layout layout) { 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = ((Spanned) text).getSpanStart(this); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int itop = layout.getLineTop(layout.getLineForOffset(st)); 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 87139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu if (dir < 0) { 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project x -= mBitmap.getWidth(); 89139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu } 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawBitmap(mBitmap, x, itop, p); 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 94139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu @Override 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void chooseHeight(CharSequence text, int start, int end, 96139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu int istartv, int v, 97139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu Paint.FontMetricsInt fm) { 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end == ((Spanned) text).getSpanEnd(this)) { 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ht = mBitmap.getHeight(); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int need = ht - (v + fm.descent - fm.ascent - istartv); 102139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu if (need > 0) { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.descent += need; 104139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project need = ht - (v + fm.bottom - fm.top - istartv); 107139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu if (need > 0) { 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fm.bottom += need; 109139e1b5c012630d6ec517fd46c6abb18d1f82694Florina Muntenescu } 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 114