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