Android: clipping code cleanup, xy and yx lines are clipped

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12755 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2018-03-15 21:50:27 +00:00
parent 6a145ed63a
commit ce5371cbf0
3 changed files with 45 additions and 181 deletions

View File

@ -118,7 +118,7 @@ class Fl_Complex_Region : public Fl_Rect_Region
Overlapping *pOv;
};
public:
Overlapping(Fl_Complex_Region *rgn, Fl_Rect_Region &rect);
Overlapping(Fl_Complex_Region *rgn, const Fl_Rect_Region &rect);
OverlappingIterator begin();
OverlappingIterator end();
Fl_Rect_Region &clipped_rect();
@ -151,7 +151,7 @@ public:
Iterator begin();
Iterator end();
Overlapping overlapping(Fl_Rect_Region &r);
Overlapping overlapping(const Fl_Rect_Region &r);
protected:
void print_data(int indent) const;
@ -189,7 +189,7 @@ protected:
#endif
public:
Fl_Android_Graphics_Driver();
~Fl_Android_Graphics_Driver();
virtual ~Fl_Android_Graphics_Driver() override;
#if 0
Fl_GDI_Graphics_Driver() {mask_bitmap_ = NULL; gc_ = NULL; p_size = 0; p = NULL; depth = -1; origins = NULL;}
virtual ~Fl_GDI_Graphics_Driver() { if (p) free(p); delete[] origins;}
@ -202,7 +202,7 @@ public:
Fl_Bitmask create_bitmask(int w, int h, const uchar *array);
void delete_bitmask(Fl_Bitmask bm);
#endif
virtual void draw_unscaled(const char* str, int n, int x, int y);
virtual void draw_unscaled(const char* str, int n, int x, int y) override;
#if 0
virtual void draw_unscaled(int angle, const char *str, int n, int x, int y);
virtual void rtl_draw_unscaled(const char* str, int n, int x, int y);
@ -244,14 +244,16 @@ protected:
void rect_unscaled(float x, float y, float w, float h);
void focus_rect(int x, int y, int w, int h);
#endif
void rectf_unscaled(float x, float y, float w, float h);
virtual void rectf_unscaled(float x, float y, float w, float h) override;
void rectf_unclipped(float x, float y, float w, float h);
#if 0
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);
#endif
virtual void xyline_unscaled(float x, float y, float x1);
virtual void yxline_unscaled(float x, float y, float y1);
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);
#if 0
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);
@ -259,14 +261,14 @@ protected:
virtual void polygon_unscaled(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3);
#endif
// --- clipping
void push_clip(int x, int y, int w, int h);
int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H);
int not_clipped(int x, int y, int w, int h);
void push_no_clip();
void pop_clip();
void restore_clip();
void clip_region(Fl_Region r);
Fl_Region clip_region();
virtual void push_clip(int x, int y, int w, int h) override;
virtual int clip_box(int x, int y, int w, int h, int &X, int &Y, int &W, int &H) override;
virtual int not_clipped(int x, int y, int w, int h) override;
virtual void push_no_clip() override;
virtual void pop_clip() override;
virtual void restore_clip() override;
virtual void clip_region(Fl_Region r) override;
virtual Fl_Region clip_region() override;
#if 0
virtual Fl_Region scale_clip(float f);
// --- implementation is in src/fl_vertex.cxx which includes src/cfg_gfx/xxx_rect.cxx

View File

