mirror of https://github.com/fltk/fltk
Android: Implemented vector drawing and polygons.
Started to implement arc and pie drawing git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12783 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
parent
3a20682764
commit
0b8116ff72
17
FL/android.H
17
FL/android.H
|
@ -25,6 +25,23 @@
|
|||
# error "Never use <FL/android.H> directly; include <FL/platform.H> instead."
|
||||
#endif // !FL_PLATFORM_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the function that application code must implement, representing
|
||||
* the main entry to the app.
|
||||
*/
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef void *Window; // used by fl_find(), fl_xid() and class Fl_X
|
||||
|
||||
/* Reference to the current device context
|
||||
|
|
|
@ -15,11 +15,182 @@
|
|||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
int N = 0;
|
||||
#define W 200
|
||||
#define H 50
|
||||
#define ROWS 14
|
||||
|
||||
// Note: Run the program with command line '-s abc' to view boxtypes
|
||||
// with scheme 'abc'.
|
||||
|
||||
// class BoxGroup - minimal class to enable visible box size debugging
|
||||
//
|
||||
// Set the following static variables to 0 (default) to disable
|
||||
// or 1 to enable the given feature.
|
||||
//
|
||||
// If you enable the 'outline' variable, then a red frame should be drawn
|
||||
// around each box, and it should ideally be fully visible.
|
||||
//
|
||||
// The white background is optional (otherwise you see the window background).
|
||||
//
|
||||
// Set BOTH variables = 0 to show the default image for the FLTK manual.
|
||||
//
|
||||
// Note: As of FLTK 1.3.3 (probably since FLTK 1.0/1.1) there are some
|
||||
// shadows 'leaking' outside their widget bounding boxes (x,y,w,h).
|
||||
// Is this intentional?
|
||||
|
||||
static const int outline = 0; // draw 1-px red frame around all boxes
|
||||
static const int box_bg = 0; // draw white background inside all boxes
|
||||
static const int inactive = 0; // deactivate boxes and use green background
|
||||
class BoxGroup : public Fl_Group {
|
||||
public:
|
||||
BoxGroup(int x, int y, int w, int h) : Fl_Group(x,y,w,h) {};
|
||||
void draw() {
|
||||
draw_box();
|
||||
if (outline + box_bg) { // outline or box_bg or both
|
||||
Fl_Widget*const* a = array();
|
||||
for (int i=children(); i--;) {
|
||||
Fl_Widget& o = **a++;
|
||||
if (outline) {
|
||||
fl_color(FL_RED);
|
||||
fl_rect(o.x()-1,o.y()-1,o.w()+2,o.h()+2);
|
||||
}
|
||||
if (box_bg) {
|
||||
fl_color(FL_WHITE);
|
||||
fl_rectf(o.x(),o.y(),o.w(),o.h());
|
||||
}
|
||||
fl_color(FL_BLACK);
|
||||
}
|
||||
} // outline or box_bg or both
|
||||
Fl_Group::draw_children();
|
||||
} // draw()
|
||||
}; // class BoxGroup
|
||||
|
||||
Fl_Double_Window *window;
|
||||
|
||||
void bt(const char *name, Fl_Boxtype type, int square=0) {
|
||||
int x = N%4;
|
||||
int y = N/4;
|
||||
N++;
|
||||
x = x*W+10;
|
||||
y = y*H+10;
|
||||
Fl_Box *b = new Fl_Box(type,x,y,square ? H-20 : W-20,H-20,name);
|
||||
b->labelsize(11);
|
||||
if (inactive) {
|
||||
b->color(FL_GREEN);
|
||||
b->deactivate();
|
||||
}
|
||||
if (square) b->align(FL_ALIGN_RIGHT);
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
window = new Fl_Double_Window(4*W,ROWS*H);
|
||||
window->box(FL_FLAT_BOX);
|
||||
#if 0 // this code uses the command line arguments to set arbitrary color schemes
|
||||
Fl::args(argc, argv);
|
||||
Fl::get_system_colors();
|
||||
#elif 0 // this code uses a single color to define a scheme
|
||||
Fl::args(argc, argv);
|
||||
Fl::get_system_colors();
|
||||
Fl::background(113,113,198);
|
||||
#else // this code uses the nice bright blue background to show box vs. frame types
|
||||
Fl::args(argc, argv);
|
||||
Fl::get_system_colors();
|
||||
window->color(12);// light blue
|
||||
#endif
|
||||
|
||||
// set window title to show active scheme
|
||||
Fl::scheme(Fl::scheme()); // init scheme
|
||||
char title[100];
|
||||
sprintf(title,"FLTK boxtypes: scheme = '%s'",Fl::scheme()?Fl::scheme():"none");
|
||||
window->label(title);
|
||||
|
||||
// create special container group for box size debugging
|
||||
BoxGroup *bg = new BoxGroup(0,0,window->w(),window->h());
|
||||
bg->box(FL_NO_BOX);
|
||||
|
||||
// create demo boxes
|
||||
bt("FL_NO_BOX",FL_NO_BOX);
|
||||
bt("FL_FLAT_BOX",FL_FLAT_BOX);
|
||||
N += 2; // go to start of next row to line up boxes & frames
|
||||
bt("FL_UP_BOX",FL_UP_BOX);
|
||||
bt("FL_DOWN_BOX",FL_DOWN_BOX);
|
||||
bt("FL_UP_FRAME",FL_UP_FRAME);
|
||||
bt("FL_DOWN_FRAME",FL_DOWN_FRAME);
|
||||
bt("FL_THIN_UP_BOX",FL_THIN_UP_BOX);
|
||||
bt("FL_THIN_DOWN_BOX",FL_THIN_DOWN_BOX);
|
||||
bt("FL_THIN_UP_FRAME",FL_THIN_UP_FRAME);
|
||||
bt("FL_THIN_DOWN_FRAME",FL_THIN_DOWN_FRAME);
|
||||
bt("FL_ENGRAVED_BOX",FL_ENGRAVED_BOX);
|
||||
bt("FL_EMBOSSED_BOX",FL_EMBOSSED_BOX);
|
||||
bt("FL_ENGRAVED_FRAME",FL_ENGRAVED_FRAME);
|
||||
bt("FL_EMBOSSED_FRAME",FL_EMBOSSED_FRAME);
|
||||
bt("FL_BORDER_BOX",FL_BORDER_BOX);
|
||||
bt("FL_SHADOW_BOX",FL_SHADOW_BOX);
|
||||
bt("FL_BORDER_FRAME",FL_BORDER_FRAME);
|
||||
bt("FL_SHADOW_FRAME",FL_SHADOW_FRAME);
|
||||
bt("FL_ROUNDED_BOX",FL_ROUNDED_BOX);
|
||||
bt("FL_RSHADOW_BOX",FL_RSHADOW_BOX);
|
||||
bt("FL_ROUNDED_FRAME",FL_ROUNDED_FRAME);
|
||||
bt("FL_RFLAT_BOX",FL_RFLAT_BOX);
|
||||
bt("FL_OVAL_BOX",FL_OVAL_BOX);
|
||||
bt("FL_OSHADOW_BOX",FL_OSHADOW_BOX);
|
||||
bt("FL_OVAL_FRAME",FL_OVAL_FRAME);
|
||||
bt("FL_OFLAT_BOX",FL_OFLAT_BOX);
|
||||
bt("FL_ROUND_UP_BOX",FL_ROUND_UP_BOX);
|
||||
bt("FL_ROUND_DOWN_BOX",FL_ROUND_DOWN_BOX);
|
||||
bt("FL_DIAMOND_UP_BOX",FL_DIAMOND_UP_BOX);
|
||||
bt("FL_DIAMOND_DOWN_BOX",FL_DIAMOND_DOWN_BOX);
|
||||
|
||||
bt("FL_PLASTIC_UP_BOX",FL_PLASTIC_UP_BOX);
|
||||
bt("FL_PLASTIC_DOWN_BOX",FL_PLASTIC_DOWN_BOX);
|
||||
bt("FL_PLASTIC_UP_FRAME",FL_PLASTIC_UP_FRAME);
|
||||
bt("FL_PLASTIC_DOWN_FRAME",FL_PLASTIC_DOWN_FRAME);
|
||||
bt("FL_PLASTIC_THIN_UP_BOX",FL_PLASTIC_THIN_UP_BOX);
|
||||
bt("FL_PLASTIC_THIN_DOWN_BOX",FL_PLASTIC_THIN_DOWN_BOX);
|
||||
N += 2;
|
||||
bt("FL_PLASTIC_ROUND_UP_BOX",FL_PLASTIC_ROUND_UP_BOX);
|
||||
bt("FL_PLASTIC_ROUND_DOWN_BOX",FL_PLASTIC_ROUND_DOWN_BOX);
|
||||
N += 2;
|
||||
|
||||
bt("FL_GTK_UP_BOX",FL_GTK_UP_BOX);
|
||||
bt("FL_GTK_DOWN_BOX",FL_GTK_DOWN_BOX);
|
||||
bt("FL_GTK_UP_FRAME",FL_GTK_UP_FRAME);
|
||||
bt("FL_GTK_DOWN_FRAME",FL_GTK_DOWN_FRAME);
|
||||
bt("FL_GTK_THIN_UP_BOX",FL_GTK_THIN_UP_BOX);
|
||||
bt("FL_GTK_THIN_DOWN_BOX",FL_GTK_THIN_DOWN_BOX);
|
||||
bt("FL_GTK_THIN_UP_FRAME",FL_GTK_THIN_UP_FRAME);
|
||||
bt("FL_GTK_THIN_DOWN_FRAME",FL_GTK_THIN_DOWN_FRAME);
|
||||
bt("FL_GTK_ROUND_UP_BOX",FL_GTK_ROUND_UP_BOX);
|
||||
bt("FL_GTK_ROUND_DOWN_BOX",FL_GTK_ROUND_DOWN_BOX);
|
||||
bg->end();
|
||||
window->resizable(window);
|
||||
window->end();
|
||||
window->show();
|
||||
return Fl::run();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
#include <src/drivers/Android/Fl_Android_Application.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Enumerations.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <FL/fl_ask.H>
|
||||
|
||||
|
||||
Fl_Window *win, *win1, *win2;
|
||||
|
@ -31,9 +202,16 @@ class MyButton : public Fl_Button
|
|||
public:
|
||||
MyButton(int x, int y, int w, int h, const char *l) : Fl_Button(x, y, w, h, l) { }
|
||||
void draw() {
|
||||
//fl_push_clip(x(), y(), w()*2/3, h()*2/3);
|
||||
Fl_Button::draw();
|
||||
//fl_pop_clip();
|
||||
fl_push_clip(x(), y(), w(), h());
|
||||
fl_color(FL_BLUE);
|
||||
for (int i=0; i<h(); i+=5) {
|
||||
fl_line(x(), y()+h()/2, x()+w(), y()+i);
|
||||
}
|
||||
for (int i=0; i<w(); i+=5) {
|
||||
fl_line(x()+w()/2, y()-50, x()+i, y()+h()+50);
|
||||
}
|
||||
fl_pop_clip();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -53,7 +231,7 @@ void hello_cb(void*)
|
|||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int xmain(int argc, char **argv)
|
||||
{
|
||||
// Fl::scheme("gleam");
|
||||
win1 = new Fl_Window(20+50, 10, 200, 200, "back");
|
||||
|
@ -88,6 +266,9 @@ int main(int argc, char **argv)
|
|||
btn->labelsize(30);
|
||||
btn->callback(
|
||||
[](Fl_Widget *w, void*) {
|
||||
// FIXME: we can't seem to re-enter the event loop without locking
|
||||
// the entire app!
|
||||
// fl_alert("This will change\nthe font for the entir\napplication");
|
||||
Fl::set_font(FL_COURIER_BOLD_ITALIC, "$DancingScript-Regular.ttf");
|
||||
w->redraw();
|
||||
}
|
||||
|
@ -102,9 +283,9 @@ int main(int argc, char **argv)
|
|||
win->show(argc, argv);
|
||||
|
||||
win2 = new Fl_Window(380-50, 10, 200, 200, "front");
|
||||
win2->color(FL_BLUE);
|
||||
win2->color(FL_LIGHT3);
|
||||
win2->box(FL_UP_BOX);
|
||||
Fl_Button *b2 = new Fl_Button(10, 10, 180, 180, "front");
|
||||
Fl_Button *b2 = new MyButton(10, 10, 180, 180, "front");
|
||||
b2->color(FL_DARK_BLUE);
|
||||
win2->end();
|
||||
win2->show();
|
||||
|
@ -114,3 +295,66 @@ int main(int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
Missing:
|
||||
- screen scale and size: most desktop apps expect to be in a draggable window
|
||||
on a larger desktop surface. For Android, there is usually no desktop, and
|
||||
screen resolution is often very high, so that a regular FLTK window would
|
||||
hide as a tiny gray spot in the top left corner
|
||||
* windows should probably be centered by default
|
||||
? the screen resolution should adapt to the first opened window
|
||||
? we should be able to hint at a prefered screen resolution
|
||||
* drawing call must scale at some point (line width!)
|
||||
* rotating the screen must call the app handler and(?) window resize
|
||||
* proportions: pixels should be square
|
||||
|
||||
test/CubeMain.cxx test/line_style.cxx
|
||||
test/CubeView.cxx test/list_visuals.cxx
|
||||
test/adjuster.cxx test/mandelbrot.cxx
|
||||
test/animated.cxx test/menubar.cxx
|
||||
* test/arc.cxx : + 'arc' works as expected
|
||||
test/message.cxx
|
||||
test/ask.cxx test/minimum.cxx
|
||||
test/bitmap.cxx test/native-filechooser.cxx
|
||||
test/blocks.cxx test/navigation.cxx
|
||||
* test/boxtype.cxx : !! testing
|
||||
test/offscreen.cxx
|
||||
test/browser.cxx test/output.cxx
|
||||
test/button.cxx test/overlay.cxx
|
||||
test/buttons.cxx test/pack.cxx
|
||||
test/cairo_test.cxx test/pixmap.cxx
|
||||
test/checkers.cxx test/pixmap_browser.cxx
|
||||
test/clock.cxx test/resizebox.cxx
|
||||
test/colbrowser.cxx test/rotated_text.cxx
|
||||
test/color_chooser.cxx test/scroll.cxx
|
||||
test/connect.cxx test/shape.cxx
|
||||
test/cube.cxx test/subwindow.cxx
|
||||
test/cursor.cxx test/sudoku.cxx
|
||||
test/curve.cxx test/symbols.cxx
|
||||
test/demo.cxx test/table.cxx
|
||||
test/device.cxx test/threads.cxx
|
||||
test/doublebuffer.cxx test/tile.cxx
|
||||
test/editor.cxx test/tiled_image.cxx
|
||||
test/file_chooser.cxx test/twowin.cxx
|
||||
test/fonts.cxx test/unittest_about.cxx
|
||||
test/forms.cxx test/unittest_circles.cxx
|
||||
test/fractals.cxx test/unittest_images.cxx
|
||||
test/fracviewer.cxx test/unittest_lines.cxx
|
||||
test/fullscreen.cxx test/unittest_points.cxx
|
||||
test/gl_overlay.cxx test/unittest_rects.cxx
|
||||
test/glpuzzle.cxx test/unittest_schemes.cxx
|
||||
test/hello.cxx : + 'hello' works fine, italics, shadow, etc.
|
||||
test/unittest_scrollbarsize.cxx
|
||||
test/help_dialog.cxx test/unittest_simple_terminal.cxx
|
||||
test/icon.cxx test/unittest_symbol.cxx
|
||||
test/iconize.cxx test/unittest_text.cxx
|
||||
test/image.cxx test/unittest_viewport.cxx
|
||||
test/input.cxx test/unittests.cxx
|
||||
test/input_choice.cxx test/utf8.cxx
|
||||
test/keyboard.cxx test/windowfocus.cxx
|
||||
test/label.cxx
|
||||
|
||||
*/
|
|
@ -245,22 +245,6 @@ private:
|
|||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This is the function that application code must implement, representing
|
||||
* the main entry to the app.
|
||||
*/
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif // FL_ANDROID_APPLICATION_H
|
||||
|
||||
//
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "Fl_Android_Application.H"
|
||||
#include "Fl_Android_Window_Driver.H"
|
||||
|
||||
#include <FL/platform.H>
|
||||
#include <FL/fl_draw.H>
|
||||
|
||||
#include <jni.h>
|
||||
|
|
|
@ -41,6 +41,13 @@ class Fl_Android_Bytemap;
|
|||
*/
|
||||
class FL_EXPORT Fl_Android_Graphics_Driver : public Fl_Scalable_Graphics_Driver
|
||||
{
|
||||
class Vertex {
|
||||
public:
|
||||
void set(float x, float y, bool gap = false) { pX = x; pY = y; pIsGap = gap; }
|
||||
float pX, pY;
|
||||
bool pIsGap;
|
||||
};
|
||||
|
||||
public:
|
||||
Fl_Android_Graphics_Driver();
|
||||
virtual ~Fl_Android_Graphics_Driver() override;
|
||||
|
@ -62,15 +69,34 @@ public:
|
|||
virtual Fl_Font set_fonts(const char *name) override;
|
||||
virtual void font_name(int num, const char *name) override;
|
||||
|
||||
// --- line drawinf stuff
|
||||
// --- line drawing stuff
|
||||
virtual void rectf_unscaled(float x, float y, float w, float h) override;
|
||||
void rectf_unclipped(float x, float y, float w, float h);
|
||||
virtual void point_unscaled(float x, float y) override;
|
||||
void rect_unscaled(float x, float y, float w, float h);
|
||||
virtual void rect_unscaled(float x, float y, float w, float h) override;
|
||||
virtual void xyline_unscaled(float x, float y, float x1) override;
|
||||
void xyline_unclipped(float x, float y, float x1);
|
||||
virtual void yxline_unscaled(float x, float y, float y1) override;
|
||||
void yxline_unclipped(float x, float y, float y1);
|
||||
virtual void line_unscaled(float x, float y, float x1, float y1) override;
|
||||
|
||||
// --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
|
||||
virtual void begin_points() override;
|
||||
virtual void begin_line() override;
|
||||
virtual void begin_loop() override;
|
||||
virtual void begin_polygon() override;
|
||||
virtual void begin_complex_polygon() override;
|
||||
virtual void end_points() override;
|
||||
virtual void end_line() override;
|
||||
virtual void end_loop() override;
|
||||
virtual void end_polygon() override;
|
||||
void end_polygon(int begin, int end);
|
||||
virtual void end_complex_polygon() override;
|
||||
virtual void gap() override;
|
||||
virtual void transformed_vertex0(float x, float y) override;
|
||||
|
||||
virtual void arc_unscaled(float x, float y, float w, float h, double a1, double a2);
|
||||
virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2);
|
||||
|
||||
// --- clipping
|
||||
virtual void push_clip(int x, int y, int w, int h) override;
|
||||
|
@ -118,30 +144,18 @@ public:
|
|||
static HRGN scale_region(HRGN r, float f, Fl_GDI_Graphics_Driver *dr);
|
||||
virtual void scale(float f);
|
||||
protected:
|
||||
void transformed_vertex0(float x, float y);
|
||||
void fixloop();
|
||||
// --- implementation is in src/fl_rect.cxx which includes src/cfg_gfx/gdi_rect.cxx
|
||||
virtual void line_unscaled(float x, float y, float x1, float y1);
|
||||
virtual void line_unscaled(float x, float y, float x1, float y1, float x2, float y2);
|
||||
virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
|
||||
virtual void loop_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
|
||||
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2);
|
||||
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
|
||||
virtual Fl_Region scale_clip(float f);
|
||||
// --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx
|
||||
void begin_complex_polygon();
|
||||
void end_points();
|
||||
void end_line();
|
||||
void end_loop();
|
||||
void end_polygon();
|
||||
void end_complex_polygon();
|
||||
void gap();
|
||||
virtual void ellipse_unscaled(double xt, double yt, double rx, double ry);
|
||||
// --- implementation is in src/fl_arc.cxx which includes src/cfg_gfx/xxx_arc.cxx if needed
|
||||
// using void Fl_Graphics_Driver::arc(double x, double y, double r, double start, double end);
|
||||
// --- implementation is in src/fl_arci.cxx which includes src/cfg_gfx/xxx_arci.cxx
|
||||
virtual void arc_unscaled(float x, float y, float w, float h, double a1, double a2);
|
||||
virtual void pie_unscaled(float x, float y, float w, float h, double a1, double a2);
|
||||
// --- implementation is in src/fl_line_style.cxx which includes src/cfg_gfx/xxx_line_style.cxx
|
||||
virtual void line_style_unscaled(int style, float width, char* dashes);
|
||||
// --- implementation is in src/fl_color.cxx which includes src/cfg_gfx/xxx_color.cxx
|
||||
|
@ -176,6 +190,11 @@ protected:
|
|||
|
||||
// Final clipping region for all graphics calls to this class.
|
||||
Fl_Complex_Region pClippingRegion;
|
||||
|
||||
void begin_vertices();
|
||||
void add_vertex(float x, float y, bool gap=false);
|
||||
int pnVertex = 0, pNVertex = 0, pVertexGapStart = 0;
|
||||
Vertex *pVertex = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
#include <FL/Fl.H>
|
||||
#include <FL/platform.H>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
static int sign(int v) { return (v<0) ? -1 : 1; }
|
||||
|
||||
/*
|
||||
* By linking this module, the following static method will instantiate the
|
||||
|
@ -229,6 +231,451 @@ void Fl_Android_Graphics_Driver::point_unscaled(float x, float y)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a line.
|
||||
* FIXME: it is incredibly inefficient to call 'point', especially for long lines
|
||||
* FIXME: clipping maust be moved into this call and drawing to the screen should happen right here
|
||||
* FIXME: line width is not considered
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::line_unscaled(float x, float y, float x1, float y1)
|
||||
{
|
||||
if (x==x1) {
|
||||
return yxline(x, y, y1);
|
||||
}
|
||||
if (y==y1) {
|
||||
return xyline(x, y, x1);
|
||||
}
|
||||
// Bresenham
|
||||
int w = x1 - x, dx = abs(w);
|
||||
int h = y1 - y, dy = abs(h);
|
||||
int dx1 = sign(w), dy1 = sign(h), dx2, dy2;
|
||||
int min, max;
|
||||
if (dx < dy) {
|
||||
min = dx; max = dy;
|
||||
dx2 = 0;
|
||||
dy2 = dy1;
|
||||
} else {
|
||||
min = dy; max = dx;
|
||||
dx2 = dx1;
|
||||
dy2 = 0;
|
||||
}
|
||||
int num = max/2;
|
||||
for (int i=max+1; i>0; i--) {
|
||||
point_unscaled(x, y);
|
||||
num += min;
|
||||
if (num>=max) {
|
||||
num -= max;
|
||||
x += dx1;
|
||||
y += dy1;
|
||||
} else {
|
||||
x += dx2;
|
||||
y += dy2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the vertex counter to zero.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::begin_vertices()
|
||||
{
|
||||
pnVertex = 0;
|
||||
pVertexGapStart = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a vertex to the vertex list. Dynamically allocates memory.
|
||||
* @param x, y position of the vertex after matrix transformation
|
||||
* @param gap line and loop call offer to leave a gap in the drawing
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::add_vertex(float x, float y, bool gap)
|
||||
{
|
||||
if (pnVertex == pNVertex) {
|
||||
pNVertex += 16;
|
||||
pVertex = (Vertex*)::realloc(pVertex, pNVertex*sizeof(Vertex));
|
||||
}
|
||||
pVertex[pnVertex].set(x, y);
|
||||
pVertex[pnVertex].pIsGap = gap;
|
||||
pnVertex++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a list of vertices to draw multiple points.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::begin_points()
|
||||
{
|
||||
begin_vertices();
|
||||
Fl_Scalable_Graphics_Driver::begin_points();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a list of vertices to draw a polyline.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::begin_line()
|
||||
{
|
||||
begin_vertices();
|
||||
Fl_Scalable_Graphics_Driver::begin_line();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a list of vertices to draw a line loop.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::begin_loop()
|
||||
{
|
||||
begin_vertices();
|
||||
Fl_Scalable_Graphics_Driver::begin_loop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a list of vertices to draw a polygon.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::begin_polygon()
|
||||
{
|
||||
begin_vertices();
|
||||
Fl_Scalable_Graphics_Driver::begin_polygon();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a list of vertices to draw a complex polygon.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::begin_complex_polygon()
|
||||
{
|
||||
begin_vertices();
|
||||
Fl_Scalable_Graphics_Driver::begin_complex_polygon();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw all stored vertices as points.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::end_points()
|
||||
{
|
||||
for (int i=0; i<pnVertex; ++i) {
|
||||
Vertex &v = pVertex[i];
|
||||
if (!v.pIsGap)
|
||||
point_unscaled(v.pX, v.pY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw all stored vertices as a polyline.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::end_line()
|
||||
{
|
||||
Vertex &v1 = pVertex[0];
|
||||
for (int i=1; i<pnVertex; ++i) {
|
||||
Vertex &v2 = pVertex[i];
|
||||
if (!v1.pIsGap && !v2.pIsGap)
|
||||
line_unscaled(v1.pX, v1.pY, v2.pX, v2.pY);
|
||||
v1 = v2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw all stored vertices as a polyline loop.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::end_loop()
|
||||
{
|
||||
gap();
|
||||
Vertex &v1 = pVertex[0];
|
||||
for (int i=1; i<pnVertex; ++i) {
|
||||
Vertex &v2 = pVertex[i];
|
||||
if (!v1.pIsGap)
|
||||
line_unscaled(v1.pX, v1.pY, v2.pX, v2.pY);
|
||||
v1 = v2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw all stored vertices as a polygon.
|
||||
* FIXME: these calls are very ineffiecient. Avoid pointer lookup.
|
||||
* FIXME: use the current clipping rect to accelerate rendering
|
||||
* FIXME: unmix float and int
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::end_polygon(int begin, int end)
|
||||
{
|
||||
if (end - begin < 2) return;
|
||||
|
||||
Vertex *v = pVertex+0;
|
||||
int xMin = v->pX, xMax = xMin, yMin = v->pY, yMax = yMin;
|
||||
for (int i = begin+1; i < end; i++) {
|
||||
v = pVertex+i;
|
||||
if (v->pX < xMin) xMin = v->pX;
|
||||
if (v->pX > xMax) xMax = v->pX;
|
||||
if (v->pY < yMin) yMin = v->pY;
|
||||
if (v->pY > yMax) yMax = v->pY;
|
||||
}
|
||||
xMax++; yMax++;
|
||||
|
||||
int nodes, nodeX[end - begin], pixelX, pixelY, i, j, swap;
|
||||
|
||||
// Loop through the rows of the image.
|
||||
for (pixelY = yMin; pixelY < yMax; pixelY++) {
|
||||
// Build a list of nodes.
|
||||
nodes = 0;
|
||||
j = begin;
|
||||
for (i = begin+1; i < end; i++) {
|
||||
if ( pVertex[i].pY < pixelY && pVertex[j].pY >= pixelY
|
||||
|| pVertex[j].pY < pixelY && pVertex[i].pY >= pixelY)
|
||||
{
|
||||
float dy = pVertex[j].pY - pVertex[i].pY;
|
||||
if (fabsf(dy)>.0001) {
|
||||
nodeX[nodes++] = (int)(pVertex[i].pX +
|
||||
(pixelY - pVertex[i].pY) / dy
|
||||
* (pVertex[j].pX - pVertex[i].pX));
|
||||
} else {
|
||||
nodeX[nodes++] = pVertex[i].pX;
|
||||
}
|
||||
}
|
||||
j = i;
|
||||
}
|
||||
|
||||
// Sort the nodes, via a simple “Bubble” sort.
|
||||
i = 0;
|
||||
while (i < nodes - 1) {
|
||||
if (nodeX[i] > nodeX[i + 1]) {
|
||||
swap = nodeX[i];
|
||||
nodeX[i] = nodeX[i + 1];
|
||||
nodeX[i + 1] = swap;
|
||||
if (i) i--;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the pixels between node pairs.
|
||||
for (i = 0; i < nodes; i += 2) {
|
||||
if (nodeX[i] >= xMax) break;
|
||||
if (nodeX[i + 1] > xMin) {
|
||||
if (nodeX[i] < xMin) nodeX[i] = xMin;
|
||||
if (nodeX[i + 1] > xMax) nodeX[i + 1] = xMax;
|
||||
xyline_unscaled(nodeX[i], pixelY, nodeX[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw all stored vertices as a polygon.
|
||||
* Mind the gap!
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::end_polygon()
|
||||
{
|
||||
if (pnVertex==0) return;
|
||||
gap();
|
||||
int start = 0, end = 0;
|
||||
for (int i=0; i<pnVertex; i++) {
|
||||
if (pVertex[i].pIsGap) {
|
||||
end = i+1;
|
||||
end_polygon(start, end);
|
||||
start = end;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw all stored vertices as a possibly self-intersecting polygon.
|
||||
* FIXME: these calls are very ineffiecient. Avoid pointer lookup.
|
||||
* FIXME: use the current clipping rect to accelerate rendering
|
||||
* FIXME: unmix float and int
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::end_complex_polygon()
|
||||
{
|
||||
if (pnVertex < 2) return;
|
||||
|
||||
gap(); // adds the first coordinate of this loop and marks it as a gap
|
||||
int begin = 0, end = pnVertex;
|
||||
|
||||
Vertex *v = pVertex+0;
|
||||
int xMin = v->pX, xMax = xMin, yMin = v->pY, yMax = yMin;
|
||||
for (int i = begin+1; i < end; i++) {
|
||||
v = pVertex+i;
|
||||
if (v->pX < xMin) xMin = v->pX;
|
||||
if (v->pX > xMax) xMax = v->pX;
|
||||
if (v->pY < yMin) yMin = v->pY;
|
||||
if (v->pY > yMax) yMax = v->pY;
|
||||
}
|
||||
xMax++; yMax++;
|
||||
|
||||
int nodes, nodeX[end - begin], pixelX, pixelY, i, j, swap;
|
||||
|
||||
// Loop through the rows of the image.
|
||||
for (pixelY = yMin; pixelY < yMax; pixelY++) {
|
||||
// Build a list of nodes.
|
||||
nodes = 0;
|
||||
for (i = begin+1; i < end; i++) {
|
||||
j = i-1;
|
||||
if (pVertex[j].pIsGap)
|
||||
continue;
|
||||
if ( pVertex[i].pY < pixelY && pVertex[j].pY >= pixelY
|
||||
|| pVertex[j].pY < pixelY && pVertex[i].pY >= pixelY)
|
||||
{
|
||||
float dy = pVertex[j].pY - pVertex[i].pY;
|
||||
if (fabsf(dy)>.0001) {
|
||||
nodeX[nodes++] = (int)(pVertex[i].pX +
|
||||
(pixelY - pVertex[i].pY) / dy
|
||||
* (pVertex[j].pX - pVertex[i].pX));
|
||||
} else {
|
||||
nodeX[nodes++] = pVertex[i].pX;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Fl_Android_Application::log_e("%d nodes (must be even!)", nodes);
|
||||
|
||||
// Sort the nodes, via a simple “Bubble” sort.
|
||||
i = 0;
|
||||
while (i < nodes - 1) {
|
||||
if (nodeX[i] > nodeX[i + 1]) {
|
||||
swap = nodeX[i];
|
||||
nodeX[i] = nodeX[i + 1];
|
||||
nodeX[i + 1] = swap;
|
||||
if (i) i--;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the pixels between node pairs.
|
||||
for (i = 0; i < nodes; i += 2) {
|
||||
if (nodeX[i] >= xMax) break;
|
||||
if (nodeX[i + 1] > xMin) {
|
||||
if (nodeX[i] < xMin) nodeX[i] = xMin;
|
||||
if (nodeX[i + 1] > xMax) nodeX[i + 1] = xMax;
|
||||
xyline_unscaled(nodeX[i], pixelY, nodeX[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a gap to a polyline drawing
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::gap()
|
||||
{
|
||||
// drop gaps at the start or gap after gap
|
||||
if (pnVertex==0 || pnVertex==pVertexGapStart)
|
||||
return;
|
||||
|
||||
// create a loop
|
||||
Vertex &v = pVertex[pVertexGapStart];
|
||||
add_vertex(v.pX, v.pY, true);
|
||||
pVertexGapStart = pnVertex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a vertex to the list.
|
||||
* TODO: we should maintain a bounding box for faster clipping.
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::transformed_vertex0(float x, float y)
|
||||
{
|
||||
add_vertex(x, y);
|
||||
}
|
||||
|
||||
|
||||
//void Fl_Pico_Graphics_Driver::circle(double x, double y, double r)
|
||||
//{
|
||||
// begin_loop();
|
||||
// double X = r;
|
||||
// double Y = 0;
|
||||
// fl_vertex(x+X,y+Y);
|
||||
//
|
||||
// double rx = fabs(transform_dx(r, r));
|
||||
// double ry = fabs(transform_dy(r, r));
|
||||
//
|
||||
// double circ = M_PI*0.5*(rx+ry);
|
||||
// int segs = circ * 360 / 1000; // every line is about three pixels long
|
||||
// if (segs<16) segs = 16;
|
||||
//
|
||||
// double A = 2*M_PI;
|
||||
// int i = segs;
|
||||
//
|
||||
// if (i) {
|
||||
// double epsilon = A/i; // Arc length for equal-size steps
|
||||
// double cos_e = cos(epsilon); // Rotation coefficients
|
||||
// double sin_e = sin(epsilon);
|
||||
// do {
|
||||
// double Xnew = cos_e*X + sin_e*Y;
|
||||
// Y = -sin_e*X + cos_e*Y;
|
||||
// fl_vertex(x + (X=Xnew), y + Y);
|
||||
// } while (--i);
|
||||
// }
|
||||
// end_loop();
|
||||
//}
|
||||
|
||||
/**
|
||||
* Draw an arc.
|
||||
* @param xi
|
||||
* @param yi
|
||||
* @param w
|
||||
* @param h
|
||||
* @param a1
|
||||
* @param a2
|
||||
* FIXME: float-to-int interpolation is horrible!
|
||||
*/
|
||||
void Fl_Android_Graphics_Driver::arc_unscaled(float xi, float yi, float w, float h, double a1, double a2)
|
||||
{
|
||||
if (a2<=a1) return;
|
||||
|
||||
double rx = w/2.0;
|
||||
double ry = h/2.0;
|
||||
double x = xi + rx;
|
||||
double y = yi + ry;
|
||||
double circ = M_PI*0.5*(rx+ry);
|
||||
int i, segs = circ * (a2-a1) / 1000; // every line is about three pixels long
|
||||
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;
|
||||
for (i=segs; i>0; i--) {
|
||||
a1+=step;
|
||||
px = nx; py = ny;
|
||||
nx = x + cos(a1)*rx;
|
||||
ny = y - sin(a1)*ry;
|
||||
line_unscaled(px, py, nx, ny);
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_Android_Graphics_Driver::pie_unscaled(float xi, float yi, float w, float h, double b1, double b2)
|
||||
{
|
||||
Fl_Color c = fl_color();
|
||||
fl_color(FL_RED);
|
||||
double a1 = b1/180*M_PI;
|
||||
double a2 = b2/180*M_PI;
|
||||
double rx = w/2.0;
|
||||
double ry = h/2.0;
|
||||
double x = xi + rx;
|
||||
double y = yi + ry;
|
||||
double yMin = y - sin(a1), yMax = y - sin(a2);
|
||||
if (yMin>yMax) { double s = yMin; yMin = yMax; yMax = s; }
|
||||
Fl_Android_Application::log_e("------ PI");
|
||||
for (double i=y-ry; i<=y+ry; i++) {
|
||||
double a = asin((i-y)/ry);
|
||||
double aR = a; if (aR<0.0) aR+=2*M_PI;
|
||||
double aL = M_PI-a;
|
||||
Fl_Android_Application::log_e("%g %g", aL, aR);
|
||||
#if 0
|
||||
if (aL>=a1 && aL<=a2)
|
||||
xyline_unscaled(x-cos(a)*rx, i, x);
|
||||
|
||||
if (aR>=a1 && aR<=a2)
|
||||
xyline_unscaled(x, i, x+cos(a)*rx);
|
||||
#else
|
||||
xyline_unscaled(x-cos(a)*rx, i, x+cos(a)*rx);
|
||||
#endif
|
||||
//xyline_unscaled(sin(a)*rx, i, y);
|
||||
}
|
||||
fl_color(FL_GREEN);
|
||||
line_unscaled(x, y, x+cos(0.5*M_PI)*rx, y+sin(0.5*M_PI)*ry);
|
||||
fl_color(c);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
|
|
|
@ -517,11 +517,11 @@ void Fl_Android_Graphics_Driver::draw_unscaled(const char* str, int n, int x, in
|
|||
if (str) {
|
||||
int dx, dy, w, h;
|
||||
text_extents_unscaled(str, n, dx, dy, w, h);
|
||||
pClippingRegion.print("<---- clip text to this");
|
||||
Fl_Rect_Region(x+dx, y+dy, w, h).print(str);
|
||||
//pClippingRegion.print("<---- clip text to this");
|
||||
//Fl_Rect_Region(x+dx, y+dy, w, h).print(str);
|
||||
for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(x+dx, y+dy, w, h))) {
|
||||
Fl_Rect_Region &r = it->clipped_rect();
|
||||
r.print("Clip");
|
||||
//r.print("Clip");
|
||||
const char *e = str + n;
|
||||
for (int i = 0; i < n;) {
|
||||
int incr = 1;
|
||||
|
|
Loading…
Reference in New Issue