blob: f5d2547799d8021c85ec75a1d610be1cf53a10c5 [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;
35import java.util.ArrayList;
36import java.util.Collections;
37import java.util.List;
38
39/**
40 * Delegate implementing the native methods of android.graphics.Paint
41 *
42 * Through the layoutlib_create tool, the original native methods of Paint have been replaced
43 * by calls to methods of the same name in this delegate class.
44 *
45 * This class behaves like the original native implementation, but in Java, keeping previously
46 * native data into its own objects and mapping them to int that are sent back and forth between
47 * it and the original Paint class.
48 *
49 * @see DelegateManager
50 *
51 */
52public class Paint_Delegate {
53
54 /**
55 * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}.
56 */
Xavier Ducrohet37f21802010-11-01 16:17:18 -070057 /*package*/ static final class FontInfo {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070058 Font mFont;
59 java.awt.FontMetrics mMetrics;
60 }
61
62 // ---- delegate manager ----
63 private static final DelegateManager<Paint_Delegate> sManager =
64 new DelegateManager<Paint_Delegate>();
65
66 // ---- delegate helper data ----
67 private List<FontInfo> mFonts;
68 private final FontRenderContext mFontContext = new FontRenderContext(
69 new AffineTransform(), true, true);
70
71 // ---- delegate data ----
72 private int mFlags;
73 private int mColor;
74 private int mStyle;
75 private int mCap;
76 private int mJoin;
Xavier Ducrohet37f21802010-11-01 16:17:18 -070077 private int mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070078 private int mTypeface;
79 private float mStrokeWidth;
80 private float mStrokeMiter;
81 private float mTextSize;
82 private float mTextScaleX;
83 private float mTextSkewX;
84
Xavier Ducroheta313b652010-11-01 18:45:20 -070085 private int mXfermode;
86 private int mColorFilter;
87 private int mShader;
88 private int mPathEffect;
89 private int mMaskFilter;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -080090 private int mRasterizer;
Xavier Ducroheta313b652010-11-01 18:45:20 -070091
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070092
93 // ---- Public Helper methods ----
94
Xavier Ducrohet37f21802010-11-01 16:17:18 -070095 public static Paint_Delegate getDelegate(int native_paint) {
96 return sManager.getDelegate(native_paint);
97 }
98
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070099 /**
100 * Returns the list of {@link Font} objects. The first item is the main font, the rest
101 * are fall backs for characters not present in the main font.
102 */
103 public List<FontInfo> getFonts() {
104 return mFonts;
105 }
106
Xavier Ducroheta313b652010-11-01 18:45:20 -0700107 public boolean isAntiAliased() {
108 return (mFlags & Paint.ANTI_ALIAS_FLAG) != 0;
109 }
110
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700111 public boolean isFilterBitmap() {
112 return (mFlags & Paint.FILTER_BITMAP_FLAG) != 0;
113 }
114
115 public int getStyle() {
116 return mStyle;
117 }
118
119 public int getColor() {
120 return mColor;
121 }
122
Xavier Ducrohet66225222010-12-21 01:33:04 -0800123 public int getAlpha() {
124 return mColor >>> 24;
125 }
126
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800127 public void setAlpha(int alpha) {
128 mColor = (alpha << 24) | (mColor & 0x00FFFFFF);
129 }
130
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700131 public int getTextAlign() {
132 return mTextAlign;
133 }
134
135 public float getStrokeWidth() {
136 return mStrokeWidth;
137 }
138
Xavier Ducrohet66225222010-12-21 01:33:04 -0800139 /**
140 * returns the value of stroke miter needed by the java api.
141 */
142 public float getJavaStrokeMiter() {
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800143 float miter = mStrokeMiter * mStrokeWidth;
144 if (miter < 1.f) {
145 miter = 1.f;
146 }
147 return miter;
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700148 }
149
150 public int getJavaCap() {
151 switch (Paint.sCapArray[mCap]) {
152 case BUTT:
153 return BasicStroke.CAP_BUTT;
154 case ROUND:
155 return BasicStroke.CAP_ROUND;
156 default:
157 case SQUARE:
158 return BasicStroke.CAP_SQUARE;
159 }
160 }
161
162 public int getJavaJoin() {
163 switch (Paint.sJoinArray[mJoin]) {
164 default:
165 case MITER:
166 return BasicStroke.JOIN_MITER;
167 case ROUND:
168 return BasicStroke.JOIN_ROUND;
169 case BEVEL:
170 return BasicStroke.JOIN_BEVEL;
171 }
172 }
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700173
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800174 public Stroke getJavaStroke() {
175 PathEffect_Delegate effectDelegate = PathEffect_Delegate.getDelegate(mPathEffect);
176 if (effectDelegate != null) {
177 if (effectDelegate.isSupported()) {
178 Stroke stroke = effectDelegate.getStroke(this);
179 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 Ducrohetb9761242010-12-23 10:22:14 -0800185 effectDelegate.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() {
204 return Xfermode_Delegate.getDelegate(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() {
213 return ColorFilter_Delegate.getDelegate(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() {
222 return Shader_Delegate.getDelegate(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() {
231 return MaskFilter_Delegate.getDelegate(mMaskFilter);
232 }
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() {
240 return Rasterizer_Delegate.getDelegate(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) {
545 // WARNING: the logic in this method is similar to Canvas.drawText.
546 // Any change to this method should be reflected in Canvas.drawText
547
548 // get the delegate
549 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
550 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700551 return 0;
552 }
553
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700554 return delegate.measureText(text, index, count);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700555 }
556
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800557 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700558 /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end) {
559 return native_measureText(thisPaint, text.toCharArray(), start, end - start);
560 }
561
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800562 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700563 /*package*/ static float native_measureText(Paint thisPaint, String text) {
564 return native_measureText(thisPaint, text.toCharArray(), 0, text.length());
565 }
566
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800567 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700568 /*package*/ static int native_breakText(Paint thisPaint, char[] text, int index, int count,
569 float maxWidth, float[] measuredWidth) {
570 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800571 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
572 "Paint.native_breakText is not supported.", null, null /*data*/);
573 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700574 }
575
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800576 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700577 /*package*/ static int native_breakText(Paint thisPaint, String text, boolean measureForwards,
578 float maxWidth, float[] measuredWidth) {
579 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800580 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
581 "Paint.native_breakText is not supported.", null, null /*data*/);
582 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700583 }
584
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800585 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700586 /*package*/ static int native_init() {
587 Paint_Delegate newDelegate = new Paint_Delegate();
588 return sManager.addDelegate(newDelegate);
589 }
590
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800591 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700592 /*package*/ static int native_initWithPaint(int paint) {
593 // get the delegate from the native int.
594 Paint_Delegate delegate = sManager.getDelegate(paint);
595 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700596 return 0;
597 }
598
599 Paint_Delegate newDelegate = new Paint_Delegate(delegate);
600 return sManager.addDelegate(newDelegate);
601 }
602
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800603 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700604 /*package*/ static void native_reset(int native_object) {
605 // get the delegate from the native int.
606 Paint_Delegate delegate = sManager.getDelegate(native_object);
607 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700608 return;
609 }
610
611 delegate.reset();
612 }
613
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800614 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700615 /*package*/ static void native_set(int native_dst, int native_src) {
616 // get the delegate from the native int.
617 Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
618 if (delegate_dst == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700619 return;
620 }
621
622 // get the delegate from the native int.
623 Paint_Delegate delegate_src = sManager.getDelegate(native_src);
624 if (delegate_src == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700625 return;
626 }
627
628 delegate_dst.set(delegate_src);
629 }
630
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800631 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700632 /*package*/ static int native_getStyle(int native_object) {
633 // get the delegate from the native int.
634 Paint_Delegate delegate = sManager.getDelegate(native_object);
635 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700636 return 0;
637 }
638
639 return delegate.mStyle;
640 }
641
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800642 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700643 /*package*/ static void native_setStyle(int native_object, int style) {
644 // get the delegate from the native int.
645 Paint_Delegate delegate = sManager.getDelegate(native_object);
646 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700647 return;
648 }
649
650 delegate.mStyle = style;
651 }
652
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800653 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700654 /*package*/ static int native_getStrokeCap(int native_object) {
655 // get the delegate from the native int.
656 Paint_Delegate delegate = sManager.getDelegate(native_object);
657 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700658 return 0;
659 }
660
661 return delegate.mCap;
662 }
663
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800664 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700665 /*package*/ static void native_setStrokeCap(int native_object, int cap) {
666 // get the delegate from the native int.
667 Paint_Delegate delegate = sManager.getDelegate(native_object);
668 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700669 return;
670 }
671
672 delegate.mCap = cap;
673 }
674
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800675 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700676 /*package*/ static int native_getStrokeJoin(int native_object) {
677 // get the delegate from the native int.
678 Paint_Delegate delegate = sManager.getDelegate(native_object);
679 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700680 return 0;
681 }
682
683 return delegate.mJoin;
684 }
685
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800686 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700687 /*package*/ static void native_setStrokeJoin(int native_object, int join) {
688 // get the delegate from the native int.
689 Paint_Delegate delegate = sManager.getDelegate(native_object);
690 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700691 return;
692 }
693
694 delegate.mJoin = join;
695 }
696
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800697 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700698 /*package*/ static boolean native_getFillPath(int native_object, int src, int dst) {
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800699 Paint_Delegate paint = sManager.getDelegate(native_object);
700 if (paint == null) {
701 return false;
702 }
703
704 Path_Delegate srcPath = Path_Delegate.getDelegate(src);
705 if (srcPath == null) {
706 return true;
707 }
708
709 Path_Delegate dstPath = Path_Delegate.getDelegate(dst);
710 if (dstPath == null) {
711 return true;
712 }
713
714 Stroke stroke = paint.getJavaStroke();
715 Shape strokeShape = stroke.createStrokedShape(srcPath.getJavaShape());
716
717 dstPath.setJavaShape(strokeShape);
718
719 // FIXME figure out the return value?
720 return true;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700721 }
722
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800723 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700724 /*package*/ static int native_setShader(int native_object, int shader) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700725 // get the delegate from the native int.
726 Paint_Delegate delegate = sManager.getDelegate(native_object);
727 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700728 return shader;
729 }
730
731 return delegate.mShader = shader;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700732 }
733
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800734 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700735 /*package*/ static int native_setColorFilter(int native_object, int filter) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700736 // get the delegate from the native int.
737 Paint_Delegate delegate = sManager.getDelegate(native_object);
738 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700739 return filter;
740 }
741
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800742 delegate.mColorFilter = filter;
743
744 // since none of those are supported, display a fidelity warning right away
745 ColorFilter_Delegate filterDelegate = delegate.getColorFilter();
746 if (filterDelegate != null && filterDelegate.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800747 Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800748 filterDelegate.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800749 }
750
751 return filter;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700752 }
753
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800754 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700755 /*package*/ static int native_setXfermode(int native_object, int xfermode) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700756 // get the delegate from the native int.
757 Paint_Delegate delegate = sManager.getDelegate(native_object);
758 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700759 return xfermode;
760 }
761
762 return delegate.mXfermode = xfermode;
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_setPathEffect(int native_object, int effect) {
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 effect;
771 }
772
773 return delegate.mPathEffect = effect;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700774 }
775
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800776 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700777 /*package*/ static int native_setMaskFilter(int native_object, int maskfilter) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700778 // get the delegate from the native int.
779 Paint_Delegate delegate = sManager.getDelegate(native_object);
780 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700781 return maskfilter;
782 }
783
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800784 delegate.mMaskFilter = maskfilter;
785
786 // since none of those are supported, display a fidelity warning right away
787 MaskFilter_Delegate filterDelegate = delegate.getMaskFilter();
788 if (filterDelegate != null && filterDelegate.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800789 Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800790 filterDelegate.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800791 }
792
793 return maskfilter;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700794 }
795
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800796 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700797 /*package*/ static int native_setTypeface(int native_object, int typeface) {
798 // get the delegate from the native int.
799 Paint_Delegate delegate = sManager.getDelegate(native_object);
800 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700801 return 0;
802 }
803
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800804 delegate.mTypeface = typeface;
805 delegate.updateFontObject();
806 return delegate.mTypeface;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700807 }
808
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800809 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700810 /*package*/ static int native_setRasterizer(int native_object, int rasterizer) {
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800811 // get the delegate from the native int.
812 Paint_Delegate delegate = sManager.getDelegate(native_object);
813 if (delegate == null) {
814 return rasterizer;
815 }
816
817 delegate.mRasterizer = rasterizer;
818
819 // since none of those are supported, display a fidelity warning right away
820 Rasterizer_Delegate rasterizerDelegate = delegate.getRasterizer();
821 if (rasterizerDelegate != null && rasterizerDelegate.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800822 Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800823 rasterizerDelegate.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800824 }
825
826 return rasterizer;
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_getTextAlign(int native_object) {
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 Ducrohet37f21802010-11-01 16:17:18 -0700837 return delegate.mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700838 }
839
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800840 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700841 /*package*/ static void native_setTextAlign(int native_object, int align) {
842 // get the delegate from the native int.
843 Paint_Delegate delegate = sManager.getDelegate(native_object);
844 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700845 return;
846 }
847
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700848 delegate.mTextAlign = align;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700849 }
850
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800851 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700852 /*package*/ static float native_getFontMetrics(int native_paint, FontMetrics metrics) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800853 // get the delegate from the native int.
854 Paint_Delegate delegate = sManager.getDelegate(native_paint);
855 if (delegate == null) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800856 return 0.f;
857 }
858
859 return delegate.getFontMetrics(metrics);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700860 }
861
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800862 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700863 /*package*/ static int native_getTextWidths(int native_object, char[] text, int index,
864 int count, float[] widths) {
865 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800866 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
867 "Paint.getTextWidths is not supported.", null, null /*data*/);
868 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700869 }
870
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800871 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700872 /*package*/ static int native_getTextWidths(int native_object, String text, int start,
873 int end, float[] widths) {
874 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800875 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
876 "Paint.getTextWidths is not supported.", null, null /*data*/);
877 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700878 }
879
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800880 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700881 /*package*/ static float native_getTextRunAdvances(int native_object,
882 char[] text, int index, int count, int contextIndex, int contextCount,
883 int flags, float[] advances, int advancesIndex) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700884 // get the delegate from the native int.
885 Paint_Delegate delegate = sManager.getDelegate(native_object);
886 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700887 return 0.f;
888 }
889
890 if (delegate.mFonts.size() > 0) {
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700891 // FIXME: handle multi-char characters (see measureText)
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700892 float totalAdvance = 0;
893 for (int i = 0; i < count; i++) {
894 char c = text[i + index];
895 boolean found = false;
896 for (FontInfo info : delegate.mFonts) {
897 if (info.mFont.canDisplay(c)) {
898 float adv = info.mMetrics.charWidth(c);
899 totalAdvance += adv;
900 if (advances != null) {
901 advances[i] = adv;
902 }
903
904 found = true;
905 break;
906 }
907 }
908
909 if (found == false) {
910 // no advance for this char.
911 if (advances != null) {
912 advances[i] = 0.f;
913 }
914 }
915 }
916
917 return totalAdvance;
918 }
919
920 return 0;
921
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700922 }
923
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800924 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700925 /*package*/ static float native_getTextRunAdvances(int native_object,
926 String text, int start, int end, int contextStart, int contextEnd,
927 int flags, float[] advances, int advancesIndex) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700928 // FIXME: support contextStart, contextEnd and direction flag
929 int count = end - start;
930 char[] buffer = TemporaryBuffer.obtain(count);
931 TextUtils.getChars(text, start, end, buffer, 0);
932
933 return native_getTextRunAdvances(native_object, buffer, 0, count, contextStart,
934 contextEnd - contextStart, flags, advances, advancesIndex);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700935 }
936
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800937 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700938 /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, char[] text,
939 int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
940 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800941 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
942 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
943 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700944 }
945
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800946 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700947 /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, String text,
948 int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
949 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800950 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
951 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
952 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700953 }
954
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800955 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700956 /*package*/ static void native_getTextPath(int native_object, int bidiFlags,
957 char[] text, int index, int count, float x, float y, int path) {
958 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800959 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
960 "Paint.getTextPath is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700961 }
962
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800963 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700964 /*package*/ static void native_getTextPath(int native_object, int bidiFlags,
965 String text, int start, int end, float x, float y, int path) {
966 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800967 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
968 "Paint.getTextPath is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700969 }
970
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800971 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700972 /*package*/ static void nativeGetStringBounds(int nativePaint, String text, int start,
973 int end, Rect bounds) {
974 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800975 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
976 "Paint.getStringBounds is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700977 }
978
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800979 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700980 /*package*/ static void nativeGetCharArrayBounds(int nativePaint, char[] text, int index,
981 int count, Rect bounds) {
982 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800983 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
984 "Paint.getCharArrayBounds is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700985 }
986
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800987 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700988 /*package*/ static void finalizer(int nativePaint) {
989 sManager.removeDelegate(nativePaint);
990 }
991
992 // ---- Private delegate/helper methods ----
993
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800994 /*package*/ Paint_Delegate() {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700995 reset();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700996 }
997
998 private Paint_Delegate(Paint_Delegate paint) {
999 set(paint);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001000 }
1001
1002 private void set(Paint_Delegate paint) {
1003 mFlags = paint.mFlags;
1004 mColor = paint.mColor;
1005 mStyle = paint.mStyle;
1006 mCap = paint.mCap;
1007 mJoin = paint.mJoin;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001008 mTextAlign = paint.mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001009 mTypeface = paint.mTypeface;
1010 mStrokeWidth = paint.mStrokeWidth;
1011 mStrokeMiter = paint.mStrokeMiter;
1012 mTextSize = paint.mTextSize;
1013 mTextScaleX = paint.mTextScaleX;
1014 mTextSkewX = paint.mTextSkewX;
Xavier Ducroheta313b652010-11-01 18:45:20 -07001015 mXfermode = paint.mXfermode;
1016 mColorFilter = paint.mColorFilter;
1017 mShader = paint.mShader;
1018 mPathEffect = paint.mPathEffect;
1019 mMaskFilter = paint.mMaskFilter;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001020 mRasterizer = paint.mRasterizer;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001021 updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001022 }
1023
1024 private void reset() {
1025 mFlags = Paint.DEFAULT_PAINT_FLAGS;
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001026 mColor = 0xFF000000;
Xavier Ducrohet66225222010-12-21 01:33:04 -08001027 mStyle = Paint.Style.FILL.nativeInt;
1028 mCap = Paint.Cap.BUTT.nativeInt;
1029 mJoin = Paint.Join.MITER.nativeInt;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001030 mTextAlign = 0;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001031 mTypeface = Typeface.sDefaults[0].native_instance;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001032 mStrokeWidth = 1.f;
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001033 mStrokeMiter = 4.f;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001034 mTextSize = 20.f;
1035 mTextScaleX = 1.f;
1036 mTextSkewX = 0.f;
Xavier Ducroheta313b652010-11-01 18:45:20 -07001037 mXfermode = 0;
1038 mColorFilter = 0;
1039 mShader = 0;
1040 mPathEffect = 0;
1041 mMaskFilter = 0;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001042 mRasterizer = 0;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001043 updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001044 }
1045
1046 /**
1047 * Update the {@link Font} object from the typeface, text size and scaling
1048 */
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001049 @SuppressWarnings("deprecation")
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001050 private void updateFontObject() {
1051 if (mTypeface != 0) {
1052 // Get the fonts from the TypeFace object.
1053 List<Font> fonts = Typeface_Delegate.getFonts(mTypeface);
1054
1055 // create new font objects as well as FontMetrics, based on the current text size
1056 // and skew info.
1057 ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(fonts.size());
1058 for (Font font : fonts) {
1059 FontInfo info = new FontInfo();
1060 info.mFont = font.deriveFont(mTextSize);
1061 if (mTextScaleX != 1.0 || mTextSkewX != 0) {
1062 // TODO: support skew
1063 info.mFont = info.mFont.deriveFont(new AffineTransform(
1064 mTextScaleX, mTextSkewX, 0, 0, 1, 0));
1065 }
1066 info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont);
1067
1068 infoList.add(info);
1069 }
1070
1071 mFonts = Collections.unmodifiableList(infoList);
1072 }
1073 }
1074
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001075 /*package*/ float measureText(char[] text, int index, int count) {
1076 if (mFonts.size() > 0) {
1077 FontInfo mainFont = mFonts.get(0);
1078 int i = index;
1079 int lastIndex = index + count;
1080 float total = 0f;
1081 while (i < lastIndex) {
1082 // always start with the main font.
1083 int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
1084 if (upTo == -1) {
1085 // shortcut to exit
1086 return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i);
1087 } else if (upTo > 0) {
1088 total += mainFont.mMetrics.charsWidth(text, i, upTo - i);
1089 i = upTo;
1090 // don't call continue at this point. Since it is certain the main font
1091 // cannot display the font a index upTo (now ==i), we move on to the
1092 // fallback fonts directly.
1093 }
1094
1095 // no char supported, attempt to read the next char(s) with the
1096 // fallback font. In this case we only test the first character
1097 // and then go back to test with the main font.
1098 // Special test for 2-char characters.
1099 boolean foundFont = false;
1100 for (int f = 1 ; f < mFonts.size() ; f++) {
1101 FontInfo fontInfo = mFonts.get(f);
1102
1103 // need to check that the font can display the character. We test
1104 // differently if the char is a high surrogate.
1105 int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
1106 upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
1107 if (upTo == -1) {
1108 total += fontInfo.mMetrics.charsWidth(text, i, charCount);
1109 i += charCount;
1110 foundFont = true;
1111 break;
1112
1113 }
1114 }
1115
1116 // in case no font can display the char, measure it with the main font.
1117 if (foundFont == false) {
1118 int size = Character.isHighSurrogate(text[i]) ? 2 : 1;
1119 total += mainFont.mMetrics.charsWidth(text, i, size);
1120 i += size;
1121 }
1122 }
1123 }
1124
1125 return 0;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001126 }
1127
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -08001128 private float getFontMetrics(FontMetrics metrics) {
1129 if (mFonts.size() > 0) {
1130 java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics;
1131 if (metrics != null) {
1132 // Android expects negative ascent so we invert the value from Java.
1133 metrics.top = - javaMetrics.getMaxAscent();
1134 metrics.ascent = - javaMetrics.getAscent();
1135 metrics.descent = javaMetrics.getDescent();
1136 metrics.bottom = javaMetrics.getMaxDescent();
1137 metrics.leading = javaMetrics.getLeading();
1138 }
1139
1140 return javaMetrics.getHeight();
1141 }
1142
1143 return 0;
1144 }
1145
1146
1147
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001148 private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) {
1149 // get the delegate from the native int.
1150 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
1151 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001152 return;
1153 }
1154
1155 if (flagValue) {
1156 delegate.mFlags |= flagMask;
1157 } else {
1158 delegate.mFlags &= ~flagMask;
1159 }
1160 }
1161}