microvg  5.0.0
microvg
microvg_helper.c
Go to the documentation of this file.
1 /*
2  * C
3  *
4  * Copyright 2022-2023 MicroEJ Corp. All rights reserved.
5  * Use of this source code is governed by a BSD-style license that can be found with this software.
6  */
7 
16 // -----------------------------------------------------------------------------
17 // Includes
18 // -----------------------------------------------------------------------------
19 
20 #include <LLVG_MATRIX_impl.h>
21 
22 #include "microvg_helper.h"
23 #include "microvg_configuration.h"
24 
25 #if defined VG_FEATURE_FONT
26 #include <freetype/internal/ftobjs.h>
27 #endif
28 
29 // -----------------------------------------------------------------------------
30 // Configuration Sanity Check
31 // -----------------------------------------------------------------------------
32 
41 #if !defined MICROVG_CONFIGURATION_VERSION
42  #error "Undefined MICROVG_CONFIGURATION_VERSION, it must be defined in microvg_configuration.h"
43 #endif
44 
45 #if defined MICROVG_CONFIGURATION_VERSION && MICROVG_CONFIGURATION_VERSION != 2
46  #error "Version of the configuration file microvg_configuration.h is not compatible with this implementation."
47 #endif
48 
49 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT
50 #include "hb.h"
51 #include "hb-ft.h"
52 #endif
53 
54 // -----------------------------------------------------------------------------
55 // Defines
56 // -----------------------------------------------------------------------------
57 
58 #define MIN_HIGH_SURROGATE ((unsigned short)0xD800)
59 #define MAX_HIGH_SURROGATE ((unsigned short)0xDBFF)
60 #define MIN_LOW_SURROGATE ((unsigned short)0xDC00)
61 #define MAX_LOW_SURROGATE ((unsigned short)0xDFFF)
62 #define MIN_SUPPLEMENTARY_CODE_POINT 0x010000
63 
64 #define GET_NEXT_CHARACTER(t,l,o) ((o) >= (l) ? (unsigned short)0 : (t)[o])
65 
66 #ifdef VG_FEATURE_FONT_COMPLEX_LAYOUT
67 #define IS_SIMPLE_LAYOUT (!(face->face_flags & FT_FACE_FLAG_COMPLEX_LAYOUT))
68 #else
69 #define IS_SIMPLE_LAYOUT true
70 #endif // VG_FEATURE_FONT_COMPLEX_LAYOUT
71 
72 // -----------------------------------------------------------------------------
73 // Globals
74 // -----------------------------------------------------------------------------
75 
76 static jfloat g_identity_matrix[LLVG_MATRIX_SIZE];
77 
78 #if defined VG_FEATURE_FONT
79 static FT_Face face;
80 
81 // Freetype layout variables
82 static unsigned short *current_text;
83 static unsigned int current_length;
84 static int current_offset;
85 static FT_UInt previous_glyph_index; // previous glyph index for kerning
86 #endif
87 
88 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT
89 // Harfbuzz layout variables
90 static hb_glyph_info_t *glyph_info;
91 static hb_glyph_position_t *glyph_pos;
92 static unsigned int glyph_count;
93 static int current_glyph;
94 static hb_buffer_t *buf;
95 #endif
96 // -----------------------------------------------------------------------------
97 // Public functions
98 // -----------------------------------------------------------------------------
99 
100 // See the header file for the function documentation
101 void MICROVG_HELPER_initialize(void) {
102  LLVG_MATRIX_IMPL_identity(g_identity_matrix);
103 }
104 
105 // See the header file for the function documentation
106 int MICROVG_HELPER_get_utf(unsigned short *textCharRam, int length, int *offset) {
107 
108  unsigned short highPart = GET_NEXT_CHARACTER(textCharRam, length, *offset);
109  int ret = 0; // means "error" (see doc)
110 
111  if ((highPart >= MIN_HIGH_SURROGATE) && (highPart <= MAX_HIGH_SURROGATE)) {
112 
113  if (*offset < (length - 1)) {
114 
115  unsigned short lowPart = GET_NEXT_CHARACTER(textCharRam, length, *(offset) + 1);
116 
117  if ((lowPart >= MIN_LOW_SURROGATE) && (lowPart <= MAX_LOW_SURROGATE)) {
118  *offset += 2;
119 
120  ret = 0;
121  ret += ((int)highPart - (int)MIN_HIGH_SURROGATE);
122  ret <<= (int)10;
123  ret += ((int)lowPart - (int)MIN_LOW_SURROGATE);
124  ret += (int)MIN_SUPPLEMENTARY_CODE_POINT;
125  }
126  // else: invalid surrogate pair
127  }
128  // else: missing second part of surrogate pair
129  }
130  else {
131  *offset += 1;
132 
133  // standard character
134  ret = 0x0000FFFF & (int)highPart;
135  }
136 
137  return ret;
138 }
139 
140 #if defined VG_FEATURE_FONT
141 // See the header file for the function documentation
142 void MICROVG_HELPER_layout_configure(int faceHandle, unsigned short *text, int length){
143  face = (FT_Face) faceHandle;
144  // For Misra rule 2.7
145  (void)text;
146  (void)length;
147 
148  if(IS_SIMPLE_LAYOUT){
149  // Freetype variables initialisation
150  current_text = text;
151  current_length = length;
152  current_offset = 0;
153  previous_glyph_index = 0;
154  }
155  else {
156 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT
157  static hb_font_t *hb_font;
158  static jint current_faceHandle = 0;
159  // load font in Harfbuzz only when faceHandle changes
160  if(faceHandle != current_faceHandle){
161  if(0 != current_faceHandle){
162  hb_font_destroy(hb_font);
163  }
164  // FT_Set_Pixel_Sizes() must be called before hb_ft_font_create() see issue M0092MEJAUI-2643
165  FT_Set_Pixel_Sizes (face, 0, face->units_per_EM); /* set character size */
166  hb_font = hb_ft_font_create(face, NULL);
167  current_faceHandle = faceHandle;
168  }
169 
170  buf = hb_buffer_create();
171  hb_buffer_add_utf16(buf, (const uint16_t *)text, length, 0, -1);
172 
173  hb_buffer_guess_segment_properties(buf);
174 
175  hb_shape(hb_font, buf, NULL, 0);
176 
177  glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count);
178  glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count);
179 
180  current_glyph = 0;
181 #endif // VG_FEATURE_FONT_COMPLEX_LAYOUT
182  }
183 }
184 #endif
185 
186 #if defined VG_FEATURE_FONT
187 // See the header file for the function documentation
188 bool MICROVG_HELPER_layout_load_glyph(int *glyph_idx, int *x_advance, int *y_advance, int *x_offset, int *y_offset){
189  // Initiate return value with default values
190  *glyph_idx = 0;
191  *x_advance = 0;
192  *y_advance = 0;
193  *x_offset = 0;
194  *y_offset = 0;
195 
196  bool ret = false;
197 
198 
199  if(IS_SIMPLE_LAYOUT){
200  // Freetype layout
201  FT_ULong next_char = MICROVG_HELPER_get_utf(current_text, current_length, &current_offset);
202  if(0 != next_char){
203  FT_UInt glyph_index = FT_Get_Char_Index(face, next_char);
204 
205  int error = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE);
206  if(FT_ERR(Ok) != error) {
207  MEJ_LOG_ERROR_MICROVG("Error while loading glyphid %d: 0x%x, refer to fterrdef.h\n",glyph_index, error);
208  }
209 
210  *x_advance = face->glyph->advance.x;
211 
212  // Compute Kerning
213  if (FT_HAS_KERNING(face) && previous_glyph_index && glyph_index){
214  FT_Vector delta;
215  FT_Get_Kerning(face, previous_glyph_index, glyph_index, FT_KERNING_UNSCALED, &delta);
216 
217  *x_offset = delta.x;
218  *x_advance += delta.x;
219  }
220 
221  previous_glyph_index = glyph_index;
222 
223  *glyph_idx = glyph_index;
224 
225  ret = true;
226  }
227  }
228  else {
229 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT
230  // Harfbuzz layout
231  if(((unsigned int) 0) != glyph_count){
232 
233  *glyph_idx = glyph_info[current_glyph].codepoint;
234  *x_advance = glyph_pos[current_glyph].x_advance/64;
235  *y_advance = glyph_pos[current_glyph].y_advance/64;
236  *x_offset = glyph_pos[current_glyph].x_offset/64;
237  *y_offset = glyph_pos[current_glyph].y_offset/64;
238 
239  glyph_count --;
240  current_glyph ++;
241 
242  // Load glyph
243  int error = FT_Load_Glyph(face, *glyph_idx, FT_LOAD_NO_SCALE);
244  if(FT_ERR(Ok) != error) {
245  MEJ_LOG_ERROR_MICROVG("Error while loading glyphid %d: 0x%x, refer to fterrdef.h\n", *glyph_idx, error);
246  }
247 
248  ret = true;
249  } else {
250  hb_buffer_destroy(buf);
251  ret = false;
252  }
253 #endif // VG_FEATURE_FONT_COMPLEX_LAYOUT
254  }
255 
256  return ret;
257 }
258 #endif
259 
260 // See the header file for the function documentation
261 jfloat* MICROVG_HELPER_check_matrix(jfloat* matrix) {
262  return (NULL == matrix) ? g_identity_matrix : matrix;
263 }
264 
265 // See the header file for the function documentation
266 uint32_t MICROVG_HELPER_apply_alpha(uint32_t color, uint32_t alpha) {
267  uint32_t color_alpha = (((color >> 24) & (uint32_t)0xff) * alpha) / (uint32_t)255;
268  return (color & (uint32_t)0xffffff) | (color_alpha << 24);
269 }
270 
271 // -----------------------------------------------------------------------------
272 // EOF
273 // -----------------------------------------------------------------------------
int MICROVG_HELPER_get_utf(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 ...
MicroEJ MicroVG library low level API: helper to implement library natives methods.
MicroEJ MicroVG library low level API: enable some features according to the hardware capacities...
#define MIN_HIGH_SURROGATE