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:
Matthias Melcher 2018-03-22 15:27:02 +00:00
parent 3a20682764
commit 0b8116ff72
7 changed files with 750 additions and 38 deletions

View File

@ -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

View File

@ -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
*/

View File

@ -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
//

View File

@ -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>

View File

@ -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;
};

View File

@ -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

View File

@ -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;