Ember blender with gamma correction into FontRenderer
This commit is contained in:
parent
bc74b2860d
commit
ae032cd185
|
@ -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;
|
||||||
|
|
||||||
|
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 hinting = ((flags & FONT_RENDERER_HINTING) != 0);
|
||||||
bool kerning = ((flags & FONT_RENDERER_KERNING) != 0);
|
bool kerning = ((flags & FONT_RENDERER_KERNING) != 0);
|
||||||
font_renderer_alpha *font_renderer = new font_renderer_alpha(hinting, kerning);
|
return new FontRendererImpl(hinting, kerning, gamma);
|
||||||
return (FontRenderer *) font_renderer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontRendererFree(FontRenderer *fr_) {
|
void FontRendererFree(FontRenderer *font_renderer) {
|
||||||
font_renderer_alpha *font_renderer = (font_renderer_alpha *) fr_;
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue