Ember blender with gamma correction into FontRenderer

This commit is contained in:
Francesco Abbate 2020-06-02 17:18:52 +02:00
parent bc74b2860d
commit ae032cd185
4 changed files with 54 additions and 35 deletions

View File

@ -6,45 +6,62 @@
#include "font_renderer_alpha.h" #include "font_renderer_alpha.h"
FontRenderer *FontRendererNew(unsigned int flags) { typedef agg::blender_rgb_gamma<agg::rgba8, agg::order_bgra, agg::gamma_lut<> > blender_gamma_type;
bool hinting = ((flags & FONT_RENDERER_HINTING) != 0);
bool kerning = ((flags & FONT_RENDERER_KERNING) != 0); class FontRendererImpl {
font_renderer_alpha *font_renderer = new font_renderer_alpha(hinting, kerning); public:
return (FontRenderer *) font_renderer; FontRendererImpl(bool hinting, bool kerning, float gamma_value) :
m_renderer(hinting, kerning),
m_gamma_lut(double(gamma_value)),
m_blender()
{
m_blender.gamma(m_gamma_lut);
} }
void FontRendererFree(FontRenderer *fr_) { font_renderer_alpha& renderer_alpha() { return m_renderer; }
font_renderer_alpha *font_renderer = (font_renderer_alpha *) fr_; blender_gamma_type& blender() { return m_blender; }
private:
font_renderer_alpha m_renderer;
agg::gamma_lut<> m_gamma_lut;
blender_gamma_type m_blender;
};
FontRenderer *FontRendererNew(unsigned int flags, float gamma) {
bool hinting = ((flags & FONT_RENDERER_HINTING) != 0);
bool kerning = ((flags & FONT_RENDERER_KERNING) != 0);
return new FontRendererImpl(hinting, kerning, gamma);
}
void FontRendererFree(FontRenderer *font_renderer) {
delete font_renderer; delete font_renderer;
} }
int FontRendererLoadFont(FontRenderer *fr_, const char *filename) { int FontRendererLoadFont(FontRenderer *font_renderer, const char *filename) {
font_renderer_alpha *font_renderer = (font_renderer_alpha *) fr_; bool success = font_renderer->renderer_alpha().load_font(filename);
bool success = font_renderer->load_font(filename);
return (success ? 0 : 1); return (success ? 0 : 1);
} }
int FontRendererGetFontHeight(FontRenderer *fr_, float size) { int FontRendererGetFontHeight(FontRenderer *font_renderer, float size) {
font_renderer_alpha *font_renderer = (font_renderer_alpha *) fr_; font_renderer_alpha& renderer_alpha = font_renderer->renderer_alpha();
double ascender, descender; double ascender, descender;
font_renderer->get_font_vmetrics(ascender, descender); renderer_alpha.get_font_vmetrics(ascender, descender);
int face_height = font_renderer->get_face_height(); int face_height = renderer_alpha.get_face_height();
float scale = renderer_alpha.scale_for_em_to_pixels(size);
float scale = font_renderer->scale_for_em_to_pixels(size);
return int((ascender - descender) * face_height * scale + 0.5); return int((ascender - descender) * face_height * scale + 0.5);
} }
int FontRendererBakeFontBitmap(FontRenderer *fr_, int font_height, int FontRendererBakeFontBitmap(FontRenderer *font_renderer, int font_height,
void *pixels, int pixels_width, int pixels_height, void *pixels, int pixels_width, int pixels_height,
int first_char, int num_chars, GlyphBitmapInfo *glyphs) int first_char, int num_chars, GlyphBitmapInfo *glyphs)
{ {
font_renderer_alpha *font_renderer = (font_renderer_alpha *) fr_; font_renderer_alpha& renderer_alpha = font_renderer->renderer_alpha();
const int pixel_size = 1; const int pixel_size = 1;
memset(pixels, 0x00, pixels_width * pixels_height * pixel_size); memset(pixels, 0x00, pixels_width * pixels_height * pixel_size);
double ascender, descender; double ascender, descender;
font_renderer->get_font_vmetrics(ascender, descender); renderer_alpha.get_font_vmetrics(ascender, descender);
const int ascender_px = int(ascender * font_height + 0.5); const int ascender_px = int(ascender * font_height + 0.5);
const int descender_px = int(descender * font_height + 0.5); const int descender_px = int(descender * font_height + 0.5);
@ -74,7 +91,7 @@ int FontRendererBakeFontBitmap(FontRenderer *fr_, int font_height,
const int y_baseline = y - pad_y - font_height; const int y_baseline = y - pad_y - font_height;
double x_next = x, y_next = y_baseline; double x_next = x, y_next = y_baseline;
font_renderer->render_codepoint(ren_buf, font_height_reduced, text_color, x_next, y_next, codepoint); renderer_alpha.render_codepoint(ren_buf, font_height_reduced, text_color, x_next, y_next, codepoint);
int x_next_i = int(x_next + 1.0); int x_next_i = int(x_next + 1.0);
GlyphBitmapInfo& glyph_info = glyphs[i]; GlyphBitmapInfo& glyph_info = glyphs[i];
@ -134,16 +151,13 @@ void blend_solid_hspan(agg::rendering_buffer& rbuf, Blender& blender,
} }
} }
// destination implicitly BGRA32. Source implictly single-byte alpha coverage. // destination implicitly BGRA32. Source implictly single-byte renderer_alpha coverage.
void FontRendererBlendGamma(uint8_t *dst, int dst_stride, uint8_t *src, int src_stride, int region_width, int region_height, FontRendererColor color) { void FontRendererBlendGamma(FontRenderer *font_renderer, uint8_t *dst, int dst_stride, uint8_t *src, int src_stride, int region_width, int region_height, FontRendererColor color) {
typedef agg::blender_rgb_gamma<agg::rgba8, agg::order_bgra, agg::gamma_lut<> > blender_type; blender_gamma_type& blender = font_renderer->blender();
agg::rendering_buffer dst_ren_buf(dst, region_width, region_height, dst_stride); agg::rendering_buffer dst_ren_buf(dst, region_width, region_height, dst_stride);
const agg::rgba8 color_a(color.r, color.g, color.b); const agg::rgba8 color_a(color.r, color.g, color.b);
// FIXME: move blender object inside FontRenderer.
blender_type blender;
blender.gamma(1.8);
for (int x = 0, y = 0; y < region_height; y++) { for (int x = 0, y = 0; y < region_height; y++) {
agg::int8u *covers = src + y * src_stride; agg::int8u *covers = src + y * src_stride;
blend_solid_hspan<blender_type>(dst_ren_buf, blender, x, y, region_width, color_a, covers); blend_solid_hspan<blender_gamma_type>(dst_ren_buf, blender, x, y, region_width, color_a, covers);
} }
} }

