summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2018-03-22 15:27:02 +0000
committerMatthias Melcher <fltk@matthiasm.com>2018-03-22 15:27:02 +0000
commit0b8116ff72145816c3e1d4909038c126327e7bf2 (patch)
tree6559a0aca4e1047fe4906fa474ab463fc3229778
parent3a20682764807173ec6b0e354ede9b57930ff6a7 (diff)
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
-rw-r--r--FL/android.H17
-rw-r--r--ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx254
-rw-r--r--src/drivers/Android/Fl_Android_Application.H16
-rw-r--r--src/drivers/Android/Fl_Android_Application.cxx1
-rw-r--r--src/drivers/Android/Fl_Android_Graphics_Driver.H47
-rw-r--r--src/drivers/Android/Fl_Android_Graphics_Driver.cxx447
-rw-r--r--src/drivers/Android/Fl_Android_Graphics_Font.cxx6
7 files changed, 750 insertions, 38 deletions
diff --git a/FL/android.H b/FL/android.H
index 262ab82b7..573664984 100644
--- a/FL/android.H
+++ b/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
diff --git a/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx b/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx
index 882d4189f..d68dcd4e2 100644
--- a/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx
+++ b/ide/AndroidStudio3/app/src/main/cpp/HelloAndroid.cxx
@@ -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
+
+ */ \ No newline at end of file
diff --git a/src/drivers/Android/Fl_Android_Application.H b/src/drivers/Android/Fl_Android_Application.H
index dc5838525..20862ab46 100644
--- a/src/drivers/Android/Fl_Android_Application.H
+++ b/src/drivers/Android/Fl_Android_Application.H
@@ -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
//
diff --git a/src/drivers/Android/Fl_Android_Application.cxx b/src/drivers/Android/Fl_Android_Application.cxx
index c1d69b9f8..97b692199 100644
--- a/src/drivers/Android/Fl_Android_Application.cxx
+++ b/src/drivers/Android/Fl_Android_Application.cxx
@@ -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>
diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.H b/src/drivers/Android/Fl_Android_Graphics_Driver.H
index dcfd27446..95d97880a 100644
--- a/src/drivers/Android/Fl_Android_Graphics_Driver.H
+++ b/src/drivers/Android/Fl_Android_Graphics_Driver.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;
};
diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx
index 71ffa6224..fbd85fc34 100644
--- a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx
+++ b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx
@@ -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
diff --git a/src/drivers/Android/Fl_Android_Graphics_Font.cxx b/src/drivers/Android/Fl_Android_Graphics_Font.cxx
index 5a06a0ad7..da8f9ddf4 100644
--- a/src/drivers/Android/Fl_Android_Graphics_Font.cxx
+++ b/src/drivers/Android/Fl_Android_Graphics_Font.cxx
@@ -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;