/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include bool Range::rangeIntersection(const Range& r,Range& rOut) const { if(m_start > r.getEnd() || r.getStart() > m_end) return false; int max_start = (m_start > r.getStart())? m_start:r.getStart(); int min_end = (m_end < r.getEnd())?m_end:r.getEnd(); int size = min_end - max_start; if(size) { rOut.setRange(max_start,min_end-max_start); return true; } return false; } bool Range::rangeUnion(const Range& r,Range& rOut) const { if(m_start > r.getEnd() || r.getStart() > m_end) return false; int min_start = (m_start < r.getStart())?m_start:r.getStart(); int max_end = (m_end > r.getEnd())?m_end:r.getEnd(); int size = max_end - min_start; if(size) { rOut.setRange(min_start,max_end-min_start); return true; } return false; } void RangeList::addRange(const Range& r) { if(r.getSize()) list.push_back(r); } void RangeList::addRanges(const RangeList& rl) { for(int i =0; i< rl.size();i++) { addRange(rl.list[i]); } } void RangeList::delRanges(const RangeList& rl,RangeList& deleted) { for(int i =0; i< rl.size();i++) { delRange(rl.list[i],deleted); } } bool RangeList::empty() const{ return list.empty(); } int RangeList::size() const{ return list.size(); } void RangeList::clear() { return list.clear(); } void RangeList::erase(unsigned int i) { if(i > list.size()) return; list.erase(list.begin() +i); } void RangeList::delRange(const Range& r,RangeList& deleted) { if(r.getSize() == 0) return; Range intersection; Range temp; // compare new rect to each and any of the rects on the list for (int i=0;i<(int)list.size();i++) { // i must be signed for i-- below // if there is intersection if (r.rangeIntersection(list[i],intersection)) { Range old=list[i]; // remove old as it is about to be split erase(i); i--; if (intersection!=old) { // otherwise split: //intersection on right side if(old.getStart() != intersection.getStart()) { list.insert(list.begin(),Range(old.getStart(),intersection.getStart() - old.getStart())); } //intersection on left side if(old.getEnd() != intersection.getEnd()) { list.insert(list.begin(),Range(intersection.getEnd(),old.getEnd() - intersection.getEnd())); } } deleted.addRange(intersection); } } } void RangeList::merge() { if(list.empty()) return; Range temp; bool changed; do { // re-run if changed in last run changed=0; // run for each combinations of two rects in the list for (int i=0;i<(((int)list.size())-1) && !changed ;i++) { for (int j=i+1;j<(int)list.size() && !changed ;j++) { if (list[i].rangeUnion(list[j],temp)) { // are them exactly one on left of the other list[i] = temp; erase(j); changed=1; } } } } while (changed); }