mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 06:10:56 +00:00
[ui] Move text handling into gui lib
And add a function to process a passage into a set of views with glyphs. The views can be flowed: they have flow gravity and their sizes set to contain all the glyphs within each view (nominally, words). Nothing is tested yet, and font rendering is currently broken completely.
This commit is contained in:
parent
136bf882f6
commit
95f55dfc34
9 changed files with 350 additions and 150 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
r_text.h
|
||||
text.h
|
||||
|
||||
Renderer text management
|
||||
Text management
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
|
@ -28,8 +28,8 @@
|
|||
|
||||
*/
|
||||
|
||||
#ifndef __r_text_h
|
||||
#define __r_text_h
|
||||
#ifndef __QF_ui_text_h
|
||||
#define __QF_ui_text_h
|
||||
|
||||
#include <hb.h>
|
||||
#include <hb-ft.h>
|
||||
|
@ -44,30 +44,54 @@ typedef struct script_component_s {
|
|||
hb_direction_t direction;
|
||||
} script_component_t;
|
||||
|
||||
typedef struct glyph_component_s {
|
||||
int id;
|
||||
typedef struct glyphobj_s {
|
||||
int glyphid;
|
||||
int x, y;
|
||||
} glyph_component_t;
|
||||
int fontid;
|
||||
} glyphobj_t;
|
||||
|
||||
typedef struct rtext_s {
|
||||
typedef struct glyphref_s {
|
||||
uint32_t start;
|
||||
uint32_t count;
|
||||
} glyphref_t;
|
||||
|
||||
typedef struct glyphset_s {
|
||||
glyphobj_t *glyphs;
|
||||
uint32_t count;
|
||||
} glyphset_t;
|
||||
|
||||
typedef struct text_s {
|
||||
const char *text;
|
||||
const char *language;
|
||||
hb_script_t script;
|
||||
hb_direction_t direction;
|
||||
} rtext_t;
|
||||
} text_t;
|
||||
|
||||
typedef struct r_hb_featureset_s DARRAY_TYPE (hb_feature_t) r_hb_featureset_t;
|
||||
enum {
|
||||
// covers both view and passage text object hierarcies
|
||||
text_href,
|
||||
// all the glyhphs in a passage
|
||||
text_passage,
|
||||
text_glyphs,
|
||||
text_script,
|
||||
text_font,
|
||||
text_features,
|
||||
|
||||
text_type_count
|
||||
};
|
||||
|
||||
typedef struct featureset_s DARRAY_TYPE (hb_feature_t) featureset_t;
|
||||
|
||||
struct font_s;
|
||||
struct rglyph_s;
|
||||
typedef void rtext_render_t (uint32_t glyphid, int x, int y, void *data);
|
||||
typedef void text_render_t (uint32_t glyphid, int x, int y, void *data);
|
||||
|
||||
typedef struct rshaper_s {
|
||||
typedef struct shaper_s {
|
||||
struct font_s *rfont;
|
||||
hb_font_t *font;
|
||||
hb_buffer_t *buffer;
|
||||
r_hb_featureset_t features;
|
||||
} rshaper_t;
|
||||
featureset_t features;
|
||||
} shaper_t;
|
||||
|
||||
extern hb_feature_t LigatureOff;
|
||||
extern hb_feature_t LigatureOn;
|
||||
|
@ -76,11 +100,16 @@ extern hb_feature_t KerningOn;
|
|||
extern hb_feature_t CligOff;
|
||||
extern hb_feature_t CligOn;
|
||||
|
||||
rshaper_t *RText_NewShaper (struct font_s *font);
|
||||
void RText_DeleteShaper (rshaper_t *shaper);
|
||||
void RText_AddFeature (rshaper_t *shaper, hb_feature_t feature);
|
||||
void RText_ShapeText (rshaper_t *shaper, rtext_t *text);
|
||||
void RText_RenderText (rshaper_t *shaper, rtext_t *text, int x, int y,
|
||||
rtext_render_t *render, void *data);
|
||||
struct font_s;
|
||||
struct passage_s;
|
||||
|
||||
#endif//__r_text_h
|
||||
shaper_t *Text_NewShaper (struct font_s *font);
|
||||
void Text_DeleteShaper (shaper_t *shaper);
|
||||
void Text_AddFeature (shaper_t *shaper, hb_feature_t feature);
|
||||
void Text_ShapeText (shaper_t *shaper, text_t *text);
|
||||
void Text_RenderText (shaper_t *shaper, text_t *text, int x, int y,
|
||||
text_render_t *render, void *data);
|
||||
void Text_Init (void);
|
||||
struct view_s Text_View (struct font_s *font, struct passage_s *passage);
|
||||
|
||||
#endif//__QF_ui_text_h
|
|
@ -15,7 +15,8 @@ libs_ui_libQFgui_la_LDFLAGS= $(lib_ldflags)
|
|||
libs_ui_libQFgui_la_LIBADD= $(gui_deps) $(ui_deps)
|
||||
libs_ui_libQFgui_la_DEPENDENCIES= $(gui_deps) $(ui_deps)
|
||||
libs_ui_libQFgui_la_SOURCES= \
|
||||
libs/ui/font.c
|
||||
libs/ui/font.c \
|
||||
libs/ui/text.c
|
||||
|
||||
libs_ui_libQFui_la_LDFLAGS= $(lib_ldflags)
|
||||
libs_ui_libQFui_la_LIBADD= $(ui_deps)
|
||||
|
|
282
libs/ui/text.c
Normal file
282
libs/ui/text.c
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
text.c
|
||||
|
||||
Font text management
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
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 <math.h>
|
||||
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "QF/ui/font.h"
|
||||
#include "QF/ui/passage.h"
|
||||
#include "QF/ui/text.h"
|
||||
#include "QF/ui/view.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
static void
|
||||
text_features_create (void *_features)
|
||||
{
|
||||
featureset_t *features = _features;
|
||||
*features = (featureset_t) DARRAY_STATIC_INIT (4);
|
||||
}
|
||||
|
||||
static const component_t text_components[text_type_count] = {
|
||||
[text_href] = {
|
||||
.size = sizeof (hierref_t),
|
||||
.name = "href",
|
||||
},
|
||||
[text_passage] = {
|
||||
.size = sizeof (glyphset_t),
|
||||
.name = "passage glyphs",
|
||||
},
|
||||
[text_glyphs] = {
|
||||
.size = sizeof (glyphref_t),
|
||||
.name = "glyphs",
|
||||
},
|
||||
[text_script] = {
|
||||
.size = sizeof (script_component_t),
|
||||
.name = "script",
|
||||
},
|
||||
[text_font] = {
|
||||
.size = sizeof (font_t *),
|
||||
.name = "font",
|
||||
},
|
||||
[text_features] = {
|
||||
.size = sizeof (featureset_t),
|
||||
.name = "features",
|
||||
.create = text_features_create,
|
||||
},
|
||||
};
|
||||
static ecs_registry_t *text_reg;
|
||||
|
||||
void
|
||||
Text_Init (void)
|
||||
{
|
||||
text_reg = ECS_NewRegistry ();
|
||||
ECS_RegisterComponents (text_reg, text_components, text_type_count);
|
||||
}
|
||||
|
||||
typedef struct glyphnode_s {
|
||||
struct glyphnode_s *next;
|
||||
uint32_t ent;
|
||||
uint32_t count;
|
||||
glyphobj_t *glyphs;
|
||||
int mins[2];
|
||||
int maxs[2];
|
||||
} glyphnode_t;
|
||||
|
||||
view_t
|
||||
Text_View (font_t *font, passage_t *passage)
|
||||
{
|
||||
hierarchy_t *h = passage->hierarchy;
|
||||
psg_text_t *text_objects = h->components[passage_type_text_obj];
|
||||
glyphnode_t *glyph_nodes = 0;
|
||||
glyphnode_t **head = &glyph_nodes;
|
||||
|
||||
hb_font_t *fnt = hb_ft_font_create (font->face, 0);
|
||||
hb_buffer_t *buffer = hb_buffer_create ();
|
||||
hb_buffer_allocation_successful (buffer);
|
||||
|
||||
/*XXX*/hb_script_t script = HB_SCRIPT_LATIN;
|
||||
/*XXX*/hb_direction_t direction = HB_DIRECTION_LTR;
|
||||
/*XXX*/hb_language_t language = hb_language_from_string ("en", 2);
|
||||
hb_buffer_set_direction (buffer, direction);
|
||||
hb_buffer_set_script (buffer, script);
|
||||
hb_buffer_set_language (buffer, language);
|
||||
|
||||
uint32_t glyph_count = 0;
|
||||
|
||||
// passages have only the root, paragraphs, and text objects in their
|
||||
// hierarchies
|
||||
for (uint32_t i = 0; i < h->childCount[0]; i++) {
|
||||
uint32_t paragraph = h->childIndex[0] + i;
|
||||
for (uint32_t j = 0; j < h->childCount[paragraph]; j++) {
|
||||
uint32_t textind = h->childIndex[0] + j;
|
||||
psg_text_t *textobj = &text_objects[textind];
|
||||
const char *str = passage->text + textobj->text;
|
||||
uint32_t len = textobj->size;
|
||||
|
||||
hb_buffer_reset (buffer);
|
||||
hb_buffer_add_utf8 (buffer, str, len, 0, len);
|
||||
hb_shape (fnt, buffer, 0, 0);
|
||||
|
||||
unsigned c;
|
||||
__auto_type glyphInfo = hb_buffer_get_glyph_infos (buffer, &c);
|
||||
__auto_type glyphPos = hb_buffer_get_glyph_positions (buffer, &c);
|
||||
|
||||
*head = alloca (sizeof (glyphnode_t));
|
||||
**head = (glyphnode_t) {
|
||||
.ent = h->ent[textind],
|
||||
.count = c,
|
||||
.glyphs = alloca (c * sizeof (glyphobj_t)),
|
||||
};
|
||||
glyph_count += c;
|
||||
|
||||
int x = 0, y = 0;
|
||||
for (unsigned k = 0; k < c; k++) {
|
||||
uint32_t glyphid = glyphInfo[k].codepoint;
|
||||
vec2i_t bearing = font->glyph_bearings[glyphid];
|
||||
|
||||
int xp = x + glyphPos[k].x_offset / 64;
|
||||
int yp = y + glyphPos[k].y_offset / 64;
|
||||
int xa = glyphPos[k].x_advance / 64;
|
||||
int ya = glyphPos[k].y_advance / 64;
|
||||
xp += bearing[0];
|
||||
yp -= bearing[1];
|
||||
int xm = xp + font->glyph_rects[glyphid].width;
|
||||
int ym = yp + font->glyph_rects[glyphid].height;
|
||||
|
||||
(*head)->mins[0] = min ((*head)->mins[0], xp);
|
||||
(*head)->mins[1] = min ((*head)->mins[1], yp);
|
||||
(*head)->maxs[0] = max ((*head)->maxs[0], xm);
|
||||
(*head)->maxs[1] = max ((*head)->maxs[1], ym);
|
||||
|
||||
(*head)->glyphs[k] = (glyphobj_t) {
|
||||
.glyphid = glyphid,
|
||||
.x = xp + bearing[0],
|
||||
.y = yp - bearing[1],
|
||||
};
|
||||
x += xa;
|
||||
y += ya;
|
||||
}
|
||||
|
||||
head = &(*head)->next;
|
||||
}
|
||||
}
|
||||
view_t passage_view = View_New (text_reg, nullview);
|
||||
glyphref_t passage_ref = {};
|
||||
glyphobj_t *glyphs = malloc (glyph_count * sizeof (glyphobj_t));
|
||||
glyphnode_t *g = glyph_nodes;
|
||||
for (uint32_t i = 0; i < h->childCount[0]; i++) {
|
||||
uint32_t paragraph = h->childIndex[0] + i;
|
||||
view_t paraview = View_New (text_reg, passage_view);
|
||||
glyphref_t pararef = { .start = passage_ref.count };
|
||||
for (uint32_t j = 0; j < h->childCount[paragraph]; j++, g = g->next) {
|
||||
view_t textview = View_New (text_reg, paraview);
|
||||
glyphref_t glyph_ref = {
|
||||
.start = passage_ref.count,
|
||||
.count = g->count,
|
||||
};
|
||||
memcpy (glyphs + passage_ref.count, g->glyphs,
|
||||
g->count * sizeof (glyphobj_t));
|
||||
Ent_SetComponent (textview.id, text_glyphs, text_reg, &glyph_ref);
|
||||
View_SetPos (textview, g->mins[0], g->mins[1]);
|
||||
View_SetLen (textview, g->maxs[0] - g->mins[0],
|
||||
g->maxs[1] - g->mins[1]);
|
||||
View_SetGravity (textview, grav_flow);
|
||||
passage_ref.count += g->count;
|
||||
}
|
||||
pararef.count = passage_ref.count - pararef.start;
|
||||
Ent_SetComponent (paraview.id, text_glyphs, text_reg, ¶ref);
|
||||
}
|
||||
Ent_SetComponent (passage_view.id, text_glyphs, text_reg, &passage_ref);
|
||||
glyphset_t glyphset = {
|
||||
.glyphs = glyphs,
|
||||
.count = glyph_count,
|
||||
};
|
||||
Ent_SetComponent (passage_view.id, text_passage, text_reg, &glyphset);
|
||||
return passage_view;
|
||||
}
|
||||
|
||||
shaper_t *
|
||||
Text_NewShaper (font_t *font)
|
||||
{
|
||||
shaper_t *shaper = malloc (sizeof (shaper_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 = (featureset_t) DARRAY_STATIC_INIT (4);
|
||||
|
||||
hb_buffer_allocation_successful (shaper->buffer);
|
||||
return shaper;
|
||||
}
|
||||
|
||||
void
|
||||
Text_DeleteShaper (shaper_t *shaper)
|
||||
{
|
||||
hb_buffer_destroy (shaper->buffer);
|
||||
hb_font_destroy (shaper->font);
|
||||
DARRAY_CLEAR (&shaper->features);
|
||||
free (shaper);
|
||||
}
|
||||
|
||||
void
|
||||
Text_AddFeature (shaper_t *shaper, hb_feature_t feature)
|
||||
{
|
||||
DARRAY_APPEND (&shaper->features, feature);
|
||||
}
|
||||
|
||||
void
|
||||
Text_ShapeText (shaper_t *shaper, text_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
|
||||
Text_RenderText (shaper_t *shaper, text_t *text, int x, int y,
|
||||
text_render_t *render, void *data)
|
||||
{
|
||||
Text_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);
|
||||
|
||||
font_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;
|
||||
}
|
||||
}
|
|
@ -32,7 +32,6 @@ video_renderer_common_sources = \
|
|||
libs/video/renderer/r_ent.c \
|
||||
libs/video/renderer/r_iqm.c \
|
||||
libs/video/renderer/r_sprite.c \
|
||||
libs/video/renderer/r_text.c \
|
||||
libs/video/renderer/vid_common.c
|
||||
|
||||
renderer_libs= \
|
||||
|
|
|
@ -60,7 +60,6 @@
|
|||
#include "QF/ui/view.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "r_text.h"
|
||||
#include "r_internal.h"
|
||||
#include "varrays.h"
|
||||
|
||||
|
@ -1076,7 +1075,7 @@ gl_Draw_AddFont (font_t *rfont)
|
|||
font->texid = GL_LoadTex ("", 0, &tex);
|
||||
return fontid;
|
||||
}
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
int fontid;
|
||||
byte color[4];
|
||||
|
@ -1106,10 +1105,11 @@ gl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
|
|||
qfglTexCoord2f (u * s, (v + h) * t);
|
||||
qfglVertex2f (x, y + h);
|
||||
}
|
||||
|
||||
#endif
|
||||
void
|
||||
gl_Draw_FontString (int x, int y, int fontid, const char *str)
|
||||
{
|
||||
#if 0
|
||||
if (fontid < 0 || (unsigned) fontid > gl_fonts.size) {
|
||||
return;
|
||||
}
|
||||
|
@ -1134,4 +1134,5 @@ gl_Draw_FontString (int x, int y, int fontid, const char *str)
|
|||
|
||||
qfglEnd ();
|
||||
qfglColor4ubv (color_white);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
#include "QF/GLSL/qf_textures.h"
|
||||
#include "QF/GLSL/qf_vid.h"
|
||||
|
||||
#include "r_text.h"
|
||||
#include "r_internal.h"
|
||||
|
||||
typedef struct cachepic_s {
|
||||
|
@ -930,7 +929,7 @@ glsl_Draw_AddFont (font_t *rfont)
|
|||
font->texid = GLSL_LoadTex ("", 1, &tex);
|
||||
return fontid;
|
||||
}
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
vrect_t *glyph_rects;
|
||||
dstring_t *batch;
|
||||
|
@ -984,10 +983,11 @@ glsl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
|
|||
QuatCopy (rgctx->color, verts[4].color);
|
||||
QuatCopy (rgctx->color, verts[5].color);
|
||||
}
|
||||
|
||||
#endif
|
||||
void
|
||||
glsl_Draw_FontString (int x, int y, int fontid, const char *str)
|
||||
{
|
||||
#if 0
|
||||
if (fontid < 0 || (unsigned) fontid > glsl_fonts.size) {
|
||||
return;
|
||||
}
|
||||
|
@ -1030,4 +1030,5 @@ glsl_Draw_FontString (int x, int y, int fontid, const char *str)
|
|||
glyph_queue->size = 0;
|
||||
qfeglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
qfeglUseProgram (quake_2d.program);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
/*
|
||||
r_text.c
|
||||
|
||||
Renderer font text management
|
||||
|
||||
Copyright (C) 2022 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
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 <math.h>
|
||||
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "QF/ui/font.h"
|
||||
|
||||
#include "r_text.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
rshaper_t *
|
||||
RText_NewShaper (font_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);
|
||||
|
||||
font_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;
|
||||
}
|
||||
}
|
|
@ -43,7 +43,6 @@
|
|||
|
||||
#include "d_iface.h"
|
||||
#include "d_local.h"
|
||||
#include "r_text.h"
|
||||
#include "r_internal.h"
|
||||
#include "vid_internal.h"
|
||||
|
||||
|
@ -1012,7 +1011,7 @@ Draw_AddFont (struct font_s *rfont)
|
|||
font->font = rfont;
|
||||
return fontid;
|
||||
}
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
vrect_t *glyph_rects;
|
||||
byte *bitmap;
|
||||
|
@ -1046,10 +1045,11 @@ sw_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
|
|||
dst += d_rowbytes;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
void
|
||||
Draw_FontString (int x, int y, int fontid, const char *str)
|
||||
{
|
||||
#if 0
|
||||
if (fontid < 0 || (unsigned) fontid > sw_fonts.size) {
|
||||
return;
|
||||
}
|
||||
|
@ -1072,4 +1072,5 @@ Draw_FontString (int x, int y, int fontid, const char *str)
|
|||
rshaper_t *shaper = RText_NewShaper (rfont);
|
||||
RText_RenderText (shaper, &text, x, y, sw_render_glyph, &rgctx);
|
||||
RText_DeleteShaper (shaper);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -69,7 +69,6 @@
|
|||
#include "QF/ui/font.h"
|
||||
#include "QF/ui/view.h"
|
||||
|
||||
#include "r_text.h"
|
||||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
|
@ -1516,7 +1515,7 @@ Vulkan_Draw_AddFont (font_t *rfont, vulkan_ctx_t *ctx)
|
|||
|
||||
return fontid;
|
||||
}
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
drawframe_t *dframe;
|
||||
descbatch_t *batch;
|
||||
|
@ -1540,11 +1539,12 @@ vulkan_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
|
|||
inst->position[0] = x;
|
||||
inst->position[1] = y;
|
||||
}
|
||||
|
||||
#endif
|
||||
void
|
||||
Vulkan_Draw_FontString (int x, int y, int fontid, const char *str,
|
||||
vulkan_ctx_t *ctx)
|
||||
{
|
||||
#if 0
|
||||
drawctx_t *dctx = ctx->draw_context;
|
||||
if (fontid < 0 || (unsigned) fontid > dctx->fonts.size) {
|
||||
return;
|
||||
|
@ -1573,6 +1573,7 @@ Vulkan_Draw_FontString (int x, int y, int fontid, const char *str,
|
|||
rshaper_t *shaper = RText_NewShaper (dctx->fonts.a[fontid].font);
|
||||
RText_RenderText (shaper, &text, x, y, vulkan_render_glyph, &rgctx);
|
||||
RText_DeleteShaper (shaper);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue