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.graphics.Canvas; 20 import android.graphics.Paint; 21 import android.graphics.Rect; 22 import android.graphics.drawable.Drawable; 23 24 import java.lang.ref.WeakReference; 25 26 /** 27 * 28 */ 29 public abstract class DynamicDrawableSpan extends ReplacementSpan { 30 private static final String TAG = "DynamicDrawableSpan"; 31 32 /** 33 * A constant indicating that the bottom of this span should be aligned 34 * with the bottom of the surrounding text, i.e., at the same level as the 35 * lowest descender in the text. 36 */ 37 public static final int ALIGN_BOTTOM = 0; 38 39 /** 40 * A constant indicating that the bottom of this span should be aligned 41 * with the baseline of the surrounding text. 42 */ 43 public static final int ALIGN_BASELINE = 1; 44 45 protected final int mVerticalAlignment; 46 DynamicDrawableSpan()47 public DynamicDrawableSpan() { 48 mVerticalAlignment = ALIGN_BOTTOM; 49 } 50 51 /** 52 * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE}. 53 */ DynamicDrawableSpan(int verticalAlignment)54 protected DynamicDrawableSpan(int verticalAlignment) { 55 mVerticalAlignment = verticalAlignment; 56 } 57 58 /** 59 * Returns the vertical alignment of this span, one of {@link #ALIGN_BOTTOM} or 60 * {@link #ALIGN_BASELINE}. 61 */ getVerticalAlignment()62 public int getVerticalAlignment() { 63 return mVerticalAlignment; 64 } 65 66 /** 67 * Your subclass must implement this method to provide the bitmap 68 * to be drawn. The dimensions of the bitmap must be the same 69 * from each call to the next. 70 */ getDrawable()71 public abstract Drawable getDrawable(); 72 73 @Override getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm)74 public int getSize(Paint paint, CharSequence text, 75 int start, int end, 76 Paint.FontMetricsInt fm) { 77 Drawable d = getCachedDrawable(); 78 Rect rect = d.getBounds(); 79 80 if (fm != null) { 81 fm.ascent = -rect.bottom; 82 fm.descent = 0; 83 84 fm.top = fm.ascent; 85 fm.bottom = 0; 86 } 87 88 return rect.right; 89 } 90 91 @Override draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint)92 public void draw(Canvas canvas, CharSequence text, 93 int start, int end, float x, 94 int top, int y, int bottom, Paint paint) { 95 Drawable b = getCachedDrawable(); 96 canvas.save(); 97 98 int transY = bottom - b.getBounds().bottom; 99 if (mVerticalAlignment == ALIGN_BASELINE) { 100 transY -= paint.getFontMetricsInt().descent; 101 } 102 103 canvas.translate(x, transY); 104 b.draw(canvas); 105 canvas.restore(); 106 } 107 getCachedDrawable()108 private Drawable getCachedDrawable() { 109 WeakReference<Drawable> wr = mDrawableRef; 110 Drawable d = null; 111 112 if (wr != null) 113 d = wr.get(); 114 115 if (d == null) { 116 d = getDrawable(); 117 mDrawableRef = new WeakReference<Drawable>(d); 118 } 119 120 return d; 121 } 122 123 private WeakReference<Drawable> mDrawableRef; 124 } 125 126