diff --git a/main.c b/main.c index a0403ab..020e471 100644 --- a/main.c +++ b/main.c @@ -206,6 +206,14 @@ static Window window; static GC default_gc; static XImage* xwindow_buffer; +static int +clamp_u32(u32 val, u32 cap) +{ + u32 result = val; + if (val > cap) result = cap; + return(result); +} + static f32 abs_f32(f32 v) { @@ -438,38 +446,79 @@ render_glyph(struct glyph g, struct line_contour *lines, { int gwidth = round_f32((g.xmax - g.xmin) * scale) + 1; int gheight = round_f32((g.ymax - g.ymin) * scale) + 1; + int oversample_y = 4; + f32 norm = 1.0f / (oversample_y + 1); struct intersection *intersections = malloc(lines->from[lines->ncontours] * sizeof(struct intersection)); for (int y = 0; y < gheight && (at_y + y < height); ++y) { - u32 ncross = intersect_glyph(lines, y, intersections); - if (ncross) { - sort_intersections(intersections, ncross); - - int state = 0; + for (int yy = 1; yy <= oversample_y; ++yy) { - for (int i = 0; i < ncross - 1; ++i) { - struct intersection inter = intersections[i]; - struct intersection next_inter = intersections[i + 1]; + u32 ncross = intersect_glyph(lines, y + norm * yy, intersections); + if (ncross) { + sort_intersections(intersections, ncross); - state += inter.dir; + int state = 0; - if (state != 0) { - f32 x0 = inter.x; - f32 x1 = next_inter.x; + for (int i = 0; i < ncross - 1; ++i) { + struct intersection inter = intersections[i]; + struct intersection next_inter = intersections[i + 1]; + + state += inter.dir; - for (int x = x0; x < x1; ++x) { - pixels[(y + at_y) * width + (at_x + x)] = 0x00; + if (state != 0) { + f32 x0 = inter.x; + f32 x1 = next_inter.x; + + int x_from = x0; + int x_to = x1; + + int start_enter = (state - inter.dir == 0); + int end_enter = (state + next_inter.dir != 0); + + u32 start_brightness; + u32 end_brightness; + + if (start_enter) { + start_brightness = (x_from + 1 - x0) * (255.99f / oversample_y); + } else { + start_brightness = (x0 - x_from) * (255.99f / oversample_y); + } + + if (end_enter) { + end_brightness = (x_to + 1 - x1) * (255.99f / oversample_y); + } else { + end_brightness = (x1 - x_to) * (255.99f / oversample_y); + } + + for (int x = x_from; x < x_to; ++x) { + pixels[(y + at_y) * width + (at_x + x)] += 255.99f / oversample_y; + pixels[(y + at_y) * width + (at_x + x)] = clamp_u32(pixels[(y + at_y) * width + (at_x + x)], 255); + } + + u32 new_start_brightness = clamp_u32(pixels[(y + at_y) * width + (at_x + x_from)] + start_brightness, 255); + u32 new_end_brightness = clamp_u32(pixels[(y + at_y) * width + (at_x + x_to)] + end_brightness, 255); + + pixels[(y + at_y) * width + (at_x + x_from)] = new_start_brightness; + pixels[(y + at_y) * width + (at_x + x_to)] = new_end_brightness; } } } } - -#if DEBUG_SHOW_POINTS - _D_render_glyph_points(g, scale, pixels, width, height); -#endif } +#if 0 + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + if (pixels[y * width + x] <= 255) { + u32 brightness = 255 - pixels[y * width + x]; + u32 white = 0xFF000000 | brightness << 16 | brightness << 8 | brightness; + pixels[y * width + x] = white; + } + } + } +#endif + free(intersections); } @@ -662,9 +711,9 @@ main(int argc, char **argv) for (;;) { - memset(pixels, 0xFFFFFFFF, width * height * 4); + memset(pixels, 0x00, width * height * 4); render_utf_string(font, 32, pixels, width, height, L"Привет, батя! Как поживаешь? Hello, Batya. Wazzaaap", 100, 100); - render_utf_string(font, 32, pixels, width, height, L"QQQQqqqqq", 100, 200); + render_utf_string(font, 20, pixels, width, height, L"QQQQqqqqq", 100, 200); XPutImage(display, window, default_gc, xwindow_buffer, 0, 0, 0, 0, width, height);