mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-15 19:02:39 +02:00
Gtk3: fixed TGtk3DeviceContext.GetPixel() so it works on wayland too. Patch by Anton Kavalenka. issue #41413
This commit is contained in:
parent
dfb0c3bf81
commit
32c1370c50
@ -2006,88 +2006,57 @@ function TGtk3DeviceContext.getPixel(x, y: Integer): TColor;
|
||||
var
|
||||
APixbuf: PGdkPixbuf;
|
||||
AData: PByte;
|
||||
APixelValue: LongWord;
|
||||
APixelValue: Longword;
|
||||
ASurfaceWidth, ASurfaceHeight, ARowStride: Integer;
|
||||
AOutSize: Tcairo_rectangle_int_t;
|
||||
ARegion: Pcairo_region_t;
|
||||
pixels,row: pointer;
|
||||
stride,r,c:integer;
|
||||
|
||||
st:Tcairo_surface_type_t;
|
||||
cr:Pcairo_t;
|
||||
img_surf,view:Pcairo_surface_t;
|
||||
begin
|
||||
Result := 0;
|
||||
|
||||
if CairoSurface = nil then
|
||||
exit;
|
||||
|
||||
if cairo_surface_get_type(CairoSurface) = CAIRO_SURFACE_TYPE_IMAGE then
|
||||
begin
|
||||
ASurfaceWidth := cairo_image_surface_get_width(CairoSurface);
|
||||
ASurfaceHeight := cairo_image_surface_get_height(CairoSurface);
|
||||
end else
|
||||
begin
|
||||
ASurfaceWidth := 0;
|
||||
ASurfaceHeight := 0;
|
||||
|
||||
//Our context have or GtkWidget or GdkWindow available.
|
||||
if Assigned(Self.Parent) then
|
||||
begin
|
||||
ASurfaceWidth := gtk_widget_get_allocated_width(Self.Parent);
|
||||
ASurfaceHeight := gtk_widget_get_allocated_height(Self.Parent);
|
||||
end else
|
||||
if Assigned(Self.Window) then
|
||||
begin
|
||||
//for now we'll use cairo region, it's faster than
|
||||
//calculate client size by calling gdk_window_get_geometry() + gdk_window_get_frame_extents()
|
||||
ARegion := gdk_window_get_clip_region(Self.Window);
|
||||
if ARegion <> nil then
|
||||
begin
|
||||
cairo_region_get_extents(ARegion, @AOutSize);
|
||||
ASurfaceWidth := AOutSize.width;
|
||||
ASurfaceHeight := AOutSize.height;
|
||||
cairo_region_destroy(ARegion);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (X < 0) or (Y < 0) or (X >= ASurfaceWidth) or (Y >= ASurfaceHeight) then
|
||||
begin
|
||||
DebugLn(Format('ERROR: TGtk3DeviceContext.getPixel: Pixel out of bounds x %d y %d surface width %d height %d !',
|
||||
[x, y, ASurfaceWidth, ASurfaceHeight]));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if cairo_surface_get_type(CairoSurface) = CAIRO_SURFACE_TYPE_IMAGE then
|
||||
begin
|
||||
cairo_surface_flush(CairoSurface);
|
||||
AData := PByte(cairo_image_surface_get_data(CairoSurface));
|
||||
|
||||
if AData <> nil then
|
||||
st := cairo_surface_get_type(CairoSurface);
|
||||
if st in [CAIRO_SURFACE_TYPE_XLIB, CAIRO_SURFACE_TYPE_XCB] then
|
||||
begin
|
||||
ARowStride := cairo_image_surface_get_stride(CairoSurface);
|
||||
APixelValue := PLongWord(AData + (Y * ARowStride) + (X * 4))^;
|
||||
|
||||
Result := ((APixelValue and $00FF0000) shr 16) or
|
||||
(APixelValue and $0000FF00) or
|
||||
((APixelValue and $000000FF) shl 16);
|
||||
exit;
|
||||
(* Allocate an image surface of a suitable size *)
|
||||
view:=cairo_surface_create_for_rectangle(CairoSurface,fncOrigin.X + x -PixelOffset, fncOrigin.Y + y - PixelOffset,1 + PixelOffset, 1 + PixelOffset);
|
||||
img_surf := cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
|
||||
cr := cairo_create(img_surf);
|
||||
cairo_set_source_surface(cr, view, 0, 0);
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint(cr);
|
||||
cairo_surface_flush (img_surf);
|
||||
// cairo_surface_write_to_png(img_surf, 'image.png');
|
||||
cairo_destroy(cr);
|
||||
pixels := cairo_image_surface_get_data(img_surf);
|
||||
APixelValue:=PLongInt(pixels)^;
|
||||
cairo_surface_destroy(img_surf);
|
||||
cairo_surface_destroy(view);
|
||||
end else
|
||||
if st=CAIRO_SURFACE_TYPE_IMAGE then
|
||||
begin
|
||||
DebugLn('Error: GetPixel for CAIRO_SURFACE_TYPE_IMAGE failed.');
|
||||
exit(0);
|
||||
pixels := cairo_image_surface_get_data(CAirosurface);
|
||||
if Assigned(pixels) then
|
||||
begin
|
||||
stride := cairo_image_surface_get_stride(CairoSurface);
|
||||
row:=pixels+(fncOrigin.Y+Y)*stride;
|
||||
inc(row,(fncOrigin.X+X)*sizeof(longint));
|
||||
APixelValue:=PLongInt(row)^;
|
||||
end;
|
||||
end;
|
||||
|
||||
APixbuf := gdk_pixbuf_get_from_surface(CairoSurface, X, Y, 1, 1);
|
||||
if APixbuf = nil then
|
||||
Exit;
|
||||
|
||||
AData := gdk_pixbuf_get_pixels(APixbuf);
|
||||
ARowStride := gdk_pixbuf_get_rowstride(APixbuf);
|
||||
|
||||
APixelValue := PLongWord(AData)^;
|
||||
|
||||
Result := ((APixelValue and $FF0000) shr 16) or
|
||||
(APixelValue and $00FF00) or
|
||||
((APixelValue and $0000FF) shl 16);
|
||||
|
||||
g_object_unref(APixbuf);
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user