1 /************************************************************************
2 * *
3 * FreeSynd - a remake of the classic Bullfrog game "Syndicate". *
4 * *
5 * Copyright (C) 2010 Benoit Blancard <benblan@users.sourceforge.net>*
6 * *
7 * This program is free software; you can redistribute it and / or *
8 * modify it under the terms of the GNU General Public License as *
9 * published by the Free Software Foundation; either version 2 of the *
10 * License, or (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
15 * General Public License for more details. *
16 * *
17 * You can view the GNU General Public License, online, at the GNU *
18 * project's web site; see <http://www.gnu.org/licenses/gpl.html>. *
19 * The full text of the license is also included in the file COPYING. *
20 * *
21 ************************************************************************/
22
23 #include "common.h"
24 #include "dirtylist.h"
25
DirtyList(int screenWidth,int screenHeight)26 DirtyList::DirtyList(int screenWidth, int screenHeight) {
27 size_ = 0;
28 pHead_ = NULL;
29 screenWidth_ = screenWidth;
30 screenHeight_ = screenHeight;
31 }
32
~DirtyList()33 DirtyList::~DirtyList() {
34 flush();
35 }
36
createLink(int x,int y,int width,int height)37 DirtyList::Link * DirtyList::createLink(int x, int y, int width, int height) {
38 Link *l = new Link();
39 l->pNext = NULL;
40 l->pPrev = NULL;
41 l->element.x = x;
42 l->element.y = y;
43 l->element.width = width;
44 l->element.height = height;
45
46 return l;
47 }
48
addRect(int x,int y,int width,int height)49 void DirtyList::addRect(int x, int y, int width, int height) {
50
51 if (x >= screenWidth_ || y >= screenHeight_ ) {
52 return;
53 }
54
55 if (pHead_ == NULL) {
56 // Create new link
57 pHead_ = createLink(x, y, width, height);
58 } else {
59
60 Link *pCurr = pHead_;
61 do {
62 if (pCurr->element.x <= x && pCurr->element.y <= y &&
63 (pCurr->element.x + pCurr->element.width) >= (x + width) &&
64 (pCurr->element.y + pCurr->element.height) >= (y + height)) {
65 // Current rect is enclosing new rect so don't add new rect
66 return;
67 } else if (pCurr->element.x > x && pCurr->element.y > y &&
68 (pCurr->element.x + pCurr->element.width) < (x + width) &&
69 (pCurr->element.y + pCurr->element.height) < (y + height)) {
70 // Current rect is enclosed by new rect so remove it from the list
71 Link *pToRemove = pCurr;
72 if (pToRemove->pNext != NULL && pToRemove->pPrev != NULL) {
73 // Current is between 2 links
74 pToRemove->pPrev->pNext = pToRemove->pNext;
75 pToRemove->pNext->pPrev = pToRemove->pPrev;
76 pCurr = pToRemove->pNext;
77 } else if (pToRemove->pPrev != NULL && pToRemove->pNext == NULL) {
78 // We are on the last element of the list
79 pToRemove->pPrev->pNext = NULL;
80 pCurr = pToRemove->pPrev;
81 } else if (pToRemove->pPrev == NULL && pToRemove->pNext != NULL) {
82 // There no previous so we're on the head
83 pHead_ = pCurr = pToRemove->pNext;
84 pHead_->pPrev = NULL;
85 } else {
86 pCurr = NULL;
87 }
88
89 // Delete current
90 pToRemove->pNext = NULL;
91 pToRemove->pPrev = NULL;
92 delete pToRemove;
93 size_--;
94 } else if (pCurr->pNext == NULL) {
95 break;
96 } else {
97 pCurr = pCurr->pNext;
98 }
99
100 } while(pCurr != NULL);
101
102 Link *l = createLink(x, y, width, height);
103 if (pCurr == NULL) {
104 pHead_ = l;
105 } else {
106 pCurr->pNext = l;
107 l->pPrev = pCurr;
108 }
109 }
110 size_++;
111 }
112
getRectAt(int pos)113 DirtyRect * DirtyList::getRectAt(int pos) {
114 if (pHead_ && pos >= 0 && pos < size_) {
115 int i = 0;
116 Link * l = pHead_;
117 while (i < pos) {
118 l = l->pNext;
119 i++;
120 }
121 return &(l->element);
122 }
123
124 return NULL;
125 }
126
flush()127 void DirtyList::flush() {
128 size_ = 0;
129 if (pHead_) {
130 Link *pCurr = pHead_;
131 do {
132 Link *pNext = pCurr->pNext;
133 if (pNext) {
134 pNext->pPrev = NULL;
135 pCurr->pNext = NULL;
136 }
137 delete pCurr;
138 pCurr = pNext;
139 } while(pCurr != NULL);
140 }
141 pHead_ = NULL;
142 }
143
intersectsList(int x,int y,int width,int height)144 bool DirtyList::intersectsList(int x, int y, int width, int height)
145 {
146 if (pHead_) {
147 Link * l = pHead_;
148 while (l) {
149 if ( !((x > l->element.x + l->element.width) ||
150 (x + width < l->element.x) ||
151 (y > l->element.y + l->element.height) ||
152 (y + height < l->element.y)) ) {
153 return true;
154 }
155
156
157 l = l->pNext;
158 }
159 }
160
161 return false;
162 }
163