Clear cairo text in gtk_window - c

I'm have a trouble with a cairo text.
I write some lines in a gtk_window:
cr = gdk_cairo_create(window->window);
cairo_set_source_rgb(cr, 255, 255, 255);
cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(cr, 14.0);
cairo_move_to(cr, 90.0, 85.0);
cairo_show_text(cr, "Terror");
cairo_set_font_size(cr, 12.0);
cairo_set_source_rgb(cr, 30, 254, 145);
cairo_move_to(cr, 90.0, 105.0);
cairo_show_text(cr, "Underdogs");
cairo_move_to(cr, 90.0, 120.0);
cairo_show_text(cr, "Disziplin");
cairo_destroy(cr);
The problem is that this text should be dynamic, but if I call more than one time the function that writes the text, lines is overlapped.
Is there any method that flushes the previous text?
Thanks!

You have to overwrite the text with the background color :)

If you want to clear your surface to a uniform, opaque color then it is quite straightforward:
/* Set surface to opaque color (r, g, b) */
cairo_set_source_rgb (cr, r, g, b);
cairo_paint (cr);
However, what if you want to clear the surface to something other than an opaque color. Simply modifying the above code to use "cairo_set_source_rgba (cr, 0, 0, 0, 0);" will not work since cairo uses the OVER compositing operator by default, and blending something entirely transparent OVER something else has no effect at all. Instead, you can use the SOURCE operator which copies both color and alpha values directly from the source to the destination instead of blending:
/* Set surface to translucent color (r, g, b, a) */
cairo_set_source_rgba (cr, r, g, b, a);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
Of course, you won't want to forget to set the default CAIRO_OPERATOR_OVER again when you're finished. And the most convenient habit for doing that is to just use cairo_save/cairo_restore around the whole block:
/* Set surface to translucent color (r, g, b, a) without disturbing graphics state. */
cairo_save (cr);
cairo_set_source_rgba (cr, r, g, b, a);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (cr);
cairo_restore (cr);
Finally, to clear a surface to all transparent, one could simply use CAIRO_OPERATOR_CLEAR instead of CAIRO_OPERATOR_SOURCE, in which case the call to cairo_set_source_rgba would not be needed at all, (the CLEAR operator always sets the destination to 0 in every channel regardless of what the source pattern contains). But the above approach with CAIRO_OPERATOR_SOURCE is a more general way to clear the surface since it allows for "clearing" to a translucent color such as 50% red rather than just clearing to entirely transparent.
source: https://www.cairographics.org/FAQ/#clear_a_surface

Related

Scale part of pixbuf acording scale factor in cairo

I have a surface created from pixbuf
gint scale = gtk_widget_get_scale_factor (drawing_area);
cairo_surface_t surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, scale, gtk_widget_get_window (drawing_area));
I want to draw a part of this surface in drawing area but scaled if scale changed
#define DIGIT_WIDTH 20
#define DIGIT_HEIGTH 30
/* same code */
int width = gtk_widget_get_allocated_width (drawing_area);
cairo_set_source_surface (cr, surface, width - DIGIT_WIDTH, 5);
cairo_rectangle (cr, width - DIGIT_WIDTH, 5, DIGIT_WIDTH, DIGIT_HEIGTH);
cairo_fill (cr);
How can I apply scale factor to DIGIT_WIDTH and DIGIT_HEIGTH?
If I understood you correctly:
int width = gtk_widget_get_allocated_width (drawing_area);
cairo_rectangle (cr, width - DIGIT_WIDTH, 5, DIGIT_WIDTH, DIGIT_HEIGTH);
cairo_scale(cr, scale, scale);
cairo_set_source_surface (cr, pixbuf, width - DIGIT_WIDTH, 5);
cairo_fill (cr);
It might be that you need to "unapply" the scaling to the source. I'm not sure right now and too lazy to test:
cairo_set_source_surface (cr, pixbuf, (width - DIGIT_WIDTH) / (double) scale, 5. / scale);

Empty output png file form Cairo

