WIP testing ahead of time coverage convolution

This commit is contained in:
Francesco Abbate 2020-06-05 15:27:55 +02:00
parent baf8cec837
commit 2e2db2d690
1 changed files with 51 additions and 33 deletions

View File

@ -59,11 +59,11 @@ int FontRendererGetFontHeight(FontRenderer *font_renderer, float size) {
return int((ascender - descender) * face_height * scale + 0.5); return int((ascender - descender) * face_height * scale + 0.5);
} }
static void glyph_trim_rect(agg::rendering_buffer& ren_buf, GlyphBitmapInfo *gli, int subpixel_scale) { static void glyph_trim_rect(agg::rendering_buffer& ren_buf, GlyphBitmapInfo& gli, int subpixel_scale) {
const int height = ren_buf.height(); const int height = ren_buf.height();
int x0 = gli->x0 * subpixel_scale, x1 = gli->x1 * subpixel_scale; int x0 = gli.x0 * subpixel_scale, x1 = gli.x1 * subpixel_scale;
int y0 = gli->y0, y1 = gli->y1; int y0 = gli.y0, y1 = gli.y1;
for (int y = gli->y0; y < gli->y1; y++) { for (int y = gli.y0; y < gli.y1; y++) {
uint8_t *row = ren_buf.row_ptr(height - 1 - y); uint8_t *row = ren_buf.row_ptr(height - 1 - y);
unsigned int row_bitsum = 0; unsigned int row_bitsum = 0;
for (int x = x0; x < x1; x++) { for (int x = x0; x < x1; x++) {
@ -75,7 +75,7 @@ static void glyph_trim_rect(agg::rendering_buffer& ren_buf, GlyphBitmapInfo *gli
break; break;
} }
} }
for (int y = gli->y1 - 1; y >= y0; y--) { for (int y = gli.y1 - 1; y >= y0; y--) {
uint8_t *row = ren_buf.row_ptr(height - 1 - y); uint8_t *row = ren_buf.row_ptr(height - 1 - y);
unsigned int row_bitsum = 0; unsigned int row_bitsum = 0;
for (int x = x0; x < x1; x++) { for (int x = x0; x < x1; x++) {
@ -87,7 +87,7 @@ static void glyph_trim_rect(agg::rendering_buffer& ren_buf, GlyphBitmapInfo *gli
break; break;
} }
} }
for (int x = gli->x0 * subpixel_scale; x < gli->x1 * subpixel_scale; x += subpixel_scale) { for (int x = gli.x0 * subpixel_scale; x < gli.x1 * subpixel_scale; x += subpixel_scale) {
unsigned int xaccu = 0; unsigned int xaccu = 0;
for (int y = y0; y < y1; y++) { for (int y = y0; y < y1; y++) {
uint8_t *row = ren_buf.row_ptr(height - 1 - y); uint8_t *row = ren_buf.row_ptr(height - 1 - y);
@ -101,7 +101,7 @@ static void glyph_trim_rect(agg::rendering_buffer& ren_buf, GlyphBitmapInfo *gli
break; break;
} }
} }
for (int x = (gli->x1 - 1) * subpixel_scale; x >= x0; x -= subpixel_scale) { for (int x = (gli.x1 - 1) * subpixel_scale; x >= x0; x -= subpixel_scale) {
unsigned int xaccu = 0; unsigned int xaccu = 0;
for (int y = y0; y < y1; y++) { for (int y = y0; y < y1; y++) {
uint8_t *row = ren_buf.row_ptr(height - 1 - y); uint8_t *row = ren_buf.row_ptr(height - 1 - y);
@ -115,12 +115,32 @@ static void glyph_trim_rect(agg::rendering_buffer& ren_buf, GlyphBitmapInfo *gli
break; break;
} }
} }
gli->xoff += (x0 / subpixel_scale) - gli->x0; gli.xoff += (x0 / subpixel_scale) - gli.x0;
gli->yoff += (y0 - gli->y0); gli.yoff += (y0 - gli.y0);
gli->x0 = x0 / subpixel_scale; gli.x0 = x0 / subpixel_scale;
gli->y0 = y0; gli.y0 = y0;
gli->x1 = x1 / subpixel_scale; gli.x1 = x1 / subpixel_scale;
gli->y1 = y1; gli.y1 = y1;
}
static void glyph_lut_convolution(agg::rendering_buffer ren_buf, agg::lcd_distribution_lut& lcd_lut, GlyphBitmapInfo& gli) {
const int subpixel = 3;
const int x0 = gli.x0, y0 = gli.y0, x1 = gli.x1, y1 = gli.y1;
const int len = (x1 - x0) * subpixel;
const int height = ren_buf.height();
agg::int8u *covers_buf = new agg::int8u[len + 2 * subpixel];
memset(covers_buf, 0, len + 2 * subpixel);
for (int y = y0; y < y1; y++) {
agg::int8u *covers = ren_buf.row_ptr(height - 1 - y) + x0 * subpixel;
memcpy(covers_buf + subpixel, covers, len);
for (int x = x0 - 1; x < x1 + 1; x++) {
for (int i = 0; i < subpixel; i++) {
const int cx = (x - x0) * subpixel + i;
covers[cx] = lcd_lut.convolution(covers_buf + subpixel, cx, -2, len + 2 - 1);
}
}
}
delete [] covers_buf;
} }
static int ceil_to_multiple(int n, int p) { static int ceil_to_multiple(int n, int p) {
@ -145,6 +165,7 @@ int FontRendererBakeFontBitmap(FontRenderer *font_renderer, int font_height,
const int pad_y = font_height / 10; const int pad_y = font_height / 10;
const int y_step = font_height + 2 * pad_y; const int y_step = font_height + 2 * pad_y;
agg::lcd_distribution_lut& lcd_lut = font_renderer->lcd_distribution_lut();
agg::rendering_buffer ren_buf((agg::int8u *) pixels, pixels_width * subpixel_scale, pixels_height, -pixels_width * subpixel_scale * pixel_size); agg::rendering_buffer ren_buf((agg::int8u *) pixels, pixels_width * subpixel_scale, pixels_height, -pixels_width * subpixel_scale * pixel_size);
// When using subpixel font rendering it is needed to leave a padding pixel on the left and on the right. // When using subpixel font rendering it is needed to leave a padding pixel on the left and on the right.
// Since each pixel is composed by n subpixel we set below x_start to subpixel_scale instead than zero. // Since each pixel is composed by n subpixel we set below x_start to subpixel_scale instead than zero.
@ -173,18 +194,22 @@ int FontRendererBakeFontBitmap(FontRenderer *font_renderer, int font_height,
renderer_alpha.render_codepoint(ren_buf, font_height_reduced, text_color, x_next, y_next, codepoint, subpixel_scale); renderer_alpha.render_codepoint(ren_buf, font_height_reduced, text_color, x_next, y_next, codepoint, subpixel_scale);
int x_next_i = (subpixel_scale == 1 ? int(x_next + 1.0) : ceil_to_multiple(x_next + 0.5, subpixel_scale)); int x_next_i = (subpixel_scale == 1 ? int(x_next + 1.0) : ceil_to_multiple(x_next + 0.5, subpixel_scale));
// Below x and x_next_i will always be integer multiples of subpixel_scale.
GlyphBitmapInfo& glyph_info = glyphs[i]; GlyphBitmapInfo& glyph_info = glyphs[i];
glyph_info.x0 = x / subpixel_scale; glyph_info.x0 = x / subpixel_scale;
glyph_info.y0 = pixels_height - (y_baseline + ascender_px + pad_y); glyph_info.y0 = pixels_height - 1 - (y_baseline + ascender_px + pad_y); // FIXME: add -1 ?
glyph_info.x1 = x_next_i / subpixel_scale; glyph_info.x1 = x_next_i / subpixel_scale;
glyph_info.y1 = pixels_height - (y_baseline + descender_px - pad_y); glyph_info.y1 = pixels_height - 1 - (y_baseline + descender_px - pad_y); // FIXME: add -1 ?
glyph_info.xoff = 0; glyph_info.xoff = 0;
glyph_info.yoff = -pad_y; glyph_info.yoff = -pad_y;
glyph_info.xadvance = (x_next - x) / subpixel_scale; glyph_info.xadvance = (x_next - x) / subpixel_scale;
glyph_trim_rect(ren_buf, &glyph_info, subpixel_scale); glyph_lut_convolution(ren_buf, lcd_lut, glyph_info);
glyph_trim_rect(ren_buf, glyph_info, subpixel_scale);
// FIXME: check if we don't need to add to x.
// When subpixel is activated we need at least two more subpixels on the right.
x = x_next_i; x = x_next_i;
} }
return res; return res;
@ -221,29 +246,21 @@ void blend_solid_hspan(agg::rendering_buffer& rbuf, blender_gamma_type& blender,
while(--len); while(--len);
} }
} }
#if 0
static int floor_div(int a, int b) { static int floor_div(int a, int b) {
if (a < 0) { if (a < 0) {
return -((-a + b - 1) / b); return -((-a + b - 1) / b);
} }
return a / b; return a / b;
} }
#endif
void blend_solid_hspan_rgb_subpixel(agg::rendering_buffer& rbuf, agg::gamma_lut<>& gamma, agg::lcd_distribution_lut& lcd_lut, void blend_solid_hspan_rgb_subpixel(agg::rendering_buffer& rbuf, agg::gamma_lut<>& gamma, agg::lcd_distribution_lut& lcd_lut,
int x_lcd, int y, unsigned len, int x, int y, unsigned len,
const agg::rgba8& c, const agg::rgba8& c,
const agg::int8u* covers) const agg::int8u* covers)
{ {
// cx being negative here and cx_max greater than 'len' means we will const int x_min = x;
// adress the 'covers' array beyond its formal limits here [0, len-1] by -subpixel_scale on the const int x_max = x + len / 3;
// left and +subpixel_scale on the right.
// We assume it is safe to do so because the data are coming from FontRendererBakeFontBitmap
// and this latter function leaves three padding pixels on the left and on the right of the buffer.
int cx = -2;
int cx_max = len + 1;
const int x_min = floor_div(x_lcd + cx, 3);
const int x_max = floor_div(x_lcd + cx_max, 3);
const int pixel_size = 4; const int pixel_size = 4;
const agg::int8u rgb[3] = { c.r, c.g, c.b }; const agg::int8u rgb[3] = { c.r, c.g, c.b };
@ -251,12 +268,13 @@ void blend_solid_hspan_rgb_subpixel(agg::rendering_buffer& rbuf, agg::gamma_lut<
// Indexes to adress RGB colors in a BGRA32 format. // Indexes to adress RGB colors in a BGRA32 format.
const int pixel_index[3] = {2, 1, 0}; const int pixel_index[3] = {2, 1, 0};
for (int x = x_min; x <= x_max; x++) for (int xp = x_min; xp <= x_max; xp++)
{ {
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
int new_cx = x * 3 - x_lcd + i; int cx = xp * 3 - x + i;
unsigned c_conv = lcd_lut.convolution(covers, new_cx, 0, len - 1); // unsigned c_conv = lcd_lut.convolution(covers, new_cx, 0, len - 1);
unsigned alpha = (c_conv + 1) * (c.a + 1); unsigned cover_value = covers[cx];
unsigned alpha = (cover_value + 1) * (c.a + 1);
unsigned dst_col = gamma.dir(rgb[i]); unsigned dst_col = gamma.dir(rgb[i]);
unsigned src_col = gamma.dir(*(p + pixel_index[i])); unsigned src_col = gamma.dir(*(p + pixel_index[i]));
*(p + pixel_index[i]) = gamma.inv((((dst_col - src_col) * alpha) + (src_col << 16)) >> 16); *(p + pixel_index[i]) = gamma.inv((((dst_col - src_col) * alpha) + (src_col << 16)) >> 16);