From ae032cd1851469aa63158b526103ac97fc95742a Mon Sep 17 00:00:00 2001 From: Francesco Abbate Date: Tue, 2 Jun 2020 17:18:52 +0200 Subject: [PATCH] Ember blender with gamma correction into FontRenderer --- src/font_renderer.cpp | 64 ++++++++++++++++++++++-------------- src/font_renderer.h | 9 ++--- src/renderer.c | 8 +++-- tests/agg_font_render_test.c | 8 +++-- 4 files changed, 54 insertions(+), 35 deletions(-) diff --git a/src/font_renderer.cpp b/src/font_renderer.cpp index d62800b9..aa6e6a5b 100644 --- a/src/font_renderer.cpp +++ b/src/font_renderer.cpp @@ -6,45 +6,62 @@ #include "font_renderer_alpha.h" -FontRenderer *FontRendererNew(unsigned int flags) { +typedef agg::blender_rgb_gamma > blender_gamma_type; + +class FontRendererImpl { +public: + 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); + } + + font_renderer_alpha& renderer_alpha() { return m_renderer; } + 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); - font_renderer_alpha *font_renderer = new font_renderer_alpha(hinting, kerning); - return (FontRenderer *) font_renderer; + return new FontRendererImpl(hinting, kerning, gamma); } -void FontRendererFree(FontRenderer *fr_) { - font_renderer_alpha *font_renderer = (font_renderer_alpha *) fr_; +void FontRendererFree(FontRenderer *font_renderer) { delete font_renderer; } -int FontRendererLoadFont(FontRenderer *fr_, const char *filename) { - font_renderer_alpha *font_renderer = (font_renderer_alpha *) fr_; - bool success = font_renderer->load_font(filename); +int FontRendererLoadFont(FontRenderer *font_renderer, const char *filename) { + bool success = font_renderer->renderer_alpha().load_font(filename); return (success ? 0 : 1); } -int FontRendererGetFontHeight(FontRenderer *fr_, float size) { - font_renderer_alpha *font_renderer = (font_renderer_alpha *) fr_; +int FontRendererGetFontHeight(FontRenderer *font_renderer, float size) { + font_renderer_alpha& renderer_alpha = font_renderer->renderer_alpha(); double ascender, descender; - font_renderer->get_font_vmetrics(ascender, descender); - int face_height = font_renderer->get_face_height(); - - float scale = font_renderer->scale_for_em_to_pixels(size); + renderer_alpha.get_font_vmetrics(ascender, descender); + int face_height = renderer_alpha.get_face_height(); + float scale = renderer_alpha.scale_for_em_to_pixels(size); 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, 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; memset(pixels, 0x00, pixels_width * pixels_height * pixel_size); 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 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; 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); 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. -void FontRendererBlendGamma(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 > blender_type; +// destination implicitly BGRA32. Source implictly single-byte renderer_alpha coverage. +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) { + blender_gamma_type& blender = font_renderer->blender(); agg::rendering_buffer dst_ren_buf(dst, region_width, region_height, dst_stride); 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++) { agg::int8u *covers = src + y * src_stride; - blend_solid_hspan(dst_ren_buf, blender, x, y, region_width, color_a, covers); + blend_solid_hspan(dst_ren_buf, blender, x, y, region_width, color_a, covers); } } diff --git a/src/font_renderer.h b/src/font_renderer.h index 904d6844..78c9f0a0 100644 --- a/src/font_renderer.h +++ b/src/font_renderer.h @@ -13,8 +13,8 @@ typedef struct { float xoff, yoff, xadvance; } GlyphBitmapInfo; -struct FontRenderer_; -typedef struct FontRenderer_ FontRenderer; +struct FontRendererImpl; +typedef struct FontRendererImpl FontRenderer; enum { FONT_RENDERER_HINTING = 1 << 0, @@ -25,7 +25,7 @@ typedef struct { uint8_t r, g, b; } FontRendererColor; -FontRenderer * FontRendererNew(unsigned int flags); +FontRenderer * FontRendererNew(unsigned int flags, float gamma); void FontRendererFree(FontRenderer *); @@ -37,7 +37,8 @@ int FontRendererBakeFontBitmap(FontRenderer *, int font_height, void *pixels, int pixels_width, int pixels_height, 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, int region_width, int region_height, FontRendererColor color); diff --git a/src/renderer.c b/src/renderer.c index aa053667..4653aa74 100644 --- a/src/renderer.c +++ b/src/renderer.c @@ -177,7 +177,8 @@ RenFont* ren_load_font(const char *filename, float size) { font = check_alloc(calloc(1, sizeof(RenFont))); 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)) { free(font); 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; } 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; const int surf_pixel_size = 4; FontRendererBlendGamma( + renderer, (uint8_t *) d, surf->w * surf_pixel_size, s, image->width, 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.width = g->x1 - g->x0; 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; } return x; diff --git a/tests/agg_font_render_test.c b/tests/agg_font_render_test.c index b31b5912..2ae900b9 100644 --- a/tests/agg_font_render_test.c +++ b/tests/agg_font_render_test.c @@ -60,9 +60,11 @@ RenFont* ren_load_font_agg(const char *filename, float size) { font = check_alloc(calloc(1, sizeof(RenFont))); font->size = size; - font->renderer = FontRendererNew(FONT_RENDERER_HINTING); - // FIXME check for errors - FontRendererLoadFont(font->renderer, filename); + font->renderer = FontRendererNew(FONT_RENDERER_HINTING, 1.8); + if (FontRendererLoadFont(font->renderer, filename)) { + free(font); + return NULL; + } font->height = FontRendererGetFontHeight(font->renderer, size); fprintf(stderr, "Font height: %d\n", font->height);