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)
33 #include <LLEXT_RES_impl.h>
34 #include <freetype/internal/ftmemory.h>
39 #include "microvg_trace.h"
49 #define GET_SCALE(s,f) ((s) / (f)->units_per_EM)
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))
77 extern int32_t SNIX_get_resource(jchar* path, SNIX_resource* resource);
87 static void _dispose_registered_font(
void* faceHandle);
100 static FT_Error __load_memory_font(FT_Face* face,
void* data,
int length);
112 static FT_Error __load_internal_font(FT_Face* face, jchar* font_name);
118 static void __register_font_description(
void* resource,
char* buffer, uint32_t bufferLength);
120 #if defined (VG_FEATURE_FONT_EXTERNAL)
132 static FT_Error __load_external_font(FT_Face* face, jchar* font_name);
146 static unsigned long __read_external_resource(FT_Stream stream,
unsigned long offset,
unsigned char* buffer,
unsigned long count);
155 static void __close_external_resource(FT_Stream stream);
157 #endif // VG_FEATURE_FONT_EXTERNAL
164 FT_Renderer renderer;
166 #if defined VG_FEATURE_FONT && defined VG_FEATURE_FONT_FREETYPE_VECTOR && (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_VECTOR)
167 const char* renderer_name =
"vglite_renderer";
169 #if defined VG_FEATURE_FONT && defined VG_FEATURE_FONT_FREETYPE_BITMAP && (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_BITMAP)
170 const char* renderer_name =
"smooth";
178 void MICROVG_FONT_FREETYPE_initialize(
void) {
180 FT_Error error = FT_Init_FreeType(&library);
181 if(FT_ERR(Ok) == error) {
182 renderer = FT_RENDERER(FT_Get_Module(library, renderer_name));
184 MEJ_LOG_INFO_MICROVG(
"Freetype renderer: %s\n", FT_MODULE_CLASS(renderer)->module_name);
187 MEJ_LOG_ERROR_MICROVG(
"No renderer found with name %s\n", renderer_name);
191 MEJ_LOG_ERROR_MICROVG(
"Internal freetype error initializing library, ID = %d\n",error);
200 jint LLVG_FONT_IMPL_load_font(jchar* font_name, jboolean complex_layout) {
202 LOG_MICROVG_FONT_START(load);
205 jint ret = LLVG_FONT_UNLOADED;
208 if(complex_layout && !LLVG_FONT_IMPL_has_complex_layouter()){
209 ret = LLVG_FONT_UNLOADED;
213 FT_Error error = __load_internal_font(&face, font_name);
215 #if defined (VG_FEATURE_FONT_EXTERNAL)
216 if (FT_ERR(Cannot_Open_Resource) == error) {
218 error = __load_external_font(&face, font_name);
220 #endif // VG_FEATURE_FONT_EXTERNAL
222 if (FT_ERR(Ok) == error) {
224 FT_Select_Charmap(face , ft_encoding_unicode);
225 MEJ_LOG_INFO_MICROVG(
"Freetype font loaded: %s\n", (
const char*)font_name);
227 SNI_registerResource((
void*)face, (SNI_closeFunction)&_dispose_registered_font, &__register_font_description);
229 #if defined (VG_FEATURE_FONT_COMPLEX_LAYOUT)
230 if(JTRUE == complex_layout){
233 #endif // VG_FEATURE_FONT_COMPLEX_LAYOUT
237 else if (FT_ERR(Cannot_Open_Resource) != error){
238 MEJ_LOG_ERROR_MICROVG(
"An error occurred during font loading: 0x%x, refer to fterrdef.h\n", error);
241 MEJ_LOG_ERROR_MICROVG(
"Resource not found: %s\n", (
const char*)font_name);
246 LOG_MICROVG_FONT_END(load);
251 jfloat LLVG_FONT_IMPL_string_width(jchar* text, jint faceHandle, jfloat size, jfloat letterSpacing) {
253 LOG_MICROVG_FONT_START(stringWidth);
256 if (LLVG_FONT_UNLOADED == faceHandle) {
257 ret = (jfloat)LLVG_RESOURCE_CLOSED;
261 FT_Face face = (FT_Face) faceHandle;
262 float scaled_width = 0.f;
265 float scale = GET_SCALE(size, face);
268 long unscaled_width = 0;
272 int previous_glyph_index = 0;
275 int previous_advance_x;
276 int previous_offset_x;
281 int length = (int)SNI_getArrayLength(text);
282 MICROVG_HELPER_layout_configure(faceHandle, text, length);
284 while(MICROVG_HELPER_layout_load_glyph(&glyph_index, &advance_x, &advance_y, &offset_x, &offset_y)) {
286 if (0 == previous_glyph_index){
288 if(0 != face->glyph->metrics.width) {
289 unscaled_width -= face->glyph->metrics.horiBearingX;
292 unscaled_width -= face->glyph->advance.x;
296 unscaled_width += advance_x;
297 previous_glyph_index = glyph_index;
301 previous_advance_x = advance_x;
302 previous_offset_x = offset_x;
306 if(0 != face->glyph->metrics.width) {
307 unscaled_width -= previous_advance_x;
308 unscaled_width += face->glyph->metrics.horiBearingX;
309 unscaled_width += face->glyph->metrics.width;
310 unscaled_width += previous_offset_x;
313 if(0 != unscaled_width){
314 unscaled_width -= previous_advance_x;
317 scaled_width = ((scale * (float) unscaled_width) + (((float) nb_chars - 1) * letterSpacing));
323 LOG_MICROVG_FONT_END(stringWidth);
328 jfloat LLVG_FONT_IMPL_string_height(jchar* text, jint faceHandle, jfloat size) {
330 LOG_MICROVG_FONT_START(stringHeight);
333 if (LLVG_FONT_UNLOADED == faceHandle) {
334 ret = (jfloat)LLVG_RESOURCE_CLOSED;
338 FT_Face face = (FT_Face) faceHandle;
339 float scaled_height = 0.f;
342 float scale = GET_SCALE(size, face);
344 FT_Pos horiBearingYTop = 0;
345 FT_Pos horiBearingYBottom = 0;
349 int previous_glyph_index = 0;
356 int length = (int)SNI_getArrayLength(text);
357 MICROVG_HELPER_layout_configure(faceHandle, text, length);
359 while(MICROVG_HELPER_layout_load_glyph(&glyph_index, &advance_x, &advance_y, &offset_x, &offset_y)) {
362 FT_Pos yBottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height;
363 horiBearingYBottom = (0 == previous_glyph_index) ? yBottom : MEJ_MIN(yBottom, horiBearingYBottom);
364 horiBearingYTop = MEJ_MAX(face->glyph->metrics.horiBearingY, horiBearingYTop);
366 previous_glyph_index = glyph_index;
369 scaled_height = scale * (float) (horiBearingYTop - horiBearingYBottom);
375 LOG_MICROVG_FONT_END(stringHeight);
380 jfloat LLVG_FONT_IMPL_get_baseline_position(jint faceHandle, jfloat size) {
382 LOG_MICROVG_FONT_START(baseline);
385 if (LLVG_FONT_UNLOADED == faceHandle) {
386 ret = (jfloat)LLVG_RESOURCE_CLOSED;
390 FT_Face face = (FT_Face) faceHandle;
391 float advance_y = 0.f;
394 float scale = GET_SCALE(size, face);
395 advance_y = (face->ascender * scale);
400 LOG_MICROVG_FONT_END(baseline);
405 jfloat LLVG_FONT_IMPL_get_height(jint faceHandle, jfloat size) {
407 LOG_MICROVG_FONT_START(height);
410 if (LLVG_FONT_UNLOADED == faceHandle) {
411 ret = (jfloat)LLVG_RESOURCE_CLOSED;
414 FT_Face face = (FT_Face) faceHandle;
415 float scale = GET_SCALE(size, face);
416 ret = face->height * scale;
419 LOG_MICROVG_FONT_END(height);
424 void LLVG_FONT_IMPL_dispose(jint faceHandle) {
425 _dispose_registered_font((
void*)faceHandle);
429 bool LLVG_FONT_IMPL_has_complex_layouter(
void){
430 #ifdef VG_FEATURE_FONT_COMPLEX_LAYOUT
441 static void _dispose_registered_font(
void* faceHandle) {
442 FT_Face face = (FT_Face) faceHandle;
445 SNI_unregisterResource((
void*)face, (SNI_closeFunction)&_dispose_registered_font);
447 #if defined (VG_FEATURE_FONT_EXTERNAL)
450 FT_Stream stream = face->stream;
451 #endif // VG_FEATURE_FONT_EXTERNAL
455 #if defined (VG_FEATURE_FONT_EXTERNAL)
458 if (&__close_external_resource == stream->close) {
459 ft_mem_free(library->memory, stream);
461 #endif // VG_FEATURE_FONT_EXTERNAL
464 static FT_Error __load_memory_font(FT_Face* face,
void* data,
int length) {
465 return FT_New_Memory_Face(library, data, length, 0, face);
468 static FT_Error __load_internal_font(FT_Face* face, jchar* font_name) {
469 SNIX_resource font_resource;
472 if (0 == SNIX_get_resource(font_name, &font_resource)) {
473 error = __load_memory_font(face, font_resource.data, font_resource.size);
476 error = FT_ERR(Cannot_Open_Resource);
481 #if defined (VG_FEATURE_FONT_EXTERNAL)
483 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) {
493 int32_t resource_size = LLEXT_RES_available(resource_id);
496 int32_t base_address = LLEXT_RES_getBaseAddress(resource_id);
498 if (-1 != base_address) {
502 error = __load_memory_font(face, (
void*)base_address, resource_size);
505 LLEXT_RES_close(resource_id);
511 args.flags = FT_OPEN_STREAM;
513 args.stream = (FT_StreamRec*)ft_mem_alloc(library->memory,
sizeof(FT_StreamRec), &error);
515 if (FT_ERR(Ok) == error) {
517 args.stream->base = NULL;
518 args.stream->size = resource_size;
519 args.stream->pos = 0;
520 args.stream->descriptor.value = resource_id;
522 args.stream->read = &__read_external_resource;
523 args.stream->close = &__close_external_resource;
525 error = FT_Open_Face(library, &args, 0, face);
528 error = FT_ERR(Out_Of_Memory);
533 error = FT_ERR(Cannot_Open_Resource);
539 static unsigned long __read_external_resource(FT_Stream stream,
unsigned long offset,
unsigned char* buffer,
unsigned long count) {
540 int32_t size = count;
541 RES_ID resource_id = (RES_ID)(stream->descriptor.value);
542 LLEXT_RES_seek(resource_id, offset);
543 LLEXT_RES_read(resource_id, buffer, &size);
547 static void __close_external_resource(FT_Stream stream) {
548 RES_ID resource_id = (RES_ID)(stream->descriptor.value);
549 LLEXT_RES_close(resource_id);
552 #endif // VG_FEATURE_FONT_EXTERNAL
554 static void __register_font_description(
void* resource,
char* buffer, uint32_t bufferLength) {
556 const char descEF[] =
"Vector Font";
557 if (bufferLength >=
sizeof(descEF)) {
558 memcpy(buffer, descEF,
sizeof(descEF));
563 #endif // defined VG_FEATURE_FONT && \
564 // (defined VG_FEATURE_FONT_FREETYPE_VECTOR || defined VG_FEATURE_FONT_FREETYPE_BITMAP) && \
565 // (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_VECTOR || VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_BITMAP)
MicroEJ MicroVG library low level API: helper to implement library natives methods.
#define FT_FACE_FLAG_COMPLEX_LAYOUT
Freetype supplementary flag for complex layout Uses a free bit in freetype face flags to convey the c...
MicroEJ MicroVG library low level API: implementation over FreeType.
MicroEJ MicroVG library low level API: enable some features according to the hardware capacities...