microvg  8.0.0
microvg
vg_helper.c
Go to the documentation of this file.
1 /*
2  * C
3  *
4  * Copyright 2022-2026 MicroEJ Corp. All rights reserved.
5  * MicroEJ Corp. PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */
7 
16 #include "vg_configuration.h"
17 
18 // -----------------------------------------------------------------------------
19 // VG Pack Sanity Check
20 // -----------------------------------------------------------------------------
21 
22 /*
23  * Sanity check between the expected version of the VG Pack used by the VEE Port
24  * and the actual version of this file (MicroVG C Module's file).
25  *
26  * If an error is raised here, it means that a new version of the VG Pack has been
27  * installed in the VEE Port or the MicroVG C Module has been updated without any change
28  * in the VEE Port. In both cases, the versions must be coherent (see the Release
29  * Notes: https://docs.microej.com/en/latest/VEEPortingGuide/vgReleaseNotes.html).
30  */
31 
32 #if (defined(LLVG_MAJOR_VERSION) && (LLVG_MAJOR_VERSION != 1)) || (defined(LLVG_MINOR_VERSION) && \
33  (LLVG_MINOR_VERSION < 8))
34 #error "This C Module is only compatible with VG Pack [1.8.0,2.0.0["
35 #endif
36 
37 // -----------------------------------------------------------------------------
38 // Includes
39 // -----------------------------------------------------------------------------
40 
41 #include <LLVG_MATRIX_impl.h>
42 
43 #include "vg_helper.h"
44 #include "vg_trace.h"
45 #include "vg_drawing.h"
46 #include "bsp_util.h"
47 
48 #if defined VG_FEATURE_PATH
49 #include "vg_path.h"
50 #endif
51 
52 #if defined VG_FEATURE_FONT
53 #include <freetype/internal/ftobjs.h>
54 #include "vg_freetype.h"
55 #endif
56 
57 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT && (VG_FEATURE_FONT_COMPLEX_LAYOUT == 1)
58 #include "hb.h"
59 #include "hb-ft.h"
60 #endif
61 
62 // -----------------------------------------------------------------------------
63 // Defines
64 // -----------------------------------------------------------------------------
65 
66 #define MIN_HIGH_SURROGATE ((unsigned short)0xD800)
67 #define MAX_HIGH_SURROGATE ((unsigned short)0xDBFF)
68 #define MIN_LOW_SURROGATE ((unsigned short)0xDC00)
69 #define MAX_LOW_SURROGATE ((unsigned short)0xDFFF)
70 #define MIN_SUPPLEMENTARY_CODE_POINT 0x010000
71 
72 #define GET_NEXT_CHARACTER(t, l, o) ((o) >= (l) ? (unsigned short)0 : (t)[o])
73 
74 #ifdef VG_FEATURE_FONT_COMPLEX_LAYOUT
75 #define IS_SIMPLE_LAYOUT (!(face->face_flags & FT_FACE_FLAG_COMPLEX_LAYOUT))
76 #else
77 #define IS_SIMPLE_LAYOUT true
78 #endif // VG_FEATURE_FONT_COMPLEX_LAYOUT
79 
80 // -----------------------------------------------------------------------------
81 // Public Globals
82 // -----------------------------------------------------------------------------
83 
84 /*
85  * @brief Identifies the MicroVG group to trace an event.
86  */
87 int32_t LLVG_TRACE_group;
88 
89 // -----------------------------------------------------------------------------
90 // Private Globals
91 // -----------------------------------------------------------------------------
92 
93 static jfloat g_identity_matrix[LLVG_MATRIX_SIZE];
94 
95 #if defined VG_FEATURE_FONT
96 static FT_Face face;
97 
98 // Freetype layout variables
99 static const unsigned short *current_text;
100 static unsigned int current_length;
101 static int current_offset;
102 static FT_UInt previous_glyph_index; // previous glyph index for kerning
103 #endif
104 
105 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT && (VG_FEATURE_FONT_COMPLEX_LAYOUT == 1)
106 // Harfbuzz layout variables
107 static hb_glyph_info_t *glyph_info;
108 static hb_glyph_position_t *glyph_pos;
109 static unsigned int glyph_count;
110 static int current_glyph;
111 static hb_buffer_t *buf;
112 #endif
113 
114 // -----------------------------------------------------------------------------
115 // LLVG_impl.h functions
116 // -----------------------------------------------------------------------------
117 
118 /*
119  * @brief Initializes the MicroVG C Module according.
120  */
121 void LLVG_IMPL_initialize(jint trace_group) {
122  // initializes the tracer
123  LLVG_TRACE_group = trace_group;
124 
125  // configures the matrix used as identity matrix (immutable)
126  LLVG_MATRIX_IMPL_identity(g_identity_matrix);
127 
128  // Configures the drawing engine
129  VG_DRAWING_initialize();
130 
131  // configures the path engine
132 #ifdef VG_FEATURE_PATH
133  VG_PATH_initialize();
134 #endif
135 
136  // configures the font engine
137 #if defined VG_FEATURE_FONT && \
138  (defined VG_FEATURE_FONT_FREETYPE_VECTOR || defined VG_FEATURE_FONT_FREETYPE_BITMAP) && \
139  (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_VECTOR || VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_BITMAP)
140 
141  VG_FREETYPE_initialize();
142 #endif
143 }
144 
145 // --------------------------------------------------------------------------------
146 // UI Pack > 14.5.1 function
147 // --------------------------------------------------------------------------------
148 
149 // See the header file for the function documentation
150 BSP_DECLARE_WEAK_FCNT void LLUI_DISPLAY_waitAsynchronousDrawingEnd(void) {
151  // cannot wait the end of drawing with UI packs [14.4.0-14.5.1]
152 }
153 
154 // -----------------------------------------------------------------------------
155 // vg_helper.h functions
156 // -----------------------------------------------------------------------------
157 
158 // See the header file for the function documentation
159 int VG_HELPER_get_utf(const unsigned short *textCharRam, int length, int *offset) {
160  unsigned short highPart = GET_NEXT_CHARACTER(textCharRam, length, *offset);
161  int ret = 0; // means "error" (see doc)
162 
163  if ((highPart >= MIN_HIGH_SURROGATE) && (highPart <= MAX_HIGH_SURROGATE)) {
164  if (*offset < (length - 1)) {
165  unsigned short lowPart = GET_NEXT_CHARACTER(textCharRam, length, *(offset) + 1);
166 
167  if ((lowPart >= MIN_LOW_SURROGATE) && (lowPart <= MAX_LOW_SURROGATE)) {
168  *offset += 2;
169 
170  ret = 0;
171  ret += ((int)highPart - (int)MIN_HIGH_SURROGATE);
172  ret <<= (int)10;
173  ret += ((int)lowPart - (int)MIN_LOW_SURROGATE);
174  ret += (int)MIN_SUPPLEMENTARY_CODE_POINT;
175  }
176  // else: invalid surrogate pair
177  }
178  // else: missing second part of surrogate pair
179  } else {
180  *offset += 1;
181 
182  // standard character
183  ret = 0x0000FFFF & (int)highPart;
184  }
185 
186  return ret;
187 }
188 
189 #if defined VG_FEATURE_FONT
190 // See the header file for the function documentation
191 void VG_HELPER_layout_configure(int faceHandle, const unsigned short *text, int length) {
192  face = (FT_Face)faceHandle;
193  // For Misra rule 2.7
194  (void)text;
195  (void)length;
196 
197  if (IS_SIMPLE_LAYOUT) {
198  // Freetype variables initialisation
199  current_text = text;
200  current_length = length;
201  current_offset = 0;
202  previous_glyph_index = 0;
203  } else {
204 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT && (VG_FEATURE_FONT_COMPLEX_LAYOUT == 1)
205  static hb_font_t *hb_font;
206  static jint current_faceHandle = 0;
207  // load font in Harfbuzz only when faceHandle changes
208  if (faceHandle != current_faceHandle) {
209  if (0 != current_faceHandle) {
210  hb_font_destroy(hb_font);
211  }
212  // FT_Set_Pixel_Sizes() must be called before hb_ft_font_create() see issue M0092MEJAUI-2643
213  FT_Set_Pixel_Sizes(face, 0, face->units_per_EM); /* set character size */
214  hb_font = hb_ft_font_create(face, NULL);
215  current_faceHandle = faceHandle;
216  }
217 
218  buf = hb_buffer_create();
219  hb_buffer_add_utf16(buf, (const uint16_t *)text, length, 0, -1);
220 
221  hb_buffer_guess_segment_properties(buf);
222 
223  hb_shape(hb_font, buf, NULL, 0);
224 
225  glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count);
226  glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count);
227 
228  current_glyph = 0;
229 #endif // VG_FEATURE_FONT_COMPLEX_LAYOUT
230  }
231 }
232 
233 #endif /* if defined VG_FEATURE_FONT */
234 
235 #if defined VG_FEATURE_FONT
236 // See the header file for the function documentation
237 bool VG_HELPER_layout_load_glyph(uint32_t *glyph_idx, int *x_advance, int *y_advance, int *x_offset, int *y_offset) {
238  // Initiate return value with default values
239  *glyph_idx = 0;
240  *x_advance = 0;
241  *y_advance = 0;
242  *x_offset = 0;
243  *y_offset = 0;
244 
245  bool ret = false;
246 
247  if (IS_SIMPLE_LAYOUT) {
248  // Freetype layout
249  FT_ULong next_char = VG_HELPER_get_utf(current_text, current_length, &current_offset);
250  if (0 != next_char) {
251  FT_UInt glyph_index = FT_Get_Char_Index(face, next_char);
252 
253  int error = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE);
254  if (FT_ERR(Ok) != error) {
255  MEJ_LOG_ERROR_MICROVG("Error while loading glyphid %d: 0x%x, refer to fterrdef.h\n", glyph_index,
256  error);
257  }
258 
259  *x_advance = face->glyph->advance.x;
260 
261  // Compute Kerning
262  if (FT_HAS_KERNING(face) && previous_glyph_index && glyph_index) {
263  FT_Vector delta;
264  FT_Get_Kerning(face, previous_glyph_index, glyph_index, FT_KERNING_UNSCALED, &delta);
265 
266  *x_offset = delta.x;
267  *x_advance += delta.x;
268  }
269 
270  previous_glyph_index = glyph_index;
271 
272  *glyph_idx = glyph_index;
273 
274  ret = true;
275  }
276  } else {
277 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT && (VG_FEATURE_FONT_COMPLEX_LAYOUT == 1)
278  // Harfbuzz layout
279  if (((unsigned int)0) != glyph_count) {
280  *glyph_idx = glyph_info[current_glyph].codepoint;
281  *x_advance = glyph_pos[current_glyph].x_advance / 64;
282  *y_advance = glyph_pos[current_glyph].y_advance / 64;
283  *x_offset = glyph_pos[current_glyph].x_offset / 64;
284  *y_offset = glyph_pos[current_glyph].y_offset / 64;
285 
286  glyph_count--;
287  current_glyph++;
288 
289  // Load glyph
290  int error = FT_Load_Glyph(face, *glyph_idx, FT_LOAD_NO_SCALE);
291  if (FT_ERR(Ok) != error) {
292  MEJ_LOG_ERROR_MICROVG("Error while loading glyphid %d: 0x%x, refer to fterrdef.h\n", *glyph_idx, error);
293  }
294 
295  ret = true;
296  } else {
297  hb_buffer_destroy(buf);
298  ret = false;
299  }
300 #endif // VG_FEATURE_FONT_COMPLEX_LAYOUT
301  }
302 
303  return ret;
304 }
305 
306 #endif /* if defined VG_FEATURE_FONT */
307 
308 // See the header file for the function documentation
309 const jfloat * VG_HELPER_check_matrix(const jfloat *matrix) {
310  return (NULL == matrix) ? g_identity_matrix : matrix;
311 }
312 
313 // See the header file for the function documentation
314 uint32_t VG_HELPER_apply_alpha(uint32_t color, uint32_t alpha) {
315  uint32_t color_alpha = (((color >> 24) & (uint32_t)0xff) * alpha) / (uint32_t)255;
316  return (color & (uint32_t)0xffffff) | (color_alpha << 24);
317 }
318 
319 // See the header file for the function documentation
320 void VG_HELPER_prepare_matrix(jfloat *dest, jfloat x, jfloat y, const jfloat *matrix) {
321  const jfloat *local_matrix = VG_HELPER_check_matrix(matrix);
322 
323  if ((0 != x) || (0 != y)) {
324  // Create translate matrix for initial x,y translation from graphicscontext.
325  LLVG_MATRIX_IMPL_setTranslate(dest, x, y);
326  LLVG_MATRIX_IMPL_concatenate(dest, local_matrix);
327  } else {
328  // use original matrix
329  LLVG_MATRIX_IMPL_copy(dest, local_matrix);
330  }
331 }
332 
333 // -----------------------------------------------------------------------------
334 // EOF
335 // -----------------------------------------------------------------------------
MicroEJ MicroVG library low level API: enable some features according to the hardware capacities.
MicroEJ MicroVG library low level API: implementation over FreeType.
BSP_DECLARE_WEAK_FCNT void LLUI_DISPLAY_waitAsynchronousDrawingEnd(void)
Waits until the end of current asynchronous drawing.
Definition: vg_helper.c:150
int VG_HELPER_get_utf(const unsigned short *textCharRam, int length, int *offset)
Gets the UTF character from a text buffer at the given offset and updates the offset to point to the ...
Definition: vg_helper.c:159
MicroEJ MicroVG library low level API: helper to implement library natives methods.
MicroEJ MicroVG library low level API: implementation of Path.