blob: c9c98007556fbc32cdc3ae017c59eecd855822d1 [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;
Xavier Ducrohet43526ab2012-04-23 17:41:37 -070039import java.util.Locale;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070040
41/**
42 * Delegate implementing the native methods of android.graphics.Paint
43 *
44 * Through the layoutlib_create tool, the original native methods of Paint have been replaced
45 * by calls to methods of the same name in this delegate class.
46 *
47 * This class behaves like the original native implementation, but in Java, keeping previously
48 * native data into its own objects and mapping them to int that are sent back and forth between
49 * it and the original Paint class.
50 *
51 * @see DelegateManager
52 *
53 */
54public class Paint_Delegate {
55
56 /**
57 * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}.
58 */
Xavier Ducrohet37f21802010-11-01 16:17:18 -070059 /*package*/ static final class FontInfo {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070060 Font mFont;
61 java.awt.FontMetrics mMetrics;
62 }
63
64 // ---- delegate manager ----
65 private static final DelegateManager<Paint_Delegate> sManager =
Xavier Ducrohetb2de8392011-02-23 16:51:08 -080066 new DelegateManager<Paint_Delegate>(Paint_Delegate.class);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070067
68 // ---- delegate helper data ----
69 private List<FontInfo> mFonts;
70 private final FontRenderContext mFontContext = new FontRenderContext(
71 new AffineTransform(), true, true);
72
73 // ---- delegate data ----
74 private int mFlags;
75 private int mColor;
76 private int mStyle;
77 private int mCap;
78 private int mJoin;
Xavier Ducrohet37f21802010-11-01 16:17:18 -070079 private int mTextAlign;
Xavier Ducrohet91672792011-02-22 11:54:37 -080080 private Typeface_Delegate mTypeface;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070081 private float mStrokeWidth;
82 private float mStrokeMiter;
83 private float mTextSize;
84 private float mTextScaleX;
85 private float mTextSkewX;
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -070086 private int mHintingMode = Paint.HINTING_ON;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070087
Xavier Ducrohet91672792011-02-22 11:54:37 -080088 private Xfermode_Delegate mXfermode;
89 private ColorFilter_Delegate mColorFilter;
90 private Shader_Delegate mShader;
91 private PathEffect_Delegate mPathEffect;
92 private MaskFilter_Delegate mMaskFilter;
93 private Rasterizer_Delegate mRasterizer;
Xavier Ducroheta313b652010-11-01 18:45:20 -070094
Xavier Ducrohet43526ab2012-04-23 17:41:37 -070095 private Locale mLocale = Locale.getDefault();
96
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070097
98 // ---- Public Helper methods ----
99
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700100 public static Paint_Delegate getDelegate(int native_paint) {
101 return sManager.getDelegate(native_paint);
102 }
103
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700104 /**
105 * Returns the list of {@link Font} objects. The first item is the main font, the rest
106 * are fall backs for characters not present in the main font.
107 */
108 public List<FontInfo> getFonts() {
109 return mFonts;
110 }
111
Xavier Ducroheta313b652010-11-01 18:45:20 -0700112 public boolean isAntiAliased() {
113 return (mFlags & Paint.ANTI_ALIAS_FLAG) != 0;
114 }
115
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700116 public boolean isFilterBitmap() {
117 return (mFlags & Paint.FILTER_BITMAP_FLAG) != 0;
118 }
119
120 public int getStyle() {
121 return mStyle;
122 }
123
124 public int getColor() {
125 return mColor;
126 }
127
Xavier Ducrohet66225222010-12-21 01:33:04 -0800128 public int getAlpha() {
129 return mColor >>> 24;
130 }
131
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800132 public void setAlpha(int alpha) {
133 mColor = (alpha << 24) | (mColor & 0x00FFFFFF);
134 }
135
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700136 public int getTextAlign() {
137 return mTextAlign;
138 }
139
140 public float getStrokeWidth() {
141 return mStrokeWidth;
142 }
143
Xavier Ducrohet66225222010-12-21 01:33:04 -0800144 /**
145 * returns the value of stroke miter needed by the java api.
146 */
147 public float getJavaStrokeMiter() {
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800148 float miter = mStrokeMiter * mStrokeWidth;
149 if (miter < 1.f) {
150 miter = 1.f;
151 }
152 return miter;
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700153 }
154
155 public int getJavaCap() {
156 switch (Paint.sCapArray[mCap]) {
157 case BUTT:
158 return BasicStroke.CAP_BUTT;
159 case ROUND:
160 return BasicStroke.CAP_ROUND;
161 default:
162 case SQUARE:
163 return BasicStroke.CAP_SQUARE;
164 }
165 }
166
167 public int getJavaJoin() {
168 switch (Paint.sJoinArray[mJoin]) {
169 default:
170 case MITER:
171 return BasicStroke.JOIN_MITER;
172 case ROUND:
173 return BasicStroke.JOIN_ROUND;
174 case BEVEL:
175 return BasicStroke.JOIN_BEVEL;
176 }
177 }
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700178
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800179 public Stroke getJavaStroke() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800180 if (mPathEffect != null) {
181 if (mPathEffect.isSupported()) {
182 Stroke stroke = mPathEffect.getStroke(this);
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800183 assert stroke != null;
184 if (stroke != null) {
185 return stroke;
186 }
187 } else {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800188 Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800189 mPathEffect.getSupportMessage(),
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800190 null, null /*data*/);
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800191 }
192 }
193
194 // if no custom stroke as been set, set the default one.
195 return new BasicStroke(
196 getStrokeWidth(),
197 getJavaCap(),
198 getJavaJoin(),
199 getJavaStrokeMiter());
200 }
201
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800202 /**
203 * Returns the {@link Xfermode} delegate or null if none have been set
204 *
205 * @return the delegate or null.
206 */
207 public Xfermode_Delegate getXfermode() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800208 return mXfermode;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700209 }
210
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800211 /**
212 * Returns the {@link ColorFilter} delegate or null if none have been set
213 *
214 * @return the delegate or null.
215 */
216 public ColorFilter_Delegate getColorFilter() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800217 return mColorFilter;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700218 }
219
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800220 /**
221 * Returns the {@link Shader} delegate or null if none have been set
222 *
223 * @return the delegate or null.
224 */
225 public Shader_Delegate getShader() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800226 return mShader;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700227 }
228
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800229 /**
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800230 * Returns the {@link MaskFilter} delegate or null if none have been set
231 *
232 * @return the delegate or null.
233 */
234 public MaskFilter_Delegate getMaskFilter() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800235 return mMaskFilter;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800236 }
237
238 /**
239 * Returns the {@link Rasterizer} delegate or null if none have been set
240 *
241 * @return the delegate or null.
242 */
243 public Rasterizer_Delegate getRasterizer() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800244 return mRasterizer;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700245 }
246
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700247 // ---- native methods ----
248
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800249 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700250 /*package*/ static int getFlags(Paint thisPaint) {
251 // get the delegate from the native int.
252 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
253 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700254 return 0;
255 }
256
257 return delegate.mFlags;
258 }
259
Xavier Ducrohet43526ab2012-04-23 17:41:37 -0700260
261
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800262 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700263 /*package*/ static void setFlags(Paint thisPaint, int flags) {
264 // get the delegate from the native int.
265 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
266 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700267 return;
268 }
269
270 delegate.mFlags = flags;
271 }
272
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800273 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700274 /*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700275 setFlag(thisPaint, Paint.FILTER_BITMAP_FLAG, filter);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700276 }
277
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800278 @LayoutlibDelegate
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -0700279 /*package*/ static int getHinting(Paint thisPaint) {
280 // get the delegate from the native int.
281 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
282 if (delegate == null) {
283 return Paint.HINTING_ON;
284 }
285
286 return delegate.mHintingMode;
287 }
288
289 @LayoutlibDelegate
290 /*package*/ static void setHinting(Paint thisPaint, int mode) {
291 // get the delegate from the native int.
292 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
293 if (delegate == null) {
294 return;
295 }
296
297 delegate.mHintingMode = mode;
298 }
299
300 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700301 /*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) {
302 setFlag(thisPaint, Paint.ANTI_ALIAS_FLAG, aa);
303 }
304
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800305 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700306 /*package*/ static void setSubpixelText(Paint thisPaint, boolean subpixelText) {
307 setFlag(thisPaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
308 }
309
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800310 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700311 /*package*/ static void setUnderlineText(Paint thisPaint, boolean underlineText) {
312 setFlag(thisPaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
313 }
314
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800315 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700316 /*package*/ static void setStrikeThruText(Paint thisPaint, boolean strikeThruText) {
317 setFlag(thisPaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
318 }
319
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800320 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700321 /*package*/ static void setFakeBoldText(Paint thisPaint, boolean fakeBoldText) {
322 setFlag(thisPaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
323 }
324
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800325 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700326 /*package*/ static void setDither(Paint thisPaint, boolean dither) {
327 setFlag(thisPaint, Paint.DITHER_FLAG, dither);
328 }
329
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800330 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700331 /*package*/ static void setLinearText(Paint thisPaint, boolean linearText) {
332 setFlag(thisPaint, Paint.LINEAR_TEXT_FLAG, linearText);
333 }
334
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800335 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700336 /*package*/ static int getColor(Paint thisPaint) {
337 // get the delegate from the native int.
338 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
339 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700340 return 0;
341 }
342
343 return delegate.mColor;
344 }
345
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800346 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700347 /*package*/ static void setColor(Paint thisPaint, int color) {
348 // get the delegate from the native int.
349 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
350 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700351 return;
352 }
353
354 delegate.mColor = color;
355 }
356
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800357 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700358 /*package*/ static int getAlpha(Paint thisPaint) {
359 // get the delegate from the native int.
360 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
361 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700362 return 0;
363 }
364
Xavier Ducrohet66225222010-12-21 01:33:04 -0800365 return delegate.getAlpha();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700366 }
367
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800368 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700369 /*package*/ static void setAlpha(Paint thisPaint, int a) {
370 // get the delegate from the native int.
371 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
372 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700373 return;
374 }
375
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800376 delegate.setAlpha(a);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700377 }
378
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800379 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700380 /*package*/ static float getStrokeWidth(Paint thisPaint) {
381 // get the delegate from the native int.
382 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
383 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700384 return 1.f;
385 }
386
387 return delegate.mStrokeWidth;
388 }
389
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800390 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700391 /*package*/ static void setStrokeWidth(Paint thisPaint, float width) {
392 // get the delegate from the native int.
393 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
394 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700395 return;
396 }
397
398 delegate.mStrokeWidth = width;
399 }
400
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800401 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700402 /*package*/ static float getStrokeMiter(Paint thisPaint) {
403 // get the delegate from the native int.
404 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
405 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700406 return 1.f;
407 }
408
409 return delegate.mStrokeMiter;
410 }
411
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800412 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700413 /*package*/ static void setStrokeMiter(Paint thisPaint, float miter) {
414 // get the delegate from the native int.
415 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
416 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700417 return;
418 }
419
420 delegate.mStrokeMiter = miter;
421 }
422
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800423 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700424 /*package*/ static void nSetShadowLayer(Paint thisPaint, float radius, float dx, float dy,
425 int color) {
426 // FIXME
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800427 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800428 "Paint.setShadowLayer is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700429 }
430
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800431 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700432 /*package*/ static float getTextSize(Paint thisPaint) {
433 // get the delegate from the native int.
434 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
435 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700436 return 1.f;
437 }
438
439 return delegate.mTextSize;
440 }
441
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800442 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700443 /*package*/ static void setTextSize(Paint thisPaint, float textSize) {
444 // get the delegate from the native int.
445 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
446 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700447 return;
448 }
449
450 delegate.mTextSize = textSize;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800451 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700452 }
453
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800454 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700455 /*package*/ static float getTextScaleX(Paint thisPaint) {
456 // get the delegate from the native int.
457 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
458 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700459 return 1.f;
460 }
461
462 return delegate.mTextScaleX;
463 }
464
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800465 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700466 /*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) {
467 // get the delegate from the native int.
468 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
469 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700470 return;
471 }
472
473 delegate.mTextScaleX = scaleX;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800474 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700475 }
476
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800477 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700478 /*package*/ static float getTextSkewX(Paint thisPaint) {
479 // get the delegate from the native int.
480 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
481 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700482 return 1.f;
483 }
484
485 return delegate.mTextSkewX;
486 }
487
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800488 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700489 /*package*/ static void setTextSkewX(Paint thisPaint, float skewX) {
490 // get the delegate from the native int.
491 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
492 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700493 return;
494 }
495
496 delegate.mTextSkewX = skewX;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800497 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700498 }
499
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800500 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700501 /*package*/ static float ascent(Paint thisPaint) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800502 // get the delegate
503 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
504 if (delegate == null) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800505 return 0;
506 }
507
508 if (delegate.mFonts.size() > 0) {
509 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
510 // Android expects negative ascent so we invert the value from Java.
511 return - javaMetrics.getAscent();
512 }
513
514 return 0;
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 float descent(Paint thisPaint) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800519 // get the delegate
520 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
521 if (delegate == null) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800522 return 0;
523 }
524
525 if (delegate.mFonts.size() > 0) {
526 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
527 return javaMetrics.getDescent();
528 }
529
530 return 0;
531
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700532 }
533
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800534 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700535 /*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700536 // get the delegate
537 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
538 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700539 return 0;
540 }
541
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800542 return delegate.getFontMetrics(metrics);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700543 }
544
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800545 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700546 /*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700547 // get the delegate
548 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
549 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700550 return 0;
551 }
552
553 if (delegate.mFonts.size() > 0) {
554 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
555 if (fmi != null) {
556 // Android expects negative ascent so we invert the value from Java.
557 fmi.top = - javaMetrics.getMaxAscent();
558 fmi.ascent = - javaMetrics.getAscent();
559 fmi.descent = javaMetrics.getDescent();
560 fmi.bottom = javaMetrics.getMaxDescent();
561 fmi.leading = javaMetrics.getLeading();
562 }
563
564 return javaMetrics.getHeight();
565 }
566
567 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700568 }
569
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800570 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700571 /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700572 int count, int bidiFlags) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700573 // get the delegate
574 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
575 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700576 return 0;
577 }
578
Deepanshu Guptac398f182013-05-23 15:20:04 -0700579 return delegate.measureText(text, index, count, bidiFlags);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700580 }
581
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800582 @LayoutlibDelegate
Deepanshu Guptac398f182013-05-23 15:20:04 -0700583 /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end,
584 int bidiFlags) {
585 return native_measureText(thisPaint, text.toCharArray(), start, end - start, bidiFlags);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700586 }
587
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800588 @LayoutlibDelegate
Deepanshu Guptac398f182013-05-23 15:20:04 -0700589 /*package*/ static float native_measureText(Paint thisPaint, String text, int bidiFlags) {
590 return native_measureText(thisPaint, text.toCharArray(), 0, text.length(), bidiFlags);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700591 }
592
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800593 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700594 /*package*/ static int native_breakText(Paint thisPaint, char[] text, int index, int count,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700595 float maxWidth, int bidiFlags, float[] measuredWidth) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800596
597 // get the delegate
598 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
599 if (delegate == null) {
600 return 0;
601 }
602
603 int inc = count > 0 ? 1 : -1;
604
605 int measureIndex = 0;
606 float measureAcc = 0;
607 for (int i = index; i != index + count; i += inc, measureIndex++) {
608 int start, end;
609 if (i < index) {
610 start = i;
611 end = index;
612 } else {
613 start = index;
614 end = i;
615 }
616
617 // measure from start to end
Deepanshu Guptac398f182013-05-23 15:20:04 -0700618 float res = delegate.measureText(text, start, end - start + 1, bidiFlags);
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800619
620 if (measuredWidth != null) {
621 measuredWidth[measureIndex] = res;
622 }
623
624 measureAcc += res;
625 if (res > maxWidth) {
626 // we should not return this char index, but since it's 0-based
627 // and we need to return a count, we simply return measureIndex;
628 return measureIndex;
629 }
630
631 }
632
633 return measureIndex;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700634 }
635
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800636 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700637 /*package*/ static int native_breakText(Paint thisPaint, String text, boolean measureForwards,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700638 float maxWidth, int bidiFlags, float[] measuredWidth) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800639 return native_breakText(thisPaint, text.toCharArray(), 0, text.length(), maxWidth,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700640 bidiFlags, measuredWidth);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700641 }
642
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800643 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700644 /*package*/ static int native_init() {
645 Paint_Delegate newDelegate = new Paint_Delegate();
Xavier Ducrohet91672792011-02-22 11:54:37 -0800646 return sManager.addNewDelegate(newDelegate);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700647 }
648
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800649 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700650 /*package*/ static int native_initWithPaint(int paint) {
651 // get the delegate from the native int.
652 Paint_Delegate delegate = sManager.getDelegate(paint);
653 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700654 return 0;
655 }
656
657 Paint_Delegate newDelegate = new Paint_Delegate(delegate);
Xavier Ducrohet91672792011-02-22 11:54:37 -0800658 return sManager.addNewDelegate(newDelegate);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700659 }
660
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800661 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700662 /*package*/ static void native_reset(int native_object) {
663 // get the delegate from the native int.
664 Paint_Delegate delegate = sManager.getDelegate(native_object);
665 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700666 return;
667 }
668
669 delegate.reset();
670 }
671
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800672 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700673 /*package*/ static void native_set(int native_dst, int native_src) {
674 // get the delegate from the native int.
675 Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
676 if (delegate_dst == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700677 return;
678 }
679
680 // get the delegate from the native int.
681 Paint_Delegate delegate_src = sManager.getDelegate(native_src);
682 if (delegate_src == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700683 return;
684 }
685
686 delegate_dst.set(delegate_src);
687 }
688
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800689 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700690 /*package*/ static int native_getStyle(int native_object) {
691 // get the delegate from the native int.
692 Paint_Delegate delegate = sManager.getDelegate(native_object);
693 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700694 return 0;
695 }
696
697 return delegate.mStyle;
698 }
699
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800700 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700701 /*package*/ static void native_setStyle(int native_object, int style) {
702 // get the delegate from the native int.
703 Paint_Delegate delegate = sManager.getDelegate(native_object);
704 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700705 return;
706 }
707
708 delegate.mStyle = style;
709 }
710
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800711 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700712 /*package*/ static int native_getStrokeCap(int native_object) {
713 // get the delegate from the native int.
714 Paint_Delegate delegate = sManager.getDelegate(native_object);
715 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700716 return 0;
717 }
718
719 return delegate.mCap;
720 }
721
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800722 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700723 /*package*/ static void native_setStrokeCap(int native_object, int cap) {
724 // get the delegate from the native int.
725 Paint_Delegate delegate = sManager.getDelegate(native_object);
726 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700727 return;
728 }
729
730 delegate.mCap = cap;
731 }
732
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800733 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700734 /*package*/ static int native_getStrokeJoin(int native_object) {
735 // get the delegate from the native int.
736 Paint_Delegate delegate = sManager.getDelegate(native_object);
737 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700738 return 0;
739 }
740
741 return delegate.mJoin;
742 }
743
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800744 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700745 /*package*/ static void native_setStrokeJoin(int native_object, int join) {
746 // get the delegate from the native int.
747 Paint_Delegate delegate = sManager.getDelegate(native_object);
748 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700749 return;
750 }
751
752 delegate.mJoin = join;
753 }
754
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800755 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700756 /*package*/ static boolean native_getFillPath(int native_object, int src, int dst) {
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800757 Paint_Delegate paint = sManager.getDelegate(native_object);
758 if (paint == null) {
759 return false;
760 }
761
762 Path_Delegate srcPath = Path_Delegate.getDelegate(src);
763 if (srcPath == null) {
764 return true;
765 }
766
767 Path_Delegate dstPath = Path_Delegate.getDelegate(dst);
768 if (dstPath == null) {
769 return true;
770 }
771
772 Stroke stroke = paint.getJavaStroke();
773 Shape strokeShape = stroke.createStrokedShape(srcPath.getJavaShape());
774
775 dstPath.setJavaShape(strokeShape);
776
777 // FIXME figure out the return value?
778 return true;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700779 }
780
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800781 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700782 /*package*/ static int native_setShader(int native_object, int shader) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700783 // get the delegate from the native int.
784 Paint_Delegate delegate = sManager.getDelegate(native_object);
785 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700786 return shader;
787 }
788
Xavier Ducrohet91672792011-02-22 11:54:37 -0800789 delegate.mShader = Shader_Delegate.getDelegate(shader);
790
791 return shader;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700792 }
793
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800794 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700795 /*package*/ static int native_setColorFilter(int native_object, int filter) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700796 // get the delegate from the native int.
797 Paint_Delegate delegate = sManager.getDelegate(native_object);
798 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700799 return filter;
800 }
801
Xavier Ducrohet91672792011-02-22 11:54:37 -0800802 delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800803
804 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800805 if (delegate.mColorFilter != null && delegate.mColorFilter.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800806 Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800807 delegate.mColorFilter.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800808 }
809
810 return filter;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700811 }
812
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800813 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700814 /*package*/ static int native_setXfermode(int native_object, int xfermode) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700815 // get the delegate from the native int.
816 Paint_Delegate delegate = sManager.getDelegate(native_object);
817 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700818 return xfermode;
819 }
820
Xavier Ducrohet91672792011-02-22 11:54:37 -0800821 delegate.mXfermode = Xfermode_Delegate.getDelegate(xfermode);
822
823 return xfermode;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700824 }
825
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800826 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700827 /*package*/ static int native_setPathEffect(int native_object, int effect) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700828 // get the delegate from the native int.
829 Paint_Delegate delegate = sManager.getDelegate(native_object);
830 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700831 return effect;
832 }
833
Xavier Ducrohet91672792011-02-22 11:54:37 -0800834 delegate.mPathEffect = PathEffect_Delegate.getDelegate(effect);
835
836 return effect;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700837 }
838
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800839 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700840 /*package*/ static int native_setMaskFilter(int native_object, int maskfilter) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700841 // get the delegate from the native int.
842 Paint_Delegate delegate = sManager.getDelegate(native_object);
843 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700844 return maskfilter;
845 }
846
Xavier Ducrohet91672792011-02-22 11:54:37 -0800847 delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800848
849 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800850 if (delegate.mMaskFilter != null && delegate.mMaskFilter.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800851 Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800852 delegate.mMaskFilter.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800853 }
854
855 return maskfilter;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700856 }
857
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800858 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700859 /*package*/ static int native_setTypeface(int native_object, int typeface) {
860 // get the delegate from the native int.
861 Paint_Delegate delegate = sManager.getDelegate(native_object);
862 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700863 return 0;
864 }
865
Xavier Ducrohet91672792011-02-22 11:54:37 -0800866 delegate.mTypeface = Typeface_Delegate.getDelegate(typeface);
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800867 delegate.updateFontObject();
Xavier Ducrohet91672792011-02-22 11:54:37 -0800868 return typeface;
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_setRasterizer(int native_object, int rasterizer) {
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800873 // get the delegate from the native int.
874 Paint_Delegate delegate = sManager.getDelegate(native_object);
875 if (delegate == null) {
876 return rasterizer;
877 }
878
Xavier Ducrohet91672792011-02-22 11:54:37 -0800879 delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800880
881 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800882 if (delegate.mRasterizer != null && delegate.mRasterizer.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800883 Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800884 delegate.mRasterizer.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800885 }
886
887 return rasterizer;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700888 }
889
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800890 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700891 /*package*/ static int native_getTextAlign(int native_object) {
892 // get the delegate from the native int.
893 Paint_Delegate delegate = sManager.getDelegate(native_object);
894 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700895 return 0;
896 }
897
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700898 return delegate.mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700899 }
900
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800901 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700902 /*package*/ static void native_setTextAlign(int native_object, int align) {
903 // get the delegate from the native int.
904 Paint_Delegate delegate = sManager.getDelegate(native_object);
905 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700906 return;
907 }
908
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700909 delegate.mTextAlign = align;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700910 }
911
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800912 @LayoutlibDelegate
Xavier Ducrohet43526ab2012-04-23 17:41:37 -0700913 /*package*/ static void native_setTextLocale(int native_object, String locale) {
914 // get the delegate from the native int.
915 Paint_Delegate delegate = sManager.getDelegate(native_object);
916 if (delegate == null) {
917 return;
918 }
919
920 delegate.setTextLocale(locale);
921 }
922
923 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700924 /*package*/ static int native_getTextWidths(int native_object, char[] text, int index,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700925 int count, int bidiFlags, float[] widths) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800926 // get the delegate from the native int.
927 Paint_Delegate delegate = sManager.getDelegate(native_object);
928 if (delegate == null) {
929 return 0;
930 }
931
932 if (delegate.mFonts.size() > 0) {
933 // FIXME: handle multi-char characters (see measureText)
934 float totalAdvance = 0;
935 for (int i = 0; i < count; i++) {
936 char c = text[i + index];
937 boolean found = false;
938 for (FontInfo info : delegate.mFonts) {
939 if (info.mFont.canDisplay(c)) {
940 float adv = info.mMetrics.charWidth(c);
941 totalAdvance += adv;
942 if (widths != null) {
943 widths[i] = adv;
944 }
945
946 found = true;
947 break;
948 }
949 }
950
951 if (found == false) {
952 // no advance for this char.
953 if (widths != null) {
954 widths[i] = 0.f;
955 }
956 }
957 }
958
959 return (int) totalAdvance;
960 }
961
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800962 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700963 }
964
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800965 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700966 /*package*/ static int native_getTextWidths(int native_object, String text, int start,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700967 int end, int bidiFlags, float[] widths) {
968 return native_getTextWidths(native_object, text.toCharArray(), start, end - start,
969 bidiFlags, widths);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700970 }
971
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800972 @LayoutlibDelegate
Xavier Ducrohet81efa7f2011-06-15 14:43:42 -0700973 /* package */static int native_getTextGlyphs(int native_object, String text, int start,
974 int end, int contextStart, int contextEnd, int flags, char[] glyphs) {
975 // FIXME
976 return 0;
977 }
978
979 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700980 /*package*/ static float native_getTextRunAdvances(int native_object,
981 char[] text, int index, int count, int contextIndex, int contextCount,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700982 int flags, float[] advances, int advancesIndex) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700983 // get the delegate from the native int.
984 Paint_Delegate delegate = sManager.getDelegate(native_object);
985 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700986 return 0.f;
987 }
988
989 if (delegate.mFonts.size() > 0) {
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700990 // FIXME: handle multi-char characters (see measureText)
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700991 float totalAdvance = 0;
992 for (int i = 0; i < count; i++) {
993 char c = text[i + index];
994 boolean found = false;
995 for (FontInfo info : delegate.mFonts) {
996 if (info.mFont.canDisplay(c)) {
997 float adv = info.mMetrics.charWidth(c);
998 totalAdvance += adv;
999 if (advances != null) {
1000 advances[i] = adv;
1001 }
1002
1003 found = true;
1004 break;
1005 }
1006 }
1007
1008 if (found == false) {
1009 // no advance for this char.
1010 if (advances != null) {
1011 advances[i] = 0.f;
1012 }
1013 }
1014 }
1015
1016 return totalAdvance;
1017 }
1018
1019 return 0;
1020
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001021 }
1022
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001023 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001024 /*package*/ static float native_getTextRunAdvances(int native_object,
1025 String text, int start, int end, int contextStart, int contextEnd,
Deepanshu Guptac398f182013-05-23 15:20:04 -07001026 int flags, float[] advances, int advancesIndex) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001027 // FIXME: support contextStart, contextEnd and direction flag
1028 int count = end - start;
1029 char[] buffer = TemporaryBuffer.obtain(count);
1030 TextUtils.getChars(text, start, end, buffer, 0);
1031
1032 return native_getTextRunAdvances(native_object, buffer, 0, count, contextStart,
Deepanshu Guptac398f182013-05-23 15:20:04 -07001033 contextEnd - contextStart, flags, advances, advancesIndex);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001034 }
1035
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001036 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001037 /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, char[] text,
1038 int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
1039 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001040 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1041 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
1042 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001043 }
1044
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001045 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001046 /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, String text,
1047 int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
1048 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001049 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1050 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
1051 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001052 }
1053
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001054 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001055 /*package*/ static void native_getTextPath(int native_object, int bidiFlags,
1056 char[] text, int index, int count, float x, float y, int path) {
1057 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001058 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1059 "Paint.getTextPath is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001060 }
1061
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001062 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001063 /*package*/ static void native_getTextPath(int native_object, int bidiFlags,
1064 String text, int start, int end, float x, float y, int path) {
1065 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001066 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1067 "Paint.getTextPath is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001068 }
1069
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001070 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001071 /*package*/ static void nativeGetStringBounds(int nativePaint, String text, int start,
Deepanshu Guptac398f182013-05-23 15:20:04 -07001072 int end, int bidiFlags, Rect bounds) {
1073 nativeGetCharArrayBounds(nativePaint, text.toCharArray(), start, end - start, bidiFlags,
1074 bounds);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001075 }
1076
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001077 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001078 /*package*/ static void nativeGetCharArrayBounds(int nativePaint, char[] text, int index,
Deepanshu Guptac398f182013-05-23 15:20:04 -07001079 int count, int bidiFlags, Rect bounds) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001080
1081 // get the delegate from the native int.
1082 Paint_Delegate delegate = sManager.getDelegate(nativePaint);
1083 if (delegate == null) {
1084 return;
1085 }
1086
1087 // FIXME should test if the main font can display all those characters.
1088 // See MeasureText
1089 if (delegate.mFonts.size() > 0) {
1090 FontInfo mainInfo = delegate.mFonts.get(0);
1091
1092 Rectangle2D rect = mainInfo.mFont.getStringBounds(text, index, index + count,
1093 delegate.mFontContext);
1094 bounds.set(0, 0, (int) rect.getWidth(), (int) rect.getHeight());
1095 }
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001096 }
1097
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001098 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001099 /*package*/ static void finalizer(int nativePaint) {
Xavier Ducrohet91672792011-02-22 11:54:37 -08001100 sManager.removeJavaReferenceFor(nativePaint);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001101 }
1102
1103 // ---- Private delegate/helper methods ----
1104
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001105 /*package*/ Paint_Delegate() {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001106 reset();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001107 }
1108
1109 private Paint_Delegate(Paint_Delegate paint) {
1110 set(paint);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001111 }
1112
1113 private void set(Paint_Delegate paint) {
1114 mFlags = paint.mFlags;
1115 mColor = paint.mColor;
1116 mStyle = paint.mStyle;
1117 mCap = paint.mCap;
1118 mJoin = paint.mJoin;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001119 mTextAlign = paint.mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001120 mTypeface = paint.mTypeface;
1121 mStrokeWidth = paint.mStrokeWidth;
1122 mStrokeMiter = paint.mStrokeMiter;
1123 mTextSize = paint.mTextSize;
1124 mTextScaleX = paint.mTextScaleX;
1125 mTextSkewX = paint.mTextSkewX;
Xavier Ducroheta313b652010-11-01 18:45:20 -07001126 mXfermode = paint.mXfermode;
1127 mColorFilter = paint.mColorFilter;
1128 mShader = paint.mShader;
1129 mPathEffect = paint.mPathEffect;
1130 mMaskFilter = paint.mMaskFilter;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001131 mRasterizer = paint.mRasterizer;
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -07001132 mHintingMode = paint.mHintingMode;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001133 updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001134 }
1135
1136 private void reset() {
1137 mFlags = Paint.DEFAULT_PAINT_FLAGS;
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001138 mColor = 0xFF000000;
Xavier Ducrohet66225222010-12-21 01:33:04 -08001139 mStyle = Paint.Style.FILL.nativeInt;
1140 mCap = Paint.Cap.BUTT.nativeInt;
1141 mJoin = Paint.Join.MITER.nativeInt;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001142 mTextAlign = 0;
Xavier Ducrohet91672792011-02-22 11:54:37 -08001143 mTypeface = Typeface_Delegate.getDelegate(Typeface.sDefaults[0].native_instance);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001144 mStrokeWidth = 1.f;
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001145 mStrokeMiter = 4.f;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001146 mTextSize = 20.f;
1147 mTextScaleX = 1.f;
1148 mTextSkewX = 0.f;
Xavier Ducrohet91672792011-02-22 11:54:37 -08001149 mXfermode = null;
1150 mColorFilter = null;
1151 mShader = null;
1152 mPathEffect = null;
1153 mMaskFilter = null;
1154 mRasterizer = null;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001155 updateFontObject();
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -07001156 mHintingMode = Paint.HINTING_ON;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001157 }
1158
1159 /**
1160 * Update the {@link Font} object from the typeface, text size and scaling
1161 */
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001162 @SuppressWarnings("deprecation")
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001163 private void updateFontObject() {
Xavier Ducrohet91672792011-02-22 11:54:37 -08001164 if (mTypeface != null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001165 // Get the fonts from the TypeFace object.
Xavier Ducrohet91672792011-02-22 11:54:37 -08001166 List<Font> fonts = mTypeface.getFonts();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001167
1168 // create new font objects as well as FontMetrics, based on the current text size
1169 // and skew info.
1170 ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(fonts.size());
1171 for (Font font : fonts) {
1172 FontInfo info = new FontInfo();
1173 info.mFont = font.deriveFont(mTextSize);
1174 if (mTextScaleX != 1.0 || mTextSkewX != 0) {
1175 // TODO: support skew
1176 info.mFont = info.mFont.deriveFont(new AffineTransform(
Xavier Ducrohet8f109102011-10-04 19:39:18 -07001177 mTextScaleX, mTextSkewX, 0, 1, 0, 0));
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001178 }
1179 info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont);
1180
1181 infoList.add(info);
1182 }
1183
1184 mFonts = Collections.unmodifiableList(infoList);
1185 }
1186 }
1187
Deepanshu Guptac398f182013-05-23 15:20:04 -07001188 /*package*/ float measureText(char[] text, int index, int count, int bidiFlags) {
1189 // TODO: find out what bidiFlags actually does.
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001190
1191 // WARNING: the logic in this method is similar to Canvas_Delegate.native_drawText
1192 // Any change to this method should be reflected there as well
1193
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001194 if (mFonts.size() > 0) {
1195 FontInfo mainFont = mFonts.get(0);
1196 int i = index;
1197 int lastIndex = index + count;
1198 float total = 0f;
1199 while (i < lastIndex) {
1200 // always start with the main font.
1201 int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
1202 if (upTo == -1) {
1203 // shortcut to exit
1204 return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i);
1205 } else if (upTo > 0) {
1206 total += mainFont.mMetrics.charsWidth(text, i, upTo - i);
1207 i = upTo;
1208 // don't call continue at this point. Since it is certain the main font
1209 // cannot display the font a index upTo (now ==i), we move on to the
1210 // fallback fonts directly.
1211 }
1212
1213 // no char supported, attempt to read the next char(s) with the
1214 // fallback font. In this case we only test the first character
1215 // and then go back to test with the main font.
1216 // Special test for 2-char characters.
1217 boolean foundFont = false;
1218 for (int f = 1 ; f < mFonts.size() ; f++) {
1219 FontInfo fontInfo = mFonts.get(f);
1220
1221 // need to check that the font can display the character. We test
1222 // differently if the char is a high surrogate.
1223 int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
1224 upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
1225 if (upTo == -1) {
1226 total += fontInfo.mMetrics.charsWidth(text, i, charCount);
1227 i += charCount;
1228 foundFont = true;
1229 break;
1230
1231 }
1232 }
1233
1234 // in case no font can display the char, measure it with the main font.
1235 if (foundFont == false) {
1236 int size = Character.isHighSurrogate(text[i]) ? 2 : 1;
1237 total += mainFont.mMetrics.charsWidth(text, i, size);
1238 i += size;
1239 }
1240 }
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001241
1242 return total;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001243 }
1244
1245 return 0;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001246 }
1247
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -08001248 private float getFontMetrics(FontMetrics metrics) {
1249 if (mFonts.size() > 0) {
1250 java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics;
1251 if (metrics != null) {
1252 // Android expects negative ascent so we invert the value from Java.
1253 metrics.top = - javaMetrics.getMaxAscent();
1254 metrics.ascent = - javaMetrics.getAscent();
1255 metrics.descent = javaMetrics.getDescent();
1256 metrics.bottom = javaMetrics.getMaxDescent();
1257 metrics.leading = javaMetrics.getLeading();
1258 }
1259
1260 return javaMetrics.getHeight();
1261 }
1262
1263 return 0;
1264 }
1265
Xavier Ducrohet43526ab2012-04-23 17:41:37 -07001266 private void setTextLocale(String locale) {
1267 mLocale = new Locale(locale);
1268 }
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -08001269
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001270 private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) {
1271 // get the delegate from the native int.
1272 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
1273 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001274 return;
1275 }
1276
1277 if (flagValue) {
1278 delegate.mFlags |= flagMask;
1279 } else {
1280 delegate.mFlags &= ~flagMask;
1281 }
1282 }
Xavier Ducrohet43526ab2012-04-23 17:41:37 -07001283
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001284}