diff options
| -rw-r--r-- | FL/Fl_Rect.H | 15 | ||||
| -rw-r--r-- | FL/platform_types.h | 7 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver.H | 63 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver.cxx | 26 | ||||
| -rw-r--r-- | src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx | 71 |
5 files changed, 136 insertions, 46 deletions
diff --git a/FL/Fl_Rect.H b/FL/Fl_Rect.H index 307410ef7..134521d16 100644 --- a/FL/Fl_Rect.H +++ b/FL/Fl_Rect.H @@ -52,21 +52,24 @@ public: Fl_Rect(int X, int Y, int W, int H) : x_(X), y_(Y), w_(W), h_(H) {} - /** This constructor creates a rectangle based on a widget's position and size. */ + /** This constructor creates a rectangle based on a widget's position and size. */ Fl_Rect (const Fl_Widget& widget) : x_(widget.x()), y_(widget.y()), w_(widget.w()), h_(widget.h()) {} - /** This constructor creates a rectangle based on a widget's position and size. */ + /** This constructor creates a rectangle based on a widget's position and size. */ Fl_Rect (const Fl_Widget* const widget) : x_(widget->x()), y_(widget->y()), w_(widget->w()), h_(widget->h()) {} - /** Return 1 if the rectangle is empty, width or height are 0 */ - int is_empty() { return (w_==0)||(h_==0); } + /** Return 1 if the rectangle is empty, width or height are 0 */ + int is_empty() { return (w_<=0)||(h_<=0); } - /** Set the position and size */ + /** Set the position and size */ void set(int x, int y, int w, int h) { x_=x; y_=y; w_=w; h_=h; } - /** return 0 if the rectangles are different, or 1 if they are the same */ + /** Clone another rectangle */ + void set(Fl_Rect *r) { x_=r->x_; y_=r->y_; w_=r->w_; h_=r->h_; } + + /** return 0 if the rectangles are different, or 1 if they are the same */ int equals(int x, int y, int w, int h) { return ( (x_==x) && (y_==y) && (w_==w) && (h_==h) ); } /** Set the position and size to zero, making this rect empty */ diff --git a/FL/platform_types.h b/FL/platform_types.h index 286fc68d1..9f6ed1e44 100644 --- a/FL/platform_types.h +++ b/FL/platform_types.h @@ -114,8 +114,11 @@ struct dirent {char d_name[1];}; #elif defined(__ANDROID__) -// see: src/driver/Android/Fl_Android_Graphics_Driver_region.cxx -typedef struct Fl_Clip_Rect *Fl_Region; +#ifdef __cplusplus +typedef class Fl_Rect_Region *Fl_Region; +#else +typedef struct Fl_Rect_Region *Fl_Region; +#endif // TODO: the types below have not yet been ported typedef unsigned long Fl_Offscreen; diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.H b/src/drivers/Android/Fl_Android_Graphics_Driver.H index a55e39400..6e03e26da 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver.H +++ b/src/drivers/Android/Fl_Android_Graphics_Driver.H @@ -30,18 +30,61 @@ #include <limits.h> -struct Fl_Clip_Rect +/** + * The Fl_Rect_Region is based on Fl_Rect with additional functionality for clipping. + */ +class Fl_Rect_Region : public Fl_Rect { - Fl_Clip_Rect() : pRect() {} - Fl_Clip_Rect(int x, int y, int w, int h) : pRect(x, y, w, h) {} - int x() { return pRect.x(); } - int y() { return pRect.y(); } - int w() { return pRect.w(); } - int h() { return pRect.h(); } - int intersect_with(Fl_Clip_Rect *r); +public: + enum { + EMPTY = 0, SAME, LESS, MORE + }; + + /** + * Create an empty clipping region. + */ + Fl_Rect_Region() {} + + /** + * Create a clipping region based on position and size. + * @param x, y position + * @param w, h size + */ + Fl_Rect_Region(int x, int y, int w, int h) : Fl_Rect(x, y, w, h) {} + int intersect_with(Fl_Rect_Region *r); static int min(int a, int b) { return (a<b) ? a : b; } static int max(int a, int b) { return (a>b) ? a : b; } - Fl_Rect pRect; +}; + + +/** + * The Fl_Complex_Region represents a clipping region of any shape. + * + * This class is organized in a tree-like structure. If the region is + * rectangular, is_simple() returns 1 and the rectangle can be used just + * as in Fl_Rect_Region. + * + * If a more complex representation is needed, the first list of + * subregions is organizen in horizontal strips. The root region rect + * will contain the outline of all subregions, and the subregions + * will either be simple rectangles, or they will contain a second + * level of subregions, subdividing the horizontal region into vertical + * columns. + * + * When reading, the tree can be easily walked using recursion. + */ +class Fl_Complex_Region : public Fl_Rect_Region +{ +public: + Fl_Complex_Region() : Fl_Rect_Region(), pSubregion(0L), pNext(0L) { } + Fl_Complex_Region(int x, int y, int w, int h) : Fl_Rect_Region(x, y, w, h), pSubregion(0L), pNext(0L) { } + ~Fl_Complex_Region(); + void set(Fl_Rect *rect); + char is_simple() { return pSubregion==0; } + char is_complex() { return pSubregion!=0; } +protected: + Fl_Complex_Region *pSubregion; + Fl_Complex_Region *pNext; }; @@ -144,7 +187,7 @@ protected: void restore_clip(); void clip_region(Fl_Region r); Fl_Region clip_region(); - static Fl_Clip_Rect pClipRect; + static Fl_Complex_Region pWindowRegion; #if 0 virtual Fl_Region scale_clip(float f); // --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx index 1df52462a..2a0b62cc8 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver.cxx +++ b/src/drivers/Android/Fl_Android_Graphics_Driver.cxx @@ -55,10 +55,32 @@ static uint16_t make565(Fl_Color crgba) void Fl_Android_Graphics_Driver::rectf_unscaled(float x, float y, float w, float h) { Fl_Android_Application::log_w("rectf %g %g %g %g", x, y, w, h); - Fl_Clip_Rect r(x, y, w, h); - if (r.intersect_with(&pClipRect)) { + Fl_Rect_Region r(x, y, w, h); + if (r.intersect_with(&pWindowRegion)) { rectf_unclipped(r.x(), r.y(), r.w(), r.h()); } + + /* + * rectf(x, y, w, h) { + * rectf(complex_window_region, drawing_rect(x, y, w, h)) + * } + * + * rectf( complexRgn, drawRgn) { + * // B: start of iterator + * if (intersect(rect_of_complexRgn, drawRgn) { + * if (complexRgn->is_complex() { + * rectf(complexRgn->subregion, drawRect); + * } else { + * rawRect = intersection(rect_of_complexRgn, drawRgn); + * rawDrawRect(rawRect); + * } + * } + * // A: recursion + * if (complexRgn->next) + * rectf(complexRgn->next, drawRgn); + * // B: end of iterator + * } + */ } void Fl_Android_Graphics_Driver::rectf_unclipped(float x, float y, float w, float h) { diff --git a/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx b/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx index 107a6e708..27e105d89 100644 --- a/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx +++ b/src/drivers/Android/Fl_Android_Graphics_Driver_region.cxx @@ -23,37 +23,55 @@ #include <FL/platform.H> -Fl_Clip_Rect Fl_Android_Graphics_Driver::pClipRect; +Fl_Complex_Region Fl_Android_Graphics_Driver::pWindowRegion; + // return 0 for empty, 1 for same, 2 if intersecting -int Fl_Clip_Rect::intersect_with(Fl_Clip_Rect *a) +int Fl_Rect_Region::intersect_with(Fl_Rect_Region *a) { - if (pRect.is_empty()) { - return 0; + if (is_empty()) { + return EMPTY; } - if (a->pRect.is_empty()) { - pRect.clear(); - return 0; + if (a->is_empty()) { + clear(); + return EMPTY; } - int x = max(pRect.x(), a->pRect.x()); - int y = max(pRect.y(), a->pRect.y()); - int r = min(pRect.r(), a->pRect.r()); - int b = min(pRect.b(), a->pRect.b()); - int w = r-x; - int h = b-y; - if (pRect.equals(x, y, w, h)) { - return 1; + int lx = max(x(), a->x()); + int ly = max(y(), a->y()); + int lr = min(r(), a->r()); + int lb = min(b(), a->b()); + int lw = lr-lx; + int lh = lb-ly; + if (equals(lx, ly, lw, lh)) { + return SAME; } - pRect.set(x, y, w, h); - if ( (pRect.w()<=0) || (pRect.h()<=0) ) { - pRect.clear(); - return 0; + set(lx, ly, lw, lh); + if ( (w()<=0) || (h()<=0) ) { + clear(); + return EMPTY; } - return 2; + return LESS; +} + + + +Fl_Complex_Region::~Fl_Complex_Region() +{ + delete pSubregion; // recursively delete all subregions + delete pNext; // recursively delete all following regions } +void Fl_Complex_Region::set(Fl_Rect *rect) +{ + delete pSubregion; + pSubregion = 0L; + delete pNext; + pNext = 0L; + Fl_Rect_Region::set(rect); +} + void Fl_Android_Graphics_Driver::clip_region(Fl_Region r) { @@ -73,27 +91,28 @@ void Fl_Android_Graphics_Driver::restore_clip() { fl_clip_state_number++; Fl_Window *win = Fl_Window::current(); - Fl_Clip_Rect a(0, 0, win->w(), win->h()); + Fl_Rect_Region a(0, 0, win->w(), win->h()); Fl_Region b = rstack[rstackptr]; if (b) { // FIXME: scaling! a.intersect_with(b); } - pClipRect = a; + pWindowRegion.set(b); + // FIXME: intersect with complex window region } void Fl_Android_Graphics_Driver::push_clip(int x, int y, int w, int h) { Fl_Region r; if (w > 0 && h > 0) { - r = new Fl_Clip_Rect(x,y,w,h); + r = new Fl_Rect_Region(x,y,w,h); Fl_Region current = rstack[rstackptr]; if (current) { r->intersect_with(current); } } else { // make empty clip region: - r = new Fl_Clip_Rect(); + r = new Fl_Rect_Region(); } if (rstackptr < region_stack_max) rstack[++rstackptr] = r; else Fl::warning("Fl_Android_Graphics_Driver::push_clip: clip stack overflow!\n"); @@ -136,7 +155,7 @@ int Fl_Android_Graphics_Driver::clip_box(int x, int y, int w, int h, int& X, int return 0; } - Fl_Clip_Rect a(x, y, w, h); + Fl_Rect_Region a(x, y, w, h); int ret = a.intersect_with(r); // return 0 for empty, 1 for same, 2 if intersecting X = a.x(); Y = a.y(); @@ -161,7 +180,7 @@ int Fl_Android_Graphics_Driver::not_clipped(int x, int y, int w, int h) { Fl_Region r = rstack[rstackptr]; if (!r) return 1; - Fl_Clip_Rect a(x, y, w, h); // return 0 for empty, 1 for same, 2 if intersecting + Fl_Rect_Region a(x, y, w, h); // return 0 for empty, 1 for same, 2 if intersecting return a.intersect_with(r); } |