View File

@ -13,8 +13,8 @@ typedef struct {
float xoff, yoff, xadvance; float xoff, yoff, xadvance;
} GlyphBitmapInfo; } GlyphBitmapInfo;
struct FontRenderer_; struct FontRendererImpl;
typedef struct FontRenderer_ FontRenderer; typedef struct FontRendererImpl FontRenderer;
enum { enum {
FONT_RENDERER_HINTING = 1 << 0, FONT_RENDERER_HINTING = 1 << 0,
@ -25,7 +25,7 @@ typedef struct {
uint8_t r, g, b; uint8_t r, g, b;
} FontRendererColor; } FontRendererColor;
FontRenderer * FontRendererNew(unsigned int flags); FontRenderer * FontRendererNew(unsigned int flags, float gamma);
void FontRendererFree(FontRenderer *); void FontRendererFree(FontRenderer *);
@ -37,7 +37,8 @@ int FontRendererBakeFontBitmap(FontRenderer *, int font_height,
void *pixels, int pixels_width, int pixels_height, void *pixels, int pixels_width, int pixels_height,
int first_char, int num_chars, GlyphBitmapInfo *glyph_info); int first_char, int num_chars, GlyphBitmapInfo *glyph_info);
void FontRendererBlendGamma(uint8_t *dst, int dst_stride, void FontRendererBlendGamma(FontRenderer *,
uint8_t *dst, int dst_stride,
uint8_t *src, int src_stride, uint8_t *src, int src_stride,
int region_width, int region_height, int region_width, int region_height,
FontRendererColor color); FontRendererColor color);

View File

@ -177,7 +177,8 @@ RenFont* ren_load_font(const char *filename, float size) {
font = check_alloc(calloc(1, sizeof(RenFont))); font = check_alloc(calloc(1, sizeof(RenFont)));
font->size = size; font->size = size;
font->renderer = FontRendererNew(FONT_RENDERER_HINTING); const float gamma = 1.8;
font->renderer = FontRendererNew(FONT_RENDERER_HINTING, gamma);
if (FontRendererLoadFont(font->renderer, filename)) { if (FontRendererLoadFont(font->renderer, filename)) {
free(font); free(font);
return NULL; return NULL;
@ -319,7 +320,7 @@ void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color)
} }
} }
static void ren_draw_coverage_with_color(RenCoverageImage *image, RenRect *sub, int x, int y, RenColor color) { static void ren_draw_coverage_with_color(FontRenderer *renderer, RenCoverageImage *image, RenRect *sub, int x, int y, RenColor color) {
if (color.a == 0) { return; } if (color.a == 0) { return; }
clip_point_inside_rect(&x, &y, sub); clip_point_inside_rect(&x, &y, sub);
@ -336,6 +337,7 @@ static void ren_draw_coverage_with_color(RenCoverageImage *image, RenRect *sub,
d += x + y * surf->w; d += x + y * surf->w;
const int surf_pixel_size = 4; const int surf_pixel_size = 4;
FontRendererBlendGamma( FontRendererBlendGamma(
renderer,
(uint8_t *) d, surf->w * surf_pixel_size, (uint8_t *) d, surf->w * surf_pixel_size,
s, image->width, s, image->width,
sub->width, sub->height, sub->width, sub->height,
@ -354,7 +356,7 @@ int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color)
rect.y = g->y0; rect.y = g->y0;
rect.width = g->x1 - g->x0; rect.width = g->x1 - g->x0;
rect.height = g->y1 - g->y0; rect.height = g->y1 - g->y0;
ren_draw_coverage_with_color(set->coverage, &rect, x + g->xoff, y + g->yoff, color); ren_draw_coverage_with_color(font->renderer, set->coverage, &rect, x + g->xoff, y + g->yoff, color);
x += g->xadvance; x += g->xadvance;
} }
return x; return x;

View File

@ -60,9 +60,11 @@ RenFont* ren_load_font_agg(const char *filename, float size) {
font = check_alloc(calloc(1, sizeof(RenFont))); font = check_alloc(calloc(1, sizeof(RenFont)));
font->size = size; font->size = size;
font->renderer = FontRendererNew(FONT_RENDERER_HINTING); font->renderer = FontRendererNew(FONT_RENDERER_HINTING, 1.8);
// FIXME check for errors if (FontRendererLoadFont(font->renderer, filename)) {
FontRendererLoadFont(font->renderer, filename); free(font);
return NULL;
}
font->height = FontRendererGetFontHeight(font->renderer, size); font->height = FontRendererGetFontHeight(font->renderer, size);
fprintf(stderr, "Font height: %d\n", font->height); fprintf(stderr, "Font height: %d\n", font->height);