Skip to content
Permalink
Browse files

Far improved font rendering and metrics

  • Loading branch information
darkuranium committed Sep 29, 2012
1 parent 55015d6 commit 34e31681738a7b4b479780a8c7069f50acbc6be6
@@ -2,7 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6)

SET(SG_VERSION_MAJOR "0")
SET(SG_VERSION_MINOR "7")
SET(SG_VERSION_PATCH "8")
SET(SG_VERSION_PATCH "9")

#ADD_DEFINITIONS(
# "-DSG_VERSION_MAJOR=${SG_VERSION_MAJOR}"
@@ -1,16 +1,16 @@
/*
Copyright (c) 2007 SIEGE Development Team
All rights reserved.
This file is part of libSIEGE.
This software is copyrighted work licensed under the terms of the
2-clause BSD license. Please consult the file "license.txt" for
details.
If you did not recieve the file with this program, please email
Tim Chas <darkuranium@gmail.com>.
*/
* Copyright (c) 2007 SIEGE Development Team
* All rights reserved.
*
* This file is part of libSIEGE.
*
* This software is copyrighted work licensed under the terms of the
* 2-clause BSD license. Please consult the file "license.txt" for
* details.
*
* If you did not recieve the file with this program, please email
* Tim Chas <darkuranium@gmail.com>.
*/

#ifndef __SIEGE_BACKEND_FONTS_CHARS_H__
#define __SIEGE_BACKEND_FONTS_CHARS_H__
@@ -25,8 +25,9 @@
extern "C"
{
#endif
SGuint SG_EXPORT SG_FPTR(sgmFontsCharsCreate)(void* face, SGuint* chars, SGuint charnum, float* width, float* height, float* prex, float* prey, float* postx, float* posty, SGuint* datawidth, SGuint* dataheight, void** data);
SGuint SG_EXPORT SG_FPTR(sgmFontsCharsFreeData)(void* data);
SGenum SG_EXPORT SG_FPTR(sgmFontsCharsCreate)(void* face, const SGdchar* chars, size_t numchars, float* width, float* height, float* prex, float* prey, float* postx, float* posty, size_t* datawidth, size_t* dataheight, void** data);
SGenum SG_EXPORT SG_FPTR(sgmFontsCharsFreeData)(void* data);
SGenum SG_EXPORT SG_FPTR(sgmFontsCharsGetKerning)(void* face, const SGdchar* chars, size_t numchars, float* kerning);
#ifdef __cplusplus
}
#endif
@@ -5,7 +5,7 @@
* This file is part of libSIEGE.
*
* This software is copyrighted work licensed under the terms of the
* 2-clause BSD license. Please consult the file "license.txt" for
* 2-clause BSD license. Please consult the file "COPYING.txt" for
* details.
*
* If you did not recieve the file with this program, please email
@@ -27,9 +27,9 @@ extern "C"
{
#endif
SGenum SG_EXPORT SG_FPTR(sgmFontsFaceCreate)(void** face, SGStream* stream);
SGuint SG_EXPORT SG_FPTR(sgmFontsFaceDestroy)(void* face);
SGuint SG_EXPORT SG_FPTR(sgmFontsFaceSetHeight)(void* face, float height);
//SGuint SG_EXPORT sgmFontsFaceGetHeight(void* face, float* height);
SGenum SG_EXPORT SG_FPTR(sgmFontsFaceDestroy)(void* face);
SGenum SG_EXPORT SG_FPTR(sgmFontsFaceSetHeight)(void* face, float height, SGuint dpi);
SGenum SG_EXPORT SG_FPTR(sgmFontsFaceGetMetrics)(void* face, float* ascent, float* descent, float* linegap);
#ifdef __cplusplus
}
#endif
@@ -137,7 +137,7 @@ typedef double SGdouble;
/// @{
#define SG_VERSION_MAJOR 0
#define SG_VERSION_MINOR 7
#define SG_VERSION_PATCH 8
#define SG_VERSION_PATCH 9
/**
* \brief Version string
*
@@ -74,8 +74,8 @@ typedef struct SGCharInfo
* \name Bitmap size
*/
/// @{
SGuint dwidth;
SGuint dheight;
size_t dwidth;
size_t dheight;
/// @}

