23 #if defined VG_FEATURE_FONT && (VG_FEATURE_FONT == VG_FEATURE_FONT_FREETYPE_VECTOR)
28 #include <freetype/internal/ftobjs.h>
29 #if defined VG_FEATURE_FREETYPE_COLORED_EMOJI && (VG_FEATURE_FREETYPE_COLORED_EMOJI == 1)
30 #include <freetype/ftcolor.h>
32 #include "ftvector/ftvector.h"
34 #include <LLVG_FONT_impl.h>
35 #include <LLVG_PATH_impl.h>
36 #include <LLVG_GRADIENT_impl.h>
37 #include <LLVG_MATRIX_impl.h>
50 #if defined VG_FEATURE_FREETYPE_COLORED_EMOJI && (VG_FEATURE_FREETYPE_COLORED_EMOJI == 1)
51 #define FT_COLOR_TO_INT(x) (*((int *)&(x)))
54 #define DIRECTION_CLOCK_WISE 0
60 extern FT_Library library;
61 extern FT_Renderer renderer;
70 static void __set_renderer(FTVECTOR_draw_glyph_data_t *data) {
71 FT_Parameter params[1];
73 params[0].tag = FT_PARAM_TAG_DRAWER;
75 params[0].data = (
void *)data;
77 FT_Set_Renderer(library, renderer, 1, ¶ms[0]);
85 static float __get_angle(
float advance,
float radius) {
86 float angle = advance / radius;
92 #if defined VG_FEATURE_FREETYPE_COLORED_EMOJI && (VG_FEATURE_FREETYPE_COLORED_EMOJI == 1)
108 static FT_Error __render_glyph(FT_Face face, FT_UInt glyph_index, FT_Color *palette,
109 FTVECTOR_draw_glyph_data_t *drawer_data) {
112 FT_UInt layer_glyph_index = 0;
113 FT_UInt layer_color_index = 0;
114 FT_LayerIterator iterator;
117 if ((NULL == palette) ||
118 (0U == FT_Get_Color_Glyph_Layer(face, glyph_index, &layer_glyph_index, &layer_color_index, &iterator))) {
120 error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
122 uint32_t default_color = drawer_data->color;
127 if (layer_color_index != 0xFFFF) {
128 drawer_data->color = VG_FREETYPE_IMPL_convert_color(FT_COLOR_TO_INT(palette[layer_color_index]));
131 error = FT_Load_Glyph(face, layer_glyph_index, FT_LOAD_NO_SCALE);
132 if (FT_ERR(Ok) == error) {
134 error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
136 VG_LOG_ERROR(
"Error while loading glyphid %d: 0x%x, refer to fterrdef.h", layer_glyph_index,
140 has_next_layer = (FT_ERR(Ok) == error) &&
141 (0U != FT_Get_Color_Glyph_Layer(face, glyph_index, &layer_glyph_index,
142 &layer_color_index, &iterator));
143 }
while (has_next_layer);
146 drawer_data->color = default_color;
160 jfloat size,
const jfloat *matrix, uint32_t color, jfloat letterSpacing, jfloat radius,
161 jint direction,
void *user_data) {
162 jint result = LLVG_SUCCESS;
165 FT_Face face = (FT_Face)faceHandle;
166 #if defined VG_FEATURE_FREETYPE_COLORED_EMOJI && (VG_FEATURE_FREETYPE_COLORED_EMOJI == 1)
170 if (0 != FT_Palette_Select(face, 0, &palette)) {
176 float letterSpacingFontUnits = letterSpacing / scale;
177 float radiusScaled = radius / scale;
178 short baselineposition = face->ascender;
181 float scaled_matrix[LLVG_MATRIX_SIZE];
182 LLVG_MATRIX_IMPL_copy(scaled_matrix, matrix);
183 LLVG_MATRIX_IMPL_scale(scaled_matrix, scale, scale);
185 float working_matrix[LLVG_MATRIX_SIZE];
187 FTVECTOR_draw_glyph_data_t drawer_data;
188 drawer_data.drawer = drawer;
189 drawer_data.matrix = working_matrix;
190 drawer_data.color = color;
191 drawer_data.user_data = user_data;
192 drawer_data.destination_error = LLVG_SUCCESS;
195 __set_renderer(&drawer_data);
202 float advance_x = 0.f;
208 float span_left = 0.f;
210 advance_x = -span_left;
216 &glyph_advance_y, &glyph_offset_x,
220 int charWidth = glyph_advance_x;
223 LLVG_MATRIX_IMPL_copy(working_matrix, scaled_matrix);
226 LLVG_MATRIX_IMPL_translate(working_matrix, advance_x + (
float)glyph_offset_x,
227 (
float)(baselineposition + advance_y + glyph_offset_y));
229 float sign = (DIRECTION_CLOCK_WISE != direction) ? -1.f : 1.f;
232 float angleDegrees = 90 + __get_angle(advance_x + (
float)glyph_offset_x,
233 radiusScaled) + __get_angle((
float)(charWidth / 2), radiusScaled);
236 LLVG_MATRIX_IMPL_rotate(working_matrix, sign * angleDegrees);
240 LLVG_MATRIX_IMPL_translate(working_matrix, -charWidth / 2, -sign * radiusScaled);
244 #if defined VG_FEATURE_FREETYPE_COLORED_EMOJI && (VG_FEATURE_FREETYPE_COLORED_EMOJI == 1)
245 FT_Error error = __render_glyph(face, glyph_index, palette, &drawer_data);
248 FT_Error error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
250 if (FT_ERR(Ok) != error) {
251 if (LLVG_SUCCESS != drawer_data.destination_error) {
253 result = drawer_data.destination_error;
254 VG_LOG_ERROR(
"String cut at glyphid %d: the drawing destination refused (error %" PRId32
")",
255 glyph_index, result);
257 VG_LOG_ERROR(
"Error while rendering glyphid %d: 0x%x, refer to fterrdef.h", glyph_index,
259 result = (FT_ERR(Out_Of_Memory) == error) ? LLVG_OUT_OF_MEMORY : LLVG_DATA_INVALID;
265 advance_x += (float)charWidth;
266 advance_x += letterSpacingFontUnits;
267 advance_y += glyph_advance_y;
275 BSP_DECLARE_WEAK_FCNT jint VG_FREETYPE_IMPL_convert_color(jint color) {
MicroEJ MicroVG library low level API: enable some features according to the hardware capacities.
#define VG_LOG_DECLARE_MODULE()
Declares the log module, once at the top of each source file that logs.
MicroEJ MicroVG library low level API: implementation over FreeType.
bool VG_FREETYPE_string_span(const jchar *text, jint length, jint face_handle, jfloat letter_spacing_font_units, jfloat *left, jfloat *right)
Folds the ink of a string and returns its two extreme edges.
jfloat VG_FREETYPE_get_scale(jint face_handle, jfloat size)
Computes the scale that converts font units to pixels at the given size.
jint VG_FREETYPE_draw_string(VG_FREETYPE_draw_glyph_t drawer, const jchar *text, jint length, jint face_handle, jfloat size, const jfloat *matrix, uint32_t color, jfloat letter_spacing, jfloat radius, jint direction, void *user_data)
Draws a string using the Freetype engine along a line or a circle, with a color or a linear gradient....
jint(* VG_FREETYPE_draw_glyph_t)(VG_PATH_HEADER_t *path, jfloat *matrix, uint32_t color, bool fill_rule_even_odd, void *user_data)
Function to draw a character element: a glyph. A glyph is a vectorial path.
MicroEJ MicroVG library low level API: helper to implement library natives methods.
void VG_HELPER_layout_configure(int faceHandle, const unsigned short *text, int length)
Configures the font layouter with a font and a text.
#define VG_LOG_ERROR(fmt,...)
Logs an error. The format has no trailing line return.
bool VG_HELPER_layout_load_glyph(uint32_t *glyph_idx, int *x_advance, int *y_advance, int *x_offset, int *y_offset)
Loads the next layouted glyph and gets index and positions.