Android: Fixed another bug when deleting complex clipping areas

Better complex region cleanup - should be compete now...

git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12772 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
This commit is contained in:
Matthias Melcher 2018-03-18 14:58:25 +00:00
parent 5900d824e9
commit d252801a31
4 changed files with 65 additions and 72 deletions

View File

@ -149,6 +149,7 @@ public:
Fl_Complex_Region();
Fl_Complex_Region(const Fl_Rect_Region&);
virtual ~Fl_Complex_Region() override;
void delete_all_subregions();
virtual void set(const Fl_Rect_Region &r) override;
void set(const Fl_Complex_Region &r);

View File

@ -212,6 +212,19 @@ Fl_Complex_Region::Fl_Complex_Region(const Fl_Rect_Region &r) :
* Delete this region, all subregions recursively, and all following regions.
*/
Fl_Complex_Region::~Fl_Complex_Region()
{
delete_all_subregions();
}
/**
* Delete all subregions of this region.
* The pSubregion pointer should always be seen as a list of subregions, rather
* than a single region and some pNext pointer. So everything we do, we should
* probably do for every object in that list.
*
* Also note, that the top level region never has pNext pointing to anything.
*/
void Fl_Complex_Region::delete_all_subregions()
{
// Do NOT delete the chain in pNext! The caller has to that job.
// A top-level coplex region has pNext always set to NULL, and it does
@ -219,7 +232,7 @@ Fl_Complex_Region::~Fl_Complex_Region()
while (pSubregion) {
Fl_Complex_Region *rgn = pSubregion;
pSubregion = rgn->pNext;
delete rgn;
delete rgn; rgn = 0;
}
}
@ -256,7 +269,7 @@ void Fl_Complex_Region::print_data(int indent) const
void Fl_Complex_Region::set(const Fl_Rect_Region &r)
{
Fl_Rect_Region::set(r);
delete pSubregion; pSubregion = 0;
delete_all_subregions();
}
/**
@ -266,17 +279,21 @@ void Fl_Complex_Region::set(const Fl_Rect_Region &r)
*/
void Fl_Complex_Region::set(const Fl_Complex_Region &r)
{
// outline:
// clear this region and copy the coordinates from r
delete pSubregion; pSubregion = 0;
Fl_Rect_Region::set((const Fl_Rect_Region&)r);
if (r.pSubregion) {
pSubregion = new Fl_Complex_Region();
pSubregion->set(*r.subregion());
}
if (r.pNext) {
pNext = new Fl_Complex_Region();
pNext->set(*r.next());
delete_all_subregions();
Fl_Complex_Region *srcRgn = r.pSubregion;
if (srcRgn) {
// copy first subregion
Fl_Complex_Region *dstRgn = pSubregion = new Fl_Complex_Region();
pSubregion->set(*srcRgn);
// copy rest of list
while (srcRgn) {
dstRgn->pNext = new Fl_Complex_Region();
dstRgn = dstRgn->next();
dstRgn->set(*srcRgn);
srcRgn = srcRgn->next();
}
}
}
@ -288,28 +305,15 @@ void Fl_Complex_Region::set(const Fl_Complex_Region &r)
int Fl_Complex_Region::intersect_with(const Fl_Rect_Region &r)
{
if (pSubregion) {
pSubregion->intersect_with(r);
Fl_Complex_Region *rgn = pSubregion;
while (rgn) {
rgn->intersect_with(r);
rgn = rgn->next();
}
compress();
} else {
int intersects = Fl_Rect_Region::intersect_with(r);
switch (intersects) {
case EMPTY:
// Will be deleted by compress()
break;
case SAME:
// nothing to do
break;
case LESS:
// nothing to do
break;
default:
Fl_Android_Application::log_e("Invalid case in %s:%d", __FUNCTION__, __LINE__);
break;
}
if (pNext) {
pNext->intersect_with(r);
}
Fl_Rect_Region::intersect_with(r);
}
compress();
return 0;
}
@ -321,7 +325,12 @@ int Fl_Complex_Region::intersect_with(const Fl_Rect_Region &r)
int Fl_Complex_Region::subtract(const Fl_Rect_Region &r)
{
if (pSubregion) {
pSubregion->subtract(r);
Fl_Complex_Region *rgn = pSubregion;
while (rgn) {
rgn->subtract(r);
rgn = rgn->next();
}
compress();
} else {
// Check if we overlap at all
Fl_Rect_Region s(r);
@ -341,11 +350,8 @@ int Fl_Complex_Region::subtract(const Fl_Rect_Region &r)
Fl_Android_Application::log_e("Invalid case in %s:%d", __FUNCTION__, __LINE__);
break;
}
if (pNext) {
pNext->subtract(r);
}
if (pSubregion) compress(); // because intersecting this may have created subregions
}
compress();
return 0;
}
@ -365,41 +371,27 @@ void Fl_Complex_Region::compress()
Fl_Complex_Region *rgn = pSubregion;
while (rgn && rgn->is_empty()) {
pSubregion = rgn->next();
delete rgn;
rgn = pSubregion;
}
#if 0
// FIXME: remove emty rectangles and lift single rectangles
// TODO: merging rectangles may take much too much time with little benefit
print("compress");
while (rgn && rgn->is_empty()) {
pSubregion = rgn->next();
delete rgn;
rgn = pSubregion;
delete rgn; rgn = pSubregion;
}
if (!pSubregion) return;
rgn = pSubregion;
while (rgn) {
Fl_Complex_Region *nextRgn = rgn->next();
if (nextRgn && nextRgn->is_empty()) {
rgn->pNext = nextRgn->next();
delete nextRgn;
nextRgn = rgn->pNext;
while (rgn->pNext && rgn->pNext->is_empty()) {
Fl_Complex_Region *nextNext = rgn->pNext->pNext;
delete rgn->pNext; rgn->pNext = nextNext;
}
rgn = rgn->next();
}
if (!pSubregion) return;
// find rectangles that can be merged into a single new rectangle
// (Too much work for much too little benefit)
// if there is only a single subregion left, merge it into this region
if (pSubregion->pNext==nullptr) {
set((Fl_Rect_Region&)*pSubregion); // deletes subregion for us
}
if (!pSubregion) return;
#endif
// finally, update the boudning box
Fl_Rect_Region::set((Fl_Rect_Region&)*pSubregion);
@ -484,7 +476,7 @@ Fl_Complex_Region::Iterator Fl_Complex_Region::begin()
*/
Fl_Complex_Region::Iterator Fl_Complex_Region::end()
{
return Iterator(0L);
return Iterator(nullptr);
}
/**
@ -574,7 +566,7 @@ Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlappi
*/
Fl_Complex_Region::Overlapping::OverlappingIterator Fl_Complex_Region::Overlapping::end()
{
return OverlappingIterator(0L);
return OverlappingIterator(nullptr);
}
/**
@ -630,7 +622,7 @@ bool Fl_Complex_Region::Overlapping::find_next()
} else {
pRegion = pRegion->parent(); // can be NULL
}
return (pRegion != 0L);
return (pRegion != nullptr);
}
// -----------------------------------------------------------------------------

View File

@ -69,7 +69,7 @@ static const char *old_font_names[] = {
* Create an empty Bytemap.
*/
Fl_Android_Bytemap::Fl_Android_Bytemap() :
pBytes(0L)
pBytes(nullptr)
{
}
@ -90,7 +90,7 @@ Fl_Android_Bytemap::~Fl_Android_Bytemap()
* @param fnum the index into the fl_fonts table
*/
Fl_Android_Font_Source::Fl_Android_Font_Source(const char *fname, Fl_Font fnum) :
pFileBuffer(0L),
pFileBuffer(nullptr),
pName(fname),
pFontIndex(fnum),
pError(false)
@ -133,7 +133,7 @@ bool Fl_Android_Font_Source::load_font_asset(const char *name)
errno = 0;
AAssetManager *aMgr = Fl_Android_Application::get_asset_manager();
AAsset *aFile = AAssetManager_open(aMgr, name, AASSET_MODE_STREAMING);
if (aFile == NULL) {
if (aFile == nullptr) {
Fl_Android_Application::log_w("Can't open font asset at '%s': ",
name, strerror(errno));
return false;
@ -173,7 +173,7 @@ bool Fl_Android_Font_Source::load_font_file(const char *name)
strcpy(buf, name);
}
FILE *f = fopen(buf, "rb");
if (f == NULL) {
if (f == nullptr) {
Fl_Android_Application::log_w("Can't open font file at '%s': ",
name, strerror(errno));
return false;
@ -242,7 +242,7 @@ void Fl_Android_Font_Source::load_font()
Fl_Android_Bytemap *Fl_Android_Font_Source::get_bytemap(uint32_t c, int size)
{
if (pFileBuffer==0) load_font();
if (pError) return 0L;
if (pError) return nullptr;
Fl_Android_Bytemap *bm = new Fl_Android_Bytemap();
@ -330,7 +330,7 @@ Fl_Android_Font_Descriptor::~Fl_Android_Font_Descriptor()
{
// Life is easy in C++11.
for (auto &i: pBytemapTable) {
delete i.second;
delete i.second; i.second = nullptr;
}
}

View File

@ -77,7 +77,7 @@ int Fl_Android_Screen_Driver::handle_app_command()
// call all registered FLTK system handlers
Fl::e_number = ((uint32_t)(cmd-Fl_Android_Application::APP_CMD_INPUT_CHANGED)) + FL_ANDROID_EVENT_INPUT_CHANGED;
fl_send_system_handlers(0L);
fl_send_system_handlers(nullptr);
// fixup and finalize application wide command handling
Fl_Android_Application::post_exec_cmd(cmd);
@ -87,7 +87,7 @@ int Fl_Android_Screen_Driver::handle_app_command()
int Fl_Android_Screen_Driver::handle_input_event()
{
AInputQueue *queue = Fl_Android_Application::input_event_queue();
AInputEvent *event = NULL;
AInputEvent *event = nullptr;
if (AInputQueue_getEvent(queue, &event) >= 0) {
if (AInputQueue_preDispatchEvent(queue, event)==0) {
@ -179,7 +179,7 @@ int Fl_Android_Screen_Driver::handle_queued_events(double time_to_wait)
struct android_poll_source *source;
for (;;) {
ident = ALooper_pollAll(Fl::damage() ? 0 : -1, NULL, &events, (void **) &source);
ident = ALooper_pollAll(Fl::damage() ? 0 : -1, nullptr, &events, (void **) &source);
switch (ident) {
// FIXME: ALOOPER_POLL_WAKE = -1, ALOOPER_POLL_CALLBACK = -2, ALOOPER_POLL_TIMEOUT = -3, ALOOPER_POLL_ERROR = -4
case Fl_Android_Application::LOOPER_ID_MAIN:
@ -718,7 +718,7 @@ struct TimerData
bool triggered;
struct itimerspec timeout;
};
static TimerData* timerData = 0L;
static TimerData* timerData = nullptr;
static int NTimerData = 0;
static int nTimerData = 0;
@ -818,7 +818,7 @@ void Fl_Android_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb
{ 0, 0 },
{ (time_t)floor(time), (long)(modf(time, &ff)*1000000000) }
};
ret = timer_settime(t.handle, 0, &t.timeout, 0L);
ret = timer_settime(t.handle, 0, &t.timeout, nullptr);
if (ret==-1) {
Fl_Android_Application::log_e("Can't launch timer: %s", strerror(errno));
return;
@ -843,7 +843,7 @@ void Fl_Android_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void *data)
{
for (int i = 0; i < nTimerData; ++i) {
TimerData& t = timerData[i];
if ( t.used && (t.callback==cb) && ( (t.data==data) || (data==NULL) ) ) {
if ( t.used && (t.callback==cb) && ( (t.data==data) || (data==nullptr) ) ) {
if (t.used)
timer_delete(t.handle);
t.triggered = t.used = false;