microui  14.1.1
microui
LLUI_PAINTER_impl.c
1 /*
2  * Copyright 2020-2024 MicroEJ Corp. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be found with this software.
4  */
5 
6 /*
7  * @file
8  * @brief This file implements all MicroUI drawing native functions.
9  * @see LLUI_PAINTER_impl.h file comment
10  * @author MicroEJ Developer Team
11  * @version 14.1.1
12  * @since MicroEJ UI Pack 13.0.0
13  */
14 
15 // --------------------------------------------------------------------------------
16 // Includes
17 // --------------------------------------------------------------------------------
18 
19 // implements LLUI_PAINTER_impl functions
20 #include <LLUI_PAINTER_impl.h>
21 
22 // use graphical engine functions to synchronize drawings
23 #include <LLUI_DISPLAY.h>
24 
25 // check UI Pack version
26 #include <LLUI_DISPLAY_impl.h>
27 
28 // calls ui_drawing functions
29 #include "ui_drawing.h"
30 
31 // logs the drawings
32 #include "ui_log.h"
33 
34 // --------------------------------------------------------------------------------
35 // Macros and Defines
36 // --------------------------------------------------------------------------------
37 
38 #if (defined(LLUI_MAJOR_VERSION) && (LLUI_MAJOR_VERSION != 14)) || (defined(LLUI_MINOR_VERSION) && \
39  (LLUI_MINOR_VERSION < 0))
40 #error "This CCO is only compatible with UI Pack [14.0.0,15.0.0["
41 #endif
42 
43 // macros to log a drawing
44 #define LOG_DRAW_START(fn) LLTRACE_record_event_u32(LLUI_EVENT_group, LLUI_EVENT_offset + UI_LOG_DRAW, \
45  CONCAT_DEFINES(LOG_DRAW_, fn))
46 #define LOG_DRAW_END(s) LLTRACE_record_event_end_u32(LLUI_EVENT_group, LLUI_EVENT_offset + UI_LOG_DRAW, (s))
47 
48 /*
49  * LOG_DRAW_EVENT logs identifiers
50  */
51 #define LOG_DRAW_writePixel 1
52 #define LOG_DRAW_drawLine 2
53 #define LOG_DRAW_drawHorizontalLine 3
54 #define LOG_DRAW_drawVerticalLine 4
55 #define LOG_DRAW_drawRectangle 5
56 #define LOG_DRAW_fillRectangle 6
57 #define LOG_DRAW_drawRoundedRectangle 8
58 #define LOG_DRAW_fillRoundedRectangle 9
59 #define LOG_DRAW_drawCircleArc 10
60 #define LOG_DRAW_fillCircleArc 11
61 #define LOG_DRAW_drawEllipseArc 12
62 #define LOG_DRAW_fillEllipseArc 13
63 #define LOG_DRAW_drawEllipse 14
64 #define LOG_DRAW_fillEllipse 15
65 #define LOG_DRAW_drawCircle 16
66 #define LOG_DRAW_fillCircle 17
67 #define LOG_DRAW_drawARGB 18
68 #define LOG_DRAW_drawImage 19
69 #define LOG_DRAW_drawString 20
70 #define LOG_DRAW_stringWidth 21
71 
72 // --------------------------------------------------------------------------------
73 // Private functions
74 // --------------------------------------------------------------------------------
75 
76 /*
77  * Checks given bound to fit in bound limits: 0 and max (excluded). Updates size and
78  * origin in consequence
79  */
80 static inline void _check_bound(jint max, jint *bound, jint *size, jint *origin) {
81  if (*bound < 0) {
82  *size += *bound; // decrease size
83  *origin -= *bound; // increase origin
84  *bound = 0;
85  }
86 
87  if ((*bound + *size) > max) {
88  *size = max - *bound; // decrease size
89  }
90 }
91 
92 // --------------------------------------------------------------------------------
93 // LLUI_PAINTER_impl.h functions
94 // --------------------------------------------------------------------------------
95 
96 // See the header file for the function documentation
97 void LLUI_PAINTER_IMPL_writePixel(MICROUI_GraphicsContext *gc, jint x, jint y) {
98  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_writePixel)) {
99  DRAWING_Status status;
100  LOG_DRAW_START(writePixel);
101  if (LLUI_DISPLAY_isPixelInClip(gc, x, y)) {
102  LLUI_DISPLAY_configureClip(gc, false /* point is in clip */);
103  status = UI_DRAWING_writePixel(gc, x, y);
104  } else {
105  // requestDrawing() has been called and accepted: notify the end of empty drawing
106  status = DRAWING_DONE;
107  }
108  LLUI_DISPLAY_setDrawingStatus(status);
109  LOG_DRAW_END(status);
110  }
111 }
112 
113 // See the header file for the function documentation
114 void LLUI_PAINTER_IMPL_drawLine(MICROUI_GraphicsContext *gc, jint startX, jint startY, jint endX, jint endY) {
115  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawLine)) {
116  LOG_DRAW_START(drawLine);
117  // cannot reduce/clip line: may be endX < startX and / or endY < startY
118  DRAWING_Status status = UI_DRAWING_drawLine(gc, startX, startY, endX, endY);
119  LLUI_DISPLAY_setDrawingStatus(status);
120  LOG_DRAW_END(status);
121  }
122 }
123 
124 // See the header file for the function documentation
125 void LLUI_PAINTER_IMPL_drawHorizontalLine(MICROUI_GraphicsContext *gc, jint x, jint y, jint length) {
126  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawHorizontalLine)) {
127  DRAWING_Status status;
128  LOG_DRAW_START(drawHorizontalLine);
129 
130  jint x1 = x;
131  jint x2 = x + length - 1;
132 
133  // tests on size and clip are performed after suspend to prevent to perform it several times
134  if ((length > 0) && LLUI_DISPLAY_clipHorizontalLine(gc, &x1, &x2, y)) {
135  LLUI_DISPLAY_configureClip(gc, false /* line has been clipped */);
136  status = UI_DRAWING_drawHorizontalLine(gc, x1, x2, y);
137  } else {
138  // requestDrawing() has been called and accepted: notify the end of empty drawing
139  status = DRAWING_DONE;
140  }
141  LLUI_DISPLAY_setDrawingStatus(status);
142  LOG_DRAW_END(status);
143  }
144 }
145 
146 // See the header file for the function documentation
147 void LLUI_PAINTER_IMPL_drawVerticalLine(MICROUI_GraphicsContext *gc, jint x, jint y, jint length) {
148  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawVerticalLine)) {
149  DRAWING_Status status;
150  LOG_DRAW_START(drawVerticalLine);
151 
152  jint y1 = y;
153  jint y2 = y + length - 1;
154 
155  // tests on size and clip are performed after suspend to prevent to perform it several times
156  if ((length > 0) && LLUI_DISPLAY_clipVerticalLine(gc, &y1, &y2, x)) {
157  LLUI_DISPLAY_configureClip(gc, false /* line has been clipped */);
158  status = UI_DRAWING_drawVerticalLine(gc, x, y1, y2);
159  } else {
160  // requestDrawing() has been called and accepted: notify the end of empty drawing
161  status = DRAWING_DONE;
162  }
163  LLUI_DISPLAY_setDrawingStatus(status);
164  LOG_DRAW_END(status);
165  }
166 }
167 
168 // See the header file for the function documentation
169 void LLUI_PAINTER_IMPL_drawRectangle(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height) {
170  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawRectangle)) {
171  DRAWING_Status status;
172  LOG_DRAW_START(drawRectangle);
173 
174  // tests on size and clip are performed after suspend to prevent to perform it several times
175  if ((width > 0) && (height > 0)) {
176  jint x1 = x;
177  jint x2 = x + width - 1;
178  jint y1 = y;
179  jint y2 = y + height - 1;
180 
181  // cannot reduce rectangle; can only check if it is fully in clip
182  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRectangleInClip(gc, x1, y1, x2, y2));
183  status = UI_DRAWING_drawRectangle(gc, x1, y1, x2, y2);
184  } else {
185  // requestDrawing() has been called and accepted: notify the end of empty drawing
186  status = DRAWING_DONE;
187  }
188  LLUI_DISPLAY_setDrawingStatus(status);
189  LOG_DRAW_END(status);
190  }
191 }
192 
193 // See the header file for the function documentation
194 void LLUI_PAINTER_IMPL_fillRectangle(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height) {
195  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillRectangle)) {
196  DRAWING_Status status;
197  LOG_DRAW_START(fillRectangle);
198 
199  jint x1 = x;
200  jint x2 = x + width - 1;
201  jint y1 = y;
202  jint y2 = y + height - 1;
203 
204  // tests on size and clip are performed after suspend to prevent to perform it several times
205  if ((width > 0) && (height > 0) && LLUI_DISPLAY_clipRectangle(gc, &x1, &y1, &x2, &y2)) {
206  LLUI_DISPLAY_configureClip(gc, false /* rectangle has been clipped */);
207  status = UI_DRAWING_fillRectangle(gc, x1, y1, x2, y2);
208  } else {
209  // requestDrawing() has been called and accepted: notify the end of empty drawing
210  status = DRAWING_DONE;
211  }
212  LLUI_DISPLAY_setDrawingStatus(status);
213  LOG_DRAW_END(status);
214  }
215 }
216 
217 // See the header file for the function documentation
218 void LLUI_PAINTER_IMPL_drawRoundedRectangle(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height,
219  jint cornerEllipseWidth, jint cornerEllipseHeight) {
220  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawRoundedRectangle)) {
221  DRAWING_Status status;
222  LOG_DRAW_START(drawRoundedRectangle);
223 
224  // tests on size and clip are performed after suspend to prevent to perform it several times
225  if ((width > 0) && (height > 0)) {
226  // cannot reduce rectangle; can only check if it is fully in clip
227  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
228  status = UI_DRAWING_drawRoundedRectangle(gc, x, y, width, height, cornerEllipseWidth, cornerEllipseHeight);
229  } else {
230  // requestDrawing() has been called and accepted: notify the end of empty drawing
231  status = DRAWING_DONE;
232  }
233  LLUI_DISPLAY_setDrawingStatus(status);
234  LOG_DRAW_END(status);
235  }
236 }
237 
238 // See the header file for the function documentation
239 void LLUI_PAINTER_IMPL_fillRoundedRectangle(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height,
240  jint cornerEllipseWidth, jint cornerEllipseHeight) {
241  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillRoundedRectangle)) {
242  DRAWING_Status status;
243  LOG_DRAW_START(fillRoundedRectangle);
244 
245  // tests on size and clip are performed after suspend to prevent to perform it several times
246  if ((width > 0) && (height > 0)) {
247  // cannot reduce rectangle; can only check if it is fully in clip
248  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
249  status = UI_DRAWING_fillRoundedRectangle(gc, x, y, width, height, cornerEllipseWidth, cornerEllipseHeight);
250  } else {
251  // requestDrawing() has been called and accepted: notify the end of empty drawing
252  status = DRAWING_DONE;
253  }
254  LLUI_DISPLAY_setDrawingStatus(status);
255  LOG_DRAW_END(status);
256  }
257 }
258 
259 // See the header file for the function documentation
260 void LLUI_PAINTER_IMPL_drawCircleArc(MICROUI_GraphicsContext *gc, jint x, jint y, jint diameter, jfloat startAngle,
261  jfloat arcAngle) {
262  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawCircleArc)) {
263  DRAWING_Status status;
264  LOG_DRAW_START(drawCircleArc);
265 
266  // tests on size and clip are performed after suspend to prevent to perform it several times
267  if ((diameter > 0) && ((int32_t)arcAngle != 0)) {
268  // cannot reduce rectangle; can only check if it is fully in clip
269  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, diameter, diameter));
270  status = UI_DRAWING_drawCircleArc(gc, x, y, diameter, startAngle, arcAngle);
271  } else {
272  // requestDrawing() has been called and accepted: notify the end of empty drawing
273  status = DRAWING_DONE;
274  }
275  LLUI_DISPLAY_setDrawingStatus(status);
276  LOG_DRAW_END(status);
277  }
278 }
279 
280 // See the header file for the function documentation
281 void LLUI_PAINTER_IMPL_drawEllipseArc(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height,
282  jfloat startAngle, jfloat arcAngle) {
283  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawEllipseArc)) {
284  DRAWING_Status status;
285  LOG_DRAW_START(drawEllipseArc);
286 
287  // tests on size and clip are performed after suspend to prevent to perform it several times
288  if ((width > 0) && (height > 0) && ((int32_t)arcAngle != 0)) {
289  // cannot reduce rectangle; can only check if it is fully in clip
290  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
291  status = UI_DRAWING_drawEllipseArc(gc, x, y, width, height, startAngle, arcAngle);
292  } else {
293  // requestDrawing() has been called and accepted: notify the end of empty drawing
294  status = DRAWING_DONE;
295  }
296  LLUI_DISPLAY_setDrawingStatus(status);
297  LOG_DRAW_END(status);
298  }
299 }
300 
301 // See the header file for the function documentation
302 void LLUI_PAINTER_IMPL_fillCircleArc(MICROUI_GraphicsContext *gc, jint x, jint y, jint diameter, jfloat startAngle,
303  jfloat arcAngle) {
304  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillCircleArc)) {
305  DRAWING_Status status;
306  LOG_DRAW_START(fillCircleArc);
307 
308  // tests on size and clip are performed after suspend to prevent to perform it several times
309  if ((diameter > 0) && ((int32_t)arcAngle != 0)) {
310  // cannot reduce rectangle; can only check if it is fully in clip
311  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, diameter, diameter));
312  status = UI_DRAWING_fillCircleArc(gc, x, y, diameter, startAngle, arcAngle);
313  } else {
314  // requestDrawing() has been called and accepted: notify the end of empty drawing
315  status = DRAWING_DONE;
316  }
317  LLUI_DISPLAY_setDrawingStatus(status);
318  LOG_DRAW_END(status);
319  }
320 }
321 
322 // See the header file for the function documentation
323 void LLUI_PAINTER_IMPL_fillEllipseArc(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height,
324  jfloat startAngle, jfloat arcAngle) {
325  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillEllipseArc)) {
326  DRAWING_Status status;
327  LOG_DRAW_START(fillEllipseArc);
328 
329  // tests on size and clip are performed after suspend to prevent to perform it several times
330  if ((width > 0) && (height > 0) && ((int32_t)arcAngle != 0)) {
331  // cannot reduce rectangle; can only check if it is fully in clip
332  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
333  status = UI_DRAWING_fillEllipseArc(gc, x, y, width, height, startAngle, arcAngle);
334  } else {
335  // requestDrawing() has been called and accepted: notify the end of empty drawing
336  status = DRAWING_DONE;
337  }
338  LLUI_DISPLAY_setDrawingStatus(status);
339  LOG_DRAW_END(status);
340  }
341 }
342 
343 // See the header file for the function documentation
344 void LLUI_PAINTER_IMPL_drawEllipse(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height) {
345  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawEllipse)) {
346  DRAWING_Status status;
347  LOG_DRAW_START(drawEllipse);
348 
349  // tests on size and clip are performed after suspend to prevent to perform it several times
350  if ((width > 0) && (height > 0)) {
351  // cannot reduce rectangle; can only check if it is fully in clip
352  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
353  status = UI_DRAWING_drawEllipse(gc, x, y, width, height);
354  } else {
355  // requestDrawing() has been called and accepted: notify the end of empty drawing
356  status = DRAWING_DONE;
357  }
358  LLUI_DISPLAY_setDrawingStatus(status);
359  LOG_DRAW_END(status);
360  }
361 }
362 
363 // See the header file for the function documentation
364 void LLUI_PAINTER_IMPL_fillEllipse(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height) {
365  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillEllipse)) {
366  DRAWING_Status status;
367  LOG_DRAW_START(fillEllipse);
368 
369  // tests on size and clip are performed after suspend to prevent to perform it several times
370  if ((width > 0) && (height > 0)) {
371  // cannot reduce rectangle; can only check if it is fully in clip
372  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
373  status = UI_DRAWING_fillEllipse(gc, x, y, width, height);
374  } else {
375  // requestDrawing() has been called and accepted: notify the end of empty drawing
376  status = DRAWING_DONE;
377  }
378  LLUI_DISPLAY_setDrawingStatus(status);
379  LOG_DRAW_END(status);
380  }
381 }
382 
383 // See the header file for the function documentation
384 void LLUI_PAINTER_IMPL_drawCircle(MICROUI_GraphicsContext *gc, jint x, jint y, jint diameter) {
385  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawCircle)) {
386  DRAWING_Status status;
387  LOG_DRAW_START(drawCircle);
388 
389  // tests on size and clip are performed after suspend to prevent to perform it several times
390  if (diameter > 0) {
391  // cannot reduce rectangle; can only check if it is fully in clip
392  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, diameter, diameter));
393  status = UI_DRAWING_drawCircle(gc, x, y, diameter);
394  } else {
395  // requestDrawing() has been called and accepted: notify the end of empty drawing
396  status = DRAWING_DONE;
397  }
398  LLUI_DISPLAY_setDrawingStatus(status);
399  LOG_DRAW_END(status);
400  }
401 }
402 
403 // See the header file for the function documentation
404 void LLUI_PAINTER_IMPL_fillCircle(MICROUI_GraphicsContext *gc, jint x, jint y, jint diameter) {
405  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillCircle)) {
406  DRAWING_Status status;
407  LOG_DRAW_START(fillCircle);
408 
409  // tests on size and clip are performed after suspend to prevent to perform it several times
410  if (diameter > 0) {
411  // cannot reduce rectangle; can only check if it is fully in clip
412  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, diameter, diameter));
413  status = UI_DRAWING_fillCircle(gc, x, y, diameter);
414  } else {
415  // requestDrawing() has been called and accepted: notify the end of empty drawing
416  status = DRAWING_DONE;
417  }
418  LLUI_DISPLAY_setDrawingStatus(status);
419  LOG_DRAW_END(status);
420  }
421 }
422 
423 // See the header file for the function documentation
424 void LLUI_PAINTER_IMPL_drawImage(MICROUI_GraphicsContext *gc, MICROUI_Image *img, jint regionX, jint regionY,
425  jint width, jint height, jint x, jint y, jint alpha) {
426  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawImage)) {
427  DRAWING_Status status = DRAWING_DONE;
428  LOG_DRAW_START(drawImage);
429 
430  // tests on parameters and clip are performed after suspend to prevent to perform it several times
431  if (!LLUI_DISPLAY_isImageClosed(img) && (alpha > 0)) {
432  // sanity check on opacity
433  jint l_alpha = (alpha > 255) ? 255 : alpha;
434 
435  // compute inside image bounds
436  _check_bound(img->width, &regionX, &width, &x);
437  _check_bound(img->height, &regionY, &height, &y);
438 
439  // compute inside graphics context bounds
440  _check_bound(gc->image.width, &x, &width, &regionX);
441  _check_bound(gc->image.height, &y, &height, &regionY);
442 
443  if ((width > 0) && (height > 0) && LLUI_DISPLAY_clipRegion(gc, &regionX, &regionY, &width, &height, &x,
444  &y)) {
445  LLUI_DISPLAY_configureClip(gc, false /* region has been clipped */);
446 
447  if (gc->image.format == img->format) {
448  // source & destination have got the same pixels memory representation
449 
450  MICROUI_Image *image = LLUI_DISPLAY_getSourceImage(img);
451 
452  if ((0xff /* fully opaque */ == l_alpha) && !LLUI_DISPLAY_isTransparent(img)) {
453  // copy source on destination without applying an opacity (beware about the overlapping)
454  status = UI_DRAWING_copyImage(gc, image, regionX, regionY, width, height, x, y);
455  } else if (LLUI_DISPLAY_getBufferAddress(img) == LLUI_DISPLAY_getBufferAddress(&gc->image)) {
456  // blend source on itself applying an opacity (beware about the overlapping)
457  status = UI_DRAWING_drawRegion(gc, regionX, regionY, width, height, x, y, l_alpha);
458  } else {
459  // blend source on destination applying an opacity
460  status = UI_DRAWING_drawImage(gc, image, regionX, regionY, width, height, x, y, l_alpha);
461  }
462  } else {
463  // draw source on destination applying an opacity
464  status = UI_DRAWING_drawImage(gc, img, regionX, regionY, width, height, x, y, l_alpha);
465  }
466  }
467  // else: nothing to do
468  }
469  // else: nothing to do
470 
471  // requestDrawing() has been called and accepted: notify the end of empty drawing
472  LLUI_DISPLAY_setDrawingStatus(status);
473  LOG_DRAW_END(status);
474  }
475 }
476 
477 // See the header file for the function documentation
478 void LLUI_PAINTER_IMPL_drawString(MICROUI_GraphicsContext *gc, jchar *chars, jint offset, jint length,
479  MICROUI_Font *font, jint x, jint y) {
480  if ((length > 0) && LLUI_DISPLAY_requestDrawing(gc, (SNI_callback)LLUI_PAINTER_IMPL_drawString)) {
481  LOG_DRAW_START(drawString);
482  DRAWING_Status status = UI_DRAWING_drawString(gc, chars + offset, length, font, x, y);
483  LLUI_DISPLAY_setDrawingStatus(status);
484  LOG_DRAW_END(status);
485  }
486 }
487 
488 // See the header file for the function documentation
489 jint LLUI_PAINTER_IMPL_stringWidth(jchar *chars, jint offset, jint length, MICROUI_Font *font) {
490  jint ret = 0;
491  if (length > 0) {
492  LOG_DRAW_START(stringWidth);
493  ret = UI_DRAWING_stringWidth(chars + offset, length, font);
494  LOG_DRAW_END(DRAWING_DONE);
495  }
496  return ret;
497 }
498 
499 // See the header file for the function documentation
500 jint LLUI_PAINTER_IMPL_initializeRenderableStringSNIContext(jchar *chars, jint offset, jint length, MICROUI_Font *font,
501  MICROUI_RenderableString *renderableString) {
502  jint ret = 0;
503  if (length > 0) {
504  ret = UI_DRAWING_initializeRenderableStringSNIContext(chars + offset, length, font, renderableString);
505  }
506  return ret;
507 }
508 
509 // See the header file for the function documentation
510 void LLUI_PAINTER_IMPL_drawRenderableString(MICROUI_GraphicsContext *gc, jchar *chars, jint offset, jint length,
511  MICROUI_Font *font, jint width, MICROUI_RenderableString *renderableString,
512  jint x, jint y) {
513  if ((length > 0) && LLUI_DISPLAY_requestDrawing(gc, (SNI_callback)LLUI_PAINTER_IMPL_drawRenderableString)) {
514  LOG_DRAW_START(drawString);
515  DRAWING_Status status =
516  UI_DRAWING_drawRenderableString(gc, chars + offset, length, font, width, renderableString, x, y);
517  LLUI_DISPLAY_setDrawingStatus(status);
518  LOG_DRAW_END(status);
519  }
520 }
521 
522 // --------------------------------------------------------------------------------
523 // EOF
524 // --------------------------------------------------------------------------------