@ -61,7 +61,6 @@ void Fl_Android_Graphics_Driver::make_current(Fl_Window *win)
pWindowRegion.intersect_with(Fl_Rect_Region(0, 0, win->w(), win->h()));
pDesktopWindowRegion.set(pWindowRegion);
pDesktopWindowRegion.print(win->label());
// remove all window rectangles that are positioned on top of this window
// TODO: this region is expensive to calculate. Cache it for each window and recalculate when windows move, show, hide, or change order
@ -72,9 +71,7 @@ void Fl_Android_Graphics_Driver::make_current(Fl_Window *win)
pDesktopWindowRegion.subtract(r);
wTop = Fl::next_window(wTop);
}
pDesktopWindowRegion.print(" #### DESKTOP");
pClippingRegion.set(pDesktopWindowRegion);
pClippingRegion.print("#### CLIPPING");
}
@ -95,88 +92,20 @@ static uint16_t make565(Fl_Color crgba)
((crgba >>11) & 0x001f) );
}
void Fl_Android_Graphics_Driver::rectf_unscaled(float x, float y, float w, float h)
{
#if 1
Fl_Rect_Region r(x, y, w, h);
for (const auto &it: pClippingRegion.overlapping(r)) {
#if 1
for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(x, y, w, h))) {
Fl_Rect_Region s(it->clipped_rect());
rectf_unclipped(s.x(), s.y(), s.w(), s.h());
#else
if (it->is_simple()) {
Fl_Rect_Region r(x, y, w, h);
if (r.intersect_with(*it)) {
rectf_unclipped(r.x(), r.y(), r.w(), r.h());
}
}
#endif
}
#elif 0
// This is elegant code, but it is not efficient. It walks the entire tree
// and checks for intersetion, even if the parent region indicated that there
// is no intersection.
//
// Maybe we can add a parameter somewhere so that the iterator runs the tree
// based on a give rectangle.
for (const auto &it: pClippingRegion) {
// TODO: if region is complex, but doesn't intersect, can we somehow manipulate the iterator?
if (it->is_simple()) {
Fl_Rect_Region r(x, y, w, h);
if (r.intersect_with(*it)) {
rectf_unclipped(r.x(), r.y(), r.w(), r.h());
}
}
}
#else
// This code is massiv and ugly and has the same problem in that it does not
// optimize the number of tests for intersections.
r.print("---- fl_rectf");
pClippingRegion.print("clip to");
for (Fl_Complex_Region *cr = &pClippingRegion; cr; cr=cr->next()) {
if (cr->subregion()) {
for (Fl_Complex_Region *cr1 = cr->subregion(); cr1; cr1=cr1->next()) {
if (cr1->subregion()) {
for (Fl_Complex_Region *cr2 = cr1->subregion(); cr2; cr2 = cr2->next()) {
Fl_Rect_Region r(x, y, w, h);
if (r.intersect_with(*cr2)) {
rectf_unclipped(r.x(), r.y(), r.w(), r.h());
}
}
} else {
Fl_Rect_Region r(x, y, w, h);
if (r.intersect_with(*cr1)) {
rectf_unclipped(r.x(), r.y(), r.w(), r.h());
}
}
}
} else {
Fl_Rect_Region r(x, y, w, h);
if (r.intersect_with(*cr)) {
rectf_unclipped(r.x(), r.y(), r.w(), r.h());
}
}
}
#endif
}
void Fl_Android_Graphics_Driver::rectf_unclipped(float x, float y, float w, float h)
{
if (w<=0 || h<=0) return;
// TODO: clip the rectangle to the window outline
// TODO: clip the rectangle to all parts of the window region
// TODo: clip the rectangle to all parts of the current clipping region
uint16_t cc = make565(color());
int32_t ss = pStride;
uint16_t *bits = pBits;
@ -192,9 +121,9 @@ void Fl_Android_Graphics_Driver::rectf_unclipped(float x, float y, float w, floa
}
}
void Fl_Android_Graphics_Driver::xyline_unscaled(float x, float y, float x1)
{
uint16_t cc = make565(color());
float w;
if (x1>x) {
w = x1-x;
@ -202,6 +131,17 @@ void Fl_Android_Graphics_Driver::xyline_unscaled(float x, float y, float x1)
w = x-x1;
x = x1;
}
for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(x, y, w, 1))) {
Fl_Rect_Region s(it->clipped_rect());
xyline_unclipped(s.x(), s.y(), s.right());
}
}
void Fl_Android_Graphics_Driver::xyline_unclipped(float x, float y, float x1)
{
uint16_t cc = make565(color());
float w = x1-x;
int32_t ss = pStride;
uint16_t *bits = pBits;
uint32_t xx = (uint32_t)x;
@ -215,7 +155,6 @@ void Fl_Android_Graphics_Driver::xyline_unscaled(float x, float y, float x1)
void Fl_Android_Graphics_Driver::yxline_unscaled(float x, float y, float y1)
{
uint16_t cc = make565(color());
float h;
if (y1>y) {
h = y1-y;
@ -223,6 +162,16 @@ void Fl_Android_Graphics_Driver::yxline_unscaled(float x, float y, float y1)
h = y-y1;
y = y1;
}
for (const auto &it: pClippingRegion.overlapping(Fl_Rect_Region(x, y, 1, h))) {
Fl_Rect_Region s(it->clipped_rect());
yxline_unclipped(s.x(), s.y(), s.bottom());
}
}
void Fl_Android_Graphics_Driver::yxline_unclipped(float x, float y, float y1)
{
uint16_t cc = make565(color());
float h = y1-y;
int32_t ss = pStride;
uint16_t *bits = pBits;
uint32_t xx = (uint32_t)x;

View File

@ -220,11 +220,6 @@ void Fl_Complex_Region::set(const Fl_Rect_Region &r)
void Fl_Complex_Region::set(const Fl_Complex_Region &r)
{
#if 0
Fl_Android_Application::log_e("Not yet implemented!");
delete pSubregion; pSubregion = 0;
Fl_Rect_Region::set(r);
#else
// outline:
// clear this region and copy the coordinates from r
delete pSubregion; pSubregion = 0;
@ -237,7 +232,6 @@ void Fl_Complex_Region::set(const Fl_Complex_Region &r)
pNext = new Fl_Complex_Region();
pNext->set(*r.next());
}
#endif
}
@ -252,14 +246,11 @@ int Fl_Complex_Region::intersect_with(const Fl_Rect_Region &r)
int Fl_Complex_Region::subtract(const Fl_Rect_Region &r)
{
// FIXME: write me.
if (pSubregion) {
pSubregion->subtract(r);
} else {
// Check if we overlap at all
Fl_Rect_Region s(r);
this->print("---- subtract");
s.print("");
int intersects = s.intersect_with(*this);
switch (intersects) {
case EMPTY:
@ -287,9 +278,7 @@ int Fl_Complex_Region::subtract(const Fl_Rect_Region &r)
int Fl_Complex_Region::subtract_smaller_region(const Fl_Rect_Region &r)
{
// subtract a smaller rect from a larger rect and create subrects as needed
print("subtract_smaller_region");
r.print("");
// FIXME: make sure that the bbox of the parent region is shrunk to the size of all children
// if there is only one single coordinte different, we can reuse this container
if (left()==r.left() && top()==r.top() && right()==r.right() && bottom()==r.bottom()) {
// this should not happen
@ -320,8 +309,6 @@ int Fl_Complex_Region::subtract_smaller_region(const Fl_Rect_Region &r)
Fl_Complex_Region *s = add_subregion();
s->set_ltrb(r.right(), r.top(), pRight, r.bottom());
}
//Fl_Android_Application::log_w("Regions too complex. Not yet implemented");
print("-- added subregions");
}
return 0;
}
@ -383,14 +370,14 @@ Fl_Complex_Region *Fl_Complex_Region::Iterator::operator*() const
// -----------------------------------------------------------------------------
Fl_Complex_Region::Overlapping Fl_Complex_Region::overlapping(Fl_Rect_Region &r)
Fl_Complex_Region::Overlapping Fl_Complex_Region::overlapping(const Fl_Rect_Region &r)
{
return Overlapping(this, r);
}
Fl_Complex_Region::Overlapping::Overlapping(Fl_Complex_Region *rgn,
Fl_Rect_Region &rect) :
const Fl_Rect_Region &rect) :
pRegion(rgn),
pOriginalRect(rect),
pClippedRect(rect)
@ -428,9 +415,6 @@ bool Fl_Complex_Region::Overlapping::find_intersecting()
for (;;) {
if (!pRegion) return false;
pClippedRect.set(pOriginalRect);
pRegion->print("find intersetion");
pClippedRect.print("with");
pOriginalRect.print("with");
if (intersects()) {
if (!pRegion->subregion()) {
return true;
@ -493,77 +477,6 @@ Fl_Complex_Region::Overlapping::OverlappingIterator::operator*() const
// =============================================================================
#if 0
void Fl_Complex_Region::set(int x, int y, int w, int h)
{
// TODO: refactor the next four lines out, repeating
delete pSubregion;
pSubregion = 0L;
delete pNext;
pNext = 0L;
Fl_Rect_Region::set(x, y, w, h);
}
void Fl_Complex_Region::set(Fl_Rect *rect)
{
delete pSubregion;
pSubregion = 0L;
delete pNext;
pNext = 0L;
Fl_Rect_Region::set(rect);
}
/**
* Subtract a rectangle from this region.
*
* This operation may create multiple new subregions, but possibly also remove
* subregions.
*
* @param x, y, w, h rectangular region that will be subtracted
*/
void Fl_Complex_Region::subtract(Fl_Rect *r)
{
Fl_Android_Application::log_i("------------ subtract");
this->print();
Fl_Android_Application::log_i("--------");
Fl_Android_Application::log_i("Rect %d %d %d %d", r->x(), r->y(), r->w(), r->h());
// ----
this->print();
Fl_Android_Application::log_i("------------ subtract done");
// FIXME: implement
int x = 3;
}
void Fl_Complex_Region::intersect(Fl_Rect*)
{
// FIXME: implement
}
void Fl_Complex_Region::clone(Fl_Complex_Region *r)
{
// FIXME: implement
// make this region simple and copy the bounding box
set(r);
if (r->pSubregion) {
pSubregion = new Fl_Complex_Region();
pSubregion->clone(r->pSubregion);
}
if (r->pNext) {
pNext = new Fl_Complex_Region();
pNext->clone(r->pNext);
}
}
void Fl_Complex_Region::print()
{
Fl_Android_Application::log_i("-------- begin region");
print_data(0);
}
#endif
void Fl_Android_Graphics_Driver::restore_clip()
{