/**
@@ -116,15 +116,21 @@ typedef struct SGFont
*/
void* handle;
float height; /// < Height of the font
SGuint dpi;
/// @}

float ascent;
float descent;
float linegap;

// char, wchar_t, utf8, utf16
SGConv* conv[4];

/**
* \name Preloaded characters
*/
/// @{
size_t npreload;
SGuint numchars; /// < The number of characters
SGCharInfo* chars; /// < The characters themselves
/// @}
@@ -156,7 +162,7 @@ SGdchar* SG_EXPORT _sgFontU8ToU32(SGFont* font, const SGchar* text);
SGdchar* SG_EXPORT _sgFontWToU32(SGFont* font, const wchar_t* text);
SGdchar* SG_EXPORT _sgFontToU32(SGFont* font, const char* text);

SGFont* SG_EXPORT sgFontCreateStream(SGStream* stream, SGbool delstream, float height, SGuint preload);
SGFont* SG_EXPORT sgFontCreateStream(SGStream* stream, SGbool delstream, float height, SGuint dpi, SGuint preload);
/// @{
/**
* \brief Load a font
@@ -177,48 +183,8 @@ SGFont* SG_EXPORT sgFontCreate(const char* fname, float height, SGuint preload);
void SG_EXPORT sgFontDestroy(SGFont* font);
/// @}

/* resize functions temporarily removed */

/**
* \name Resizing
*/
/// @{
/**
* \brief Resize the font, force duplication.
*
* \param font The font to resize
* \param height New font height
*
* \return A copy of the font, with the height \a height.
*
* This resizes the font and forces for it to be duplicated even
* if the character data for the new size has already been created.
*
* It is roughly equivalent to:
* \code
* sgFontCreate(font->fname, font->height, font->preload);
* \endcode
*
* \see sgFontResize
*/

//SGFont* SG_EXPORT sgFontResizeCopy(SGFont* font, float height);
/**
* \brief Resize the font, duplicating only if necessarry.
*
* \param font The font to resize
* \param height New font height
*
* \return A new font if one had to be created;
* otherwise a previously-created font.
*
* This function is similar to sgFontResizeCopy(), only it
* does not allocate a new font if it doesn't have to.
*
* \see sgFontResizeCopy
*/
//SGFont* SG_EXPORT sgFontResize(SGFont* font, float height);
/// @}
void SG_EXPORT sgFontClearCache(SGFont* font);
void SG_EXPORT sgFontSetHeight(SGFont* font, float height, SGuint dpi);

/**
* \name Printing
@@ -94,28 +94,36 @@ SGenum SG_EXPORT sgmFontsFaceCreate(void** face, SGStream* stream)
return SG_UNKNOWN_ERROR;
return SG_OK;
}
SGuint SG_EXPORT sgmFontsFaceDestroy(void* face)
SGenum SG_EXPORT sgmFontsFaceDestroy(void* face)
{
if(face == NULL)
return SG_OK; // SG_INVALID_VALUE
FT_Done_Face(((FontFace*)face)->ftface);
free(face);
return SG_OK;
}
SGuint SG_EXPORT sgmFontsFaceSetHeight(void* face, float height)

SGenum SG_EXPORT sgmFontsFaceSetHeight(void* face, float height, SGuint dpi)
{
if(face == NULL)
return SG_OK; // SG_INVALID_VALUE
((FontFace*)face)->height = height;
FT_Set_Char_Size(((FontFace*)face)->ftface, (SGuint)(height * 64), (SGuint)(height * 64), 72, 72);
FT_Set_Char_Size(((FontFace*)face)->ftface, (SGuint)(height * 64), (SGuint)(height * 64), dpi, dpi);
return SG_OK;
}
/*SGuint SG_EXPORT sgmFontsFaceGetHeight(void* face, float* height)
SGenum SG_EXPORT sgmFontsFaceGetMetrics(void* face, float* ascent, float* descent, float* linegap)
{
*height = ((FontFace*)face)->height;
if(!face) return SG_INVALID_VALUE;
FontFace* fface = face;

*ascent = fface->ftface->size->metrics.ascender / 64.0;
*descent = fface->ftface->size->metrics.descender / 64.0;
*linegap = fface->ftface->size->metrics.height / 64.0 + *descent - *ascent;

return SG_OK;
}*/
SGuint SG_EXPORT sgmFontsCharsCreate(void* face, SGuint* chars, SGuint charnum, float* width, float* height, float* prex, float* prey, float* postx, float* posty, SGuint* datawidth, SGuint* dataheight, void** data)
}

