OpenGL implementation of all fl_ "Drawing Fast Shapes" graphics calls (#385)

* Fix build system for unites,

* Updated unittest to check OpenGL drawing.

Making sure that OpenGL drawing is exactly the same
as native drawing to make FLTK widget rendering
look the same in GL windows.

* Make OpenGL optional.

* Implemented clipping in OpenGL

* unites drawing fast shapes

* Fixed CMake

* Updating unittest.

Added tests for fl_pi and fl_arc (int)
Renamed tab to render complex shapes.

* Improved OpenGL FLTK drawing emulation.

* Fixed GTK ROUND DOWN BOX

* Fixing Makefile for unittest

* Correctly aligning OpenGL text.

* Fixed text alignment in GL windows.

Explained the "FLTK over GL " example in Cube.

* Overlapping test.

* Better GL graphics alignment.

* Drawing the focus rect.

* Adding Alpha Channel support for GL.

* Added FLTK-on-GL documentation.
This commit is contained in:
Matthias Melcher
2022-02-06 15:22:24 +01:00
committed by GitHub
parent af4954aee3
commit db0a1f4bae
30 changed files with 1670 additions and 424 deletions
+2
View File
@@ -1063,6 +1063,7 @@ int main() {
// color map:
static void set_color(Fl_Color, uchar, uchar, uchar);
static void set_color(Fl_Color, uchar, uchar, uchar, uchar);
/**
Sets an entry in the fl_color index table. You can set it to any
8-bit RGB color. The color is not allocated until fl_color(i) is used.
@@ -1070,6 +1071,7 @@ int main() {
static void set_color(Fl_Color i, unsigned c); // platform dependent
static unsigned get_color(Fl_Color i);
static void get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue);
static void get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue, uchar &alpha);
/**
Frees the specified color from the colormap, if applicable.
If overlay is non-zero then the color is freed from the
+2
View File
@@ -67,7 +67,9 @@ class FL_EXPORT Fl_Gl_Window : public Fl_Window {
int mode(int, const int *);
static int gl_plugin_linkage();
protected:
void draw_begin();
virtual void draw();
void draw_end();
public:
void show();
+69
View File
@@ -257,6 +257,75 @@ adhere to for maximum portability:
Do \e not call \p gl_start() or
\p gl_finish() when drawing into an Fl_Gl_Window !
\section opengl_with_fltk_widgets Using FLTK widgets in OpenGL Windows
FLTK widgets can be added to `Fl_Gl_Window`s just as they would be added to
`Fl_Window`s. They are rendered as an overlay over the user defined
OpenGL graphics using 'fl_..' graphics calls that are implemented in GL.
`Fl_Gl_Window` does not add subsequent widgets as children by default as
`Fl_Window` does. Call `myGlWindow->begin()` after creating the GL window to
automatically add following widgets. Remember to call `myGlWindow->end()`.
\code
class My_Gl_Window : public Fl_Gl_Window {
...
void draw();
...
};
...
myGlWindow = new My_Gl_Window(0, 0, 500, 500);
myGlWindow->begin();
myButton = new Fl_Button(10, 10, 120, 24, "Hello!");
myGlWindow->end();
...
void My_Gl_Window::draw() {
// ... user GL drawing code
Fl_Gl_Window::draw(); // Draw FLTK child widgets.
}
\endcode
Users can draw into the overlay by using GL graphics calls as well as all
`fl_...` graphics calls from the "Drawing Fast Shapes" section.
\code
void My_Gl_Window::draw() {
// ... user GL drawing code
Fl_Gl_Window::draw_begin(); // Set up 1:1 projection
Fl_Window::draw(); // Draw FLTK children
fl_color(FL_RED);
fl_rect(10, 10, 100, 100);
Fl_Gl_Window::draw_end(); // Restore GL state
}
\endcode
Widgets can be drawn with transparencies by assigning an alpha value to a
colormap entry and using that color in the widget.
\code
Fl::set_color(FL_FREE_COLOR, 255, 255, 0, 127); // 50% transparent yellow
myGlWindow = new My_Gl_Window(0, 0, 500, 500);
myGlWindow->begin();
myButton = new Fl_Button(10, 10, 120, 24, "Hello!");
myButton->box(FL_BORDER_BOX);
myButton->color(FL_FREE_COLOR);
myGlWindow->end();
\endcode
Transparencies can also be set directly when drawing. This can be used to
create custom box types and RGB overlay drawings with an alpha channel.
\code
fl_color(0, 255, 0, 127); // 50% transparent green
fl_rectf(10, 10, 100, 100);
fl_color(FL_RED); // back to opaque red
fl_rect(20, 20, 80, 80);
\endcode
\section opengl_drawing OpenGL Drawing Functions
FLTK provides some useful OpenGL drawing functions. They can
+65 -21
View File
@@ -26,6 +26,7 @@ extern int fl_gl_load_plugin;
#include <FL/Fl_Graphics_Driver.H>
#include <FL/fl_utf8.h>
#include "drivers/OpenGL/Fl_OpenGL_Display_Device.H"
#include "drivers/OpenGL/Fl_OpenGL_Graphics_Driver.H"
#include <stdlib.h>
# if (HAVE_DLSYM && HAVE_DLFCN_H)
@@ -337,6 +338,53 @@ void Fl_Gl_Window::init() {
void Fl_Gl_Window::draw_overlay() {}
void Fl_Gl_Window::draw_begin() {
Fl_Surface_Device::push_current( Fl_OpenGL_Display_Device::display_device() );
Fl_OpenGL_Graphics_Driver *drv = (Fl_OpenGL_Graphics_Driver*)fl_graphics_driver;
drv->pixels_per_unit_ = pixels_per_unit();
if (!valid()) {
glViewport(0, 0, pixel_w(), pixel_h());
valid(1);
}
glPushAttrib(GL_ENABLE_BIT);
glPushAttrib(GL_TRANSFORM_BIT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
// glOrtho(-0.5, w()-0.5, h()-0.5, -0.5, -1, 1);
glOrtho(0.0, w(), h(), 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glEnable(GL_POINT_SMOOTH);
glLineWidth((GLfloat)(drv->pixels_per_unit_*drv->line_width_));
glPointSize((GLfloat)(drv->pixels_per_unit_));
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
// TODO: all of the settings should be saved on the GL stack
}
void Fl_Gl_Window::draw_end() {
glMatrixMode(GL_MODELVIEW_MATRIX);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib(); // GL_TRANSFORM_BIT
glPopAttrib(); // GL_ENABLE_BIT
Fl_Surface_Device::pop_current();
}
/** Draws the Fl_Gl_Window.
You \e \b must subclass Fl_Gl_Window and provide an implementation for
draw(). You may also provide an implementation of draw_overlay()
@@ -389,32 +437,28 @@ void Fl_Gl_Window::draw_overlay() {}
}
\endcode
Regular FLTK widgets can be added as children to the Fl_Gl_Window. To
correctly overlay the widgets, Fl_Gl_Window::draw() must be called after
rendering the main scene.
\code
void mywindow::draw() {
// draw 3d graphics scene
Fl_Gl_Window::draw();
// -- or --
draw_begin();
Fl_Window::draw();
// other 2d drawing calls, overlays, etc.
draw_end();
}
\endcode
*/
void Fl_Gl_Window::draw() {
Fl_Surface_Device::push_current( Fl_OpenGL_Display_Device::display_device() );
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_DEPTH_TEST);
glPushMatrix();
glLoadIdentity();
GLint viewport[4];
glGetIntegerv (GL_VIEWPORT, viewport);
if (viewport[2] != pixel_w() || viewport[3] != pixel_h()) {
glViewport(0, 0, pixel_w(), pixel_h());
}
glOrtho(-0.5, w()-0.5, h()-0.5, -0.5, -1, 1);
// glOrtho(0, w(), h(), 0, -1, 1);
glLineWidth((GLfloat)pixels_per_unit()); // should be 1 or 2 (2 if highres OpenGL)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // FIXME: push on state stack
glEnable(GL_BLEND); // FIXME: push on state stack
draw_begin();
Fl_Window::draw();
glPopMatrix();
glPopAttrib();
Fl_Surface_Device::pop_current();
draw_end();
}
/**
Handle some FLTK events as needed.
*/
+17 -2
View File
@@ -24,12 +24,20 @@
#define FL_OPENGL_GRAPHICS_DRIVER_H
#include <FL/Fl_Graphics_Driver.H>
#include <FL/fl_draw.H>
/**
\brief OpenGL specific graphics class.
*/
class FL_EXPORT Fl_OpenGL_Graphics_Driver : public Fl_Graphics_Driver {
public:
float pixels_per_unit_;
float line_width_;
int line_stipple_;
Fl_OpenGL_Graphics_Driver() :
pixels_per_unit_(1.0f),
line_width_(1.0f),
line_stipple_(FL_SOLID) { }
// --- line and polygon drawing with integer coordinates
void point(int x, int y);
void rect(int x, int y, int w, int h);
@@ -46,10 +54,17 @@ public:
void loop(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
void polygon(int x0, int y0, int x1, int y1, int x2, int y2);
void polygon(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3);
void focus_rect(int x, int y, int w, int h);
// ---- clipping
void push_clip(int x, int y, int w, int h);
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
int not_clipped(int x, int y, int w, int h);
void pop_clip();
void push_no_clip();
Fl_Region clip_region();
void clip_region(Fl_Region r);
void restore_clip();
int not_clipped(int x, int y, int w, int h);
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
// ---- matrix transformed drawing
void transformed_vertex(double xf, double yf);
void begin_points();
void end_points();
@@ -27,20 +27,21 @@
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#define _USE_MATH_DEFINES
#include <math.h>
#include <FL/math.h>
void Fl_OpenGL_Graphics_Driver::arc(int x,int y,int w,int h,double a1,double a2) {
if (w <= 0 || h <= 0) return;
while (a2<a1) a2 += 360.0; // TODO: write a sensible fmod angle alignment here
a1 = a1/180.0f*M_PI; a2 = a2/180.0f*M_PI;
double cx = x + 0.5f*w - 0.5f, cy = y + 0.5f*h - 0.5f;
double rMax; if (w<h) rMax = h/2; else rMax = w/2;
a1 = a1/180.0*M_PI; a2 = a2/180.0*M_PI;
double cx = x + 0.5*w, cy = y + 0.5*h;
double rx = 0.5*w-0.3, ry = 0.5*h-0.3;
double rMax; if (w>h) rMax = rx; else rMax = ry;
int nSeg = (int)(10 * sqrt(rMax))+1;
double incr = (a2-a1)/(double)nSeg;
glBegin(GL_LINE_STRIP);
for (int i=0; i<nSeg; i++) {
glVertex2d(cx+cos(a1)*rMax, cy-sin(a1)*rMax);
for (int i=0; i<=nSeg; i++) {
glVertex2d(cx+cos(a1)*rx, cy-sin(a1)*ry);
a1 += incr;
}
glEnd();
@@ -53,16 +54,17 @@ void Fl_OpenGL_Graphics_Driver::arc(double x, double y, double r, double start,
void Fl_OpenGL_Graphics_Driver::pie(int x,int y,int w,int h,double a1,double a2) {
if (w <= 0 || h <= 0) return;
while (a2<a1) a2 += 360.0; // TODO: write a sensible fmod angle alignment here
a1 = a1/180.0f*M_PI; a2 = a2/180.0f*M_PI;
double cx = x + 0.5f*w - 0.5f, cy = y + 0.5f*h - 0.5f;
double rMax; if (w<h) rMax = h/2; else rMax = w/2;
a1 = a1/180.0*M_PI; a2 = a2/180.0*M_PI;
double cx = x + 0.5*w, cy = y + 0.5*h;
double rx = 0.5*w, ry = 0.5*h;
double rMax; if (w>h) rMax = rx; else rMax = ry;
int nSeg = (int)(10 * sqrt(rMax))+1;
double incr = (a2-a1)/(double)nSeg;
glBegin(GL_TRIANGLE_FAN);
glVertex2d(cx, cy);
for (int i=0; i<nSeg+1; i++) {
glVertex2d(cx+cos(a1)*rMax, cy-sin(a1)*rMax);
for (int i=0; i<=nSeg; i++) {
glVertex2d(cx+cos(a1)*rx, cy-sin(a1)*ry);
a1 += incr;
}
glEnd();
@@ -30,41 +30,21 @@
// Implementation of fl_color(i), fl_color(r,g,b).
extern unsigned fl_cmap[256]; // defined in fl_color.cxx
void Fl_OpenGL_Graphics_Driver::color(Fl_Color i) {
// FIXME: do we need the code below?
/*
#if HAVE_GL_OVERLAY
#if defined(_WIN32)
if (fl_overlay && fl_overlay_depth) {
if (fl_overlay_depth < 8) {
// only black & white produce the expected colors. This could
// be improved by fixing the colormap set in Fl_Gl_Overlay.cxx
int size = 1<<fl_overlay_depth;
if (!i) glIndexi(size-2);
else if (i >= size-2) glIndexi(size-1);
else glIndexi(i);
} else {
glIndexi(i ? i : FL_GRAY_RAMP);
}
return;
}
#else
if (fl_overlay) {glIndexi(int(fl_xpixel(i))); return;}
#endif
#endif
*/
if (i & 0xffffff00) {
unsigned rgb = (unsigned)i;
color((uchar)(rgb >> 24), (uchar)(rgb >> 16), (uchar)(rgb >> 8));
} else {
unsigned rgba = ((unsigned)i)^0x000000ff;
Fl_Graphics_Driver::color(i);
uchar red, green, blue;
Fl::get_color(i, red, green, blue);
glColor3ub(red, green, blue);
glColor4ub(rgba>>24, rgba>>16, rgba>>8, rgba);
} else {
unsigned rgba = ((unsigned)fl_cmap[i])^0x000000ff;
Fl_Graphics_Driver::color(fl_cmap[i]);
glColor4ub(rgba>>24, rgba>>16, rgba>>8, rgba);
}
}
void Fl_OpenGL_Graphics_Driver::color(uchar r,uchar g,uchar b) {
void Fl_OpenGL_Graphics_Driver::color(uchar r, uchar g, uchar b) {
Fl_Graphics_Driver::color( fl_rgb_color(r, g, b) );
glColor3ub(r,g,b);
}
@@ -31,27 +31,41 @@
// OpenGL implementation does not support cap and join types
void Fl_OpenGL_Graphics_Driver::line_style(int style, int width, char* dashes) {
if (width<1) width = 1;
line_width_ = width;
if (style==FL_SOLID) {
int stipple = style & 0x00ff;
line_stipple_ = stipple;
// int cap = style & 0x0f00;
// int join = style & 0xf000;
if (stipple==FL_SOLID) {
glLineStipple(1, 0xFFFF);
glDisable(GL_LINE_STIPPLE);
} else {
switch (style) {
char enable = 1;
switch (stipple & 0x00ff) {
case FL_DASH:
glLineStipple(width, 0x0F0F); // ....****....****
glLineStipple(pixels_per_unit_*line_width_, 0x0F0F); // ....****....****
break;
case FL_DOT:
glLineStipple(width, 0x5555); // .*.*.*.*.*.*.*.*
glLineStipple(pixels_per_unit_*line_width_, 0x5555); // .*.*.*.*.*.*.*.*
break;
case FL_DASHDOT:
glLineStipple(width, 0x2727); // ..*..***..*..***
glLineStipple(pixels_per_unit_*line_width_, 0x2727); // ..*..***..*..***
break;
case FL_DASHDOTDOT:
glLineStipple(width, 0x5757); // .*.*.***.*.*.***
glLineStipple(pixels_per_unit_*line_width_, 0x5757); // .*.*.***.*.*.***
break;
default:
glLineStipple(1, 0xFFFF);
enable = 0;
}
glEnable(GL_LINE_STIPPLE);
if (enable)
glEnable(GL_LINE_STIPPLE);
else
glDisable(GL_LINE_STIPPLE);
}
glLineWidth( (GLfloat)(pixels_per_unit_ * line_width_) );
glPointSize( (GLfloat)(pixels_per_unit_) );
}
@@ -26,105 +26,109 @@
#include <FL/Fl_Gl_Window.H>
#include <FL/Fl_RGB_Image.H>
#include <FL/Fl.H>
#include <FL/math.h>
// --- line and polygon drawing with integer coordinates
void Fl_OpenGL_Graphics_Driver::point(int x, int y) {
glBegin(GL_POINTS);
glVertex2i(x, y);
glVertex2f(x+0.5f, y+0.5f);
glEnd();
}
void Fl_OpenGL_Graphics_Driver::rect(int x, int y, int w, int h) {
glBegin(GL_LINE_LOOP);
glVertex2i(x, y);
glVertex2i(x+w, y);
glVertex2i(x+w, y+h);
glVertex2i(x, y+h);
glEnd();
float offset = line_width_ / 2.0f;
float xx = x+0.5f, yy = y+0.5f;
float rr = x+w-0.5f, bb = y+h-0.5f;
glRectf(xx-offset, yy-offset, rr+offset, yy+offset);
glRectf(xx-offset, bb-offset, rr+offset, bb+offset);
glRectf(xx-offset, yy-offset, xx+offset, bb+offset);
glRectf(rr-offset, yy-offset, rr+offset, bb+offset);
}
void Fl_OpenGL_Graphics_Driver::rectf(int x, int y, int w, int h) {
if (w<=0 || h<=0) return;
// OpenGL has the natural origin at the bottom left. Drawing in FLTK
// coordinates requires that we shift the rectangle one pixel up.
glBegin(GL_POLYGON);
glVertex2i(x, y-1);
glVertex2i(x+w, y-1);
glVertex2i(x+w, y+h-1);
glVertex2i(x, y+h-1);
glEnd();
glRectf(x, y, x+w, y+h);
}
void Fl_OpenGL_Graphics_Driver::line(int x, int y, int x1, int y1) {
glBegin(GL_LINE_STRIP);
glVertex2i(x, y);
glVertex2i(x1, y1);
glEnd();
point(x1, y1);
if (x==x1 && y==y1) return;
if (x==x1) {
yxline(x, y, y1);
return;
}
if (y==y1) {
xyline(x, y, x1);
return;
}
float xx = x+0.5f, xx1 = x1+0.5f;
float yy = y+0.5f, yy1 = y1+0.5f;
if (line_width_==1.0f) {
glBegin(GL_LINE_STRIP);
glVertex2f(xx, yy);
glVertex2f(xx1, yy1);
glEnd();
} else {
float dx = xx1-xx, dy = yy1-yy;
float len = sqrtf(dx*dx+dy*dy);
dx = dx/len*line_width_*0.5f;
dy = dy/len*line_width_*0.5f;
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(xx-dy, yy+dx);
glVertex2f(xx+dy, yy-dx);
glVertex2f(xx1-dy, yy1+dx);
glVertex2f(xx1+dy, yy1-dx);
glEnd();
}
}
void Fl_OpenGL_Graphics_Driver::line(int x, int y, int x1, int y1, int x2, int y2) {
glBegin(GL_LINE_STRIP);
glVertex2i(x, y);
glVertex2i(x1, y1);
glVertex2i(x2, y2);
glEnd();
point(x2, y2);
// TODO: no corner types (miter) yet
line(x, y, x1, y1);
line(x1, y1, x2, y2);
}
void Fl_OpenGL_Graphics_Driver::xyline(int x, int y, int x1) {
glBegin(GL_LINE_STRIP);
glVertex2i(x, y);
glVertex2i(x1, y);
glEnd();
point(x1, y);
float offset = line_width_ / 2.0f;
float xx = x, yy = y+0.5f, rr = x1+1.0f;
glRectf(xx, yy-offset, rr, yy+offset);
}
void Fl_OpenGL_Graphics_Driver::xyline(int x, int y, int x1, int y2) {
glBegin(GL_LINE_STRIP);
glVertex2i(x, y);
glVertex2i(x1, y);
glVertex2i(x1, y2);
glEnd();
point(x1, y2);
float offset = line_width_ / 2.0f;
float xx = x, yy = y+0.5f, rr = x1+0.5f, bb = y2+1.0f;
glRectf(xx, yy-offset, rr+offset, yy+offset);
glRectf(rr-offset, yy+offset, rr+offset, bb);
}
void Fl_OpenGL_Graphics_Driver::xyline(int x, int y, int x1, int y2, int x3) {
glBegin(GL_LINE_STRIP);
glVertex2i(x, y);
glVertex2i(x1, y);
glVertex2i(x1, y2);
glVertex2i(x3, y2);
glEnd();
point(x3, y2);
float offset = line_width_ / 2.0f;
float xx = x, yy = y+0.5f, xx1 = x1+0.5f, rr = x3+1.0f, bb = y2+0.5;
glRectf(xx, yy-offset, xx1+offset, yy+offset);
glRectf(xx1-offset, yy+offset, xx1+offset, bb+offset);
glRectf(xx1+offset, bb-offset, rr, bb+offset);
}
void Fl_OpenGL_Graphics_Driver::yxline(int x, int y, int y1) {
glBegin(GL_LINE_STRIP);
glVertex2i(x, y);
glVertex2i(x, y1);
glEnd();
point(x, y1);
float offset = line_width_ / 2.0f;
float xx = x+0.5f, yy = y, bb = y1+1.0f;
glRectf(xx-offset, yy, xx+offset, bb);
}
void Fl_OpenGL_Graphics_Driver::yxline(int x, int y, int y1, int x2) {
glBegin(GL_LINE_STRIP);
glVertex2i(x, y);
glVertex2i(x, y1);
glVertex2i(x2, y1);
glEnd();
point(x2, y1);
float offset = line_width_ / 2.0f;
float xx = x+0.5f, yy = y, rr = x2+1.0f, bb = y1+0.5f;
glRectf(xx-offset, yy, xx+offset, bb+offset);
glRectf(xx+offset, bb-offset, rr, bb+offset);
}
void Fl_OpenGL_Graphics_Driver::yxline(int x, int y, int y1, int x2, int y3) {
glBegin(GL_LINE_STRIP);
glVertex2i(x, y);
glVertex2i(x, y1);
glVertex2i(x2, y1);
glVertex2i(x2, y3);
glEnd();
point(x2, y3);
float offset = line_width_ / 2.0f;
float xx = x+0.5f, yy = y, yy1 = y1+0.5f, rr = x2+0.5f, bb = y3+1.0f;
glRectf(xx-offset, yy, xx+offset, yy1+offset);
glRectf(xx+offset, yy1-offset, rr+offset, yy1+offset);
glRectf(rr-offset, yy1+offset, rr+offset, bb);
}
void Fl_OpenGL_Graphics_Driver::loop(int x0, int y0, int x1, int y1, int x2, int y2) {
@@ -161,24 +165,197 @@ void Fl_OpenGL_Graphics_Driver::polygon(int x0, int y0, int x1, int y1, int x2,
glEnd();
}
void Fl_OpenGL_Graphics_Driver::focus_rect(int x, int y, int w, int h) {
float width = line_width_;
int stipple = line_stipple_;
line_style(FL_DOT, 1);
glBegin(GL_LINE_LOOP);
glVertex2f(x+0.5f, y+0.5f);
glVertex2f(x+w+0.5f, y+0.5f);
glVertex2f(x+w+0.5f, y+h+0.5f);
glVertex2f(x+0.5f, y+h+0.5f);
glEnd();
line_style(stipple, width);
}
// -----------------------------------------------------------------------------
static int gl_min(int a, int b) { return (a<b) ? a : b; }
static int gl_max(int a, int b) { return (a>b) ? a : b; }
enum {
kStateFull, // Region is the full window
kStateRect, // Region is a rectangle
kStateEmpty // Region is an empty space
};
typedef struct Fl_Gl_Region {
int x, y, w, h;
int gl_x, gl_y, gl_w, gl_h;
char state;
void set(int inX, int inY, int inW, int inH) {
if (inW<=0 || inH<=0) {
state = kStateEmpty;
x = inX; y = inY; w = 1; h = 1; // or 0?
} else {
x = inX; y = inY; w = inW; h = inH;
state = kStateRect;
}
Fl_Gl_Window *win = Fl_Gl_Window::current()->as_gl_window();
if (win) {
float scale = win->pixels_per_unit();
gl_x = x*scale;
gl_y = (win->h()-h-y+1)*scale;
gl_w = (w-1)*scale;
gl_h = (h-1)*scale;
if (inX<=0 && inY<=0 && inX+inW>win->w() && inY+inH>=win->h()) {
state = kStateFull;
}
} else {
state = kStateFull;
}
}
void set_full() { state = kStateFull; }
void set_empty() { state = kStateEmpty; }
void set_intersect(int inX, int inY, int inW, int inH, Fl_Gl_Region &g) {
if (g.state==kStateFull) {
set(inX, inY, inW, inH);
} else if (g.state==kStateEmpty) {
set_empty();
} else {
int rx = gl_max(inX, g.x);
int ry = gl_max(inY, g.y);
int rr = gl_min(inX+inW, g.x+g.w);
int rb = gl_max(inY+inH, g.y+g.h);
set(rx, ry, rr-rx, rb-ry);
}
}
void apply() {
if (state==kStateFull) {
glDisable(GL_SCISSOR_TEST);
} else {
glScissor(gl_x, gl_y, gl_w, gl_h);
glEnable(GL_SCISSOR_TEST);
}
}
} Fl_Gl_Region;
static int gl_rstackptr = 0;
static const int gl_region_stack_max = FL_REGION_STACK_SIZE - 1;
static Fl_Gl_Region gl_rstack[FL_REGION_STACK_SIZE];
/*
Intersect the given rect with the current rect, push the result on the stack,
and apply the new clipping area.
*/
void Fl_OpenGL_Graphics_Driver::push_clip(int x, int y, int w, int h) {
// TODO: implement OpenGL clipping
if (rstackptr < region_stack_max) rstack[++rstackptr] = 0L;
else Fl::warning("Fl_OpenGL_Graphics_Driver::push_clip: clip stack overflow!\n");
if (gl_rstackptr==gl_region_stack_max) {
Fl::warning("Fl_OpenGL_Graphics_Driver::push_clip: clip stack overflow!\n");
return;
}
if (gl_rstackptr==0) {
gl_rstack[gl_rstackptr].set(x, y, w, h);
} else {
gl_rstack[gl_rstackptr].set_intersect(x, y, w, h, gl_rstack[gl_rstackptr-1]);
}
gl_rstack[gl_rstackptr].apply();
gl_rstackptr++;
}
int Fl_OpenGL_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) {
// TODO: implement OpenGL clipping
X = x; Y = y; W = w; H = h;
return 0;
/*
Remove the current clipping area and apply the previous one on the stack.
*/
void Fl_OpenGL_Graphics_Driver::pop_clip() {
if (gl_rstackptr==0) {
glDisable(GL_SCISSOR_TEST);
Fl::warning("Fl_OpenGL_Graphics_Driver::pop_clip: clip stack underflow!\n");
return;
}
gl_rstackptr--;
restore_clip();
}
int Fl_OpenGL_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
// TODO: implement OpenGL clipping
return 1;
/*
Push a full area onton the stack, so no clipping will take place.
*/
void Fl_OpenGL_Graphics_Driver::push_no_clip() {
if (gl_rstackptr==gl_region_stack_max) {
Fl::warning("Fl_OpenGL_Graphics_Driver::push_no_clip: clip stack overflow!\n");
return;
}
gl_rstack[gl_rstackptr].set_full();
gl_rstack[gl_rstackptr].apply();
gl_rstackptr++;
}
/*
We don't know the format of clip regions of the default driver, so return NULL.
*/
Fl_Region Fl_OpenGL_Graphics_Driver::clip_region() {
return NULL;
}
/*
We don't know the format of clip regions of the default driver, so do the best
we can.
*/
void Fl_OpenGL_Graphics_Driver::clip_region(Fl_Region r) {
if (r==NULL) {
glDisable(GL_SCISSOR_TEST);
} else {
restore_clip();
}
}
/*
Apply the current clipping rect.
*/
void Fl_OpenGL_Graphics_Driver::restore_clip() {
// TODO: implement OpenGL clipping
fl_clip_state_number++;
if (gl_rstackptr==0) {
glDisable(GL_SCISSOR_TEST);
} else {
gl_rstack[gl_rstackptr-1].apply();
}
}
/*
Does the rectangle intersect the current clip region?
0 = regions don't intersect, nothing to draw
1 = region is fully inside current clipping region
2 = region is partially inside current clipping region
*/
int Fl_OpenGL_Graphics_Driver::not_clipped(int x, int y, int w, int h) {
if (gl_rstackptr==0)
return 1;
Fl_Gl_Region &g = gl_rstack[gl_rstackptr-1];
if (g.state==kStateFull)
return 1;
if (g.state==kStateEmpty)
return 0;
int r = x+w, b = y + h;
int gr = g.x+g.w, gb = g.y+g.h;
if (r<=g.x || x>=gr || b<=g.y || y>=gb) return 0;
if (x>=g.x && y>=g.y && r<=gr && b<=gb) return 1;
return 2;
}
/*
Calculate the intersection of the given rect and the clipping area.
Return 0 if the result did not change.
*/
int Fl_OpenGL_Graphics_Driver::clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) {
X = x; Y = y; W = w; H = h;
if (gl_rstackptr==0)
return 0;
Fl_Gl_Region &g = gl_rstack[gl_rstackptr-1];
if (g.state==kStateFull)
return 0;
int r = x+w, b = y + h;
int gr = g.x+g.w, gb = g.y+g.h;
X = gl_max(x, g.x);
Y = gl_max(y, g.y);
W = gl_min(r, gr) - X;
H = gl_min(b, gb) - Y;
return (x!=X || y!=Y || w!=W || h!=H);
}
+33
View File
@@ -64,6 +64,19 @@ void Fl::set_color(Fl_Color i, uchar red, uchar green, uchar blue) {
((unsigned)red<<24)+((unsigned)green<<16)+((unsigned)blue<<8));
}
/**
Sets an entry in the fl_color index table.
You can set it to any 8-bit RGBA color.
*/
void Fl::set_color(Fl_Color i, uchar red, uchar green, uchar blue, uchar alpha) {
Fl::set_color((Fl_Color)(i & 255),
((unsigned)red<<24)
|((unsigned)green<<16)
|((unsigned)blue<<8)
|(alpha^0xff));
}
void Fl::set_color(Fl_Color i, unsigned c)
{
@@ -96,6 +109,26 @@ void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue) {
blue = uchar(c>>8);
}
/**
Returns the RGBA value(s) for the given FLTK color index.
This form returns the red, green, blue, and alpha values
separately in referenced variables.
\see unsigned get_color(Fl_Color c)
*/
void Fl::get_color(Fl_Color i, uchar &red, uchar &green, uchar &blue, uchar &alpha) {
unsigned c;
if (i & 0xffffff00) c = (unsigned)i;
else c = fl_cmap[i];
red = uchar(c>>24);
green = uchar(c>>16);
blue = uchar(c>>8);
alpha = uchar(c^0x000000ff);
}
/**
Returns the weighted average color between the two given colors.
+10
View File
@@ -234,6 +234,16 @@ static void gtk_round_down_box(int x, int y, int w, int h, Fl_Color c) {
gtk_color(c);
draw(FILL, x, y, w, h, 2);
gtk_color(fl_color_average(FL_WHITE, c, 0.1f));
draw(LOWER_RIGHT, x+1, y, w-2, h, 2);
draw(LOWER_RIGHT, x, y, w, h, 3);
gtk_color(fl_color_average(FL_WHITE, c, 0.2f));
draw(LOWER_RIGHT, x+1, y, w-2, h, 1);
draw(LOWER_RIGHT, x, y, w, h, 2);
gtk_color(fl_color_average(FL_WHITE, c, 0.5f));
draw(LOWER_RIGHT, x+1, y, w-2, h, 0);
draw(LOWER_RIGHT, x, y, w, h, 1);
gtk_color(fl_color_average(FL_BLACK, c, 0.05f));
draw(UPPER_LEFT, x, y, w, h, 2);
draw(UPPER_LEFT, x+1, y, w-2, h, 1);
+20 -1
View File
@@ -139,9 +139,28 @@ CREATE_EXAMPLE (tile tile.cxx fltk)
CREATE_EXAMPLE (tiled_image tiled_image.cxx fltk)
CREATE_EXAMPLE (tree tree.fl fltk)
CREATE_EXAMPLE (twowin twowin.cxx fltk)
SET (UNITTEST_SRCS
unittests.cxx
unittest_about.cxx
unittest_points.cxx
unittest_complex_shapes.cxx
unittest_fast_shapes.cxx
unittest_circles.cxx
unittest_text.cxx
unittest_symbol.cxx
unittest_images.cxx
unittest_viewport.cxx
unittest_scrollbarsize.cxx
unittest_schemes.cxx
unittest_simple_terminal.cxx
)
if (OPENGL_FOUND)
CREATE_EXAMPLE (unittests "${UNITTEST_SRCS}" "fltk_gl;fltk;${OPENGL_LIBRARIES}") # opt. Fl_Gl_Window
else()
CREATE_EXAMPLE (unittests "${UNITTEST_SRCS}" fltk) # w/o Fl_Gl_Window
endif()
CREATE_EXAMPLE (utf8 utf8.cxx fltk)
CREATE_EXAMPLE (valuators valuators.fl fltk)
CREATE_EXAMPLE (unittests unittests.cxx fltk)
CREATE_EXAMPLE (windowfocus windowfocus.cxx fltk)
CREATE_EXAMPLE (wizard wizard.cxx fltk)
+40 -9
View File
@@ -16,6 +16,36 @@
include ../makeinclude
CPPUNITTEST = \
unittests.cxx \
unittest_about.cxx \
unittest_points.cxx \
unittest_complex_shapes.cxx \
unittest_fast_shapes.cxx \
unittest_circles.cxx \
unittest_text.cxx \
unittest_symbol.cxx \
unittest_images.cxx \
unittest_viewport.cxx \
unittest_scrollbarsize.cxx \
unittest_schemes.cxx \
unittest_simple_terminal.cxx
OBJUNITTEST = \
unittests.o \
unittest_about.o \
unittest_points.o \
unittest_complex_shapes.o \
unittest_fast_shapes.o \
unittest_circles.o \
unittest_text.o \
unittest_symbol.o \
unittest_images.o \
unittest_viewport.o \
unittest_scrollbarsize.o \
unittest_schemes.o \
unittest_simple_terminal.o
CPPFILES =\
adjuster.cxx \
animated.cxx \
@@ -103,13 +133,12 @@ CPPFILES =\
tiled_image.cxx \
tree.cxx \
twowin.cxx \
unittests.cxx \
utf8.cxx \
valuators.cxx \
windowfocus.cxx
windowfocus.cxx \
$(CPPUNITTEST)
ALL = \
unittests$(EXEEXT) \
animated$(EXEEXT) \
adjuster$(EXEEXT) \
arc$(EXEEXT) \
@@ -200,7 +229,8 @@ GLALL = \
fullscreen$(EXEEXT) \
gl_overlay$(EXEEXT) \
glpuzzle$(EXEEXT) \
shape$(EXEEXT)
shape$(EXEEXT) \
unittests$(EXEEXT)
all: $(ALL) $(GLDEMOS)
@@ -299,11 +329,7 @@ uninstall-osx:
$(ALL): $(LIBNAME)
# General demos...
unittests$(EXEEXT): unittests.o
unittests.o: unittests.cxx unittest_about.cxx unittest_points.cxx unittest_lines.cxx unittest_circles.cxx \
unittest_rects.cxx unittest_text.cxx unittest_symbol.cxx unittest_viewport.cxx unittest_images.cxx \
unittest_schemes.cxx unittest_scrollbarsize.cxx unittest_simple_terminal.cxx
unittests$(EXEEXT): $(OBJUNITTEST)
adjuster$(EXEEXT): adjuster.o
@@ -626,6 +652,11 @@ gl_overlay$(EXEEXT): gl_overlay.o
$(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ gl_overlay.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS)
$(OSX_ONLY) ../fltk-config --post $@
unittests$(EXEEXT): $(OBJUNITTEST)
echo Linking $@...
$(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJUNITTEST) $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS)
$(OSX_ONLY) ../fltk-config --post $@
shape$(EXEEXT): shape.o
echo Linking $@...
$(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ shape.o $(LINKFLTKGL) $(LINKFLTK) $(GLDLIBS)
+17 -1
View File
@@ -18,6 +18,7 @@
#include <config.h>
#include <FL/Fl.H>
#include <FL/fl_ask.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
@@ -184,6 +185,12 @@ void print_cb(Fl_Widget *w, void *data)
#define MARGIN2 (MARGIN*2)
#define MARGIN3 (MARGIN*3)
void show_info_cb(Fl_Widget*, void*) {
fl_message("This is an example of using FLTK widgets inside OpenGL windows.\n"
"Multiple widgets can be added to Fl_Gl_Windows. They will be\n"
"rendered as overlays over the scene.");
}
void makeform(const char *name) {
// Widget's XYWH's
int form_w = 800 + 4 * MARGIN; // main window width
@@ -207,6 +214,14 @@ void makeform(const char *name) {
lt_grp->begin();
// left GL window
lt_cube = new cube_box(lt_cub_x, lt_cub_y, lt_cub_w, lt_cub_h, 0);
lt_cube->begin();
Fl_Widget *w = new Fl_Button(10, 10, 120, 30, "FLTK over GL");
w->color(FL_FREE_COLOR);
w->box(FL_BORDER_BOX );
w->callback(show_info_cb);
lt_cube->end();
// center group
Fl_Group *ct_grp = new Fl_Group(ct_grp_x, ct_grp_y, ct_grp_w, ct_grp_h);
ct_grp->begin();
@@ -238,6 +253,7 @@ void makeform(const char *name) {
int main(int argc, char **argv) {
Fl::use_high_res_GL(1);
Fl::set_color(FL_FREE_COLOR, 255, 255, 0, 75);
makeform(argv[0]);
speed->bounds(4,0);
#if HAVE_GL
@@ -246,7 +262,7 @@ int main(int argc, char **argv) {
speed->value(lt_cube->speed = rt_cube->speed = 0.0);
#endif
size->bounds(4,0.01);
size->value(lt_cube->size = rt_cube->size = 1.0);
size->value(lt_cube->size = rt_cube->size = 3.0);
flat->value(1); lt_cube->wire = 0; rt_cube->wire = 1;
form->label("cube");
form->show(argc,argv);
+2 -2
View File
@@ -2535,9 +2535,9 @@ unittests.o: ../FL/platform_types.h
unittests.o: unittest_about.cxx
unittests.o: unittest_circles.cxx
unittests.o: unittest_images.cxx
unittests.o: unittest_lines.cxx
unittests.o: unittest_complex_shapes.cxx
unittests.o: unittest_points.cxx
unittests.o: unittest_rects.cxx
unittests.o: unittest_fast_shapes.cxx
unittests.o: unittest_schemes.cxx
unittests.o: unittest_scrollbarsize.cxx
unittests.o: unittest_simple_terminal.cxx
+3 -1
View File
@@ -14,6 +14,8 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <FL/Fl_Help_View.H>
//
@@ -51,4 +53,4 @@ public:
}
};
UnitTest about("About...", About::create);
UnitTest about(kTestAbout, "About...", About::create);
+184 -52
View File
@@ -14,71 +14,203 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <config.h>
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>
#include <FL/math.h>
#if HAVE_GL
#include <FL/Fl_Gl_Window.H>
#endif
//
// --- test drawing circles and arcs ------
//
void arc(int xi, int yi, int w, int h, double a1, double a2)
{
if (a2<=a1) return;
double rx = w/2.0;
double ry = h/2.0;
double x = xi + rx + 0.5;
double y = yi + ry + 0.5;
double circ = M_PI*0.5*(rx+ry);
int i, segs = circ * (a2-a1) / 100;
if (segs<3) segs = 3;
int px, py;
a1 = a1/180*M_PI;
a2 = a2/180*M_PI;
double step = (a2-a1)/segs;
int nx = x + cos(a1)*rx;
int ny = y - sin(a1)*ry;
fl_point(nx, ny);
for (i=segs; i>0; i--) {
a1+=step;
px = nx; py = ny;
nx = x + cos(a1)*rx;
ny = y - sin(a1)*ry;
//fl_line(px, py, nx, ny);
fl_point(nx, ny);
}
}
void draw_circles() {
int a = 0, b = 0, w=40, h=40;
// ---- 1: draw a circle and a filled circle
fl_color(FL_RED);
arc(a+1, b+1, w-2, h-2, 0.0, 360.0);
fl_color(FL_GREEN);
arc(a, b, w, h, 0.0, 360.0);
arc(a+2, b+2, w-4, h-4, 0.0, 360.0);
fl_color(FL_BLACK);
fl_arc(a+1, b+1, w-1, h-1, 0.0, 360.0);
// ----
fl_color(FL_RED);
arc(a+1+50, b+1, w-2, h-2, 0.0, 360.0);
fl_color(FL_GREEN);
arc(a+50, b, w, h, 0.0, 360.0);
fl_color(FL_BLACK);
fl_pie(a+1+50, b+1, w-1, h-1, 0.0, 360.0);
b+=44;
// ---- 2: draw arcs and pies
fl_color(FL_RED);
// arc(a-5, b-5, w+10, h+10, 45.0, 315.0);
arc(a+1, b+1, w-2, h-2, 45.0, 315.0);
// arc(a+5, b+5, w-10, h-10, 45.0, 315.0);
// arc(a+10, b+10, w-20, h-20, 45.0, 315.0);
fl_color(FL_GREEN);
arc(a, b, w, h, 45.0, 315.0);
arc(a+2, b+2, w-4, h-4, 45.0, 315.0);
fl_color(FL_BLACK);
// fl_arc(a-5, b-5, w+10, h+10, 45.0, 315.0);
fl_arc(a+1, b+1, w-1, h-1, 45.0, 315.0);
// fl_arc(a+5, b+5, w-10, h-10, 45.0, 315.0);
// fl_arc(a+10, b+10, w-20, h-20, 45.0, 315.0);
fl_color(FL_RED);
// ----
arc(a+1+50, b+1, w-2, h-2, 45.0, 315.0);
fl_line(a+50+20, b+20, a+50+20+14, b+20-14);
fl_line(a+50+20, b+20, a+50+20+14, b+20+14);
fl_color(FL_GREEN);
arc(a+50, b, w, h, 45.0, 315.0);
fl_line(a+50+21, b+20, a+50+21+14, b+20-14);
fl_line(a+50+21, b+20, a+50+21+14, b+20+14);
fl_color(FL_BLACK);
fl_pie(a+1+50, b+1, w-1, h-1, 45.0, 315.0);
}
#if HAVE_GL
class GLCircleTest : public Fl_Gl_Window {
public:
GLCircleTest(int x, int y, int w, int h)
: Fl_Gl_Window(x, y, w, h) {
box(FL_FLAT_BOX);
}
void draw() {
draw_begin();
Fl_Window::draw();
draw_circles();
draw_end();
}
};
#endif
class NativeCircleTest : public Fl_Window {
public:
NativeCircleTest(int x, int y, int w, int h)
: Fl_Window(x, y, w, h) {
box(FL_FLAT_BOX);
end();
}
void draw() {
Fl_Window::draw();
draw_circles();
}
};
//
//------- test the circle drawing capabilities of this implementation ----------
//
class CircleTest : public Fl_Box {
class CircleTest : public Fl_Group {
public:
static Fl_Widget *create() {
return new CircleTest(TESTAREA_X, TESTAREA_Y, TESTAREA_W, TESTAREA_H);
}
CircleTest(int x, int y, int w, int h) : Fl_Box(x, y, w, h) {
label("testing int drawing of circles and ovals (fl_arc, fl_pie)\n"
CircleTest(int x, int y, int w, int h) : Fl_Group(x, y, w, h) {
label("Testing fast circle, arc, and pie drawing\n\n"
"No red lines should be visible. "
"If you see bright red pixels, the circle drawing alignment is off. "
"If you see dark red pixels, your system supports anti-aliasing "
"which should be of no concern. "
"The green rectangles should not be overwritten by circle drawings.");
"The green outlines should not be overwritten by circle drawings.");
align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP);
box(FL_BORDER_BOX);
}
void draw() {
Fl_Box::draw();
int a = x()+10, b = y()+10; fl_color(FL_BLACK); fl_rect(a, b, 100, 100);
// test fl_arc for full circles
fl_color(FL_GREEN); fl_rect(a+ 9, b+ 9, 33, 33);
fl_color(FL_RED); fl_xyline(a+24, b+10, a+27); fl_xyline(a+24, b+40, a+27);
fl_yxline(a+10, b+24, b+27); fl_yxline(a+40, b+24, b+27);
fl_color(FL_BLACK); fl_arc(a+10, b+10, 31, 31, 0.0, 360.0);
// test fl_arc segmet 1
fl_color(FL_GREEN); fl_rect(a+54, b+ 4, 43, 43);
fl_rect(a+54, b+4, 18, 18); fl_rect(a+79, b+29, 18, 18);
fl_color(FL_RED); fl_point(a+55, b+30); fl_point(a+70, b+45);
fl_point(a+80, b+5); fl_point(a+95, b+20);
fl_color(FL_BLACK); fl_arc(a+65, b+ 5, 31, 31, -35.0, 125.0);
// test fl_arc segmet 2
fl_color(FL_BLACK); fl_arc(a+55, b+15, 31, 31, 145.0, 305.0);
// test fl_pie for full circles
fl_color(FL_RED); fl_xyline(a+24, b+60, a+27); fl_xyline(a+24, b+90, a+27);
fl_yxline(a+10, b+74, b+77); fl_yxline(a+40, b+74, b+77);
fl_color(FL_GREEN); fl_rect(a+ 9, b+59, 33, 33);
fl_color(FL_BLACK); fl_pie(a+10, b+60, 31, 31, 0.0, 360.0);
// test fl_pie segmet 1
fl_color(FL_GREEN); fl_rect(a+54, b+54, 43, 43);
fl_rect(a+54, b+54, 18, 18); fl_rect(a+79, b+79, 18, 18);
fl_point(a+79, b+71); fl_point(a+71, b+79);
fl_color(FL_RED); fl_point(a+55, b+80); fl_point(a+70, b+95);
fl_point(a+80, b+55); fl_point(a+95, b+70);
fl_point(a+81, b+69); fl_point(a+69, b+81);
fl_color(FL_BLACK); fl_pie(a+65, b+55, 31, 31, -30.0, 120.0);
// test fl_pie segmet 2
fl_color(FL_BLACK); fl_pie(a+55, b+65, 31, 31, 150.0, 300.0);
//---- oval testing (horizontal squish)
a +=120; b += 0; fl_color(FL_BLACK); fl_rect(a, b, 100, 100);
fl_color(FL_GREEN);
fl_rect(a+19, b+9, 63, 33); fl_rect(a+19, b+59, 63, 33);
fl_color(FL_BLACK);
fl_arc(a+20, b+10, 61, 31, 0, 360); fl_pie(a+20, b+60, 61, 31, 0, 360);
//---- oval testing (horizontal squish)
a += 120; b += 0; fl_color(FL_BLACK); fl_rect(a, b, 100, 100);
fl_color(FL_GREEN);
fl_rect(a+9, b+19, 33, 63); fl_rect(a+59, b+19, 33, 63);
fl_color(FL_BLACK);
fl_arc(a+10, b+20, 31, 61, 0, 360); fl_pie(a+60, b+20, 31, 61, 0, 360);
int a = x+16, b = y+34;
Fl_Box *t = new Fl_Box(a, b-24, 80, 18, "native");
t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
/* NativeCircleTest *nr = */ new NativeCircleTest(a+23, b-1, 200, 200);
t = new Fl_Box(a, b, 18, 18, "1");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing circle alignment.\n\n"
// Description:
"This draws a black circle and a black disc, surrounded by a green frame.\n\n"
// Things to look out for:
"If green pixels are missing, circle drawing must be adjusted (see fl_arc, fl_pie).\n\n"
"If red pixels are showing, line width or aligment may be off."
);
b+=44;
t = new Fl_Box(a, b, 18, 18, "2");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing arc and pie drawing.\n\n"
// Description:
"This draws a black frame, surrounded on the inside and outside by a green frame.\n\n"
// Things to look out for:
"If green pixels are missing or red pixels are showing, rectangular frame drawing schould be adjusted (see fl_rect).\n\n"
"If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted."
);
#if HAVE_GL
a = x+16+250, b = y+34;
t = new Fl_Box(a, b-24, 80, 18, "OpenGL");
t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
/* GLCircleTest *glr = */ new GLCircleTest(a+31, b-1, 200, 200);
t = new Fl_Box(a, b, 26, 18, "1a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing circle alignment.\n\n"
// Description:
"This draws a black circle and a black disc, surrounded by a green frame.\n\n"
// Things to look out for:
"If green pixels are missing, circle drawing must be adjusted (see fl_arc, fl_pie).\n\n"
"If red pixels are showing, line width or aligment may be off."
);
b+=44;
t = new Fl_Box(a, b, 26, 18, "2a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing arc and pie drawing.\n\n"
// Description:
"This draws a black frame, surrounded on the inside and outside by a green frame.\n\n"
// Things to look out for:
"If green pixels are missing or red pixels are showing, rectangular frame drawing schould be adjusted (see fl_rect).\n\n"
"If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted."
);
#endif
t = new Fl_Box(x+w-1,y+h-1, 1, 1);
resizable(t);
}
};
UnitTest circle("circles and arcs", CircleTest::create);
UnitTest circle(kTestCircles, "Circles and Arcs", CircleTest::create);
@@ -14,23 +14,67 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>
#if 0
// TODO:
void fl_push_matrix()
void fl_pop_matrix()
void fl_scale(double x,double y)
void fl_scale(double x)
void fl_translate(double x,double y)
void fl_rotate(double d)
void fl_mult_matrix(double a,double b,double c,double d,double x,double y)
double fl_transform_x(double x, double y)
double fl_transform_y(double x, double y)
double fl_transform_dx(double x, double y)
double fl_transform_dy(double x, double y)
void fl_transformed_vertex(double xf, double yf)
void fl_begin_points()
void fl_end_points()
void fl_begin_line()
void fl_end_line()
void fl_begin_loop()
void fl_end_loop()
void fl_begin_polygon()
void fl_end_polygon()
void fl_begin_complex_polygon()
void fl_gap()
void fl_end_complex_polygon()
void fl_vertex(double x,double y)
void fl_curve(double X0, double Y0, double X1, double Y1, double X2, double Y2, double X3, double Y3)
void fl_arc(double x, double y, double r, double start, double end)
void fl_circle(double x, double y, double r)
#endif
//
//------- test the line drawing capabilities of this implementation ----------
//------- test Complex Shape drawing capabilities of this implementation ----------
//
class LineTest : public Fl_Box {
class ComplexShapesTest : public Fl_Box {
public:
static Fl_Widget *create() {
return new LineTest(TESTAREA_X, TESTAREA_Y, TESTAREA_W, TESTAREA_H);
return new ComplexShapesTest(TESTAREA_X, TESTAREA_Y, TESTAREA_W, TESTAREA_H);
}
LineTest(int x, int y, int w, int h) : Fl_Box(x, y, w, h) {
label("testing the integer based fl_line calls\n"
"No red pixels should be visible.\n"
"If you see bright red pixels, the line drawing alignment is off,\n"
"or the last pixel in a line does not get drawn.\n"
"If you see dark red pixels, anti-aliasing must be switched off.");
ComplexShapesTest(int x, int y, int w, int h) : Fl_Box(x, y, w, h) {
label("Testing complex shape drawing.\n\n"
"Complex Shapes in FLTK are rendered using floating point coordinates "
"which can be transformed through a matrix.");
align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP);
box(FL_BORDER_BOX);
}
@@ -74,4 +118,4 @@ public:
}
};
UnitTest lines("drawing lines", LineTest::create);
//UnitTest lines(kTestComplexShapes, "Complex Shapes", ComplexShapesTest::create);
+383
View File
@@ -0,0 +1,383 @@
//
// Unit tests for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2010 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <config.h>
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H> // fl_text_extents()
#if HAVE_GL
#include <FL/Fl_Gl_Window.H>
#endif
#if 0
// TODO:
void fl_line(int x, int y, int x1, int y1)
void fl_line(int x, int y, int x1, int y1, int x2, int y2)
Draw one or two lines between the given points.
void fl_loop(int x, int y, int x1, int y1, int x2, int y2)
void fl_loop(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3)
Outline a 3 or 4-sided polygon with lines.
void fl_polygon(int x, int y, int x1, int y1, int x2, int y2)
void fl_polygon(int x, int y, int x1, int y1, int x2, int y2, int x3, int y3)
Draw vertical and horizontal lines. A vertical line is drawn first, then a horizontal, then a vertical.
#endif
//
// --- test drawing shapes that are not transformed by the drawing matrix ------
//
void draw_fast_shapes() {
int a = 0, b = 0, i;
// 1: draw a filled rectangle (fl_rectf)
fl_color(FL_GREEN);
for (i=0; i<=40; i++) { fl_point(a+i, b); fl_point(a+i, b+20); }
for (i=0; i<=20; i++) { fl_point(a, b+i); fl_point(a+40, b+i); }
fl_color(FL_RED);
for (i=1; i<=39; i++) { fl_point(a+i, b+1); fl_point(a+i, b+19); }
for (i=1; i<=19; i++) { fl_point(a+1, b+i); fl_point(a+39, b+i); }
fl_color(FL_BLACK);
fl_rectf(a+1, b+1, 39, 19);
// 2: draw a one units wide frame
b+=24;
fl_color(FL_GREEN);
for (i=0; i<=40; i++) { fl_point(a+i, b); fl_point(a+i, b+20); }
for (i=0; i<=20; i++) { fl_point(a, b+i); fl_point(a+40, b+i); }
fl_color(FL_GREEN);
for (i=2; i<=38; i++) { fl_point(a+i, b+2); fl_point(a+i, b+18); }
for (i=2; i<=18; i++) { fl_point(a+2, b+i); fl_point(a+38, b+i); }
fl_color(FL_RED);
for (i=1; i<=39; i++) { fl_point(a+i, b+1); fl_point(a+i, b+19); }
for (i=1; i<=19; i++) { fl_point(a+1, b+i); fl_point(a+39, b+i); }
fl_color(FL_BLACK);
fl_rect(a+1, b+1, 39, 19);
// 3: draw a three units wide frame
b+=24;
fl_color(FL_GREEN);
fl_rect(a, b, 41, 21);
fl_rect(a+4, b+4, 33, 13);
fl_color(FL_RED);
fl_rect(a+1, b+1, 39, 19);
fl_rect(a+3, b+3, 35, 15);
fl_color(FL_BLACK);
fl_line_style(FL_SOLID, 3);
fl_rect(a+2, b+2, 37, 17);
fl_line_style(FL_SOLID, 1);
// 4: draw fl_xyline
b+=24;
fl_color(FL_GREEN);
fl_rect(a, b+8, 41, 3); // single line
fl_rect(a+45, b, 41, 3); // horizontal, then vertical line
fl_rect(a+83, b, 3, 21);
fl_rect(a+90, b, 21, 3); // horizontal, vertical, horizontal line
fl_rect(a+109, b, 3, 21);
fl_rect(a+109, b+18, 21, 3);
fl_color(FL_RED);
fl_rectf(a+1, b+9, 39, 1); // single line
fl_rectf(a+46, b+1, 39, 1); // two lines
fl_rectf(a+84, b+1, 1, 19);
fl_rectf(a+91, b+1, 20, 1); // three lines
fl_rectf(a+110, b+1, 1, 19);
fl_rectf(a+110, b+19, 19, 1); // three lines
fl_color(FL_BLACK);
fl_xyline(a+1, b+9, a+39);
fl_xyline(a+46, b+1, a+84, b+19);
fl_xyline(a+91, b+1, a+110, b+19, a+128);
b+=24;
fl_color(FL_GREEN);
fl_rect(a, b+7, 41, 5); // single line
fl_rect(a+45, b, 41, 5); // horizontal, then vertical line
fl_rect(a+81, b, 5, 21);
fl_rect(a+90, b, 22, 5); // horizontal, vertical, horizontal line
fl_rect(a+108, b, 5, 21);
fl_rect(a+108, b+16, 22, 5);
fl_color(FL_RED);
fl_rectf(a+1, b+8, 39, 3); // single line
fl_rectf(a+46, b+1, 39, 3); // two lines
fl_rectf(a+82, b+1, 3, 19);
fl_rectf(a+91, b+1, 20, 3); // three lines
fl_rectf(a+109, b+1, 3, 19);
fl_rectf(a+109, b+17, 20, 3); // three lines
fl_color(FL_BLACK);
fl_line_style(FL_SOLID, 3);
fl_xyline(a+1, b+9, a+39);
fl_xyline(a+46, b+2, a+83, b+19);
fl_xyline(a+91, b+2, a+110, b+18, a+128);
fl_line_style(FL_SOLID, 1);
// 5: draw fl_xyline
b+=24;
fl_color(FL_GREEN);
fl_rect(a+9, b, 3, 21); // single line
fl_rect(a+45, b, 3, 21); // horizontal, then vertical line
fl_rect(a+45, b+18, 41, 3);
fl_rect(a+90, b, 3, 11); // horizontal, vertical, horizontal line
fl_rect(a+90, b+9, 40, 3);
fl_rect(a+127, b+9, 3, 12);
fl_color(FL_RED);
fl_rectf(a+10, b+1, 1, 19); // single line
fl_rectf(a+46, b+1, 1, 19); // two lines
fl_rectf(a+46, b+19, 39, 1);
fl_rectf(a+91, b+1, 1, 10); // three lines
fl_rectf(a+91, b+10, 38, 1);
fl_rectf(a+128, b+10, 1, 10); // three lines
fl_color(FL_BLACK);
fl_yxline(a+10, b+1, b+19);
fl_yxline(a+46, b+1, b+19, a+84);
fl_yxline(a+91, b+1, b+10, a+128, b+19);
b+=24;
fl_color(FL_GREEN);
fl_rect(a+8, b, 5, 21); // single line
fl_rect(a+45, b, 5, 21); // horizontal, then vertical line
fl_rect(a+45, b+16, 41, 5);
fl_rect(a+90, b, 5, 11); // horizontal, vertical, horizontal line
fl_rect(a+90, b+8, 40, 5);
fl_rect(a+125, b+8, 5, 13);
fl_color(FL_RED);
fl_rectf(a+9, b+1, 3, 19); // single line
fl_rectf(a+46, b+1, 3, 19); // two lines
fl_rectf(a+46, b+17, 39, 3);
fl_rectf(a+91, b+1, 3, 10); // three lines
fl_rectf(a+91, b+9, 38, 3);
fl_rectf(a+126, b+9, 3, 11); // three lines
fl_color(FL_BLACK);
fl_line_style(FL_SOLID, 3);
fl_yxline(a+10, b+1, b+19);
fl_yxline(a+47, b+1, b+18, a+84);
fl_yxline(a+92, b+1, b+10, a+127, b+19);
fl_line_style(FL_SOLID, 1);
// 6: fast diagonal lines
b+=24;
fl_color(FL_GREEN);
fl_point(a, b); fl_point(a+1, b); fl_point(a, b+1);
fl_point(a+20, b+20); fl_point(a+19, b+20); fl_point(a+20, b+19);
fl_color(FL_RED);
fl_point(a+1, b+1); fl_point(a+19, b+19);
fl_color(FL_BLACK);
fl_line(a+1, b+1, a+19, b+19);
fl_color(FL_GREEN);
fl_point(a+25+1, b); fl_point(a+25, b+1); fl_point(a+25+4, b); fl_point(a+25, b+4);
fl_point(a+25+20, b+19); fl_point(a+25+19, b+20); fl_point(a+25+16, b+20); fl_point(a+25+20, b+16);
fl_color(FL_RED);
fl_point(a+25+2, b+2); fl_point(a+25+18, b+18);
fl_color(FL_BLACK);
fl_line_style(FL_SOLID, 5);
fl_line(a+25+1, b+1, a+25+19, b+19);
fl_line(a+50+1, b+1, a+50+20, b+20, a+50+39, b+1);
fl_line_style(FL_SOLID, 1);
}
#if HAVE_GL
class GLRectTest : public Fl_Gl_Window {
public:
GLRectTest(int x, int y, int w, int h)
: Fl_Gl_Window(x, y, w, h) {
box(FL_FLAT_BOX);
}
void draw() {
draw_begin();
fl_color(color());
fl_rectf(0, 0, w(), h());
draw_fast_shapes();
draw_end();
}
};
#endif
class NativeRectTest : public Fl_Window {
public:
NativeRectTest(int x, int y, int w, int h)
: Fl_Window(x, y, w, h) {
box(FL_FLAT_BOX);
end();
}
void draw() {
Fl_Window::draw();
draw_fast_shapes();
}
};
class RectTest : public Fl_Group { // 520 x 365
public:
static Fl_Widget *create() {
return new RectTest(TESTAREA_X, TESTAREA_Y, TESTAREA_W, TESTAREA_H);
}
RectTest(int x, int y, int w, int h) : Fl_Group(x, y, w, h) {
label("Testing FLTK fast shape calls.\n"
"These calls draw horizontal and vertical lines, frames, and rectangles.\n\n"
"No red pixels should be visible. "
"If you see bright red lines, or if parts of the green frames are hidden, "
"drawing alignment is off.");
align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP);
box(FL_BORDER_BOX);
int a = x+16, b = y+34;
Fl_Box *t = new Fl_Box(a, b-24, 80, 18, "native");
t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
/* NativeRectTest *nr = */ new NativeRectTest(a+23, b-1, 200, 200);
t = new Fl_Box(a, b, 18, 18, "1");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing filled rectangle alignment.\n\n"
// Description:
"This draws a black rectangle, surrounded by a green frame.\n\n"
// Things to look out for:
"If green pixels are missing, filled rectangles draw too big (see fl_rectf).\n\n"
"If red pixels are showing, filled rectangles are drawn too small."
);
b+=24;
t = new Fl_Box(a, b, 18, 18, "2");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing rectangle frame alignment.\n\n"
// Description:
"This draws a black frame, surrounded on the inside and outside by a green frame.\n\n"
// Things to look out for:
"If green pixels are missing or red pixels are showing, rectangular frame drawing schould be adjusted (see fl_rect).\n\n"
"If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted."
);
b+=24;
t = new Fl_Box(a, b, 18, 18, "3");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing scaled frame alignment.\n\n"
// Description:
"This draws a 3 units wide black frame, surrounded on the inside and outside by a green frame.\n\n"
// Things to look out for:
"If green pixels are missing or red pixels are showing, line width schould be adjusted (see fl_line_style).\n\n"
"If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted."
);
b+=24;
t = new Fl_Box(a, b, 18, 18, "4");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing fl_xyline.\n\n"
// Description:
"This draws 3 versions of fl_xyline surronded with a green outline.\n\n"
// Things to look out for:
"If green pixels are missing or red pixels are showing, fl_xyline must be adjusted."
);
b+=48;
t = new Fl_Box(a, b, 18, 18, "5");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing fl_yxline.\n\n"
// Description:
"This draws 3 versions of fl_yxline surronded with a green outline.\n\n"
// Things to look out for:
"If green pixels are missing or red pixels are showing, fl_yxline must be adjusted."
);
b+=48;
t = new Fl_Box(a, b, 18, 18, "6");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing fl_line(int...).\n\n"
// Description:
"This draws 2 lines at differnet widths, and one connected line.\n\n"
// Things to look out for:
"Green and red pixels mark the beginning and end of single lines."
"The line caps should be flat, the joints shoould be of type \"miter\"."
);
#if HAVE_GL
a = x+16+250, b = y+34;
t = new Fl_Box(a, b-24, 80, 18, "OpenGL");
t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
/*GLRectTest *glr = */ new GLRectTest(a+31, b-1, 200, 200);
t = new Fl_Box(a, b, 26, 18, "1a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing filled rectangle alignment.\n\n"
// Description:
"This draws a black rectangle, surrounded by a green frame.\n\n"
// Things to look out for:
"If green pixels are missing, filled rectangles draw too big (see fl_rectf).\n\n"
"If red pixels are showing, filled rectangles are drawn too small."
);
b+=24;
t = new Fl_Box(a, b, 26, 18, "2a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing rectangle frame alignment.\n\n"
// Description:
"This draws a black frame, surrounded on the inside and outside by a green frame.\n\n"
// Things to look out for:
"If green pixels are missing or red pixels are showing, rectangular frame drawing schould be adjusted (see fl_rect).\n\n"
"If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted."
);
b+=24;
t = new Fl_Box(a, b, 26, 18, "3a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing scaled frame alignment.\n\n"
// Description:
"This draws a 3 units wide black frame, surrounded on the inside and outside by a green frame.\n\n"
// Things to look out for:
"If green pixels are missing or red pixels are showing, line width schould be adjusted (see fl_line_style).\n\n"
"If red pixels show in the corners of the frame in hidpi mode, line endings should be adjusted."
);
b+=24;
t = new Fl_Box(a, b, 26, 18, "4a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing fl_xyline.\n\n"
// Description:
"This draws 3 versions of fl_xyline surronded with a green outline.\n\n"
// Things to look out for:
"If green pixels are missing or red pixels are showing, fl_xyline must be adjusted."
);
b+=48;
t = new Fl_Box(a, b, 26, 18, "5a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing fl_yxline.\n\n"
// Description:
"This draws 3 versions of fl_yxline surronded with a green outline.\n\n"
// Things to look out for:
"If green pixels are missing or red pixels are showing, fl_yxline must be adjusted."
);
b+=48;
t = new Fl_Box(a, b, 26, 18, "6a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing fl_line(int...).\n\n"
// Description:
"This draws 2 lines at differnet widths, and one connected line.\n\n"
// Things to look out for:
"Green and red pixels mark the beginning and end of single lines."
"The line caps should be flat, the joints shoould be of type \"miter\"."
);
#endif
t = new Fl_Box(x+w-1,y+h-1, 1, 1);
resizable(t);
}
};
UnitTest rects(kTestFastShapes, "Fast Shapes", RectTest::create);
+5 -1
View File
@@ -14,12 +14,16 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <FL/Fl_Group.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Radio_Button.H>
#include <FL/Fl_Check_Button.H>
#include <FL/fl_draw.H>
#include <stdlib.h>
// Note: currently (March 2010) fl_draw_image() supports transparency with
// alpha channel only on Apple (Mac OS X), but Fl_RGB_Image->draw()
// supports transparency on all platforms !
@@ -291,4 +295,4 @@ Fl_RGB_Image *ImageTest::i_ga = 0;
Fl_RGB_Image *ImageTest::i_rgb = 0;
Fl_RGB_Image *ImageTest::i_rgba = 0;
UnitTest images("drawing images", ImageTest::create);
UnitTest images(kTestImages, "Drawing Images", ImageTest::create);
+279 -27
View File
@@ -14,41 +14,293 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <config.h>
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>
#if HAVE_GL
#include <FL/Fl_Gl_Window.H>
#endif
//
//------- test the point drawing capabilities of this implementation ----------
//
class PointTest : public Fl_Box {
class PointTestWin : public Fl_Window {
public:
static Fl_Widget *create() {
return new PointTest(TESTAREA_X, TESTAREA_Y, TESTAREA_W, TESTAREA_H);
}
PointTest(int x, int y, int w, int h) : Fl_Box(x, y, w, h) {
label("testing the fl_point call\n"
"You should see four pixels each in black, red, green and blue. "
"Make sure that pixels are not anti-aliased (blurred across multiple pixels)!");
align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP);
box(FL_BORDER_BOX);
}
PointTestWin(int x, int y, int w, int h) :
Fl_Window(x, y, w, h) { end(); }
void draw() {
Fl_Box::draw();
int a = x()+10, b = y()+10;
fl_color(FL_WHITE); fl_rectf(a, b, 90, 90);
fl_color(FL_BLACK); fl_rect(a, b, 90, 90);
fl_point(a+10, b+10); fl_point(a+20, b+20);
fl_point(a+10, b+20); fl_point(a+20, b+10);
fl_color(FL_RED); a = x()+70;
fl_point(a+10, b+10); fl_point(a+20, b+20);
fl_point(a+10, b+20); fl_point(a+20, b+10);
fl_color(FL_GREEN); a = x()+10; b = y()+70;
fl_point(a+10, b+10); fl_point(a+20, b+20);
fl_point(a+10, b+20); fl_point(a+20, b+10);
fl_color(FL_BLUE); a = x()+70;
fl_point(a+10, b+10); fl_point(a+20, b+20);
fl_point(a+10, b+20); fl_point(a+20, b+10);
int i;
fl_color(FL_WHITE);
fl_rectf(0, 0, 10, 10);
fl_color(FL_BLACK);
for (i=0; i<10; i++) {
fl_point(i, 0);
fl_point(i, 9);
}
for (i=0; i<10; i++) {
fl_point(0, i);
fl_point(9, i);
}
}
};
UnitTest points("drawing points", PointTest::create);
#if HAVE_GL
class GLTestWin : public Fl_Gl_Window {
public:
GLTestWin(int x, int y, int w, int h) :
Fl_Gl_Window(x, y, w, h) {
box(FL_FLAT_BOX);
end();
}
void draw() {
Fl_Gl_Window::draw_begin();
Fl_Window::draw();
int a = -24, b = 5-9, i, j;
// Test 1a: pixel size
fl_color(FL_WHITE); fl_rectf(a+24, b+9-5, 10, 10);
fl_color(FL_BLACK);
for (i=0; i<8; i++)
for (j=0; j<8; j++)
if ((i+j)&1)
fl_point(a+i+24+1, b+j+9-5+1);
// Test 2a: pixel color
for (int n=0; n<3; n++) {
static Fl_Color lut[3] = { FL_RED, FL_GREEN, FL_BLUE };
int yy = b+9-5+24 + 16*n;
fl_color(FL_WHITE); fl_rectf(a+24, yy, 10, 10);
fl_color(lut[n]);
for (i=0; i<8; i++)
for (j=0; j<8; j++)
fl_point(a+i+24+1, yy+j+1);
}
// Test 3a: pixel alignment inside windows (drawing happens in PointTestWin)
int xx = a+24, yy = b+2*24+2*16+9-5;
fl_color(FL_RED);
for (i=0; i<10; i++) {
fl_point(xx-1, yy+i);
fl_point(xx+10, yy+i);
}
fl_color(FL_BLACK);
for (i=0; i<10; i++) {
fl_point(xx+i, yy);
fl_point(xx+i, yy+9);
}
for (i=0; i<10; i++) {
fl_point(xx, yy+i);
fl_point(xx+9, yy+i);
}
fl_color(FL_WHITE);
for (i=0; i<8; i++)
for (j=0; j<8; j++)
fl_point(xx+i+1, yy+j+1);
// Test 4a: check pixel clipping
xx = a+24; yy = b+3*24+2*16+9-5;
fl_push_clip(xx+1, yy+1, 9, 9);
fl_color(FL_RED);
for (i=0; i<10; i++) {
fl_point(xx+i, yy);
fl_point(xx+i, yy+9);
}
for (i=0; i<10; i++) {
fl_point(xx, yy+i);
fl_point(xx+9, yy+i);
}
fl_color(FL_BLACK);
for (i=1; i<9; i++) {
fl_point(xx+i, yy+1);
fl_point(xx+i, yy+8);
}
for (i=1; i<9; i++) {
fl_point(xx+1, yy+i);
fl_point(xx+8, yy+i);
}
fl_color(FL_WHITE);
for (i=1; i<7; i++)
for (j=1; j<7; j++)
fl_point(xx+i+1, yy+j+1);
fl_pop_clip();
Fl_Gl_Window::draw_end();
}
};
#endif
class PointTest : public Fl_Group {
PointTestWin *align_test_win;
#if HAVE_GL
GLTestWin *gl_test_win;
#endif
public:
static Fl_Widget *create() {
return new PointTest(TESTAREA_X, TESTAREA_Y, TESTAREA_W, TESTAREA_H);
// 520x365, resizable
}
PointTest(int x, int y, int w, int h) : Fl_Group(x, y, w, h) {
label("Testing the fl_point call.");
align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP);
box(FL_BORDER_BOX);
int a = x+16, b = y+34;
Fl_Box *t = new Fl_Box(a, b-24, 80, 18, "native");
t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
t = new Fl_Box(a, b, 18, 18, "1");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing pixel size and antialiasing.\n\n"
// Description:
"This draws a checker board of black points on a white background.\n\n"
// Things to look out for:
"Black and white points should be the same size of one unit (1 pixel in regular mode, 2x2 pixels in hidpi mode)."
"If black points are smaller than white in hidpi mode, point size must be increased.\n\n"
"Points should not be blurry. Antialiasing should be switched of and the point coordinates should be centered on the pixel(s).\n\n"
"If parts of the white border are missing, the size of fl_rect should be adjusted."
);
t = new Fl_Box(a, b+24, 18, 18, "2");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing pixels color.\n\n"
// Description:
"This draws three squares in red, green, and blue.\n\n"
// Things to look out for:
"If the order of colors is different, the byte order when writing into the pixel buffer should be fixed."
);
t = new Fl_Box(a, b+2*24+2*16, 18, 18, "3");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing pixels alignment in windows.\n\n"
// Description:
"This draws a black frame around a white square.\n\n"
// Things to look out for:
"If parts of the black frame are clipped by the window and not visible, pixel offsets must be adjusted."
);
align_test_win = new PointTestWin(a+24, b+2*24+2*16+9-5, 10, 10);
t = new Fl_Box(a, b+3*24+2*16, 18, 18, "4");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing pixels clipping.\n\n"
// Description:
"This draws a black frame around a white square.\n\n"
// Things to look out for:
"If red pixels are visble or black pixels are missing, graphics clipping is misaligned."
);
a+=100;
#if HAVE_GL
t = new Fl_Box(a, b-24, 80, 18, "OpenGL");
t->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE);
t = new Fl_Box(a, b, 26, 18, "1a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing pixel size and antialiasing.\n\n"
// Description:
"This draws a checker board of black points on a white background.\n\n"
// Things to look out for:
"Black and white points should be the same size of one unit (1 pixel in regular mode, 2x2 pixels in hidpi mode)."
"If black points are smaller than white in hidpi mode, point size must be increased.\n\n"
"Points should not be blurry. Antialiasing should be switched of and the point coordinates should be centered on the pixel(s).\n\n"
"If parts of the white border are missing, the size of fl_rect should be adjusted."
);
t = new Fl_Box(a, b+24, 26, 18, "2a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing pixels color.\n\n"
// Description:
"This draws three squares in red, green, and blue.\n\n"
// Things to look out for:
"If the order of colors is different, the color component order when writing into the pixel buffer should be fixed."
);
t = new Fl_Box(a, b+2*24+2*16, 26, 18, "3a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing pixels alignment in windows.\n\n"
// Description:
"This draws a black frame around a white square, extending to both sides.\n\n"
// Things to look out for:
"If parts of the black frame are clipped by the window and not visible, pixel offsets must be adjusted horizontally.\n\n"
"If the horizontal lines are misaligned, vertical pixel offset should be adjusted."
);
t = new Fl_Box(a, b+3*24+2*16, 26, 18, "4a");
t->box(FL_ROUNDED_BOX); t->color(FL_YELLOW);
t->tooltip(// Title:
"Testing pixels clipping.\n\n"
// Description:
"This draws a black frame around a white square. The square is slightly smaller.\n\n"
// Things to look out for:
"If red pixels are visble or black pixels are missing, graphics clipping is misaligned."
);
gl_test_win = new GLTestWin(a+24+8, b+9-5, 10, 4*24+2*16);
#endif
t = new Fl_Box(x+w-1,y+h-1, 1, 1);
resizable(t);
}
void draw() {
Fl_Group::draw();
int a = x()+16, b = y()+34, i, j;
// Test 1: pixel size
fl_color(FL_WHITE); fl_rectf(a+24, b+9-5, 10, 10);
fl_color(FL_BLACK);
for (i=0; i<8; i++)
for (j=0; j<8; j++)
if ((i+j)&1)
fl_point(a+i+24+1, b+j+9-5+1);
// Test 2: pixel color
for (int n=0; n<3; n++) {
static Fl_Color lut[3] = { FL_RED, FL_GREEN, FL_BLUE };
int yy = b+9-5+24 + 16*n;
fl_color(FL_WHITE); fl_rectf(a+24, yy, 10, 10);
fl_color(lut[n]);
for (i=0; i<8; i++)
for (j=0; j<8; j++)
fl_point(a+i+24+1, yy+j+1);
}
// Test 3: pixel alignment inside windows (drawing happens in PointTestWin)
// Test 4: check pixel clipping
int xx = a+24, yy = b+3*24+2*16+9-5;
fl_push_clip(xx, yy, 10, 10);
fl_color(FL_RED);
for (i=-1; i<11; i++) {
fl_point(xx+i, yy-1);
fl_point(xx+i, yy+10);
}
for (i=-1; i<11; i++) {
fl_point(xx-1, yy+i);
fl_point(xx+10, yy+i);
}
fl_color(FL_BLACK);
for (i=0; i<10; i++) {
fl_point(xx+i, yy);
fl_point(xx+i, yy+9);
}
for (i=0; i<10; i++) {
fl_point(xx, yy+i);
fl_point(xx+9, yy+i);
}
fl_color(FL_WHITE);
for (i=0; i<8; i++)
for (j=0; j<8; j++)
fl_point(xx+i+1, yy+j+1);
fl_pop_clip();
// Test 3a: pixel alignment inside the OpenGL window
#if HAVE_GL
xx = a+24+108; yy = b+2*24+2*16+9-5;
fl_color(FL_BLACK);
for (i=-4; i<14; i++) {
fl_point(xx+i, yy);
fl_point(xx+i, yy+9);
}
#endif
}
};
UnitTest points(kTestPoints, "Drawing Points", PointTest::create);
-51
View File
@@ -1,51 +0,0 @@
//
// Unit tests for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2010 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H> // fl_text_extents()
//
//------- test the rectangle drawing capabilities of this implementation ----------
//
class RectTest : public Fl_Box {
public:
static Fl_Widget *create() {
return new RectTest(TESTAREA_X, TESTAREA_Y, TESTAREA_W, TESTAREA_H);
}
RectTest(int x, int y, int w, int h) : Fl_Box(x, y, w, h) {
label("testing the fl_rect call\n"
"No red pixels should be visible. "
"If you see bright red lines, or if parts of the green frames are hidden, "
"the rect drawing alignment is off.");
align(FL_ALIGN_INSIDE|FL_ALIGN_BOTTOM|FL_ALIGN_LEFT|FL_ALIGN_WRAP);
box(FL_BORDER_BOX);
}
void draw() {
Fl_Box::draw();
int a = x()+10, b = y()+10; fl_color(FL_BLACK); fl_rect(a, b, 100, 100);
// testing fl_rect() with positive size
fl_color(FL_RED); fl_loop(a+10, b+10, a+40, b+10, a+40, b+40, a+10, b+40);
fl_color(FL_GREEN); fl_loop(a+ 9, b+ 9, a+41, b+ 9, a+41, b+41, a+ 9, b+41);
fl_color(FL_GREEN); fl_loop(a+11, b+11, a+39, b+11, a+39, b+39, a+11, b+39);
fl_color(FL_BLACK); fl_rect(a+10, b+10, 31, 31);
// testing fl_rect() with positive size
fl_color(FL_RED); fl_loop(a+60, b+60, a+90, b+60, a+90, b+90, a+60, b+90);
fl_color(FL_GREEN); fl_loop(a+59, b+59, a+91, b+59, a+91, b+91, a+59, b+91);
fl_color(FL_BLACK); fl_rectf(a+60, b+60, 31, 31);
}
};
UnitTest rects("rectangles", RectTest::create);
+3 -1
View File
@@ -16,6 +16,8 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <FL/Fl_Choice.H>
// needed by Edmanuel's test layout
@@ -324,4 +326,4 @@ public:
}
};
UnitTest schemestest("schemes test", SchemesTest::create);
UnitTest schemestest(kTestSchemes, "Schemes Test", SchemesTest::create);
+4 -1
View File
@@ -14,7 +14,10 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <FL/Fl_Group.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Browser.H>
#include <FL/Fl_Tree.H>
#include <FL/Fl_Table.H>
@@ -216,4 +219,4 @@ public:
}
};
UnitTest scrollbarsize("scrollbar size", ScrollBarSizeTest::create);
UnitTest scrollbarsize(kTestScrollbarsize, "Scrollbar Size", ScrollBarSizeTest::create);
+3 -1
View File
@@ -14,6 +14,8 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <time.h>
#include <FL/Fl_Group.H>
#include <FL/Fl_Simple_Terminal.H>
@@ -115,4 +117,4 @@ public:
}
};
UnitTest simple_terminal("simple terminal", SimpleTerminal::create);
UnitTest simple_terminal(kTestSimpleTerminal, "Simple Terminal", SimpleTerminal::create);
+3 -1
View File
@@ -14,6 +14,8 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>
@@ -86,4 +88,4 @@ public:
}
};
UnitTest symbolExtents("symbol text", SymbolTest::create);
UnitTest symbolExtents(kTestSymbol, "Symbol Text", SymbolTest::create);
+3 -1
View File
@@ -14,6 +14,8 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>
@@ -79,4 +81,4 @@ public:
}
};
UnitTest textExtents("rendering text", TextExtentsTest::create);
UnitTest textExtents(kTestText, "Rendering text", TextExtentsTest::create);
+3 -1
View File
@@ -14,6 +14,8 @@
// https://www.fltk.org/bugs.php
//
#include "unittests.h"
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>
@@ -46,4 +48,4 @@ public:
}
};
UnitTest viewport("viewport test", ViewportTest::create);
UnitTest viewport(kTestViewport, "Viewport Test", ViewportTest::create);
+84 -118
View File
@@ -21,6 +21,8 @@
// v1.0 - Submit for svn
// v1.1 - Matthias seperated all tests into multiple source files for hopefully easier handling
#include "unittests.h"
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Hold_Browser.H>
@@ -31,130 +33,91 @@
#include <FL/fl_string_functions.h> // fl_strdup()
#include <stdlib.h> // malloc, free
// WINDOW/WIDGET SIZES
#define MAINWIN_W 700 // main window w()
#define MAINWIN_H 400 // main window h()
#define BROWSER_X 10 // browser x()
#define BROWSER_Y 25 // browser y()
#define BROWSER_W 150 // browser w()
#define BROWSER_H MAINWIN_H-35 // browser h()
#define TESTAREA_X (BROWSER_W + 20) // test area x()
#define TESTAREA_Y 25 // test area y()
#define TESTAREA_W (MAINWIN_W - BROWSER_W - 30) // test area w()
#define TESTAREA_H BROWSER_H // test area h()
typedef void (*UnitTestCallback)(const char*,Fl_Group*);
class MainWindow *mainwin = 0;
Fl_Hold_Browser *browser = 0;
class Fl_Hold_Browser *browser = 0;
// This class helps to automagically register a new test with the unittest app.
// Please see the examples on how this is used.
class UnitTest {
public:
UnitTest(const char *label, Fl_Widget* (*create)()) :
fWidget(0L)
{
fLabel = fl_strdup(label);
fCreate = create;
add(this);
}
~UnitTest() {
delete fWidget;
free(fLabel);
}
const char *label() {
return fLabel;
}
void create() {
fWidget = fCreate();
if (fWidget) fWidget->hide();
}
void show() {
if (fWidget) fWidget->show();
}
void hide() {
if (fWidget) fWidget->hide();
}
static int numTest() { return nTest; }
static UnitTest *test(int i) { return fTest[i]; }
private:
char *fLabel;
Fl_Widget *(*fCreate)();
Fl_Widget *fWidget;
UnitTest::UnitTest(int index, const char *label, Fl_Widget* (*create)()) :
fWidget(0L)
{
fLabel = fl_strdup(label);
fCreate = create;
add(index, this);
}
static void add(UnitTest *t) {
fTest[nTest] = t;
nTest++;
}
static int nTest;
static UnitTest *fTest[];
};
UnitTest::~UnitTest() {
delete fWidget;
free(fLabel);
}
const char *UnitTest::label() {
return fLabel;
}
void UnitTest::create() {
fWidget = fCreate();
if (fWidget) fWidget->hide();
}
void UnitTest::show() {
if (fWidget) fWidget->show();
}
void UnitTest::hide() {
if (fWidget) fWidget->hide();
}
void UnitTest::add(int index, UnitTest *t) {
fTest[index] = t;
if (index>=nTest)
nTest = index+1;
}
int UnitTest::nTest = 0;
UnitTest *UnitTest::fTest[200];
UnitTest *UnitTest::fTest[200] = { 0 };
MainWindow::MainWindow(int w, int h, const char *l) :
Fl_Double_Window(w, h, l),
fTestAlignment(0)
{ }
// The main window needs an additional drawing feature in order to support
// the viewport alignment test.
class MainWindow : public Fl_Double_Window {
public:
MainWindow(int w, int h, const char *l=0L) :
Fl_Double_Window(w, h, l),
fTestAlignment(0)
{ }
// this code is used by the viewport alignment test
void drawAlignmentIndicators() {
const int sze = 16;
// top left corner
fl_color(FL_GREEN); fl_yxline(0, sze, 0, sze);
fl_color(FL_RED); fl_yxline(-1, sze, -1, sze);
fl_color(FL_WHITE); fl_rectf(3, 3, sze-2, sze-2);
fl_color(FL_BLACK); fl_rect(3, 3, sze-2, sze-2);
// bottom left corner
fl_color(FL_GREEN); fl_yxline(0, h()-sze-1, h()-1, sze);
fl_color(FL_RED); fl_yxline(-1, h()-sze-1, h(), sze);
fl_color(FL_WHITE); fl_rectf(3, h()-sze-1, sze-2, sze-2);
fl_color(FL_BLACK); fl_rect(3, h()-sze-1, sze-2, sze-2);
// bottom right corner
fl_color(FL_GREEN); fl_yxline(w()-1, h()-sze-1, h()-1, w()-sze-1);
fl_color(FL_RED); fl_yxline(w(), h()-sze-1, h(), w()-sze-1);
fl_color(FL_WHITE); fl_rectf(w()-sze-1, h()-sze-1, sze-2, sze-2);
fl_color(FL_BLACK); fl_rect(w()-sze-1, h()-sze-1, sze-2, sze-2);
// top right corner
fl_color(FL_GREEN); fl_yxline(w()-1, sze, 0, w()-sze-1);
fl_color(FL_RED); fl_yxline(w(), sze, -1, w()-sze-1);
fl_color(FL_WHITE); fl_rectf(w()-sze-1, 3, sze-2, sze-2);
fl_color(FL_BLACK); fl_rect(w()-sze-1, 3, sze-2, sze-2);
void MainWindow::drawAlignmentIndicators() {
const int sze = 16;
// top left corner
fl_color(FL_GREEN); fl_yxline(0, sze, 0, sze);
fl_color(FL_RED); fl_yxline(-1, sze, -1, sze);
fl_color(FL_WHITE); fl_rectf(3, 3, sze-2, sze-2);
fl_color(FL_BLACK); fl_rect(3, 3, sze-2, sze-2);
// bottom left corner
fl_color(FL_GREEN); fl_yxline(0, h()-sze-1, h()-1, sze);
fl_color(FL_RED); fl_yxline(-1, h()-sze-1, h(), sze);
fl_color(FL_WHITE); fl_rectf(3, h()-sze-1, sze-2, sze-2);
fl_color(FL_BLACK); fl_rect(3, h()-sze-1, sze-2, sze-2);
// bottom right corner
fl_color(FL_GREEN); fl_yxline(w()-1, h()-sze-1, h()-1, w()-sze-1);
fl_color(FL_RED); fl_yxline(w(), h()-sze-1, h(), w()-sze-1);
fl_color(FL_WHITE); fl_rectf(w()-sze-1, h()-sze-1, sze-2, sze-2);
fl_color(FL_BLACK); fl_rect(w()-sze-1, h()-sze-1, sze-2, sze-2);
// top right corner
fl_color(FL_GREEN); fl_yxline(w()-1, sze, 0, w()-sze-1);
fl_color(FL_RED); fl_yxline(w(), sze, -1, w()-sze-1);
fl_color(FL_WHITE); fl_rectf(w()-sze-1, 3, sze-2, sze-2);
fl_color(FL_BLACK); fl_rect(w()-sze-1, 3, sze-2, sze-2);
}
void MainWindow::draw() {
Fl_Double_Window::draw();
if (fTestAlignment) {
drawAlignmentIndicators();
}
void draw() {
Fl_Double_Window::draw();
if (fTestAlignment) {
drawAlignmentIndicators();
}
}
void testAlignment(int v) {
fTestAlignment = v;
redraw();
}
int fTestAlignment;
};
}
void MainWindow::testAlignment(int v) {
fTestAlignment = v;
redraw();
}
//------- include the various unit tests as inline code -------
#include "unittest_about.cxx"
#include "unittest_points.cxx"
#include "unittest_lines.cxx"
#include "unittest_rects.cxx"
#include "unittest_circles.cxx"
#include "unittest_text.cxx"
#include "unittest_symbol.cxx"
#include "unittest_images.cxx"
#include "unittest_viewport.cxx"
#include "unittest_scrollbarsize.cxx"
#include "unittest_schemes.cxx"
#include "unittest_simple_terminal.cxx"
// callback whenever the browser value changes
void Browser_CB(Fl_Widget*, void*) {
for ( int t=1; t<=browser->size(); t++ ) {
@@ -175,6 +138,7 @@ int main(int argc, char **argv) {
Fl::get_system_colors();
Fl::scheme(Fl::scheme()); // init scheme before instantiating tests
Fl::visual(FL_RGB);
Fl::use_high_res_GL(1);
mainwin = new MainWindow(MAINWIN_W, MAINWIN_H, "FLTK Unit Tests");
browser = new Fl_Hold_Browser(BROWSER_X, BROWSER_Y, BROWSER_W, BROWSER_H, "Unit Tests");
browser->align(FL_ALIGN_TOP|FL_ALIGN_LEFT);
@@ -184,16 +148,18 @@ int main(int argc, char **argv) {
int i, n = UnitTest::numTest();
for (i=0; i<n; i++) {
UnitTest *t = UnitTest::test(i);
mainwin->begin();
t->create();
mainwin->end();
browser->add(t->label(), (void*)t);
if (t) {
mainwin->begin();
t->create();
mainwin->end();
browser->add(t->label(), (void*)t);
}
}
mainwin->resizable(mainwin);
mainwin->show(argc,argv);
// Select first test in browser, and show that test.
browser->select(1);
browser->select(kTestAbout+1);
Browser_CB(browser,0);
return(Fl::run());
}
+87
View File
@@ -0,0 +1,87 @@
//
// Unit tests for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2022 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
// file is missing or damaged, see the license at:
//
// https://www.fltk.org/COPYING.php
//
// Please see the following page on how to report bugs and issues:
//
// https://www.fltk.org/bugs.php
//
#ifndef UNITTESTS_H
#define UNITTESTS_H 1
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
// WINDOW/WIDGET SIZES
#define MAINWIN_W 700 // main window w()
#define MAINWIN_H 400 // main window h()
#define BROWSER_X 10 // browser x()
#define BROWSER_Y 25 // browser y()
#define BROWSER_W 150 // browser w()
#define BROWSER_H MAINWIN_H-35 // browser h()
#define TESTAREA_X (BROWSER_W + 20) // test area x()
#define TESTAREA_Y 25 // test area y()
#define TESTAREA_W (MAINWIN_W - BROWSER_W - 30) // test area w()
#define TESTAREA_H BROWSER_H // test area h()
typedef void (*UnitTestCallback)(const char*, class Fl_Group*);
extern class MainWindow *mainwin;
extern class Fl_Hold_Browser *browser;
enum {
kTestAbout = 0,
kTestPoints,
kTestFastShapes,
kTestCircles,
// kTestComplexShapes,
kTestText,
kTestSymbol,
kTestImages,
kTestViewport,
kTestScrollbarsize,
kTestSchemes,
kTestSimpleTerminal
};
// This class helps to automatically register a new test with the unittest app.
// Please see the examples on how this is used.
class UnitTest {
public:
UnitTest(int index, const char *label, Fl_Widget* (*create)());
~UnitTest();
const char *label();
void create();
void show();
void hide();
static int numTest() { return nTest; }
static UnitTest *test(int i) { return fTest[i]; }
private:
char *fLabel;
Fl_Widget *(*fCreate)();
Fl_Widget *fWidget;
static void add(int index, UnitTest *t);
static int nTest;
static UnitTest *fTest[];
};
// The main window needs an additional drawing feature in order to support
// the viewport alignment test.
class MainWindow : public Fl_Double_Window {
public:
MainWindow(int w, int h, const char *l=0L);
void drawAlignmentIndicators();
void draw();
void testAlignment(int v);
int fTestAlignment;
};
#endif