mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-17 21:22:49 +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
|
var
|
||||||
APixbuf: PGdkPixbuf;
|
APixbuf: PGdkPixbuf;
|
||||||
AData: PByte;
|
AData: PByte;
|
||||||
APixelValue: LongWord;
|
APixelValue: Longword;
|
||||||
ASurfaceWidth, ASurfaceHeight, ARowStride: Integer;
|
ASurfaceWidth, ASurfaceHeight, ARowStride: Integer;
|
||||||
AOutSize: Tcairo_rectangle_int_t;
|
AOutSize: Tcairo_rectangle_int_t;
|
||||||
ARegion: Pcairo_region_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
|
begin
|
||||||
Result := 0;
|
Result := 0;
|
||||||
|
|
||||||
if CairoSurface = nil then
|
if CairoSurface = nil then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
if cairo_surface_get_type(CairoSurface) = CAIRO_SURFACE_TYPE_IMAGE then
|
cairo_surface_flush(CairoSurface);
|
||||||
|
|
||||||
|
st := cairo_surface_get_type(CairoSurface);
|
||||||
|
if st in [CAIRO_SURFACE_TYPE_XLIB, CAIRO_SURFACE_TYPE_XCB] then
|
||||||
begin
|
begin
|
||||||
ASurfaceWidth := cairo_image_surface_get_width(CairoSurface);
|
(* Allocate an image surface of a suitable size *)
|
||||||
ASurfaceHeight := cairo_image_surface_get_height(CairoSurface);
|
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
|
end else
|
||||||
|
if st=CAIRO_SURFACE_TYPE_IMAGE then
|
||||||
begin
|
begin
|
||||||
ASurfaceWidth := 0;
|
pixels := cairo_image_surface_get_data(CAirosurface);
|
||||||
ASurfaceHeight := 0;
|
if Assigned(pixels) then
|
||||||
|
|
||||||
//Our context have or GtkWidget or GdkWindow available.
|
|
||||||
if Assigned(Self.Parent) then
|
|
||||||
begin
|
begin
|
||||||
ASurfaceWidth := gtk_widget_get_allocated_width(Self.Parent);
|
stride := cairo_image_surface_get_stride(CairoSurface);
|
||||||
ASurfaceHeight := gtk_widget_get_allocated_height(Self.Parent);
|
row:=pixels+(fncOrigin.Y+Y)*stride;
|
||||||
end else
|
inc(row,(fncOrigin.X+X)*sizeof(longint));
|
||||||
if Assigned(Self.Window) then
|
APixelValue:=PLongInt(row)^;
|
||||||
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;
|
||||||
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
|
|
||||||
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;
|
|
||||||
end else
|
|
||||||
begin
|
|
||||||
DebugLn('Error: GetPixel for CAIRO_SURFACE_TYPE_IMAGE failed.');
|
|
||||||
exit(0);
|
|
||||||
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
|
Result := ((APixelValue and $FF0000) shr 16) or
|
||||||
(APixelValue and $00FF00) or
|
(APixelValue and $00FF00) or
|
||||||
((APixelValue and $0000FF) shl 16);
|
((APixelValue and $0000FF) shl 16);
|
||||||
|
|
||||||
g_object_unref(APixbuf);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user