Remove freetype2 font backend

The freetype2 font backend lacks support for proper combining marks and I
do not intend to ever implement that. Use pango!

If you don't want heavy dependencies, you can use the unifont or 8x16
backends.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
David Herrmann 2013-10-29 09:31:03 +01:00
parent 96b28e953d
commit 761434ecac
7 changed files with 2 additions and 825 deletions

View File

@ -451,28 +451,6 @@ mod_unifont_la_LDFLAGS = \
-module \
-avoid-version
if BUILD_ENABLE_FONT_FREETYPE2
module_LTLIBRARIES += mod-freetype2.la
endif
mod_freetype2_la_SOURCES = \
src/kmscon_module_interface.h \
src/font_freetype2.c \
src/kmscon_mod_freetype2.c
mod_freetype2_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(FREETYPE2_CFLAGS) \
$(TSM_CFLAGS)
mod_freetype2_la_LIBADD = \
$(FREETYPE2_LIBS) \
$(TSM_LIBS) \
-lpthread \
libshl.la
mod_freetype2_la_LDFLAGS = \
$(AM_LDFLAGS) \
-module \
-avoid-version
if BUILD_ENABLE_FONT_PANGO
module_LTLIBRARIES += mod-pango.la
endif

1
README
View File

@ -74,7 +74,6 @@ Released tarballs can be found at:
Default is: fbdev,drm2d,drm3d
--with-fonts: Font renderers. Available backends are:
- unifont: Static built-in non-scalable font (Unicode Unifont)
- freetype2: Freetype2+fontconfig based scalable font renderer
- pango: Pango based scalable font renderer
Default is: unifont,pango
The 8x16 backend is always built-in.

View File

