microui  14.4.1
microui
LLUI_PAINTER_impl.c
1 /*
2  * Copyright 2020-2025 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.4.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 // --------------------------------------------------------------------------------
44 // Private functions
45 // --------------------------------------------------------------------------------
46 
47 /*
48  * Checks given bound to fit in bound limits: 0 and max (excluded). Updates size and
49  * origin in consequence
50  */
51 static inline void _check_bound(jint max, jint *bound, jint *size, jint *origin) {
52  if (*bound < 0) {
53  *size += *bound; // decrease size
54  *origin -= *bound; // increase origin
55  *bound = 0;
56  }
57 
58  if ((*bound + *size) > max) {
59  *size = max - *bound; // decrease size
60  }
61 }
62 
63 // --------------------------------------------------------------------------------
64 // LLUI_PAINTER_impl.h functions
65 // --------------------------------------------------------------------------------
66 
67 // See the header file for the function documentation
68 void LLUI_PAINTER_IMPL_writePixel(MICROUI_GraphicsContext *gc, jint x, jint y) {
69  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_writePixel)) {
70  DRAWING_Status status = DRAWING_DONE;
71  UI_LOG_DRAW_START(writePixel, gc, x, y);
72  if (LLUI_DISPLAY_isPixelInClip(gc, x, y)) {
73  LLUI_DISPLAY_configureClip(gc, false /* point is in clip */);
74  status = UI_DRAWING_writePixel(gc, x, y);
75  } else {
76  UI_LOG_START(OutOfClip, UI_LOG_BUFFER(&gc->image));
77  }
78  LLUI_DISPLAY_setDrawingStatus(status);
79  UI_LOG_DRAW_END(writePixel, status);
80  }
81 }
82 
83 // See the header file for the function documentation
84 void LLUI_PAINTER_IMPL_drawLine(MICROUI_GraphicsContext *gc, jint startX, jint startY, jint endX, jint endY) {
85  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawLine)) {
86  UI_LOG_DRAW_START(drawLine, gc, startX, startY, endX, endY);
87  // cannot reduce/clip line: may be endX < startX and / or endY < startY
88  DRAWING_Status status = UI_DRAWING_drawLine(gc, startX, startY, endX, endY);
89  LLUI_DISPLAY_setDrawingStatus(status);
90  UI_LOG_DRAW_END(drawLine, status);
91  }
92 }
93 
94 // See the header file for the function documentation
95 void LLUI_PAINTER_IMPL_drawHorizontalLine(MICROUI_GraphicsContext *gc, jint x, jint y, jint length) {
96  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawHorizontalLine)) {
97  DRAWING_Status status = DRAWING_DONE;
98  UI_LOG_DRAW_START(drawHorizontalLine, gc, x, y, length);
99 
100  if (length > 0) {
101  jint x1 = x;
102  jint x2 = x + length - 1;
103  if (LLUI_DISPLAY_clipHorizontalLine(gc, &x1, &x2, y)) {
104  LLUI_DISPLAY_configureClip(gc, false /* line has been clipped */);
105  UI_LOG_START(DrawnRegion, UI_LOG_BUFFER(&gc->image), true, x1, y, x2 - x1 + 1, 1);
106  status = UI_DRAWING_drawHorizontalLine(gc, x1, x2, y);
107  } else {
108  UI_LOG_START(OutOfClip, UI_LOG_BUFFER(&gc->image));
109  }
110  }
111 
112  LLUI_DISPLAY_setDrawingStatus(status);
113  UI_LOG_DRAW_END(drawHorizontalLine, status);
114  }
115 }
116 
117 // See the header file for the function documentation
118 void LLUI_PAINTER_IMPL_drawVerticalLine(MICROUI_GraphicsContext *gc, jint x, jint y, jint length) {
119  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawVerticalLine)) {
120  DRAWING_Status status = DRAWING_DONE;
121  UI_LOG_DRAW_START(drawVerticalLine, gc, x, y, length);
122 
123  if (length > 0) {
124  jint y1 = y;
125  jint y2 = y + length - 1;
126  if (LLUI_DISPLAY_clipVerticalLine(gc, &y1, &y2, x)) {
127  LLUI_DISPLAY_configureClip(gc, false /* line has been clipped */);
128  UI_LOG_START(DrawnRegion, UI_LOG_BUFFER(&gc->image), true, x, y1, 1, y2 - y1 + 1);
129  status = UI_DRAWING_drawVerticalLine(gc, x, y1, y2);
130  } else {
131  UI_LOG_START(OutOfClip, UI_LOG_BUFFER(&gc->image));
132  }
133  }
134 
135  LLUI_DISPLAY_setDrawingStatus(status);
136  UI_LOG_DRAW_END(drawVerticalLine, status);
137  }
138 }
139 
140 // See the header file for the function documentation
141 void LLUI_PAINTER_IMPL_drawRectangle(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height) {
142  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawRectangle)) {
143  DRAWING_Status status = DRAWING_DONE;
144  UI_LOG_DRAW_START(drawRectangle, gc, x, y, width, height);
145 
146  if ((width > 0) && (height > 0)) {
147  jint x1 = x;
148  jint x2 = x + width - 1;
149  jint y1 = y;
150  jint y2 = y + height - 1;
151 
152  // cannot reduce rectangle; can only check if it is fully in clip
153  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRectangleInClip(gc, x1, y1, x2, y2));
154  status = UI_DRAWING_drawRectangle(gc, x1, y1, x2, y2);
155  }
156 
157  LLUI_DISPLAY_setDrawingStatus(status);
158  UI_LOG_DRAW_END(drawRectangle, status);
159  }
160 }
161 
162 // See the header file for the function documentation
163 void LLUI_PAINTER_IMPL_fillRectangle(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height) {
164  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillRectangle)) {
165  DRAWING_Status status = DRAWING_DONE;
166  UI_LOG_DRAW_START(fillRectangle, gc, x, y, width, height);
167 
168  if ((width > 0) && (height > 0)) {
169  jint x1 = x;
170  jint x2 = x + width - 1;
171  jint y1 = y;
172  jint y2 = y + height - 1;
173 
174  if (LLUI_DISPLAY_clipRectangle(gc, &x1, &y1, &x2, &y2)) {
175  LLUI_DISPLAY_configureClip(gc, false /* rectangle has been clipped */);
176  UI_LOG_START(DrawnRegion, UI_LOG_BUFFER(&gc->image), true, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
177  status = UI_DRAWING_fillRectangle(gc, x1, y1, x2, y2);
178  } else {
179  UI_LOG_START(OutOfClip, UI_LOG_BUFFER(&gc->image));
180  }
181  }
182  LLUI_DISPLAY_setDrawingStatus(status);
183  UI_LOG_DRAW_END(fillRectangle, status);
184  }
185 }
186 
187 // See the header file for the function documentation
188 void LLUI_PAINTER_IMPL_drawRoundedRectangle(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height,
189  jint cornerEllipseWidth, jint cornerEllipseHeight) {
190  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawRoundedRectangle)) {
191  DRAWING_Status status = DRAWING_DONE;
192  UI_LOG_DRAW_START(drawRoundedRectangle, gc, x, y, width, height, cornerEllipseWidth, cornerEllipseHeight);
193 
194  // tests on size and clip are performed after suspend to prevent to perform it several times
195  if ((width > 0) && (height > 0)) {
196  // cannot reduce rectangle; can only check if it is fully in clip
197  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
198  status = UI_DRAWING_drawRoundedRectangle(gc, x, y, width, height, cornerEllipseWidth, cornerEllipseHeight);
199  }
200  LLUI_DISPLAY_setDrawingStatus(status);
201  UI_LOG_DRAW_END(drawRoundedRectangle, status);
202  }
203 }
204 
205 // See the header file for the function documentation
206 void LLUI_PAINTER_IMPL_fillRoundedRectangle(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height,
207  jint cornerEllipseWidth, jint cornerEllipseHeight) {
208  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillRoundedRectangle)) {
209  DRAWING_Status status = DRAWING_DONE;
210  UI_LOG_DRAW_START(fillRoundedRectangle, gc, x, y, width, height, cornerEllipseWidth, cornerEllipseHeight);
211 
212  // tests on size and clip are performed after suspend to prevent to perform it several times
213  if ((width > 0) && (height > 0)) {
214  jint x1 = x;
215  jint x2 = x + width - 1;
216  jint y1 = y;
217  jint y2 = y + height - 1;
218 
219  if (LLUI_DISPLAY_clipRectangle(gc, &x1, &y1, &x2, &y2)) {
220  // drawing fully or partially fits the clip
221  // cannot reduce rectangle; can only check if it is fully in clip
222  bool disable_clip = LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height);
223  LLUI_DISPLAY_configureClip(gc, !disable_clip);
224  UI_LOG_START(DrawnRegion, UI_LOG_BUFFER(&gc->image), disable_clip, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
225  status = UI_DRAWING_fillRoundedRectangle(gc, x, y, width, height, cornerEllipseWidth, cornerEllipseHeight);
226  }
227  else {
228  UI_LOG_START(OutOfClip, UI_LOG_BUFFER(&gc->image));
229  }
230  }
231  LLUI_DISPLAY_setDrawingStatus(status);
232  UI_LOG_DRAW_END(fillRoundedRectangle, status);
233  }
234 }
235 
236 // See the header file for the function documentation
237 void LLUI_PAINTER_IMPL_drawCircleArc(MICROUI_GraphicsContext *gc, jint x, jint y, jint diameter, jfloat startAngle,
238  jfloat arcAngle) {
239  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawCircleArc)) {
240  DRAWING_Status status = DRAWING_DONE;
241  UI_LOG_DRAW_START(drawCircleArc, gc, x, y, diameter, (uint32_t)startAngle, (uint32_t)arcAngle);
242 
243  // tests on size and clip are performed after suspend to prevent to perform it several times
244  if ((diameter > 0) && ((int32_t)arcAngle != 0)) {
245  // cannot reduce rectangle; can only check if it is fully in clip
246  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, diameter, diameter));
247  status = UI_DRAWING_drawCircleArc(gc, x, y, diameter, startAngle, arcAngle);
248  }
249  LLUI_DISPLAY_setDrawingStatus(status);
250  UI_LOG_DRAW_END(drawCircleArc, status);
251  }
252 }
253 
254 // See the header file for the function documentation
255 void LLUI_PAINTER_IMPL_drawEllipseArc(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height,
256  jfloat startAngle, jfloat arcAngle) {
257  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawEllipseArc)) {
258  DRAWING_Status status = DRAWING_DONE;
259  UI_LOG_DRAW_START(drawEllipseArc, gc, x, y, width, height, (uint32_t)startAngle, (uint32_t)arcAngle);
260 
261  // tests on size and clip are performed after suspend to prevent to perform it several times
262  if ((width > 0) && (height > 0) && ((int32_t)arcAngle != 0)) {
263  // cannot reduce rectangle; can only check if it is fully in clip
264  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
265  status = UI_DRAWING_drawEllipseArc(gc, x, y, width, height, startAngle, arcAngle);
266  }
267  LLUI_DISPLAY_setDrawingStatus(status);
268  UI_LOG_DRAW_END(drawEllipseArc, status);
269  }
270 }
271 
272 // See the header file for the function documentation
273 void LLUI_PAINTER_IMPL_fillCircleArc(MICROUI_GraphicsContext *gc, jint x, jint y, jint diameter, jfloat startAngle,
274  jfloat arcAngle) {
275  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillCircleArc)) {
276  DRAWING_Status status = DRAWING_DONE;
277  UI_LOG_DRAW_START(fillCircleArc, gc, x, y, diameter, (uint32_t)startAngle, (uint32_t)arcAngle);
278 
279  // tests on size and clip are performed after suspend to prevent to perform it several times
280  if ((diameter > 0) && ((int32_t)arcAngle != 0)) {
281  // cannot reduce rectangle; can only check if it is fully in clip
282  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, diameter, diameter));
283  status = UI_DRAWING_fillCircleArc(gc, x, y, diameter, startAngle, arcAngle);
284  }
285  LLUI_DISPLAY_setDrawingStatus(status);
286  UI_LOG_DRAW_END(fillCircleArc, status);
287  }
288 }
289 
290 // See the header file for the function documentation
291 void LLUI_PAINTER_IMPL_fillEllipseArc(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height,
292  jfloat startAngle, jfloat arcAngle) {
293  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillEllipseArc)) {
294  DRAWING_Status status = DRAWING_DONE;
295  UI_LOG_DRAW_START(fillEllipseArc, gc, x, y, width, height, (uint32_t)startAngle, (uint32_t)arcAngle);
296 
297  // tests on size and clip are performed after suspend to prevent to perform it several times
298  if ((width > 0) && (height > 0) && ((int32_t)arcAngle != 0)) {
299  // cannot reduce rectangle; can only check if it is fully in clip
300  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
301  status = UI_DRAWING_fillEllipseArc(gc, x, y, width, height, startAngle, arcAngle);
302  }
303  LLUI_DISPLAY_setDrawingStatus(status);
304  UI_LOG_DRAW_END(fillEllipseArc, status);
305  }
306 }
307 
308 // See the header file for the function documentation
309 void LLUI_PAINTER_IMPL_drawEllipse(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height) {
310  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawEllipse)) {
311  DRAWING_Status status = DRAWING_DONE;
312  UI_LOG_DRAW_START(drawEllipse, gc, x, y, width, height);
313 
314  // tests on size and clip are performed after suspend to prevent to perform it several times
315  if ((width > 0) && (height > 0)) {
316  // cannot reduce rectangle; can only check if it is fully in clip
317  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
318  status = UI_DRAWING_drawEllipse(gc, x, y, width, height);
319  }
320  LLUI_DISPLAY_setDrawingStatus(status);
321  UI_LOG_DRAW_END(drawEllipse, status);
322  }
323 }
324 
325 // See the header file for the function documentation
326 void LLUI_PAINTER_IMPL_fillEllipse(MICROUI_GraphicsContext *gc, jint x, jint y, jint width, jint height) {
327  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillEllipse)) {
328  DRAWING_Status status = DRAWING_DONE;
329  UI_LOG_DRAW_START(fillEllipse, gc, x, y, width, height);
330 
331  // tests on size and clip are performed after suspend to prevent to perform it several times
332  if ((width > 0) && (height > 0)) {
333  // cannot reduce rectangle; can only check if it is fully in clip
334  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, width, height));
335  status = UI_DRAWING_fillEllipse(gc, x, y, width, height);
336  }
337  LLUI_DISPLAY_setDrawingStatus(status);
338  UI_LOG_DRAW_END(fillEllipse, status);
339  }
340 }
341 
342 // See the header file for the function documentation
343 void LLUI_PAINTER_IMPL_drawCircle(MICROUI_GraphicsContext *gc, jint x, jint y, jint diameter) {
344  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawCircle)) {
345  DRAWING_Status status = DRAWING_DONE;
346  UI_LOG_DRAW_START(drawCircle, gc, x, y, diameter);
347 
348  // tests on size and clip are performed after suspend to prevent to perform it several times
349  if (diameter > 0) {
350  // cannot reduce rectangle; can only check if it is fully in clip
351  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, diameter, diameter));
352  status = UI_DRAWING_drawCircle(gc, x, y, diameter);
353  }
354  LLUI_DISPLAY_setDrawingStatus(status);
355  UI_LOG_DRAW_END(drawCircle, status);
356  }
357 }
358 
359 // See the header file for the function documentation
360 void LLUI_PAINTER_IMPL_fillCircle(MICROUI_GraphicsContext *gc, jint x, jint y, jint diameter) {
361  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_fillCircle)) {
362  DRAWING_Status status = DRAWING_DONE;
363  UI_LOG_DRAW_START(fillCircle, gc, x, y, diameter);
364 
365  // tests on size and clip are performed after suspend to prevent to perform it several times
366  if (diameter > 0) {
367  // cannot reduce rectangle; can only check if it is fully in clip
368  LLUI_DISPLAY_configureClip(gc, !LLUI_DISPLAY_isRegionInClip(gc, x, y, diameter, diameter));
369  status = UI_DRAWING_fillCircle(gc, x, y, diameter);
370  }
371  LLUI_DISPLAY_setDrawingStatus(status);
372  UI_LOG_DRAW_END(fillCircle, status);
373  }
374 }
375 
376 // See the header file for the function documentation
377 void LLUI_PAINTER_IMPL_drawImage(MICROUI_GraphicsContext *gc, MICROUI_Image *img, jint regionX, jint regionY,
378  jint width, jint height, jint x, jint y, jint alpha) {
379  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback) & LLUI_PAINTER_IMPL_drawImage)) {
380  DRAWING_Status status = DRAWING_DONE;
381  UI_LOG_DRAW_START(drawImage, gc, UI_LOG_BUFFER(img), regionX, regionY, width, height, x, y, alpha);
382 
383  // tests on parameters and clip are performed after suspend to prevent to perform it several times
384  if (!LLUI_DISPLAY_isImageClosed(img) && (alpha > 0)) {
385  // sanity check on opacity
386  jint l_alpha = (alpha > 255) ? 255 : alpha;
387 
388  // compute inside image bounds
389  _check_bound(img->width, &regionX, &width, &x);
390  _check_bound(img->height, &regionY, &height, &y);
391 
392  // compute inside graphics context bounds
393  _check_bound(gc->image.width, &x, &width, &regionX);
394  _check_bound(gc->image.height, &y, &height, &regionY);
395 
396  if ((width > 0) && (height > 0)) {
397 
398  if (LLUI_DISPLAY_clipRegion(gc, &regionX, &regionY, &width, &height, &x, &y)) {
399  LLUI_DISPLAY_configureClip(gc, false /* region has been clipped */);
400  UI_LOG_START(DrawnRegion, UI_LOG_BUFFER(&gc->image), true, x, y, width, height);
401 
402  if (gc->image.format == img->format) {
403  // source & destination have got the same pixels memory representation
404 
405  MICROUI_Image *image = LLUI_DISPLAY_getSourceImage(img);
406 
407  if ((0xff /* fully opaque */ == l_alpha) && !LLUI_DISPLAY_isTransparent(img)) {
408  // copy source on destination without applying an opacity (beware about the overlapping)
409  status = UI_DRAWING_copyImage(gc, image, regionX, regionY, width, height, x, y);
410  } else if (LLUI_DISPLAY_getBufferAddress(img) == LLUI_DISPLAY_getBufferAddress(&gc->image)) {
411  // blend source on itself applying an opacity (beware about the overlapping)
412  status = UI_DRAWING_drawRegion(gc, regionX, regionY, width, height, x, y, l_alpha);
413  } else {
414  // blend source on destination applying an opacity
415  status = UI_DRAWING_drawImage(gc, image, regionX, regionY, width, height, x, y, l_alpha);
416  }
417  } else {
418  // draw source on destination applying an opacity
419  status = UI_DRAWING_drawImage(gc, img, regionX, regionY, width, height, x, y, l_alpha);
420  }
421  } else {
422  UI_LOG_START(OutOfClip, UI_LOG_BUFFER(&gc->image));
423  }
424  }
425  // else: nothing to do
426  }
427  // else: nothing to do
428 
429  // requestDrawing() has been called and accepted: notify the end of empty drawing
430  LLUI_DISPLAY_setDrawingStatus(status);
431  UI_LOG_DRAW_END(drawImage, status);
432  }
433 }
434 
435 // See the header file for the function documentation
436 void LLUI_PAINTER_IMPL_drawString(MICROUI_GraphicsContext *gc, jchar *chars, jint offset, jint length,
437  MICROUI_Font *font, jint x, jint y) {
438  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback)LLUI_PAINTER_IMPL_drawString)) {
439  DRAWING_Status status = DRAWING_DONE;
440  UI_LOG_DRAW_START(drawString, gc, length, x, y);
441  if (length > 0) {
442  status = UI_DRAWING_drawString(gc, chars + offset, length, font, x, y);
443  }
444  LLUI_DISPLAY_setDrawingStatus(status);
445  UI_LOG_DRAW_END(drawString, status);
446  }
447 }
448 
449 // See the header file for the function documentation
450 jint LLUI_PAINTER_IMPL_stringWidth(jchar *chars, jint offset, jint length, MICROUI_Font *font) {
451  UI_LOG_START(stringWidth, length);
452  return length <= 0 ? 0 : UI_DRAWING_stringWidth(chars + offset, length, font);
453 }
454 
455 // See the header file for the function documentation
456 jint LLUI_PAINTER_IMPL_initializeRenderableStringSNIContext(jchar *chars, jint offset, jint length, MICROUI_Font *font,
457  MICROUI_RenderableString *renderableString) {
458  jint ret = 0;
459  if (length > 0) {
460  ret = UI_DRAWING_initializeRenderableStringSNIContext(chars + offset, length, font, renderableString);
461  }
462  return ret;
463 }
464 
465 // See the header file for the function documentation
466 void LLUI_PAINTER_IMPL_drawRenderableString(MICROUI_GraphicsContext *gc, jchar *chars, jint offset, jint length,
467  MICROUI_Font *font, jint width, MICROUI_RenderableString *renderableString,
468  jint x, jint y) {
469  if (LLUI_DISPLAY_requestDrawing(gc, (SNI_callback)LLUI_PAINTER_IMPL_drawRenderableString)) {
470  DRAWING_Status status = DRAWING_DONE;
471  UI_LOG_DRAW_START(drawRenderableString, gc, length, x, y);
472  if (length > 0) {
473  status = UI_DRAWING_drawRenderableString(gc, chars + offset, length, font, width, renderableString, x, y);
474  }
475  LLUI_DISPLAY_setDrawingStatus(status);
476  UI_LOG_DRAW_END(drawRenderableString, status);
477  }
478 }
479 
480 // --------------------------------------------------------------------------------
481 // EOF
482 // --------------------------------------------------------------------------------