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