NAME
Image::Base::X11::Protocol::Drawable -- draw into an X11::Protocol window or pixmap
SYNOPSIS
use Image::Base::X11::Protocol::Drawable;
my $X = X11::Protocol->new;
my $image = Image::Base::X11::Protocol::Drawable->new
(-X => $X,
-drawable => $xid,
-colormap => $colormap);
$image->line (0,0, 99,99, '#FF00FF');
$image->rectangle (10,10, 20,15, 'white');
CLASS HIERARCHY
Image::Base::X11::Protocol::Drawable
is a subclass of Image::Base
,
Image::Base
Image::Base::X11::Protocol::Drawable
DESCRIPTION
Image::Base::X11::Protocol::Drawable
extends Image::Base
to draw into X windows or pixmaps by sending drawing requests to an X server with X11::Protocol
. There's no file load or save, just drawing operations.
The subclasses Image::Base::X11::Protocol::Pixmap
and Image::Base::X11::Protocol::Window
have things specific to a pixmap or window. Drawable is the common parts.
Native X drawing does much more than Image::Base
but if you have some generic pixel twiddling code for Image::Base
then this module lets you point it at an X window, pixmap, etc. Drawing directly into a window is a good way to show slow drawing progressively, rather than drawing a pixmap or image file and only displaying when complete. Or see Image::Base::Multiplex
for a way to do both simultaneously.
Colour Names
Colour names are the server's colour names per AllocNamedColor
plus hexadecimal RGB, and set/clear for bitmaps or monochrome windows,
AllocNamedColor usually server's /etc/X11/rgb.txt
#RGB 1 to 4 digit hex
#RRGGBB
#RRRGGGBBB
#RRRRGGGGBBBB
1 \
0 | for bitmaps and monochrome windows
set |
clear /
Colours used are allocated in a specified -colormap
.
FUNCTIONS
See "FUNCTIONS" in Image::Base for the behaviour common to all Image-Base classes.
$image = Image::Base::X11::Protocol::Drawable->new (key=>value,...)
-
Create and return a new image object. This requires an
X11::Protocol
connection object and a drawable XID (an integer).my $image = Image::Base::X11::Protocol::Drawable->new (-X => $x11_protocol_obj, -drawable => $drawable_xid, -colormap => $X->{'default_colormap'});
A colormap should be given if allocating colours, which means generally means anything except a bitmap or monochrome window.
$colour = $image->xy ($x, $y)
$image->xy ($x, $y, $colour)
-
Get or set the pixel at
$x
,$y
.Fetching a pixel is an X server round-trip so reading a big region will be slow. The protocol allows a big region or an entire drawable to be read in one go, so some function for that could be made if needed.
In the current code the colour returned is either the name used to draw it, or 4-digit hex #RRRRGGGGBBBB queried from the
-colormap
, or otherwise a raw pixel value. If two colour names are the same pixel value because that was as close as could be represented then fetching might give either name. The hex return is 4 digit components because that's the range in the X protocol.If the drawable is a window then parts overlapped by another window (including a sub-window) generally read back as an random colour. Parts of a window which are off-screen have no data at all and the return is currently an empty string
""
. Wouldundef
or the window background pixel be better? (An off-screenGetImage
is actually a Match error reply, but that's turned into a plain return here since that will be much more helpful than the$X
connection error handler.) $image->add_colours ($name, $name, ...)
-
Allocate colours in the
-colormap
. Colour names are the same as for the drawing functions. For example,$image->add_colours ('red', 'green', '#FF00FF');
Drawing automatically adds a colour if it doesn't already exist but using
add_colours
can do a set of pixel lookups in a single server round-trip instead of separate individual ones.If using the default colormap of the screen then names "black" and "white" are taken from the screen info and don't query the server (neither in the drawing operations nor
add_colours
).All colours, both named and hex, are sent to the server for interpretation. On a static visual like TrueColor a hex RGB might be turned into a pixel just on the client side, but the X spec allows non-linear colour ramps so only the server can do it properly.
ATTRIBUTES
-drawable
(integer XID)-
The target drawable.
-colormap
(integer XID)-
The colormap in which to allocate colours when drawing.
Setting
-colormap
only affects where colours are allocated. If the drawable is a window then the colormap is not set into the window's attributes (that's left to an application if/when required). -width
(integer, read-only)-height
(integer, read-only)-
Width and height are read-only. The minimum is 1 pixel, the maximum in the protocol is 0x7FFF (a signed 16-bit value).
Fetching with
get()
queries the server withGetGeometry
and then caches. If you already know the size then including values in thenew()
will record them ready for laterget()
.$image = Image::Base::X11::Protocol::Drawable->new (-X => $x11_protocol_obj, -drawable => $id, -width => 200, # known values to -height => 100, # avoid server query -colormap => $colormap);
-depth
(integer, read-only)-
The depth of the drawable, meaning how many bits per pixel.
-screen
(integer, read-only)-
The screen number of the
-drawable
, for example 0 for the first screen.
The depth and screen of a drawable cannot be changed, and for the purposes of this interface the width and height are regarded as fixed too. (Is that a good idea?)
get()
of -width
, -height
, -depth
or -screen
for a root window uses values from the X11::Protocol
object info without querying the server. For other drawables a GetGeometry
request is made. If you already know the values of some of these attributes then include them in the new()
to record ready for later get()
and avoid that GetGeometry
query. Of course if nothing ever does such a get()
then there's no need. The plain drawing operations don't need the size.
ALGORITHMS
ellipse()
unfilled uses the X PolyArc
line centred on the boundary pixels, being the midpoints of the $y1
row, $y2
row, $x1
column, etc. The way the pixel "centre within the shape" rule works should mean that circles are symmetric, but the X protocol spec allows the server some implementation-dependent latitude for ellipses width!=height.
ellipse()
filled uses the X FillArc
, but that means the area inside an ellipse centred on the boundary pixels, which is effectively 1/2 pixel in from the ellipse line edge. The pixel "centre on the boundary drawn if above or left" rule also means the bottom row and rightmost column aren't drawn at all. The current strategy is to draw a PolyArc
on top for the extra 1/2 pixel radius.
For a filled circle an alternative strategy would be to set the line width to half the radius and draw from half way in from the edges. That means the line width is from the centre of the box to the outer edges. The way a line has linewidth/2 each side makes a resolution of 1/2 pixel possible. The disadvantage would be changing the GC each time, which might be undesirable if it came from the user (secret as-yet undocumented -gc
attribute). Note also this is no good for an ellipse width!=height because if you draw a fixed distance tangent to an ellipse then it's not a bigger ellipse, but a shape fatter than an ellipse.
The FillArc
plus PolyArc
combination ends up drawing some pixels twice, which is no good for an "XOR" gc operation. Currently that doesn't affect Image::Base::X11::Protocol::Drawable
, but if there was a user supplied -gc
then more care might be wanted. At worst the base Image::Base
code could be left to handle it all, or draw onto a temporary bitmap to make a mask of desired pixels, or something like that.
diamond()
uses PolyLine
and FillPoly
in similar ways to the ellipse above. The FillPoly
has the same 1/2 pixel inside as the FillArc
and so a filled diamond is a PolyLine
on top of a FillPoly
.
BUGS
The pixel values for each colour used for drawing are cached for later re-use. This is highly desirable to avoid a server round-trip on every drawing operation, but if you use a lot of different shades then the cache may become big. Perhaps some sort of least recently used discard could keep a lid on it. Perhaps the colour-to-pixel hash or some such attribute could be exposed so it could be both initialized, manipulated, or set to some tied LRU hash etc as desired.
SEE ALSO
Image::Base, Image::Base::X11::Protocol::Pixmap, Image::Base::X11::Protocol::Window, X11::Protocol, Image::Base::Multiplex
HOME PAGE
http://user42.tuxfamily.org/image-base-x11-protocol/index.html
LICENSE
Image-Base-X11-Protocol is Copyright 2010, 2011, 2012, 2013, 2017 Kevin Ryde
Image-Base-X11-Protocol is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
Image-Base-X11-Protocol is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Image-Base-X11-Protocol. If not, see <http://www.gnu.org/licenses/>.