SGenum SG_EXPORT sgmFontsCharsCreate(void* face, const SGdchar* chars, size_t numchars, float* width, float* height, float* prex, float* prey, float* postx, float* posty, size_t* datawidth, size_t* dataheight, void** data)
{
if(face == NULL)
{
@@ -137,8 +145,8 @@ SGuint SG_EXPORT sgmFontsCharsCreate(void* face, SGuint* chars, SGuint charnum,
FT_Glyph glyph;
FT_BitmapGlyph bitmap_glyph;
FT_Bitmap bitmap;
SGuint i/*, j*/;
for(i = 0; i < charnum; i++)
SGuint i;
for(i = 0; i < numchars; i++)
{
ret = FT_Load_Glyph(fface->ftface, FT_Get_Char_Index(fface->ftface, chars[i]), FT_LOAD_DEFAULT);
if(ret)
@@ -160,27 +168,45 @@ SGuint SG_EXPORT sgmFontsCharsCreate(void* face, SGuint* chars, SGuint charnum,

data[i] = malloc(bitmap.width * bitmap.rows);
memcpy(data[i], bitmap.buffer, bitmap.width * bitmap.rows);
/*for(j = 0; j < bitmap.rows; j++)
memcpy((char*)data[i] + j * bitmap.width, bitmap.buffer + (bitmap.rows - j - 1) * bitmap.width, bitmap.width);*/

prex[i] = bitmap_glyph->left;
//prey[i] = -bitmap_glyph->top + bitmap.rows;
prey[i] = -bitmap_glyph->top;

postx[i] = fface->ftface->glyph->advance.x / 64.0;
posty[i] = 0;

width[i] = fface->ftface->glyph->/*bitmap.width*/advance.x / 64.0;
height[i] = fface->height;
width[i] = fface->ftface->glyph->metrics.width;
height[i] = fface->ftface->glyph->metrics.height;

FT_Done_Glyph(glyph);
}

return SG_OK;
}

SGuint SG_EXPORT sgmFontsCharsFreeData(void* data)
SGenum SG_EXPORT sgmFontsCharsFreeData(void* data)
{
free(data);
return SG_OK;
}

SGenum SG_EXPORT sgmFontsCharsGetKerning(void* face, const SGdchar* chars, size_t numchars, float* kerning)
{
if(!face) return SG_INVALID_VALUE;
FontFace* fface = face;

FT_Vector vec;

FT_UInt prev = numchars ? FT_Get_Char_Index(fface->ftface, chars[0]) : 0;
FT_UInt curr;

size_t i;
for(i = 1; i < numchars; i++)
{
curr = FT_Get_Char_Index(fface->ftface, chars[i]);
FT_Get_Kerning(fface->ftface, prev, curr, FT_KERNING_DEFAULT, &vec);
kerning[i-1] = vec.x / 64.0;
prev = curr;
}

return SG_OK;
}
@@ -20,7 +20,7 @@ typedef struct FontFace
{
stbtt_fontinfo info;
void* buf;
float height;
float scale;
} FontFace;

SGenum SG_EXPORT sgmFontsFaceCreate(void** face, SGStream* stream)
@@ -50,6 +50,8 @@ SGenum SG_EXPORT sgmFontsFaceCreate(void** face, SGStream* stream)
goto err;
stbtt_InitFont(&fface->info, fface->buf, 0);

fface->scale = 1.0;

return SG_OK;

err:
@@ -64,50 +66,74 @@ SGenum SG_EXPORT sgmFontsFaceDestroy(void* face)
free(fface);
return SG_OK;
}
SGenum SG_EXPORT sgmFontsFaceSetHeight(void* face, float height)

SGenum SG_EXPORT sgmFontsFaceSetHeight(void* face, float height, SGuint dpi)
{
if(!face) return SG_INVALID_VALUE;
FontFace* fface = face;
fface->height = height;
//fface->scale = stbtt_ScaleForPixelHeight(&fface->info, height);
fface->scale = stbtt_ScaleForMappingEmToPixels(&fface->info, height * dpi / 72.0);
return SG_OK;
}
SGenum SG_EXPORT sgmFontsCharsCreate(void* face, SGuint* chars, SGuint charnum, float* width, float* height, float* prex, float* prey, float* postx, float* posty, SGuint* datawidth, SGuint* dataheight, void** data)
SGenum SG_EXPORT sgmFontsFaceGetMetrics(void* face, float* ascent, float* descent, float* linegap)
{
if(!face) return SG_INVALID_VALUE;
FontFace* fface = face;

int iasc, idesc, igap;
stbtt_GetFontVMetrics(&fface->info, &iasc, &idesc, &igap);
*ascent = iasc * fface->scale;
*descent = idesc * fface->scale;
*linegap = igap * fface->scale;

return SG_OK;
}

SGenum SG_EXPORT sgmFontsCharsCreate(void* face, const SGdchar* chars, size_t numchars, float* width, float* height, float* prex, float* prey, float* postx, float* posty, size_t* datawidth, size_t* dataheight, void** data)
{
if(!face) return SG_INVALID_VALUE;

FontFace* fface = (FontFace*)face;
//float scale = stbtt_ScaleForPixelHeight(&fface->info, fface->height);
float scale = stbtt_ScaleForMappingEmToPixels(&fface->info, fface->height);

int adv, left;
int dw, dh;
int xo, yo;
int kern = 0;

int glyph;
size_t i;
for(i = 0; i < charnum; i++)
for(i = 0; i < numchars; i++)
{
glyph = stbtt_FindGlyphIndex(&fface->info, chars[i]);

data[i] = stbtt_GetGlyphBitmap(&fface->info, scale, scale, glyph, &dw, &dh, &xo, &yo);
data[i] = stbtt_GetGlyphBitmap(&fface->info, fface->scale, fface->scale, glyph, &dw, &dh, &xo, &yo);
datawidth[i] = dw;
dataheight[i] = dh;

if(i) kern = stbtt_GetGlyphKernAdvance(&fface->info, chars[i-1], chars[i]);

stbtt_GetGlyphHMetrics(&fface->info, glyph, &adv, &left);
prex[i] = (left + kern) * scale + xo;
prex[i] = /*-left * fface->scale * 0.5 + */xo;
prey[i] = yo;
postx[i] = adv * scale;
postx[i] = adv * fface->scale;
posty[i] = 0;
width[i] = adv * fface->scale;
height[i] = 0; /* TODO */
}

return SG_OK;
}

SGenum SG_EXPORT sgmFontsCharsFreeData(void* data)
{
stbtt_FreeBitmap(data, NULL);
return SG_OK;
}

SGenum SG_EXPORT sgmFontsCharsGetKerning(void* face, const SGdchar* chars, size_t numchars, float* kerning)
{
if(!face) return SG_INVALID_VALUE;
FontFace* fface = face;

size_t i;
for(i = 1; i < numchars; i++)
kerning[i-1] = stbtt_GetCodepointKernAdvance(&fface->info, chars[i-1], chars[i]) * fface->scale;

return SG_OK;
}

0 comments on commit 34e3168

Please sign in to comment.
You can’t perform that action at this time.