I've render the hello example for C. I mean, the minimal C program using Cairo showing Here.
However when I try to render this:
#include <cairo.h>
int main(void){
/* Where we gonna draw. The image to print. */
cairo_surface_t *surface;
/* The context. The printed layer by a surface */
cairo_t *cr;
/* The format (in this case ARGB), width and height of surface */
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 120, 120);
/* The context behind of surface */
cr = cairo_create(surface);
/* void cairo_set_source_rgb(cairo_t *cr, double red, double green, double blue); */
cairo_set_source_rgb(cr, 0, 0, 0);
/* void cairo_move_to(cairo_t *cr, double x, double y); */
/* After this call the current point will be (x,y). */
cairo_move_to (cr, 0, 0);
/* void cairo_line_to(cairo_t *cr, double x, double y); */
/* Adds a line to the path from the current position (x,y). After this call the current point will be (x,y). */
/* Must be a current point, otherwise the beahavior gonna be like move_to */
cairo_line_to (cr, 1, 1);
cairo_move_to (cr, 1, 0);
cairo_line_to (cr, 0, 1);
/* void cairo_set_line_width(cairo_t *cr, double width); */
/* Sets the current line width within the cairo context. The line width value specifies the diameter of a pen is circular */
cairo_set_line_width (cr, 0.2);
/* void cairo_stroke(cairo_t *cr); */
/* A drawing operator that strokes the current path according to the current line width, line join, line cap, and dash settings. */
cairo_stroke (cr);
/* void cairo_rectangle(cairo_t *cr, double x, double y, double width, double height); */
/* Adds a closed sub-path rectangle of the given size to the current path at position (x,y) in user-space coordinates. */
/* This function is logically equivalent to:
* cairo_move_to (cr, x, y);
* cairo_rel_line_to (cr, width, 0);
* cairo_rel_line_to (cr, 0, height);
* cairo_rel_line_to (cr, -width, 0);
* cairo_close_path (cr);
* *************************************/
cairo_rectangle (cr, 0, 0, 0.5, 0.5);
/* cairo_set_source_rgba(cairo_t *cr, double red, double green, double blue, double alpha); */
/* Sets the source pattern within cr to a translucent color. This color will then be used for any subsequent drawing operation
* until a new source pattern is set.
* The color and alpha components are floating point numbers in the range 0 to 1. If the values passed in are outside that range,
* they will be clamped.
* The default source pattern is opaque black, (that is, it is equivalent to cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0)).
* *****************************************************************************************************************************/
cairo_set_source_rgba (cr, 1, 0, 0, 0.80);
/* void cairo_fill(cairo_t *cr); */
/* A drawing operator that fills the current path according to the current fill rule, (each sub-path is implicitly closed before
* being filled). After cairo_fill(), the current path will be cleared from the cairo context.
* *****************************************************************************************************************************/
cairo_fill (cr);
cairo_rectangle (cr, 0, 0.5, 0.5, 0.5);
cairo_set_source_rgba (cr, 0, 1, 0, 0.60);
cairo_fill (cr);
cairo_rectangle (cr, 0.5, 0, 0.5, 0.5);
cairo_set_source_rgba (cr, 0, 0, 1, 0.40);
cairo_fill (cr);
cairo_surface_write_to_png(surface, "image.png");
cairo_destroy(cr);
cairo_surface_destroy(surface);
return 0;
}
I obtain an empty png. It looks like there's something there but it doesn't paint it.
I compile with:
cc -o file $(pkg-config --cflags --libs cairo) file.c
My brew info Cairo outs this:
cairo: stable 1.16.0 (bottled), HEAD
Vector graphics library with cross-device output support
https://cairographics.org/
/usr/local/Cellar/cairo/1.16.0_3 (117 files, 5.7MB) *
Poured from bottle on 2020-10-12 at 00:17:34
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/cairo.rb
License: LGPL-2.1
==> Dependencies
Build: pkg-config ✔
Required: fontconfig ✔, freetype ✔, glib ✔, libpng ✔, lzo ✔, pixman ✔
==> Options
--HEAD
Install HEAD version
==> Analytics
install: 110,282 (30 days), 348,240 (90 days), 1,254,903 (365 days)
install-on-request: 13,651 (30 days), 54,037 (90 days), 132,345 (365 days)
build-error: 0 (30 days)
The pkg-config libs outs this:
-L/usr/local/Cellar/cairo/1.16.0_3/lib -lcairo
And pkg-config Cflags:
-I/usr/local/Cellar/libffi/3.3/include -I/usr/local/Cellar/cairo/1.16.0_3/include/cairo
-I/usr/local/Cellar/glib/2.66.1/include -I/usr/local/Cellar/glib/2.66.1/include/glib-2.0
-I/usr/local/Cellar/glib/2.66.1/lib/glib-2.0/include -I/usr/local/opt/gettext/include
-I/usr/local/Cellar/pcre/8.44/include -I/usr/local/Cellar/pixman/0.40.0/include/pixman-1
-I/usr/local/Cellar/fontconfig/2.13.1/include -I/usr/local/opt/freetype/include/freetype2
-I/usr/local/Cellar/libpng/1.6.37/include/libpng16
Is there something wrong that I can't see? Everything looks great. I don't know what happen.
cairo_rectangle (cr, 0, 0, 0.5, 0.5);
You seem to assume the coordinates are within a range of 0..1 to cover the whole surface.
This is not true. Instead the coordinates ragnes are from 0..width and 0..height.
Your instruction will create a rectangle with half a pixel in each direction and the line width was set to 1/5 pixel before. You will not see much with those coordinates.
The sample you linked, uses much larger values. Try them.

