font scaling fixes
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
d99ef4d2c2
commit
355e98bb19
|
@ -114,7 +114,8 @@ WELLSPRINGAPI Wellspring_Font* Wellspring_CreateFont(
|
||||||
const uint8_t *fontBytes,
|
const uint8_t *fontBytes,
|
||||||
uint32_t fontBytesLength,
|
uint32_t fontBytesLength,
|
||||||
const uint8_t *atlasJsonBytes,
|
const uint8_t *atlasJsonBytes,
|
||||||
uint32_t atlasJsonBytesLength
|
uint32_t atlasJsonBytesLength,
|
||||||
|
float *pPixelsPerEm
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Batches are not thread-safe, recommend one batch per thread. */
|
/* Batches are not thread-safe, recommend one batch per thread. */
|
||||||
|
@ -128,8 +129,7 @@ WELLSPRINGAPI void Wellspring_StartTextBatch(
|
||||||
|
|
||||||
WELLSPRINGAPI uint8_t Wellspring_TextBounds(
|
WELLSPRINGAPI uint8_t Wellspring_TextBounds(
|
||||||
Wellspring_Font *font,
|
Wellspring_Font *font,
|
||||||
float x,
|
int pixelSize,
|
||||||
float y,
|
|
||||||
Wellspring_HorizontalAlignment horizontalAlignment,
|
Wellspring_HorizontalAlignment horizontalAlignment,
|
||||||
Wellspring_VerticalAlignment verticalAlignment,
|
Wellspring_VerticalAlignment verticalAlignment,
|
||||||
const uint8_t *strBytes,
|
const uint8_t *strBytes,
|
||||||
|
@ -141,6 +141,7 @@ WELLSPRINGAPI uint8_t Wellspring_Draw(
|
||||||
Wellspring_TextBatch *textBatch,
|
Wellspring_TextBatch *textBatch,
|
||||||
float x,
|
float x,
|
||||||
float y,
|
float y,
|
||||||
|
int pixelSize,
|
||||||
float depth,
|
float depth,
|
||||||
Wellspring_Color *color,
|
Wellspring_Color *color,
|
||||||
Wellspring_HorizontalAlignment horizontalAlignment,
|
Wellspring_HorizontalAlignment horizontalAlignment,
|
||||||
|
|
|
@ -154,8 +154,10 @@ typedef struct Font
|
||||||
float ascender;
|
float ascender;
|
||||||
float descender;
|
float descender;
|
||||||
float lineHeight;
|
float lineHeight;
|
||||||
|
float pixelsPerEm;
|
||||||
|
|
||||||
float scale;
|
float scale;
|
||||||
float geometryScale; // all json values are premultiplied by this value, we need it for kerning
|
float kerningScale; // kerning values from stb_tt are in a different scale
|
||||||
|
|
||||||
Packer packer;
|
Packer packer;
|
||||||
} Font;
|
} Font;
|
||||||
|
@ -228,7 +230,6 @@ static uint8_t json_object_has_key(const json_object_t *object, const char* name
|
||||||
{
|
{
|
||||||
if (currentElement->next == NULL)
|
if (currentElement->next == NULL)
|
||||||
{
|
{
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Key %s not found in JSON!", name);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,7 +350,8 @@ Wellspring_Font* Wellspring_CreateFont(
|
||||||
const uint8_t* fontBytes,
|
const uint8_t* fontBytes,
|
||||||
uint32_t fontBytesLength,
|
uint32_t fontBytesLength,
|
||||||
const uint8_t *atlasJsonBytes,
|
const uint8_t *atlasJsonBytes,
|
||||||
uint32_t atlasJsonBytesLength
|
uint32_t atlasJsonBytesLength,
|
||||||
|
float *pPixelsPerEm
|
||||||
) {
|
) {
|
||||||
Font *font = Wellspring_malloc(sizeof(Font));
|
Font *font = Wellspring_malloc(sizeof(Font));
|
||||||
|
|
||||||
|
@ -396,13 +398,13 @@ Wellspring_Font* Wellspring_CreateFont(
|
||||||
|
|
||||||
font->packer.width = json_object_get_uint(atlasObject, "width");
|
font->packer.width = json_object_get_uint(atlasObject, "width");
|
||||||
font->packer.height = json_object_get_uint(atlasObject, "height");
|
font->packer.height = json_object_get_uint(atlasObject, "height");
|
||||||
|
font->pixelsPerEm = json_object_get_double(atlasObject, "size");
|
||||||
|
|
||||||
font->ascender = json_object_get_double(metricsObject, "ascender");
|
font->ascender = json_object_get_double(metricsObject, "ascender");
|
||||||
font->descender = json_object_get_double(metricsObject, "descender");
|
font->descender = json_object_get_double(metricsObject, "descender");
|
||||||
font->lineHeight = json_object_get_double(metricsObject, "lineHeight");
|
font->lineHeight = json_object_get_double(metricsObject, "lineHeight");
|
||||||
|
|
||||||
font->geometryScale = font->ascender / stbAscender;
|
font->scale = font->pixelsPerEm * 4 / 3; // converting from "points" (dpi) to pixels
|
||||||
font->scale = 1 / (font->ascender - font->descender);
|
|
||||||
|
|
||||||
/* Pack unicode ranges */
|
/* Pack unicode ranges */
|
||||||
|
|
||||||
|
@ -459,10 +461,6 @@ Wellspring_Font* Wellspring_CreateFont(
|
||||||
packedChar->atlasTop = json_object_get_double(boundsObject, "top");
|
packedChar->atlasTop = json_object_get_double(boundsObject, "top");
|
||||||
packedChar->atlasBottom = json_object_get_double(boundsObject, "bottom");
|
packedChar->atlasBottom = json_object_get_double(boundsObject, "bottom");
|
||||||
|
|
||||||
// flip texture coords because the atlas outputs glyphs in OpenGL texture space (lol)
|
|
||||||
packedChar->atlasTop = font->packer.height - packedChar->atlasTop;
|
|
||||||
packedChar->atlasBottom = font->packer.height - packedChar->atlasBottom;
|
|
||||||
|
|
||||||
json_object_t *planeObject = json_object_get_object(currentGlyphObject, "planeBounds");
|
json_object_t *planeObject = json_object_get_object(currentGlyphObject, "planeBounds");
|
||||||
|
|
||||||
packedChar->planeLeft = json_object_get_double(planeObject, "left");
|
packedChar->planeLeft = json_object_get_double(planeObject, "left");
|
||||||
|
@ -474,7 +472,14 @@ Wellspring_Font* Wellspring_CreateFont(
|
||||||
currentGlyphElement = currentGlyphElement->next;
|
currentGlyphElement = currentGlyphElement->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int advanceWidth, bearing;
|
||||||
|
stbtt_GetCodepointHMetrics(&font->fontInfo, font->packer.ranges[0].firstCodepoint, &advanceWidth, &bearing);
|
||||||
|
|
||||||
|
font->kerningScale = font->packer.ranges[0].data[0].xAdvance / advanceWidth;
|
||||||
|
|
||||||
Wellspring_free(jsonRoot);
|
Wellspring_free(jsonRoot);
|
||||||
|
|
||||||
|
*pPixelsPerEm = font->pixelsPerEm;
|
||||||
return (Wellspring_Font*) font;
|
return (Wellspring_Font*) font;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -581,8 +586,7 @@ static void GetPackedQuad(PackedChar *charData, float scale, int packerWidth, in
|
||||||
|
|
||||||
static uint8_t Wellspring_Internal_TextBounds(
|
static uint8_t Wellspring_Internal_TextBounds(
|
||||||
Font* font,
|
Font* font,
|
||||||
float x,
|
int pixelSize,
|
||||||
float y,
|
|
||||||
Wellspring_HorizontalAlignment horizontalAlignment,
|
Wellspring_HorizontalAlignment horizontalAlignment,
|
||||||
Wellspring_VerticalAlignment verticalAlignment,
|
Wellspring_VerticalAlignment verticalAlignment,
|
||||||
const uint8_t* strBytes,
|
const uint8_t* strBytes,
|
||||||
|
@ -597,14 +601,16 @@ static uint8_t Wellspring_Internal_TextBounds(
|
||||||
PackedChar* rangeData;
|
PackedChar* rangeData;
|
||||||
Quad charQuad;
|
Quad charQuad;
|
||||||
uint32_t i, j;
|
uint32_t i, j;
|
||||||
|
float x = 0, y = 0;
|
||||||
float minX = x;
|
float minX = x;
|
||||||
float minY = y;
|
float minY = y;
|
||||||
float maxX = x;
|
float maxX = x;
|
||||||
float maxY = y;
|
float maxY = y;
|
||||||
float startX = x;
|
float startX = x;
|
||||||
float advance = 0;
|
float advance = 0;
|
||||||
|
float sizeFactor = pixelSize / font->pixelsPerEm;
|
||||||
|
|
||||||
y += Wellspring_INTERNAL_GetVerticalAlignOffset(font, verticalAlignment, font->scale);
|
y += Wellspring_INTERNAL_GetVerticalAlignOffset(font, verticalAlignment, sizeFactor * font->scale);
|
||||||
|
|
||||||
for (i = 0; i < strLengthInBytes; i += 1)
|
for (i = 0; i < strLengthInBytes; i += 1)
|
||||||
{
|
{
|
||||||
|
@ -645,8 +651,8 @@ static uint8_t Wellspring_Internal_TextBounds(
|
||||||
if (IsWhitespace(codepoint))
|
if (IsWhitespace(codepoint))
|
||||||
{
|
{
|
||||||
PackedChar *packedChar = rangeData + rangeIndex;
|
PackedChar *packedChar = rangeData + rangeIndex;
|
||||||
x += font->scale * packedChar->xAdvance;
|
x += sizeFactor * font->scale * packedChar->xAdvance;
|
||||||
maxX += font->scale * packedChar->xAdvance;
|
maxX += sizeFactor * font->scale * packedChar->xAdvance;
|
||||||
previousGlyphIndex = -1;
|
previousGlyphIndex = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -655,12 +661,12 @@ static uint8_t Wellspring_Internal_TextBounds(
|
||||||
|
|
||||||
if (previousGlyphIndex != -1)
|
if (previousGlyphIndex != -1)
|
||||||
{
|
{
|
||||||
x += font->geometryScale * font->scale * stbtt_GetGlyphKernAdvance(&font->fontInfo, previousGlyphIndex, glyphIndex);
|
x += sizeFactor * font->kerningScale * font->scale * stbtt_GetGlyphKernAdvance(&font->fontInfo, previousGlyphIndex, glyphIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetPackedQuad(
|
GetPackedQuad(
|
||||||
rangeData,
|
rangeData,
|
||||||
font->scale,
|
sizeFactor * font->scale,
|
||||||
packer->width,
|
packer->width,
|
||||||
packer->height,
|
packer->height,
|
||||||
rangeIndex,
|
rangeIndex,
|
||||||
|
@ -700,8 +706,7 @@ static uint8_t Wellspring_Internal_TextBounds(
|
||||||
|
|
||||||
uint8_t Wellspring_TextBounds(
|
uint8_t Wellspring_TextBounds(
|
||||||
Wellspring_Font *font,
|
Wellspring_Font *font,
|
||||||
float x,
|
int pixelSize,
|
||||||
float y,
|
|
||||||
Wellspring_HorizontalAlignment horizontalAlignment,
|
Wellspring_HorizontalAlignment horizontalAlignment,
|
||||||
Wellspring_VerticalAlignment verticalAlignment,
|
Wellspring_VerticalAlignment verticalAlignment,
|
||||||
const uint8_t* strBytes,
|
const uint8_t* strBytes,
|
||||||
|
@ -710,8 +715,7 @@ uint8_t Wellspring_TextBounds(
|
||||||
) {
|
) {
|
||||||
return Wellspring_Internal_TextBounds(
|
return Wellspring_Internal_TextBounds(
|
||||||
(Font*) font,
|
(Font*) font,
|
||||||
x,
|
pixelSize,
|
||||||
y,
|
|
||||||
horizontalAlignment,
|
horizontalAlignment,
|
||||||
verticalAlignment,
|
verticalAlignment,
|
||||||
strBytes,
|
strBytes,
|
||||||
|
@ -724,6 +728,7 @@ uint8_t Wellspring_Draw(
|
||||||
Wellspring_TextBatch *textBatch,
|
Wellspring_TextBatch *textBatch,
|
||||||
float x,
|
float x,
|
||||||
float y,
|
float y,
|
||||||
|
int pixelSize,
|
||||||
float depth,
|
float depth,
|
||||||
Wellspring_Color *color,
|
Wellspring_Color *color,
|
||||||
Wellspring_HorizontalAlignment horizontalAlignment,
|
Wellspring_HorizontalAlignment horizontalAlignment,
|
||||||
|
@ -745,13 +750,14 @@ uint8_t Wellspring_Draw(
|
||||||
uint32_t indexBufferIndex;
|
uint32_t indexBufferIndex;
|
||||||
Wellspring_Rectangle bounds;
|
Wellspring_Rectangle bounds;
|
||||||
uint32_t i, j;
|
uint32_t i, j;
|
||||||
|
float sizeFactor = pixelSize / font->pixelsPerEm;
|
||||||
|
|
||||||
y += Wellspring_INTERNAL_GetVerticalAlignOffset(font, verticalAlignment, font->scale);
|
y += Wellspring_INTERNAL_GetVerticalAlignOffset(font, verticalAlignment, sizeFactor * font->scale);
|
||||||
|
|
||||||
/* FIXME: If we horizontally align, we have to decode and process glyphs twice, very inefficient. */
|
/* FIXME: If we horizontally align, we have to decode and process glyphs twice, very inefficient. */
|
||||||
if (horizontalAlignment == WELLSPRING_HORIZONTALALIGNMENT_RIGHT)
|
if (horizontalAlignment == WELLSPRING_HORIZONTALALIGNMENT_RIGHT)
|
||||||
{
|
{
|
||||||
if (!Wellspring_Internal_TextBounds(font, x, y, horizontalAlignment, verticalAlignment, strBytes, strLengthInBytes, &bounds))
|
if (!Wellspring_Internal_TextBounds(font, pixelSize, horizontalAlignment, verticalAlignment, strBytes, strLengthInBytes, &bounds))
|
||||||
{
|
{
|
||||||
/* Something went wrong while calculating bounds. */
|
/* Something went wrong while calculating bounds. */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -761,7 +767,7 @@ uint8_t Wellspring_Draw(
|
||||||
}
|
}
|
||||||
else if (horizontalAlignment == WELLSPRING_HORIZONTALALIGNMENT_CENTER)
|
else if (horizontalAlignment == WELLSPRING_HORIZONTALALIGNMENT_CENTER)
|
||||||
{
|
{
|
||||||
if (!Wellspring_Internal_TextBounds(font, x, y, horizontalAlignment, verticalAlignment, strBytes, strLengthInBytes, &bounds))
|
if (!Wellspring_Internal_TextBounds(font, pixelSize, horizontalAlignment, verticalAlignment, strBytes, strLengthInBytes, &bounds))
|
||||||
{
|
{
|
||||||
/* Something went wrong while calculating bounds. */
|
/* Something went wrong while calculating bounds. */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -807,7 +813,7 @@ uint8_t Wellspring_Draw(
|
||||||
if (IsWhitespace(codepoint))
|
if (IsWhitespace(codepoint))
|
||||||
{
|
{
|
||||||
PackedChar *packedChar = rangeData + rangeIndex;
|
PackedChar *packedChar = rangeData + rangeIndex;
|
||||||
x += font->scale * packedChar->xAdvance;
|
x += sizeFactor * font->scale * packedChar->xAdvance;
|
||||||
previousGlyphIndex = -1;
|
previousGlyphIndex = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -816,12 +822,12 @@ uint8_t Wellspring_Draw(
|
||||||
|
|
||||||
if (previousGlyphIndex != -1)
|
if (previousGlyphIndex != -1)
|
||||||
{
|
{
|
||||||
x += font->geometryScale * font->scale * stbtt_GetGlyphKernAdvance(&font->fontInfo, previousGlyphIndex, glyphIndex);
|
x += sizeFactor * font->kerningScale * font->scale * stbtt_GetGlyphKernAdvance(&font->fontInfo, previousGlyphIndex, glyphIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
GetPackedQuad(
|
GetPackedQuad(
|
||||||
rangeData,
|
rangeData,
|
||||||
font->scale,
|
sizeFactor * font->scale,
|
||||||
myPacker->width,
|
myPacker->width,
|
||||||
myPacker->height,
|
myPacker->height,
|
||||||
rangeIndex,
|
rangeIndex,
|
||||||
|
|
Loading…
Reference in New Issue