mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 02:11:19 +00:00
[renderer] Star work on adding FreeType support
Right now, this just initializes the library and loads a font into memory, preloading a given set of characters (specified by unicode values).
This commit is contained in:
parent
d39f02ecfc
commit
4d5b38f0c9
8 changed files with 291 additions and 2 deletions
|
@ -26,7 +26,7 @@ NOCONV_DIST= \
|
|||
|
||||
BUILT_SOURCES = $(top_srcdir)/.version
|
||||
#AM_CFLAGS= @PREFER_NON_PIC@
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS)
|
||||
AM_CPPFLAGS= -I$(top_srcdir)/include $(PTHREAD_CFLAGS) $(FNM_FLAGS) $(NCURSES_CFLAGS) $(FREETYPE_CFLAGS)
|
||||
|
||||
common_ldflags= -export-dynamic @PTHREAD_LDFLAGS@
|
||||
|
||||
|
|
15
config.d/freetype.m4
Normal file
15
config.d/freetype.m4
Normal file
|
@ -0,0 +1,15 @@
|
|||
AC_ARG_ENABLE(freetype,
|
||||
AS_HELP_STRING([--disable-freetype], [disable freetype support]))
|
||||
if test "x$enable_freetype" != "xno"; then
|
||||
if test "x$PKG_CONFIG" != "x"; then
|
||||
PKG_CHECK_MODULES([FREETYPE], [freetype2], HAVE_FREETYPE=yes, HAVE_FREETYPE=no)
|
||||
fi
|
||||
else
|
||||
HAVE_FREETYPE=no
|
||||
FREETYPE_LIBS=
|
||||
fi
|
||||
AC_SUBST(FREETYPE_LIBS)
|
||||
|
||||
if test "x$HAVE_FREETYPE" == "xyes"; then
|
||||
AC_DEFINE(HAVE_FREETYPE, 1, [Define if you have the freetype library])
|
||||
fi
|
|
@ -68,6 +68,7 @@ m4_include(config.d/x11.m4)
|
|||
m4_include(config.d/sdl.m4)
|
||||
|
||||
m4_include(config.d/curses.m4)
|
||||
m4_include(config.d/freetype.m4)
|
||||
|
||||
dnl ==================================================================
|
||||
dnl Checks for system type
|
||||
|
|
66
include/r_font.h
Normal file
66
include/r_font.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
r_font.h
|
||||
|
||||
Renderer font 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
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __r_font_h
|
||||
#define __r_font_h
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include "QF/hash.h"
|
||||
#include "QF/progs.h" //FIXME for PR_RESMAP
|
||||
|
||||
#include "QF/ui/vrect.h"
|
||||
#include "QF/simd/types.h"
|
||||
|
||||
#include "r_scrap.h"
|
||||
|
||||
typedef struct rglyph_s {
|
||||
struct rfont_s *font;
|
||||
vrect_t *rect;
|
||||
vec2i_t bearing;
|
||||
int advance;
|
||||
int charcode;
|
||||
} rglyph_t;
|
||||
|
||||
typedef struct rfont_s {
|
||||
void *font_resource;
|
||||
FT_Face face;
|
||||
rscrap_t scrap;
|
||||
byte *scrap_bitmap;
|
||||
hashtab_t *glyphmap;
|
||||
PR_RESMAP(rglyph_t) glyphs;
|
||||
} rfont_t;
|
||||
|
||||
void R_FontInit (void);
|
||||
void R_FontFree (rfont_t *font);
|
||||
rfont_t *R_FontLoad (QFile *font_file, int size, const int *preload);
|
||||
|
||||
#endif//__r_font_h
|
|
@ -30,13 +30,15 @@ video_renderer_common_sources = \
|
|||
libs/video/renderer/r_billboard.c \
|
||||
libs/video/renderer/r_dyn_textures.c \
|
||||
libs/video/renderer/r_ent.c \
|
||||
libs/video/renderer/r_font.c \
|
||||
libs/video/renderer/r_iqm.c \
|
||||
libs/video/renderer/r_sprite.c \
|
||||
libs/video/renderer/vid_common.c
|
||||
|
||||
renderer_libs= \
|
||||
@vid_render_static_plugin_libs@ \
|
||||
libs/util/libQFutil.la
|
||||
libs/util/libQFutil.la \
|
||||
$(FREETYPE_LIBS)
|
||||
|
||||
libs_video_renderer_libQFrenderer_la_LDFLAGS= @STATIC@
|
||||
libs_video_renderer_libQFrenderer_la_LIBADD= $(renderer_libs)
|
||||
|
|
186
libs/video/renderer/r_font.c
Normal file
186
libs/video/renderer/r_font.c
Normal file
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
r_font.c
|
||||
|
||||
Renderer font management 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/math/bitop.h"
|
||||
|
||||
#include "r_font.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
static FT_Library ft;
|
||||
|
||||
static uintptr_t
|
||||
glyph_get_hash (const void *_glyph, void *unused)
|
||||
{
|
||||
__auto_type glyph = (const rglyph_t *) _glyph;
|
||||
return glyph->charcode;
|
||||
}
|
||||
|
||||
static int
|
||||
glyph_compare (const void *_a, const void *_b, void *unused)
|
||||
{
|
||||
__auto_type a = (const rglyph_t *) _a;
|
||||
__auto_type b = (const rglyph_t *) _b;
|
||||
return a->charcode == b->charcode;
|
||||
}
|
||||
|
||||
static rglyph_t *
|
||||
alloc_glyph (rfont_t *font)
|
||||
{
|
||||
return PR_RESNEW(font->glyphs);
|
||||
}
|
||||
|
||||
static void
|
||||
free_glyph (rfont_t *font, rglyph_t *glyph)
|
||||
{
|
||||
PR_RESFREE (font->glyphs, glyph);
|
||||
}
|
||||
|
||||
static void
|
||||
copy_glypn (rglyph_t *glyph, FT_GlyphSlot src_glyph)
|
||||
{
|
||||
int dst_pitch = glyph->font->scrap.width;
|
||||
byte *dst = glyph->font->scrap_bitmap + glyph->rect->x + glyph->rect->y * dst_pitch;
|
||||
int src_pitch = src_glyph->bitmap.pitch;
|
||||
byte *src = src_glyph->bitmap.buffer;
|
||||
|
||||
for (unsigned i = 0; i < src_glyph->bitmap.rows; i++) {
|
||||
memcpy (dst, src, src_glyph->bitmap.width);
|
||||
dst += dst_pitch;
|
||||
src += src_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
glyphmap_free_glyph (void *_g, void *_f)
|
||||
{
|
||||
rglyph_t *glyph = _g;
|
||||
rfont_t *font = _f;
|
||||
free_glyph (font, glyph);
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
R_FontInit (void)
|
||||
{
|
||||
if (FT_Init_FreeType (&ft)) {
|
||||
Sys_Error ("Could not init FreeType library");
|
||||
}
|
||||
}
|
||||
|
||||
VISIBLE void
|
||||
R_FontFree (rfont_t *font)
|
||||
{
|
||||
if (font->face) {
|
||||
FT_Done_Face (font->face);
|
||||
}
|
||||
if (font->glyphmap) {
|
||||
Hash_DelTable (font->glyphmap);
|
||||
}
|
||||
if (font->scrap.rects || font->scrap.free_rects) {
|
||||
R_ScrapDelete (&font->scrap);
|
||||
}
|
||||
free (font->scrap_bitmap);
|
||||
free (font->font_resource);
|
||||
free (font);
|
||||
}
|
||||
|
||||
VISIBLE rfont_t *
|
||||
R_FontLoad (QFile *font_file, int size, const int *preload)
|
||||
{
|
||||
byte *font_data = QFS_LoadFile (font_file, 0);
|
||||
if (!font_data) {
|
||||
return 0;
|
||||
}
|
||||
size_t font_size = Qfilesize (font_file);;
|
||||
rfont_t *font = calloc (1, sizeof (rfont_t));
|
||||
font->font_resource = font_data;
|
||||
if (FT_New_Memory_Face (ft, font_data, font_size, 0, &font->face)) {
|
||||
R_FontFree (font);
|
||||
return 0;
|
||||
}
|
||||
|
||||
font->glyphmap = Hash_NewTable (0x10000, 0, glyphmap_free_glyph, font, 0);
|
||||
Hash_SetHashCompare (font->glyphmap, glyph_get_hash, glyph_compare);
|
||||
|
||||
FT_Set_Pixel_Sizes(font->face, 0, size);
|
||||
int pixels = 0;
|
||||
for (const int *c = preload; *c; c++) {
|
||||
rglyph_t search = { .charcode = *c };
|
||||
rglyph_t *glyph = Hash_FindElement (font->glyphmap, &search);
|
||||
if (glyph) {
|
||||
continue;
|
||||
}
|
||||
if (FT_Load_Char(font->face, *c, FT_LOAD_DEFAULT)) {
|
||||
continue;
|
||||
}
|
||||
__auto_type g = font->face->glyph;
|
||||
pixels += g->bitmap.width * g->bitmap.rows;
|
||||
|
||||
glyph = alloc_glyph (font);
|
||||
glyph->charcode = *c;
|
||||
Hash_AddElement (font->glyphmap, glyph);
|
||||
}
|
||||
Hash_FlushTable (font->glyphmap);
|
||||
pixels = sqrt (2 * pixels);
|
||||
pixels = BITOP_RUP (pixels);
|
||||
R_ScrapInit (&font->scrap, pixels, pixels);
|
||||
font->scrap_bitmap = calloc (1, pixels * pixels);
|
||||
|
||||
for (const int *c = preload; *c; c++) {
|
||||
rglyph_t search = { .charcode = *c };
|
||||
rglyph_t *glyph = Hash_FindElement (font->glyphmap, &search);
|
||||
if (glyph) {
|
||||
continue;
|
||||
}
|
||||
if (FT_Load_Char(font->face, *c, FT_LOAD_RENDER)) {
|
||||
continue;
|
||||
}
|
||||
__auto_type g = font->face->glyph;
|
||||
int width = g->bitmap.width;
|
||||
int height = g->bitmap.rows;
|
||||
glyph = alloc_glyph (font);
|
||||
glyph->font = font;
|
||||
glyph->rect = R_ScrapAlloc (&font->scrap, width, height);
|
||||
glyph->bearing = (vec2i_t) { g->bitmap_left, g->bitmap_top };
|
||||
glyph->advance = g->advance.x;
|
||||
glyph->charcode = *c;
|
||||
Hash_AddElement (font->glyphmap, glyph);
|
||||
|
||||
copy_glypn (glyph, g);
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
|
@ -39,12 +39,14 @@
|
|||
#include "QF/draw.h"
|
||||
#include "QF/hash.h"
|
||||
#include "QF/progs.h"
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/render.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "QF/ui/view.h"
|
||||
|
||||
#include "r_internal.h"
|
||||
#include "r_font.h"
|
||||
|
||||
typedef struct {
|
||||
pr_int_t width;
|
||||
|
@ -332,6 +334,18 @@ bi_Draw_Height (progs_t *pr, void *_res)
|
|||
R_INT (pr) = r_data->vid->conview->ylen;
|
||||
}
|
||||
|
||||
static void
|
||||
bi_Font_Load (progs_t *pr, void *_res)
|
||||
{
|
||||
const char *font_path = P_GSTRING (pr, 0);
|
||||
int font_size = P_INT (pr, 1);
|
||||
int *preload = (int *) P_GPOINTER (pr, 2);
|
||||
|
||||
QFile *font_file = QFS_FOpenFile (font_path);
|
||||
rfont_t *font = R_FontLoad (font_file, font_size, preload);
|
||||
(void)font;
|
||||
}
|
||||
|
||||
static const char *
|
||||
bi_draw_get_key (const void *p, void *unused)
|
||||
{
|
||||
|
@ -381,6 +395,8 @@ static builtin_t builtins[] = {
|
|||
bi(Draw_Fill, 5, p(int), p(int), p(int), p(int), p(int)),
|
||||
bi(Draw_Line, 5, p(int), p(int), p(int), p(int), p(int)),
|
||||
bi(Draw_Crosshair, 5, p(int), p(int), p(int), p(int)),
|
||||
|
||||
bi(Font_Load, 3, p(string), p(int), p(ptr)),
|
||||
{0}
|
||||
};
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$";
|
|||
#include "QF/plugin/console.h"
|
||||
|
||||
#include "rua_internal.h"
|
||||
#include "r_font.h"
|
||||
|
||||
#include "ruamoko/qwaq/qwaq.h"
|
||||
|
||||
|
@ -330,6 +331,8 @@ BI_Graphics_Init (progs_t *pr)
|
|||
IN_Init ();
|
||||
Mod_Init ();
|
||||
R_Init ();
|
||||
R_FontInit ();
|
||||
|
||||
R_Progs_Init (pr);
|
||||
RUA_Game_Init (pr, thread->rua_security);
|
||||
S_Progs_Init (pr);
|
||||
|
|
Loading…
Reference in a new issue