blob: e60a61c9fd97f8a2f59b0f22d6fe93118a86b233 [file] [log] [blame]
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.graphics;
18
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -080019import com.android.ide.common.rendering.api.LayoutLog;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -080020import com.android.layoutlib.bridge.Bridge;
Xavier Ducrohet3bd98982010-11-09 18:25:03 -080021import com.android.layoutlib.bridge.impl.DelegateManager;
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -080022import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070023
24import android.graphics.Paint.FontMetrics;
25import android.graphics.Paint.FontMetricsInt;
Xavier Ducrohet37f21802010-11-01 16:17:18 -070026import android.text.TextUtils;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070027
Xavier Ducrohet37f21802010-11-01 16:17:18 -070028import java.awt.BasicStroke;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070029import java.awt.Font;
Xavier Ducrohetb9761242010-12-23 10:22:14 -080030import java.awt.Shape;
31import java.awt.Stroke;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070032import java.awt.Toolkit;
33import java.awt.font.FontRenderContext;
34import java.awt.geom.AffineTransform;
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -080035import java.awt.geom.Rectangle2D;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070036import java.util.ArrayList;
37import java.util.Collections;
38import java.util.List;
39
40/**
41 * Delegate implementing the native methods of android.graphics.Paint
42 *
43 * Through the layoutlib_create tool, the original native methods of Paint have been replaced
44 * by calls to methods of the same name in this delegate class.
45 *
46 * This class behaves like the original native implementation, but in Java, keeping previously
47 * native data into its own objects and mapping them to int that are sent back and forth between
48 * it and the original Paint class.
49 *
50 * @see DelegateManager
51 *
52 */
53public class Paint_Delegate {
54
55 /**
56 * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}.
57 */
Xavier Ducrohet37f21802010-11-01 16:17:18 -070058 /*package*/ static final class FontInfo {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -070059 Font mFont;
60 java.awt.FontMetrics mMetrics;
61 }
62
63 // ---- delegate manager ----
64 private static final DelegateManager<Paint_Delegate> sManager =
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 Ducrohetef44aea2010-10-28 11:52:00 -070094
95 // ---- Public Helper methods ----
96
Xavier Ducrohet37f21802010-11-01 16:17:18 -070097 public static Paint_Delegate getDelegate(int native_paint) {
98 return sManager.getDelegate(native_paint);
99 }
100
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700101 /**
102 * Returns the list of {@link Font} objects. The first item is the main font, the rest
103 * are fall backs for characters not present in the main font.
104 */
105 public List<FontInfo> getFonts() {
106 return mFonts;
107 }
108
Xavier Ducroheta313b652010-11-01 18:45:20 -0700109 public boolean isAntiAliased() {
110 return (mFlags & Paint.ANTI_ALIAS_FLAG) != 0;
111 }
112
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700113 public boolean isFilterBitmap() {
114 return (mFlags & Paint.FILTER_BITMAP_FLAG) != 0;
115 }
116
117 public int getStyle() {
118 return mStyle;
119 }
120
121 public int getColor() {
122 return mColor;
123 }
124
Xavier Ducrohet66225222010-12-21 01:33:04 -0800125 public int getAlpha() {
126 return mColor >>> 24;
127 }
128
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800129 public void setAlpha(int alpha) {
130 mColor = (alpha << 24) | (mColor & 0x00FFFFFF);
131 }
132
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700133 public int getTextAlign() {
134 return mTextAlign;
135 }
136
137 public float getStrokeWidth() {
138 return mStrokeWidth;
139 }
140
Xavier Ducrohet66225222010-12-21 01:33:04 -0800141 /**
142 * returns the value of stroke miter needed by the java api.
143 */
144 public float getJavaStrokeMiter() {
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800145 float miter = mStrokeMiter * mStrokeWidth;
146 if (miter < 1.f) {
147 miter = 1.f;
148 }
149 return miter;
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700150 }
151
152 public int getJavaCap() {
153 switch (Paint.sCapArray[mCap]) {
154 case BUTT:
155 return BasicStroke.CAP_BUTT;
156 case ROUND:
157 return BasicStroke.CAP_ROUND;
158 default:
159 case SQUARE:
160 return BasicStroke.CAP_SQUARE;
161 }
162 }
163
164 public int getJavaJoin() {
165 switch (Paint.sJoinArray[mJoin]) {
166 default:
167 case MITER:
168 return BasicStroke.JOIN_MITER;
169 case ROUND:
170 return BasicStroke.JOIN_ROUND;
171 case BEVEL:
172 return BasicStroke.JOIN_BEVEL;
173 }
174 }
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700175
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800176 public Stroke getJavaStroke() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800177 if (mPathEffect != null) {
178 if (mPathEffect.isSupported()) {
179 Stroke stroke = mPathEffect.getStroke(this);
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800180 assert stroke != null;
181 if (stroke != null) {
182 return stroke;
183 }
184 } else {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800185 Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800186 mPathEffect.getSupportMessage(),
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800187 null, null /*data*/);
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800188 }
189 }
190
191 // if no custom stroke as been set, set the default one.
192 return new BasicStroke(
193 getStrokeWidth(),
194 getJavaCap(),
195 getJavaJoin(),
196 getJavaStrokeMiter());
197 }
198
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800199 /**
200 * Returns the {@link Xfermode} delegate or null if none have been set
201 *
202 * @return the delegate or null.
203 */
204 public Xfermode_Delegate getXfermode() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800205 return mXfermode;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700206 }
207
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800208 /**
209 * Returns the {@link ColorFilter} delegate or null if none have been set
210 *
211 * @return the delegate or null.
212 */
213 public ColorFilter_Delegate getColorFilter() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800214 return mColorFilter;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700215 }
216
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800217 /**
218 * Returns the {@link Shader} delegate or null if none have been set
219 *
220 * @return the delegate or null.
221 */
222 public Shader_Delegate getShader() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800223 return mShader;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700224 }
225
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800226 /**
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800227 * Returns the {@link MaskFilter} delegate or null if none have been set
228 *
229 * @return the delegate or null.
230 */
231 public MaskFilter_Delegate getMaskFilter() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800232 return mMaskFilter;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800233 }
234
235 /**
236 * Returns the {@link Rasterizer} delegate or null if none have been set
237 *
238 * @return the delegate or null.
239 */
240 public Rasterizer_Delegate getRasterizer() {
Xavier Ducrohet91672792011-02-22 11:54:37 -0800241 return mRasterizer;
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700242 }
243
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700244 // ---- native methods ----
245
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800246 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700247 /*package*/ static int getFlags(Paint thisPaint) {
248 // get the delegate from the native int.
249 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
250 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700251 return 0;
252 }
253
254 return delegate.mFlags;
255 }
256
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800257 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700258 /*package*/ static void setFlags(Paint thisPaint, int flags) {
259 // get the delegate from the native int.
260 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
261 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700262 return;
263 }
264
265 delegate.mFlags = flags;
266 }
267
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800268 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700269 /*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700270 setFlag(thisPaint, Paint.FILTER_BITMAP_FLAG, filter);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700271 }
272
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800273 @LayoutlibDelegate
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -0700274 /*package*/ static int getHinting(Paint thisPaint) {
275 // get the delegate from the native int.
276 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
277 if (delegate == null) {
278 return Paint.HINTING_ON;
279 }
280
281 return delegate.mHintingMode;
282 }
283
284 @LayoutlibDelegate
285 /*package*/ static void setHinting(Paint thisPaint, int mode) {
286 // get the delegate from the native int.
287 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
288 if (delegate == null) {
289 return;
290 }
291
292 delegate.mHintingMode = mode;
293 }
294
295 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700296 /*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) {
297 setFlag(thisPaint, Paint.ANTI_ALIAS_FLAG, aa);
298 }
299
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800300 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700301 /*package*/ static void setSubpixelText(Paint thisPaint, boolean subpixelText) {
302 setFlag(thisPaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
303 }
304
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800305 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700306 /*package*/ static void setUnderlineText(Paint thisPaint, boolean underlineText) {
307 setFlag(thisPaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
308 }
309
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800310 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700311 /*package*/ static void setStrikeThruText(Paint thisPaint, boolean strikeThruText) {
312 setFlag(thisPaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
313 }
314
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800315 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700316 /*package*/ static void setFakeBoldText(Paint thisPaint, boolean fakeBoldText) {
317 setFlag(thisPaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
318 }
319
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800320 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700321 /*package*/ static void setDither(Paint thisPaint, boolean dither) {
322 setFlag(thisPaint, Paint.DITHER_FLAG, dither);
323 }
324
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800325 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700326 /*package*/ static void setLinearText(Paint thisPaint, boolean linearText) {
327 setFlag(thisPaint, Paint.LINEAR_TEXT_FLAG, linearText);
328 }
329
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800330 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700331 /*package*/ static int getColor(Paint thisPaint) {
332 // get the delegate from the native int.
333 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
334 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700335 return 0;
336 }
337
338 return delegate.mColor;
339 }
340
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800341 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700342 /*package*/ static void setColor(Paint thisPaint, int color) {
343 // get the delegate from the native int.
344 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
345 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700346 return;
347 }
348
349 delegate.mColor = color;
350 }
351
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800352 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700353 /*package*/ static int getAlpha(Paint thisPaint) {
354 // get the delegate from the native int.
355 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
356 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700357 return 0;
358 }
359
Xavier Ducrohet66225222010-12-21 01:33:04 -0800360 return delegate.getAlpha();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700361 }
362
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800363 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700364 /*package*/ static void setAlpha(Paint thisPaint, int a) {
365 // get the delegate from the native int.
366 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
367 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700368 return;
369 }
370
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -0800371 delegate.setAlpha(a);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700372 }
373
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800374 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700375 /*package*/ static float getStrokeWidth(Paint thisPaint) {
376 // get the delegate from the native int.
377 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
378 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700379 return 1.f;
380 }
381
382 return delegate.mStrokeWidth;
383 }
384
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800385 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700386 /*package*/ static void setStrokeWidth(Paint thisPaint, float width) {
387 // get the delegate from the native int.
388 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
389 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700390 return;
391 }
392
393 delegate.mStrokeWidth = width;
394 }
395
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800396 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700397 /*package*/ static float getStrokeMiter(Paint thisPaint) {
398 // get the delegate from the native int.
399 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
400 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700401 return 1.f;
402 }
403
404 return delegate.mStrokeMiter;
405 }
406
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800407 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700408 /*package*/ static void setStrokeMiter(Paint thisPaint, float miter) {
409 // get the delegate from the native int.
410 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
411 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700412 return;
413 }
414
415 delegate.mStrokeMiter = miter;
416 }
417
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800418 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700419 /*package*/ static void nSetShadowLayer(Paint thisPaint, float radius, float dx, float dy,
420 int color) {
421 // FIXME
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800422 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
Xavier Ducrohetf69bb292011-01-14 16:40:43 -0800423 "Paint.setShadowLayer is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700424 }
425
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800426 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700427 /*package*/ static float getTextSize(Paint thisPaint) {
428 // get the delegate from the native int.
429 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
430 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700431 return 1.f;
432 }
433
434 return delegate.mTextSize;
435 }
436
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800437 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700438 /*package*/ static void setTextSize(Paint thisPaint, float textSize) {
439 // get the delegate from the native int.
440 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
441 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700442 return;
443 }
444
445 delegate.mTextSize = textSize;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800446 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700447 }
448
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800449 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700450 /*package*/ static float getTextScaleX(Paint thisPaint) {
451 // get the delegate from the native int.
452 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
453 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700454 return 1.f;
455 }
456
457 return delegate.mTextScaleX;
458 }
459
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800460 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700461 /*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) {
462 // get the delegate from the native int.
463 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
464 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700465 return;
466 }
467
468 delegate.mTextScaleX = scaleX;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800469 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700470 }
471
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800472 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700473 /*package*/ static float getTextSkewX(Paint thisPaint) {
474 // get the delegate from the native int.
475 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
476 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700477 return 1.f;
478 }
479
480 return delegate.mTextSkewX;
481 }
482
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800483 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700484 /*package*/ static void setTextSkewX(Paint thisPaint, float skewX) {
485 // get the delegate from the native int.
486 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
487 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700488 return;
489 }
490
491 delegate.mTextSkewX = skewX;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800492 delegate.updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700493 }
494
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800495 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700496 /*package*/ static float ascent(Paint thisPaint) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800497 // get the delegate
498 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
499 if (delegate == null) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800500 return 0;
501 }
502
503 if (delegate.mFonts.size() > 0) {
504 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
505 // Android expects negative ascent so we invert the value from Java.
506 return - javaMetrics.getAscent();
507 }
508
509 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700510 }
511
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800512 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700513 /*package*/ static float descent(Paint thisPaint) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800514 // get the delegate
515 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
516 if (delegate == null) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800517 return 0;
518 }
519
520 if (delegate.mFonts.size() > 0) {
521 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
522 return javaMetrics.getDescent();
523 }
524
525 return 0;
526
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700527 }
528
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800529 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700530 /*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700531 // get the delegate
532 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
533 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700534 return 0;
535 }
536
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800537 return delegate.getFontMetrics(metrics);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700538 }
539
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800540 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700541 /*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700542 // get the delegate
543 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
544 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700545 return 0;
546 }
547
548 if (delegate.mFonts.size() > 0) {
549 java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
550 if (fmi != null) {
551 // Android expects negative ascent so we invert the value from Java.
552 fmi.top = - javaMetrics.getMaxAscent();
553 fmi.ascent = - javaMetrics.getAscent();
554 fmi.descent = javaMetrics.getDescent();
555 fmi.bottom = javaMetrics.getMaxDescent();
556 fmi.leading = javaMetrics.getLeading();
557 }
558
559 return javaMetrics.getHeight();
560 }
561
562 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700563 }
564
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800565 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700566 /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
567 int count) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700568 // get the delegate
569 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
570 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700571 return 0;
572 }
573
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700574 return delegate.measureText(text, index, count);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700575 }
576
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800577 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700578 /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end) {
579 return native_measureText(thisPaint, text.toCharArray(), start, end - start);
580 }
581
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800582 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700583 /*package*/ static float native_measureText(Paint thisPaint, String text) {
584 return native_measureText(thisPaint, text.toCharArray(), 0, text.length());
585 }
586
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800587 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700588 /*package*/ static int native_breakText(Paint thisPaint, char[] text, int index, int count,
589 float maxWidth, float[] measuredWidth) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800590
591 // get the delegate
592 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
593 if (delegate == null) {
594 return 0;
595 }
596
597 int inc = count > 0 ? 1 : -1;
598
599 int measureIndex = 0;
600 float measureAcc = 0;
601 for (int i = index; i != index + count; i += inc, measureIndex++) {
602 int start, end;
603 if (i < index) {
604 start = i;
605 end = index;
606 } else {
607 start = index;
608 end = i;
609 }
610
611 // measure from start to end
612 float res = delegate.measureText(text, start, end - start + 1);
613
614 if (measuredWidth != null) {
615 measuredWidth[measureIndex] = res;
616 }
617
618 measureAcc += res;
619 if (res > maxWidth) {
620 // we should not return this char index, but since it's 0-based
621 // and we need to return a count, we simply return measureIndex;
622 return measureIndex;
623 }
624
625 }
626
627 return measureIndex;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700628 }
629
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800630 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700631 /*package*/ static int native_breakText(Paint thisPaint, String text, boolean measureForwards,
632 float maxWidth, float[] measuredWidth) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800633 return native_breakText(thisPaint, text.toCharArray(), 0, text.length(), maxWidth,
634 measuredWidth);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700635 }
636
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800637 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700638 /*package*/ static int native_init() {
639 Paint_Delegate newDelegate = new Paint_Delegate();
Xavier Ducrohet91672792011-02-22 11:54:37 -0800640 return sManager.addNewDelegate(newDelegate);
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_initWithPaint(int paint) {
645 // get the delegate from the native int.
646 Paint_Delegate delegate = sManager.getDelegate(paint);
647 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700648 return 0;
649 }
650
651 Paint_Delegate newDelegate = new Paint_Delegate(delegate);
Xavier Ducrohet91672792011-02-22 11:54:37 -0800652 return sManager.addNewDelegate(newDelegate);
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 void native_reset(int native_object) {
657 // get the delegate from the native int.
658 Paint_Delegate delegate = sManager.getDelegate(native_object);
659 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700660 return;
661 }
662
663 delegate.reset();
664 }
665
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800666 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700667 /*package*/ static void native_set(int native_dst, int native_src) {
668 // get the delegate from the native int.
669 Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
670 if (delegate_dst == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700671 return;
672 }
673
674 // get the delegate from the native int.
675 Paint_Delegate delegate_src = sManager.getDelegate(native_src);
676 if (delegate_src == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700677 return;
678 }
679
680 delegate_dst.set(delegate_src);
681 }
682
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800683 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700684 /*package*/ static int native_getStyle(int native_object) {
685 // get the delegate from the native int.
686 Paint_Delegate delegate = sManager.getDelegate(native_object);
687 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700688 return 0;
689 }
690
691 return delegate.mStyle;
692 }
693
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800694 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700695 /*package*/ static void native_setStyle(int native_object, int style) {
696 // get the delegate from the native int.
697 Paint_Delegate delegate = sManager.getDelegate(native_object);
698 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700699 return;
700 }
701
702 delegate.mStyle = style;
703 }
704
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800705 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700706 /*package*/ static int native_getStrokeCap(int native_object) {
707 // get the delegate from the native int.
708 Paint_Delegate delegate = sManager.getDelegate(native_object);
709 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700710 return 0;
711 }
712
713 return delegate.mCap;
714 }
715
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800716 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700717 /*package*/ static void native_setStrokeCap(int native_object, int cap) {
718 // get the delegate from the native int.
719 Paint_Delegate delegate = sManager.getDelegate(native_object);
720 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700721 return;
722 }
723
724 delegate.mCap = cap;
725 }
726
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800727 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700728 /*package*/ static int native_getStrokeJoin(int native_object) {
729 // get the delegate from the native int.
730 Paint_Delegate delegate = sManager.getDelegate(native_object);
731 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700732 return 0;
733 }
734
735 return delegate.mJoin;
736 }
737
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800738 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700739 /*package*/ static void native_setStrokeJoin(int native_object, int join) {
740 // get the delegate from the native int.
741 Paint_Delegate delegate = sManager.getDelegate(native_object);
742 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700743 return;
744 }
745
746 delegate.mJoin = join;
747 }
748
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800749 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700750 /*package*/ static boolean native_getFillPath(int native_object, int src, int dst) {
Xavier Ducrohetb9761242010-12-23 10:22:14 -0800751 Paint_Delegate paint = sManager.getDelegate(native_object);
752 if (paint == null) {
753 return false;
754 }
755
756 Path_Delegate srcPath = Path_Delegate.getDelegate(src);
757 if (srcPath == null) {
758 return true;
759 }
760
761 Path_Delegate dstPath = Path_Delegate.getDelegate(dst);
762 if (dstPath == null) {
763 return true;
764 }
765
766 Stroke stroke = paint.getJavaStroke();
767 Shape strokeShape = stroke.createStrokedShape(srcPath.getJavaShape());
768
769 dstPath.setJavaShape(strokeShape);
770
771 // FIXME figure out the return value?
772 return true;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700773 }
774
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800775 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700776 /*package*/ static int native_setShader(int native_object, int shader) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700777 // get the delegate from the native int.
778 Paint_Delegate delegate = sManager.getDelegate(native_object);
779 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700780 return shader;
781 }
782
Xavier Ducrohet91672792011-02-22 11:54:37 -0800783 delegate.mShader = Shader_Delegate.getDelegate(shader);
784
785 return shader;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700786 }
787
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800788 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700789 /*package*/ static int native_setColorFilter(int native_object, int filter) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700790 // get the delegate from the native int.
791 Paint_Delegate delegate = sManager.getDelegate(native_object);
792 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700793 return filter;
794 }
795
Xavier Ducrohet91672792011-02-22 11:54:37 -0800796 delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800797
798 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800799 if (delegate.mColorFilter != null && delegate.mColorFilter.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800800 Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800801 delegate.mColorFilter.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800802 }
803
804 return filter;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700805 }
806
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800807 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700808 /*package*/ static int native_setXfermode(int native_object, int xfermode) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700809 // get the delegate from the native int.
810 Paint_Delegate delegate = sManager.getDelegate(native_object);
811 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700812 return xfermode;
813 }
814
Xavier Ducrohet91672792011-02-22 11:54:37 -0800815 delegate.mXfermode = Xfermode_Delegate.getDelegate(xfermode);
816
817 return xfermode;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700818 }
819
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800820 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700821 /*package*/ static int native_setPathEffect(int native_object, int effect) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700822 // get the delegate from the native int.
823 Paint_Delegate delegate = sManager.getDelegate(native_object);
824 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700825 return effect;
826 }
827
Xavier Ducrohet91672792011-02-22 11:54:37 -0800828 delegate.mPathEffect = PathEffect_Delegate.getDelegate(effect);
829
830 return effect;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700831 }
832
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800833 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700834 /*package*/ static int native_setMaskFilter(int native_object, int maskfilter) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700835 // get the delegate from the native int.
836 Paint_Delegate delegate = sManager.getDelegate(native_object);
837 if (delegate == null) {
Xavier Ducroheta313b652010-11-01 18:45:20 -0700838 return maskfilter;
839 }
840
Xavier Ducrohet91672792011-02-22 11:54:37 -0800841 delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800842
843 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800844 if (delegate.mMaskFilter != null && delegate.mMaskFilter.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800845 Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800846 delegate.mMaskFilter.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800847 }
848
849 return maskfilter;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700850 }
851
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800852 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700853 /*package*/ static int native_setTypeface(int native_object, int typeface) {
854 // get the delegate from the native int.
855 Paint_Delegate delegate = sManager.getDelegate(native_object);
856 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700857 return 0;
858 }
859
Xavier Ducrohet91672792011-02-22 11:54:37 -0800860 delegate.mTypeface = Typeface_Delegate.getDelegate(typeface);
Xavier Ducrohet42e2b282010-12-06 11:08:37 -0800861 delegate.updateFontObject();
Xavier Ducrohet91672792011-02-22 11:54:37 -0800862 return typeface;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700863 }
864
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800865 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700866 /*package*/ static int native_setRasterizer(int native_object, int rasterizer) {
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800867 // get the delegate from the native int.
868 Paint_Delegate delegate = sManager.getDelegate(native_object);
869 if (delegate == null) {
870 return rasterizer;
871 }
872
Xavier Ducrohet91672792011-02-22 11:54:37 -0800873 delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800874
875 // since none of those are supported, display a fidelity warning right away
Xavier Ducrohet91672792011-02-22 11:54:37 -0800876 if (delegate.mRasterizer != null && delegate.mRasterizer.isSupported() == false) {
Xavier Ducrohet3f9b0372011-01-13 10:59:34 -0800877 Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
Xavier Ducrohet91672792011-02-22 11:54:37 -0800878 delegate.mRasterizer.getSupportMessage(), null, null /*data*/);
Xavier Ducroheta6e51d52010-12-23 07:16:21 -0800879 }
880
881 return rasterizer;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700882 }
883
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800884 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700885 /*package*/ static int native_getTextAlign(int native_object) {
886 // get the delegate from the native int.
887 Paint_Delegate delegate = sManager.getDelegate(native_object);
888 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700889 return 0;
890 }
891
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700892 return delegate.mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700893 }
894
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800895 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700896 /*package*/ static void native_setTextAlign(int native_object, int align) {
897 // get the delegate from the native int.
898 Paint_Delegate delegate = sManager.getDelegate(native_object);
899 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700900 return;
901 }
902
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700903 delegate.mTextAlign = align;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700904 }
905
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800906 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700907 /*package*/ static float native_getFontMetrics(int native_paint, FontMetrics metrics) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800908 // get the delegate from the native int.
909 Paint_Delegate delegate = sManager.getDelegate(native_paint);
910 if (delegate == null) {
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -0800911 return 0.f;
912 }
913
914 return delegate.getFontMetrics(metrics);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700915 }
916
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800917 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700918 /*package*/ static int native_getTextWidths(int native_object, char[] text, int index,
919 int count, float[] widths) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800920 // get the delegate from the native int.
921 Paint_Delegate delegate = sManager.getDelegate(native_object);
922 if (delegate == null) {
923 return 0;
924 }
925
926 if (delegate.mFonts.size() > 0) {
927 // FIXME: handle multi-char characters (see measureText)
928 float totalAdvance = 0;
929 for (int i = 0; i < count; i++) {
930 char c = text[i + index];
931 boolean found = false;
932 for (FontInfo info : delegate.mFonts) {
933 if (info.mFont.canDisplay(c)) {
934 float adv = info.mMetrics.charWidth(c);
935 totalAdvance += adv;
936 if (widths != null) {
937 widths[i] = adv;
938 }
939
940 found = true;
941 break;
942 }
943 }
944
945 if (found == false) {
946 // no advance for this char.
947 if (widths != null) {
948 widths[i] = 0.f;
949 }
950 }
951 }
952
953 return (int) totalAdvance;
954 }
955
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -0800956 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700957 }
958
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800959 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700960 /*package*/ static int native_getTextWidths(int native_object, String text, int start,
961 int end, float[] widths) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -0800962 return native_getTextWidths(native_object, text.toCharArray(), start, end - start, widths);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700963 }
964
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -0800965 @LayoutlibDelegate
Xavier Ducrohet81efa7f2011-06-15 14:43:42 -0700966 /* package */static int native_getTextGlyphs(int native_object, String text, int start,
967 int end, int contextStart, int contextEnd, int flags, char[] glyphs) {
968 // FIXME
969 return 0;
970 }
971
972 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -0700973 /*package*/ static float native_getTextRunAdvances(int native_object,
974 char[] text, int index, int count, int contextIndex, int contextCount,
Xavier Ducrohet81efa7f2011-06-15 14:43:42 -0700975 int flags, float[] advances, int advancesIndex, int reserved) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700976 // get the delegate from the native int.
977 Paint_Delegate delegate = sManager.getDelegate(native_object);
978 if (delegate == null) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700979 return 0.f;
980 }
981
982 if (delegate.mFonts.size() > 0) {
Xavier Ducrohetf1a174522010-11-01 22:02:08 -0700983 // FIXME: handle multi-char characters (see measureText)
Xavier Ducrohet37f21802010-11-01 16:17:18 -0700984 float totalAdvance = 0;
985 for (int i = 0; i < count; i++) {
986 char c = text[i + index];
987 boolean found = false;
988 for (FontInfo info : delegate.mFonts) {
989 if (info.mFont.canDisplay(c)) {
990 float adv = info.mMetrics.charWidth(c);
991 totalAdvance += adv;
992 if (advances != null) {
993 advances[i] = adv;
994 }
995
996 found = true;
997 break;
998 }
999 }
1000
1001 if (found == false) {
1002 // no advance for this char.
1003 if (advances != null) {
1004 advances[i] = 0.f;
1005 }
1006 }
1007 }
1008
1009 return totalAdvance;
1010 }
1011
1012 return 0;
1013
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001014 }
1015
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001016 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001017 /*package*/ static float native_getTextRunAdvances(int native_object,
1018 String text, int start, int end, int contextStart, int contextEnd,
Xavier Ducrohet81efa7f2011-06-15 14:43:42 -07001019 int flags, float[] advances, int advancesIndex, int reserved) {
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001020 // FIXME: support contextStart, contextEnd and direction flag
1021 int count = end - start;
1022 char[] buffer = TemporaryBuffer.obtain(count);
1023 TextUtils.getChars(text, start, end, buffer, 0);
1024
1025 return native_getTextRunAdvances(native_object, buffer, 0, count, contextStart,
Xavier Ducrohet81efa7f2011-06-15 14:43:42 -07001026 contextEnd - contextStart, flags, advances, advancesIndex, reserved);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001027 }
1028
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001029 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001030 /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, char[] text,
1031 int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
1032 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001033 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1034 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
1035 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001036 }
1037
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001038 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001039 /*package*/ static int native_getTextRunCursor(Paint thisPaint, int native_object, String text,
1040 int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
1041 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001042 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1043 "Paint.getTextRunCursor is not supported.", null, null /*data*/);
1044 return 0;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001045 }
1046
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001047 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001048 /*package*/ static void native_getTextPath(int native_object, int bidiFlags,
1049 char[] text, int index, int count, float x, float y, int path) {
1050 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001051 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1052 "Paint.getTextPath is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001053 }
1054
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001055 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001056 /*package*/ static void native_getTextPath(int native_object, int bidiFlags,
1057 String text, int start, int end, float x, float y, int path) {
1058 // FIXME
Xavier Ducrohet1eeaea02011-02-09 19:39:52 -08001059 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
1060 "Paint.getTextPath is not supported.", null, null /*data*/);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001061 }
1062
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001063 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001064 /*package*/ static void nativeGetStringBounds(int nativePaint, String text, int start,
1065 int end, Rect bounds) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001066 nativeGetCharArrayBounds(nativePaint, text.toCharArray(), start, end - start, bounds);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001067 }
1068
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001069 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001070 /*package*/ static void nativeGetCharArrayBounds(int nativePaint, char[] text, int index,
1071 int count, Rect bounds) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001072
1073 // get the delegate from the native int.
1074 Paint_Delegate delegate = sManager.getDelegate(nativePaint);
1075 if (delegate == null) {
1076 return;
1077 }
1078
1079 // FIXME should test if the main font can display all those characters.
1080 // See MeasureText
1081 if (delegate.mFonts.size() > 0) {
1082 FontInfo mainInfo = delegate.mFonts.get(0);
1083
1084 Rectangle2D rect = mainInfo.mFont.getStringBounds(text, index, index + count,
1085 delegate.mFontContext);
1086 bounds.set(0, 0, (int) rect.getWidth(), (int) rect.getHeight());
1087 }
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001088 }
1089
Xavier Ducrohet94c80bf2011-02-09 17:17:49 -08001090 @LayoutlibDelegate
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001091 /*package*/ static void finalizer(int nativePaint) {
Xavier Ducrohet91672792011-02-22 11:54:37 -08001092 sManager.removeJavaReferenceFor(nativePaint);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001093 }
1094
1095 // ---- Private delegate/helper methods ----
1096
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001097 /*package*/ Paint_Delegate() {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001098 reset();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001099 }
1100
1101 private Paint_Delegate(Paint_Delegate paint) {
1102 set(paint);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001103 }
1104
1105 private void set(Paint_Delegate paint) {
1106 mFlags = paint.mFlags;
1107 mColor = paint.mColor;
1108 mStyle = paint.mStyle;
1109 mCap = paint.mCap;
1110 mJoin = paint.mJoin;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001111 mTextAlign = paint.mTextAlign;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001112 mTypeface = paint.mTypeface;
1113 mStrokeWidth = paint.mStrokeWidth;
1114 mStrokeMiter = paint.mStrokeMiter;
1115 mTextSize = paint.mTextSize;
1116 mTextScaleX = paint.mTextScaleX;
1117 mTextSkewX = paint.mTextSkewX;
Xavier Ducroheta313b652010-11-01 18:45:20 -07001118 mXfermode = paint.mXfermode;
1119 mColorFilter = paint.mColorFilter;
1120 mShader = paint.mShader;
1121 mPathEffect = paint.mPathEffect;
1122 mMaskFilter = paint.mMaskFilter;
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001123 mRasterizer = paint.mRasterizer;
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -07001124 mHintingMode = paint.mHintingMode;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001125 updateFontObject();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001126 }
1127
1128 private void reset() {
1129 mFlags = Paint.DEFAULT_PAINT_FLAGS;
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001130 mColor = 0xFF000000;
Xavier Ducrohet66225222010-12-21 01:33:04 -08001131 mStyle = Paint.Style.FILL.nativeInt;
1132 mCap = Paint.Cap.BUTT.nativeInt;
1133 mJoin = Paint.Join.MITER.nativeInt;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001134 mTextAlign = 0;
Xavier Ducrohet91672792011-02-22 11:54:37 -08001135 mTypeface = Typeface_Delegate.getDelegate(Typeface.sDefaults[0].native_instance);
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001136 mStrokeWidth = 1.f;
Xavier Ducrohetcf2030c2010-12-21 06:20:28 -08001137 mStrokeMiter = 4.f;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001138 mTextSize = 20.f;
1139 mTextScaleX = 1.f;
1140 mTextSkewX = 0.f;
Xavier Ducrohet91672792011-02-22 11:54:37 -08001141 mXfermode = null;
1142 mColorFilter = null;
1143 mShader = null;
1144 mPathEffect = null;
1145 mMaskFilter = null;
1146 mRasterizer = null;
Xavier Ducrohet42e2b282010-12-06 11:08:37 -08001147 updateFontObject();
Xavier Ducrohetb6f7f572011-08-22 13:13:16 -07001148 mHintingMode = Paint.HINTING_ON;
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001149 }
1150
1151 /**
1152 * Update the {@link Font} object from the typeface, text size and scaling
1153 */
Xavier Ducroheta6e51d52010-12-23 07:16:21 -08001154 @SuppressWarnings("deprecation")
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001155 private void updateFontObject() {
Xavier Ducrohet91672792011-02-22 11:54:37 -08001156 if (mTypeface != null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001157 // Get the fonts from the TypeFace object.
Xavier Ducrohet91672792011-02-22 11:54:37 -08001158 List<Font> fonts = mTypeface.getFonts();
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001159
1160 // create new font objects as well as FontMetrics, based on the current text size
1161 // and skew info.
1162 ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(fonts.size());
1163 for (Font font : fonts) {
1164 FontInfo info = new FontInfo();
1165 info.mFont = font.deriveFont(mTextSize);
1166 if (mTextScaleX != 1.0 || mTextSkewX != 0) {
1167 // TODO: support skew
1168 info.mFont = info.mFont.deriveFont(new AffineTransform(
1169 mTextScaleX, mTextSkewX, 0, 0, 1, 0));
1170 }
1171 info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont);
1172
1173 infoList.add(info);
1174 }
1175
1176 mFonts = Collections.unmodifiableList(infoList);
1177 }
1178 }
1179
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001180 /*package*/ float measureText(char[] text, int index, int count) {
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001181
1182 // WARNING: the logic in this method is similar to Canvas_Delegate.native_drawText
1183 // Any change to this method should be reflected there as well
1184
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001185 if (mFonts.size() > 0) {
1186 FontInfo mainFont = mFonts.get(0);
1187 int i = index;
1188 int lastIndex = index + count;
1189 float total = 0f;
1190 while (i < lastIndex) {
1191 // always start with the main font.
1192 int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
1193 if (upTo == -1) {
1194 // shortcut to exit
1195 return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i);
1196 } else if (upTo > 0) {
1197 total += mainFont.mMetrics.charsWidth(text, i, upTo - i);
1198 i = upTo;
1199 // don't call continue at this point. Since it is certain the main font
1200 // cannot display the font a index upTo (now ==i), we move on to the
1201 // fallback fonts directly.
1202 }
1203
1204 // no char supported, attempt to read the next char(s) with the
1205 // fallback font. In this case we only test the first character
1206 // and then go back to test with the main font.
1207 // Special test for 2-char characters.
1208 boolean foundFont = false;
1209 for (int f = 1 ; f < mFonts.size() ; f++) {
1210 FontInfo fontInfo = mFonts.get(f);
1211
1212 // need to check that the font can display the character. We test
1213 // differently if the char is a high surrogate.
1214 int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
1215 upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
1216 if (upTo == -1) {
1217 total += fontInfo.mMetrics.charsWidth(text, i, charCount);
1218 i += charCount;
1219 foundFont = true;
1220 break;
1221
1222 }
1223 }
1224
1225 // in case no font can display the char, measure it with the main font.
1226 if (foundFont == false) {
1227 int size = Character.isHighSurrogate(text[i]) ? 2 : 1;
1228 total += mainFont.mMetrics.charsWidth(text, i, size);
1229 i += size;
1230 }
1231 }
Xavier Ducrohetf4d52a62011-02-23 09:53:56 -08001232
1233 return total;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001234 }
1235
1236 return 0;
Xavier Ducrohet37f21802010-11-01 16:17:18 -07001237 }
1238
Xavier Ducrohetdf67eab2010-12-13 16:42:01 -08001239 private float getFontMetrics(FontMetrics metrics) {
1240 if (mFonts.size() > 0) {
1241 java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics;
1242 if (metrics != null) {
1243 // Android expects negative ascent so we invert the value from Java.
1244 metrics.top = - javaMetrics.getMaxAscent();
1245 metrics.ascent = - javaMetrics.getAscent();
1246 metrics.descent = javaMetrics.getDescent();
1247 metrics.bottom = javaMetrics.getMaxDescent();
1248 metrics.leading = javaMetrics.getLeading();
1249 }
1250
1251 return javaMetrics.getHeight();
1252 }
1253
1254 return 0;
1255 }
1256
1257
1258
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001259 private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) {
1260 // get the delegate from the native int.
1261 Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
1262 if (delegate == null) {
Xavier Ducrohetef44aea2010-10-28 11:52:00 -07001263 return;
1264 }
1265
1266 if (flagValue) {
1267 delegate.mFlags |= flagMask;
1268 } else {
1269 delegate.mFlags &= ~flagMask;
1270 }
1271 }
1272}