| /* |
| * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer. |
| * 2. Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials |
| * provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
| * OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "ExclusionInterval.h" |
| |
| #include <wtf/MathExtras.h> |
| |
| namespace WebCore { |
| |
| struct IntervalX1Comparator { |
| bool operator() (const ExclusionInterval& i1, const ExclusionInterval& i2) const |
| { |
| return i1.x1 < i2.x1; |
| } |
| }; |
| |
| bool ExclusionInterval::intersect(const ExclusionInterval& i, ExclusionInterval& rv) const |
| { |
| if (x2 < i.x1 || x1 > i.x2) |
| return false; |
| rv.x1 = std::max(x1, i.x1); |
| rv.x2 = std::min(x2, i.x2); |
| return true; |
| } |
| |
| void sortExclusionIntervals(Vector<ExclusionInterval>& v) |
| { |
| std::sort(v.begin(), v.end(), IntervalX1Comparator()); |
| } |
| |
| void mergeExclusionIntervals(const Vector<ExclusionInterval>& v1, const Vector<ExclusionInterval>& v2, Vector<ExclusionInterval>& rv) |
| { |
| if (!v1.size()) |
| rv.appendRange(v2.begin(), v2.end()); |
| else if (!v2.size()) |
| rv.appendRange(v1.begin(), v1.end()); |
| else { |
| Vector<ExclusionInterval> v(v1.size() + v2.size()); |
| ExclusionInterval* interval = 0; |
| |
| std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin(), IntervalX1Comparator()); |
| |
| for (size_t i = 0; i < v.size(); i++) { |
| if (!interval) |
| interval = &v[i]; |
| else if (v[i].x1 >= interval->x1 && v[i].x1 <= interval->x2) // FIXME: 1st <= test not needed? |
| interval->x2 = std::max(interval->x2, v[i].x2); |
| else { |
| rv.append(*interval); |
| interval = &v[i]; |
| } |
| } |
| |
| if (interval) |
| rv.append(*interval); |
| } |
| } |
| |
| void intersectExclusionIntervals(const Vector<ExclusionInterval>& v1, const Vector<ExclusionInterval>& v2, Vector<ExclusionInterval>& rv) |
| { |
| size_t v1Size = v1.size(); |
| size_t v2Size = v2.size(); |
| |
| if (!v1Size || !v2Size) |
| return; |
| |
| ExclusionInterval interval; |
| bool overlap = false; |
| size_t i1 = 0; |
| size_t i2 = 0; |
| |
| while (i1 < v1Size && i2 < v2Size) { |
| ExclusionInterval v12; |
| if (v1[i1].intersect(v2[i2], v12)) { |
| if (!overlap || !v12.intersect(interval, interval)) { |
| if (overlap) |
| rv.append(interval); |
| interval = v12; |
| overlap = true; |
| } |
| if (v1[i1].x2 < v2[i2].x2) |
| i1++; |
| else |
| i2++; |
| } else { |
| if (overlap) |
| rv.append(interval); |
| overlap = false; |
| if (v1[i1].x1 < v2[i2].x1) |
| i1++; |
| else |
| i2++; |
| } |
| } |
| |
| if (overlap) |
| rv.append(interval); |
| } |
| |
| void subtractExclusionIntervals(const Vector<ExclusionInterval>& v1, const Vector<ExclusionInterval>& v2, Vector<ExclusionInterval>& rv) |
| { |
| size_t v1Size = v1.size(); |
| size_t v2Size = v2.size(); |
| |
| if (!v1Size) |
| return; |
| |
| if (!v2Size) |
| rv.appendRange(v1.begin(), v1.end()); |
| else { |
| size_t i1 = 0, i2 = 0; |
| rv.appendRange(v1.begin(), v1.end()); |
| |
| while (i1 < rv.size() && i2 < v2Size) { |
| ExclusionInterval& interval1 = rv[i1]; |
| const ExclusionInterval& interval2 = v2[i2]; |
| |
| if (interval2.x1 <= interval1.x1 && interval2.x2 >= interval1.x2) |
| rv.remove(i1); |
| else if (interval2.x2 < interval1.x1) |
| i2 += 1; |
| else if (interval2.x1 > interval1.x2) |
| i1 += 1; |
| else if (interval2.x1 > interval1.x1 && interval2.x2 < interval1.x2) { |
| rv.insert(i1, ExclusionInterval(interval1.x1, interval2.x1)); |
| interval1.x1 = interval2.x2; |
| i2 += 1; |
| } else if (interval2.x1 <= interval1.x1) { |
| interval1.x1 = interval2.x2; |
| i2 += 1; |
| } else { // (interval2.x2 >= interval1.x2) |
| interval1.x2 = interval2.x1; |
| i1 += 1; |
| } |
| } |
| } |
| } |
| |
| } // namespace WebCore |