diff --git a/base/usr/include/toaru/text.h b/base/usr/include/toaru/text.h index 11dd837a..8df025ee 100644 --- a/base/usr/include/toaru/text.h +++ b/base/usr/include/toaru/text.h @@ -28,3 +28,10 @@ extern int tt_string_width_int(struct TT_Font * font, const char * s); extern int tt_draw_string(gfx_context_t * ctx, struct TT_Font * font, int x, int y, const char * s, uint32_t color); extern void tt_draw_string_shadow(gfx_context_t * ctx, struct TT_Font * font, char * string, int font_size, int left, int top, uint32_t text_color, uint32_t shadow_color, int blur); +struct TT_FontMetrics { + float ascender; + float descender; + float lineGap; +}; + +extern int tt_measure_font(struct TT_Font * font, struct TT_FontMetrics * metrics); diff --git a/lib/kuroko/_yutani2.c b/lib/kuroko/_yutani2.c index aa143048..29bcbf79 100644 --- a/lib/kuroko/_yutani2.c +++ b/lib/kuroko/_yutani2.c @@ -871,6 +871,23 @@ KRK_Method(Font,width) { return INTEGER_VAL(tt_string_width(self->fontData, s)); } +KRK_Method(Font,measure) { + INIT_CHECK(Font); + + KrkTuple * out = krk_newTuple(3); + krk_push(OBJECT_VAL(out)); + + struct TT_FontMetrics metrics; + + tt_measure_font(self->fontData, &metrics); + + out->values.values[out->values.count++] = FLOATING_VAL(metrics.ascender); + out->values.values[out->values.count++] = FLOATING_VAL(metrics.descender); + out->values.values[out->values.count++] = FLOATING_VAL(metrics.lineGap); + + return krk_pop(); +} + #undef CURRENT_CTYPE WRAP_TYPE(MenuBar,struct menu_bar,menuBar); @@ -1645,6 +1662,7 @@ KrkValue krk_module_onload__yutani2(void) { BIND_METHOD(Font,draw_string); BIND_METHOD(Font,draw_string_shadow); BIND_METHOD(Font,width); + BIND_METHOD(Font,measure); BIND_PROP(Font,size); krk_finalizeClass(Font); diff --git a/lib/text.c b/lib/text.c index eeaf470f..875d682d 100644 --- a/lib/text.c +++ b/lib/text.c @@ -85,6 +85,7 @@ struct TT_Font { struct TT_Table hhea_ptr; struct TT_Table hmtx_ptr; struct TT_Table name_ptr; + struct TT_Table os_2_ptr; off_t cmap_start; @@ -97,6 +98,11 @@ struct TT_Font { int loca_type; }; +struct TT_FontMetrics { + float ascender; + float descender; + float lineGap; +}; /* Currently, the edge sorter is disabled. It doesn't really help much, * and it's very slow with our horrible qsort implementation. */ @@ -381,6 +387,29 @@ static inline uint16_t tt_read_16(struct TT_Font * font) { ((b & 0xFF) << 0); } +int tt_measure_font(struct TT_Font * font, struct TT_FontMetrics * metrics) { + int a, d, l; + if (font->os_2_ptr.offset) { + tt_seek(font, font->os_2_ptr.offset + 2 * 37); + a = (int16_t)tt_read_16(font); + d = -(int16_t)tt_read_16(font); + + tt_seek(font, font->hhea_ptr.offset + 2 * 4); + l = (int16_t)tt_read_16(font); + } else { + tt_seek(font, font->hhea_ptr.offset + 2 * 2); + a = (int16_t)tt_read_16(font); + d = (int16_t)tt_read_16(font); + l = (int16_t)tt_read_16(font); + } + + metrics->ascender = a * font->scale; + metrics->descender = d * font->scale; + metrics->lineGap = l * font->scale; + + return 0; +} + int tt_xadvance_for_glyph(struct TT_Font * font, unsigned int ind) { tt_seek(font, font->hhea_ptr.offset + 2 * 17); uint16_t numLong = tt_read_16(font); @@ -843,6 +872,10 @@ static int tt_font_load(struct TT_Font * font) { font->name_ptr.offset = offset; font->name_ptr.length = length; break; + case 0x4f532f32: /* OS/2 */ + font->os_2_ptr.offset = offset; + font->name_ptr.length = length; + break; } }