WIP testing ahead of time coverage convolution
This commit is contained in:
parent
baf8cec837
commit
2e2db2d690
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue