/* r_font.c Renderer font management management Copyright (C) 2022 Bill Currie Author: Bill Currie Date: 2022/8/26 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include "QF/quakefs.h" #include "QF/sys.h" #include "r_font.h" #include "r_text.h" #include "compat.h" rshaper_t * RText_NewShaper (rfont_t *font) { rshaper_t *shaper = malloc (sizeof (rshaper_t)); shaper->rfont = font; shaper->font = hb_ft_font_create (font->face, 0); hb_ft_font_set_funcs (shaper->font); shaper->buffer = hb_buffer_create (); shaper->features = (r_hb_featureset_t) DARRAY_STATIC_INIT (4); hb_buffer_allocation_successful (shaper->buffer); return shaper; } void RText_DeleteShaper (rshaper_t *shaper) { hb_buffer_destroy (shaper->buffer); hb_font_destroy (shaper->font); DARRAY_CLEAR (&shaper->features); free (shaper); } void RText_AddFeature (rshaper_t *shaper, hb_feature_t feature) { DARRAY_APPEND (&shaper->features, feature); } void RText_ShapeText (rshaper_t *shaper, rtext_t *text) { hb_buffer_reset (shaper->buffer); hb_buffer_set_direction (shaper->buffer, text->direction); hb_buffer_set_script (shaper->buffer, text->script); const char *lang = text->language; hb_buffer_set_language (shaper->buffer, hb_language_from_string (lang, strlen (lang))); size_t length = strlen (text->text); hb_buffer_add_utf8 (shaper->buffer, text->text, length, 0, length); hb_shape (shaper->font, shaper->buffer, shaper->features.a, shaper->features.size); } void RText_RenderText (rshaper_t *shaper, rtext_t *text, int x, int y, rtext_render_t *render, void *data) { RText_ShapeText (shaper, text); unsigned count; __auto_type glyphInfo = hb_buffer_get_glyph_infos (shaper->buffer, &count); __auto_type glyphPos = hb_buffer_get_glyph_positions (shaper->buffer, &count); rfont_t *font = shaper->rfont; for (unsigned i = 0; i < count; i++) { vec2i_t bearing = font->glyph_bearings[glyphInfo[i].codepoint]; int xp = x + glyphPos[i].x_offset / 64; int yp = y + glyphPos[i].y_offset / 64; int xa = glyphPos[i].x_advance / 64; int ya = glyphPos[i].y_advance / 64; xp += bearing[0]; yp -= bearing[1]; render (glyphInfo[i].codepoint, xp, yp, data); x += xa; y += ya; } }