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