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.graphics;
18
19import android.text.TextUtils;
20import android.text.SpannableString;
21import android.text.SpannedString;
22import android.text.GraphicsOperations;
23
24/**
25 * The Paint class holds the style and color information about how to draw
26 * geometries, text and bitmaps.
27 */
28public class Paint {
29
30    /*package*/ int     mNativePaint;
31    private ColorFilter mColorFilter;
32    private MaskFilter  mMaskFilter;
33    private PathEffect  mPathEffect;
34    private Rasterizer  mRasterizer;
35    private Shader      mShader;
36    private Typeface    mTypeface;
37    private Xfermode    mXfermode;
38
39    private boolean     mHasCompatScaling;
40    private float       mCompatScaling;
41    private float       mInvCompatScaling;
42
43    private static final Style[] sStyleArray = {
44        Style.FILL, Style.STROKE, Style.FILL_AND_STROKE
45    };
46    private static final Cap[] sCapArray = {
47        Cap.BUTT, Cap.ROUND, Cap.SQUARE
48    };
49    private static final Join[] sJoinArray = {
50        Join.MITER, Join.ROUND, Join.BEVEL
51    };
52    private static final Align[] sAlignArray = {
53        Align.LEFT, Align.CENTER, Align.RIGHT
54    };
55
56    /** bit mask for the flag enabling antialiasing */
57    public static final int ANTI_ALIAS_FLAG     = 0x01;
58    /** bit mask for the flag enabling bitmap filtering */
59    public static final int FILTER_BITMAP_FLAG  = 0x02;
60    /** bit mask for the flag enabling dithering */
61    public static final int DITHER_FLAG         = 0x04;
62    /** bit mask for the flag enabling underline text */
63    public static final int UNDERLINE_TEXT_FLAG = 0x08;
64    /** bit mask for the flag enabling strike-thru text */
65    public static final int STRIKE_THRU_TEXT_FLAG = 0x10;
66    /** bit mask for the flag enabling fake-bold text */
67    public static final int FAKE_BOLD_TEXT_FLAG = 0x20;
68    /** bit mask for the flag enabling linear-text (no caching) */
69    public static final int LINEAR_TEXT_FLAG    = 0x40;
70    /** bit mask for the flag enabling subpixel-text */
71    public static final int SUBPIXEL_TEXT_FLAG  = 0x80;
72    /** bit mask for the flag enabling device kerning for text */
73    public static final int DEV_KERN_TEXT_FLAG  = 0x100;
74
75    // we use this when we first create a paint
76    private static final int DEFAULT_PAINT_FLAGS = DEV_KERN_TEXT_FLAG;
77
78    /**
79     * The Style specifies if the primitive being drawn is filled,
80     * stroked, or both (in the same color). The default is FILL.
81     */
82    public enum Style {
83        /**
84         * Geometry and text drawn with this style will be filled, ignoring all
85         * stroke-related settings in the paint.
86         */
87        FILL            (0),
88        /**
89         * Geometry and text drawn with this style will be stroked, respecting
90         * the stroke-related fields on the paint.
91         */
92        STROKE          (1),
93        /**
94         * Geometry and text drawn with this style will be both filled and
95         * stroked at the same time, respecting the stroke-related fields on
96         * the paint.
97         */
98        FILL_AND_STROKE (2);
99
100        Style(int nativeInt) {
101            this.nativeInt = nativeInt;
102        }
103        final int nativeInt;
104    }
105
106    /**
107     * The Cap specifies the treatment for the beginning and ending of
108     * stroked lines and paths. The default is BUTT.
109     */
110    public enum Cap {
111        /**
112         * The stroke ends with the path, and does not project beyond it.
113         */
114        BUTT    (0),
115        /**
116         * The stroke projects out as a semicircle, with the center at the
117         * end of the path.
118         */
119        ROUND   (1),
120        /**
121         * The stroke projects out as a square, with the center at the end
122         * of the path.
123         */
124        SQUARE  (2);
125
126        private Cap(int nativeInt) {
127            this.nativeInt = nativeInt;
128        }
129        final int nativeInt;
130    }
131
132    /**
133     * The Join specifies the treatment where lines and curve segments
134     * join on a stroked path. The default is MITER.
135     */
136    public enum Join {
137        /**
138         * The outer edges of a join meet at a sharp angle
139         */
140        MITER   (0),
141        /**
142         * The outer edges of a join meet in a circular arc.
143         */
144        ROUND   (1),
145        /**
146         * The outer edges of a join meet with a straight line
147         */
148        BEVEL   (2);
149
150        private Join(int nativeInt) {
151            this.nativeInt = nativeInt;
152        }
153        final int nativeInt;
154    }
155
156    /**
157     * Align specifies how drawText aligns its text relative to the
158     * [x,y] coordinates. The default is LEFT.
159     */
160    public enum Align {
161        /**
162         * The text is drawn to the right of the x,y origin
163         */
164        LEFT    (0),
165        /**
166         * The text is drawn centered horizontally on the x,y origin
167         */
168        CENTER  (1),
169        /**
170         * The text is drawn to the left of the x,y origin
171         */
172        RIGHT   (2);
173
174        private Align(int nativeInt) {
175            this.nativeInt = nativeInt;
176        }
177        final int nativeInt;
178    }
179
180    /**
181     * Create a new paint with default settings.
182     */
183    public Paint() {
184        this(0);
185    }
186
187    /**
188     * Create a new paint with the specified flags. Use setFlags() to change
189     * these after the paint is created.
190     *
191     * @param flags initial flag bits, as if they were passed via setFlags().
192     */
193    public Paint(int flags) {
194        mNativePaint = native_init();
195        setFlags(flags | DEFAULT_PAINT_FLAGS);
196        mCompatScaling = mInvCompatScaling = 1;
197    }
198
199    /**
200     * Create a new paint, initialized with the attributes in the specified
201     * paint parameter.
202     *
203     * @param paint Existing paint used to initialized the attributes of the
204     *              new paint.
205     */
206    public Paint(Paint paint) {
207        mNativePaint = native_initWithPaint(paint.mNativePaint);
208        mHasCompatScaling = paint.mHasCompatScaling;
209        mCompatScaling = paint.mCompatScaling;
210        mInvCompatScaling = paint.mInvCompatScaling;
211    }
212
213    /** Restores the paint to its default settings. */
214    public void reset() {
215        native_reset(mNativePaint);
216        setFlags(DEFAULT_PAINT_FLAGS);
217        mHasCompatScaling = false;
218        mCompatScaling = mInvCompatScaling = 1;
219    }
220
221    /**
222     * Copy the fields from src into this paint. This is equivalent to calling
223     * get() on all of the src fields, and calling the corresponding set()
224     * methods on this.
225     */
226    public void set(Paint src) {
227        if (this != src) {
228            // copy over the native settings
229            native_set(mNativePaint, src.mNativePaint);
230            // copy over our java settings
231            mColorFilter    = src.mColorFilter;
232            mMaskFilter     = src.mMaskFilter;
233            mPathEffect     = src.mPathEffect;
234            mRasterizer     = src.mRasterizer;
235            mShader         = src.mShader;
236            mTypeface       = src.mTypeface;
237            mXfermode       = src.mXfermode;
238            mHasCompatScaling = src.mHasCompatScaling;
239            mCompatScaling    = src.mCompatScaling;
240            mInvCompatScaling = src.mInvCompatScaling;
241        }
242    }
243
244    /** @hide */
245    public void setCompatibilityScaling(float factor) {
246        if (factor == 1.0) {
247            mHasCompatScaling = false;
248            mCompatScaling = mInvCompatScaling = 1.0f;
249        } else {
250            mHasCompatScaling = true;
251            mCompatScaling = factor;
252            mInvCompatScaling = 1.0f/factor;
253        }
254    }
255
256    /**
257     * Return the paint's flags. Use the Flag enum to test flag values.
258     *
259     * @return the paint's flags (see enums ending in _Flag for bit masks)
260     */
261    public native int getFlags();
262
263    /**
264     * Set the paint's flags. Use the Flag enum to specific flag values.
265     *
266     * @param flags The new flag bits for the paint
267     */
268    public native void setFlags(int flags);
269
270    /**
271     * Helper for getFlags(), returning true if ANTI_ALIAS_FLAG bit is set
272     * AntiAliasing smooths out the edges of what is being drawn, but is has
273     * no impact on the interior of the shape. See setDither() and
274     * setFilterBitmap() to affect how colors are treated.
275     *
276     * @return true if the antialias bit is set in the paint's flags.
277     */
278    public final boolean isAntiAlias() {
279        return (getFlags() & ANTI_ALIAS_FLAG) != 0;
280    }
281
282    /**
283     * Helper for setFlags(), setting or clearing the ANTI_ALIAS_FLAG bit
284     * AntiAliasing smooths out the edges of what is being drawn, but is has
285     * no impact on the interior of the shape. See setDither() and
286     * setFilterBitmap() to affect how colors are treated.
287     *
288     * @param aa true to set the antialias bit in the flags, false to clear it
289     */
290    public native void setAntiAlias(boolean aa);
291
292    /**
293     * Helper for getFlags(), returning true if DITHER_FLAG bit is set
294     * Dithering affects how colors that are higher precision than the device
295     * are down-sampled. No dithering is generally faster, but higher precision
296     * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to
297     * distribute the error inherent in this process, to reduce the visual
298     * artifacts.
299     *
300     * @return true if the dithering bit is set in the paint's flags.
301     */
302    public final boolean isDither() {
303        return (getFlags() & DITHER_FLAG) != 0;
304    }
305
306    /**
307     * Helper for setFlags(), setting or clearing the DITHER_FLAG bit
308     * Dithering affects how colors that are higher precision than the device
309     * are down-sampled. No dithering is generally faster, but higher precision
310     * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to
311     * distribute the error inherent in this process, to reduce the visual
312     * artifacts.
313     *
314     * @param dither true to set the dithering bit in flags, false to clear it
315     */
316    public native void setDither(boolean dither);
317
318    /**
319     * Helper for getFlags(), returning true if LINEAR_TEXT_FLAG bit is set
320     *
321     * @return true if the lineartext bit is set in the paint's flags
322     */
323    public final boolean isLinearText() {
324        return (getFlags() & LINEAR_TEXT_FLAG) != 0;
325    }
326
327    /**
328     * Helper for setFlags(), setting or clearing the LINEAR_TEXT_FLAG bit
329     *
330     * @param linearText true to set the linearText bit in the paint's flags,
331     *                   false to clear it.
332     */
333    public native void setLinearText(boolean linearText);
334
335    /**
336     * Helper for getFlags(), returning true if SUBPIXEL_TEXT_FLAG bit is set
337     *
338     * @return true if the subpixel bit is set in the paint's flags
339     */
340    public final boolean isSubpixelText() {
341        return (getFlags() & SUBPIXEL_TEXT_FLAG) != 0;
342    }
343
344    /**
345     * Helper for setFlags(), setting or clearing the SUBPIXEL_TEXT_FLAG bit
346     *
347     * @param subpixelText true to set the subpixelText bit in the paint's
348     *                     flags, false to clear it.
349     */
350    public native void setSubpixelText(boolean subpixelText);
351
352    /**
353     * Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set
354     *
355     * @return true if the underlineText bit is set in the paint's flags.
356     */
357    public final boolean isUnderlineText() {
358        return (getFlags() & UNDERLINE_TEXT_FLAG) != 0;
359    }
360
361    /**
362     * Helper for setFlags(), setting or clearing the UNDERLINE_TEXT_FLAG bit
363     *
364     * @param underlineText true to set the underlineText bit in the paint's
365     *                      flags, false to clear it.
366     */
367    public native void setUnderlineText(boolean underlineText);
368
369    /**
370     * Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set
371     *
372     * @return true if the strikeThruText bit is set in the paint's flags.
373     */
374    public final boolean isStrikeThruText() {
375        return (getFlags() & STRIKE_THRU_TEXT_FLAG) != 0;
376    }
377
378    /**
379     * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit
380     *
381     * @param strikeThruText true to set the strikeThruText bit in the paint's
382     *                       flags, false to clear it.
383     */
384    public native void setStrikeThruText(boolean strikeThruText);
385
386    /**
387     * Helper for getFlags(), returning true if FAKE_BOLD_TEXT_FLAG bit is set
388     *
389     * @return true if the fakeBoldText bit is set in the paint's flags.
390     */
391    public final boolean isFakeBoldText() {
392        return (getFlags() & FAKE_BOLD_TEXT_FLAG) != 0;
393    }
394
395    /**
396     * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit
397     *
398     * @param fakeBoldText true to set the fakeBoldText bit in the paint's
399     *                     flags, false to clear it.
400     */
401    public native void setFakeBoldText(boolean fakeBoldText);
402
403    /**
404     * Whether or not the bitmap filter is activated.
405     * Filtering affects the sampling of bitmaps when they are transformed.
406     * Filtering does not affect how the colors in the bitmap are converted into
407     * device pixels. That is dependent on dithering and xfermodes.
408     *
409     * @see #setFilterBitmap(boolean) setFilterBitmap()
410     */
411    public final boolean isFilterBitmap() {
412        return (getFlags() & FILTER_BITMAP_FLAG) != 0;
413    }
414
415    /**
416     * Helper for setFlags(), setting or clearing the FILTER_BITMAP_FLAG bit.
417     * Filtering affects the sampling of bitmaps when they are transformed.
418     * Filtering does not affect how the colors in the bitmap are converted into
419     * device pixels. That is dependent on dithering and xfermodes.
420     *
421     * @param filter true to set the FILTER_BITMAP_FLAG bit in the paint's
422     *               flags, false to clear it.
423     */
424    public native void setFilterBitmap(boolean filter);
425
426    /**
427     * Return the paint's style, used for controlling how primitives'
428     * geometries are interpreted (except for drawBitmap, which always assumes
429     * FILL_STYLE).
430     *
431     * @return the paint's style setting (Fill, Stroke, StrokeAndFill)
432     */
433    public Style getStyle() {
434        return sStyleArray[native_getStyle(mNativePaint)];
435    }
436
437    /**
438     * Set the paint's style, used for controlling how primitives'
439     * geometries are interpreted (except for drawBitmap, which always assumes
440     * Fill).
441     *
442     * @param style The new style to set in the paint
443     */
444    public void setStyle(Style style) {
445        native_setStyle(mNativePaint, style.nativeInt);
446    }
447
448    /**
449     * Return the paint's color. Note that the color is a 32bit value
450     * containing alpha as well as r,g,b. This 32bit value is not premultiplied,
451     * meaning that its alpha can be any value, regardless of the values of
452     * r,g,b. See the Color class for more details.
453     *
454     * @return the paint's color (and alpha).
455     */
456    public native int getColor();
457
458    /**
459     * Set the paint's color. Note that the color is an int containing alpha
460     * as well as r,g,b. This 32bit value is not premultiplied, meaning that
461     * its alpha can be any value, regardless of the values of r,g,b.
462     * See the Color class for more details.
463     *
464     * @param color The new color (including alpha) to set in the paint.
465     */
466    public native void setColor(int color);
467
468    /**
469     * Helper to getColor() that just returns the color's alpha value. This is
470     * the same as calling getColor() >>> 24. It always returns a value between
471     * 0 (completely transparent) and 255 (completely opaque).
472     *
473     * @return the alpha component of the paint's color.
474     */
475    public native int getAlpha();
476
477    /**
478     * Helper to setColor(), that only assigns the color's alpha value,
479     * leaving its r,g,b values unchanged. Results are undefined if the alpha
480     * value is outside of the range [0..255]
481     *
482     * @param a set the alpha component [0..255] of the paint's color.
483     */
484    public native void setAlpha(int a);
485
486    /**
487     * Helper to setColor(), that takes a,r,g,b and constructs the color int
488     *
489     * @param a The new alpha component (0..255) of the paint's color.
490     * @param r The new red component (0..255) of the paint's color.
491     * @param g The new green component (0..255) of the paint's color.
492     * @param b The new blue component (0..255) of the paint's color.
493     */
494    public void setARGB(int a, int r, int g, int b) {
495        setColor((a << 24) | (r << 16) | (g << 8) | b);
496    }
497
498    /**
499     * Return the width for stroking.
500     * <p />
501     * A value of 0 strokes in hairline mode.
502     * Hairlines always draws a single pixel independent of the canva's matrix.
503     *
504     * @return the paint's stroke width, used whenever the paint's style is
505     *         Stroke or StrokeAndFill.
506     */
507    public native float getStrokeWidth();
508
509    /**
510     * Set the width for stroking.
511     * Pass 0 to stroke in hairline mode.
512     * Hairlines always draws a single pixel independent of the canva's matrix.
513     *
514     * @param width set the paint's stroke width, used whenever the paint's
515     *              style is Stroke or StrokeAndFill.
516     */
517    public native void setStrokeWidth(float width);
518
519    /**
520     * Return the paint's stroke miter value. Used to control the behavior
521     * of miter joins when the joins angle is sharp.
522     *
523     * @return the paint's miter limit, used whenever the paint's style is
524     *         Stroke or StrokeAndFill.
525     */
526    public native float getStrokeMiter();
527
528    /**
529     * Set the paint's stroke miter value. This is used to control the behavior
530     * of miter joins when the joins angle is sharp. This value must be >= 0.
531     *
532     * @param miter set the miter limit on the paint, used whenever the paint's
533     *              style is Stroke or StrokeAndFill.
534     */
535    public native void setStrokeMiter(float miter);
536
537    /**
538     * Return the paint's Cap, controlling how the start and end of stroked
539     * lines and paths are treated.
540     *
541     * @return the line cap style for the paint, used whenever the paint's
542     *         style is Stroke or StrokeAndFill.
543     */
544    public Cap getStrokeCap() {
545        return sCapArray[native_getStrokeCap(mNativePaint)];
546    }
547
548    /**
549     * Set the paint's Cap.
550     *
551     * @param cap set the paint's line cap style, used whenever the paint's
552     *            style is Stroke or StrokeAndFill.
553     */
554    public void setStrokeCap(Cap cap) {
555        native_setStrokeCap(mNativePaint, cap.nativeInt);
556    }
557
558    /**
559     * Return the paint's stroke join type.
560     *
561     * @return the paint's Join.
562     */
563    public Join getStrokeJoin() {
564        return sJoinArray[native_getStrokeJoin(mNativePaint)];
565    }
566
567    /**
568     * Set the paint's Join.
569     *
570     * @param join set the paint's Join, used whenever the paint's style is
571     *             Stroke or StrokeAndFill.
572     */
573    public void setStrokeJoin(Join join) {
574        native_setStrokeJoin(mNativePaint, join.nativeInt);
575    }
576
577    /**
578     * Applies any/all effects (patheffect, stroking) to src, returning the
579     * result in dst. The result is that drawing src with this paint will be
580     * the same as drawing dst with a default paint (at least from the
581     * geometric perspective).
582     *
583     * @param src input path
584     * @param dst output path (may be the same as src)
585     * @return    true if the path should be filled, or false if it should be
586     *                 drawn with a hairline (width == 0)
587     */
588    public boolean getFillPath(Path src, Path dst) {
589        return native_getFillPath(mNativePaint, src.ni(), dst.ni());
590    }
591
592    /**
593     * Get the paint's shader object.
594     *
595     * @return the paint's shader (or null)
596     */
597    public Shader getShader() {
598        return mShader;
599    }
600
601    /**
602     * Set or clear the shader object.
603     * <p />
604     * Pass null to clear any previous shader.
605     * As a convenience, the parameter passed is also returned.
606     *
607     * @param shader May be null. the new shader to be installed in the paint
608     * @return       shader
609     */
610    public Shader setShader(Shader shader) {
611        int shaderNative = 0;
612        if (shader != null)
613            shaderNative = shader.native_instance;
614        native_setShader(mNativePaint, shaderNative);
615        mShader = shader;
616        return shader;
617    }
618
619    /**
620     * Get the paint's colorfilter (maybe be null).
621     *
622     * @return the paint's colorfilter (maybe be null)
623     */
624    public ColorFilter getColorFilter() {
625        return mColorFilter;
626    }
627
628    /**
629     * Set or clear the paint's colorfilter, returning the parameter.
630     *
631     * @param filter May be null. The new filter to be installed in the paint
632     * @return       filter
633     */
634    public ColorFilter setColorFilter(ColorFilter filter) {
635        int filterNative = 0;
636        if (filter != null)
637            filterNative = filter.native_instance;
638        native_setColorFilter(mNativePaint, filterNative);
639        mColorFilter = filter;
640        return filter;
641    }
642
643    /**
644     * Get the paint's xfermode object.
645     *
646     * @return the paint's xfermode (or null)
647     */
648    public Xfermode getXfermode() {
649        return mXfermode;
650    }
651
652    /**
653     * Set or clear the xfermode object.
654     * <p />
655     * Pass null to clear any previous xfermode.
656     * As a convenience, the parameter passed is also returned.
657     *
658     * @param xfermode May be null. The xfermode to be installed in the paint
659     * @return         xfermode
660     */
661    public Xfermode setXfermode(Xfermode xfermode) {
662        int xfermodeNative = 0;
663        if (xfermode != null)
664            xfermodeNative = xfermode.native_instance;
665        native_setXfermode(mNativePaint, xfermodeNative);
666        mXfermode = xfermode;
667        return xfermode;
668    }
669
670    /**
671     * Get the paint's patheffect object.
672     *
673     * @return the paint's patheffect (or null)
674     */
675    public PathEffect getPathEffect() {
676        return mPathEffect;
677    }
678
679    /**
680     * Set or clear the patheffect object.
681     * <p />
682     * Pass null to clear any previous patheffect.
683     * As a convenience, the parameter passed is also returned.
684     *
685     * @param effect May be null. The patheffect to be installed in the paint
686     * @return       effect
687     */
688    public PathEffect setPathEffect(PathEffect effect) {
689        int effectNative = 0;
690        if (effect != null) {
691            effectNative = effect.native_instance;
692        }
693        native_setPathEffect(mNativePaint, effectNative);
694        mPathEffect = effect;
695        return effect;
696    }
697
698    /**
699     * Get the paint's maskfilter object.
700     *
701     * @return the paint's maskfilter (or null)
702     */
703    public MaskFilter getMaskFilter() {
704        return mMaskFilter;
705    }
706
707    /**
708     * Set or clear the maskfilter object.
709     * <p />
710     * Pass null to clear any previous maskfilter.
711     * As a convenience, the parameter passed is also returned.
712     *
713     * @param maskfilter May be null. The maskfilter to be installed in the
714     *                   paint
715     * @return           maskfilter
716     */
717    public MaskFilter setMaskFilter(MaskFilter maskfilter) {
718        int maskfilterNative = 0;
719        if (maskfilter != null) {
720            maskfilterNative = maskfilter.native_instance;
721        }
722        native_setMaskFilter(mNativePaint, maskfilterNative);
723        mMaskFilter = maskfilter;
724        return maskfilter;
725    }
726
727    /**
728     * Get the paint's typeface object.
729     * <p />
730     * The typeface object identifies which font to use when drawing or
731     * measuring text.
732     *
733     * @return the paint's typeface (or null)
734     */
735    public Typeface getTypeface() {
736        return mTypeface;
737    }
738
739    /**
740     * Set or clear the typeface object.
741     * <p />
742     * Pass null to clear any previous typeface.
743     * As a convenience, the parameter passed is also returned.
744     *
745     * @param typeface May be null. The typeface to be installed in the paint
746     * @return         typeface
747     */
748    public Typeface setTypeface(Typeface typeface) {
749        int typefaceNative = 0;
750        if (typeface != null) {
751            typefaceNative = typeface.native_instance;
752        }
753        native_setTypeface(mNativePaint, typefaceNative);
754        mTypeface = typeface;
755        return typeface;
756    }
757
758    /**
759     * Get the paint's rasterizer (or null).
760     * <p />
761     * The raster controls/modifies how paths/text are turned into alpha masks.
762     *
763     * @return         the paint's rasterizer (or null)
764     */
765    public Rasterizer getRasterizer() {
766        return mRasterizer;
767    }
768
769    /**
770     * Set or clear the rasterizer object.
771     * <p />
772     * Pass null to clear any previous rasterizer.
773     * As a convenience, the parameter passed is also returned.
774     *
775     * @param rasterizer May be null. The new rasterizer to be installed in
776     *                   the paint.
777     * @return           rasterizer
778     */
779    public Rasterizer setRasterizer(Rasterizer rasterizer) {
780        int rasterizerNative = 0;
781        if (rasterizer != null) {
782            rasterizerNative = rasterizer.native_instance;
783        }
784        native_setRasterizer(mNativePaint, rasterizerNative);
785        mRasterizer = rasterizer;
786        return rasterizer;
787    }
788
789    /**
790     * Temporary API to expose layer drawing. This draws a shadow layer below
791     * the main layer, with the specified offset and color, and blur radius.
792     * If radius is 0, then the shadow layer is removed.
793     */
794    public native void setShadowLayer(float radius, float dx, float dy,
795                                      int color);
796
797    /**
798     * Temporary API to clear the shadow layer.
799     */
800    public void clearShadowLayer() {
801        setShadowLayer(0, 0, 0, 0);
802    }
803
804    /**
805     * Return the paint's Align value for drawing text. This controls how the
806     * text is positioned relative to its origin. LEFT align means that all of
807     * the text will be drawn to the right of its origin (i.e. the origin
808     * specifieds the LEFT edge of the text) and so on.
809     *
810     * @return the paint's Align value for drawing text.
811     */
812    public Align getTextAlign() {
813        return sAlignArray[native_getTextAlign(mNativePaint)];
814    }
815
816    /**
817     * Set the paint's text alignment. This controls how the
818     * text is positioned relative to its origin. LEFT align means that all of
819     * the text will be drawn to the right of its origin (i.e. the origin
820     * specifieds the LEFT edge of the text) and so on.
821     *
822     * @param align set the paint's Align value for drawing text.
823     */
824    public void setTextAlign(Align align) {
825        native_setTextAlign(mNativePaint, align.nativeInt);
826    }
827
828    /**
829     * Return the paint's text size.
830     *
831     * @return the paint's text size.
832     */
833    public native float getTextSize();
834
835    /**
836     * Set the paint's text size. This value must be > 0
837     *
838     * @param textSize set the paint's text size.
839     */
840    public native void setTextSize(float textSize);
841
842    /**
843     * Return the paint's horizontal scale factor for text. The default value
844     * is 1.0.
845     *
846     * @return the paint's scale factor in X for drawing/measuring text
847     */
848    public native float getTextScaleX();
849
850    /**
851     * Set the paint's horizontal scale factor for text. The default value
852     * is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will
853     * stretch the text narrower.
854     *
855     * @param scaleX set the paint's scale in X for drawing/measuring text.
856     */
857    public native void setTextScaleX(float scaleX);
858
859    /**
860     * Return the paint's horizontal skew factor for text. The default value
861     * is 0.
862     *
863     * @return         the paint's skew factor in X for drawing text.
864     */
865    public native float getTextSkewX();
866
867    /**
868     * Set the paint's horizontal skew factor for text. The default value
869     * is 0. For approximating oblique text, use values around -0.25.
870     *
871     * @param skewX set the paint's skew factor in X for drawing text.
872     */
873    public native void setTextSkewX(float skewX);
874
875    /**
876     * Return the distance above (negative) the baseline (ascent) based on the
877     * current typeface and text size.
878     *
879     * @return the distance above (negative) the baseline (ascent) based on the
880     *         current typeface and text size.
881     */
882    public native float ascent();
883
884    /**
885     * Return the distance below (positive) the baseline (descent) based on the
886     * current typeface and text size.
887     *
888     * @return the distance below (positive) the baseline (descent) based on
889     *         the current typeface and text size.
890     */
891    public native float descent();
892
893    /**
894     * Class that describes the various metrics for a font at a given text size.
895     * Remember, Y values increase going down, so those values will be positive,
896     * and values that measure distances going up will be negative. This class
897     * is returned by getFontMetrics().
898     */
899    public static class FontMetrics {
900        /**
901         * The maximum distance above the baseline for the tallest glyph in
902         * the font at a given text size.
903         */
904        public float   top;
905        /**
906         * The recommended distance above the baseline for singled spaced text.
907         */
908        public float   ascent;
909        /**
910         * The recommended distance below the baseline for singled spaced text.
911         */
912        public float   descent;
913        /**
914         * The maximum distance below the baseline for the lowest glyph in
915         * the font at a given text size.
916         */
917        public float   bottom;
918        /**
919         * The recommended additional space to add between lines of text.
920         */
921        public float   leading;
922    }
923
924    /**
925     * Return the font's recommended interline spacing, given the Paint's
926     * settings for typeface, textSize, etc. If metrics is not null, return the
927     * fontmetric values in it.
928     *
929     * @param metrics If this object is not null, its fields are filled with
930     *                the appropriate values given the paint's text attributes.
931     * @return the font's recommended interline spacing.
932     */
933    public native float getFontMetrics(FontMetrics metrics);
934
935    /**
936     * Allocates a new FontMetrics object, and then calls getFontMetrics(fm)
937     * with it, returning the object.
938     */
939    public FontMetrics getFontMetrics() {
940        FontMetrics fm = new FontMetrics();
941        getFontMetrics(fm);
942        return fm;
943    }
944
945    /**
946     * Convenience method for callers that want to have FontMetrics values as
947     * integers.
948     */
949    public static class FontMetricsInt {
950        public int   top;
951        public int   ascent;
952        public int   descent;
953        public int   bottom;
954        public int   leading;
955
956        @Override public String toString() {
957            return "FontMetricsInt: top=" + top + " ascent=" + ascent +
958                    " descent=" + descent + " bottom=" + bottom +
959                    " leading=" + leading;
960        }
961    }
962
963    /**
964     * Return the font's interline spacing, given the Paint's settings for
965     * typeface, textSize, etc. If metrics is not null, return the fontmetric
966     * values in it. Note: all values have been converted to integers from
967     * floats, in such a way has to make the answers useful for both spacing
968     * and clipping. If you want more control over the rounding, call
969     * getFontMetrics().
970     *
971     * @return the font's interline spacing.
972     */
973    public native int getFontMetricsInt(FontMetricsInt fmi);
974
975    public FontMetricsInt getFontMetricsInt() {
976        FontMetricsInt fm = new FontMetricsInt();
977        getFontMetricsInt(fm);
978        return fm;
979    }
980
981    /**
982     * Return the recommend line spacing based on the current typeface and
983     * text size.
984     *
985     * @return  recommend line spacing based on the current typeface and
986     *          text size.
987     */
988    public float getFontSpacing() {
989        return getFontMetrics(null);
990    }
991
992    /**
993     * Return the width of the text.
994     *
995     * @param text  The text to measure
996     * @param index The index of the first character to start measuring
997     * @param count THe number of characters to measure, beginning with start
998     * @return      The width of the text
999     */
1000    public float measureText(char[] text, int index, int count) {
1001        if (!mHasCompatScaling) return native_measureText(text, index, count);
1002        final float oldSize = getTextSize();
1003        setTextSize(oldSize*mCompatScaling);
1004        float w = native_measureText(text, index, count);
1005        setTextSize(oldSize);
1006        return w*mInvCompatScaling;
1007    }
1008
1009    private native float native_measureText(char[] text, int index, int count);
1010
1011    /**
1012     * Return the width of the text.
1013     *
1014     * @param text  The text to measure
1015     * @param start The index of the first character to start measuring
1016     * @param end   1 beyond the index of the last character to measure
1017     * @return      The width of the text
1018     */
1019    public float measureText(String text, int start, int end) {
1020        if (!mHasCompatScaling) return native_measureText(text, start, end);
1021        final float oldSize = getTextSize();
1022        setTextSize(oldSize*mCompatScaling);
1023        float w = native_measureText(text, start, end);
1024        setTextSize(oldSize);
1025        return w*mInvCompatScaling;
1026    }
1027
1028    private native float native_measureText(String text, int start, int end);
1029
1030    /**
1031     * Return the width of the text.
1032     *
1033     * @param text  The text to measure
1034     * @return      The width of the text
1035     */
1036    public float measureText(String text) {
1037        if (!mHasCompatScaling) return native_measureText(text);
1038        final float oldSize = getTextSize();
1039        setTextSize(oldSize*mCompatScaling);
1040        float w = native_measureText(text);
1041        setTextSize(oldSize);
1042        return w*mInvCompatScaling;
1043    }
1044
1045    private native float native_measureText(String text);
1046
1047    /**
1048     * Return the width of the text.
1049     *
1050     * @param text  The text to measure
1051     * @param start The index of the first character to start measuring
1052     * @param end   1 beyond the index of the last character to measure
1053     * @return      The width of the text
1054     */
1055    public float measureText(CharSequence text, int start, int end) {
1056        if (text instanceof String) {
1057            return measureText((String)text, start, end);
1058        }
1059        if (text instanceof SpannedString ||
1060            text instanceof SpannableString) {
1061            return measureText(text.toString(), start, end);
1062        }
1063        if (text instanceof GraphicsOperations) {
1064            return ((GraphicsOperations)text).measureText(start, end, this);
1065        }
1066
1067        char[] buf = TemporaryBuffer.obtain(end - start);
1068        TextUtils.getChars(text, start, end, buf, 0);
1069        float result = measureText(buf, 0, end - start);
1070        TemporaryBuffer.recycle(buf);
1071        return result;
1072    }
1073
1074    /**
1075     * Measure the text, stopping early if the measured width exceeds maxWidth.
1076     * Return the number of chars that were measured, and if measuredWidth is
1077     * not null, return in it the actual width measured.
1078     *
1079     * @param text  The text to measure
1080     * @param index The offset into text to begin measuring at
1081     * @param count The number of maximum number of entries to measure. If count
1082     *              is negative, then the characters before index are measured
1083     *              in reverse order. This allows for measuring the end of
1084     *              string.
1085     * @param maxWidth The maximum width to accumulate.
1086     * @param measuredWidth Optional. If not null, returns the actual width
1087     *                     measured.
1088     * @return The number of chars that were measured. Will always be <=
1089     *         abs(count).
1090     */
1091    public int breakText(char[] text, int index, int count,
1092                                float maxWidth, float[] measuredWidth) {
1093        if (!mHasCompatScaling) {
1094            return native_breakText(text, index, count, maxWidth, measuredWidth);
1095        }
1096        final float oldSize = getTextSize();
1097        setTextSize(oldSize*mCompatScaling);
1098        int res = native_breakText(text, index, count, maxWidth*mCompatScaling,
1099                measuredWidth);
1100        setTextSize(oldSize);
1101        if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
1102        return res;
1103    }
1104
1105    private native int native_breakText(char[] text, int index, int count,
1106                                        float maxWidth, float[] measuredWidth);
1107
1108    /**
1109     * Measure the text, stopping early if the measured width exceeds maxWidth.
1110     * Return the number of chars that were measured, and if measuredWidth is
1111     * not null, return in it the actual width measured.
1112     *
1113     * @param text  The text to measure
1114     * @param start The offset into text to begin measuring at
1115     * @param end   The end of the text slice to measure.
1116     * @param measureForwards If true, measure forwards, starting at start.
1117     *                        Otherwise, measure backwards, starting with end.
1118     * @param maxWidth The maximum width to accumulate.
1119     * @param measuredWidth Optional. If not null, returns the actual width
1120     *                     measured.
1121     * @return The number of chars that were measured. Will always be <=
1122     *         abs(end - start).
1123     */
1124    public int breakText(CharSequence text, int start, int end,
1125                         boolean measureForwards,
1126                         float maxWidth, float[] measuredWidth) {
1127        if (start == 0 && text instanceof String && end == text.length()) {
1128            return breakText((String) text, measureForwards, maxWidth,
1129                             measuredWidth);
1130        }
1131
1132        char[] buf = TemporaryBuffer.obtain(end - start);
1133        int result;
1134
1135        TextUtils.getChars(text, start, end, buf, 0);
1136
1137        if (measureForwards) {
1138            result = breakText(buf, 0, end - start, maxWidth, measuredWidth);
1139        } else {
1140            result = breakText(buf, 0, -(end - start), maxWidth, measuredWidth);
1141        }
1142
1143        TemporaryBuffer.recycle(buf);
1144        return result;
1145    }
1146
1147    /**
1148     * Measure the text, stopping early if the measured width exceeds maxWidth.
1149     * Return the number of chars that were measured, and if measuredWidth is
1150     * not null, return in it the actual width measured.
1151     *
1152     * @param text  The text to measure
1153     * @param measureForwards If true, measure forwards, starting with the
1154     *                        first character in the string. Otherwise,
1155     *                        measure backwards, starting with the
1156     *                        last character in the string.
1157     * @param maxWidth The maximum width to accumulate.
1158     * @param measuredWidth Optional. If not null, returns the actual width
1159     *                     measured.
1160     * @return The number of chars that were measured. Will always be <=
1161     *         abs(count).
1162     */
1163    public int breakText(String text, boolean measureForwards,
1164                                float maxWidth, float[] measuredWidth) {
1165        if (!mHasCompatScaling) {
1166            return native_breakText(text, measureForwards, maxWidth, measuredWidth);
1167        }
1168        final float oldSize = getTextSize();
1169        setTextSize(oldSize*mCompatScaling);
1170        int res = native_breakText(text, measureForwards, maxWidth*mCompatScaling,
1171                measuredWidth);
1172        setTextSize(oldSize);
1173        if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
1174        return res;
1175    }
1176
1177    private native int native_breakText(String text, boolean measureForwards,
1178                                        float maxWidth, float[] measuredWidth);
1179
1180    /**
1181     * Return the advance widths for the characters in the string.
1182     *
1183     * @param text     The text to measure
1184     * @param index    The index of the first char to to measure
1185     * @param count    The number of chars starting with index to measure
1186     * @param widths   array to receive the advance widths of the characters.
1187     *                 Must be at least a large as count.
1188     * @return         the actual number of widths returned.
1189     */
1190    public int getTextWidths(char[] text, int index, int count,
1191                             float[] widths) {
1192        if ((index | count) < 0 || index + count > text.length
1193                || count > widths.length) {
1194            throw new ArrayIndexOutOfBoundsException();
1195        }
1196
1197        if (!mHasCompatScaling) {
1198            return native_getTextWidths(mNativePaint, text, index, count, widths);
1199        }
1200        final float oldSize = getTextSize();
1201        setTextSize(oldSize*mCompatScaling);
1202        int res = native_getTextWidths(mNativePaint, text, index, count, widths);
1203        setTextSize(oldSize);
1204        for (int i=0; i<res; i++) {
1205            widths[i] *= mInvCompatScaling;
1206        }
1207        return res;
1208    }
1209
1210    /**
1211     * Return the advance widths for the characters in the string.
1212     *
1213     * @param text     The text to measure
1214     * @param start    The index of the first char to to measure
1215     * @param end      The end of the text slice to measure
1216     * @param widths   array to receive the advance widths of the characters.
1217     *                 Must be at least a large as (end - start).
1218     * @return         the actual number of widths returned.
1219     */
1220    public int getTextWidths(CharSequence text, int start, int end,
1221                             float[] widths) {
1222        if (text instanceof String) {
1223            return getTextWidths((String) text, start, end, widths);
1224        }
1225        if (text instanceof SpannedString ||
1226            text instanceof SpannableString) {
1227            return getTextWidths(text.toString(), start, end, widths);
1228        }
1229        if (text instanceof GraphicsOperations) {
1230            return ((GraphicsOperations) text).getTextWidths(start, end,
1231                                                                 widths, this);
1232        }
1233
1234        char[] buf = TemporaryBuffer.obtain(end - start);
1235    	TextUtils.getChars(text, start, end, buf, 0);
1236    	int result = getTextWidths(buf, 0, end - start, widths);
1237        TemporaryBuffer.recycle(buf);
1238    	return result;
1239    }
1240
1241    /**
1242     * Return the advance widths for the characters in the string.
1243     *
1244     * @param text   The text to measure
1245     * @param start  The index of the first char to to measure
1246     * @param end    The end of the text slice to measure
1247     * @param widths array to receive the advance widths of the characters.
1248     *               Must be at least a large as the text.
1249     * @return       the number of unichars in the specified text.
1250     */
1251    public int getTextWidths(String text, int start, int end, float[] widths) {
1252        if ((start | end | (end - start) | (text.length() - end)) < 0) {
1253            throw new IndexOutOfBoundsException();
1254        }
1255        if (end - start > widths.length) {
1256            throw new ArrayIndexOutOfBoundsException();
1257        }
1258
1259        if (!mHasCompatScaling) {
1260            return native_getTextWidths(mNativePaint, text, start, end, widths);
1261        }
1262        final float oldSize = getTextSize();
1263        setTextSize(oldSize*mCompatScaling);
1264        int res = native_getTextWidths(mNativePaint, text, start, end, widths);
1265        setTextSize(oldSize);
1266        for (int i=0; i<res; i++) {
1267            widths[i] *= mInvCompatScaling;
1268        }
1269        return res;
1270    }
1271
1272    /**
1273     * Return the advance widths for the characters in the string.
1274     *
1275     * @param text   The text to measure
1276     * @param widths array to receive the advance widths of the characters.
1277     *               Must be at least a large as the text.
1278     * @return       the number of unichars in the specified text.
1279     */
1280    public int getTextWidths(String text, float[] widths) {
1281        return getTextWidths(text, 0, text.length(), widths);
1282    }
1283
1284    /**
1285     * Return the path (outline) for the specified text.
1286     * Note: just like Canvas.drawText, this will respect the Align setting in
1287     * the paint.
1288     *
1289     * @param text     The text to retrieve the path from
1290     * @param index    The index of the first character in text
1291     * @param count    The number of characterss starting with index
1292     * @param x        The x coordinate of the text's origin
1293     * @param y        The y coordinate of the text's origin
1294     * @param path     The path to receive the data describing the text. Must
1295     *                 be allocated by the caller.
1296     */
1297    public void getTextPath(char[] text, int index, int count,
1298                            float x, float y, Path path) {
1299        if ((index | count) < 0 || index + count > text.length) {
1300            throw new ArrayIndexOutOfBoundsException();
1301        }
1302        native_getTextPath(mNativePaint, text, index, count, x, y, path.ni());
1303    }
1304
1305    /**
1306     * Return the path (outline) for the specified text.
1307     * Note: just like Canvas.drawText, this will respect the Align setting
1308     * in the paint.
1309     *
1310     * @param text  The text to retrieve the path from
1311     * @param start The first character in the text
1312     * @param end   1 past the last charcter in the text
1313     * @param x     The x coordinate of the text's origin
1314     * @param y     The y coordinate of the text's origin
1315     * @param path  The path to receive the data describing the text. Must
1316     *              be allocated by the caller.
1317     */
1318    public void getTextPath(String text, int start, int end,
1319                            float x, float y, Path path) {
1320        if ((start | end | (end - start) | (text.length() - end)) < 0) {
1321            throw new IndexOutOfBoundsException();
1322        }
1323        native_getTextPath(mNativePaint, text, start, end, x, y, path.ni());
1324    }
1325
1326    /**
1327     * Return in bounds (allocated by the caller) the smallest rectangle that
1328     * encloses all of the characters, with an implied origin at (0,0).
1329     *
1330     * @param text  String to measure and return its bounds
1331     * @param start Index of the first char in the string to measure
1332     * @param end   1 past the last char in the string measure
1333     * @param bounds Returns the unioned bounds of all the text. Must be
1334     *               allocated by the caller.
1335     */
1336    public void getTextBounds(String text, int start, int end, Rect bounds) {
1337        if ((start | end | (end - start) | (text.length() - end)) < 0) {
1338            throw new IndexOutOfBoundsException();
1339        }
1340        if (bounds == null) {
1341            throw new NullPointerException("need bounds Rect");
1342        }
1343        nativeGetStringBounds(mNativePaint, text, start, end, bounds);
1344    }
1345
1346    /**
1347     * Return in bounds (allocated by the caller) the smallest rectangle that
1348     * encloses all of the characters, with an implied origin at (0,0).
1349     *
1350     * @param text  Array of chars to measure and return their unioned bounds
1351     * @param index Index of the first char in the array to measure
1352     * @param count The number of chars, beginning at index, to measure
1353     * @param bounds Returns the unioned bounds of all the text. Must be
1354     *               allocated by the caller.
1355     */
1356    public void getTextBounds(char[] text, int index, int count, Rect bounds) {
1357        if ((index | count) < 0 || index + count > text.length) {
1358            throw new ArrayIndexOutOfBoundsException();
1359        }
1360        if (bounds == null) {
1361            throw new NullPointerException("need bounds Rect");
1362        }
1363        nativeGetCharArrayBounds(mNativePaint, text, index, count, bounds);
1364    }
1365
1366    protected void finalize() throws Throwable {
1367        finalizer(mNativePaint);
1368    }
1369
1370    private static native int native_init();
1371    private static native int native_initWithPaint(int paint);
1372    private static native void native_reset(int native_object);
1373    private static native void native_set(int native_dst, int native_src);
1374    private static native int native_getStyle(int native_object);
1375    private static native void native_setStyle(int native_object, int style);
1376    private static native int native_getStrokeCap(int native_object);
1377    private static native void native_setStrokeCap(int native_object, int cap);
1378    private static native int native_getStrokeJoin(int native_object);
1379    private static native void native_setStrokeJoin(int native_object,
1380                                                    int join);
1381    private static native boolean native_getFillPath(int native_object,
1382                                                     int src, int dst);
1383    private static native int native_setShader(int native_object, int shader);
1384    private static native int native_setColorFilter(int native_object,
1385                                                    int filter);
1386    private static native int native_setXfermode(int native_object,
1387                                                 int xfermode);
1388    private static native int native_setPathEffect(int native_object,
1389                                                   int effect);
1390    private static native int native_setMaskFilter(int native_object,
1391                                                   int maskfilter);
1392    private static native int native_setTypeface(int native_object,
1393                                                 int typeface);
1394    private static native int native_setRasterizer(int native_object,
1395                                                   int rasterizer);
1396
1397    private static native int native_getTextAlign(int native_object);
1398    private static native void native_setTextAlign(int native_object,
1399                                                   int align);
1400
1401    private static native float native_getFontMetrics(int native_paint,
1402                                                      FontMetrics metrics);
1403    private static native int native_getTextWidths(int native_object,
1404                            char[] text, int index, int count, float[] widths);
1405    private static native int native_getTextWidths(int native_object,
1406                            String text, int start, int end, float[] widths);
1407    private static native void native_getTextPath(int native_object,
1408                char[] text, int index, int count, float x, float y, int path);
1409    private static native void native_getTextPath(int native_object,
1410                String text, int start, int end, float x, float y, int path);
1411    private static native void nativeGetStringBounds(int nativePaint,
1412                                String text, int start, int end, Rect bounds);
1413    private static native void nativeGetCharArrayBounds(int nativePaint,
1414                                char[] text, int index, int count, Rect bounds);
1415    private static native void finalizer(int nativePaint);
1416}
1417
1418