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 17package android.text.style; 18 19import android.graphics.Canvas; 20import android.graphics.Paint; 21import android.graphics.Path; 22import android.graphics.Path.Direction; 23import android.os.Parcel; 24import android.text.Layout; 25import android.text.ParcelableSpan; 26import android.text.Spanned; 27import android.text.TextUtils; 28 29public class BulletSpan implements LeadingMarginSpan, ParcelableSpan { 30 private final int mGapWidth; 31 private final boolean mWantColor; 32 private final int mColor; 33 34 private static final int BULLET_RADIUS = 3; 35 private static Path sBulletPath = null; 36 public static final int STANDARD_GAP_WIDTH = 2; 37 38 public BulletSpan() { 39 mGapWidth = STANDARD_GAP_WIDTH; 40 mWantColor = false; 41 mColor = 0; 42 } 43 44 public BulletSpan(int gapWidth) { 45 mGapWidth = gapWidth; 46 mWantColor = false; 47 mColor = 0; 48 } 49 50 public BulletSpan(int gapWidth, int color) { 51 mGapWidth = gapWidth; 52 mWantColor = true; 53 mColor = color; 54 } 55 56 public BulletSpan(Parcel src) { 57 mGapWidth = src.readInt(); 58 mWantColor = src.readInt() != 0; 59 mColor = src.readInt(); 60 } 61 62 public int getSpanTypeId() { 63 return getSpanTypeIdInternal(); 64 } 65 66 /** @hide */ 67 public int getSpanTypeIdInternal() { 68 return TextUtils.BULLET_SPAN; 69 } 70 71 public int describeContents() { 72 return 0; 73 } 74 75 public void writeToParcel(Parcel dest, int flags) { 76 writeToParcelInternal(dest, flags); 77 } 78 79 /** @hide */ 80 public void writeToParcelInternal(Parcel dest, int flags) { 81 dest.writeInt(mGapWidth); 82 dest.writeInt(mWantColor ? 1 : 0); 83 dest.writeInt(mColor); 84 } 85 86 public int getLeadingMargin(boolean first) { 87 return 2 * BULLET_RADIUS + mGapWidth; 88 } 89 90 public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, 91 int top, int baseline, int bottom, 92 CharSequence text, int start, int end, 93 boolean first, Layout l) { 94 if (((Spanned) text).getSpanStart(this) == start) { 95 Paint.Style style = p.getStyle(); 96 int oldcolor = 0; 97 98 if (mWantColor) { 99 oldcolor = p.getColor(); 100 p.setColor(mColor); 101 } 102 103 p.setStyle(Paint.Style.FILL); 104 105 if (c.isHardwareAccelerated()) { 106 if (sBulletPath == null) { 107 sBulletPath = new Path(); 108 // Bullet is slightly better to avoid aliasing artifacts on mdpi devices. 109 sBulletPath.addCircle(0.0f, 0.0f, 1.2f * BULLET_RADIUS, Direction.CW); 110 } 111 112 c.save(); 113 c.translate(x + dir * BULLET_RADIUS, (top + bottom) / 2.0f); 114 c.drawPath(sBulletPath, p); 115 c.restore(); 116 } else { 117 c.drawCircle(x + dir * BULLET_RADIUS, (top + bottom) / 2.0f, BULLET_RADIUS, p); 118 } 119 120 if (mWantColor) { 121 p.setColor(oldcolor); 122 } 123 124 p.setStyle(style); 125 } 126 } 127} 128