Texture do not rotate with OpenGL (C)

I am trying to rotate a texture extracted from a video frame (provided by ffmpeg), I have tried the following code :
glTexSubImage2D(GL_TEXTURE_2D,
0,
0,
0,
textureWidth,
textureHeight,
GL_RGBA,
GL_UNSIGNED_BYTE,
//s_pixels);
pFrameConverted->data[0]);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(0.5,0.5,0.0);
glRotatef(90,0.0,0.0,1.0);
glTranslatef(-0.5,-0.5,0.0);
glMatrixMode(GL_MODELVIEW);
//glDrawTexiOES(-dPaddingX, -dPaddingY, 0, drawWidth + 2 * dPaddingX, drawHeight + 2 * dPaddingY);
glDrawTexiOES(0, 0, 0, drawWidth, drawHeight);
The image is not rotated, do you see the problem ?
From the GL_OES_draw_texture extension specification:
Note also that s, t, r, and q are computed for each fragment as part of DrawTex rendering. This implies that the texture matrix is ignored and has no effect on the rendered result.
You are trying to transform the texture coordinates using the fixed-function texture matrix, but like point sprites, those coordinates are generated per-fragment rather than per-vertex. Thus, that means that nothing you do to the texture matrix is ever going to affect the output of glDrawTexiOES (...).
Consider using a textured quad instead, those will pass through the traditional vertex processing pipeline.

How to write out a greyscale cairo surface to PNG

I have a cairo_surface_t of format CAIRO_FORMAT_A8. I want to write out the surfe as a greyscale image, so every pixel has a single byte value of type uchar.
If I use cairo_surface_write_to_png directly on the CAIRO_FORMAT_A8 surface, all I get is an all-black image. I think this is how cairo internally treats the A8 surface - as alpha values, not as greyscale data. I want a single greyscale image, however.
I'd be enough if somebody count point out how to copy the A8 format to all 3 layers of an RGB24 image.
Any help appreciated!
Untested code below. The idea is to create an ARGB-surface and "copy" the A8 surface there via cairo_mask_surface(). If the colors are "swapped", swap the two cairo_set_source_rgb() calls.
cairo_surface_t *s = YOUR_A8_SURFACE;
cairo_t *cr = cairo_create(s);
cairo_push_group_with_content(cr, CAIRO_CONTENT_COLOR_ALPHA);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_paint(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_mask_surface(cr, cairo_get_target(cr), 0, 0);
cairo_surface_write_to_png(cairo_get_group_target(cr), "/tmp/foo.png");
/* If you want to continue using the context:
cairo_pattern_destroy(cairo_pop_group(cr)); */
cairo_destroy(cr);

How do I fill the screen with a rectangle in OpenGL ortho mode?

I have a single 640x480 texture that needs to fill the screen. So far, I can make it work with a square texture, but not a rectangular one.
glViewport(0, 0, display->w, display->h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double aspectRatio = (double)display->w / (double)display->h;
if (display->w <= display->h)
glOrtho(-1, 1, -1 / aspectRatio, 1 / aspectRatio, -1, 1);
else
glOrtho(-1 * aspectRatio, 1 * aspectRatio, -1, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
What modifications do I need to make so that it will fit any texture to the screen, regardless of its aspect ratio?
This may have some relevance.
Tiling texture bmp file as texture onto a rectangle in OpenGL?
You may wish to consider ARB extension texture rectangle as an alternative approach to (assuming glTexImage2D?) http://glprogramming.com/red/chapter09.html

Resources