microvg  8.0.3
microvg
LLVG_FONT_impl_freetype.c
Go to the documentation of this file.
1 /*
2  * C
3  *
4  * Copyright 2020-2026 MicroEJ Corp. All rights reserved.
5  * MicroEJ Corp. PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  *
7  * Build: 7E4D1F7C
8  */
9 
17 #include <assert.h>
18 #include "vg_configuration.h"
19 
20 #if defined VG_FEATURE_FONT && \
21  (defined VG_FEATURE_FONT_FREETYPE_VECTOR || defined VG_FEATURE_FONT_FREETYPE_BITMAP) && \
22  (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_VECTOR || VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_BITMAP)
23 
24 // -----------------------------------------------------------------------------
25 // Includes
26 // -----------------------------------------------------------------------------
27 
28 #include <math.h>
29 #include <string.h>
30 #include <aftypes.h>
31 
32 #include <LLVG_impl.h>
33 #include <LLVG_FONT_impl.h>
34 
35 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
36 #include <LLEXT_RES_impl.h>
37 #include <freetype/internal/ftmemory.h>
38 #endif
39 
40 #include "vg_freetype.h"
41 #include "vg_helper.h"
42 #include "vg_outline_box.h"
43 #include "vg_trace.h"
44 #include "ui_util.h"
45 
47 
48 // -----------------------------------------------------------------------------
49 // Macros and Defines
50 // -----------------------------------------------------------------------------
51 
52 /*
53  * @brief Macro to add a FONT event and its type.
54  */
55 #define LOG_MICROVG_FONT_START(fn) LOG_MICROVG_START(LOG_MICROVG_FONT_ID, CONCAT_DEFINES(LOG_MICROVG_FONT_, fn))
56 #define LOG_MICROVG_FONT_END(fn) LOG_MICROVG_END(LOG_MICROVG_FONT_ID, CONCAT_DEFINES(LOG_MICROVG_FONT_, fn))
57 
58 // -----------------------------------------------------------------------------
59 // Types
60 // -----------------------------------------------------------------------------
61 
62 /*
63  * @brief Structure to load a resource by calling SNIX_get_resource()
64  */
65 typedef struct {
66  void *data;
67  uint32_t size;
68 } SNIX_resource;
69 
70 // -----------------------------------------------------------------------------
71 // Extern functions
72 // -----------------------------------------------------------------------------
73 
74 /*
75  * @brief SNIX_get_resource() available since MicroEJ Architecture version 7.13
76  */
77 extern int32_t SNIX_get_resource(jchar *path, SNIX_resource *resource);
78 
79 // -----------------------------------------------------------------------------
80 // Internal function definitions
81 // -----------------------------------------------------------------------------
82 
83 /*
84  * @brief Disposes Freetype font when the associated Java object VectorFont is
85  * garbaged collected.
86  */
87 static void __dispose_registered_font(void *faceHandle);
88 
89 /*
90  * @brief Disposes Freetype font.
91  */
92 static void __dispose_font(void *faceHandle);
93 
94 /*
95  * @brief Opens a font that has been loaded into memory.
96  *
97  * @see FT_New_Memory_Face in freetype.h
98  *
99  * @param[in] face: a handle to a new face object.
100  * @param[in] data: a pointer to the beginning of the font data.
101  * @param[in] length: the size of the memory chunk used by the font data.
102  *
103  * @return FreeType error code.
104  */
105 static FT_Error __load_memory_font(FT_Face *face, void *data, int length);
106 
107 /*
108  * @brief Opens a font that has been compiled with the application.
109  *
110  * @see FT_New_Memory_Face in freetype.h
111  *
112  * @param[in] face: a handle to a new face object.
113  * @param[in] font_name: a path to the font file.
114  *
115  * @return FreeType error code.
116  */
117 static FT_Error __load_internal_font(FT_Face *face, jchar *font_name);
118 
119 /*
120  * @brief Gets the description of the given native resource: a vector font.
121  * @see SNI_getDescriptionFunction
122  */
123 static void __register_font_description(void *resource, char *buffer, uint32_t bufferLength);
124 
125 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
126 
127 /*
128  * @brief Opens a font that has not been compiled with the application.
129  *
130  * @see FT_Open_Face in freetype.h
131  *
132  * @param[in] face: a handle to a new face object.
133  * @param[in] font_name: a path to the font file.
134  *
135  * @return FreeType error code.
136  */
137 static FT_Error __load_external_font(FT_Face *face, jchar *font_name);
138 
139 /*
140  * @brief Reads a chunk from an external resource.
141  *
142  * @see FT_Stream_IoFunc in ftsystem.h
143  *
144  * @param[in] stream: a handle to the source stream.
145  * @param[in] offset: the offset of read in stream.
146  * @param[in] buffer: the address of the read buffer.
147  * @param[in] count: the number of bytes to read from the stream.
148  *
149  * @return the number of bytes effectively read by the stream.
150  */
151 static unsigned long __read_external_resource(FT_Stream stream, unsigned long offset, unsigned char *buffer,
152  unsigned long count);
153 
154 /*
155  * @brief Closes a given input stream.
156  *
157  * @see FT_Stream_IoFunc in ftsystem.h
158  *
159  * @param[in] stream: a handle to the target stream.
160  */
161 static void __close_external_resource(FT_Stream stream);
162 
163 #endif // VG_FEATURE_FONT_EXTERNAL
164 
165 // -----------------------------------------------------------------------------
166 // Global Variables
167 // -----------------------------------------------------------------------------
168 
169 FT_Library library;
170 FT_Renderer renderer;
171 
172 #if defined VG_FEATURE_FONT && defined VG_FEATURE_FONT_FREETYPE_VECTOR && \
173  (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_VECTOR)
174 const char *renderer_name = "microvg";
175 #endif
176 #if defined VG_FEATURE_FONT && defined VG_FEATURE_FONT_FREETYPE_BITMAP && \
177  (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_BITMAP)
178 const char *renderer_name = "smooth";
179 #endif
180 
181 // -----------------------------------------------------------------------------
182 // vg_freetype.h functions
183 // -----------------------------------------------------------------------------
184 
185 // See the header file for the function documentation
186 void VG_FREETYPE_initialize(void) {
187  FT_Error error = FT_Init_FreeType(&library);
188  if (FT_ERR(Ok) == error) {
189  renderer = FT_RENDERER(FT_Get_Module(library, renderer_name));
190  if (0 != renderer) {
191  VG_LOG_INFO("Freetype renderer: %s", FT_MODULE_CLASS(renderer)->module_name);
192  } else {
193  VG_LOG_ERROR("No renderer found with name %s", renderer_name);
194  }
195  } else {
196  VG_LOG_ERROR("Internal freetype error initializing library, ID = %d", error);
197  }
198 }
199 
200 // See the header file for the function documentation
201 bool VG_FREETYPE_string_span(const jchar *text, jint length, jint face_handle, jfloat letter_spacing_font_units,
202  jfloat *left, jfloat *right) {
203  FT_Face face = (FT_Face)face_handle;
204  bool has_drawn_glyph = false;
205  float pen = 0.f;
206  float span_left = 0.f;
207  float span_right = 0.f;
208 
209  // Layout variables
210  FT_UInt glyph_index = 0;
211 
212  int advance_x = 0;
213  int advance_y = 0;
214  int offset_x = 0;
215  int offset_y = 0;
216 
217  // A caller that asks for the left edge alone lets the fold stop once the pen has moved past the
218  // leftmost ink the face declares: while the pen grows, no later glyph can reach further left.
219  // The margin of one EM covers what places a glyph left of its own pen, the kerning and the
220  // positioning offsets, and a face declaring a box tighter than the ink it draws. So the stop
221  // needs the pen to grow, which a letter spacing below zero and a negative advance both break.
222  bool stop_on_left = (NULL == right) && (letter_spacing_font_units >= 0.f);
223  const float unreachable_left = MIN((float)face->bbox.xMin, 0.f) - (float)face->units_per_EM;
224 
225  // Box the current glyph draws, control points excluded.
226  VG_OUTLINE_BOX box = { .x_min = 0.f, .x_max = 0.f, .y_min = 0.f, .y_max = 0.f, .empty = true };
227 
228  VG_HELPER_layout_configure(face_handle, text, length);
229 
230  while (VG_HELPER_layout_load_glyph(&glyph_index, &advance_x, &advance_y, &offset_x, &offset_y)) {
231  // At that point the current glyph has been loaded by Freetype
232  VG_OUTLINE_BOX_compute(&face->glyph->outline, &box);
233 
234  // A space carries a real glyph index and an empty box, so the box is what says whether the
235  // glyph draws. An empty one contributes no edge, at either end.
236  if (!box.empty) {
237  float glyph_left = pen + (float)offset_x + box.x_min;
238  float glyph_right = pen + (float)offset_x + box.x_max;
239 
240  if (!has_drawn_glyph) {
241  span_left = glyph_left;
242  span_right = glyph_right;
243  has_drawn_glyph = true;
244  } else {
245  span_left = MIN(glyph_left, span_left);
246  span_right = MAX(glyph_right, span_right);
247  }
248  }
249 
250  float step = (float)advance_x + letter_spacing_font_units;
251  pen += step;
252 
253  // A step that moves the pen backwards is evidence that this face does it, so the fold stops
254  // trusting the bound and reads the string to its end.
255  if (step < 0.f) {
256  stop_on_left = false;
257  }
258 
259  if (stop_on_left && has_drawn_glyph && ((pen + unreachable_left) >= span_left)) {
260  break;
261  }
262  }
263 
264  // The iteration may have stopped before its end, which leaves the layouter holding it.
266 
267  if (has_drawn_glyph) {
268  *left = span_left;
269  if (NULL != right) {
270  *right = span_right;
271  }
272  }
273 
274  return has_drawn_glyph;
275 }
276 
277 // See the header file for the function documentation
278 jfloat VG_FREETYPE_get_scale(jint face_handle, jfloat size) {
279  FT_Face face = (FT_Face)face_handle;
280  return size / (float)face->units_per_EM;
281 }
282 
283 // See the header file for the function documentation
284 jfloat VG_FREETYPE_string_width(jchar *text, jint length, jint face_handle, jfloat size, jfloat letter_spacing) {
285  float scaled_width = 0.f;
286  FT_Face face = (FT_Face)face_handle;
287 
288  if ((size > 0) && (length > 0)) {
289  float scale = VG_FREETYPE_get_scale(face_handle, size);
290 
291  float left = 0.f;
292  float right = 0.f;
293 
294  if (VG_FREETYPE_string_span(text, length, face_handle, letter_spacing / scale, &left, &right)) {
295  assert(right >= left);
296  scaled_width = scale * (right - left);
297  }
298  }
299 
300  return scaled_width;
301 }
302 
303 // -----------------------------------------------------------------------------
304 // LLVG_FONT_impl.h functions
305 // -----------------------------------------------------------------------------
306 
307 // See the header file for the function documentation
308 jint LLVG_FONT_IMPL_load_font(jchar *font_name, jboolean complex_layout) {
309  LOG_MICROVG_FONT_START(load);
310 
311  FT_Face face = 0;
312  jint ret = LLVG_FONT_UNLOADED;
313 
314  // Check that complex layouter is available for complex text layout
315  if (complex_layout && !LLVG_FONT_IMPL_has_complex_layouter()) {
316  ret = LLVG_FONT_UNLOADED;
317  } else {
318  // try to load an internal resource
319  FT_Error error = __load_internal_font(&face, font_name);
320 
321 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
322  if (FT_ERR(Cannot_Open_Resource) == error) {
323  // try to load an external resource
324  error = __load_external_font(&face, font_name);
325  }
326 #endif // VG_FEATURE_FONT_EXTERNAL
327 
328  if ((FT_ERR(Ok) == error) && (!FT_IS_SCALABLE(face) || (0U == face->units_per_EM))) {
329  // Every text measure and the drawing divide by the EM size, so a face that declares none
330  // is refused here, once, instead of being guarded in each of them.
331  VG_LOG_ERROR("Font not scalable: %s", (const char *)font_name);
332  __dispose_font((void *)face);
333  } else if (FT_ERR(Ok) == error) {
334  // Use Unicode
335  FT_Select_Charmap(face, ft_encoding_unicode);
336  VG_LOG_INFO("Freetype font loaded: %s", (const char *)font_name);
337 
338  int32_t registered = SNI_registerResource((void *)face, (SNI_closeFunction) & __dispose_registered_font,
339  &__register_font_description);
340  assert(SNI_OK == registered);
341 
342 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT && (VG_FEATURE_FONT_COMPLEX_LAYOUT == 1)
343  if (JTRUE == complex_layout) {
344  face->face_flags |= FT_FACE_FLAG_COMPLEX_LAYOUT;
345  }
346 #endif // VG_FEATURE_FONT_COMPLEX_LAYOUT
347 
348  ret = (jint)face;
349  } else if (FT_ERR(Cannot_Open_Resource) != error) {
350  VG_LOG_ERROR("An error occurred during font loading: 0x%x, refer to fterrdef.h", error);
351  } else {
352  VG_LOG_ERROR("Resource not found: %s", (const char *)font_name);
353  }
354  }
355 
356  LOG_MICROVG_FONT_END(load);
357  return ret;
358 }
359 
360 // See the header file for the function documentation
361 jfloat LLVG_FONT_IMPL_string_width(jchar *text, jint faceHandle, jfloat size, jfloat letterSpacing) {
362  LOG_MICROVG_FONT_START(stringWidth);
363  jfloat ret;
364 
365  if (LLVG_FONT_UNLOADED == faceHandle) {
366  ret = (jfloat)LLVG_RESOURCE_CLOSED;
367  } else {
368  int length = (int)SNI_getArrayLength(text);
369  ret = VG_FREETYPE_string_width(text, length, faceHandle, size, letterSpacing);
370  }
371 
372  LOG_MICROVG_FONT_END(stringWidth);
373  return ret;
374 }
375 
376 // See the header file for the function documentation
377 jfloat LLVG_FONT_IMPL_string_height(jchar *text, jint faceHandle, jfloat size) {
378  LOG_MICROVG_FONT_START(stringHeight);
379  jfloat ret;
380 
381  if (LLVG_FONT_UNLOADED == faceHandle) {
382  ret = (jfloat)LLVG_RESOURCE_CLOSED;
383  } else {
384  FT_Face face = (FT_Face)faceHandle;
385  float scaled_height = 0.f;
386 
387  // This fold is the vertical twin of VG_FREETYPE_string_span(), and it stays separate: it
388  // folds boxes where they are loaded rather than at a pen position, so one shared core
389  // would have to carry a horizontal axis this function never advances.
390  if (size > 0) {
391  float scale = VG_FREETYPE_get_scale(faceHandle, size);
392 
393  float drawn_y_top = 0.f;
394  float drawn_y_bottom = 0.f;
395  // Whether a glyph with a non-empty box has been folded in yet: a space carries a
396  // real glyph index, so the glyph index cannot be used to seed the first drawn glyph,
397  // and neither end can start pinned at 0 without biasing a string that draws entirely
398  // on one side of the baseline.
399  bool has_drawn_glyph = false;
400 
401  // Layout variables
402  FT_UInt glyph_index = 0;
403 
404  int advance_x = 0;
405  int advance_y = 0;
406  int offset_x = 0;
407  int offset_y = 0;
408 
409  // Box the current glyph draws, control points excluded.
410  VG_OUTLINE_BOX box = { .x_min = 0.f, .x_max = 0.f, .y_min = 0.f, .y_max = 0.f, .empty = true };
411 
412  int length = (int)SNI_getArrayLength(text);
413  VG_HELPER_layout_configure(faceHandle, text, length);
414 
415  while (VG_HELPER_layout_load_glyph(&glyph_index, &advance_x, &advance_y, &offset_x, &offset_y)) {
416  // At that point the current glyph has been loaded by Freetype
417  VG_OUTLINE_BOX_compute(&face->glyph->outline, &box);
418 
419  // A space has no outline: without this guard its zeroed, empty box would enter
420  // the fold below and drag the bottom of the string to 0.
421  if (!box.empty) {
422  if (!has_drawn_glyph) {
423  drawn_y_bottom = box.y_min;
424  drawn_y_top = box.y_max;
425  has_drawn_glyph = true;
426  } else {
427  drawn_y_bottom = MIN(box.y_min, drawn_y_bottom);
428  drawn_y_top = MAX(box.y_max, drawn_y_top);
429  }
430  }
431  }
432 
433  assert(drawn_y_top >= drawn_y_bottom);
434  scaled_height = scale * (drawn_y_top - drawn_y_bottom);
435  }
436 
437  ret = scaled_height;
438  }
439 
440  LOG_MICROVG_FONT_END(stringHeight);
441  return ret;
442 }
443 
444 // See the header file for the function documentation
445 jfloat LLVG_FONT_IMPL_get_baseline_position(jint faceHandle, jfloat size) {
446  LOG_MICROVG_FONT_START(baseline);
447  jfloat ret;
448 
449  if (LLVG_FONT_UNLOADED == faceHandle) {
450  ret = (jfloat)LLVG_RESOURCE_CLOSED;
451  } else {
452  FT_Face face = (FT_Face)faceHandle;
453  float advance_y = 0.f;
454 
455  if (size > 0) {
456  float scale = VG_FREETYPE_get_scale(faceHandle, size);
457  advance_y = (face->ascender * scale);
458  }
459  ret = advance_y;
460  }
461 
462  LOG_MICROVG_FONT_END(baseline);
463  return ret;
464 }
465 
466 // See the header file for the function documentation
467 jfloat LLVG_FONT_IMPL_get_height(jint faceHandle, jfloat size) {
468  LOG_MICROVG_FONT_START(height);
469  jfloat ret;
470 
471  if (LLVG_FONT_UNLOADED == faceHandle) {
472  ret = (jfloat)LLVG_RESOURCE_CLOSED;
473  } else {
474  FT_Face face = (FT_Face)faceHandle;
475  float scaled_height = 0.f;
476 
477  if (size > 0) {
478  scaled_height = face->height * VG_FREETYPE_get_scale(faceHandle, size);
479  }
480 
481  ret = scaled_height;
482  }
483 
484  LOG_MICROVG_FONT_END(height);
485  return ret;
486 }
487 
488 // See the header file for the function documentation
489 void LLVG_FONT_IMPL_dispose(jint faceHandle) {
490  // unregister the resource since the VEE does not need to call it anymore
491  int32_t unregistered = SNI_unregisterResource((void *)faceHandle, (SNI_closeFunction) & __dispose_registered_font);
492  assert(SNI_OK == unregistered);
493  __dispose_font((void *)faceHandle);
494 }
495 
496 // See the header file for the function documentation
497 bool LLVG_FONT_IMPL_has_complex_layouter(void) {
498 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT && (VG_FEATURE_FONT_COMPLEX_LAYOUT == 1)
499  return true;
500 #else
501  return false;
502 #endif
503 }
504 
505 // -----------------------------------------------------------------------------
506 // Internal functions
507 // -----------------------------------------------------------------------------
508 
509 static void __dispose_font(void *faceHandle) {
510  FT_Face face = (FT_Face)faceHandle;
511 
512 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
513  // FT_Done_Face() frees the stream of a memory font and only closes the stream this CCO allocated
514  // for an external font, so the stream is read here, before it can be freed. Freetype doesn't
515  // recommend to read the flag FT_FACE_FLAG_EXTERNAL_STREAM.
516  FT_Stream stream = face->stream;
517  bool is_own_stream = (&__close_external_resource == stream->close);
518 #endif // VG_FEATURE_FONT_EXTERNAL
519 
520  // The layouter's state holds this face and reads through it for its whole life, so it goes first.
521  VG_HELPER_layout_dispose((int)faceHandle);
522 
523  FT_Done_Face(face);
524 
525 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
526  if (is_own_stream) {
527  ft_mem_free(library->memory, stream);
528  }
529 #endif // VG_FEATURE_FONT_EXTERNAL
530 }
531 
532 /*
533  * Only called when killing a KF feature (automatic SNI resource management): have
534  * to wait the end of GPU before closing the image.
535  */
536 static void __dispose_registered_font(void *faceHandle) {
537  // ensure GPU is not working in our font...
539  // ... and close it
540  __dispose_font(faceHandle);
541 }
542 
543 static FT_Error __load_memory_font(FT_Face *face, void *data, int length) {
544  return FT_New_Memory_Face(library, data, length, 0, face);
545 }
546 
547 static FT_Error __load_internal_font(FT_Face *face, jchar *font_name) {
548  SNIX_resource font_resource;
549  FT_Error error;
550 
551  if (0 == SNIX_get_resource(font_name, &font_resource)) {
552  error = __load_memory_font(face, font_resource.data, font_resource.size);
553  } else {
554  error = FT_ERR(Cannot_Open_Resource);
555  }
556  return error;
557 }
558 
559 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
560 
561 static FT_Error __load_external_font(FT_Face *face, jchar *font_name) {
562  FT_Error error;
563 
564  // try to load an external resource (respect LLEXT_RES_open path naming convention)
565  char const *ext_path = &(((char const *)(font_name))[1]) /* first '/' */;
566  RES_ID resource_id = LLEXT_RES_open(ext_path);
567 
568  if (0 <= resource_id) {
569  int32_t resource_size = LLEXT_RES_available(resource_id);
570 
571  // check if the external resource is byte addressable
572  int32_t base_address = LLEXT_RES_getBaseAddress(resource_id);
573 
574  if (-1 != base_address) {
575  // load the font as "memory" font
576  // cppcheck-suppress [misra-c2012-11.6] base_address is an address
577  error = __load_memory_font(face, (void *)base_address, resource_size);
578 
579  // we can close the resource because we know its address
580  LLEXT_RES_close(resource_id);
581  } else {
582  // load the font as external font
583 
584  FT_Open_Args args;
585  args.flags = FT_OPEN_STREAM;
586  args.driver = NULL;
587  args.stream = (FT_StreamRec *)ft_mem_alloc(library->memory, sizeof(FT_StreamRec), &error);
588 
589  if (FT_ERR(Ok) == error) {
590  args.stream->base = NULL;
591  args.stream->size = resource_size;
592  args.stream->pos = 0;
593  args.stream->descriptor.value = resource_id;
594  // args.stream->pathname = NULL; // not used
595  args.stream->read = &__read_external_resource;
596  args.stream->close = &__close_external_resource;
597 
598  error = FT_Open_Face(library, &args, 0, face);
599  } else {
600  error = FT_ERR(Out_Of_Memory);
601  }
602  }
603  } else {
604  error = FT_ERR(Cannot_Open_Resource);
605  }
606 
607  return error;
608 }
609 
610 static unsigned long __read_external_resource(FT_Stream stream, unsigned long offset, unsigned char *buffer,
611  unsigned long count) {
612  int32_t size = count;
613  RES_ID resource_id = (RES_ID)(stream->descriptor.value);
614  LLEXT_RES_seek(resource_id, offset);
615  LLEXT_RES_read(resource_id, buffer, &size);
616  return size;
617 }
618 
619 static void __close_external_resource(FT_Stream stream) {
620  RES_ID resource_id = (RES_ID)(stream->descriptor.value);
621  LLEXT_RES_close(resource_id);
622 }
623 
624 #endif // VG_FEATURE_FONT_EXTERNAL
625 
626 static void __register_font_description(void *resource, char *buffer, uint32_t bufferLength) {
627  (void)resource;
628  REGISTERDESC("VectorFont", buffer, bufferLength);
629 }
630 
631 // -----------------------------------------------------------------------------
632 // TestResource functions
633 // -----------------------------------------------------------------------------
634 
635 jlong Java_com_microej_microvg_test_TestResource_getSNICloseFunctionForFont(void) {
636  return (jlong) & __dispose_registered_font;
637 }
638 
639 // cppcheck-suppress [misra-c2012-3.2]
640 #endif \
641  // defined VG_FEATURE_FONT && \
642  // (defined VG_FEATURE_FONT_FREETYPE_VECTOR || defined VG_FEATURE_FONT_FREETYPE_BITMAP) && \
643  // (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_VECTOR || VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_BITMAP)
644 
645 // -----------------------------------------------------------------------------
646 // EOF
647 // -----------------------------------------------------------------------------
The box of the curve an outline draws, control points excluded.
MicroEJ MicroVG library low level API: enable some features according to the hardware capacities.
#define VG_LOG_DECLARE_MODULE()
Declares the log module, once at the top of each source file that logs.
MicroEJ MicroVG library low level API: implementation over FreeType.
bool VG_FREETYPE_string_span(const jchar *text, jint length, jint face_handle, jfloat letter_spacing_font_units, jfloat *left, jfloat *right)
Folds the ink of a string and returns its two extreme edges.
void VG_FREETYPE_initialize(void)
Initializes the lowlevel font library.
jfloat VG_FREETYPE_get_scale(jint face_handle, jfloat size)
Computes the scale that converts font units to pixels at the given size.
jfloat VG_FREETYPE_string_width(jchar *text, jint length, jint face_handle, jfloat size, jfloat letter_spacing)
Measures the width of a text for the specified font and size.
MicroEJ MicroVG library low level API: helper to implement library natives methods.
#define REGISTERDESC(desc, buf, buf_len)
Registers the description of a SNI close function.
Definition: vg_helper.h:99
void VG_HELPER_layout_dispose(int faceHandle)
Releases the font layouter's state built from a font face, when that face is about to be freed....
void LLUI_DISPLAY_waitAsynchronousDrawingEnd(void)
Waits until the end of current asynchronous drawing.
Definition: vg_helper.c:157
#define VG_LOG_INFO(fmt,...)
Logs an informative message. The format has no trailing line return.
Definition: vg_helper.h:53
void VG_HELPER_layout_stop(void)
Releases what the layouter still holds for the current iteration. Does nothing when there is nothing ...
#define FT_FACE_FLAG_COMPLEX_LAYOUT
Freetype supplementary flag for complex layout Uses a free bit in freetype face flags to convey the c...
Definition: vg_helper.h:84
void VG_HELPER_layout_configure(int faceHandle, const unsigned short *text, int length)
Configures the font layouter with a font and a text.
#define VG_LOG_ERROR(fmt,...)
Logs an error. The format has no trailing line return.
Definition: vg_helper.h:42
bool VG_HELPER_layout_load_glyph(uint32_t *glyph_idx, int *x_advance, int *y_advance, int *x_offset, int *y_offset)
Loads the next layouted glyph and gets index and positions.
MicroEJ MicroVG library low level API: box of the curve an outline draws.
void VG_OUTLINE_BOX_compute(const FT_Outline *outline, VG_OUTLINE_BOX *box)
Computes the box of the curve the given outline draws, where the box a font declares also bounds the ...