public interface AlignmentSpan extends ParagraphStyle {
    public Layout.Alignment getAlignment();

    public static class Standard
    implements AlignmentSpan, ParcelableSpan {
        public Standard(Layout.Alignment align) {
            mAlignment = align;
        }

        public Standard(Parcel src) {
            mAlignment = Layout.Alignment.valueOf(src.readString());
        }

        public int getSpanTypeId() {
            return getSpanTypeIdInternal();
        }

        public int describeContents() {
            return 0;
        }

        public void writeToParcel(Parcel dest, int flags) {
            writeToParcelInternal( dest, flags);
        }

        public Layout.Alignment getAlignment() {
            return mAlignment;
        }

        private final Layout.Alignment mAlignment;

        public int getSpanTypeIdInternal() {
            return TextUtils.ALIGNMENT_SPAN;
        }
        public void writeToParcelInternal(Parcel dest, int flags) {
            dest.writeString(mAlignment.name());
        }
    }
} public class BackgroundColorSpan extends CharacterStyle
        implements UpdateAppearance, ParcelableSpan {

    private final int mColor;

	public BackgroundColorSpan(int color) {
		mColor = color;
	}

    public BackgroundColorSpan(Parcel src) {
        mColor = src.readInt();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

	public int getBackgroundColor() {
		return mColor;
	}

	@Override
	public void updateDrawState(TextPaint ds) {
		ds.bgColor = mColor;
	}
    public int getSpanTypeIdInternal() {
        return TextUtils.BACKGROUND_COLOR_SPAN;
    }
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeInt(mColor);
    }
} public class BulletSpan implements LeadingMarginSpan, ParcelableSpan {
    private final int mGapWidth;
    private final boolean mWantColor;
    private final int mColor;

    private static final int BULLET_RADIUS = 3;
    public static final int STANDARD_GAP_WIDTH = 2;

    public BulletSpan() {
        mGapWidth = STANDARD_GAP_WIDTH;
        mWantColor = false;
        mColor = 0;
    }

    public BulletSpan(int gapWidth) {
        mGapWidth = gapWidth;
        mWantColor = false;
        mColor = 0;
    }

    public BulletSpan(int gapWidth, int color) {
        mGapWidth = gapWidth;
        mWantColor = true;
        mColor = color;
    }

    public BulletSpan(Parcel src) {
        mGapWidth = src.readInt();
        mWantColor = src.readInt() != 0;
        mColor = src.readInt();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

    public int getLeadingMargin(boolean first) {
        return 2 * BULLET_RADIUS + mGapWidth;
    }

    public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
                                  int top, int baseline, int bottom,
                                  CharSequence text, int start, int end,
                                  boolean first, Layout l) {
        if (((Spanned) text).getSpanStart(this) == start) {
            Paint.Style style = p.getStyle();
            int oldcolor = 0;

            if (mWantColor) {
                oldcolor = p.getColor();
                p.setColor(mColor);
            }

            p.setStyle(Paint.Style.FILL);

            c.drawCircle(x + dir * BULLET_RADIUS, (top + bottom) / 2.0f,
                         BULLET_RADIUS, p);

            if (mWantColor) {
                p.setColor(oldcolor);
            }

            p.setStyle(style);
        }
    }
    public int getSpanTypeIdInternal() {
        return TextUtils.BULLET_SPAN;
    }

    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeInt(mGapWidth);
        dest.writeInt(mWantColor ? 1 : 0);
        dest.writeInt(mColor);
    }
} public class ForegroundColorSpan extends CharacterStyle
        implements UpdateAppearance, ParcelableSpan {

    private int mColor;
    private int mStart;
    private int mEnd;

    static private ArrayList<ForegroundColorSpan> sPool = new ArrayList<ForegroundColorSpan>();

	public ForegroundColorSpan(int color) {
		mColor = color;
	}

    public ForegroundColorSpan(Parcel src) {
        mColor = src.readInt();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal() ;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal( dest, flags);
    }

	public int getForegroundColor() {
		return mColor;
	}

    @Override
	public void updateDrawState(TextPaint ds) {
		ds.setColor(mColor);
	}

    public boolean isLapped(int s, int e)
    {
        return  ( mStart < e && s < mEnd );
    }

    static public ForegroundColorSpan obtain(int color,int start,int end)
    {
        if ( sPool.size() == 0 ){
            return new ForegroundColorSpan(color);
        }else{
            ForegroundColorSpan fcs = sPool.get(0);
            sPool.remove(fcs);
            fcs.mColor = color;
            fcs.mStart = start;
            fcs.mEnd = end;
            return fcs;
        }
    }

    public void recycle()
    {
        sPool.add(this);
    }

    public int getSpanTypeIdInternal() {
        return TextUtils.FOREGROUND_COLOR_SPAN;
    }
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeInt(mColor);
    }
} public interface LeadingMarginSpan
extends ParagraphStyle
{
    /**
     * Returns the amount by which to adjust the leading margin. Positive values
     * move away from the leading edge of the paragraph, negative values move
     * towards it.
     *
     * @param first true if the request is for the first line of a paragraph,
     * false for subsequent lines
     * @return the offset for the margin.
     */
    public int getLeadingMargin(boolean first);

    /**
     * Renders the leading margin.  This is called before the margin has been
     * adjusted by the value returned by {@link #getLeadingMargin(boolean)}.
     *
     * @param c the canvas
     * @param p the paint. The this should be left unchanged on exit.
     * @param x the current position of the margin
     * @param dir the base direction of the paragraph; if negative, the margin
     * is to the right of the text, otherwise it is to the left.
     * @param top the top of the line
     * @param baseline the baseline of the line
     * @param bottom the bottom of the line
     * @param text the text
     * @param start the start of the line
     * @param end the end of the line
     * @param first true if this is the first line of its paragraph
     * @param layout the layout containing this line
     */
    public void drawLeadingMargin(Canvas c, Paint p,
                                  int x, int dir,
                                  int top, int baseline, int bottom,
                                  CharSequence text, int start, int end,
                                  boolean first, Layout layout);


    /**
     * An extended version of {@link LeadingMarginSpan}, which allows
     * the implementor to specify the number of lines of text to which
     * this object is attached that the "first line of paragraph" margin
     * width will be applied to.
     */
    public interface LeadingMarginSpan2 extends LeadingMarginSpan, WrapTogetherSpan {
        /**
         * Returns the number of lines of text to which this object is
         * attached that the "first line" margin will apply to.
         * Note that if this returns N, the first N lines of the region,
         * not the first N lines of each paragraph, will be given the
         * special margin width.
         */
        public int getLeadingMarginLineCount();
    };

    /**
     * The standard implementation of LeadingMarginSpan, which adjusts the
     * margin but does not do any rendering.
     */
    public static class Standard implements LeadingMarginSpan, ParcelableSpan {
        private final int mFirst, mRest;

        /**
         * Constructor taking separate indents for the first and subsequent
         * lines.
         *
         * @param first the indent for the first line of the paragraph
         * @param rest the indent for the remaining lines of the paragraph
         */
        public Standard(int first, int rest) {
            mFirst = first;
            mRest = rest;
        }

        /**
         * Constructor taking an indent for all lines.
         * @param every the indent of each line
         */
        public Standard(int every) {
            this(every, every);
        }

        public Standard(Parcel src) {
            mFirst = src.readInt();
            mRest = src.readInt();
        }

        public int getSpanTypeId() {
            return getSpanTypeIdInternal() ;
        }

        public int describeContents() {
            return 0;
        }

        public void writeToParcel(Parcel dest, int flags) {
            writeToParcelInternal(dest, flags) ;
        }

        public int getLeadingMargin(boolean first) {
            return first ? mFirst : mRest;
        }

        public void drawLeadingMargin(Canvas c, Paint p,
                                      int x, int dir,
                                      int top, int baseline, int bottom,
                                      CharSequence text, int start, int end,
                                      boolean first, Layout layout) {
            ;
        }
        public int getSpanTypeIdInternal() {
            return TextUtils.LEADING_MARGIN_SPAN;
        }
        public void writeToParcelInternal(Parcel dest, int flags) {
            dest.writeInt(mFirst);
            dest.writeInt(mRest);
        }
    }
} public abstract class MetricAffectingSpan
extends CharacterStyle
implements UpdateLayout {

	public abstract void updateMeasureState(TextPaint p);

    /**
     * Returns "this" for most MetricAffectingSpans, but for
     * MetricAffectingSpans that were generated by {@link #wrap},
     * returns the underlying MetricAffectingSpan.
     */
    @Override
    public MetricAffectingSpan getUnderlying() {
        return this;
    }

    /**
     * A Passthrough MetricAffectingSpan is one that
     * passes {@link #updateDrawState} and {@link #updateMeasureState}
     * calls through to the specified MetricAffectingSpan
     * while still being a distinct object,
     * and is therefore able to be attached to the same Spannable
     * to which the specified MetricAffectingSpan is already attached.
     */
    /* package */ static class Passthrough extends MetricAffectingSpan {
        private MetricAffectingSpan mStyle;

        /**
         * Creates a new Passthrough of the specfied MetricAffectingSpan.
         */
        public Passthrough(MetricAffectingSpan cs) {
            mStyle = cs;
        }

        /**
         * Passes updateDrawState through to the underlying MetricAffectingSpan.
         */
        @Override
        public void updateDrawState(TextPaint tp) {
            mStyle.updateDrawState(tp);
        }

        /**
         * Passes updateMeasureState through to the underlying MetricAffectingSpan.
         */
        @Override
        public void updateMeasureState(TextPaint tp) {
            mStyle.updateMeasureState(tp);
        }

        /**
         * Returns the MetricAffectingSpan underlying this one, or the one
         * underlying it if it too is a Passthrough.
         */
        @Override
        public MetricAffectingSpan getUnderlying() {
            return mStyle.getUnderlying();
        }
    }
} public class QuoteSpan implements LeadingMarginSpan, ParcelableSpan {
    private static final int STRIPE_WIDTH = 2;
    private static final int GAP_WIDTH = 2;

    private final int mColor;

    public QuoteSpan() {
        super();
        mColor = 0xff0000ff;
    }

    public QuoteSpan(int color) {
        super();
        mColor = color;
    }

    public QuoteSpan(Parcel src) {
        mColor = src.readInt();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest,  flags);
    }

    public int getColor() {
        return mColor;
    }

    public int getLeadingMargin(boolean first) {
        return STRIPE_WIDTH + GAP_WIDTH;
    }

    public void drawLeadingMargin(Canvas c, Paint p, int x, int dir,
                                  int top, int baseline, int bottom,
                                  CharSequence text, int start, int end,
                                  boolean first, Layout layout) {
        Paint.Style style = p.getStyle();
        int color = p.getColor();

        p.setStyle(Paint.Style.FILL);
        p.setColor(mColor);

        c.drawRect(x, top, x + dir * STRIPE_WIDTH, bottom, p);

        p.setStyle(style);
        p.setColor(color);
    }
    public int getSpanTypeIdInternal() {
        return TextUtils.QUOTE_SPAN;
    }
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeInt(mColor);
    }
} public class RelativeSizeSpan extends MetricAffectingSpan implements ParcelableSpan {

	private final float mProportion;

	public RelativeSizeSpan(float proportion) {
		mProportion = proportion;
	}

    public RelativeSizeSpan(Parcel src) {
        mProportion = src.readFloat();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal() ;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
		writeToParcelInternal(dest, flags);
    }

	public float getSizeChange() {
		return mProportion;
	}

	@Override
	public void updateDrawState(TextPaint ds) {
		ds.setTextSize(ds.getTextSize() * mProportion);
	}

	@Override
	public void updateMeasureState(TextPaint ds) {
		ds.setTextSize(ds.getTextSize() * mProportion);
	}

	public int getSpanTypeIdInternal() {
		return TextUtils.RELATIVE_SIZE_SPAN;
	}

	public void writeToParcelInternal(Parcel dest, int flags) {
		dest.writeFloat(mProportion);
	}
} public abstract class ReplacementSpan extends MetricAffectingSpan {

    public abstract int getSize(Paint paint, CharSequence text,
                         int start, int end,
                         Paint.FontMetricsInt fm);
    public abstract void draw(Canvas canvas, CharSequence text,
                     int start, int end, float x,
                     int top, int y, int bottom, Paint paint);

    /**
     * This method does nothing, since ReplacementSpans are measured
     * explicitly instead of affecting Paint properties.
     */
    public void updateMeasureState(TextPaint p) { }

    /**
     * This method does nothing, since ReplacementSpans are drawn
     * explicitly instead of affecting Paint properties.
     */
    public void updateDrawState(TextPaint ds) { }
} public class ScaleXSpan extends MetricAffectingSpan implements ParcelableSpan {

	private final float mProportion;

	public ScaleXSpan(float proportion) {
		mProportion = proportion;
	}

    public ScaleXSpan(Parcel src) {
        mProportion = src.readFloat();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal() ;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
		writeToParcelInternal(dest,  flags);
    }

	public float getScaleX() {
		return mProportion;
	}

	@Override
	public void updateDrawState(TextPaint ds) {
		ds.setTextScaleX(ds.getTextScaleX() * mProportion);
	}

	@Override
	public void updateMeasureState(TextPaint ds) {
		ds.setTextScaleX(ds.getTextScaleX() * mProportion);
	}
	public int getSpanTypeIdInternal() {
		return TextUtils.SCALE_X_SPAN;
	}
	public void writeToParcelInternal(Parcel dest, int flags) {
		dest.writeFloat(mProportion);
	}
} public class StrikethroughSpan extends CharacterStyle
        implements UpdateAppearance, ParcelableSpan {
    public StrikethroughSpan() {
    }

    public StrikethroughSpan(Parcel src) {
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

	@Override
	public void updateDrawState(TextPaint ds) {
		ds.setStrikeThruText(true);
	}

    public int getSpanTypeIdInternal() {
        return TextUtils.STRIKETHROUGH_SPAN;
    }
    public void writeToParcelInternal(Parcel dest, int flags) {
    }
} public class StyleSpan extends MetricAffectingSpan implements ParcelableSpan {

	private final int mStyle;

	/**
	 *
	 * @param style An integer constant describing the style for this span. Examples
	 * include bold, italic, and normal. Values are constants defined
	 * in {@link android.graphics.Typeface}.
	 */
	public StyleSpan(int style) {
		mStyle = style;
	}

    public StyleSpan(Parcel src) {
        mStyle = src.readInt();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal() ;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest,  flags);
    }

	/**
	 * Returns the style constant defined in {@link android.graphics.Typeface}.
	 */
	public int getStyle() {
		return mStyle;
	}

	@Override
    public void updateDrawState(TextPaint ds) {
        apply(ds, mStyle);
    }

	@Override
    public void updateMeasureState(TextPaint paint) {
        apply(paint, mStyle);
    }

    private static void apply(Paint paint, int style) {
        int oldStyle;

        Typeface old = paint.getTypeface();
        if (old == null) {
            oldStyle = 0;
        } else {
            oldStyle = old.getStyle();
        }

        int want = oldStyle | style;

        Typeface tf;
        if (old == null) {
            tf = Typeface.defaultFromStyle(want);
        } else {
            tf = Typeface.create(old, want);
        }

        int fake = want & ~tf.getStyle();

        if ((fake & Typeface.BOLD) != 0) {
            paint.setFakeBoldText(true);
        }

        if ((fake & Typeface.ITALIC) != 0) {
            paint.setTextSkewX(-0.25f);
        }

        paint.setTypeface(tf);
    }
    public int getSpanTypeIdInternal() {
        return TextUtils.STYLE_SPAN;
    }
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeInt(mStyle);
    }
} public class SubscriptSpan extends MetricAffectingSpan implements ParcelableSpan {
    public SubscriptSpan() {
    }

    public SubscriptSpan(Parcel src) {
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal() ;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest,  flags);
    }

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.baselineShift -= (int) (tp.ascent() / 2);
    }

    @Override
    public void updateMeasureState(TextPaint tp) {
        tp.baselineShift -= (int) (tp.ascent() / 2);
    }

    public int getSpanTypeIdInternal() {
        return TextUtils.SUBSCRIPT_SPAN;
    }
    public void writeToParcelInternal(Parcel dest, int flags) {
    }
} public class SuperscriptSpan extends MetricAffectingSpan implements ParcelableSpan {
    public SuperscriptSpan() {
    }

    public SuperscriptSpan(Parcel src) {
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal() ;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

    @Override
    public void updateDrawState(TextPaint tp) {
        tp.baselineShift += (int) (tp.ascent() / 2);
    }

    @Override
    public void updateMeasureState(TextPaint tp) {
        tp.baselineShift += (int) (tp.ascent() / 2);
    }

    public int getSpanTypeIdInternal() {
        return TextUtils.SUPERSCRIPT_SPAN;
    }
    public void writeToParcelInternal(Parcel dest, int flags) {
    }
} public class TextAppearanceSpan extends MetricAffectingSpan implements ParcelableSpan {
    private final String mTypeface;
    private final int mStyle;
    private final int mTextSize;
    private final ColorStateList mTextColor;
    private final ColorStateList mTextColorLink;

    /**
     * Uses the specified TextAppearance resource to determine the
     * text appearance.  The <code>appearance</code> should be, for example,
     * <code>android.R.style.TextAppearance_Small</code>.
     */
    public TextAppearanceSpan(Context context, int appearance) {
        this(context, appearance, -1);
    }

    /**
     * Uses the specified TextAppearance resource to determine the
     * text appearance, and the specified text color resource
     * to determine the color.  The <code>appearance</code> should be,
     * for example, <code>android.R.style.TextAppearance_Small</code>,
     * and the <code>colorList</code> should be, for example,
     * <code>android.R.styleable.Theme_textColorDim</code>.
     */
    public TextAppearanceSpan(Context context, int appearance,
                              int colorList) {
        ColorStateList textColor;

        TypedArray a =
            context.obtainStyledAttributes(appearance,
                                           com.android.internal.R.styleable.TextAppearance);

        textColor = a.getColorStateList(com.android.internal.R.styleable.
                                        TextAppearance_textColor);
        mTextColorLink = a.getColorStateList(com.android.internal.R.styleable.
                                        TextAppearance_textColorLink);
        mTextSize = a.getDimensionPixelSize(com.android.internal.R.styleable.
                                        TextAppearance_textSize, -1);

        mStyle = a.getInt(com.android.internal.R.styleable.TextAppearance_textStyle, 0);
        int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0);

        switch (tf) {
            case 1:
                mTypeface = "sans";
                break;

            case 2:
                mTypeface = "serif";
                break;

            case 3:
                mTypeface = "monospace";
                break;

            default:
                mTypeface = null;
                break;
        }

        a.recycle();

        if (colorList >= 0) {
            a = context.obtainStyledAttributes(com.android.internal.R.style.Theme,
                                            com.android.internal.R.styleable.Theme);

            textColor = a.getColorStateList(colorList);
            a.recycle();
        }

        mTextColor = textColor;
    }

    /**
     * Makes text be drawn with the specified typeface, size, style,
     * and colors.
     */
    public TextAppearanceSpan(String family, int style, int size,
                              ColorStateList color, ColorStateList linkColor) {
        mTypeface = family;
        mStyle = style;
        mTextSize = size;
        mTextColor = color;
        mTextColorLink = linkColor;
    }

    public TextAppearanceSpan(Parcel src) {
        mTypeface = src.readString();
        mStyle = src.readInt();
        mTextSize = src.readInt();
        if (src.readInt() != 0) {
            mTextColor = ColorStateList.CREATOR.createFromParcel(src);
        } else {
            mTextColor = null;
        }
        if (src.readInt() != 0) {
            mTextColorLink = ColorStateList.CREATOR.createFromParcel(src);
        } else {
            mTextColorLink = null;
        }
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal() ;
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

    /**
     * Returns the typeface family specified by this span, or <code>null</code>
     * if it does not specify one.
     */
    public String getFamily() {
        return mTypeface;
    }

    /**
     * Returns the text color specified by this span, or <code>null</code>
     * if it does not specify one.
     */
    public ColorStateList getTextColor() {
        return mTextColor;
    }

    /**
     * Returns the link color specified by this span, or <code>null</code>
     * if it does not specify one.
     */
    public ColorStateList getLinkTextColor() {
        return mTextColorLink;
    }

    /**
     * Returns the text size specified by this span, or <code>-1</code>
     * if it does not specify one.
     */
    public int getTextSize() {
        return mTextSize;
    }

    /**
     * Returns the text style specified by this span, or <code>0</code>
     * if it does not specify one.
     */
    public int getTextStyle() {
        return mStyle;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        updateMeasureState(ds);

        if (mTextColor != null) {
            ds.setColor(mTextColor.getColorForState(ds.drawableState, 0));
        }

        if (mTextColorLink != null) {
            ds.linkColor = mTextColor.getColorForState(ds.drawableState, 0);
        }
    }

    @Override
    public void updateMeasureState(TextPaint ds) {
        if (mTypeface != null || mStyle != 0) {
            Typeface tf = ds.getTypeface();
            int style = 0;

            if (tf != null) {
                style = tf.getStyle();
            }

            style |= mStyle;

            if (mTypeface != null) {
                tf = Typeface.create(mTypeface, style);
            } else if (tf == null) {
                tf = Typeface.defaultFromStyle(style);
            } else {
                tf = Typeface.create(tf, style);
            }

            int fake = style & ~tf.getStyle();

            if ((fake & Typeface.BOLD) != 0) {
                ds.setFakeBoldText(true);
            }

            if ((fake & Typeface.ITALIC) != 0) {
                ds.setTextSkewX(-0.25f);
            }

            ds.setTypeface(tf);
        }

        if (mTextSize > 0) {
            ds.setTextSize(mTextSize);
        }
    }
    public int getSpanTypeIdInternal() {
        return TextUtils.TEXT_APPEARANCE_SPAN;
    }
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeString(mTypeface);
        dest.writeInt(mStyle);
        dest.writeInt(mTextSize);
        if (mTextColor != null) {
            dest.writeInt(1);
            mTextColor.writeToParcel(dest, flags);
        } else {
            dest.writeInt(0);
        }
        if (mTextColorLink != null) {
            dest.writeInt(1);
            mTextColorLink.writeToParcel(dest, flags);
        } else {
            dest.writeInt(0);
        }
    }
} public class TypefaceSpan extends MetricAffectingSpan implements ParcelableSpan {
    private final String mFamily;

    /**
     * @param family The font family for this typeface.  Examples include
     * "monospace", "serif", and "sans-serif".
     */
    public TypefaceSpan(String family) {
        mFamily = family;
    }

    public TypefaceSpan(Parcel src) {
        mFamily = src.readString();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

    /**
     * Returns the font family name.
     */
    public String getFamily() {
        return mFamily;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        apply(ds, mFamily);
    }

    @Override
    public void updateMeasureState(TextPaint paint) {
        apply(paint, mFamily);
    }

    private static void apply(Paint paint, String family) {
        int oldStyle;

        Typeface old = paint.getTypeface();
        if (old == null) {
            oldStyle = 0;
        } else {
            oldStyle = old.getStyle();
        }

        Typeface tf = Typeface.create(family, oldStyle);
        int fake = oldStyle & ~tf.getStyle();

        if ((fake & Typeface.BOLD) != 0) {
            paint.setFakeBoldText(true);
        }

        if ((fake & Typeface.ITALIC) != 0) {
            paint.setTextSkewX(-0.25f);
        }

        paint.setTypeface(tf);
    }
    public int getSpanTypeIdInternal() {
        return TextUtils.TYPEFACE_SPAN;
    }
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeString(mFamily);
    }
} public class URLSpan extends ClickableSpan implements ParcelableSpan {

    private final String mURL;

    public URLSpan(String url) {
        mURL = url;
    }

    public URLSpan(Parcel src) {
        mURL = src.readString();
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    @Override
    public int getSpanTypeIdInternal() {
        return TextUtils.URL_SPAN;
    }

    @Override
    public void writeToParcelInternal(Parcel dest, int flags) {
        dest.writeString(mURL);
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest, flags);
    }

    public String getURL() {
        return mURL;
    }

    @Override
    public void onClick(View widget) {
        Uri uri = Uri.parse(getURL());
        Context context = widget.getContext();
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
        context.startActivity(intent);
    }
} public class UnderlineSpan extends CharacterStyle
        implements UpdateAppearance, ParcelableSpan {
    public UnderlineSpan() {
    }

    public UnderlineSpan(Parcel src) {
    }

    public int getSpanTypeId() {
        return getSpanTypeIdInternal();
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel dest, int flags) {
        writeToParcelInternal(dest,  flags);
    }

	@Override
	public void updateDrawState(TextPaint ds) {
		ds.setUnderlineText(true);
	}

    public int getSpanTypeIdInternal() {
        return TextUtils.UNDERLINE_SPAN;
    }
    public void writeToParcelInternal(Parcel dest, int flags) {
    }
}
import java.util.Iterator;
import java.util.regex.Pattern;
import jp.sblo.pandora.jota.text.style.AlignmentSpan;
import jp.sblo.pandora.jota.text.style.BackgroundColorSpan;
import jp.sblo.pandora.jota.text.style.BulletSpan;
import jp.sblo.pandora.jota.text.style.ForegroundColorSpan;
import jp.sblo.pandora.jota.text.style.LeadingMarginSpan;
import jp.sblo.pandora.jota.text.style.MetricAffectingSpan;
import jp.sblo.pandora.jota.text.style.QuoteSpan;
import jp.sblo.pandora.jota.text.style.RelativeSizeSpan;
import jp.sblo.pandora.jota.text.style.ReplacementSpan;
import jp.sblo.pandora.jota.text.style.ScaleXSpan;
import jp.sblo.pandora.jota.text.style.StrikethroughSpan;
import jp.sblo.pandora.jota.text.style.StyleSpan;
import jp.sblo.pandora.jota.text.style.SubscriptSpan;
import jp.sblo.pandora.jota.text.style.SuperscriptSpan;
import jp.sblo.pandora.jota.text.style.TextAppearanceSpan;
import jp.sblo.pandora.jota.text.style.TypefaceSpan;
import jp.sblo.pandora.jota.text.style.URLSpan;
import jp.sblo.pandora.jota.text.style.UnderlineSpan;
import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.AndroidCharacter;
import android.text.Annotation;
import android.text.GetChars;
import android.text.InputType;
import android.text.ParcelableSpan;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.TextPaint;
import android.text.style.CharacterStyle;
import android.util.Printer;
import com.android.internal.R;
    /** @hide */
    public static final int LEADING_MARGIN_SPAN = 10;
    /** @hide */
    public static final int URL_SPAN = 11;
    /** @hide */
    public static final int BACKGROUND_COLOR_SPAN = 12;
    /** @hide */
    public static final int TYPEFACE_SPAN = 13;
    /** @hide */
    public static final int SUPERSCRIPT_SPAN = 14;
    /** @hide */
    public static final int SUBSCRIPT_SPAN = 15;
    /** @hide */
    public static final int ABSOLUTE_SIZE_SPAN = 16;
    /** @hide */
    public static final int TEXT_APPEARANCE_SPAN = 17;
    /** @hide */
    public static final int ANNOTATION = 18;

    /**
     * Flatten a CharSequence and whatever styles can be copied across processes
     * into the parcel.
     */
    public static void writeToParcel(CharSequence cs, Parcel p,
            int parcelableFlags) {
        if (cs instanceof Spanned) {
            p.writeInt(0);
            p.writeString(cs.toString());

            Spanned sp = (Spanned) cs;
            Object[] os = sp.getSpans(0, cs.length(), Object.class);

            // note to people adding to this: check more specific types
            // before more generic types.  also notice that it uses
            // "if" instead of "else if" where there are interfaces
            // so one object can be several.

            for (int i = 0; i < os.length; i++) {
                Object o = os[i];
                Object prop = os[i];

                if (prop instanceof CharacterStyle) {
                    prop = ((CharacterStyle) prop).getUnderlying();
                }

                if (prop instanceof ParcelableSpan) {
                    ParcelableSpan ps = (ParcelableSpan)prop;

                    // dont percel unknown span id
                    int id = ps.getSpanTypeId();
                    if ( id <= ANNOTATION ){
                        p.writeInt(id);
                        ps.writeToParcel(p, parcelableFlags);
                        writeWhere(p, sp, o);
                    }
//                    p.writeInt(ps.getSpanTypeId());
//                    ps.writeToParcel(p, parcelableFlags);
//                    writeWhere(p, sp, o);
                }
            }

            p.writeInt(0);
        } else {
            p.writeInt(1);
            if (cs != null) {
                p.writeString(cs.toString());
            } else {
                p.writeString(null);
            }
        }
    }

    private static void writeWhere(Parcel p, Spanned sp, Object o) {
        p.writeInt(sp.getSpanStart(o));
        p.writeInt(sp.getSpanEnd(o));
        p.writeInt(sp.getSpanFlags(o));
    }

    public static final Parcelable.Creator<CharSequence> CHAR_SEQUENCE_CREATOR
            = new Parcelable.Creator<CharSequence>() {
        /**
         * Read and return a new CharSequence, possibly with styles,
         * from the parcel.
         */
        public  CharSequence createFromParcel(Parcel p) {
            int kind = p.readInt();

            if (kind == 1)
                return p.readString();

            SpannableString sp = new SpannableString(p.readString());

            while (true) {
                kind = p.readInt();

                if (kind == 0)
                    break;

                switch (kind) {
                case ALIGNMENT_SPAN:
                    readSpan(p, sp, new AlignmentSpan.Standard(p));
                    break;

                case FOREGROUND_COLOR_SPAN:
                    readSpan(p, sp, new ForegroundColorSpan(p));
                    break;

                case RELATIVE_SIZE_SPAN:
                    readSpan(p, sp, new RelativeSizeSpan(p));
                    break;

                case SCALE_X_SPAN:
                    readSpan(p, sp, new ScaleXSpan(p));
                    break;

                case STRIKETHROUGH_SPAN:
                    readSpan(p, sp, new StrikethroughSpan(p));
                    break;

                case UNDERLINE_SPAN:
                    readSpan(p, sp, new UnderlineSpan(p));