0

I am drawing some random rectangles via cairo in its image surface, scaling and translating it and displaying the result using

unsigned char* data = cairo_image_surface_get_data(surface);

but the rectangles seem blurred: (I could not post the screenshot)

Corners are (probably) not mapped to integer coordinates. The texture containing data is the same size and format with the surface and I have already played with AntiAliasing settings (text display is even more blurry!!). What should I do to map the resulting shapes to integer coordinates and improve quality (without using super-sampling and without dropping scaling-translation)?

Edit: I used the below code (with and without the third line) and it didn't work!:

cairo_save(cr);    
cairo_identity_matrix(cr);
cairo_translate(cr, 0.5, 0.5);
cairo_scale(cr, size.width, size.height);
cairo_set_antialias(cr, CAIRO_ANTIALIAS_GOOD);
(make the drawing!!)
cairo_restore(cr);

Edit2: I used the snapping fun. (after all transformations code), but it also did not work:

double szero1 = zero,szero2 = zero, sone1 = one, sone2 = one;
snapToPixel(cr, &szero1, &szero2);
snapToPixel(cr, &sone1, &sone2);
cairo_rectangle (cr, szero1, szero2, sone1, sone2);
user3648895
  • 395
  • 10
  • 20

3 Answers3

0

Without preprocessing the coordinate there is no way to force cairo to snap to the nearest integer-pixel-coordinate.

void snapToPixel(cairo_t *cr, float *x, float *y) {
     cairo_user_to_device (cr, x, y);
     *x = round(*x);
     *y = round(*y);
     cairo_device_to_user (cr, x, y);
}

Stroke-widths will have the same problem (+different in x, y if width != height).

More information at http://cairographics.org/FAQ/#sharp_lines

KoKuToru
  • 4,055
  • 2
  • 20
  • 21
  • Unfortunately, it did not work (@see the Edit); I am scaling and translating before the draw... – user3648895 May 18 '14 at 19:50
  • @user3648895 based on you Edit, your coordinates (for drawing) are from 0.0-1.0 ? – KoKuToru May 18 '14 at 19:56
  • Yes, I make all drawings in unit coordinates and scale-translate them when needed; I expect cairo to handle this as it is a vector library.. By the way, Thank you for your interest.. – user3648895 May 18 '14 at 19:59
0

I used round numbers, but it still blurry

func (me *canvas) DrawRectF(left, top, right, bottom float32, paint *Paint) {
    if right <= left || bottom <= top {
        return
    }

    C.cairo_set_antialias(me.ptr, C.CAIRO_ANTIALIAS_NONE)

    fix := paint.Style == STROKE && int32(paint.Width)%2 != 0
    fix = false
    if fix {
        me.Save()
        me.TranslateF(0.5, 0.5)

    }
    C.cairo_rectangle(me.ptr, 100, 100, 500, 500)
    C.cairo_rectangle(me.ptr, 110, 110, 510, 510)
    me.drawPaint(paint)

    if fix {
        me.Restore()
    }
}

this is a line in cairo
enter image description here

this is a line in code editor
enter image description here

how should I do to draw a sharp with single-pixel-wide line like code editor?

sword-yang
  • 71
  • 5
  • Is not cairo's problem, it is SDL2's problem. add `SDL_WINDOW_ALLOW_HIGHDPI` when `CreateWindow` will be ok – sword-yang May 04 '20 at 15:19
0

I know this is not cairo's problem but SDL2, SDL2 need to set SDL_WINDOW_ALLOW_HIGHDPI to show a single pixel line, but I found anthor problem, and this time I use cairo_surface_write_to_png without SDL2, the line is clear and bright, but the text is blurry. the blew picture is a text compare between cairo and other apps. enter image description here

cairo_surface_t *surface;     
    cairo_t *cr;                  
    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 100, 100);
    cr = cairo_create (surface);

    cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
    cairo_paint(cr);


    cairo_text_extents_t extents;
    const char *utf8 = "bulrry text";
    double x,y;
    printf("x = %f, y = %f ", x, y);
    snapToPixel(cr, &x, &y);
    printf("x = %f, y = %f ", x, y);

    // cairo_set_antialias(cr, CAIRO_ANTIALIAS_BEST);
    cairo_select_font_face (cr, "mono",
        CAIRO_FONT_SLANT_NORMAL,
        CAIRO_FONT_WEIGHT_NORMAL);

    cairo_set_font_size (cr, 14.0);
    cairo_text_extents (cr, utf8, &extents);
    x = 128.0-(extents.width/2 );
    y = 128.0-(extents.height/2 );

    cairo_move_to (cr, 0, 15);
    cairo_set_source_rgba (cr, 1, 1, 1, 1);
    cairo_show_text (cr, utf8);

    /* draw helping lines */
    cairo_set_source_rgb (cr, 1, 0, 0);
    cairo_set_line_width (cr, 1.0);
    cairo_rectangle(cr, 20.5, 20.5, 50, 50);
    cairo_stroke (cr);
    cairo_surface_write_to_png(surface , "./a.png");
sword-yang
  • 71
  • 5
  • it can be an issue about the (underlying) font drawing library, like freetype. Quality font/glyph rendering requires techniques like Anti Aliasing, Sub-Pixel Rendering (LCD), ... etc. – user3648895 May 06 '20 at 12:46