blob: 51b3efe12cd7a08f3b3a112f128372059ccc14ef [file] [log] [blame]
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001/*
2 * Copyright (C) 2010 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
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -080019import com.android.ide.common.rendering.api.LayoutLog;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -080020import com.android.layoutlib.bridge.Bridge;
Xavier Ducrohet3bd98982010-11-09 18:25:03 -080021import com.android.layoutlib.bridge.impl.DelegateManager;
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -080022import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070023
24import android.graphics.Paint.FontMetrics;
25import android.graphics.Paint.FontMetricsInt;
Xavier Ducrohet37f21802010-11-01 16:17:18 -070026import android.text.TextUtils;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070027
Xavier Ducrohet37f21802010-11-01 16:17:18 -070028import java.awt.BasicStroke;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070029import java.awt.Font;
Xavier Ducrohetb9761242010-12-23 10:22:14 -080030import java.awt.Shape;
31import java.awt.Stroke;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070032import java.awt.Toolkit;
33import java.awt.font.FontRenderContext;
34import java.awt.geom.AffineTransform;
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -080035import java.awt.geom.Rectangle2D;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070036import java.util.ArrayList;
37import java.util.Collections;
38import java.util.List;
39
40/**
41 * Delegate implementing the native methods of android.graphics.Paint
42 *
43 * Through the layoutlib_create tool, the original native methods of Paint have been replaced
44 * by calls to methods of the same name in this delegate class.
45 *
46 * This class behaves like the original native implementation, but in Java, keeping previously
47 * native data into its own objects and mapping them to int that are sent back and forth between
48 * it and the original Paint class.
49 *
50 * @see DelegateManager
51 *
52 */
53public class Paint_Delegate {
54
55 /**
56 * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}.
57 */
Xavier Ducrohet37f21802010-11-01 16:17:18 -070058 /*package*/ static final class FontInfo {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070059 Font mFont;
60 java.awt.FontMetrics mMetrics;
61 }
62
63 // ---- delegate manager ----
64 private static final DelegateManager<Paint_Delegate> sManager =
65 new DelegateManager<Paint_Delegate>();
66
67 // ---- delegate helper data ----
68 private List<FontInfo> mFonts;
69 private final FontRenderContext mFontContext = new FontRenderContext(
70 new AffineTransform(), true, true);
71
72 // ---- delegate data ----
73 private int mFlags;
74 private int mColor;
75 private int mStyle;
76 private int mCap;
77 private int mJoin;
Xavier Ducrohet37f21802010-11-01 16:17:18 -070078 private int mTextAlign;
Xavier Ducrohet91672792011-02-22 11:54:37 -080079 private Typeface_Delegate mTypeface;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070080 private float mStrokeWidth;
81 private float mStrokeMiter;
82 private float mTextSize;
83 private float mTextScaleX;
84 private float mTextSkewX;
85
Xavier Ducrohet91672792011-02-22 11:54:37 -080086 private Xfermode_Delegate mXfermode;
87 private ColorFilter_Delegate mColorFilter;
88 private Shader_Delegate mShader;
89 private PathEffect_Delegate mPathEffect;
90 private MaskFilter_Delegate mMaskFilter;
91 private Rasterizer_Delegate mRasterizer;
Xavier Ducroheta313b652010-11-01 18:45:20 -070092
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070093
94 // ---- Public Helper methods ----
95
Xavier Ducrohet37f21802010-11-01 16:17:18 -070096 public static Paint_Delegate getDelegate(int native_paint) {
97 return sManager.getDelegate(native_paint);
98 }
99
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700100 /**
101 * Returns the list of {@link Font} objects. The first item is the main font, the rest
102 * are fall backs for characters not present in the main font.
103 */
104 public List<FontInfo> getFonts() {
105 return mFonts;
106 }
107
Xavier Ducroheta313b652010-11-01 18:45:20 -0700108 public boolean isAntiAliased() {
109 return (mFlags & Paint.ANTI_ALIAS_FLAG) != 0;
110 }
111
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700112 public boolean isFilterBitmap() {
113 return (mFlags & Paint.FILTER_BITMAP_FLAG) != 0;
114 }
115
116 public int getStyle() {
117 return mStyle;
118 }
119
120 public int getColor() {
121 return mColor;
122 }
123
Xavier Ducrohet66225222010-12-21 01:33:04 -0800124 public int getAlpha() {
125 return mColor >>> 24;
126 }
127
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800128 public void setAlpha(int alpha) {
129 mColor = (alpha << 24) | (mColor & 0x00FFFFFF);
130 }
131
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700132 public int getTextAlign() {
133 return mTextAlign;
134 }
135
136 public float getStrokeWidth() {
137 return mStrokeWidth;
138 }
139
Xavier Ducrohet66225222010-12-21 01:33:04 -0800140 /**
141 * returns the value of stroke miter needed by the java api.
142 */
143 public float getJavaStrokeMiter() {
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800144 float miter = mStrokeMiter * mStrokeWidth;
145 if (miter < 1.f) {
146 miter = 1.f;
147 }
148 return miter;
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700149 }
150
151 public int getJavaCap() {
152 switch (Paint.sCapArray[mCap]) {
153 case BUTT:
154 return BasicStroke.CAP_BUTT;
155 case ROUND:
156 return BasicStroke.CAP_ROUND;
157 default:
158 case SQUARE:
159 return BasicStroke.CAP_SQUARE;
160 }
161 }
162
163 public int getJavaJoin() {
164 switch (Paint.sJoinArray[mJoin]) {
165 default:
166 case MITER:
167 return BasicStroke.JOIN_MITER;
168 case ROUND:
169 return BasicStroke.JOIN_ROUND;
170 case BEVEL:
171 return BasicStroke.JOIN_BEVEL;
172 }
173 }
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700174
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800175 public Stroke getJavaStroke() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800176 if (mPathEffect != null) {
177 if (mPathEffect.isSupported()) {
178 Stroke stroke = mPathEffect.getStroke(this);
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800179 assert stroke != null;
180 if (stroke != null) {
181 return stroke;
182 }
183 } else {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800184 Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800185 mPathEffect.getSupportMessage(),
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800186 null, null /*data*/);
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800187 }
188 }
189
190 // if no custom stroke as been set, set the default one.
191 return new BasicStroke(
192 getStrokeWidth(),
193 getJavaCap(),
194 getJavaJoin(),
195 getJavaStrokeMiter());
196 }
197
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800198 /**
199 * Returns the {@link Xfermode} delegate or null if none have been set
200 *
201 * @return the delegate or null.
202 */
203 public Xfermode_Delegate getXfermode() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800204 return mXfermode;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700205 }
206
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800207 /**
208 * Returns the {@link ColorFilter} delegate or null if none have been set
209 *
210 * @return the delegate or null.
211 */
212 public ColorFilter_Delegate getColorFilter() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800213 return mColorFilter;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700214 }
215
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800216 /**
217 * Returns the {@link Shader} delegate or null if none have been set
218 *
219 * @return the delegate or null.
220 */
221 public Shader_Delegate getShader() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800222 return mShader;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700223 }
224
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800225 /**
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800226 * Returns the {@link MaskFilter} delegate or null if none have been set
227 *
228 * @return the delegate or null.
229 */
230 public MaskFilter_Delegate getMaskFilter() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800231 return mMaskFilter;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800232 }
233
234 /**
235 * Returns the {@link Rasterizer} delegate or null if none have been set
236 *
237 * @return the delegate or null.
238 */
239 public Rasterizer_Delegate getRasterizer() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800240 return mRasterizer;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700241 }
242
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700243 // ---- native methods ----
244
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800245 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700246 /*package*/ static int getFlags(Paint thisPaint) {
247 // get the delegate from the native int.
248 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
249 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700250 return 0;
251 }
252
253 return delegate.mFlags;
254 }
255
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800256 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700257 /*package*/ static void setFlags(Paint thisPaint, int flags) {
258 // get the delegate from the native int.
259 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
260 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700261 return;
262 }
263
264 delegate.mFlags = flags;
265 }
266
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800267 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700268 /*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700269 setFlag(thisPaint, Paint.FILTER_BITMAP_FLAG, filter);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700270 }
271
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800272 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700273 /*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) {
274 setFlag(thisPaint, Paint.ANTI_ALIAS_FLAG, aa);
275 }
276
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800277 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700278 /*package*/ static void setSubpixelText(Paint thisPaint, boolean subpixelText) {
279 setFlag(thisPaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
280 }
281
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800282 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700283 /*package*/ static void setUnderlineText(Paint thisPaint, boolean underlineText) {
284 setFlag(thisPaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
285 }
286
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800287 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700288 /*package*/ static void setStrikeThruText(Paint thisPaint, boolean strikeThruText) {
289 setFlag(thisPaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
290 }
291
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800292 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700293 /*package*/ static void setFakeBoldText(Paint thisPaint, boolean fakeBoldText) {
294 setFlag(thisPaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
295 }
296
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800297 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700298 /*package*/ static void setDither(Paint thisPaint, boolean dither) {
299 setFlag(thisPaint, Paint.DITHER_FLAG, dither);
300 }
301
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800302 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700303 /*package*/ static void setLinearText(Paint thisPaint, boolean linearText) {
304 setFlag(thisPaint, Paint.LINEAR_TEXT_FLAG, linearText);
305 }
306
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800307 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700308 /*package*/ static int getColor(Paint thisPaint) {
309 // get the delegate from the native int.
310 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
311 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700312 return 0;
313 }
314
315 return delegate.mColor;
316 }
317
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800318 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700319 /*package*/ static void setColor(Paint thisPaint, int color) {
320 // get the delegate from the native int.
321 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
322 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700323 return;
324 }
325
326 delegate.mColor = color;
327 }
328
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800329 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700330 /*package*/ static int getAlpha(Paint thisPaint) {
331 // get the delegate from the native int.
332 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
333 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700334 return 0;
335 }
336
Xavier Ducrohet66225222010-12-21 01:33:04 -0800337 return delegate.getAlpha();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700338 }
339
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800340 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700341 /*package*/ static void setAlpha(Paint thisPaint, int a) {
342 // get the delegate from the native int.
343 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
344 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700345 return;
346 }
347
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800348 delegate.setAlpha(a);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700349 }
350
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800351 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700352 /*package*/ static float getStrokeWidth(Paint thisPaint) {
353 // get the delegate from the native int.
354 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
355 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700356 return 1.f;
357 }
358
359 return delegate.mStrokeWidth;
360 }
361
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800362 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700363 /*package*/ static void setStrokeWidth(Paint thisPaint, float width) {
364 // get the delegate from the native int.
365 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
366 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700367 return;
368 }
369
370 delegate.mStrokeWidth = width;
371 }
372
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800373 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700374 /*package*/ static float getStrokeMiter(Paint thisPaint) {
375 // get the delegate from the native int.
376 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
377 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700378 return 1.f;
379 }
380
381 return delegate.mStrokeMiter;
382 }
383
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800384 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700385 /*package*/ static void setStrokeMiter(Paint thisPaint, float miter) {
386 // get the delegate from the native int.
387 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
388 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700389 return;
390 }
391
392 delegate.mStrokeMiter = miter;
393 }
394
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800395 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700396 /*package*/ static void nSetShadowLayer(Paint thisPaint, float radius, float dx, float dy,
397 int color) {
398 // FIXME
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800399 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800400 "Paint.setShadowLayer is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700401 }
402
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800403 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700404 /*package*/ static float getTextSize(Paint thisPaint) {
405 // get the delegate from the native int.
406 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
407 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700408 return 1.f;
409 }
410
411 return delegate.mTextSize;
412 }
413
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800414 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700415 /*package*/ static void setTextSize(Paint thisPaint, float textSize) {
416 // get the delegate from the native int.
417 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
418 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700419 return;
420 }
421
422 delegate.mTextSize = textSize;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800423 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700424 }
425
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800426 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700427 /*package*/ static float getTextScaleX(Paint thisPaint) {
428 // get the delegate from the native int.
429 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
430 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700431 return 1.f;
432 }
433
434 return delegate.mTextScaleX;
435 }
436
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800437 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700438 /*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) {
439 // get the delegate from the native int.
440 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
441 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700442 return;
443 }
444
445 delegate.mTextScaleX = scaleX;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800446 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700447 }
448
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800449 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700450 /*package*/ static float getTextSkewX(Paint thisPaint) {
451 // get the delegate from the native int.
452 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
453 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700454 return 1.f;
455 }
456
457 return delegate.mTextSkewX;
458 }
459
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800460 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700461 /*package*/ static void setTextSkewX(Paint thisPaint, float skewX) {
462 // get the delegate from the native int.
463 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
464 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700465 return;
466 }
467
468 delegate.mTextSkewX = skewX;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800469 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700470 }
471
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800472 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700473 /*package*/ static float ascent(Paint thisPaint) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800474 // get the delegate
475 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
476 if (delegate == null) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800477 return 0;
478 }
479
480 if (delegate.mFonts.size() > 0) {
481 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
482 // Android expects negative ascent so we invert the value from Java.
483 return - javaMetrics.getAscent();
484 }
485
486 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700487 }
488
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800489 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700490 /*package*/ static float descent(Paint thisPaint) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800491 // get the delegate
492 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
493 if (delegate == null) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800494 return 0;
495 }
496
497 if (delegate.mFonts.size() > 0) {
498 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
499 return javaMetrics.getDescent();
500 }
501
502 return 0;
503
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700504 }
505
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800506 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700507 /*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700508 // get the delegate
509 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
510 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700511 return 0;
512 }
513
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800514 return delegate.getFontMetrics(metrics);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700515 }
516
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800517 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700518 /*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700519 // get the delegate
520 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
521 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700522 return 0;
523 }
524
525 if (delegate.mFonts.size() > 0) {
526 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
527 if (fmi != null) {
528 // Android expects negative ascent so we invert the value from Java.
529 fmi.top = - javaMetrics.getMaxAscent();
530 fmi.ascent = - javaMetrics.getAscent();
531 fmi.descent = javaMetrics.getDescent();
532 fmi.bottom = javaMetrics.getMaxDescent();
533 fmi.leading = javaMetrics.getLeading();
534 }
535
536 return javaMetrics.getHeight();
537 }
538
539 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700540 }
541
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800542 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700543 /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
544 int count) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700545 // get the delegate
546 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
547 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700548 return 0;
549 }
550
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700551 return delegate.measureText(text, index, count);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700552 }
553
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800554 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700555 /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end) {
556 return native_measureText(thisPaint, text.toCharArray(), start, end - start);
557 }
558
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800559 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700560 /*package*/ static float native_measureText(Paint thisPaint, String text) {
561 return native_measureText(thisPaint, text.toCharArray(), 0, text.length());
562 }
563
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800564 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700565 /*package*/ static int native_breakText(Paint thisPaint, char[] text, int index, int count,
566 float maxWidth, float[] measuredWidth) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800567
568 // get the delegate
569 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
570 if (delegate == null) {
571 return 0;
572 }
573
574 int inc = count > 0 ? 1 : -1;
575
576 int measureIndex = 0;
577 float measureAcc = 0;
578 for (int i = index; i != index + count; i += inc, measureIndex++) {
579 int start, end;
580 if (i < index) {
581 start = i;
582 end = index;
583 } else {
584 start = index;
585 end = i;
586 }
587
588 // measure from start to end
589 float res = delegate.measureText(text, start, end - start + 1);
590
591 if (measuredWidth != null) {
592 measuredWidth[measureIndex] = res;
593 }
594
595 measureAcc += res;
596 if (res > maxWidth) {
597 // we should not return this char index, but since it's 0-based
598 // and we need to return a count, we simply return measureIndex;
599 return measureIndex;
600 }
601
602 }
603
604 return measureIndex;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700605 }
606
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800607 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700608 /*package*/ static int native_breakText(Paint thisPaint, String text, boolean measureForwards,
609 float maxWidth, float[] measuredWidth) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800610 return native_breakText(thisPaint, text.toCharArray(), 0, text.length(), maxWidth,
611 measuredWidth);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700612 }
613
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800614 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700615 /*package*/ static int native_init() {
616 Paint_Delegate newDelegate = new Paint_Delegate();
Xavier Ducrohet91672792011-02-22 11:54:37 -0800617 return sManager.addNewDelegate(newDelegate);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700618 }
619
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800620 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700621 /*package*/ static int native_initWithPaint(int paint) {
622 // get the delegate from the native int.
623 Paint_Delegate delegate = sManager.getDelegate(paint);
624 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700625 return 0;
626 }
627
628 Paint_Delegate newDelegate = new Paint_Delegate(delegate);
Xavier Ducrohet91672792011-02-22 11:54:37 -0800629 return sManager.addNewDelegate(newDelegate);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700630 }
631
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800632 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700633 /*package*/ static void native_reset(int native_object) {
634 // get the delegate from the native int.
635 Paint_Delegate delegate = sManager.getDelegate(native_object);
636 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700637 return;
638 }
639
640 delegate.reset();
641 }
642
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800643 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700644 /*package*/ static void native_set(int native_dst, int native_src) {
645 // get the delegate from the native int.
646 Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
647 if (delegate_dst == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700648 return;
649 }
650
651 // get the delegate from the native int.
652 Paint_Delegate delegate_src = sManager.getDelegate(native_src);
653 if (delegate_src == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700654 return;
655 }
656
657 delegate_dst.set(delegate_src);
658 }
659
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800660 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700661 /*package*/ static int native_getStyle(int native_object) {
662 // get the delegate from the native int.
663 Paint_Delegate delegate = sManager.getDelegate(native_object);
664 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700665 return 0;
666 }
667
668 return delegate.mStyle;
669 }
670
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800671 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700672 /*package*/ static void native_setStyle(int native_object, int style) {
673 // get the delegate from the native int.
674 Paint_Delegate delegate = sManager.getDelegate(native_object);
675 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700676 return;
677 }
678
679 delegate.mStyle = style;
680 }
681
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800682 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700683 /*package*/ static int native_getStrokeCap(int native_object) {
684 // get the delegate from the native int.
685 Paint_Delegate delegate = sManager.getDelegate(native_object);
686 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700687 return 0;
688 }
689
690 return delegate.mCap;
691 }
692
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800693 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700694 /*package*/ static void native_setStrokeCap(int native_object, int cap) {
695 // get the delegate from the native int.
696 Paint_Delegate delegate = sManager.getDelegate(native_object);
697 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700698 return;
699 }
700
701 delegate.mCap = cap;
702 }
703
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800704 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700705 /*package*/ static int native_getStrokeJoin(int native_object) {
706 // get the delegate from the native int.
707 Paint_Delegate delegate = sManager.getDelegate(native_object);
708 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700709 return 0;
710 }
711
712 return delegate.mJoin;
713 }
714
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800715 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700716 /*package*/ static void native_setStrokeJoin(int native_object, int join) {
717 // get the delegate from the native int.
718 Paint_Delegate delegate = sManager.getDelegate(native_object);
719 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700720 return;
721 }
722
723 delegate.mJoin = join;
724 }
725
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800726 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700727 /*package*/ static boolean native_getFillPath(int native_object, int src, int dst) {
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800728 Paint_Delegate paint = sManager.getDelegate(native_object);
729 if (paint == null) {
730 return false;
731 }
732
733 Path_Delegate srcPath = Path_Delegate.getDelegate(src);
734 if (srcPath == null) {
735 return true;
736 }
737
738 Path_Delegate dstPath = Path_Delegate.getDelegate(dst);
739 if (dstPath == null) {
740 return true;
741 }
742
743 Stroke stroke = paint.getJavaStroke();
744 Shape strokeShape = stroke.createStrokedShape(srcPath.getJavaShape());
745
746 dstPath.setJavaShape(strokeShape);
747
748 // FIXME figure out the return value?
749 return true;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700750 }
751
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800752 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700753 /*package*/ static int native_setShader(int native_object, int shader) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700754 // get the delegate from the native int.
755 Paint_Delegate delegate = sManager.getDelegate(native_object);
756 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700757 return shader;
758 }
759
Xavier Ducrohet91672792011-02-22 11:54:37 -0800760 delegate.mShader = Shader_Delegate.getDelegate(shader);
761
762 return shader;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700763 }
764
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800765 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700766 /*package*/ static int native_setColorFilter(int native_object, int filter) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700767 // get the delegate from the native int.
768 Paint_Delegate delegate = sManager.getDelegate(native_object);
769 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700770 return filter;
771 }
772
Xavier Ducrohet91672792011-02-22 11:54:37 -0800773 delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800774
775 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800776 if (delegate.mColorFilter != null && delegate.mColorFilter.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800777 Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800778 delegate.mColorFilter.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800779 }
780
781 return filter;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700782 }
783
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800784 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700785 /*package*/ static int native_setXfermode(int native_object, int xfermode) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700786 // get the delegate from the native int.
787 Paint_Delegate delegate = sManager.getDelegate(native_object);
788 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700789 return xfermode;
790 }
791
Xavier Ducrohet91672792011-02-22 11:54:37 -0800792 delegate.mXfermode = Xfermode_Delegate.getDelegate(xfermode);
793
794 return xfermode;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700795 }
796
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800797 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700798 /*package*/ static int native_setPathEffect(int native_object, int effect) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700799 // get the delegate from the native int.
800 Paint_Delegate delegate = sManager.getDelegate(native_object);
801 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700802 return effect;
803 }
804
Xavier Ducrohet91672792011-02-22 11:54:37 -0800805 delegate.mPathEffect = PathEffect_Delegate.getDelegate(effect);
806
807 return effect;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700808 }
809
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800810 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700811 /*package*/ static int native_setMaskFilter(int native_object, int maskfilter) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700812 // get the delegate from the native int.
813 Paint_Delegate delegate = sManager.getDelegate(native_object);
814 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700815 return maskfilter;
816 }
817
Xavier Ducrohet91672792011-02-22 11:54:37 -0800818 delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800819
820 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800821 if (delegate.mMaskFilter != null && delegate.mMaskFilter.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800822 Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800823 delegate.mMaskFilter.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800824 }
825
826 return maskfilter;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700827 }
828
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800829 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700830 /*package*/ static int native_setTypeface(int native_object, int typeface) {
831 // get the delegate from the native int.
832 Paint_Delegate delegate = sManager.getDelegate(native_object);
833 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700834 return 0;
835 }
836
Xavier Ducrohet91672792011-02-22 11:54:37 -0800837 delegate.mTypeface = Typeface_Delegate.getDelegate(typeface);
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800838 delegate.updateFontObject();
Xavier Ducrohet91672792011-02-22 11:54:37 -0800839 return typeface;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700840 }
841
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800842 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700843 /*package*/ static int native_setRasterizer(int native_object, int rasterizer) {
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800844 // get the delegate from the native int.
845 Paint_Delegate delegate = sManager.getDelegate(native_object);
846 if (delegate == null) {
847 return rasterizer;
848 }
849
Xavier Ducrohet91672792011-02-22 11:54:37 -0800850 delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800851
852 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800853 if (delegate.mRasterizer != null && delegate.mRasterizer.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800854 Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800855 delegate.mRasterizer.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800856 }
857
858 return rasterizer;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700859 }
860
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800861 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700862 /*package*/ static int native_getTextAlign(int native_object) {
863 // get the delegate from the native int.
864 Paint_Delegate delegate = sManager.getDelegate(native_object);
865 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700866 return 0;
867 }
868
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700869 return delegate.mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700870 }
871
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800872 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700873 /*package*/ static void native_setTextAlign(int native_object, int align) {
874 // get the delegate from the native int.
875 Paint_Delegate delegate = sManager.getDelegate(native_object);
876 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700877 return;
878 }
879
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700880 delegate.mTextAlign = align;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700881 }
882
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800883 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700884 /*package*/ static float native_getFontMetrics(int native_paint, FontMetrics metrics) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800885 // get the delegate from the native int.
886 Paint_Delegate delegate = sManager.getDelegate(native_paint);
887 if (delegate == null) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800888 return 0.f;
889 }
890
891 return delegate.getFontMetrics(metrics);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700892 }
893
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800894 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700895 /*package*/ static int native_getTextWidths(int native_object, char[] text, int index,
896 int count, float[] widths) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800897 // get the delegate from the native int.
898 Paint_Delegate delegate = sManager.getDelegate(native_object);
899 if (delegate == null) {
900 return 0;
901 }
902
903 if (delegate.mFonts.size() > 0) {
904 // FIXME: handle multi-char characters (see measureText)
905 float totalAdvance = 0;
906 for (int i = 0; i < count; i++) {
907 char c = text[i + index];
908 boolean found = false;
909 for (FontInfo info : delegate.mFonts) {
910 if (info.mFont.canDisplay(c)) {
911 float adv = info.mMetrics.charWidth(c);
912 totalAdvance += adv;
913 if (widths != null) {
914 widths[i] = adv;
915 }
916
917 found = true;
918 break;
919 }
920 }
921
922 if (found == false) {
923 // no advance for this char.
924 if (widths != null) {
925 widths[i] = 0.f;
926 }
927 }
928 }
929
930 return (int) totalAdvance;
931 }
932
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800933 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700934 }
935
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800936 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700937 /*package*/ static int native_getTextWidths(int native_object, String text, int start,
938 int end, float[] widths) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800939 return native_getTextWidths(native_object, text.toCharArray(), start, end - start, widths);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700940 }
941
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800942 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700943 /*package*/ static float native_getTextRunAdvances(int native_object,
944 char[] text, int index, int count, int contextIndex, int contextCount,
945 int flags, float[] advances, int advancesIndex) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700946 // get the delegate from the native int.
947 Paint_Delegate delegate = sManager.getDelegate(native_object);
948 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700949 return 0.f;
950 }
951
952 if (delegate.mFonts.size() > 0) {
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700953 // FIXME: handle multi-char characters (see measureText)
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700954 float totalAdvance = 0;
955 for (int i = 0; i < count; i++) {
956 char c = text[i + index];
957 boolean found = false;
958 for (FontInfo info : delegate.mFonts) {
959 if (info.mFont.canDisplay(c)) {
960 float adv = info.mMetrics.charWidth(c);
961 totalAdvance += adv;
962 if (advances != null) {
963 advances[i] = adv;
964 }
965
966 found = true;
967 break;
968 }
969 }
970
971 if (found == false) {
972 // no advance for this char.
973 if (advances != null) {
974 advances[i] = 0.f;
975 }
976 }
977 }
978
979 return totalAdvance;
980 }
981
982 return 0;
983
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700984 }
985
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800986 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700987 /*package*/ static float native_getTextRunAdvances(int native_object,
988 String text, int start, int end, int contextStart, int contextEnd,
989 int flags, float[] advances, int advancesIndex) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700990 // FIXME: support contextStart, contextEnd and direction flag
991 int count = end - start;
992 char[] buffer = TemporaryBuffer.obtain(count);
993 TextUtils.getChars(text, start, end, buffer, 0);
994
995 return native_getTextRunAdvances(native_object, buffer, 0, count, contextStart,
996 contextEnd - contextStart, flags, advances, advancesIndex);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700997 }
998
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800999 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001000 /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, char[] text,
1001 int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
1002 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001003 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1004 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
1005 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001006 }
1007
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001008 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001009 /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, String text,
1010 int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
1011 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001012 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1013 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
1014 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001015 }
1016
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001017 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001018 /*package*/ static void native_getTextPath(int native_object, int bidiFlags,
1019 char[] text, int index, int count, float x, float y, int path) {
1020 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001021 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1022 "Paint.getTextPath is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001023 }
1024
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001025 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001026 /*package*/ static void native_getTextPath(int native_object, int bidiFlags,
1027 String text, int start, int end, float x, float y, int path) {
1028 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001029 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1030 "Paint.getTextPath is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001031 }
1032
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001033 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001034 /*package*/ static void nativeGetStringBounds(int nativePaint, String text, int start,
1035 int end, Rect bounds) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001036 nativeGetCharArrayBounds(nativePaint, text.toCharArray(), start, end - start, bounds);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001037 }
1038
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001039 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001040 /*package*/ static void nativeGetCharArrayBounds(int nativePaint, char[] text, int index,
1041 int count, Rect bounds) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001042
1043 // get the delegate from the native int.
1044 Paint_Delegate delegate = sManager.getDelegate(nativePaint);
1045 if (delegate == null) {
1046 return;
1047 }
1048
1049 // FIXME should test if the main font can display all those characters.
1050 // See MeasureText
1051 if (delegate.mFonts.size() > 0) {
1052 FontInfo mainInfo = delegate.mFonts.get(0);
1053
1054 Rectangle2D rect = mainInfo.mFont.getStringBounds(text, index, index + count,
1055 delegate.mFontContext);
1056 bounds.set(0, 0, (int) rect.getWidth(), (int) rect.getHeight());
1057 }
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001058 }
1059
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001060 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001061 /*package*/ static void finalizer(int nativePaint) {
Xavier Ducrohet91672792011-02-22 11:54:37 -08001062 sManager.removeJavaReferenceFor(nativePaint);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001063 }
1064
1065 // ---- Private delegate/helper methods ----
1066
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001067 /*package*/ Paint_Delegate() {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001068 reset();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001069 }
1070
1071 private Paint_Delegate(Paint_Delegate paint) {
1072 set(paint);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001073 }
1074
1075 private void set(Paint_Delegate paint) {
1076 mFlags = paint.mFlags;
1077 mColor = paint.mColor;
1078 mStyle = paint.mStyle;
1079 mCap = paint.mCap;
1080 mJoin = paint.mJoin;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001081 mTextAlign = paint.mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001082 mTypeface = paint.mTypeface;
1083 mStrokeWidth = paint.mStrokeWidth;
1084 mStrokeMiter = paint.mStrokeMiter;
1085 mTextSize = paint.mTextSize;
1086 mTextScaleX = paint.mTextScaleX;
1087 mTextSkewX = paint.mTextSkewX;
Xavier Ducroheta313b652010-11-01 18:45:20 -07001088 mXfermode = paint.mXfermode;
1089 mColorFilter = paint.mColorFilter;
1090 mShader = paint.mShader;
1091 mPathEffect = paint.mPathEffect;
1092 mMaskFilter = paint.mMaskFilter;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001093 mRasterizer = paint.mRasterizer;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001094 updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001095 }
1096
1097 private void reset() {
1098 mFlags = Paint.DEFAULT_PAINT_FLAGS;
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001099 mColor = 0xFF000000;
Xavier Ducrohet66225222010-12-21 01:33:04 -08001100 mStyle = Paint.Style.FILL.nativeInt;
1101 mCap = Paint.Cap.BUTT.nativeInt;
1102 mJoin = Paint.Join.MITER.nativeInt;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001103 mTextAlign = 0;
Xavier Ducrohet91672792011-02-22 11:54:37 -08001104 mTypeface = Typeface_Delegate.getDelegate(Typeface.sDefaults[0].native_instance);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001105 mStrokeWidth = 1.f;
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001106 mStrokeMiter = 4.f;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001107 mTextSize = 20.f;
1108 mTextScaleX = 1.f;
1109 mTextSkewX = 0.f;
Xavier Ducrohet91672792011-02-22 11:54:37 -08001110 mXfermode = null;
1111 mColorFilter = null;
1112 mShader = null;
1113 mPathEffect = null;
1114 mMaskFilter = null;
1115 mRasterizer = null;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001116 updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001117 }
1118
1119 /**
1120 * Update the {@link Font} object from the typeface, text size and scaling
1121 */
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001122 @SuppressWarnings("deprecation")
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001123 private void updateFontObject() {
Xavier Ducrohet91672792011-02-22 11:54:37 -08001124 if (mTypeface != null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001125 // Get the fonts from the TypeFace object.
Xavier Ducrohet91672792011-02-22 11:54:37 -08001126 List<Font> fonts = mTypeface.getFonts();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001127
1128 // create new font objects as well as FontMetrics, based on the current text size
1129 // and skew info.
1130 ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(fonts.size());
1131 for (Font font : fonts) {
1132 FontInfo info = new FontInfo();
1133 info.mFont = font.deriveFont(mTextSize);
1134 if (mTextScaleX != 1.0 || mTextSkewX != 0) {
1135 // TODO: support skew
1136 info.mFont = info.mFont.deriveFont(new AffineTransform(
1137 mTextScaleX, mTextSkewX, 0, 0, 1, 0));
1138 }
1139 info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont);
1140
1141 infoList.add(info);
1142 }
1143
1144 mFonts = Collections.unmodifiableList(infoList);
1145 }
1146 }
1147
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001148 /*package*/ float measureText(char[] text, int index, int count) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001149
1150 // WARNING: the logic in this method is similar to Canvas_Delegate.native_drawText
1151 // Any change to this method should be reflected there as well
1152
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001153 if (mFonts.size() > 0) {
1154 FontInfo mainFont = mFonts.get(0);
1155 int i = index;
1156 int lastIndex = index + count;
1157 float total = 0f;
1158 while (i < lastIndex) {
1159 // always start with the main font.
1160 int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
1161 if (upTo == -1) {
1162 // shortcut to exit
1163 return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i);
1164 } else if (upTo > 0) {
1165 total += mainFont.mMetrics.charsWidth(text, i, upTo - i);
1166 i = upTo;
1167 // don't call continue at this point. Since it is certain the main font
1168 // cannot display the font a index upTo (now ==i), we move on to the
1169 // fallback fonts directly.
1170 }
1171
1172 // no char supported, attempt to read the next char(s) with the
1173 // fallback font. In this case we only test the first character
1174 // and then go back to test with the main font.
1175 // Special test for 2-char characters.
1176 boolean foundFont = false;
1177 for (int f = 1 ; f < mFonts.size() ; f++) {
1178 FontInfo fontInfo = mFonts.get(f);
1179
1180 // need to check that the font can display the character. We test
1181 // differently if the char is a high surrogate.
1182 int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
1183 upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
1184 if (upTo == -1) {
1185 total += fontInfo.mMetrics.charsWidth(text, i, charCount);
1186 i += charCount;
1187 foundFont = true;
1188 break;
1189
1190 }
1191 }
1192
1193 // in case no font can display the char, measure it with the main font.
1194 if (foundFont == false) {
1195 int size = Character.isHighSurrogate(text[i]) ? 2 : 1;
1196 total += mainFont.mMetrics.charsWidth(text, i, size);
1197 i += size;
1198 }
1199 }
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001200
1201 return total;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001202 }
1203
1204 return 0;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001205 }
1206
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -08001207 private float getFontMetrics(FontMetrics metrics) {
1208 if (mFonts.size() > 0) {
1209 java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics;
1210 if (metrics != null) {
1211 // Android expects negative ascent so we invert the value from Java.
1212 metrics.top = - javaMetrics.getMaxAscent();
1213 metrics.ascent = - javaMetrics.getAscent();
1214 metrics.descent = javaMetrics.getDescent();
1215 metrics.bottom = javaMetrics.getMaxDescent();
1216 metrics.leading = javaMetrics.getLeading();
1217 }
1218
1219 return javaMetrics.getHeight();
1220 }
1221
1222 return 0;
1223 }
1224
1225
1226
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001227 private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) {
1228 // get the delegate from the native int.
1229 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
1230 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001231 return;
1232 }
1233
1234 if (flagValue) {
1235 delegate.mFlags |= flagMask;
1236 } else {
1237 delegate.mFlags &= ~flagMask;
1238 }
1239 }
1240}