diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/Android/Fl_Android_Application.H | 16 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Application.cxx | 1 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver.H | 47 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver.cxx | 447 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Font.cxx | 6 |
5 files changed, 484 insertions, 33 deletions
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; |
