How to stretch draw a cairo gdk pixbuf pattern region with an arbitrary opacity?
-
28-06-2021 - |
Frage
How can I stretch draw an area of a gdk pixbuf to a cairo surface with a user defined opacity?
I am trying to write a cross platform interface for working with bitmaps and want to add alpha blending to my cairo stretch draw method. What I have right now works just fine, but I am unable to think up a way of to mold alpha blending into a series of cairo/gdk apis which work somewhat like Microsoft's AlphaBlend function.
What I have so far is this:
procedure TGtkBitmap.Draw(const Source: TRect; Canvas: TCanvas;
const Dest: TRect; Alpha: Byte = $FF);
var
D: PGdkDrawable;
C: Pcairo_t;
M: cairo_matrix_t;
begin
if FBuffer = nil then
Exit;
if (WidthOf(Source) < 1) or (WidthOf(Dest) < 1) then
Exit;
if (HeightOf(Source) < 1) or (HeightOf(Dest) < 1) then
Exit;
D := TGtk2DeviceContext(Canvas.Handle).Drawable;
C := gdk_cairo_create(D);
gdk_cairo_set_source_pixbuf(C, FBuffer, 0, 0);
cairo_matrix_init_identity(@M);
cairo_matrix_translate(@M, Source.Left, Source.Top);
cairo_matrix_scale(@M, WidthOf(Source) / WidthOf(Dest),
HeightOf(Source) / HeightOf(Dest));
cairo_matrix_translate(@M, -Dest.Left, -Dest.Top);
cairo_pattern_set_matrix(cairo_get_source(C), @M);
cairo_rectangle(C, Dest.Left, Dest.Top, WidthOf(Dest), HeightOf(Dest));
// what cairo functions can I combine here to vary
// the opacity of the pattern fill using Alpha argument?
cairo_fill(C);
cairo_destroy(C);
end;
Everything works fine, but I am unsure how to get alpha blending with a pix buff pattern working. I can imagine one way which involves creating a second cairo surface, drawing the entire pixbuf to it with a user defined opacity, then creating pattern for the first surface using the new surface, which all gets a little messy and probably is much slower than something I'd be happy with.
Here is a video recording of what I have working so far. I'd like to know from someone familiar with cairo, what can I insert into my routine above to set the alpha level of the pixbuf source pattern?
Lösung
Chris Wilson from the cairo mailing lists offered this solution which works perfectly.
Replace the:
cairo_fill(C);
with:
cairo_clip(C);
cairo_paint_with_alpha(C, Alpha / $FF);
Thanks to Chris Wilson from the cairo mailing lists!