blob: 83df745a561dadb3be4f7ad427984e1e896416db [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;
Xavier Ducrohet43526ab2012-04-23 17:41:37 -070038import java.util.Locale;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070039
40/**
41 * Delegate implementing the native methods of android.graphics.Paint
42 *
43 * Through the layoutlib_create tool, the original native methods of Paint have been replaced
44 * by calls to methods of the same name in this delegate class.
45 *
46 * This class behaves like the original native implementation, but in Java, keeping previously
47 * native data into its own objects and mapping them to int that are sent back and forth between
48 * it and the original Paint class.
49 *
50 * @see DelegateManager
51 *
52 */
53public class Paint_Delegate {
54
55 /**
56 * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}.
57 */
Xavier Ducrohet37f21802010-11-01 16:17:18 -070058 /*package*/ static final class FontInfo {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070059 Font mFont;
60 java.awt.FontMetrics mMetrics;
61 }
62
63 // ---- delegate manager ----
64 private static final DelegateManager<Paint_Delegate> sManager =
Xavier Ducrohetb2de8392011-02-23 16:51:08 -080065 new DelegateManager<Paint_Delegate>(Paint_Delegate.class);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070066
67 // ---- delegate helper data ----
68 private List<FontInfo> mFonts;
69 private final FontRenderContext mFontContext = new FontRenderContext(
70 new AffineTransform(), true, true);
71
72 // ---- delegate data ----
73 private int mFlags;
74 private int mColor;
75 private int mStyle;
76 private int mCap;
77 private int mJoin;
Xavier Ducrohet37f21802010-11-01 16:17:18 -070078 private int mTextAlign;
Xavier Ducrohet91672792011-02-22 11:54:37 -080079 private Typeface_Delegate mTypeface;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070080 private float mStrokeWidth;
81 private float mStrokeMiter;
82 private float mTextSize;
83 private float mTextScaleX;
84 private float mTextSkewX;
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -070085 private int mHintingMode = Paint.HINTING_ON;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070086
Xavier Ducrohet91672792011-02-22 11:54:37 -080087 private Xfermode_Delegate mXfermode;
88 private ColorFilter_Delegate mColorFilter;
89 private Shader_Delegate mShader;
90 private PathEffect_Delegate mPathEffect;
91 private MaskFilter_Delegate mMaskFilter;
92 private Rasterizer_Delegate mRasterizer;
Xavier Ducroheta313b652010-11-01 18:45:20 -070093
Xavier Ducrohet43526ab2012-04-23 17:41:37 -070094 private Locale mLocale = Locale.getDefault();
95
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070096
97 // ---- Public Helper methods ----
98
Narayan Kamath633d6882014-01-27 14:24:16 +000099 public static Paint_Delegate getDelegate(long native_paint) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700100 return sManager.getDelegate(native_paint);
101 }
102
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700103 /**
104 * Returns the list of {@link Font} objects. The first item is the main font, the rest
105 * are fall backs for characters not present in the main font.
106 */
107 public List<FontInfo> getFonts() {
108 return mFonts;
109 }
110
Xavier Ducroheta313b652010-11-01 18:45:20 -0700111 public boolean isAntiAliased() {
112 return (mFlags & Paint.ANTI_ALIAS_FLAG) != 0;
113 }
114
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700115 public boolean isFilterBitmap() {
116 return (mFlags & Paint.FILTER_BITMAP_FLAG) != 0;
117 }
118
119 public int getStyle() {
120 return mStyle;
121 }
122
123 public int getColor() {
124 return mColor;
125 }
126
Xavier Ducrohet66225222010-12-21 01:33:04 -0800127 public int getAlpha() {
128 return mColor >>> 24;
129 }
130
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800131 public void setAlpha(int alpha) {
132 mColor = (alpha << 24) | (mColor & 0x00FFFFFF);
133 }
134
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700135 public int getTextAlign() {
136 return mTextAlign;
137 }
138
139 public float getStrokeWidth() {
140 return mStrokeWidth;
141 }
142
Xavier Ducrohet66225222010-12-21 01:33:04 -0800143 /**
144 * returns the value of stroke miter needed by the java api.
145 */
146 public float getJavaStrokeMiter() {
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800147 float miter = mStrokeMiter * mStrokeWidth;
148 if (miter < 1.f) {
149 miter = 1.f;
150 }
151 return miter;
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700152 }
153
154 public int getJavaCap() {
155 switch (Paint.sCapArray[mCap]) {
156 case BUTT:
157 return BasicStroke.CAP_BUTT;
158 case ROUND:
159 return BasicStroke.CAP_ROUND;
160 default:
161 case SQUARE:
162 return BasicStroke.CAP_SQUARE;
163 }
164 }
165
166 public int getJavaJoin() {
167 switch (Paint.sJoinArray[mJoin]) {
168 default:
169 case MITER:
170 return BasicStroke.JOIN_MITER;
171 case ROUND:
172 return BasicStroke.JOIN_ROUND;
173 case BEVEL:
174 return BasicStroke.JOIN_BEVEL;
175 }
176 }
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700177
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800178 public Stroke getJavaStroke() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800179 if (mPathEffect != null) {
180 if (mPathEffect.isSupported()) {
181 Stroke stroke = mPathEffect.getStroke(this);
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800182 assert stroke != null;
183 if (stroke != null) {
184 return stroke;
185 }
186 } else {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800187 Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800188 mPathEffect.getSupportMessage(),
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800189 null, null /*data*/);
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800190 }
191 }
192
193 // if no custom stroke as been set, set the default one.
194 return new BasicStroke(
195 getStrokeWidth(),
196 getJavaCap(),
197 getJavaJoin(),
198 getJavaStrokeMiter());
199 }
200
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800201 /**
202 * Returns the {@link Xfermode} delegate or null if none have been set
203 *
204 * @return the delegate or null.
205 */
206 public Xfermode_Delegate getXfermode() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800207 return mXfermode;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700208 }
209
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800210 /**
211 * Returns the {@link ColorFilter} delegate or null if none have been set
212 *
213 * @return the delegate or null.
214 */
215 public ColorFilter_Delegate getColorFilter() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800216 return mColorFilter;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700217 }
218
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800219 /**
220 * Returns the {@link Shader} delegate or null if none have been set
221 *
222 * @return the delegate or null.
223 */
224 public Shader_Delegate getShader() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800225 return mShader;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700226 }
227
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800228 /**
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800229 * Returns the {@link MaskFilter} delegate or null if none have been set
230 *
231 * @return the delegate or null.
232 */
233 public MaskFilter_Delegate getMaskFilter() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800234 return mMaskFilter;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800235 }
236
237 /**
238 * Returns the {@link Rasterizer} delegate or null if none have been set
239 *
240 * @return the delegate or null.
241 */
242 public Rasterizer_Delegate getRasterizer() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800243 return mRasterizer;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700244 }
245
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700246 // ---- native methods ----
247
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800248 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700249 /*package*/ static int getFlags(Paint thisPaint) {
250 // get the delegate from the native int.
251 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
252 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700253 return 0;
254 }
255
256 return delegate.mFlags;
257 }
258
Xavier Ducrohet43526ab2012-04-23 17:41:37 -0700259
260
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800261 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700262 /*package*/ static void setFlags(Paint thisPaint, int flags) {
263 // get the delegate from the native int.
264 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
265 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700266 return;
267 }
268
269 delegate.mFlags = flags;
270 }
271
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800272 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700273 /*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700274 setFlag(thisPaint, Paint.FILTER_BITMAP_FLAG, filter);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700275 }
276
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800277 @LayoutlibDelegate
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -0700278 /*package*/ static int getHinting(Paint thisPaint) {
279 // get the delegate from the native int.
280 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
281 if (delegate == null) {
282 return Paint.HINTING_ON;
283 }
284
285 return delegate.mHintingMode;
286 }
287
288 @LayoutlibDelegate
289 /*package*/ static void setHinting(Paint thisPaint, int mode) {
290 // get the delegate from the native int.
291 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
292 if (delegate == null) {
293 return;
294 }
295
296 delegate.mHintingMode = mode;
297 }
298
299 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700300 /*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) {
301 setFlag(thisPaint, Paint.ANTI_ALIAS_FLAG, aa);
302 }
303
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800304 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700305 /*package*/ static void setSubpixelText(Paint thisPaint, boolean subpixelText) {
306 setFlag(thisPaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
307 }
308
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800309 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700310 /*package*/ static void setUnderlineText(Paint thisPaint, boolean underlineText) {
311 setFlag(thisPaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
312 }
313
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800314 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700315 /*package*/ static void setStrikeThruText(Paint thisPaint, boolean strikeThruText) {
316 setFlag(thisPaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
317 }
318
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800319 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700320 /*package*/ static void setFakeBoldText(Paint thisPaint, boolean fakeBoldText) {
321 setFlag(thisPaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
322 }
323
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800324 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700325 /*package*/ static void setDither(Paint thisPaint, boolean dither) {
326 setFlag(thisPaint, Paint.DITHER_FLAG, dither);
327 }
328
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800329 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700330 /*package*/ static void setLinearText(Paint thisPaint, boolean linearText) {
331 setFlag(thisPaint, Paint.LINEAR_TEXT_FLAG, linearText);
332 }
333
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800334 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700335 /*package*/ static int getColor(Paint thisPaint) {
336 // get the delegate from the native int.
337 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
338 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700339 return 0;
340 }
341
342 return delegate.mColor;
343 }
344
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800345 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700346 /*package*/ static void setColor(Paint thisPaint, int color) {
347 // get the delegate from the native int.
348 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
349 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700350 return;
351 }
352
353 delegate.mColor = color;
354 }
355
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800356 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700357 /*package*/ static int getAlpha(Paint thisPaint) {
358 // get the delegate from the native int.
359 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
360 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700361 return 0;
362 }
363
Xavier Ducrohet66225222010-12-21 01:33:04 -0800364 return delegate.getAlpha();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700365 }
366
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800367 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700368 /*package*/ static void setAlpha(Paint thisPaint, int a) {
369 // get the delegate from the native int.
370 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
371 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700372 return;
373 }
374
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800375 delegate.setAlpha(a);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700376 }
377
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800378 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700379 /*package*/ static float getStrokeWidth(Paint thisPaint) {
380 // get the delegate from the native int.
381 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
382 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700383 return 1.f;
384 }
385
386 return delegate.mStrokeWidth;
387 }
388
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800389 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700390 /*package*/ static void setStrokeWidth(Paint thisPaint, float width) {
391 // get the delegate from the native int.
392 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
393 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700394 return;
395 }
396
397 delegate.mStrokeWidth = width;
398 }
399
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800400 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700401 /*package*/ static float getStrokeMiter(Paint thisPaint) {
402 // get the delegate from the native int.
403 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
404 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700405 return 1.f;
406 }
407
408 return delegate.mStrokeMiter;
409 }
410
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800411 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700412 /*package*/ static void setStrokeMiter(Paint thisPaint, float miter) {
413 // get the delegate from the native int.
414 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
415 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700416 return;
417 }
418
419 delegate.mStrokeMiter = miter;
420 }
421
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800422 @LayoutlibDelegate
Deepanshu Gupta0bec6852014-05-15 09:30:11 -0700423 /*package*/ static void native_setShadowLayer(long paint, float radius, float dx, float dy,
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700424 int color) {
425 // FIXME
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800426 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800427 "Paint.setShadowLayer is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700428 }
429
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800430 @LayoutlibDelegate
Deepanshu Gupta0bec6852014-05-15 09:30:11 -0700431 /*package*/ static boolean native_hasShadowLayer(long paint) {
432 // FIXME
433 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
434 "Paint.hasShadowLayer is not supported.", null, null /*data*/);
435 return false;
436 }
437
438 @LayoutlibDelegate
Deepanshu Guptabd49b122014-04-18 15:43:06 -0700439 /*package*/ static boolean isElegantTextHeight(Paint thisPaint) {
440 return false;
441 }
442
443 @LayoutlibDelegate
444 /*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) {
445 // TODO
446 }
447
448 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700449 /*package*/ static float getTextSize(Paint thisPaint) {
450 // get the delegate from the native int.
451 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
452 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700453 return 1.f;
454 }
455
456 return delegate.mTextSize;
457 }
458
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800459 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700460 /*package*/ static void setTextSize(Paint thisPaint, float textSize) {
461 // get the delegate from the native int.
462 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
463 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700464 return;
465 }
466
467 delegate.mTextSize = textSize;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800468 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700469 }
470
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800471 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700472 /*package*/ static float getTextScaleX(Paint thisPaint) {
473 // get the delegate from the native int.
474 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
475 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700476 return 1.f;
477 }
478
479 return delegate.mTextScaleX;
480 }
481
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800482 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700483 /*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) {
484 // get the delegate from the native int.
485 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
486 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700487 return;
488 }
489
490 delegate.mTextScaleX = scaleX;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800491 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700492 }
493
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800494 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700495 /*package*/ static float getTextSkewX(Paint thisPaint) {
496 // get the delegate from the native int.
497 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
498 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700499 return 1.f;
500 }
501
502 return delegate.mTextSkewX;
503 }
504
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800505 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700506 /*package*/ static void setTextSkewX(Paint thisPaint, float skewX) {
507 // get the delegate from the native int.
508 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
509 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700510 return;
511 }
512
513 delegate.mTextSkewX = skewX;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800514 delegate.updateFontObject();
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 ascent(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 // Android expects negative ascent so we invert the value from Java.
528 return - javaMetrics.getAscent();
529 }
530
531 return 0;
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 descent(Paint thisPaint) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800536 // get the delegate
537 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
538 if (delegate == null) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800539 return 0;
540 }
541
542 if (delegate.mFonts.size() > 0) {
543 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
544 return javaMetrics.getDescent();
545 }
546
547 return 0;
548
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700549 }
550
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800551 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700552 /*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700553 // get the delegate
554 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
555 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700556 return 0;
557 }
558
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800559 return delegate.getFontMetrics(metrics);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700560 }
561
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800562 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700563 /*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700564 // get the delegate
565 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
566 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700567 return 0;
568 }
569
570 if (delegate.mFonts.size() > 0) {
571 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
572 if (fmi != null) {
573 // Android expects negative ascent so we invert the value from Java.
574 fmi.top = - javaMetrics.getMaxAscent();
575 fmi.ascent = - javaMetrics.getAscent();
576 fmi.descent = javaMetrics.getDescent();
577 fmi.bottom = javaMetrics.getMaxDescent();
578 fmi.leading = javaMetrics.getLeading();
579 }
580
581 return javaMetrics.getHeight();
582 }
583
584 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700585 }
586
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800587 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700588 /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700589 int count, int bidiFlags) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700590 // get the delegate
591 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
592 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700593 return 0;
594 }
595
Deepanshu Guptaeb998d32014-01-07 11:58:44 -0800596 RectF bounds = delegate.measureText(text, index, count, isRtl(bidiFlags));
597 return bounds.right - bounds.left;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700598 }
599
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800600 @LayoutlibDelegate
Deepanshu Guptac398f182013-05-23 15:20:04 -0700601 /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end,
602 int bidiFlags) {
603 return native_measureText(thisPaint, text.toCharArray(), start, end - start, bidiFlags);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700604 }
605
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800606 @LayoutlibDelegate
Deepanshu Guptac398f182013-05-23 15:20:04 -0700607 /*package*/ static float native_measureText(Paint thisPaint, String text, int bidiFlags) {
608 return native_measureText(thisPaint, text.toCharArray(), 0, text.length(), bidiFlags);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700609 }
610
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800611 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700612 /*package*/ static int native_breakText(Paint thisPaint, char[] text, int index, int count,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700613 float maxWidth, int bidiFlags, float[] measuredWidth) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800614
615 // get the delegate
616 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
617 if (delegate == null) {
618 return 0;
619 }
620
621 int inc = count > 0 ? 1 : -1;
622
623 int measureIndex = 0;
624 float measureAcc = 0;
625 for (int i = index; i != index + count; i += inc, measureIndex++) {
626 int start, end;
627 if (i < index) {
628 start = i;
629 end = index;
630 } else {
631 start = index;
632 end = i;
633 }
634
635 // measure from start to end
Deepanshu Guptaeb998d32014-01-07 11:58:44 -0800636 RectF bounds = delegate.measureText(text, start, end - start + 1, isRtl(bidiFlags));
637 float res = bounds.right - bounds.left;
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800638
639 if (measuredWidth != null) {
640 measuredWidth[measureIndex] = res;
641 }
642
643 measureAcc += res;
644 if (res > maxWidth) {
645 // we should not return this char index, but since it's 0-based
646 // and we need to return a count, we simply return measureIndex;
647 return measureIndex;
648 }
649
650 }
651
652 return measureIndex;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700653 }
654
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800655 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700656 /*package*/ static int native_breakText(Paint thisPaint, String text, boolean measureForwards,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700657 float maxWidth, int bidiFlags, float[] measuredWidth) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800658 return native_breakText(thisPaint, text.toCharArray(), 0, text.length(), maxWidth,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700659 bidiFlags, measuredWidth);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700660 }
661
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800662 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000663 /*package*/ static long native_init() {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700664 Paint_Delegate newDelegate = new Paint_Delegate();
Xavier Ducrohet91672792011-02-22 11:54:37 -0800665 return sManager.addNewDelegate(newDelegate);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700666 }
667
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800668 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000669 /*package*/ static long native_initWithPaint(long paint) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700670 // get the delegate from the native int.
671 Paint_Delegate delegate = sManager.getDelegate(paint);
672 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700673 return 0;
674 }
675
676 Paint_Delegate newDelegate = new Paint_Delegate(delegate);
Xavier Ducrohet91672792011-02-22 11:54:37 -0800677 return sManager.addNewDelegate(newDelegate);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700678 }
679
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800680 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000681 /*package*/ static void native_reset(long native_object) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700682 // get the delegate from the native int.
683 Paint_Delegate delegate = sManager.getDelegate(native_object);
684 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700685 return;
686 }
687
688 delegate.reset();
689 }
690
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800691 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000692 /*package*/ static void native_set(long native_dst, long native_src) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700693 // get the delegate from the native int.
694 Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
695 if (delegate_dst == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700696 return;
697 }
698
699 // get the delegate from the native int.
700 Paint_Delegate delegate_src = sManager.getDelegate(native_src);
701 if (delegate_src == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700702 return;
703 }
704
705 delegate_dst.set(delegate_src);
706 }
707
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800708 @LayoutlibDelegate
Deepanshu Guptaf9a82352014-02-21 16:22:10 -0800709 /*package*/ static int native_getStyle(long native_object) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700710 // get the delegate from the native int.
711 Paint_Delegate delegate = sManager.getDelegate(native_object);
712 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700713 return 0;
714 }
715
716 return delegate.mStyle;
717 }
718
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800719 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000720 /*package*/ static void native_setStyle(long native_object, int style) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700721 // get the delegate from the native int.
722 Paint_Delegate delegate = sManager.getDelegate(native_object);
723 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700724 return;
725 }
726
727 delegate.mStyle = style;
728 }
729
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800730 @LayoutlibDelegate
Deepanshu Guptaf9a82352014-02-21 16:22:10 -0800731 /*package*/ static int native_getStrokeCap(long native_object) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700732 // get the delegate from the native int.
733 Paint_Delegate delegate = sManager.getDelegate(native_object);
734 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700735 return 0;
736 }
737
738 return delegate.mCap;
739 }
740
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800741 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000742 /*package*/ static void native_setStrokeCap(long native_object, int cap) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700743 // get the delegate from the native int.
744 Paint_Delegate delegate = sManager.getDelegate(native_object);
745 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700746 return;
747 }
748
749 delegate.mCap = cap;
750 }
751
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800752 @LayoutlibDelegate
Deepanshu Guptaf9a82352014-02-21 16:22:10 -0800753 /*package*/ static int native_getStrokeJoin(long native_object) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700754 // get the delegate from the native int.
755 Paint_Delegate delegate = sManager.getDelegate(native_object);
756 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700757 return 0;
758 }
759
760 return delegate.mJoin;
761 }
762
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800763 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000764 /*package*/ static void native_setStrokeJoin(long native_object, int join) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700765 // get the delegate from the native int.
766 Paint_Delegate delegate = sManager.getDelegate(native_object);
767 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700768 return;
769 }
770
771 delegate.mJoin = join;
772 }
773
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800774 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000775 /*package*/ static boolean native_getFillPath(long native_object, long src, long dst) {
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800776 Paint_Delegate paint = sManager.getDelegate(native_object);
777 if (paint == null) {
778 return false;
779 }
780
781 Path_Delegate srcPath = Path_Delegate.getDelegate(src);
782 if (srcPath == null) {
783 return true;
784 }
785
786 Path_Delegate dstPath = Path_Delegate.getDelegate(dst);
787 if (dstPath == null) {
788 return true;
789 }
790
791 Stroke stroke = paint.getJavaStroke();
792 Shape strokeShape = stroke.createStrokedShape(srcPath.getJavaShape());
793
794 dstPath.setJavaShape(strokeShape);
795
796 // FIXME figure out the return value?
797 return true;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700798 }
799
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800800 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000801 /*package*/ static long native_setShader(long native_object, long shader) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700802 // get the delegate from the native int.
803 Paint_Delegate delegate = sManager.getDelegate(native_object);
804 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700805 return shader;
806 }
807
Xavier Ducrohet91672792011-02-22 11:54:37 -0800808 delegate.mShader = Shader_Delegate.getDelegate(shader);
809
810 return shader;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700811 }
812
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800813 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000814 /*package*/ static long native_setColorFilter(long native_object, long filter) {
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 filter;
819 }
820
Xavier Ducrohet91672792011-02-22 11:54:37 -0800821 delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800822
823 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800824 if (delegate.mColorFilter != null && delegate.mColorFilter.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800825 Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800826 delegate.mColorFilter.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800827 }
828
829 return filter;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700830 }
831
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800832 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000833 /*package*/ static long native_setXfermode(long native_object, long xfermode) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700834 // get the delegate from the native int.
835 Paint_Delegate delegate = sManager.getDelegate(native_object);
836 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700837 return xfermode;
838 }
839
Xavier Ducrohet91672792011-02-22 11:54:37 -0800840 delegate.mXfermode = Xfermode_Delegate.getDelegate(xfermode);
841
842 return xfermode;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700843 }
844
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800845 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000846 /*package*/ static long native_setPathEffect(long native_object, long effect) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700847 // get the delegate from the native int.
848 Paint_Delegate delegate = sManager.getDelegate(native_object);
849 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700850 return effect;
851 }
852
Xavier Ducrohet91672792011-02-22 11:54:37 -0800853 delegate.mPathEffect = PathEffect_Delegate.getDelegate(effect);
854
855 return effect;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700856 }
857
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800858 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000859 /*package*/ static long native_setMaskFilter(long native_object, long maskfilter) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700860 // get the delegate from the native int.
861 Paint_Delegate delegate = sManager.getDelegate(native_object);
862 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700863 return maskfilter;
864 }
865
Xavier Ducrohet91672792011-02-22 11:54:37 -0800866 delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800867
868 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800869 if (delegate.mMaskFilter != null && delegate.mMaskFilter.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800870 Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800871 delegate.mMaskFilter.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800872 }
873
874 return maskfilter;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700875 }
876
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800877 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000878 /*package*/ static long native_setTypeface(long native_object, long typeface) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700879 // get the delegate from the native int.
880 Paint_Delegate delegate = sManager.getDelegate(native_object);
881 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700882 return 0;
883 }
884
Xavier Ducrohet91672792011-02-22 11:54:37 -0800885 delegate.mTypeface = Typeface_Delegate.getDelegate(typeface);
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800886 delegate.updateFontObject();
Xavier Ducrohet91672792011-02-22 11:54:37 -0800887 return typeface;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700888 }
889
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800890 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000891 /*package*/ static long native_setRasterizer(long native_object, long rasterizer) {
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800892 // get the delegate from the native int.
893 Paint_Delegate delegate = sManager.getDelegate(native_object);
894 if (delegate == null) {
895 return rasterizer;
896 }
897
Xavier Ducrohet91672792011-02-22 11:54:37 -0800898 delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800899
900 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800901 if (delegate.mRasterizer != null && delegate.mRasterizer.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800902 Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800903 delegate.mRasterizer.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800904 }
905
906 return rasterizer;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700907 }
908
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800909 @LayoutlibDelegate
Deepanshu Guptaf9a82352014-02-21 16:22:10 -0800910 /*package*/ static int native_getTextAlign(long native_object) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700911 // get the delegate from the native int.
912 Paint_Delegate delegate = sManager.getDelegate(native_object);
913 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700914 return 0;
915 }
916
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700917 return delegate.mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700918 }
919
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800920 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000921 /*package*/ static void native_setTextAlign(long native_object, int align) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700922 // get the delegate from the native int.
923 Paint_Delegate delegate = sManager.getDelegate(native_object);
924 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700925 return;
926 }
927
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700928 delegate.mTextAlign = align;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700929 }
930
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800931 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000932 /*package*/ static void native_setTextLocale(long native_object, String locale) {
Xavier Ducrohet43526ab2012-04-23 17:41:37 -0700933 // get the delegate from the native int.
934 Paint_Delegate delegate = sManager.getDelegate(native_object);
935 if (delegate == null) {
936 return;
937 }
938
939 delegate.setTextLocale(locale);
940 }
941
942 @LayoutlibDelegate
Deepanshu Guptaf9a82352014-02-21 16:22:10 -0800943 /*package*/ static int native_getTextWidths(long native_object, char[] text, int index,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700944 int count, int bidiFlags, float[] widths) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800945 // get the delegate from the native int.
946 Paint_Delegate delegate = sManager.getDelegate(native_object);
947 if (delegate == null) {
948 return 0;
949 }
950
951 if (delegate.mFonts.size() > 0) {
952 // FIXME: handle multi-char characters (see measureText)
953 float totalAdvance = 0;
954 for (int i = 0; i < count; i++) {
955 char c = text[i + index];
956 boolean found = false;
957 for (FontInfo info : delegate.mFonts) {
958 if (info.mFont.canDisplay(c)) {
959 float adv = info.mMetrics.charWidth(c);
960 totalAdvance += adv;
961 if (widths != null) {
962 widths[i] = adv;
963 }
964
965 found = true;
966 break;
967 }
968 }
969
970 if (found == false) {
971 // no advance for this char.
972 if (widths != null) {
973 widths[i] = 0.f;
974 }
975 }
976 }
977
978 return (int) totalAdvance;
979 }
980
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800981 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700982 }
983
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800984 @LayoutlibDelegate
Deepanshu Guptaf9a82352014-02-21 16:22:10 -0800985 /*package*/ static int native_getTextWidths(long native_object, String text, int start,
Deepanshu Guptac398f182013-05-23 15:20:04 -0700986 int end, int bidiFlags, float[] widths) {
987 return native_getTextWidths(native_object, text.toCharArray(), start, end - start,
988 bidiFlags, widths);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700989 }
990
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800991 @LayoutlibDelegate
Deepanshu Guptaf9a82352014-02-21 16:22:10 -0800992 /* package */static int native_getTextGlyphs(long native_object, String text, int start,
Xavier Ducrohet81efa7f2011-06-15 14:43:42 -0700993 int end, int contextStart, int contextEnd, int flags, char[] glyphs) {
994 // FIXME
995 return 0;
996 }
997
998 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +0000999 /*package*/ static float native_getTextRunAdvances(long native_object,
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001000 char[] text, int index, int count, int contextIndex, int contextCount,
Deepanshu Guptac398f182013-05-23 15:20:04 -07001001 int flags, float[] advances, int advancesIndex) {
Deepanshu Guptaa6b207a2013-07-12 11:38:05 -07001002
1003 if (advances != null)
1004 for (int i = advancesIndex; i< advancesIndex+count; i++)
1005 advances[i]=0;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001006 // get the delegate from the native int.
1007 Paint_Delegate delegate = sManager.getDelegate(native_object);
Deepanshu Guptaa6b207a2013-07-12 11:38:05 -07001008 if (delegate == null || delegate.mFonts == null || delegate.mFonts.size() == 0) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001009 return 0.f;
1010 }
Deepanshu Guptaa6b207a2013-07-12 11:38:05 -07001011 boolean isRtl = isRtl(flags);
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001012
Deepanshu Guptaa6b207a2013-07-12 11:38:05 -07001013 int limit = index + count;
Deepanshu Guptaeb998d32014-01-07 11:58:44 -08001014 RectF bounds = new BidiRenderer(null, delegate, text).renderText(
Deepanshu Guptaa6b207a2013-07-12 11:38:05 -07001015 index, limit, isRtl, advances, advancesIndex, false, 0, 0);
Deepanshu Guptaeb998d32014-01-07 11:58:44 -08001016 return bounds.right - bounds.left;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001017 }
1018
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001019 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +00001020 /*package*/ static float native_getTextRunAdvances(long native_object,
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001021 String text, int start, int end, int contextStart, int contextEnd,
Deepanshu Guptac398f182013-05-23 15:20:04 -07001022 int flags, float[] advances, int advancesIndex) {
Deepanshu Guptaa6b207a2013-07-12 11:38:05 -07001023 // FIXME: support contextStart and contextEnd
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001024 int count = end - start;
1025 char[] buffer = TemporaryBuffer.obtain(count);
1026 TextUtils.getChars(text, start, end, buffer, 0);
1027
1028 return native_getTextRunAdvances(native_object, buffer, 0, count, contextStart,
Deepanshu Guptac398f182013-05-23 15:20:04 -07001029 contextEnd - contextStart, flags, advances, advancesIndex);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001030 }
1031
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001032 @LayoutlibDelegate
Deepanshu Guptaf9a82352014-02-21 16:22:10 -08001033 /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, char[] text,
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001034 int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
1035 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001036 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1037 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
1038 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001039 }
1040
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001041 @LayoutlibDelegate
Deepanshu Guptaf9a82352014-02-21 16:22:10 -08001042 /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, String text,
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001043 int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
1044 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001045 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1046 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
1047 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001048 }
1049
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001050 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +00001051 /*package*/ static void native_getTextPath(long native_object, int bidiFlags,
1052 char[] text, int index, int count, float x, float y, long path) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001053 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001054 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1055 "Paint.getTextPath is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001056 }
1057
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001058 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +00001059 /*package*/ static void native_getTextPath(long native_object, int bidiFlags,
1060 String text, int start, int end, float x, float y, long path) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001061 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001062 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1063 "Paint.getTextPath is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001064 }
1065
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001066 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +00001067 /*package*/ static void nativeGetStringBounds(long nativePaint, String text, int start,
Deepanshu Guptac398f182013-05-23 15:20:04 -07001068 int end, int bidiFlags, Rect bounds) {
1069 nativeGetCharArrayBounds(nativePaint, text.toCharArray(), start, end - start, bidiFlags,
1070 bounds);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001071 }
1072
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001073 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +00001074 /*package*/ static void nativeGetCharArrayBounds(long nativePaint, char[] text, int index,
Deepanshu Guptac398f182013-05-23 15:20:04 -07001075 int count, int bidiFlags, Rect bounds) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001076
1077 // get the delegate from the native int.
1078 Paint_Delegate delegate = sManager.getDelegate(nativePaint);
Deepanshu Guptaa6b207a2013-07-12 11:38:05 -07001079 if (delegate == null || delegate.mFonts == null || delegate.mFonts.size() == 0) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001080 return;
1081 }
Deepanshu Guptaeb998d32014-01-07 11:58:44 -08001082 delegate.measureText(text, index, count, isRtl(bidiFlags)).roundOut(bounds);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001083 }
1084
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001085 @LayoutlibDelegate
Narayan Kamath633d6882014-01-27 14:24:16 +00001086 /*package*/ static void finalizer(long nativePaint) {
Xavier Ducrohet91672792011-02-22 11:54:37 -08001087 sManager.removeJavaReferenceFor(nativePaint);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001088 }
1089
1090 // ---- Private delegate/helper methods ----
1091
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001092 /*package*/ Paint_Delegate() {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001093 reset();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001094 }
1095
1096 private Paint_Delegate(Paint_Delegate paint) {
1097 set(paint);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001098 }
1099
1100 private void set(Paint_Delegate paint) {
1101 mFlags = paint.mFlags;
1102 mColor = paint.mColor;
1103 mStyle = paint.mStyle;
1104 mCap = paint.mCap;
1105 mJoin = paint.mJoin;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001106 mTextAlign = paint.mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001107 mTypeface = paint.mTypeface;
1108 mStrokeWidth = paint.mStrokeWidth;
1109 mStrokeMiter = paint.mStrokeMiter;
1110 mTextSize = paint.mTextSize;
1111 mTextScaleX = paint.mTextScaleX;
1112 mTextSkewX = paint.mTextSkewX;
Xavier Ducroheta313b652010-11-01 18:45:20 -07001113 mXfermode = paint.mXfermode;
1114 mColorFilter = paint.mColorFilter;
1115 mShader = paint.mShader;
1116 mPathEffect = paint.mPathEffect;
1117 mMaskFilter = paint.mMaskFilter;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001118 mRasterizer = paint.mRasterizer;
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -07001119 mHintingMode = paint.mHintingMode;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001120 updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001121 }
1122
1123 private void reset() {
1124 mFlags = Paint.DEFAULT_PAINT_FLAGS;
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001125 mColor = 0xFF000000;
Xavier Ducrohet66225222010-12-21 01:33:04 -08001126 mStyle = Paint.Style.FILL.nativeInt;
1127 mCap = Paint.Cap.BUTT.nativeInt;
1128 mJoin = Paint.Join.MITER.nativeInt;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001129 mTextAlign = 0;
Xavier Ducrohet91672792011-02-22 11:54:37 -08001130 mTypeface = Typeface_Delegate.getDelegate(Typeface.sDefaults[0].native_instance);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001131 mStrokeWidth = 1.f;
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001132 mStrokeMiter = 4.f;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001133 mTextSize = 20.f;
1134 mTextScaleX = 1.f;
1135 mTextSkewX = 0.f;
Xavier Ducrohet91672792011-02-22 11:54:37 -08001136 mXfermode = null;
1137 mColorFilter = null;
1138 mShader = null;
1139 mPathEffect = null;
1140 mMaskFilter = null;
1141 mRasterizer = null;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001142 updateFontObject();
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -07001143 mHintingMode = Paint.HINTING_ON;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001144 }
1145
1146 /**
1147 * Update the {@link Font} object from the typeface, text size and scaling
1148 */
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001149 @SuppressWarnings("deprecation")
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001150 private void updateFontObject() {
Xavier Ducrohet91672792011-02-22 11:54:37 -08001151 if (mTypeface != null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001152 // Get the fonts from the TypeFace object.
Xavier Ducrohet91672792011-02-22 11:54:37 -08001153 List<Font> fonts = mTypeface.getFonts();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001154
1155 // create new font objects as well as FontMetrics, based on the current text size
1156 // and skew info.
1157 ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(fonts.size());
1158 for (Font font : fonts) {
1159 FontInfo info = new FontInfo();
1160 info.mFont = font.deriveFont(mTextSize);
1161 if (mTextScaleX != 1.0 || mTextSkewX != 0) {
1162 // TODO: support skew
1163 info.mFont = info.mFont.deriveFont(new AffineTransform(
Xavier Ducrohet8f109102011-10-04 19:39:18 -07001164 mTextScaleX, mTextSkewX, 0, 1, 0, 0));
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001165 }
Deepanshu Guptaa6b207a2013-07-12 11:38:05 -07001166 // The metrics here don't have anti-aliasing set.
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001167 info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont);
1168
1169 infoList.add(info);
1170 }
1171
1172 mFonts = Collections.unmodifiableList(infoList);
1173 }
1174 }
1175
Deepanshu Guptaeb998d32014-01-07 11:58:44 -08001176 /*package*/ RectF measureText(char[] text, int index, int count, boolean isRtl) {
Deepanshu Guptaa6b207a2013-07-12 11:38:05 -07001177 return new BidiRenderer(null, this, text).renderText(
1178 index, index + count, isRtl, null, 0, false, 0, 0);
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001179 }
1180
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -08001181 private float getFontMetrics(FontMetrics metrics) {
1182 if (mFonts.size() > 0) {
1183 java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics;
1184 if (metrics != null) {
1185 // Android expects negative ascent so we invert the value from Java.
1186 metrics.top = - javaMetrics.getMaxAscent();
1187 metrics.ascent = - javaMetrics.getAscent();
1188 metrics.descent = javaMetrics.getDescent();
1189 metrics.bottom = javaMetrics.getMaxDescent();
1190 metrics.leading = javaMetrics.getLeading();
1191 }
1192
1193 return javaMetrics.getHeight();
1194 }
1195
1196 return 0;
1197 }
1198
Xavier Ducrohet43526ab2012-04-23 17:41:37 -07001199 private void setTextLocale(String locale) {
1200 mLocale = new Locale(locale);
1201 }
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -08001202
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001203 private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) {
1204 // get the delegate from the native int.
1205 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
1206 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001207 return;
1208 }
1209
1210 if (flagValue) {
1211 delegate.mFlags |= flagMask;
1212 } else {
1213 delegate.mFlags &= ~flagMask;
1214 }
1215 }
Xavier Ducrohet43526ab2012-04-23 17:41:37 -07001216
Deepanshu Guptaa6b207a2013-07-12 11:38:05 -07001217 private static boolean isRtl(int flag) {
1218 switch(flag) {
1219 case Paint.BIDI_RTL:
1220 case Paint.BIDI_FORCE_RTL:
1221 case Paint.BIDI_DEFAULT_RTL:
1222 return true;
1223 default:
1224 return false;
1225 }
1226 }
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001227}