@ -95,11 +95,6 @@ PKG_CHECK_MODULES([GLES2], [glesv2],
AC_SUBST(GLES2_CFLAGS)
AC_SUBST(GLES2_LIBS)
PKG_CHECK_MODULES([FREETYPE2], [freetype2 fontconfig],
[have_freetype2=yes], [have_freetype2=no])
AC_SUBST(FREETYPE2_CFLAGS)
AC_SUBST(FREETYPE2_LIBS)
PKG_CHECK_MODULES([PANGO], [pango pangoft2],
[have_pango=yes], [have_pango=no])
AC_SUBST(PANGO_CFLAGS)
@ -341,16 +336,13 @@ AC_ARG_WITH([fonts],
[],
[with_fonts="default"])
enable_font_unifont="no"
enable_font_freetype2="no"
enable_font_pango="no"
if test "x$enable_all" = "xyes" ; then
enable_font_unifont="yes"
enable_font_freetype2="yes"
enable_font_pango="yes"
with_fonts="unifont,freetype2,pango (all)"
with_fonts="unifont,pango (all)"
elif test "x$with_fonts" = "xdefault" ; then
enable_font_unifont="yes (default)"
enable_font_freetype2="no (default)"
enable_font_pango="yes (default)"
with_fonts="unifont,pango (default)"
elif test ! "x$with_fonts" = "x" ; then
@ -359,8 +351,6 @@ elif test ! "x$with_fonts" = "x" ; then
for i in $with_fonts ; do
if test "x$i" = "xunifont" ; then
enable_font_unifont="yes"
elif test "x$i" = "xfreetype2" ; then
enable_font_freetype2="yes"
elif test "x$i" = "xpango" ; then
enable_font_pango="yes"
else
@ -659,25 +649,6 @@ else
font_unifont_missing="enable-font-unifont"
fi
# font freetype2
font_freetype2_avail=no
font_freetype2_missing=""
if test ! "x$enable_font_freetype2" = "xno" ; then
font_freetype2_avail=yes
if test "x$have_freetype2" = "xno" ; then
font_freetype2_avail=no
font_freetype2_missing="libfontconfig,libfreetype2"
fi
if test "x$font_freetype2_avail" = "xno" ; then
if test "x$enable_font_freetype2" = "xyes" ; then
AC_ERROR([missing for font-freetype2: $font_freetype2_missing])
fi
fi
else
font_freetype2_missing="enable-font-freetype2"
fi
# font pango
font_pango_avail=no
font_pango_missing=""
@ -796,14 +767,6 @@ if test "x$font_pango_avail" = "xyes" ; then
fi
fi
# font freetype2
font_freetype2_enabled=no
if test "x$font_freetype2_avail" = "xyes" ; then
if test "x${enable_font_freetype2% *}" = "xyes" ; then
font_freetype2_enabled=yes
fi
fi
# font unifont
font_unifont_enabled=no
if test "x$font_unifont_avail" = "xyes" ; then
@ -1060,15 +1023,6 @@ fi
AM_CONDITIONAL([BUILD_ENABLE_FONT_UNIFONT],
[test "x$font_unifont_enabled" = "xyes"])
# font freetype2
if test "x$font_freetype2_enabled" = "xyes" ; then
AC_DEFINE([BUILD_ENABLE_FONT_FREETYPE2], [1],
[Build freetype2 font backend])
fi
AM_CONDITIONAL([BUILD_ENABLE_FONT_FREETYPE2],
[test "x$font_freetype2_enabled" = "xyes"])
# font pango
if test "x$font_pango_enabled" = "xyes" ; then
AC_DEFINE([BUILD_ENABLE_FONT_PANGO], [1],
@ -1200,7 +1154,6 @@ AC_MSG_NOTICE([Build configuration:
Font Backends:
unifont: $font_unifont_enabled ($font_unifont_avail: $font_unifont_missing)
freetype2: $font_freetype2_enabled ($font_freetype2_avail: $font_freetype2_missing)
pango: $font_pango_enabled ($font_pango_avail: $font_pango_missing)
Renderers:

View File

@ -476,7 +476,7 @@
<varlistentry>
<term><option>--font-engine {engine}</option></term>
<listitem>
<para>Select font-engine. Available engines are 'pango', 'freetype2',
<para>Select font-engine. Available engines are 'pango',
'unifont' and '8x16'. (default: pango)</para>
</listitem>
</varlistentry>

View File

@ -111,7 +111,6 @@ int kmscon_font_render_inval(struct kmscon_font *font,
extern struct kmscon_font_ops kmscon_font_8x16_ops;
extern struct kmscon_font_ops kmscon_font_unifont_ops;
extern struct kmscon_font_ops kmscon_font_freetype2_ops;
extern struct kmscon_font_ops kmscon_font_pango_ops;
#endif /* KMSCON_FONT_H */

View File

@ -1,694 +0,0 @@
/*
* kmscon - Freetype2 font backend
*
* Copyright (c) 2011-2013 David Herrmann <dh.herrmann@googlemail.com>
* Copyright (c) 2011 University of Tuebingen
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/**
* SECTION:font_freetype2.c
* @short_description: Freetype2 font backend
* @include: font.h
*
* The freetype2 backend uses freetype2 to render glyphs into memory
* buffers. It uses a hashmap to cache all rendered glyphs of a single
* font-face. Therefore, rendering should be very fast. Also, when loading a
* glyph it pre-renders all common (mostly ASCII) characters, so it can measure
* the font and return a valid font width.
*/
#include <errno.h>
#include <fontconfig/fontconfig.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <libtsm.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "font.h"
#include "shl_dlist.h"
#include "shl_hashtable.h"
#include "shl_log.h"
#include "uterm_video.h"
#define LOG_SUBSYSTEM "font_freetype2"
struct glyph {
bool shrinked;
unsigned int width;
};
struct face {
unsigned long ref;
struct shl_dlist list;
bool shrink;
struct kmscon_font_attr attr;
struct kmscon_font_attr real_attr;
unsigned int baseline;
FT_Face face;
pthread_mutex_t glyph_lock;
struct shl_hashtable *glyphs;
struct kmscon_glyph empty;
struct kmscon_glyph inval;
};
static pthread_mutex_t manager_mutex = PTHREAD_MUTEX_INITIALIZER;
static unsigned long manager__refcnt;
static FT_Library manager__lib;
static struct shl_dlist manager__list = SHL_DLIST_INIT(manager__list);
static void manager_lock()
{
pthread_mutex_lock(&manager_mutex);
}
static void manager_unlock()
{
pthread_mutex_unlock(&manager_mutex);
}
/* TODO: We currently load the default font-config configuration on start-up but
* should probably provide a way to refresh it on SIGHUP or similar. Font-config
* provides the FcInitBringUptoDate() or FcInitReinitialize() functions. */
static int manager__ref()
{
FT_Error err;
if (!manager__refcnt++) {
err = FT_Init_FreeType(&manager__lib);
if (err) {
log_warn("cannot initialize freetype2");
--manager__refcnt;
return -EFAULT;
}
if (!FcInit()) {
log_warn("cannot initialize fontconfig library");
err = FT_Done_FreeType(manager__lib);
if (err)
log_warn("cannot deinitialize freetype2");
--manager__refcnt;
return -EFAULT;
}
}
return 0;
}
static void manager__unref()
{
FT_Error err;
if (!--manager__refcnt) {
/* FcFini() uses assert() to check whether all resources were
* correctly freed before FcFini() is called. As an emergency
* console, we cannot risk being killed because we have a small
* memory leak. Therefore, we rather skip deinitializing
* fontconfig and blame their authors here.
* Never ever use assert()/abort()/etc. in critical code paths!
* Bullshit...
* TODO: Fix upstream fontconfig to drop all those ugly
* assertions. */
// FcFini();
err = FT_Done_FreeType(manager__lib);
if (err)
log_warn("cannot deinitialize freetype2");
}
}
static int get_glyph(struct face *face, struct kmscon_glyph **out,
uint32_t id, const uint32_t *ch, size_t len)
{
struct kmscon_glyph *glyph;
struct glyph *data;
FT_Error err;
FT_UInt idx;
FT_Bitmap *bmap;
FT_GlyphSlot slot;
bool res;
unsigned int i, j, wmax, hmax, idx1, idx2, cwidth;
int ret, hoff1, hoff2, woff1, woff2;
if (!len)
return -ERANGE;
cwidth = tsm_ucs4_get_width(*ch);
if (!cwidth)
return -ERANGE;
pthread_mutex_lock(&face->glyph_lock);
res = shl_hashtable_find(face->glyphs, (void**)&glyph,
(void*)(long)id);
pthread_mutex_unlock(&face->glyph_lock);
if (res) {
*out = glyph;
return 0;
}
manager_lock();
glyph = malloc(sizeof(*glyph) + sizeof(struct glyph));
if (!glyph) {
log_error("cannot allocate memory for new glyph");
ret = -ENOMEM;
goto out_unlock;
}
memset(glyph, 0, sizeof(*glyph) + sizeof(struct glyph));
glyph->data = (void*)(((uint8_t*)glyph) + sizeof(*glyph));
data = glyph->data;
glyph->width = cwidth;
/* We currently ignore composed-symbols. That is, we only use the first
* UCS-4 code and draw this character. This works great for most simple
* ASCII characters but composed CJK characters often consist of
* multiple UCS-4 codes.
* TODO: Fix this by drawing all related characters into a single glyph
* and saving it or simply refer to the pango backend which already does
* that. */
if (!*ch) {
ret = -ERANGE;
goto out_glyph;
}
idx = FT_Get_Char_Index(face->face, *ch);
err = FT_Load_Glyph(face->face, idx, FT_LOAD_DEFAULT);
if (err) {
ret = -ERANGE;
goto out_glyph;
}
err = FT_Render_Glyph(face->face->glyph, FT_RENDER_MODE_NORMAL);
if (err) {
ret = -ERANGE;
goto out_glyph;
}
slot = face->face->glyph;
bmap = &slot->bitmap;
if (slot->format != FT_GLYPH_FORMAT_BITMAP ||
bmap->pixel_mode != FT_PIXEL_MODE_GRAY ||
bmap->num_grays != 256 ||
!bmap->rows ||
!bmap->width) {
ret = -ERANGE;
goto out_glyph;
}
data->width = bmap->width;
glyph->buf.width = face->real_attr.width * cwidth;
glyph->buf.height = face->real_attr.height;
glyph->buf.stride = glyph->buf.width;
glyph->buf.format = UTERM_FORMAT_GREY;
glyph->buf.data = malloc(glyph->buf.stride * glyph->buf.height);
if (!glyph->buf.data) {
ret = -ENOMEM;
goto out_glyph;
}
memset(glyph->buf.data, 0, glyph->buf.stride * glyph->buf.height);
/* compute width-offsets and relative width-differences */
if (slot->bitmap_left >= glyph->buf.width) {
wmax = 0;
woff1 = 0;
woff2 = 0;
} else if (slot->bitmap_left < 0) {
if (glyph->buf.width > bmap->width)
wmax = bmap->width;
else
wmax = glyph->buf.width;
woff1 = 0;
woff2 = 0;
} else {
wmax = glyph->buf.width - slot->bitmap_left;
if (wmax > bmap->width)
wmax = bmap->width;
woff1 = slot->bitmap_left;
woff2 = 0;
}
/* compute height-offsets and relative height-differences */
hoff1 = (int)glyph->buf.height - face->baseline;
if (hoff1 > slot->bitmap_top) {
hoff1 -= slot->bitmap_top;
hoff2 = 0;
} else {
hoff2 = slot->bitmap_top - hoff1;
hoff1 = 0;
}
if (bmap->rows - hoff2 > glyph->buf.height - hoff1)
hmax = glyph->buf.height - hoff1;
else
hmax = bmap->rows - hoff2;
/* copy bitmap into glyph buffer */
for (i = 0; i < hmax; ++i) {
for (j = 0; j < wmax; ++j) {
idx1 = (i + hoff1) * glyph->buf.stride + (j + woff1);
idx2 = (i + hoff2) * bmap->pitch + (j + woff2);
glyph->buf.data[idx1] = bmap->buffer[idx2];
}
}
pthread_mutex_lock(&face->glyph_lock);
ret = shl_hashtable_insert(face->glyphs, (void*)(long)id, glyph);
pthread_mutex_unlock(&face->glyph_lock);
if (ret) {
log_error("cannot add glyph to hashtable");
goto out_buffer;
}
*out = glyph;
goto out_unlock;
out_buffer:
free(glyph->buf.data);
out_glyph:
free(glyph);
out_unlock:
manager_unlock();
return ret;
}
static void free_glyph(void *data)
{
struct kmscon_glyph *glyph = data;
free(glyph->buf.data);
free(glyph);
}
static int manager_get_face(struct face **out, struct kmscon_font_attr *attr)
{
struct shl_dlist *iter;
struct face *face, *f;
FcPattern *pat, *mat;
FcResult res;
FcChar8 *fname;
FT_Error err;
int ret, tmp, idx, weight, slant;
double s, em, xsc, ysc;
manager_lock();
if (!attr->height) {
ret = -EINVAL;
goto out_unlock;
}
if (!attr->width)
attr->width = attr->height;
shl_dlist_for_each(iter, &manager__list) {
face = shl_dlist_entry(iter, struct face, list);
if (kmscon_font_attr_match(&face->attr, attr)) {
++face->ref;
*out = face;
ret = 0;
goto out_unlock;
}
}
ret = manager__ref();
if (ret)
goto out_unlock;
face = malloc(sizeof(*face));
if (!face) {
log_error("cannot allocate memory for new face");
ret = -ENOMEM;
goto err_manager;
}
memset(face, 0, sizeof(*face));
face->ref = 1;
memcpy(&face->attr, attr, sizeof(*attr));
memcpy(&face->real_attr, attr, sizeof(*attr));
ret = pthread_mutex_init(&face->glyph_lock, NULL);
if (ret) {
log_error("cannot initialize glyph lock");
goto err_free;
}
ret = shl_hashtable_new(&face->glyphs, shl_direct_hash,
shl_direct_equal, NULL, free_glyph);
if (ret) {
log_error("cannot allocate hashtable");
goto err_lock;
}
s = face->attr.height;
weight = face->attr.bold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL;
slant = face->attr.italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN;
pat = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, face->attr.name,
FC_PIXEL_SIZE, FcTypeDouble, s,
FC_WEIGHT, FcTypeInteger, weight,
FC_SLANT, FcTypeInteger, slant,
NULL);
if (!pat) {
log_error("cannot create font-config pattern");
ret = -EFAULT;
goto err_htable;
}
if (!FcConfigSubstitute(NULL, pat, FcMatchPattern)) {
FcPatternDestroy(pat);
log_error("cannot perform font-config substitutions");
ret = -ENOMEM;
goto err_htable;
}
res = FcResultMatch;
mat = FcFontMatch(NULL, pat, &res);
if (res != FcResultMatch) {
if (mat)
FcPatternDestroy(mat);
FcPatternDestroy(pat);
log_error("font-config cannot find font: %d", res);
ret = -EFAULT;
goto err_htable;
}
res = FcPatternGetString(mat, FC_FILE, 0, &fname);
if (res != FcResultMatch) {
FcPatternDestroy(mat);
FcPatternDestroy(pat);
log_error("font-config cannot find font (name)");
ret = -EFAULT;
goto err_htable;
}
res = FcPatternGetInteger(mat, FC_INDEX, 0, &idx);
if (res != FcResultMatch) {
FcPatternDestroy(mat);
FcPatternDestroy(pat);
log_error("font-config cannot find font (index)");
ret = -EFAULT;
goto err_htable;
}
log_debug("loading font %s:%d", (const char*)fname, idx);
err = FT_New_Face(manager__lib, (const char*)fname, idx, &face->face);
FcPatternDestroy(mat);
FcPatternDestroy(pat);
if (err) {
if (err == FT_Err_Unknown_File_Format)
log_error("unknown font file format");
else
log_error("cannot load font");
ret = -EFAULT;
goto err_htable;
}
if (!face->face->charmap) {
log_warn("cannot load charmap of new font");
ret = -EFAULT;
goto err_face;
}
if (!FT_IS_SCALABLE(face->face)) {
log_warn("non-scalable font");
ret = -EFAULT;
goto err_face;
}
err = FT_Set_Pixel_Sizes(face->face, face->attr.width,
face->attr.height);
if (err) {
log_warn("cannot set pixel size of font");
ret = -EFAULT;
goto err_face;
}
/* Every font provides an ascender/descender value which we use to
* compute glyph-height and the baseline offset. We need monospace fonts
* as we have the same fixed bounding-box for every glyph. However, if
* the font is not a monospace font, then the most straight-forward
* approach would be using the biggest bounding box. This, however, will
* not work as some characters are extremely wide and the text will look
* horrible. Therefore, we use the ascender/descender values provided
* with each font. This guarantees that special characters like
* line-segments are properly aligned without spacing. If the font does
* not provide proper asc/desc values, then freetype2 will return proper
* substitutions. */
em = face->face->units_per_EM;
xsc = face->face->size->metrics.x_ppem / em;
ysc = face->face->size->metrics.y_ppem / em;
tmp = face->face->descender * ysc;
if (tmp > 0)
tmp = 0;
face->baseline = -tmp;
tmp = face->face->ascender * ysc + face->baseline;
if (tmp < 0 || tmp < face->baseline) {
log_warn("invalid ascender/descender values for font");
ret = -EFAULT;
goto err_face;
}
face->real_attr.height = tmp;
/* For font-width we use the biggest bounding-box-width. After the font
* has been loaded, this is cut down by pre-rendering some characters
* and computing a better average. */
tmp = 1 + (int)(xsc * (face->face->bbox.xMax - face->face->bbox.xMin));
if (tmp < 0)
tmp = 0;
face->real_attr.width = tmp;
kmscon_font_attr_normalize(&face->real_attr);
if (!face->real_attr.height || !face->real_attr.width) {
log_warn("invalid scaled font sizes");
ret = -EFAULT;
goto err_face;
}
/* The real metrics probably differ from the requested metrics so try
* again to find a suitable cached font. */
shl_dlist_for_each(iter, &manager__list) {
f = shl_dlist_entry(iter, struct face, list);
if (kmscon_font_attr_match(&f->real_attr, &face->real_attr)) {
++f->ref;
*out = f;
ret = 0;
goto err_face;
}
}
shl_dlist_link(&manager__list, &face->list);
*out = face;
ret = 0;
goto out_unlock;
err_face:
FT_Done_Face(face->face);
err_htable:
shl_hashtable_free(face->glyphs);
err_lock:
pthread_mutex_destroy(&face->glyph_lock);
err_free:
free(face);
err_manager:
manager__unref();
out_unlock:
manager_unlock();
return ret;
}
static void manager_put_face(struct face *face)
{
manager_lock();
if (!--face->ref) {
shl_dlist_unlink(&face->list);
shl_hashtable_free(face->glyphs);
pthread_mutex_destroy(&face->glyph_lock);
FT_Done_Face(face->face);
free(face);
manager__unref();
}
manager_unlock();
}
static int generate_specials(struct face *face)
{
size_t s;
struct kmscon_glyph *g;
int ret;
static const uint32_t question_mark = '?';
face->empty.width = 1;
face->empty.data = NULL;
face->empty.buf.width = face->real_attr.width;
face->empty.buf.height = face->real_attr.height;
face->empty.buf.stride = face->empty.buf.width;
face->empty.buf.format = UTERM_FORMAT_GREY;
s = face->empty.buf.stride * face->empty.buf.height;
face->empty.buf.data = malloc(s);
if (!face->empty.buf.data)
return -ENOMEM;
memset(face->empty.buf.data, 0, s);
ret = get_glyph(face, &g, question_mark, &question_mark, 1);
if (ret) {
memcpy(&face->inval, &face->empty, sizeof(face->inval));
} else {
memcpy(&face->inval, g, sizeof(face->inval));
}
return 0;
}
static int kmscon_font_freetype2_init(struct kmscon_font *out,
const struct kmscon_font_attr *attr)
{
struct face *face = NULL;
int ret;
unsigned int width;
uint32_t i;
struct kmscon_glyph *glyph;
struct glyph *data;
memcpy(&out->attr, attr, sizeof(*attr));
kmscon_font_attr_normalize(&out->attr);
log_debug("loading freetype2 font %s", out->attr.name);
ret = manager_get_face(&face, &out->attr);
if (ret)
return ret;
memcpy(&out->attr, &face->real_attr, sizeof(out->attr));
out->baseline = face->baseline;
/* Shrinking is done to get a better width-value for fonts. As not all
* fonts provide monospace-glyphs, we need to calculate a proper width
* by pre-rendering all ASCII characters and using the widest value.
* TODO: We should extend this with a better algorithm as there are
* common non-ASCII glyphs which are much wider.
* We enable shrinking by default as most fonts have a maximum-width
* which is about 3 times the size of 'M'.*/
face->shrink = true;
if (face->shrink) {
width = 0;
for (i = 0x20; i < 0x7f; ++i) {
ret = get_glyph(face, &glyph, i, &i, 1);
if (ret)
continue;
data = glyph->data;
if (data->width > width)
width = data->width;
}
if (!width) {
log_warning("cannot measure font");
face->shrink = false;
} else if (width < face->real_attr.width) {
face->real_attr.width = width;
kmscon_font_attr_normalize(&face->real_attr);
memcpy(&out->attr, &face->real_attr, sizeof(out->attr));
}
}
/* generate inval/empty glyphs after shrinking */
ret = generate_specials(face);
if (ret)
goto err_face;
out->data = face;
return 0;
err_face:
manager_put_face(face);
return ret;
}
static void kmscon_font_freetype2_destroy(struct kmscon_font *font)
{
struct face *face;
face = font->data;
log_debug("unloading freetype2 font %s", face->real_attr.name);
free(face->empty.buf.data);
manager_put_face(face);
}
static int kmscon_font_freetype2_render(struct kmscon_font *font, uint32_t id,
const uint32_t *ch, size_t len,
const struct kmscon_glyph **out)
{
struct kmscon_glyph *glyph;
struct glyph *data;
struct face *face;
int ret;
ret = get_glyph(font->data, &glyph, id, ch, len);
if (ret)
return ret;
face = font->data;
data = glyph->data;
if (face->shrink && !data->shrinked) {
data->shrinked = true;
glyph->buf.width = face->real_attr.width * glyph->width;
}
*out = glyph;
return 0;
}
static int kmscon_font_freetype2_render_empty(struct kmscon_font *font,
const struct kmscon_glyph **out)
{
struct face *face = font->data;
*out = &face->empty;
return 0;
}
static int kmscon_font_freetype2_render_inval(struct kmscon_font *font,
const struct kmscon_glyph **out)
{
struct face *face = font->data;
*out = &face->inval;
return 0;
}
struct kmscon_font_ops kmscon_font_freetype2_ops = {
.name = "freetype2",
.owner = NULL,
.init = kmscon_font_freetype2_init,
.destroy = kmscon_font_freetype2_destroy,
.render = kmscon_font_freetype2_render,
.render_empty = kmscon_font_freetype2_render_empty,
.render_inval = kmscon_font_freetype2_render_inval,
};

View File

@ -1,58 +0,0 @@
/*
* kmscon - Freetype2 font backend module
*
* Copyright (c) 2011-2013 David Herrmann <dh.herrmann@googlemail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Freetype2 font backend module
* This module registers the freetype2 font backend with kmscon.
*/
#include <errno.h>
#include <stdlib.h>
#include "font.h"
#include "kmscon_module_interface.h"
#include "shl_log.h"
#define LOG_SUBSYSTEM "mod_freetype2"
static int kmscon_freetype2_load(void)
{
int ret;
kmscon_font_freetype2_ops.owner = KMSCON_THIS_MODULE;
ret = kmscon_font_register(&kmscon_font_freetype2_ops);
if (ret) {
log_error("cannot register pango font");
return ret;
}
return 0;
}
static void kmscon_freetype2_unload(void)
{
kmscon_font_unregister(kmscon_font_freetype2_ops.name);
}
KMSCON_MODULE(NULL, kmscon_freetype2_load, kmscon_freetype2_unload, NULL);