blob: 88ff0e6b3d8964e26ef8dfb0b297669349adb456 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
Doug Feltf47d7402010-04-21 16:01:52 -070019import android.text.GraphicsOperations;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.text.SpannableString;
21import android.text.SpannedString;
Doug Feltf47d7402010-04-21 16:01:52 -070022import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023
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
Romain Guyc7d53492010-06-25 13:41:57 -070030 /**
31 * @hide
32 */
33 public int mNativePaint;
34
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035 private ColorFilter mColorFilter;
36 private MaskFilter mMaskFilter;
37 private PathEffect mPathEffect;
38 private Rasterizer mRasterizer;
39 private Shader mShader;
40 private Typeface mTypeface;
41 private Xfermode mXfermode;
42
Dianne Hackbornafa78962009-09-28 17:33:54 -070043 private boolean mHasCompatScaling;
44 private float mCompatScaling;
45 private float mInvCompatScaling;
Doug Feltf47d7402010-04-21 16:01:52 -070046 /* package */ int mBidiFlags = BIDI_DEFAULT_LTR;
Dianne Hackbornafa78962009-09-28 17:33:54 -070047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 private static final Style[] sStyleArray = {
49 Style.FILL, Style.STROKE, Style.FILL_AND_STROKE
50 };
51 private static final Cap[] sCapArray = {
52 Cap.BUTT, Cap.ROUND, Cap.SQUARE
53 };
54 private static final Join[] sJoinArray = {
55 Join.MITER, Join.ROUND, Join.BEVEL
56 };
57 private static final Align[] sAlignArray = {
58 Align.LEFT, Align.CENTER, Align.RIGHT
59 };
60
61 /** bit mask for the flag enabling antialiasing */
62 public static final int ANTI_ALIAS_FLAG = 0x01;
63 /** bit mask for the flag enabling bitmap filtering */
64 public static final int FILTER_BITMAP_FLAG = 0x02;
65 /** bit mask for the flag enabling dithering */
66 public static final int DITHER_FLAG = 0x04;
67 /** bit mask for the flag enabling underline text */
68 public static final int UNDERLINE_TEXT_FLAG = 0x08;
69 /** bit mask for the flag enabling strike-thru text */
70 public static final int STRIKE_THRU_TEXT_FLAG = 0x10;
71 /** bit mask for the flag enabling fake-bold text */
72 public static final int FAKE_BOLD_TEXT_FLAG = 0x20;
73 /** bit mask for the flag enabling linear-text (no caching) */
74 public static final int LINEAR_TEXT_FLAG = 0x40;
75 /** bit mask for the flag enabling subpixel-text */
76 public static final int SUBPIXEL_TEXT_FLAG = 0x80;
77 /** bit mask for the flag enabling device kerning for text */
78 public static final int DEV_KERN_TEXT_FLAG = 0x100;
79
80 // we use this when we first create a paint
81 private static final int DEFAULT_PAINT_FLAGS = DEV_KERN_TEXT_FLAG;
82
83 /**
Doug Feltf47d7402010-04-21 16:01:52 -070084 * Bidi flag to set LTR paragraph direction.
85 *
86 * @hide
87 */
88 public static final int BIDI_LTR = 0x0;
89
90 /**
91 * Bidi flag to set RTL paragraph direction.
92 *
93 * @hide
94 */
95 public static final int BIDI_RTL = 0x1;
96
97 /**
98 * Bidi flag to detect paragraph direction via heuristics, defaulting to
99 * LTR.
100 *
101 * @hide
102 */
103 public static final int BIDI_DEFAULT_LTR = 0x2;
104
105 /**
106 * Bidi flag to detect paragraph direction via heuristics, defaulting to
107 * RTL.
108 *
109 * @hide
110 */
111 public static final int BIDI_DEFAULT_RTL = 0x3;
112
113 /**
114 * Bidi flag to override direction to all LTR (ignore bidi).
115 *
116 * @hide
117 */
118 public static final int BIDI_FORCE_LTR = 0x4;
119
120 /**
121 * Bidi flag to override direction to all RTL (ignore bidi).
122 *
123 * @hide
124 */
125 public static final int BIDI_FORCE_RTL = 0x5;
126
127 /**
128 * Maximum Bidi flag value.
129 * @hide
130 */
131 private static final int BIDI_MAX_FLAG_VALUE = BIDI_FORCE_RTL;
Doug Felt0c702b82010-05-14 10:55:42 -0700132
Doug Feltf47d7402010-04-21 16:01:52 -0700133 /**
134 * Mask for bidi flags.
135 * @hide
136 */
137 private static final int BIDI_FLAG_MASK = 0x7;
Doug Felt0c702b82010-05-14 10:55:42 -0700138
139 /**
140 * Flag for getTextRunAdvances indicating left-to-right run direction.
141 * @hide
142 */
143 public static final int DIRECTION_LTR = 0;
144
145 /**
146 * Flag for getTextRunAdvances indicating right-to-left run direction.
147 * @hide
148 */
149 public static final int DIRECTION_RTL = 1;
150
151 /**
152 * Option for getTextRunCursor to compute the valid cursor after
153 * offset or the limit of the context, whichever is less.
154 * @hide
155 */
156 public static final int CURSOR_AFTER = 0;
157
158 /**
159 * Option for getTextRunCursor to compute the valid cursor at or after
160 * the offset or the limit of the context, whichever is less.
161 * @hide
162 */
163 public static final int CURSOR_AT_OR_AFTER = 1;
164
165 /**
166 * Option for getTextRunCursor to compute the valid cursor before
167 * offset or the start of the context, whichever is greater.
168 * @hide
169 */
170 public static final int CURSOR_BEFORE = 2;
171
172 /**
173 * Option for getTextRunCursor to compute the valid cursor at or before
174 * offset or the start of the context, whichever is greater.
175 * @hide
176 */
177 public static final int CURSOR_AT_OR_BEFORE = 3;
178
179 /**
180 * Option for getTextRunCursor to return offset if the cursor at offset
181 * is valid, or -1 if it isn't.
182 * @hide
183 */
184 public static final int CURSOR_AT = 4;
185
186 /**
187 * Maximum cursor option value.
188 */
189 private static final int CURSOR_OPT_MAX_VALUE = CURSOR_AT;
190
Doug Feltf47d7402010-04-21 16:01:52 -0700191 /**
192 * The Style specifies if the primitive being drawn is filled, stroked, or
193 * both (in the same color). The default is FILL.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 */
195 public enum Style {
196 /**
197 * Geometry and text drawn with this style will be filled, ignoring all
198 * stroke-related settings in the paint.
199 */
200 FILL (0),
201 /**
202 * Geometry and text drawn with this style will be stroked, respecting
203 * the stroke-related fields on the paint.
204 */
205 STROKE (1),
206 /**
207 * Geometry and text drawn with this style will be both filled and
208 * stroked at the same time, respecting the stroke-related fields on
Mike Reedd404d6f2010-04-14 14:46:46 -0400209 * the paint. This mode can give unexpected results if the geometry
210 * is oriented counter-clockwise. This restriction does not apply to
211 * either FILL or STROKE.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 */
213 FILL_AND_STROKE (2);
214
215 Style(int nativeInt) {
216 this.nativeInt = nativeInt;
217 }
218 final int nativeInt;
219 }
220
221 /**
222 * The Cap specifies the treatment for the beginning and ending of
223 * stroked lines and paths. The default is BUTT.
224 */
225 public enum Cap {
226 /**
227 * The stroke ends with the path, and does not project beyond it.
228 */
229 BUTT (0),
230 /**
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700231 * The stroke projects out as a semicircle, with the center at the
232 * end of the path.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 */
234 ROUND (1),
235 /**
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -0700236 * The stroke projects out as a square, with the center at the end
237 * of the path.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 */
239 SQUARE (2);
240
241 private Cap(int nativeInt) {
242 this.nativeInt = nativeInt;
243 }
244 final int nativeInt;
245 }
246
247 /**
248 * The Join specifies the treatment where lines and curve segments
249 * join on a stroked path. The default is MITER.
250 */
251 public enum Join {
252 /**
253 * The outer edges of a join meet at a sharp angle
254 */
255 MITER (0),
256 /**
257 * The outer edges of a join meet in a circular arc.
258 */
259 ROUND (1),
260 /**
261 * The outer edges of a join meet with a straight line
262 */
263 BEVEL (2);
264
265 private Join(int nativeInt) {
266 this.nativeInt = nativeInt;
267 }
268 final int nativeInt;
269 }
270
271 /**
272 * Align specifies how drawText aligns its text relative to the
273 * [x,y] coordinates. The default is LEFT.
274 */
275 public enum Align {
276 /**
277 * The text is drawn to the right of the x,y origin
278 */
279 LEFT (0),
280 /**
281 * The text is drawn centered horizontally on the x,y origin
282 */
283 CENTER (1),
284 /**
285 * The text is drawn to the left of the x,y origin
286 */
287 RIGHT (2);
288
289 private Align(int nativeInt) {
290 this.nativeInt = nativeInt;
291 }
292 final int nativeInt;
293 }
294
295 /**
296 * Create a new paint with default settings.
297 */
298 public Paint() {
299 this(0);
300 }
301
302 /**
303 * Create a new paint with the specified flags. Use setFlags() to change
304 * these after the paint is created.
305 *
306 * @param flags initial flag bits, as if they were passed via setFlags().
307 */
308 public Paint(int flags) {
309 mNativePaint = native_init();
310 setFlags(flags | DEFAULT_PAINT_FLAGS);
Dianne Hackbornafa78962009-09-28 17:33:54 -0700311 mCompatScaling = mInvCompatScaling = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 }
313
314 /**
315 * Create a new paint, initialized with the attributes in the specified
316 * paint parameter.
317 *
318 * @param paint Existing paint used to initialized the attributes of the
319 * new paint.
320 */
321 public Paint(Paint paint) {
322 mNativePaint = native_initWithPaint(paint.mNativePaint);
Dianne Hackbornafa78962009-09-28 17:33:54 -0700323 mHasCompatScaling = paint.mHasCompatScaling;
324 mCompatScaling = paint.mCompatScaling;
325 mInvCompatScaling = paint.mInvCompatScaling;
Doug Feltf47d7402010-04-21 16:01:52 -0700326 mBidiFlags = paint.mBidiFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 }
328
329 /** Restores the paint to its default settings. */
330 public void reset() {
331 native_reset(mNativePaint);
332 setFlags(DEFAULT_PAINT_FLAGS);
Dianne Hackbornafa78962009-09-28 17:33:54 -0700333 mHasCompatScaling = false;
334 mCompatScaling = mInvCompatScaling = 1;
Doug Feltf47d7402010-04-21 16:01:52 -0700335 mBidiFlags = BIDI_DEFAULT_LTR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 }
337
338 /**
339 * Copy the fields from src into this paint. This is equivalent to calling
340 * get() on all of the src fields, and calling the corresponding set()
341 * methods on this.
342 */
343 public void set(Paint src) {
344 if (this != src) {
345 // copy over the native settings
346 native_set(mNativePaint, src.mNativePaint);
347 // copy over our java settings
348 mColorFilter = src.mColorFilter;
349 mMaskFilter = src.mMaskFilter;
350 mPathEffect = src.mPathEffect;
351 mRasterizer = src.mRasterizer;
352 mShader = src.mShader;
353 mTypeface = src.mTypeface;
354 mXfermode = src.mXfermode;
Dianne Hackbornafa78962009-09-28 17:33:54 -0700355 mHasCompatScaling = src.mHasCompatScaling;
356 mCompatScaling = src.mCompatScaling;
357 mInvCompatScaling = src.mInvCompatScaling;
Doug Feltf47d7402010-04-21 16:01:52 -0700358 mBidiFlags = src.mBidiFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 }
360 }
361
Dianne Hackbornafa78962009-09-28 17:33:54 -0700362 /** @hide */
363 public void setCompatibilityScaling(float factor) {
364 if (factor == 1.0) {
365 mHasCompatScaling = false;
366 mCompatScaling = mInvCompatScaling = 1.0f;
367 } else {
368 mHasCompatScaling = true;
369 mCompatScaling = factor;
370 mInvCompatScaling = 1.0f/factor;
371 }
372 }
Doug Feltf47d7402010-04-21 16:01:52 -0700373
374 /**
375 * Return the bidi flags on the paint.
376 *
377 * @return the bidi flags on the paint
378 * @hide
379 */
380 public int getBidiFlags() {
381 return mBidiFlags;
382 }
383
384 /**
385 * Set the bidi flags on the paint.
386 * @hide
387 */
388 public void setBidiFlags(int flags) {
389 // only flag value is the 3-bit BIDI control setting
390 flags &= BIDI_FLAG_MASK;
391 if (flags > BIDI_MAX_FLAG_VALUE) {
392 throw new IllegalArgumentException("unknown bidi flag: " + flags);
393 }
394 mBidiFlags = flags;
395 }
396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800397 /**
398 * Return the paint's flags. Use the Flag enum to test flag values.
Doug Feltf47d7402010-04-21 16:01:52 -0700399 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 * @return the paint's flags (see enums ending in _Flag for bit masks)
401 */
402 public native int getFlags();
403
404 /**
405 * Set the paint's flags. Use the Flag enum to specific flag values.
406 *
407 * @param flags The new flag bits for the paint
408 */
409 public native void setFlags(int flags);
410
411 /**
412 * Helper for getFlags(), returning true if ANTI_ALIAS_FLAG bit is set
413 * AntiAliasing smooths out the edges of what is being drawn, but is has
414 * no impact on the interior of the shape. See setDither() and
415 * setFilterBitmap() to affect how colors are treated.
416 *
417 * @return true if the antialias bit is set in the paint's flags.
418 */
419 public final boolean isAntiAlias() {
420 return (getFlags() & ANTI_ALIAS_FLAG) != 0;
421 }
422
423 /**
424 * Helper for setFlags(), setting or clearing the ANTI_ALIAS_FLAG bit
425 * AntiAliasing smooths out the edges of what is being drawn, but is has
426 * no impact on the interior of the shape. See setDither() and
427 * setFilterBitmap() to affect how colors are treated.
428 *
429 * @param aa true to set the antialias bit in the flags, false to clear it
430 */
431 public native void setAntiAlias(boolean aa);
432
433 /**
434 * Helper for getFlags(), returning true if DITHER_FLAG bit is set
435 * Dithering affects how colors that are higher precision than the device
436 * are down-sampled. No dithering is generally faster, but higher precision
437 * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to
438 * distribute the error inherent in this process, to reduce the visual
439 * artifacts.
440 *
441 * @return true if the dithering bit is set in the paint's flags.
442 */
443 public final boolean isDither() {
444 return (getFlags() & DITHER_FLAG) != 0;
445 }
446
447 /**
448 * Helper for setFlags(), setting or clearing the DITHER_FLAG bit
449 * Dithering affects how colors that are higher precision than the device
450 * are down-sampled. No dithering is generally faster, but higher precision
451 * colors are just truncated down (e.g. 8888 -> 565). Dithering tries to
452 * distribute the error inherent in this process, to reduce the visual
453 * artifacts.
454 *
455 * @param dither true to set the dithering bit in flags, false to clear it
456 */
457 public native void setDither(boolean dither);
458
459 /**
460 * Helper for getFlags(), returning true if LINEAR_TEXT_FLAG bit is set
461 *
462 * @return true if the lineartext bit is set in the paint's flags
463 */
464 public final boolean isLinearText() {
465 return (getFlags() & LINEAR_TEXT_FLAG) != 0;
466 }
467
468 /**
469 * Helper for setFlags(), setting or clearing the LINEAR_TEXT_FLAG bit
470 *
471 * @param linearText true to set the linearText bit in the paint's flags,
472 * false to clear it.
473 */
474 public native void setLinearText(boolean linearText);
475
476 /**
477 * Helper for getFlags(), returning true if SUBPIXEL_TEXT_FLAG bit is set
478 *
479 * @return true if the subpixel bit is set in the paint's flags
480 */
481 public final boolean isSubpixelText() {
482 return (getFlags() & SUBPIXEL_TEXT_FLAG) != 0;
483 }
484
485 /**
486 * Helper for setFlags(), setting or clearing the SUBPIXEL_TEXT_FLAG bit
487 *
488 * @param subpixelText true to set the subpixelText bit in the paint's
489 * flags, false to clear it.
490 */
491 public native void setSubpixelText(boolean subpixelText);
492
493 /**
494 * Helper for getFlags(), returning true if UNDERLINE_TEXT_FLAG bit is set
495 *
496 * @return true if the underlineText bit is set in the paint's flags.
497 */
498 public final boolean isUnderlineText() {
499 return (getFlags() & UNDERLINE_TEXT_FLAG) != 0;
500 }
501
502 /**
503 * Helper for setFlags(), setting or clearing the UNDERLINE_TEXT_FLAG bit
504 *
505 * @param underlineText true to set the underlineText bit in the paint's
506 * flags, false to clear it.
507 */
508 public native void setUnderlineText(boolean underlineText);
509
510 /**
511 * Helper for getFlags(), returning true if STRIKE_THRU_TEXT_FLAG bit is set
512 *
513 * @return true if the strikeThruText bit is set in the paint's flags.
514 */
515 public final boolean isStrikeThruText() {
516 return (getFlags() & STRIKE_THRU_TEXT_FLAG) != 0;
517 }
518
519 /**
520 * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit
521 *
522 * @param strikeThruText true to set the strikeThruText bit in the paint's
523 * flags, false to clear it.
524 */
525 public native void setStrikeThruText(boolean strikeThruText);
526
527 /**
528 * Helper for getFlags(), returning true if FAKE_BOLD_TEXT_FLAG bit is set
529 *
530 * @return true if the fakeBoldText bit is set in the paint's flags.
531 */
532 public final boolean isFakeBoldText() {
533 return (getFlags() & FAKE_BOLD_TEXT_FLAG) != 0;
534 }
535
536 /**
537 * Helper for setFlags(), setting or clearing the STRIKE_THRU_TEXT_FLAG bit
538 *
539 * @param fakeBoldText true to set the fakeBoldText bit in the paint's
540 * flags, false to clear it.
541 */
542 public native void setFakeBoldText(boolean fakeBoldText);
543
544 /**
545 * Whether or not the bitmap filter is activated.
546 * Filtering affects the sampling of bitmaps when they are transformed.
547 * Filtering does not affect how the colors in the bitmap are converted into
548 * device pixels. That is dependent on dithering and xfermodes.
549 *
550 * @see #setFilterBitmap(boolean) setFilterBitmap()
551 */
552 public final boolean isFilterBitmap() {
553 return (getFlags() & FILTER_BITMAP_FLAG) != 0;
554 }
555
556 /**
557 * Helper for setFlags(), setting or clearing the FILTER_BITMAP_FLAG bit.
558 * Filtering affects the sampling of bitmaps when they are transformed.
559 * Filtering does not affect how the colors in the bitmap are converted into
560 * device pixels. That is dependent on dithering and xfermodes.
561 *
562 * @param filter true to set the FILTER_BITMAP_FLAG bit in the paint's
563 * flags, false to clear it.
564 */
565 public native void setFilterBitmap(boolean filter);
566
567 /**
568 * Return the paint's style, used for controlling how primitives'
569 * geometries are interpreted (except for drawBitmap, which always assumes
570 * FILL_STYLE).
571 *
572 * @return the paint's style setting (Fill, Stroke, StrokeAndFill)
573 */
574 public Style getStyle() {
575 return sStyleArray[native_getStyle(mNativePaint)];
576 }
577
578 /**
579 * Set the paint's style, used for controlling how primitives'
580 * geometries are interpreted (except for drawBitmap, which always assumes
581 * Fill).
582 *
583 * @param style The new style to set in the paint
584 */
585 public void setStyle(Style style) {
586 native_setStyle(mNativePaint, style.nativeInt);
587 }
588
589 /**
590 * Return the paint's color. Note that the color is a 32bit value
591 * containing alpha as well as r,g,b. This 32bit value is not premultiplied,
592 * meaning that its alpha can be any value, regardless of the values of
593 * r,g,b. See the Color class for more details.
594 *
595 * @return the paint's color (and alpha).
596 */
597 public native int getColor();
598
599 /**
600 * Set the paint's color. Note that the color is an int containing alpha
601 * as well as r,g,b. This 32bit value is not premultiplied, meaning that
602 * its alpha can be any value, regardless of the values of r,g,b.
603 * See the Color class for more details.
604 *
605 * @param color The new color (including alpha) to set in the paint.
606 */
607 public native void setColor(int color);
608
609 /**
610 * Helper to getColor() that just returns the color's alpha value. This is
611 * the same as calling getColor() >>> 24. It always returns a value between
612 * 0 (completely transparent) and 255 (completely opaque).
613 *
614 * @return the alpha component of the paint's color.
615 */
616 public native int getAlpha();
617
618 /**
619 * Helper to setColor(), that only assigns the color's alpha value,
620 * leaving its r,g,b values unchanged. Results are undefined if the alpha
621 * value is outside of the range [0..255]
622 *
623 * @param a set the alpha component [0..255] of the paint's color.
624 */
625 public native void setAlpha(int a);
626
627 /**
628 * Helper to setColor(), that takes a,r,g,b and constructs the color int
629 *
630 * @param a The new alpha component (0..255) of the paint's color.
631 * @param r The new red component (0..255) of the paint's color.
632 * @param g The new green component (0..255) of the paint's color.
633 * @param b The new blue component (0..255) of the paint's color.
634 */
635 public void setARGB(int a, int r, int g, int b) {
636 setColor((a << 24) | (r << 16) | (g << 8) | b);
637 }
638
639 /**
640 * Return the width for stroking.
641 * <p />
642 * A value of 0 strokes in hairline mode.
643 * Hairlines always draws a single pixel independent of the canva's matrix.
644 *
645 * @return the paint's stroke width, used whenever the paint's style is
646 * Stroke or StrokeAndFill.
647 */
648 public native float getStrokeWidth();
649
650 /**
651 * Set the width for stroking.
652 * Pass 0 to stroke in hairline mode.
653 * Hairlines always draws a single pixel independent of the canva's matrix.
654 *
655 * @param width set the paint's stroke width, used whenever the paint's
656 * style is Stroke or StrokeAndFill.
657 */
658 public native void setStrokeWidth(float width);
659
660 /**
661 * Return the paint's stroke miter value. Used to control the behavior
662 * of miter joins when the joins angle is sharp.
663 *
664 * @return the paint's miter limit, used whenever the paint's style is
665 * Stroke or StrokeAndFill.
666 */
667 public native float getStrokeMiter();
668
669 /**
670 * Set the paint's stroke miter value. This is used to control the behavior
671 * of miter joins when the joins angle is sharp. This value must be >= 0.
672 *
673 * @param miter set the miter limit on the paint, used whenever the paint's
674 * style is Stroke or StrokeAndFill.
675 */
676 public native void setStrokeMiter(float miter);
677
678 /**
679 * Return the paint's Cap, controlling how the start and end of stroked
680 * lines and paths are treated.
681 *
682 * @return the line cap style for the paint, used whenever the paint's
683 * style is Stroke or StrokeAndFill.
684 */
685 public Cap getStrokeCap() {
686 return sCapArray[native_getStrokeCap(mNativePaint)];
687 }
688
689 /**
690 * Set the paint's Cap.
691 *
692 * @param cap set the paint's line cap style, used whenever the paint's
693 * style is Stroke or StrokeAndFill.
694 */
695 public void setStrokeCap(Cap cap) {
696 native_setStrokeCap(mNativePaint, cap.nativeInt);
697 }
698
699 /**
700 * Return the paint's stroke join type.
701 *
702 * @return the paint's Join.
703 */
704 public Join getStrokeJoin() {
705 return sJoinArray[native_getStrokeJoin(mNativePaint)];
706 }
707
708 /**
709 * Set the paint's Join.
710 *
711 * @param join set the paint's Join, used whenever the paint's style is
712 * Stroke or StrokeAndFill.
713 */
714 public void setStrokeJoin(Join join) {
715 native_setStrokeJoin(mNativePaint, join.nativeInt);
716 }
717
718 /**
719 * Applies any/all effects (patheffect, stroking) to src, returning the
720 * result in dst. The result is that drawing src with this paint will be
721 * the same as drawing dst with a default paint (at least from the
722 * geometric perspective).
723 *
724 * @param src input path
725 * @param dst output path (may be the same as src)
726 * @return true if the path should be filled, or false if it should be
727 * drawn with a hairline (width == 0)
728 */
729 public boolean getFillPath(Path src, Path dst) {
730 return native_getFillPath(mNativePaint, src.ni(), dst.ni());
731 }
732
733 /**
734 * Get the paint's shader object.
735 *
736 * @return the paint's shader (or null)
737 */
738 public Shader getShader() {
739 return mShader;
740 }
741
742 /**
743 * Set or clear the shader object.
744 * <p />
745 * Pass null to clear any previous shader.
746 * As a convenience, the parameter passed is also returned.
747 *
748 * @param shader May be null. the new shader to be installed in the paint
749 * @return shader
750 */
751 public Shader setShader(Shader shader) {
752 int shaderNative = 0;
753 if (shader != null)
754 shaderNative = shader.native_instance;
755 native_setShader(mNativePaint, shaderNative);
756 mShader = shader;
757 return shader;
758 }
759
760 /**
761 * Get the paint's colorfilter (maybe be null).
762 *
763 * @return the paint's colorfilter (maybe be null)
764 */
765 public ColorFilter getColorFilter() {
766 return mColorFilter;
767 }
768
769 /**
770 * Set or clear the paint's colorfilter, returning the parameter.
771 *
772 * @param filter May be null. The new filter to be installed in the paint
773 * @return filter
774 */
775 public ColorFilter setColorFilter(ColorFilter filter) {
776 int filterNative = 0;
777 if (filter != null)
778 filterNative = filter.native_instance;
779 native_setColorFilter(mNativePaint, filterNative);
780 mColorFilter = filter;
781 return filter;
782 }
783
784 /**
785 * Get the paint's xfermode object.
786 *
787 * @return the paint's xfermode (or null)
788 */
789 public Xfermode getXfermode() {
790 return mXfermode;
791 }
792
793 /**
794 * Set or clear the xfermode object.
795 * <p />
796 * Pass null to clear any previous xfermode.
797 * As a convenience, the parameter passed is also returned.
798 *
799 * @param xfermode May be null. The xfermode to be installed in the paint
800 * @return xfermode
801 */
802 public Xfermode setXfermode(Xfermode xfermode) {
803 int xfermodeNative = 0;
804 if (xfermode != null)
805 xfermodeNative = xfermode.native_instance;
806 native_setXfermode(mNativePaint, xfermodeNative);
807 mXfermode = xfermode;
808 return xfermode;
809 }
810
811 /**
812 * Get the paint's patheffect object.
813 *
814 * @return the paint's patheffect (or null)
815 */
816 public PathEffect getPathEffect() {
817 return mPathEffect;
818 }
819
820 /**
821 * Set or clear the patheffect object.
822 * <p />
823 * Pass null to clear any previous patheffect.
824 * As a convenience, the parameter passed is also returned.
825 *
826 * @param effect May be null. The patheffect to be installed in the paint
827 * @return effect
828 */
829 public PathEffect setPathEffect(PathEffect effect) {
830 int effectNative = 0;
831 if (effect != null) {
832 effectNative = effect.native_instance;
833 }
834 native_setPathEffect(mNativePaint, effectNative);
835 mPathEffect = effect;
836 return effect;
837 }
838
839 /**
840 * Get the paint's maskfilter object.
841 *
842 * @return the paint's maskfilter (or null)
843 */
844 public MaskFilter getMaskFilter() {
845 return mMaskFilter;
846 }
847
848 /**
849 * Set or clear the maskfilter object.
850 * <p />
851 * Pass null to clear any previous maskfilter.
852 * As a convenience, the parameter passed is also returned.
853 *
854 * @param maskfilter May be null. The maskfilter to be installed in the
855 * paint
856 * @return maskfilter
857 */
858 public MaskFilter setMaskFilter(MaskFilter maskfilter) {
859 int maskfilterNative = 0;
860 if (maskfilter != null) {
861 maskfilterNative = maskfilter.native_instance;
862 }
863 native_setMaskFilter(mNativePaint, maskfilterNative);
864 mMaskFilter = maskfilter;
865 return maskfilter;
866 }
867
868 /**
869 * Get the paint's typeface object.
870 * <p />
871 * The typeface object identifies which font to use when drawing or
872 * measuring text.
873 *
874 * @return the paint's typeface (or null)
875 */
876 public Typeface getTypeface() {
877 return mTypeface;
878 }
879
880 /**
881 * Set or clear the typeface object.
882 * <p />
883 * Pass null to clear any previous typeface.
884 * As a convenience, the parameter passed is also returned.
885 *
886 * @param typeface May be null. The typeface to be installed in the paint
887 * @return typeface
888 */
889 public Typeface setTypeface(Typeface typeface) {
890 int typefaceNative = 0;
891 if (typeface != null) {
892 typefaceNative = typeface.native_instance;
893 }
894 native_setTypeface(mNativePaint, typefaceNative);
895 mTypeface = typeface;
896 return typeface;
897 }
898
899 /**
900 * Get the paint's rasterizer (or null).
901 * <p />
902 * The raster controls/modifies how paths/text are turned into alpha masks.
903 *
904 * @return the paint's rasterizer (or null)
905 */
906 public Rasterizer getRasterizer() {
907 return mRasterizer;
908 }
909
910 /**
911 * Set or clear the rasterizer object.
912 * <p />
913 * Pass null to clear any previous rasterizer.
914 * As a convenience, the parameter passed is also returned.
915 *
916 * @param rasterizer May be null. The new rasterizer to be installed in
917 * the paint.
918 * @return rasterizer
919 */
920 public Rasterizer setRasterizer(Rasterizer rasterizer) {
921 int rasterizerNative = 0;
922 if (rasterizer != null) {
923 rasterizerNative = rasterizer.native_instance;
924 }
925 native_setRasterizer(mNativePaint, rasterizerNative);
926 mRasterizer = rasterizer;
927 return rasterizer;
928 }
929
930 /**
931 * Temporary API to expose layer drawing. This draws a shadow layer below
932 * the main layer, with the specified offset and color, and blur radius.
933 * If radius is 0, then the shadow layer is removed.
934 */
935 public native void setShadowLayer(float radius, float dx, float dy,
936 int color);
937
938 /**
939 * Temporary API to clear the shadow layer.
940 */
941 public void clearShadowLayer() {
942 setShadowLayer(0, 0, 0, 0);
943 }
944
945 /**
946 * Return the paint's Align value for drawing text. This controls how the
947 * text is positioned relative to its origin. LEFT align means that all of
948 * the text will be drawn to the right of its origin (i.e. the origin
949 * specifieds the LEFT edge of the text) and so on.
950 *
951 * @return the paint's Align value for drawing text.
952 */
953 public Align getTextAlign() {
954 return sAlignArray[native_getTextAlign(mNativePaint)];
955 }
956
957 /**
958 * Set the paint's text alignment. This controls how the
959 * text is positioned relative to its origin. LEFT align means that all of
960 * the text will be drawn to the right of its origin (i.e. the origin
961 * specifieds the LEFT edge of the text) and so on.
962 *
963 * @param align set the paint's Align value for drawing text.
964 */
965 public void setTextAlign(Align align) {
966 native_setTextAlign(mNativePaint, align.nativeInt);
967 }
968
969 /**
970 * Return the paint's text size.
971 *
972 * @return the paint's text size.
973 */
974 public native float getTextSize();
975
976 /**
977 * Set the paint's text size. This value must be > 0
978 *
979 * @param textSize set the paint's text size.
980 */
981 public native void setTextSize(float textSize);
982
983 /**
984 * Return the paint's horizontal scale factor for text. The default value
985 * is 1.0.
986 *
987 * @return the paint's scale factor in X for drawing/measuring text
988 */
989 public native float getTextScaleX();
990
991 /**
992 * Set the paint's horizontal scale factor for text. The default value
993 * is 1.0. Values > 1.0 will stretch the text wider. Values < 1.0 will
994 * stretch the text narrower.
995 *
996 * @param scaleX set the paint's scale in X for drawing/measuring text.
997 */
998 public native void setTextScaleX(float scaleX);
999
1000 /**
1001 * Return the paint's horizontal skew factor for text. The default value
1002 * is 0.
1003 *
1004 * @return the paint's skew factor in X for drawing text.
1005 */
1006 public native float getTextSkewX();
1007
1008 /**
1009 * Set the paint's horizontal skew factor for text. The default value
1010 * is 0. For approximating oblique text, use values around -0.25.
1011 *
1012 * @param skewX set the paint's skew factor in X for drawing text.
1013 */
1014 public native void setTextSkewX(float skewX);
1015
1016 /**
1017 * Return the distance above (negative) the baseline (ascent) based on the
1018 * current typeface and text size.
1019 *
1020 * @return the distance above (negative) the baseline (ascent) based on the
1021 * current typeface and text size.
1022 */
1023 public native float ascent();
1024
1025 /**
1026 * Return the distance below (positive) the baseline (descent) based on the
1027 * current typeface and text size.
1028 *
1029 * @return the distance below (positive) the baseline (descent) based on
1030 * the current typeface and text size.
1031 */
1032 public native float descent();
1033
1034 /**
1035 * Class that describes the various metrics for a font at a given text size.
1036 * Remember, Y values increase going down, so those values will be positive,
1037 * and values that measure distances going up will be negative. This class
1038 * is returned by getFontMetrics().
1039 */
1040 public static class FontMetrics {
1041 /**
1042 * The maximum distance above the baseline for the tallest glyph in
1043 * the font at a given text size.
1044 */
1045 public float top;
1046 /**
1047 * The recommended distance above the baseline for singled spaced text.
1048 */
1049 public float ascent;
1050 /**
1051 * The recommended distance below the baseline for singled spaced text.
1052 */
1053 public float descent;
1054 /**
1055 * The maximum distance below the baseline for the lowest glyph in
1056 * the font at a given text size.
1057 */
1058 public float bottom;
1059 /**
1060 * The recommended additional space to add between lines of text.
1061 */
1062 public float leading;
1063 }
1064
1065 /**
1066 * Return the font's recommended interline spacing, given the Paint's
1067 * settings for typeface, textSize, etc. If metrics is not null, return the
1068 * fontmetric values in it.
1069 *
1070 * @param metrics If this object is not null, its fields are filled with
1071 * the appropriate values given the paint's text attributes.
1072 * @return the font's recommended interline spacing.
1073 */
1074 public native float getFontMetrics(FontMetrics metrics);
1075
1076 /**
1077 * Allocates a new FontMetrics object, and then calls getFontMetrics(fm)
1078 * with it, returning the object.
1079 */
1080 public FontMetrics getFontMetrics() {
1081 FontMetrics fm = new FontMetrics();
1082 getFontMetrics(fm);
1083 return fm;
1084 }
1085
1086 /**
1087 * Convenience method for callers that want to have FontMetrics values as
1088 * integers.
1089 */
1090 public static class FontMetricsInt {
1091 public int top;
1092 public int ascent;
1093 public int descent;
1094 public int bottom;
1095 public int leading;
1096
1097 @Override public String toString() {
1098 return "FontMetricsInt: top=" + top + " ascent=" + ascent +
1099 " descent=" + descent + " bottom=" + bottom +
1100 " leading=" + leading;
1101 }
1102 }
1103
1104 /**
1105 * Return the font's interline spacing, given the Paint's settings for
1106 * typeface, textSize, etc. If metrics is not null, return the fontmetric
1107 * values in it. Note: all values have been converted to integers from
1108 * floats, in such a way has to make the answers useful for both spacing
1109 * and clipping. If you want more control over the rounding, call
1110 * getFontMetrics().
1111 *
1112 * @return the font's interline spacing.
1113 */
1114 public native int getFontMetricsInt(FontMetricsInt fmi);
1115
1116 public FontMetricsInt getFontMetricsInt() {
1117 FontMetricsInt fm = new FontMetricsInt();
1118 getFontMetricsInt(fm);
1119 return fm;
1120 }
1121
1122 /**
1123 * Return the recommend line spacing based on the current typeface and
1124 * text size.
1125 *
1126 * @return recommend line spacing based on the current typeface and
1127 * text size.
1128 */
1129 public float getFontSpacing() {
1130 return getFontMetrics(null);
1131 }
1132
1133 /**
1134 * Return the width of the text.
1135 *
1136 * @param text The text to measure
1137 * @param index The index of the first character to start measuring
1138 * @param count THe number of characters to measure, beginning with start
1139 * @return The width of the text
1140 */
Dianne Hackbornafa78962009-09-28 17:33:54 -07001141 public float measureText(char[] text, int index, int count) {
1142 if (!mHasCompatScaling) return native_measureText(text, index, count);
1143 final float oldSize = getTextSize();
1144 setTextSize(oldSize*mCompatScaling);
1145 float w = native_measureText(text, index, count);
1146 setTextSize(oldSize);
1147 return w*mInvCompatScaling;
1148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149
Dianne Hackbornafa78962009-09-28 17:33:54 -07001150 private native float native_measureText(char[] text, int index, int count);
1151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 /**
1153 * Return the width of the text.
1154 *
1155 * @param text The text to measure
1156 * @param start The index of the first character to start measuring
1157 * @param end 1 beyond the index of the last character to measure
1158 * @return The width of the text
1159 */
Dianne Hackbornafa78962009-09-28 17:33:54 -07001160 public float measureText(String text, int start, int end) {
1161 if (!mHasCompatScaling) return native_measureText(text, start, end);
1162 final float oldSize = getTextSize();
1163 setTextSize(oldSize*mCompatScaling);
1164 float w = native_measureText(text, start, end);
1165 setTextSize(oldSize);
1166 return w*mInvCompatScaling;
1167 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168
Dianne Hackbornafa78962009-09-28 17:33:54 -07001169 private native float native_measureText(String text, int start, int end);
1170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171 /**
1172 * Return the width of the text.
1173 *
1174 * @param text The text to measure
1175 * @return The width of the text
1176 */
Dianne Hackbornafa78962009-09-28 17:33:54 -07001177 public float measureText(String text) {
1178 if (!mHasCompatScaling) return native_measureText(text);
1179 final float oldSize = getTextSize();
1180 setTextSize(oldSize*mCompatScaling);
1181 float w = native_measureText(text);
1182 setTextSize(oldSize);
1183 return w*mInvCompatScaling;
1184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185
Dianne Hackbornafa78962009-09-28 17:33:54 -07001186 private native float native_measureText(String text);
1187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001188 /**
1189 * Return the width of the text.
1190 *
1191 * @param text The text to measure
1192 * @param start The index of the first character to start measuring
1193 * @param end 1 beyond the index of the last character to measure
1194 * @return The width of the text
1195 */
1196 public float measureText(CharSequence text, int start, int end) {
1197 if (text instanceof String) {
1198 return measureText((String)text, start, end);
1199 }
1200 if (text instanceof SpannedString ||
1201 text instanceof SpannableString) {
1202 return measureText(text.toString(), start, end);
1203 }
1204 if (text instanceof GraphicsOperations) {
1205 return ((GraphicsOperations)text).measureText(start, end, this);
1206 }
1207
1208 char[] buf = TemporaryBuffer.obtain(end - start);
Dianne Hackbornafa78962009-09-28 17:33:54 -07001209 TextUtils.getChars(text, start, end, buf, 0);
1210 float result = measureText(buf, 0, end - start);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 TemporaryBuffer.recycle(buf);
Dianne Hackbornafa78962009-09-28 17:33:54 -07001212 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001213 }
1214
1215 /**
1216 * Measure the text, stopping early if the measured width exceeds maxWidth.
1217 * Return the number of chars that were measured, and if measuredWidth is
1218 * not null, return in it the actual width measured.
1219 *
1220 * @param text The text to measure
1221 * @param index The offset into text to begin measuring at
1222 * @param count The number of maximum number of entries to measure. If count
1223 * is negative, then the characters before index are measured
1224 * in reverse order. This allows for measuring the end of
1225 * string.
1226 * @param maxWidth The maximum width to accumulate.
1227 * @param measuredWidth Optional. If not null, returns the actual width
1228 * measured.
1229 * @return The number of chars that were measured. Will always be <=
1230 * abs(count).
1231 */
Dianne Hackbornafa78962009-09-28 17:33:54 -07001232 public int breakText(char[] text, int index, int count,
1233 float maxWidth, float[] measuredWidth) {
1234 if (!mHasCompatScaling) {
1235 return native_breakText(text, index, count, maxWidth, measuredWidth);
1236 }
1237 final float oldSize = getTextSize();
1238 setTextSize(oldSize*mCompatScaling);
1239 int res = native_breakText(text, index, count, maxWidth*mCompatScaling,
1240 measuredWidth);
1241 setTextSize(oldSize);
1242 if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
1243 return res;
1244 }
1245
Dianne Hackbornc20a9602009-09-29 11:38:01 -07001246 private native int native_breakText(char[] text, int index, int count,
1247 float maxWidth, float[] measuredWidth);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001248
1249 /**
1250 * Measure the text, stopping early if the measured width exceeds maxWidth.
1251 * Return the number of chars that were measured, and if measuredWidth is
1252 * not null, return in it the actual width measured.
1253 *
1254 * @param text The text to measure
1255 * @param start The offset into text to begin measuring at
1256 * @param end The end of the text slice to measure.
1257 * @param measureForwards If true, measure forwards, starting at start.
1258 * Otherwise, measure backwards, starting with end.
1259 * @param maxWidth The maximum width to accumulate.
1260 * @param measuredWidth Optional. If not null, returns the actual width
1261 * measured.
1262 * @return The number of chars that were measured. Will always be <=
1263 * abs(end - start).
1264 */
1265 public int breakText(CharSequence text, int start, int end,
1266 boolean measureForwards,
1267 float maxWidth, float[] measuredWidth) {
1268 if (start == 0 && text instanceof String && end == text.length()) {
1269 return breakText((String) text, measureForwards, maxWidth,
1270 measuredWidth);
1271 }
1272
1273 char[] buf = TemporaryBuffer.obtain(end - start);
1274 int result;
1275
1276 TextUtils.getChars(text, start, end, buf, 0);
1277
1278 if (measureForwards) {
1279 result = breakText(buf, 0, end - start, maxWidth, measuredWidth);
1280 } else {
1281 result = breakText(buf, 0, -(end - start), maxWidth, measuredWidth);
1282 }
1283
1284 TemporaryBuffer.recycle(buf);
1285 return result;
1286 }
1287
1288 /**
1289 * Measure the text, stopping early if the measured width exceeds maxWidth.
1290 * Return the number of chars that were measured, and if measuredWidth is
1291 * not null, return in it the actual width measured.
1292 *
1293 * @param text The text to measure
Dirk Dougherty33a31b32009-05-12 14:10:20 -07001294 * @param measureForwards If true, measure forwards, starting with the
1295 * first character in the string. Otherwise,
1296 * measure backwards, starting with the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001297 * last character in the string.
1298 * @param maxWidth The maximum width to accumulate.
1299 * @param measuredWidth Optional. If not null, returns the actual width
1300 * measured.
1301 * @return The number of chars that were measured. Will always be <=
1302 * abs(count).
1303 */
Dianne Hackbornafa78962009-09-28 17:33:54 -07001304 public int breakText(String text, boolean measureForwards,
1305 float maxWidth, float[] measuredWidth) {
1306 if (!mHasCompatScaling) {
1307 return native_breakText(text, measureForwards, maxWidth, measuredWidth);
1308 }
1309 final float oldSize = getTextSize();
1310 setTextSize(oldSize*mCompatScaling);
1311 int res = native_breakText(text, measureForwards, maxWidth*mCompatScaling,
1312 measuredWidth);
1313 setTextSize(oldSize);
1314 if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling;
1315 return res;
1316 }
1317
Dianne Hackbornc20a9602009-09-29 11:38:01 -07001318 private native int native_breakText(String text, boolean measureForwards,
1319 float maxWidth, float[] measuredWidth);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320
1321 /**
1322 * Return the advance widths for the characters in the string.
1323 *
1324 * @param text The text to measure
1325 * @param index The index of the first char to to measure
1326 * @param count The number of chars starting with index to measure
1327 * @param widths array to receive the advance widths of the characters.
1328 * Must be at least a large as count.
1329 * @return the actual number of widths returned.
1330 */
1331 public int getTextWidths(char[] text, int index, int count,
1332 float[] widths) {
1333 if ((index | count) < 0 || index + count > text.length
1334 || count > widths.length) {
1335 throw new ArrayIndexOutOfBoundsException();
1336 }
Dianne Hackbornafa78962009-09-28 17:33:54 -07001337
1338 if (!mHasCompatScaling) {
1339 return native_getTextWidths(mNativePaint, text, index, count, widths);
1340 }
1341 final float oldSize = getTextSize();
1342 setTextSize(oldSize*mCompatScaling);
1343 int res = native_getTextWidths(mNativePaint, text, index, count, widths);
1344 setTextSize(oldSize);
1345 for (int i=0; i<res; i++) {
1346 widths[i] *= mInvCompatScaling;
1347 }
1348 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 }
1350
1351 /**
1352 * Return the advance widths for the characters in the string.
1353 *
1354 * @param text The text to measure
1355 * @param start The index of the first char to to measure
1356 * @param end The end of the text slice to measure
1357 * @param widths array to receive the advance widths of the characters.
1358 * Must be at least a large as (end - start).
1359 * @return the actual number of widths returned.
1360 */
1361 public int getTextWidths(CharSequence text, int start, int end,
1362 float[] widths) {
1363 if (text instanceof String) {
1364 return getTextWidths((String) text, start, end, widths);
1365 }
1366 if (text instanceof SpannedString ||
1367 text instanceof SpannableString) {
1368 return getTextWidths(text.toString(), start, end, widths);
1369 }
1370 if (text instanceof GraphicsOperations) {
1371 return ((GraphicsOperations) text).getTextWidths(start, end,
1372 widths, this);
1373 }
1374
1375 char[] buf = TemporaryBuffer.obtain(end - start);
Doug Felt0c702b82010-05-14 10:55:42 -07001376 TextUtils.getChars(text, start, end, buf, 0);
1377 int result = getTextWidths(buf, 0, end - start, widths);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 TemporaryBuffer.recycle(buf);
Doug Felt0c702b82010-05-14 10:55:42 -07001379 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 }
1381
1382 /**
1383 * Return the advance widths for the characters in the string.
1384 *
1385 * @param text The text to measure
1386 * @param start The index of the first char to to measure
1387 * @param end The end of the text slice to measure
1388 * @param widths array to receive the advance widths of the characters.
1389 * Must be at least a large as the text.
1390 * @return the number of unichars in the specified text.
1391 */
1392 public int getTextWidths(String text, int start, int end, float[] widths) {
1393 if ((start | end | (end - start) | (text.length() - end)) < 0) {
1394 throw new IndexOutOfBoundsException();
1395 }
1396 if (end - start > widths.length) {
1397 throw new ArrayIndexOutOfBoundsException();
1398 }
Dianne Hackbornafa78962009-09-28 17:33:54 -07001399
1400 if (!mHasCompatScaling) {
1401 return native_getTextWidths(mNativePaint, text, start, end, widths);
1402 }
1403 final float oldSize = getTextSize();
1404 setTextSize(oldSize*mCompatScaling);
1405 int res = native_getTextWidths(mNativePaint, text, start, end, widths);
1406 setTextSize(oldSize);
1407 for (int i=0; i<res; i++) {
1408 widths[i] *= mInvCompatScaling;
1409 }
1410 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 }
1412
1413 /**
1414 * Return the advance widths for the characters in the string.
1415 *
1416 * @param text The text to measure
1417 * @param widths array to receive the advance widths of the characters.
1418 * Must be at least a large as the text.
1419 * @return the number of unichars in the specified text.
1420 */
1421 public int getTextWidths(String text, float[] widths) {
1422 return getTextWidths(text, 0, text.length(), widths);
1423 }
1424
1425 /**
Doug Felt0c702b82010-05-14 10:55:42 -07001426 * Convenience overload that takes a char array instead of a
1427 * String.
1428 *
1429 * @see #getTextRunAdvances(String, int, int, int, int, int, float[], int)
1430 * @hide
1431 */
1432 public float getTextRunAdvances(char[] chars, int index, int count,
1433 int contextIndex, int contextCount, int flags, float[] advances,
1434 int advancesIndex) {
1435
1436 if ((index | count | contextIndex | contextCount | advancesIndex
1437 | (index - contextIndex)
1438 | ((contextIndex + contextCount) - (index + count))
1439 | (chars.length - (contextIndex + contextCount))
1440 | (advances == null ? 0 :
1441 (advances.length - (advancesIndex + count)))) < 0) {
1442 throw new IndexOutOfBoundsException();
1443 }
1444 if (flags != DIRECTION_LTR && flags != DIRECTION_RTL) {
1445 throw new IllegalArgumentException("unknown flags value: " + flags);
1446 }
1447
1448 if (!mHasCompatScaling) {
1449 return native_getTextRunAdvances(mNativePaint, chars, index, count,
1450 contextIndex, contextCount, flags, advances, advancesIndex);
1451 }
1452
1453 final float oldSize = getTextSize();
1454 setTextSize(oldSize * mCompatScaling);
1455 float res = native_getTextRunAdvances(mNativePaint, chars, index, count,
1456 contextIndex, contextCount, flags, advances, advancesIndex);
1457 setTextSize(oldSize);
1458
1459 if (advances != null) {
1460 for (int i = advancesIndex, e = i + count; i < e; i++) {
1461 advances[i] *= mInvCompatScaling;
1462 }
1463 }
1464 return res * mInvCompatScaling; // assume errors are not significant
1465 }
1466
1467 /**
1468 * Convenience overload that takes a CharSequence instead of a
1469 * String.
1470 *
1471 * @see #getTextRunAdvances(String, int, int, int, int, int, float[], int)
1472 * @hide
1473 */
1474 public float getTextRunAdvances(CharSequence text, int start, int end,
1475 int contextStart, int contextEnd, int flags, float[] advances,
1476 int advancesIndex) {
1477
1478 if (text instanceof String) {
1479 return getTextRunAdvances((String) text, start, end,
1480 contextStart, contextEnd, flags, advances, advancesIndex);
1481 }
1482 if (text instanceof SpannedString ||
1483 text instanceof SpannableString) {
1484 return getTextRunAdvances(text.toString(), start, end,
1485 contextStart, contextEnd, flags, advances, advancesIndex);
1486 }
1487 if (text instanceof GraphicsOperations) {
1488 return ((GraphicsOperations) text).getTextRunAdvances(start, end,
1489 contextStart, contextEnd, flags, advances, advancesIndex, this);
1490 }
1491
1492 int contextLen = contextEnd - contextStart;
1493 int len = end - start;
1494 char[] buf = TemporaryBuffer.obtain(contextLen);
1495 TextUtils.getChars(text, start, end, buf, 0);
1496 float result = getTextRunAdvances(buf, start - contextStart, len,
1497 0, contextLen, flags, advances, advancesIndex);
1498 TemporaryBuffer.recycle(buf);
1499 return result;
1500 }
1501
1502 /**
1503 * Returns the total advance width for the characters in the run
1504 * between start and end, and if advances is not null, the advance
1505 * assigned to each of these characters (java chars).
1506 *
1507 * <p>The trailing surrogate in a valid surrogate pair is assigned
1508 * an advance of 0. Thus the number of returned advances is
1509 * always equal to count, not to the number of unicode codepoints
1510 * represented by the run.
1511 *
1512 * <p>In the case of conjuncts or combining marks, the total
1513 * advance is assigned to the first logical character, and the
1514 * following characters are assigned an advance of 0.
1515 *
1516 * <p>This generates the sum of the advances of glyphs for
1517 * characters in a reordered cluster as the width of the first
1518 * logical character in the cluster, and 0 for the widths of all
1519 * other characters in the cluster. In effect, such clusters are
1520 * treated like conjuncts.
1521 *
1522 * <p>The shaping bounds limit the amount of context available
1523 * outside start and end that can be used for shaping analysis.
1524 * These bounds typically reflect changes in bidi level or font
1525 * metrics across which shaping does not occur.
1526 *
1527 * @param text the text to measure
1528 * @param start the index of the first character to measure
1529 * @param end the index past the last character to measure
1530 * @param contextStart the index of the first character to use for shaping context,
1531 * must be <= start
1532 * @param contextEnd the index past the last character to use for shaping context,
1533 * must be >= end
1534 * @param flags the flags to control the advances, either {@link #DIRECTION_LTR}
1535 * or {@link #DIRECTION_RTL}
1536 * @param advances array to receive the advances, must have room for all advances,
1537 * can be null if only total advance is needed
1538 * @param advancesIndex the position in advances at which to put the
1539 * advance corresponding to the character at start
1540 * @return the total advance
1541 *
1542 * @hide
1543 */
1544 public float getTextRunAdvances(String text, int start, int end, int contextStart,
1545 int contextEnd, int flags, float[] advances, int advancesIndex) {
1546
1547 if ((start | end | contextStart | contextEnd | advancesIndex | (end - start)
1548 | (start - contextStart) | (contextEnd - end)
1549 | (text.length() - contextEnd)
1550 | (advances == null ? 0 :
1551 (advances.length - advancesIndex - (end - start)))) < 0) {
1552 throw new IndexOutOfBoundsException();
1553 }
1554 if (flags != DIRECTION_LTR && flags != DIRECTION_RTL) {
1555 throw new IllegalArgumentException("unknown flags value: " + flags);
1556 }
1557
1558 if (!mHasCompatScaling) {
1559 return native_getTextRunAdvances(mNativePaint, text, start, end,
1560 contextStart, contextEnd, flags, advances, advancesIndex);
1561 }
1562
1563 final float oldSize = getTextSize();
1564 setTextSize(oldSize * mCompatScaling);
1565 float totalAdvance = native_getTextRunAdvances(mNativePaint, text, start, end,
1566 contextStart, contextEnd, flags, advances, advancesIndex);
1567 setTextSize(oldSize);
1568
1569 if (advances != null) {
1570 for (int i = advancesIndex, e = i + (end - start); i < e; i++) {
1571 advances[i] *= mInvCompatScaling;
1572 }
1573 }
1574 return totalAdvance * mInvCompatScaling; // assume errors are insignificant
1575 }
1576
1577 /**
1578 * Returns the next cursor position in the run. This avoids placing the
1579 * cursor between surrogates, between characters that form conjuncts,
1580 * between base characters and combining marks, or within a reordering
1581 * cluster.
1582 *
1583 * <p>ContextStart and offset are relative to the start of text.
1584 * The context is the shaping context for cursor movement, generally
1585 * the bounds of the metric span enclosing the cursor in the direction of
1586 * movement.
1587 *
1588 * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
1589 * cursor position, this returns -1. Otherwise this will never return a
1590 * value before contextStart or after contextStart + contextLength.
1591 *
1592 * @param text the text
1593 * @param contextStart the start of the context
1594 * @param contextLength the length of the context
1595 * @param flags either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
1596 * @param offset the cursor position to move from
1597 * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
1598 * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
1599 * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
1600 * @return the offset of the next position, or -1
1601 * @hide
1602 */
1603 public int getTextRunCursor(char[] text, int contextStart, int contextLength,
1604 int flags, int offset, int cursorOpt) {
1605 int contextEnd = contextStart + contextLength;
1606 if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
1607 | (offset - contextStart) | (contextEnd - offset)
1608 | (text.length - contextEnd) | cursorOpt) < 0)
1609 || cursorOpt > CURSOR_OPT_MAX_VALUE) {
1610 throw new IndexOutOfBoundsException();
1611 }
1612
1613 return native_getTextRunCursor(mNativePaint, text,
1614 contextStart, contextLength, flags, offset, cursorOpt);
1615 }
1616
1617 /**
1618 * Returns the next cursor position in the run. This avoids placing the
1619 * cursor between surrogates, between characters that form conjuncts,
1620 * between base characters and combining marks, or within a reordering
1621 * cluster.
1622 *
1623 * <p>ContextStart, contextEnd, and offset are relative to the start of
1624 * text. The context is the shaping context for cursor movement, generally
1625 * the bounds of the metric span enclosing the cursor in the direction of
1626 * movement.
1627 *
1628 * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
1629 * cursor position, this returns -1. Otherwise this will never return a
1630 * value before contextStart or after contextEnd.
1631 *
1632 * @param text the text
1633 * @param contextStart the start of the context
1634 * @param contextEnd the end of the context
1635 * @param flags either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
1636 * @param offset the cursor position to move from
1637 * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
1638 * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
1639 * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
1640 * @return the offset of the next position, or -1
1641 * @hide
1642 */
1643 public int getTextRunCursor(CharSequence text, int contextStart,
1644 int contextEnd, int flags, int offset, int cursorOpt) {
1645
1646 if (text instanceof String || text instanceof SpannedString ||
1647 text instanceof SpannableString) {
1648 return getTextRunCursor(text.toString(), contextStart, contextEnd,
1649 flags, offset, cursorOpt);
1650 }
1651 if (text instanceof GraphicsOperations) {
1652 return ((GraphicsOperations) text).getTextRunCursor(
1653 contextStart, contextEnd, flags, offset, cursorOpt, this);
1654 }
1655
1656 int contextLen = contextEnd - contextStart;
1657 char[] buf = TemporaryBuffer.obtain(contextLen);
1658 TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
1659 int result = getTextRunCursor(buf, 0, contextLen, flags, offset, cursorOpt);
1660 TemporaryBuffer.recycle(buf);
1661 return result;
1662 }
1663
1664 /**
1665 * Returns the next cursor position in the run. This avoids placing the
1666 * cursor between surrogates, between characters that form conjuncts,
1667 * between base characters and combining marks, or within a reordering
1668 * cluster.
1669 *
1670 * <p>ContextStart, contextEnd, and offset are relative to the start of
1671 * text. The context is the shaping context for cursor movement, generally
1672 * the bounds of the metric span enclosing the cursor in the direction of
1673 * movement.
1674 *
1675 * <p>If cursorOpt is {@link #CURSOR_AT} and the offset is not a valid
1676 * cursor position, this returns -1. Otherwise this will never return a
1677 * value before contextStart or after contextEnd.
1678 *
1679 * @param text the text
1680 * @param contextStart the start of the context
1681 * @param contextEnd the end of the context
1682 * @param flags either {@link #DIRECTION_RTL} or {@link #DIRECTION_LTR}
1683 * @param offset the cursor position to move from
1684 * @param cursorOpt how to move the cursor, one of {@link #CURSOR_AFTER},
1685 * {@link #CURSOR_AT_OR_AFTER}, {@link #CURSOR_BEFORE},
1686 * {@link #CURSOR_AT_OR_BEFORE}, or {@link #CURSOR_AT}
1687 * @return the offset of the next position, or -1
1688 * @hide
1689 */
1690 public int getTextRunCursor(String text, int contextStart, int contextEnd,
1691 int flags, int offset, int cursorOpt) {
1692 if (((contextStart | contextEnd | offset | (contextEnd - contextStart)
1693 | (offset - contextStart) | (contextEnd - offset)
1694 | (text.length() - contextEnd) | cursorOpt) < 0)
1695 || cursorOpt > CURSOR_OPT_MAX_VALUE) {
1696 throw new IndexOutOfBoundsException();
1697 }
1698
1699 return native_getTextRunCursor(mNativePaint, text,
1700 contextStart, contextEnd, flags, offset, cursorOpt);
1701 }
1702
1703 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 * Return the path (outline) for the specified text.
1705 * Note: just like Canvas.drawText, this will respect the Align setting in
1706 * the paint.
1707 *
1708 * @param text The text to retrieve the path from
1709 * @param index The index of the first character in text
1710 * @param count The number of characterss starting with index
1711 * @param x The x coordinate of the text's origin
1712 * @param y The y coordinate of the text's origin
1713 * @param path The path to receive the data describing the text. Must
1714 * be allocated by the caller.
1715 */
1716 public void getTextPath(char[] text, int index, int count,
1717 float x, float y, Path path) {
1718 if ((index | count) < 0 || index + count > text.length) {
1719 throw new ArrayIndexOutOfBoundsException();
1720 }
1721 native_getTextPath(mNativePaint, text, index, count, x, y, path.ni());
1722 }
1723
1724 /**
1725 * Return the path (outline) for the specified text.
1726 * Note: just like Canvas.drawText, this will respect the Align setting
1727 * in the paint.
1728 *
1729 * @param text The text to retrieve the path from
1730 * @param start The first character in the text
1731 * @param end 1 past the last charcter in the text
1732 * @param x The x coordinate of the text's origin
1733 * @param y The y coordinate of the text's origin
1734 * @param path The path to receive the data describing the text. Must
1735 * be allocated by the caller.
1736 */
1737 public void getTextPath(String text, int start, int end,
1738 float x, float y, Path path) {
1739 if ((start | end | (end - start) | (text.length() - end)) < 0) {
1740 throw new IndexOutOfBoundsException();
1741 }
1742 native_getTextPath(mNativePaint, text, start, end, x, y, path.ni());
1743 }
1744
1745 /**
1746 * Return in bounds (allocated by the caller) the smallest rectangle that
1747 * encloses all of the characters, with an implied origin at (0,0).
1748 *
1749 * @param text String to measure and return its bounds
1750 * @param start Index of the first char in the string to measure
1751 * @param end 1 past the last char in the string measure
1752 * @param bounds Returns the unioned bounds of all the text. Must be
1753 * allocated by the caller.
1754 */
1755 public void getTextBounds(String text, int start, int end, Rect bounds) {
1756 if ((start | end | (end - start) | (text.length() - end)) < 0) {
1757 throw new IndexOutOfBoundsException();
1758 }
1759 if (bounds == null) {
1760 throw new NullPointerException("need bounds Rect");
1761 }
1762 nativeGetStringBounds(mNativePaint, text, start, end, bounds);
1763 }
1764
1765 /**
1766 * Return in bounds (allocated by the caller) the smallest rectangle that
1767 * encloses all of the characters, with an implied origin at (0,0).
1768 *
1769 * @param text Array of chars to measure and return their unioned bounds
1770 * @param index Index of the first char in the array to measure
1771 * @param count The number of chars, beginning at index, to measure
1772 * @param bounds Returns the unioned bounds of all the text. Must be
1773 * allocated by the caller.
1774 */
1775 public void getTextBounds(char[] text, int index, int count, Rect bounds) {
1776 if ((index | count) < 0 || index + count > text.length) {
1777 throw new ArrayIndexOutOfBoundsException();
1778 }
1779 if (bounds == null) {
1780 throw new NullPointerException("need bounds Rect");
1781 }
1782 nativeGetCharArrayBounds(mNativePaint, text, index, count, bounds);
1783 }
1784
1785 protected void finalize() throws Throwable {
1786 finalizer(mNativePaint);
1787 }
1788
1789 private static native int native_init();
1790 private static native int native_initWithPaint(int paint);
1791 private static native void native_reset(int native_object);
1792 private static native void native_set(int native_dst, int native_src);
1793 private static native int native_getStyle(int native_object);
1794 private static native void native_setStyle(int native_object, int style);
1795 private static native int native_getStrokeCap(int native_object);
1796 private static native void native_setStrokeCap(int native_object, int cap);
1797 private static native int native_getStrokeJoin(int native_object);
1798 private static native void native_setStrokeJoin(int native_object,
1799 int join);
1800 private static native boolean native_getFillPath(int native_object,
1801 int src, int dst);
1802 private static native int native_setShader(int native_object, int shader);
1803 private static native int native_setColorFilter(int native_object,
1804 int filter);
1805 private static native int native_setXfermode(int native_object,
1806 int xfermode);
1807 private static native int native_setPathEffect(int native_object,
1808 int effect);
1809 private static native int native_setMaskFilter(int native_object,
1810 int maskfilter);
1811 private static native int native_setTypeface(int native_object,
1812 int typeface);
1813 private static native int native_setRasterizer(int native_object,
1814 int rasterizer);
1815
1816 private static native int native_getTextAlign(int native_object);
1817 private static native void native_setTextAlign(int native_object,
1818 int align);
1819
1820 private static native float native_getFontMetrics(int native_paint,
1821 FontMetrics metrics);
1822 private static native int native_getTextWidths(int native_object,
1823 char[] text, int index, int count, float[] widths);
1824 private static native int native_getTextWidths(int native_object,
1825 String text, int start, int end, float[] widths);
Doug Felt0c702b82010-05-14 10:55:42 -07001826
1827 private static native float native_getTextRunAdvances(int native_object,
1828 char[] text, int index, int count, int contextIndex, int contextCount,
1829 int flags, float[] advances, int advancesIndex);
1830 private static native float native_getTextRunAdvances(int native_object,
1831 String text, int start, int end, int contextStart, int contextEnd,
1832 int flags, float[] advances, int advancesIndex);
1833
1834 private native int native_getTextRunCursor(int native_object, char[] text,
1835 int contextStart, int contextLength, int flags, int offset, int cursorOpt);
1836 private native int native_getTextRunCursor(int native_object, String text,
1837 int contextStart, int contextEnd, int flags, int offset, int cursorOpt);
1838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 private static native void native_getTextPath(int native_object,
1840 char[] text, int index, int count, float x, float y, int path);
1841 private static native void native_getTextPath(int native_object,
1842 String text, int start, int end, float x, float y, int path);
1843 private static native void nativeGetStringBounds(int nativePaint,
1844 String text, int start, int end, Rect bounds);
1845 private static native void nativeGetCharArrayBounds(int nativePaint,
1846 char[] text, int index, int count, Rect bounds);
1847 private static native void finalizer(int nativePaint);
1848}