On X systems you can draw using any Xlib calls. Xlib requires a bunch of silly extra arguments, and FL gives you values for all of these in static variables declared in <FL/x.H>:
extern Display* fl_display;
extern GC fl_gc;
extern Window fl_window;
extern int fl_screen;
extern XVisualInfo* fl_visual;
extern Colormap fl_colormap;
XDrawSomething(fl_display, fl_window, fl_gc, ...);
It may also be useful to refer to Fl_Window::current()
to get the window's size or position.
unsigned long fl_xpixel(uchar i);
unsigned long fl_xpixel(uchar r, uchar g, uchar
b);
It may be possible to use OpenGL to draw normal objects (also see Fl_Gl_Window). This lets you use Gourand shading and other useful functions to make cool looking widgets. It's apparent the designers and implementors of the glX extension did not consider this possibility, but it works with some limitations: you must choose a default visual with Fl::gl_visual(), you cannot use double buffered gl contexts, and you cannot use Fl_Double_Window (or Fl_Overlay_Window).
void gl_start();
void gl_finish();
You may want to use Fl_Window::current()->h()
to get
the drawable height so you can flip the coordinate system.
Do not use these when drawing an Fl_Gl_Window!
FL provides some extra gl drawing functions to draw characters, rectangles, and arcs. See Fl_Gl_Window for a list.
The plan is to reproduce the following functions on machines that
do not use X:
Set the color for all subsequent drawing operations. Colors are
identified by an 8-bit index. This is not the X pixel, it is
an internal table! The table provides several general colors, a
24-entry gray ramp, and a 5x8x5 color cube. All of these are named
with poorly-documented symbols in <FL/Enumerations.H>.
Under X, a color cell will be allocated out of fl_colormap each
time you request an fl_color the first time. If the colormap fills up
then a least-squares algorithim is used to find the closest color.
Set the color for all subsequent drawing operations. The closest
possible match to the rgb color is used. Under X this works
perfectly for TrueColor visuals. For colormap visuals the nearest index
in the gray ramp or color cube is figured out, and fl_color(i) is done
with that, this can result in two approximations of the color and is
very inaccurate!
It is your responsibility to pop exactly the same number of clips
that you push in a draw() implementation. If the stack is not empty
when the graphics context is changed unpredictable results occur.
FL considers integer positions to be at the corners of pixels, and
a 1-pixel thick line fills in the pixel below and to the right of the
mathematical line.
Under X, fl_circle will use Xlib to draw the circle. Ellipses
will not draw correctly if the coordinate system is rotated. fl_arc
is simulated with line segments, and there are only 16 around a circle.
Transform a point to the actual x and y, and add a vertex without
doing any transformation. These calls are designed to allow
piece-wise curves to be drawn, where the number of pieces depends on
the current scale.
You must set the font before you can measure the widths of any
characters. Therefore it is useful to call fl_font outside a draw()
context. This will however open the display.
The sizes are sorted from smallest to largest and indicate what
sizes can be given to fl_font() that will be matched exactly
(fl_font() will pick the closest size for other sizes). A zero in the
first location of the array indicates a scalable font, where any size
works, although the array may list sizes that work "better" than
others.
The string and array passed to the callback point at local storage and
must be copied if you want to keep them after the callback returns.
There currently is no fl_draw_bitmap() function. Probably it will
be added.
The current X version only supports some visuals. If
fl_visual does not fulfull the following requirements, FL will
abort when fl_draw_image is called:
To use an XPM, do " In the current version the XPM data is converted to 8-bit full
color and passed through fl_draw_image(). This is obviously not the
most efficient way to do it, and has the same visual limitations as
listed above for fl_draw_image(). Transparent colors are replaced by
the optional bg color argument (this may change in the future).
FL supports some (questionable) enhancements to
the XPM format.
The cursor may be one of For X you can get any XC_cursor value by
passing Big kludge to draw interactive selection rectangles without using
the overlay. FL will xor a single rectangle outline over a window.
Calling this will erase any previous rectangle (by xor'ing it), and
then draw the new one. Calling fl_overlay_clear() will erase the
rectangle without drawing a new one. Using this is tricky. You
should make an object with both a handle() and draw() method. draw()
should call fl_overlay_clear() before doing anything else. Your
handle() method should call window()->make_current() and then
fl_overlay_rect() after FL_DRAG events, and should call
fl_overlay_clear() after a FL_RELEASE event.
Colors
void fl_color(uchar);
void fl_color(uchar r, uchar g, uchar
b);
void Fl::set_color(uchar, uchar r, uchar g, uchar b);
void Fl::get_color(uchar, uchar &, uchar &, uchar &);
Set or get an entry in the fl_color index table. You can set it to
any 8-bit rgb color. On X, if the index has been requested before,
the pixel is free'd. No pixel is allocated until fl_color(i) is used
again, and there is no guarantee that the same pixel will be used next
time.
Clipping
void fl_clip(int x, int y, int w, int h);
Push a new clip rectangle onto the stack. It is intersected with the
current clip rectangle. All drawing is limited to the resulting
bounding box.
void fl_pop_clip();
Pop off a clip rectangle, restoring the previous one.
extern struct Fl_Clip {short x,y,r,b;} fl_current_clip;
extern int fl_clipped;
The current clipping is accessible so you can avoid lengthy drawing
routines that won't produce anything. If
fl_clipped
is
non-zero then fl_current_clip.x
is the left edge of the
clipping, fl_current_clip.y
is the top,
fl_current_clip.r
is the right, and
fl_current_clip.b
is the bottom. If fl_clipped
is false then you should assumme no clipping.
Fixed-size drawing code
These functions are used to draw almost all the FL objects. They draw
on exact pixel boundaries and are as fast as possible. Do not call
these between fl_push_matrix() and fl_pop_matrix(), or after
fl_rotate(), fl_scale(), or fl_translate(), as the results are undefined.
void fl_rect(int x,int y,int w,int h);
void fl_rectf(int x,int y,int w,int h);
Draw rectangles that exactly fill the given bounding box. fl_rectf()
fills the box with color. fl_rect() draws a 1-pixel border
inside this bounding box.
void fl_line(int x,int y,int x1,int y1,...);
Draw a sequence of 1-pixel thick lines. Currently 2 and 3 points
versions are supplied.
void fl_loop(int x,int y,int x1,int y1,int x2,int y2,...);
Draw a loop of 1-pixel thick lines. Same as fl_line except another
line segment is added back to the first point. Currently 3 and 4 point
versions are supplied.
void fl_polygon(int x,int y,int x1,int y1,int x2,int y2,...);
Fill a polygon. The polygon must be convex. Currently 3 and 4 point
versions are supplied.
void fl_xyline(int x,int y,int x1(,y1,x2...));
Draw 1-pixel wide horizontal and vertical lines. After the first
point subsequent points are defined by alternating x and y
coordinates. 2-point, 3-point, and 4-point versions are supplied.
void fl_yxline(int x,int y,int y1(,x2,y3...));
Draw 1-pixel wide vertical and horizontal lines. After the first
point subsequent points are defined by alternating y and x
coordinates. 2-point, 3-point, and 4-point versions are supplied.
Scalable drawing code
These functions let you draw arbitrary shapes with simple
transformations. The exact pixels filled in is less defined than for
the above calls, so that FL can take advantage of drawing hardware.
X unfortunately rounds all the transformed verticies to integers
before drawing the line segments. This severely limits the accuracy
of these functions for complex graphics. Try using OpenGL
instead.
void fl_push_matrix();
void fl_pop_matrix();
Save and restore the current transformation. The maximum depth of the
stack is 4.
void fl_scale(float x,float y);
void fl_scale(float x);
void fl_translate(float x,float y);
void fl_rotate(float d);
void fl_mult_matrix(float a, float b, float c, float d, float x, float y);
Concat another transformation to the current one. The rotation angle
is in degrees counter-clockwise.
void fl_begin_line();
Start drawing 1-pixel thick lines.
void fl_begin_loop();
Start drawing a closed sequence of 1-pixel thick lines.
void fl_begin_polygon();
Start drawing a filled polygon.
void fl_vertex(float x,float y);
void fl_vertex(const float* p);
Add a single vertex to the current path. The second version takes a
pointer to an x,y pair.
void fl_arc(float x,float y,float w,float h,int start,int end);
void fl_arc(float x,float y,float r,int start,int end);
void fl_circle(float x,float y,float w,float h);
void fl_circle(float x,float y,float r);
Add a series of points to the current path on an ellipse or circle.
The ellipse is specified with a bounding box it fits into, and the
circle by a center point and radius. The start and end angles of
fl_arc() are in degrees counter-clockwise from 3 o'clock. The
fl_circle() functions draw a loop of points that if closed will
produce a circle.
void fl_end();
Finish the current path.
float fl_transform_x(float x,float y);
float fl_transform_y(float x,float y);
void fl_transformed_vertex(float x,float y);
Fonts
void fl_font(uchar fontid, int size);
Set the current font, which is then used by the routines described
below. The current font is identified with a "fontid" and a "size".
The "fontid" is an index into a table of string font names, and the
size scales the font so the line spacing is approximately that many
pixels. There are several symbolic names for fontids, including
FL_HELVETICA, FL_TIMES, FL_COURIER, and modifier values FL_BOLD and
FL_ITALIC which can be added to these.
int fl_height();
Recommended minimum line spacing for the current font. You can also
just use the size that you used to select the font.
int fl_descent();
Recommended distance above the bottom of a fl_height() tall box to
draw the text at so it looks centered vertically in that box.
float fl_width(const char*);
float fl_width(const char*, int n);
float fl_width(uchar);
Return the width of a null-terminated string, a sequence of n
characters, and a single character.
void fl_draw(const char*, float x, float y);
void fl_draw(const char*, int n, float x, float y);
Draw a null terminated string or an array of n characters in the
current font, starting at the given location.
void fl_draw(const char*, int x,int y,int w,int h, uchar
align, uchar c);
Fancy string drawing function which is used to draw all the labels.
The string is formatted and aligned inside the passed box. Handles
'\t' and '\n' to make multiple lines, expands all other control
characters to ^X, and aligns inside or against the edges of the box.
const char* fl_shortcut_label(const char*);
Unparse an FL shortcut string (the same string used by
Fl::test_shortcut()) into a human-readable string like "Alt+N". If
the string contains many shortcuts only the first one is unparsed. If
the string is NULL or empty then an empty string is returned. The
return value points at a static buffer that is overwritten with each
call.
const char* Fl::get_font(uchar fontid);
Get the string describing this font id. The format of the string is
system specific. Under X this string is passed to XListFonts, and
the returned fonts are searched for the correct pixel size.
uchar Fl::set_font(uchar fontid, const char*);
Change a fontid. The string pointer is simply stored, the string is
not copied, so the string must be in static memory.
uchar Fl::set_font(uchar fontid, uchar from);
Copy one fontid to another.
uchar Fl::set_font(const char*);
FL selects an unused font id, sets it to the given string, and returns
it.
void Fl::font_enumerate(void (*cb)(const char*, const
int*, int));
FL will call the cb function once for each font on the system. The
arguments for the cb function are a string that can be passed to
Fl::set_font(), an array of sizes, and the length of the array.
Bitmaps, Pixmaps and Images
To draw images, you can either do it directly from data in your
memory, or you can create an "Fl_Pixmap" or similar object from the
data. The advantage of drawing directly is that it is more intuitive,
and it is faster if the image data changes more often than it is
redrawn. The advantage of using the object is that FL will cache
transated forms of the image (on X it uses a server pixmap) and thus
redrawing it is much faster.
void fl_draw_image(const uchar*, int X, int Y, int W, int H, int D=3,
int LD=0);
Draw an 8-bit per color rgb image. The pointer points at the "r" data
of the top-left pixel. Data must be in r,g,b order. X, Y are where
to put the top-left corner. W and H define the size of the image. D
is the delta to add to the pointer between pixels, it may be any value
greater or equal to 3, or it can be negative to flip the image
horizontally. LD is the delta to add to the pointer between lines (if
0 is passed it uses W*D), and may be larger than W*D to crop data, or
negative to flip the image vertically.
void fl_draw_image_mono(const uchar*, int X, int Y, int W, int H, int
D=1,int LD=0);
Draw a monochrome image. In this case the data is expected to be a
single 8-bit value per pixel. By setting D to 3 or 4 you can display
one of the channels of a color image.
int fl_draw_pixmap(char** data, int x, int y, uchar bg=FL_GRAY);
Draw XPM image data, with the top-left corner at the given position.
The images is dithered on 8-bit displays so you won't lose color space
for programs displaying both images and pixmaps. This function
returns zero if there was any error decoding the xpm data.
#include "foo.xpm"
" and then
"fl_draw_pixmap(foo, X, Y)
".
int fl_pixmap_size(char** data, int &w, int
&h);
An XPM image contains the dimensions in it's data. This function
finds and returns the width and height. The return value is non-zero
if it parsed the dimensions ok, and zero if there is any problem.
void fl_draw(Fl_Bitmap* b,int x,int y,int w,int h);
void fl_draw(Fl_Pixmap* b,int x,int y,int w,int h);
void fl_draw(Fl_Image* b,int x,int y,int w,int h);
Draw Fl_Bitmap, Fl_Pixmap, or Fl_Image objects, centered (and possibly
clipped) to the passed bounding box. These create server pixmaps so
drawing the same image a second time is really fast. See the pages
for these objects for details.
Cursor
void fl_cursor(uchar, uchar bg=FL_WHITE, uchar
fg=FL_BLACK);
Change the cursor. For portability you should assumme there is only
one cursor everywhere (under X this just changes the cursor of the
current window). You should change the cursor in response to
FL_ENTER/FL_EXIT or FL_PUSH/FL_RELEASE events. Put it back to the
default when the cursor leaves the window.
FL_CURSOR_DEFAULT (0),
FL_CURSOR_ARROW, FL_CURSOR_CROSS, FL_CURSOR_BUSY, FL_CURSOR_INSERT, or
FL_CURSOR_NONE
The two colors will be used to color the cursor,
if possible. They are ignored for FL_CURSOR_DEFAULT
.
(XC_foo/2)+1
.
Selection rectangle
void fl_overlay_rect(int x, int y, int w, int h);
void fl_overlay_clear();