| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| 11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
| 12 * | 12 * |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
| 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
| 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| 23 * THE POSSIBILITY OF SUCH DAMAGE. | 23 * THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "config.h" | 26 #include "config.h" |
| 27 #include "core/platform/graphics/Region.h" | 27 #include "platform/geometry/Region.h" |
| 28 | 28 |
| 29 #include <stdio.h> | 29 #include <stdio.h> |
| 30 | 30 |
| 31 // A region class based on the paper "Scanline Coherent Shape Algebra" | 31 // A region class based on the paper "Scanline Coherent Shape Algebra" |
| 32 // by Jonathan E. Steinhart from the book "Graphics Gems II". | 32 // by Jonathan E. Steinhart from the book "Graphics Gems II". |
| 33 // | 33 // |
| 34 // This implementation uses two vectors instead of linked list, and | 34 // This implementation uses two vectors instead of linked list, and |
| 35 // also compresses regions when possible. | 35 // also compresses regions when possible. |
| 36 | 36 |
| 37 namespace WebCore { | 37 namespace WebCore { |
| 38 | 38 |
| 39 Region::Region() | 39 Region::Region() |
| 40 { | 40 { |
| 41 } | 41 } |
| 42 | 42 |
| 43 Region::Region(const IntRect& rect) | 43 Region::Region(const IntRect& rect) |
| 44 : m_bounds(rect) | 44 : m_bounds(rect) |
| 45 , m_shape(rect) | 45 , m_shape(rect) |
| 46 { | 46 { |
| 47 } | 47 } |
| 48 | 48 |
| 49 Vector<IntRect> Region::rects() const | 49 Vector<IntRect> Region::rects() const |
| 50 { | 50 { |
| 51 Vector<IntRect> rects; | 51 Vector<IntRect> rects; |
| 52 | 52 |
| 53 for (Shape::SpanIterator span = m_shape.spans_begin(), end = m_shape.spans_e
nd(); span != end && span + 1 != end; ++span) { | 53 for (Shape::SpanIterator span = m_shape.spansBegin(), end = m_shape.spansEnd
(); span != end && span + 1 != end; ++span) { |
| 54 int y = span->y; | 54 int y = span->y; |
| 55 int height = (span + 1)->y - y; | 55 int height = (span + 1)->y - y; |
| 56 | 56 |
| 57 for (Shape::SegmentIterator segment = m_shape.segments_begin(span), end
= m_shape.segments_end(span); segment != end && segment + 1 != end; segment += 2
) { | 57 for (Shape::SegmentIterator segment = m_shape.segmentsBegin(span), end =
m_shape.segmentsEnd(span); segment != end && segment + 1 != end; segment += 2)
{ |
| 58 int x = *segment; | 58 int x = *segment; |
| 59 int width = *(segment + 1) - x; | 59 int width = *(segment + 1) - x; |
| 60 | 60 |
| 61 rects.append(IntRect(x, y, width, height)); | 61 rects.append(IntRect(x, y, width, height)); |
| 62 } | 62 } |
| 63 } | 63 } |
| 64 | 64 |
| 65 return rects; | 65 return rects; |
| 66 } | 66 } |
| 67 | 67 |
| 68 bool Region::contains(const Region& region) const | 68 bool Region::contains(const Region& region) const |
| 69 { | 69 { |
| 70 if (!m_bounds.contains(region.m_bounds)) | 70 if (!m_bounds.contains(region.m_bounds)) |
| 71 return false; | 71 return false; |
| 72 | 72 |
| 73 return Shape::compareShapes<Shape::CompareContainsOperation>(m_shape, region
.m_shape); | 73 return Shape::compareShapes<Shape::CompareContainsOperation>(m_shape, region
.m_shape); |
| 74 } | 74 } |
| 75 | 75 |
| 76 bool Region::contains(const IntPoint& point) const | 76 bool Region::contains(const IntPoint& point) const |
| 77 { | 77 { |
| 78 if (!m_bounds.contains(point)) | 78 if (!m_bounds.contains(point)) |
| 79 return false; | 79 return false; |
| 80 | 80 |
| 81 for (Shape::SpanIterator span = m_shape.spans_begin(), end = m_shape.spans_e
nd(); span != end && span + 1 != end; ++span) { | 81 for (Shape::SpanIterator span = m_shape.spansBegin(), end = m_shape.spansEnd
(); span != end && span + 1 != end; ++span) { |
| 82 int y = span->y; | 82 int y = span->y; |
| 83 int maxY = (span + 1)->y; | 83 int maxY = (span + 1)->y; |
| 84 | 84 |
| 85 if (y > point.y()) | 85 if (y > point.y()) |
| 86 break; | 86 break; |
| 87 if (maxY <= point.y()) | 87 if (maxY <= point.y()) |
| 88 continue; | 88 continue; |
| 89 | 89 |
| 90 for (Shape::SegmentIterator segment = m_shape.segments_begin(span), end
= m_shape.segments_end(span); segment != end && segment + 1 != end; segment += 2
) { | 90 for (Shape::SegmentIterator segment = m_shape.segmentsBegin(span), end =
m_shape.segmentsEnd(span); segment != end && segment + 1 != end; segment += 2)
{ |
| 91 int x = *segment; | 91 int x = *segment; |
| 92 int maxX = *(segment + 1); | 92 int maxX = *(segment + 1); |
| 93 | 93 |
| 94 if (x > point.x()) | 94 if (x > point.x()) |
| 95 break; | 95 break; |
| 96 if (maxX > point.x()) | 96 if (maxX > point.x()) |
| 97 return true; | 97 return true; |
| 98 } | 98 } |
| 99 } | 99 } |
| 100 | 100 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 121 } | 121 } |
| 122 | 122 |
| 123 return totalArea; | 123 return totalArea; |
| 124 } | 124 } |
| 125 | 125 |
| 126 template<typename CompareOperation> | 126 template<typename CompareOperation> |
| 127 bool Region::Shape::compareShapes(const Shape& aShape, const Shape& bShape) | 127 bool Region::Shape::compareShapes(const Shape& aShape, const Shape& bShape) |
| 128 { | 128 { |
| 129 bool result = CompareOperation::defaultResult; | 129 bool result = CompareOperation::defaultResult; |
| 130 | 130 |
| 131 Shape::SpanIterator aSpan = aShape.spans_begin(); | 131 Shape::SpanIterator aSpan = aShape.spansBegin(); |
| 132 Shape::SpanIterator aSpanEnd = aShape.spans_end(); | 132 Shape::SpanIterator aSpanEnd = aShape.spansEnd(); |
| 133 Shape::SpanIterator bSpan = bShape.spans_begin(); | 133 Shape::SpanIterator bSpan = bShape.spansBegin(); |
| 134 Shape::SpanIterator bSpanEnd = bShape.spans_end(); | 134 Shape::SpanIterator bSpanEnd = bShape.spansEnd(); |
| 135 | 135 |
| 136 bool aHadSegmentInPreviousSpan = false; | 136 bool aHadSegmentInPreviousSpan = false; |
| 137 bool bHadSegmentInPreviousSpan = false; | 137 bool bHadSegmentInPreviousSpan = false; |
| 138 while (aSpan != aSpanEnd && aSpan + 1 != aSpanEnd && bSpan != bSpanEnd && bS
pan + 1 != bSpanEnd) { | 138 while (aSpan != aSpanEnd && aSpan + 1 != aSpanEnd && bSpan != bSpanEnd && bS
pan + 1 != bSpanEnd) { |
| 139 int aY = aSpan->y; | 139 int aY = aSpan->y; |
| 140 int aMaxY = (aSpan + 1)->y; | 140 int aMaxY = (aSpan + 1)->y; |
| 141 int bY = bSpan->y; | 141 int bY = bSpan->y; |
| 142 int bMaxY = (bSpan + 1)->y; | 142 int bMaxY = (bSpan + 1)->y; |
| 143 | 143 |
| 144 Shape::SegmentIterator aSegment = aShape.segments_begin(aSpan); | 144 Shape::SegmentIterator aSegment = aShape.segmentsBegin(aSpan); |
| 145 Shape::SegmentIterator aSegmentEnd = aShape.segments_end(aSpan); | 145 Shape::SegmentIterator aSegmentEnd = aShape.segmentsEnd(aSpan); |
| 146 Shape::SegmentIterator bSegment = bShape.segments_begin(bSpan); | 146 Shape::SegmentIterator bSegment = bShape.segmentsBegin(bSpan); |
| 147 Shape::SegmentIterator bSegmentEnd = bShape.segments_end(bSpan); | 147 Shape::SegmentIterator bSegmentEnd = bShape.segmentsEnd(bSpan); |
| 148 | 148 |
| 149 // Look for a non-overlapping part of the spans. If B had a segment in i
ts previous span, then we already tested A against B within that span. | 149 // Look for a non-overlapping part of the spans. If B had a segment in i
ts previous span, then we already tested A against B within that span. |
| 150 bool aHasSegmentInSpan = aSegment != aSegmentEnd; | 150 bool aHasSegmentInSpan = aSegment != aSegmentEnd; |
| 151 bool bHasSegmentInSpan = bSegment != bSegmentEnd; | 151 bool bHasSegmentInSpan = bSegment != bSegmentEnd; |
| 152 if (aY < bY && !bHadSegmentInPreviousSpan && aHasSegmentInSpan && Compar
eOperation::aOutsideB(result)) | 152 if (aY < bY && !bHadSegmentInPreviousSpan && aHasSegmentInSpan && Compar
eOperation::aOutsideB(result)) |
| 153 return result; | 153 return result; |
| 154 if (bY < aY && !aHadSegmentInPreviousSpan && bHasSegmentInSpan && Compar
eOperation::bOutsideA(result)) | 154 if (bY < aY && !aHadSegmentInPreviousSpan && bHasSegmentInSpan && Compar
eOperation::bOutsideA(result)) |
| 155 return result; | 155 return result; |
| 156 | 156 |
| 157 aHadSegmentInPreviousSpan = aHasSegmentInSpan; | 157 aHadSegmentInPreviousSpan = aHasSegmentInSpan; |
| 158 bHadSegmentInPreviousSpan = bHasSegmentInSpan; | 158 bHadSegmentInPreviousSpan = bHasSegmentInSpan; |
| 159 | 159 |
| 160 bool spansOverlap = bMaxY > aY && bY < aMaxY; | 160 bool spansOverlap = bMaxY > aY && bY < aMaxY; |
| 161 if (spansOverlap) { | 161 if (spansOverlap) { |
| 162 while (aSegment != aSegmentEnd && bSegment != bSegmentEnd) { | 162 while (aSegment != aSegmentEnd && bSegment != bSegmentEnd) { |
| 163 int aX = *aSegment; | 163 int aX = *aSegment; |
| 164 int aMaxX = *(aSegment + 1); | 164 int aMaxX = *(aSegment + 1); |
| 165 int bX = *bSegment; | 165 int bX = *bSegment; |
| 166 int bMaxX = *(bSegment + 1); | 166 int bMaxX = *(bSegment + 1); |
| 167 | 167 |
| 168 bool segmentsOverlap = bMaxX > aX && bX < aMaxX; | 168 bool segmentsOverlap = bMaxX > aX && bX < aMaxX; |
| 169 if (segmentsOverlap && CompareOperation::aOverlapsB(result)) | 169 if (segmentsOverlap && CompareOperation::aOverlapsB(result)) |
| 170 return result; | 170 return result; |
| 171 if (aX < bX && CompareOperation::aOutsideB(result)) | 171 if (aX < bX && CompareOperation::aOutsideB(result)) |
| 172 return result; | 172 return result; |
| 173 if (bX < aX && CompareOperation::bOutsideA(result)) | 173 if (bX < aX && CompareOperation::bOutsideA(result)) |
| 174 return result; | 174 return result; |
| 175 | 175 |
| 176 if (aMaxX < bMaxX) | 176 if (aMaxX < bMaxX) { |
| 177 aSegment += 2; | 177 aSegment += 2; |
| 178 else if (bMaxX < aMaxX) | 178 } else if (bMaxX < aMaxX) { |
| 179 bSegment += 2; | 179 bSegment += 2; |
| 180 else { | 180 } else { |
| 181 aSegment += 2; | 181 aSegment += 2; |
| 182 bSegment += 2; | 182 bSegment += 2; |
| 183 } | 183 } |
| 184 } | 184 } |
| 185 | 185 |
| 186 if (aSegment != aSegmentEnd && CompareOperation::aOutsideB(result)) | 186 if (aSegment != aSegmentEnd && CompareOperation::aOutsideB(result)) |
| 187 return result; | 187 return result; |
| 188 if (bSegment != bSegmentEnd && CompareOperation::bOutsideA(result)) | 188 if (bSegment != bSegmentEnd && CompareOperation::bOutsideA(result)) |
| 189 return result; | 189 return result; |
| 190 } | 190 } |
| 191 | 191 |
| 192 if (aMaxY < bMaxY) | 192 if (aMaxY < bMaxY) { |
| 193 aSpan += 1; | 193 aSpan += 1; |
| 194 else if (bMaxY < aMaxY) | 194 } else if (bMaxY < aMaxY) { |
| 195 bSpan += 1; | 195 bSpan += 1; |
| 196 else { | 196 } else { |
| 197 aSpan += 1; | 197 aSpan += 1; |
| 198 bSpan += 1; | 198 bSpan += 1; |
| 199 } | 199 } |
| 200 } | 200 } |
| 201 | 201 |
| 202 if (aSpan != aSpanEnd && aSpan + 1 != aSpanEnd && CompareOperation::aOutside
B(result)) | 202 if (aSpan != aSpanEnd && aSpan + 1 != aSpanEnd && CompareOperation::aOutside
B(result)) |
| 203 return result; | 203 return result; |
| 204 if (bSpan != bSpanEnd && bSpan + 1 != bSpanEnd && CompareOperation::bOutside
A(result)) | 204 if (bSpan != bSpanEnd && bSpan + 1 != bSpanEnd && CompareOperation::bOutside
A(result)) |
| 205 return result; | 205 return result; |
| 206 | 206 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 if (canCoalesce(begin, end)) | 263 if (canCoalesce(begin, end)) |
| 264 return; | 264 return; |
| 265 | 265 |
| 266 appendSpan(y); | 266 appendSpan(y); |
| 267 m_segments.appendRange(begin, end); | 267 m_segments.appendRange(begin, end); |
| 268 } | 268 } |
| 269 | 269 |
| 270 void Region::Shape::appendSpans(const Shape& shape, SpanIterator begin, SpanIter
ator end) | 270 void Region::Shape::appendSpans(const Shape& shape, SpanIterator begin, SpanIter
ator end) |
| 271 { | 271 { |
| 272 for (SpanIterator it = begin; it != end; ++it) | 272 for (SpanIterator it = begin; it != end; ++it) |
| 273 appendSpan(it->y, shape.segments_begin(it), shape.segments_end(it)); | 273 appendSpan(it->y, shape.segmentsBegin(it), shape.segmentsEnd(it)); |
| 274 } | 274 } |
| 275 | 275 |
| 276 void Region::Shape::appendSegment(int x) | 276 void Region::Shape::appendSegment(int x) |
| 277 { | 277 { |
| 278 m_segments.append(x); | 278 m_segments.append(x); |
| 279 } | 279 } |
| 280 | 280 |
| 281 Region::Shape::SpanIterator Region::Shape::spans_begin() const | 281 Region::Shape::SpanIterator Region::Shape::spansBegin() const |
| 282 { | 282 { |
| 283 return m_spans.data(); | 283 return m_spans.data(); |
| 284 } | 284 } |
| 285 | 285 |
| 286 Region::Shape::SpanIterator Region::Shape::spans_end() const | 286 Region::Shape::SpanIterator Region::Shape::spansEnd() const |
| 287 { | 287 { |
| 288 return m_spans.data() + m_spans.size(); | 288 return m_spans.data() + m_spans.size(); |
| 289 } | 289 } |
| 290 | 290 |
| 291 Region::Shape::SegmentIterator Region::Shape::segments_begin(SpanIterator it) co
nst | 291 Region::Shape::SegmentIterator Region::Shape::segmentsBegin(SpanIterator it) con
st |
| 292 { | 292 { |
| 293 ASSERT(it >= m_spans.data()); | 293 ASSERT(it >= m_spans.data()); |
| 294 ASSERT(it < m_spans.data() + m_spans.size()); | 294 ASSERT(it < m_spans.data() + m_spans.size()); |
| 295 | 295 |
| 296 // Check if this span has any segments. | 296 // Check if this span has any segments. |
| 297 if (it->segmentIndex == m_segments.size()) | 297 if (it->segmentIndex == m_segments.size()) |
| 298 return 0; | 298 return 0; |
| 299 | 299 |
| 300 return &m_segments[it->segmentIndex]; | 300 return &m_segments[it->segmentIndex]; |
| 301 } | 301 } |
| 302 | 302 |
| 303 Region::Shape::SegmentIterator Region::Shape::segments_end(SpanIterator it) cons
t | 303 Region::Shape::SegmentIterator Region::Shape::segmentsEnd(SpanIterator it) const |
| 304 { | 304 { |
| 305 ASSERT(it >= m_spans.data()); | 305 ASSERT(it >= m_spans.data()); |
| 306 ASSERT(it < m_spans.data() + m_spans.size()); | 306 ASSERT(it < m_spans.data() + m_spans.size()); |
| 307 | 307 |
| 308 // Check if this span has any segments. | 308 // Check if this span has any segments. |
| 309 if (it->segmentIndex == m_segments.size()) | 309 if (it->segmentIndex == m_segments.size()) |
| 310 return 0; | 310 return 0; |
| 311 | 311 |
| 312 ASSERT(it + 1 < m_spans.data() + m_spans.size()); | 312 ASSERT(it + 1 < m_spans.data() + m_spans.size()); |
| 313 size_t segmentIndex = (it + 1)->segmentIndex; | 313 size_t segmentIndex = (it + 1)->segmentIndex; |
| 314 | 314 |
| 315 ASSERT_WITH_SECURITY_IMPLICATION(segmentIndex <= m_segments.size()); | 315 ASSERT_WITH_SECURITY_IMPLICATION(segmentIndex <= m_segments.size()); |
| 316 return m_segments.data() + segmentIndex; | 316 return m_segments.data() + segmentIndex; |
| 317 } | 317 } |
| 318 | 318 |
| 319 #ifndef NDEBUG | 319 #ifndef NDEBUG |
| 320 void Region::Shape::dump() const | 320 void Region::Shape::dump() const |
| 321 { | 321 { |
| 322 for (Shape::SpanIterator span = spans_begin(), end = spans_end(); span != en
d; ++span) { | 322 for (Shape::SpanIterator span = spansBegin(), end = spansEnd(); span != end;
++span) { |
| 323 printf("%6d: (", span->y); | 323 printf("%6d: (", span->y); |
| 324 | 324 |
| 325 for (Shape::SegmentIterator segment = segments_begin(span), end = segmen
ts_end(span); segment != end; ++segment) | 325 for (Shape::SegmentIterator segment = segmentsBegin(span), end = segment
sEnd(span); segment != end; ++segment) |
| 326 printf("%d ", *segment); | 326 printf("%d ", *segment); |
| 327 printf(")\n"); | 327 printf(")\n"); |
| 328 } | 328 } |
| 329 | 329 |
| 330 printf("\n"); | 330 printf("\n"); |
| 331 } | 331 } |
| 332 #endif | 332 #endif |
| 333 | 333 |
| 334 IntRect Region::Shape::bounds() const | 334 IntRect Region::Shape::bounds() const |
| 335 { | 335 { |
| 336 if (isEmpty()) | 336 if (isEmpty()) |
| 337 return IntRect(); | 337 return IntRect(); |
| 338 | 338 |
| 339 SpanIterator span = spans_begin(); | 339 SpanIterator span = spansBegin(); |
| 340 int minY = span->y; | 340 int minY = span->y; |
| 341 | 341 |
| 342 SpanIterator lastSpan = spans_end() - 1; | 342 SpanIterator lastSpan = spansEnd() - 1; |
| 343 int maxY = lastSpan->y; | 343 int maxY = lastSpan->y; |
| 344 | 344 |
| 345 int minX = std::numeric_limits<int>::max(); | 345 int minX = std::numeric_limits<int>::max(); |
| 346 int maxX = std::numeric_limits<int>::min(); | 346 int maxX = std::numeric_limits<int>::min(); |
| 347 | 347 |
| 348 while (span != lastSpan) { | 348 while (span != lastSpan) { |
| 349 SegmentIterator firstSegment = segments_begin(span); | 349 SegmentIterator firstSegment = segmentsBegin(span); |
| 350 SegmentIterator lastSegment = segments_end(span) - 1; | 350 SegmentIterator lastSegment = segmentsEnd(span) - 1; |
| 351 | 351 |
| 352 if (firstSegment && lastSegment) { | 352 if (firstSegment && lastSegment) { |
| 353 ASSERT(firstSegment != lastSegment); | 353 ASSERT(firstSegment != lastSegment); |
| 354 | 354 |
| 355 if (*firstSegment < minX) | 355 if (*firstSegment < minX) |
| 356 minX = *firstSegment; | 356 minX = *firstSegment; |
| 357 | 357 |
| 358 if (*lastSegment > maxX) | 358 if (*lastSegment > maxX) |
| 359 maxX = *lastSegment; | 359 maxX = *lastSegment; |
| 360 } | 360 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 390 template<typename Operation> | 390 template<typename Operation> |
| 391 Region::Shape Region::Shape::shapeOperation(const Shape& shape1, const Shape& sh
ape2) | 391 Region::Shape Region::Shape::shapeOperation(const Shape& shape1, const Shape& sh
ape2) |
| 392 { | 392 { |
| 393 COMPILE_ASSERT(!(!Operation::shouldAddRemainingSegmentsFromSpan1 && Operatio
n::shouldAddRemainingSegmentsFromSpan2), invalid_segment_combination); | 393 COMPILE_ASSERT(!(!Operation::shouldAddRemainingSegmentsFromSpan1 && Operatio
n::shouldAddRemainingSegmentsFromSpan2), invalid_segment_combination); |
| 394 COMPILE_ASSERT(!(!Operation::shouldAddRemainingSpansFromShape1 && Operation:
:shouldAddRemainingSpansFromShape2), invalid_span_combination); | 394 COMPILE_ASSERT(!(!Operation::shouldAddRemainingSpansFromShape1 && Operation:
:shouldAddRemainingSpansFromShape2), invalid_span_combination); |
| 395 | 395 |
| 396 Shape result; | 396 Shape result; |
| 397 if (Operation::trySimpleOperation(shape1, shape2, result)) | 397 if (Operation::trySimpleOperation(shape1, shape2, result)) |
| 398 return result; | 398 return result; |
| 399 | 399 |
| 400 SpanIterator spans1 = shape1.spans_begin(); | 400 SpanIterator spans1 = shape1.spansBegin(); |
| 401 SpanIterator spans1End = shape1.spans_end(); | 401 SpanIterator spans1End = shape1.spansEnd(); |
| 402 | 402 |
| 403 SpanIterator spans2 = shape2.spans_begin(); | 403 SpanIterator spans2 = shape2.spansBegin(); |
| 404 SpanIterator spans2End = shape2.spans_end(); | 404 SpanIterator spans2End = shape2.spansEnd(); |
| 405 | 405 |
| 406 SegmentIterator segments1 = 0; | 406 SegmentIterator segments1 = 0; |
| 407 SegmentIterator segments1End = 0; | 407 SegmentIterator segments1End = 0; |
| 408 | 408 |
| 409 SegmentIterator segments2 = 0; | 409 SegmentIterator segments2 = 0; |
| 410 SegmentIterator segments2End = 0; | 410 SegmentIterator segments2End = 0; |
| 411 | 411 |
| 412 // Iterate over all spans. | 412 // Iterate over all spans. |
| 413 while (spans1 != spans1End && spans2 != spans2End) { | 413 while (spans1 != spans1End && spans2 != spans2End) { |
| 414 int y = 0; | 414 int y = 0; |
| 415 int test = spans1->y - spans2->y; | 415 int test = spans1->y - spans2->y; |
| 416 | 416 |
| 417 if (test <= 0) { | 417 if (test <= 0) { |
| 418 y = spans1->y; | 418 y = spans1->y; |
| 419 | 419 |
| 420 segments1 = shape1.segments_begin(spans1); | 420 segments1 = shape1.segmentsBegin(spans1); |
| 421 segments1End = shape1.segments_end(spans1); | 421 segments1End = shape1.segmentsEnd(spans1); |
| 422 ++spans1; | 422 ++spans1; |
| 423 } | 423 } |
| 424 if (test >= 0) { | 424 if (test >= 0) { |
| 425 y = spans2->y; | 425 y = spans2->y; |
| 426 | 426 |
| 427 segments2 = shape2.segments_begin(spans2); | 427 segments2 = shape2.segmentsBegin(spans2); |
| 428 segments2End = shape2.segments_end(spans2); | 428 segments2End = shape2.segmentsEnd(spans2); |
| 429 ++spans2; | 429 ++spans2; |
| 430 } | 430 } |
| 431 | 431 |
| 432 int flag = 0; | 432 int flag = 0; |
| 433 int oldFlag = 0; | 433 int oldFlag = 0; |
| 434 | 434 |
| 435 SegmentIterator s1 = segments1; | 435 SegmentIterator s1 = segments1; |
| 436 SegmentIterator s2 = segments2; | 436 SegmentIterator s2 = segments2; |
| 437 | 437 |
| 438 Vector<int, 32> segments; | 438 Vector<int, 32> segments; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 }; | 537 }; |
| 538 | 538 |
| 539 Region::Shape Region::Shape::subtractShapes(const Shape& shape1, const Shape& sh
ape2) | 539 Region::Shape Region::Shape::subtractShapes(const Shape& shape1, const Shape& sh
ape2) |
| 540 { | 540 { |
| 541 return shapeOperation<SubtractOperation>(shape1, shape2); | 541 return shapeOperation<SubtractOperation>(shape1, shape2); |
| 542 } | 542 } |
| 543 | 543 |
| 544 #ifndef NDEBUG | 544 #ifndef NDEBUG |
| 545 void Region::dump() const | 545 void Region::dump() const |
| 546 { | 546 { |
| 547 printf("Bounds: (%d, %d, %d, %d)\n", | 547 printf("Bounds: (%d, %d, %d, %d)\n", m_bounds.x(), m_bounds.y(), m_bounds.wi
dth(), m_bounds.height()); |
| 548 m_bounds.x(), m_bounds.y(), m_bounds.width(), m_bounds.height()); | |
| 549 m_shape.dump(); | 548 m_shape.dump(); |
| 550 } | 549 } |
| 551 #endif | 550 #endif |
| 552 | 551 |
| 553 void Region::intersect(const Region& region) | 552 void Region::intersect(const Region& region) |
| 554 { | 553 { |
| 555 if (m_bounds.isEmpty()) | 554 if (m_bounds.isEmpty()) |
| 556 return; | 555 return; |
| 557 if (!m_bounds.intersects(region.m_bounds)) { | 556 if (!m_bounds.intersects(region.m_bounds)) { |
| 558 m_shape = Shape(); | 557 m_shape = Shape(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 m_bounds = m_shape.bounds(); | 601 m_bounds = m_shape.bounds(); |
| 603 } | 602 } |
| 604 | 603 |
| 605 void Region::translate(const IntSize& offset) | 604 void Region::translate(const IntSize& offset) |
| 606 { | 605 { |
| 607 m_bounds.move(offset); | 606 m_bounds.move(offset); |
| 608 m_shape.translate(offset); | 607 m_shape.translate(offset); |
| 609 } | 608 } |
| 610 | 609 |
| 611 } // namespace WebCore | 610 } // namespace WebCore |
| OLD | NEW |