17 #if defined VG_FEATURE_FONT && \
18 (defined VG_FEATURE_FONT_FREETYPE_VECTOR || defined VG_FEATURE_FONT_FREETYPE_BITMAP) && \
19 (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_VECTOR || VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_BITMAP)
29 #include <LLVG_impl.h>
30 #include <LLVG_FONT_impl.h>
32 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
33 #include <LLEXT_RES_impl.h>
34 #include <freetype/internal/ftmemory.h>
49 #define GET_SCALE(s, f) ((s) / (f)->units_per_EM)
54 #define LOG_MICROVG_FONT_START(fn) LOG_MICROVG_START(LOG_MICROVG_FONT_ID, CONCAT_DEFINES(LOG_MICROVG_FONT_, fn))
55 #define LOG_MICROVG_FONT_END(fn) LOG_MICROVG_END(LOG_MICROVG_FONT_ID, CONCAT_DEFINES(LOG_MICROVG_FONT_, fn))
76 extern int32_t SNIX_get_resource(jchar *path, SNIX_resource *resource);
86 static void __dispose_registered_font(
void *faceHandle);
91 static void __dispose_font(
void *faceHandle);
104 static FT_Error __load_memory_font(FT_Face *face,
void *data,
int length);
116 static FT_Error __load_internal_font(FT_Face *face, jchar *font_name);
122 static void __register_font_description(
void *resource,
char *buffer, uint32_t bufferLength);
124 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
136 static FT_Error __load_external_font(FT_Face *face, jchar *font_name);
150 static unsigned long __read_external_resource(FT_Stream stream,
unsigned long offset,
unsigned char *buffer,
151 unsigned long count);
160 static void __close_external_resource(FT_Stream stream);
169 FT_Renderer renderer;
171 #if defined VG_FEATURE_FONT && defined VG_FEATURE_FONT_FREETYPE_VECTOR && \
172 (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_VECTOR)
173 const char *renderer_name =
"microvg";
175 #if defined VG_FEATURE_FONT && defined VG_FEATURE_FONT_FREETYPE_BITMAP && \
176 (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_BITMAP)
177 const char *renderer_name =
"smooth";
185 void VG_FREETYPE_initialize(
void) {
186 FT_Error error = FT_Init_FreeType(&library);
187 if (FT_ERR(Ok) == error) {
188 renderer = FT_RENDERER(FT_Get_Module(library, renderer_name));
190 MEJ_LOG_INFO_MICROVG(
"Freetype renderer: %s\n", FT_MODULE_CLASS(renderer)->module_name);
192 MEJ_LOG_ERROR_MICROVG(
"No renderer found with name %s\n", renderer_name);
195 MEJ_LOG_ERROR_MICROVG(
"Internal freetype error initializing library, ID = %d\n", error);
200 jfloat VG_FREETYPE_string_width(jchar *text, jint length, jint face_handle, jfloat size, jfloat letter_spacing) {
201 float scaled_width = 0.f;
204 FT_Face face = (FT_Face)face_handle;
205 float scale = GET_SCALE(size, face);
208 long unscaled_width = 0;
212 FT_UInt previous_glyph_index = 0;
215 int previous_advance_x = 0;
216 int previous_offset_x = 0;
221 VG_HELPER_layout_configure(face_handle, text, length);
223 while (VG_HELPER_layout_load_glyph(&glyph_index, &advance_x, &advance_y, &offset_x, &offset_y)) {
225 if (0 == previous_glyph_index) {
227 if (0 != face->glyph->metrics.width) {
228 unscaled_width -= face->glyph->metrics.horiBearingX;
230 unscaled_width -= face->glyph->advance.x;
234 unscaled_width += advance_x;
235 previous_glyph_index = glyph_index;
239 previous_advance_x = advance_x;
240 previous_offset_x = offset_x;
244 if (0 != face->glyph->metrics.width) {
245 unscaled_width -= previous_advance_x;
246 unscaled_width += face->glyph->metrics.horiBearingX;
247 unscaled_width += face->glyph->metrics.width;
248 unscaled_width += previous_offset_x;
250 if (0 != unscaled_width) {
251 unscaled_width -= previous_advance_x;
254 scaled_width = ((scale * (float)unscaled_width) + (((float)nb_chars - 1) * letter_spacing));
265 jint LLVG_FONT_IMPL_load_font(jchar *font_name, jboolean complex_layout) {
266 LOG_MICROVG_FONT_START(load);
269 jint ret = LLVG_FONT_UNLOADED;
272 if (complex_layout && !LLVG_FONT_IMPL_has_complex_layouter()) {
273 ret = LLVG_FONT_UNLOADED;
276 FT_Error error = __load_internal_font(&face, font_name);
278 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
279 if (FT_ERR(Cannot_Open_Resource) == error) {
281 error = __load_external_font(&face, font_name);
285 if (FT_ERR(Ok) == error) {
287 FT_Select_Charmap(face, ft_encoding_unicode);
288 MEJ_LOG_INFO_MICROVG(
"Freetype font loaded: %s\n", (
const char *)font_name);
290 SNI_registerResource((
void *)face, (SNI_closeFunction) & __dispose_registered_font,
291 &__register_font_description);
293 #if defined VG_FEATURE_FONT_COMPLEX_LAYOUT && (VG_FEATURE_FONT_COMPLEX_LAYOUT == 1)
294 if (JTRUE == complex_layout) {
300 }
else if (FT_ERR(Cannot_Open_Resource) != error) {
301 MEJ_LOG_ERROR_MICROVG(
"An error occurred during font loading: 0x%x, refer to fterrdef.h\n", error);
303 MEJ_LOG_ERROR_MICROVG(
"Resource not found: %s\n", (
const char *)font_name);
307 LOG_MICROVG_FONT_END(load);
312 jfloat LLVG_FONT_IMPL_string_width(jchar *text, jint faceHandle, jfloat size, jfloat letterSpacing) {
313 LOG_MICROVG_FONT_START(stringWidth);
316 if (LLVG_FONT_UNLOADED == faceHandle) {
317 ret = (jfloat)LLVG_RESOURCE_CLOSED;
319 int length = (int)SNI_getArrayLength(text);
320 ret = VG_FREETYPE_string_width(text, length, faceHandle, size, letterSpacing);
323 LOG_MICROVG_FONT_END(stringWidth);
328 jfloat LLVG_FONT_IMPL_string_height(jchar *text, jint faceHandle, jfloat size) {
329 LOG_MICROVG_FONT_START(stringHeight);
332 if (LLVG_FONT_UNLOADED == faceHandle) {
333 ret = (jfloat)LLVG_RESOURCE_CLOSED;
335 FT_Face face = (FT_Face)faceHandle;
336 float scaled_height = 0.f;
339 float scale = GET_SCALE(size, face);
341 FT_Pos horiBearingYTop = 0;
342 FT_Pos horiBearingYBottom = 0;
346 FT_UInt previous_glyph_index = 0;
353 int length = (int)SNI_getArrayLength(text);
354 VG_HELPER_layout_configure(faceHandle, text, length);
356 while (VG_HELPER_layout_load_glyph(&glyph_index, &advance_x, &advance_y, &offset_x, &offset_y)) {
359 FT_Pos yBottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
360 horiBearingYBottom = (0 == previous_glyph_index) ? yBottom : MIN(yBottom, horiBearingYBottom);
361 horiBearingYTop = MAX(face->glyph->metrics.horiBearingY, horiBearingYTop);
363 previous_glyph_index = glyph_index;
366 scaled_height = scale * (float)(horiBearingYTop - horiBearingYBottom);
372 LOG_MICROVG_FONT_END(stringHeight);
377 jfloat LLVG_FONT_IMPL_get_baseline_position(jint faceHandle, jfloat size) {
378 LOG_MICROVG_FONT_START(baseline);
381 if (LLVG_FONT_UNLOADED == faceHandle) {
382 ret = (jfloat)LLVG_RESOURCE_CLOSED;
384 FT_Face face = (FT_Face)faceHandle;
385 float advance_y = 0.f;
388 float scale = GET_SCALE(size, face);
389 advance_y = (face->ascender * scale);
394 LOG_MICROVG_FONT_END(baseline);
399 jfloat LLVG_FONT_IMPL_get_height(jint faceHandle, jfloat size) {
400 LOG_MICROVG_FONT_START(height);
403 if (LLVG_FONT_UNLOADED == faceHandle) {
404 ret = (jfloat)LLVG_RESOURCE_CLOSED;
406 FT_Face face = (FT_Face)faceHandle;
407 float scale = GET_SCALE(size, face);
408 ret = face->height * scale;
411 LOG_MICROVG_FONT_END(height);
416 void LLVG_FONT_IMPL_dispose(jint faceHandle) {
418 SNI_unregisterResource((
void *)faceHandle, (SNI_closeFunction) & __dispose_registered_font);
419 __dispose_font((
void *)faceHandle);
423 bool LLVG_FONT_IMPL_has_complex_layouter(
void) {
424 #ifdef VG_FEATURE_FONT_COMPLEX_LAYOUT
435 static void __dispose_font(
void *faceHandle) {
436 FT_Face face = (FT_Face)faceHandle;
438 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
441 FT_Stream stream = face->stream;
446 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
449 if (&__close_external_resource == stream->close) {
450 ft_mem_free(library->memory, stream);
459 static void __dispose_registered_font(
void *faceHandle) {
463 __dispose_font(faceHandle);
466 static FT_Error __load_memory_font(FT_Face *face,
void *data,
int length) {
467 return FT_New_Memory_Face(library, data, length, 0, face);
470 static FT_Error __load_internal_font(FT_Face *face, jchar *font_name) {
471 SNIX_resource font_resource;
474 if (0 == SNIX_get_resource(font_name, &font_resource)) {
475 error = __load_memory_font(face, font_resource.data, font_resource.size);
477 error = FT_ERR(Cannot_Open_Resource);
482 #if defined VG_FEATURE_FONT_EXTERNAL && (VG_FEATURE_FONT_EXTERNAL == 1)
484 static FT_Error __load_external_font(FT_Face *face, jchar *font_name) {
488 char const *ext_path = &(((
char const *)(font_name))[1]) ;
489 RES_ID resource_id = LLEXT_RES_open(ext_path);
491 if (0 <= resource_id) {
492 int32_t resource_size = LLEXT_RES_available(resource_id);
495 int32_t base_address = LLEXT_RES_getBaseAddress(resource_id);
497 if (-1 != base_address) {
500 error = __load_memory_font(face, (
void *)base_address, resource_size);
503 LLEXT_RES_close(resource_id);
508 args.flags = FT_OPEN_STREAM;
510 args.stream = (FT_StreamRec *)ft_mem_alloc(library->memory,
sizeof(FT_StreamRec), &error);
512 if (FT_ERR(Ok) == error) {
513 args.stream->base = NULL;
514 args.stream->size = resource_size;
515 args.stream->pos = 0;
516 args.stream->descriptor.value = resource_id;
518 args.stream->read = &__read_external_resource;
519 args.stream->close = &__close_external_resource;
521 error = FT_Open_Face(library, &args, 0, face);
523 error = FT_ERR(Out_Of_Memory);
527 error = FT_ERR(Cannot_Open_Resource);
533 static unsigned long __read_external_resource(FT_Stream stream,
unsigned long offset,
unsigned char *buffer,
534 unsigned long count) {
535 int32_t size = count;
536 RES_ID resource_id = (RES_ID)(stream->descriptor.value);
537 LLEXT_RES_seek(resource_id, offset);
538 LLEXT_RES_read(resource_id, buffer, &size);
542 static void __close_external_resource(FT_Stream stream) {
543 RES_ID resource_id = (RES_ID)(stream->descriptor.value);
544 LLEXT_RES_close(resource_id);
549 static void __register_font_description(
void *resource,
char *buffer, uint32_t bufferLength) {
558 jlong Java_com_microej_microvg_test_TestResource_getSNICloseFunctionForFont(
void) {
559 return (jlong) & __dispose_registered_font;
MicroEJ MicroVG library low level API: enable some features according to the hardware capacities.
MicroEJ MicroVG library low level API: implementation over FreeType.
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.
void LLUI_DISPLAY_waitAsynchronousDrawingEnd(void)
Waits until the end of current asynchronous drawing.
#define FT_FACE_FLAG_COMPLEX_LAYOUT
Freetype supplementary flag for complex layout Uses a free bit in freetype face flags to convey the c...