Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* |
michael@0 | 2 | * Copyright 2013 Google Inc. |
michael@0 | 3 | * |
michael@0 | 4 | * Use of this source code is governed by a BSD-style license that can be |
michael@0 | 5 | * found in the LICENSE file. |
michael@0 | 6 | */ |
michael@0 | 7 | #include "SkIntersections.h" |
michael@0 | 8 | #include "SkOpContour.h" |
michael@0 | 9 | #include "SkPathWriter.h" |
michael@0 | 10 | #include "SkTSort.h" |
michael@0 | 11 | |
michael@0 | 12 | bool SkOpContour::addCoincident(int index, SkOpContour* other, int otherIndex, |
michael@0 | 13 | const SkIntersections& ts, bool swap) { |
michael@0 | 14 | SkPoint pt0 = ts.pt(0).asSkPoint(); |
michael@0 | 15 | SkPoint pt1 = ts.pt(1).asSkPoint(); |
michael@0 | 16 | if (pt0 == pt1) { |
michael@0 | 17 | // FIXME: one could imagine a case where it would be incorrect to ignore this |
michael@0 | 18 | // suppose two self-intersecting cubics overlap to be coincident -- |
michael@0 | 19 | // this needs to check that by some measure the t values are far enough apart |
michael@0 | 20 | // or needs to check to see if the self-intersection bit was set on the cubic segment |
michael@0 | 21 | return false; |
michael@0 | 22 | } |
michael@0 | 23 | SkCoincidence& coincidence = fCoincidences.push_back(); |
michael@0 | 24 | coincidence.fOther = other; |
michael@0 | 25 | coincidence.fSegments[0] = index; |
michael@0 | 26 | coincidence.fSegments[1] = otherIndex; |
michael@0 | 27 | coincidence.fTs[swap][0] = ts[0][0]; |
michael@0 | 28 | coincidence.fTs[swap][1] = ts[0][1]; |
michael@0 | 29 | coincidence.fTs[!swap][0] = ts[1][0]; |
michael@0 | 30 | coincidence.fTs[!swap][1] = ts[1][1]; |
michael@0 | 31 | coincidence.fPts[0] = pt0; |
michael@0 | 32 | coincidence.fPts[1] = pt1; |
michael@0 | 33 | return true; |
michael@0 | 34 | } |
michael@0 | 35 | |
michael@0 | 36 | SkOpSegment* SkOpContour::nonVerticalSegment(int* start, int* end) { |
michael@0 | 37 | int segmentCount = fSortedSegments.count(); |
michael@0 | 38 | SkASSERT(segmentCount > 0); |
michael@0 | 39 | for (int sortedIndex = fFirstSorted; sortedIndex < segmentCount; ++sortedIndex) { |
michael@0 | 40 | SkOpSegment* testSegment = fSortedSegments[sortedIndex]; |
michael@0 | 41 | if (testSegment->done()) { |
michael@0 | 42 | continue; |
michael@0 | 43 | } |
michael@0 | 44 | *start = *end = 0; |
michael@0 | 45 | while (testSegment->nextCandidate(start, end)) { |
michael@0 | 46 | if (!testSegment->isVertical(*start, *end)) { |
michael@0 | 47 | return testSegment; |
michael@0 | 48 | } |
michael@0 | 49 | } |
michael@0 | 50 | } |
michael@0 | 51 | return NULL; |
michael@0 | 52 | } |
michael@0 | 53 | |
michael@0 | 54 | // first pass, add missing T values |
michael@0 | 55 | // second pass, determine winding values of overlaps |
michael@0 | 56 | void SkOpContour::addCoincidentPoints() { |
michael@0 | 57 | int count = fCoincidences.count(); |
michael@0 | 58 | for (int index = 0; index < count; ++index) { |
michael@0 | 59 | SkCoincidence& coincidence = fCoincidences[index]; |
michael@0 | 60 | int thisIndex = coincidence.fSegments[0]; |
michael@0 | 61 | SkOpSegment& thisOne = fSegments[thisIndex]; |
michael@0 | 62 | SkOpContour* otherContour = coincidence.fOther; |
michael@0 | 63 | int otherIndex = coincidence.fSegments[1]; |
michael@0 | 64 | SkOpSegment& other = otherContour->fSegments[otherIndex]; |
michael@0 | 65 | if ((thisOne.done() || other.done()) && thisOne.complete() && other.complete()) { |
michael@0 | 66 | // OPTIMIZATION: remove from array |
michael@0 | 67 | continue; |
michael@0 | 68 | } |
michael@0 | 69 | #if DEBUG_CONCIDENT |
michael@0 | 70 | thisOne.debugShowTs("-"); |
michael@0 | 71 | other.debugShowTs("o"); |
michael@0 | 72 | #endif |
michael@0 | 73 | double startT = coincidence.fTs[0][0]; |
michael@0 | 74 | double endT = coincidence.fTs[0][1]; |
michael@0 | 75 | bool startSwapped, oStartSwapped, cancelers; |
michael@0 | 76 | if ((cancelers = startSwapped = startT > endT)) { |
michael@0 | 77 | SkTSwap(startT, endT); |
michael@0 | 78 | } |
michael@0 | 79 | if (startT == endT) { // if one is very large the smaller may have collapsed to nothing |
michael@0 | 80 | if (endT <= 1 - FLT_EPSILON) { |
michael@0 | 81 | endT += FLT_EPSILON; |
michael@0 | 82 | SkASSERT(endT <= 1); |
michael@0 | 83 | } else { |
michael@0 | 84 | startT -= FLT_EPSILON; |
michael@0 | 85 | SkASSERT(startT >= 0); |
michael@0 | 86 | } |
michael@0 | 87 | } |
michael@0 | 88 | SkASSERT(!approximately_negative(endT - startT)); |
michael@0 | 89 | double oStartT = coincidence.fTs[1][0]; |
michael@0 | 90 | double oEndT = coincidence.fTs[1][1]; |
michael@0 | 91 | if ((oStartSwapped = oStartT > oEndT)) { |
michael@0 | 92 | SkTSwap(oStartT, oEndT); |
michael@0 | 93 | cancelers ^= true; |
michael@0 | 94 | } |
michael@0 | 95 | SkASSERT(!approximately_negative(oEndT - oStartT)); |
michael@0 | 96 | if (cancelers) { |
michael@0 | 97 | // make sure startT and endT have t entries |
michael@0 | 98 | const SkPoint& startPt = coincidence.fPts[startSwapped]; |
michael@0 | 99 | if (startT > 0 || oEndT < 1 |
michael@0 | 100 | || thisOne.isMissing(startT, startPt) || other.isMissing(oEndT, startPt)) { |
michael@0 | 101 | thisOne.addTPair(startT, &other, oEndT, true, startPt); |
michael@0 | 102 | } |
michael@0 | 103 | const SkPoint& oStartPt = coincidence.fPts[oStartSwapped]; |
michael@0 | 104 | if (oStartT > 0 || endT < 1 |
michael@0 | 105 | || thisOne.isMissing(endT, oStartPt) || other.isMissing(oStartT, oStartPt)) { |
michael@0 | 106 | other.addTPair(oStartT, &thisOne, endT, true, oStartPt); |
michael@0 | 107 | } |
michael@0 | 108 | } else { |
michael@0 | 109 | const SkPoint& startPt = coincidence.fPts[startSwapped]; |
michael@0 | 110 | if (startT > 0 || oStartT > 0 |
michael@0 | 111 | || thisOne.isMissing(startT, startPt) || other.isMissing(oStartT, startPt)) { |
michael@0 | 112 | thisOne.addTPair(startT, &other, oStartT, true, startPt); |
michael@0 | 113 | } |
michael@0 | 114 | const SkPoint& oEndPt = coincidence.fPts[!oStartSwapped]; |
michael@0 | 115 | if (endT < 1 || oEndT < 1 |
michael@0 | 116 | || thisOne.isMissing(endT, oEndPt) || other.isMissing(oEndT, oEndPt)) { |
michael@0 | 117 | other.addTPair(oEndT, &thisOne, endT, true, oEndPt); |
michael@0 | 118 | } |
michael@0 | 119 | } |
michael@0 | 120 | #if DEBUG_CONCIDENT |
michael@0 | 121 | thisOne.debugShowTs("+"); |
michael@0 | 122 | other.debugShowTs("o"); |
michael@0 | 123 | #endif |
michael@0 | 124 | } |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | bool SkOpContour::addPartialCoincident(int index, SkOpContour* other, int otherIndex, |
michael@0 | 128 | const SkIntersections& ts, int ptIndex, bool swap) { |
michael@0 | 129 | SkPoint pt0 = ts.pt(ptIndex).asSkPoint(); |
michael@0 | 130 | SkPoint pt1 = ts.pt(ptIndex + 1).asSkPoint(); |
michael@0 | 131 | if (SkDPoint::ApproximatelyEqual(pt0, pt1)) { |
michael@0 | 132 | // FIXME: one could imagine a case where it would be incorrect to ignore this |
michael@0 | 133 | // suppose two self-intersecting cubics overlap to form a partial coincidence -- |
michael@0 | 134 | // although it isn't clear why the regular coincidence could wouldn't pick this up |
michael@0 | 135 | // this is exceptional enough to ignore for now |
michael@0 | 136 | return false; |
michael@0 | 137 | } |
michael@0 | 138 | SkCoincidence& coincidence = fPartialCoincidences.push_back(); |
michael@0 | 139 | coincidence.fOther = other; |
michael@0 | 140 | coincidence.fSegments[0] = index; |
michael@0 | 141 | coincidence.fSegments[1] = otherIndex; |
michael@0 | 142 | coincidence.fTs[swap][0] = ts[0][ptIndex]; |
michael@0 | 143 | coincidence.fTs[swap][1] = ts[0][ptIndex + 1]; |
michael@0 | 144 | coincidence.fTs[!swap][0] = ts[1][ptIndex]; |
michael@0 | 145 | coincidence.fTs[!swap][1] = ts[1][ptIndex + 1]; |
michael@0 | 146 | coincidence.fPts[0] = pt0; |
michael@0 | 147 | coincidence.fPts[1] = pt1; |
michael@0 | 148 | return true; |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | void SkOpContour::calcCoincidentWinding() { |
michael@0 | 152 | int count = fCoincidences.count(); |
michael@0 | 153 | #if DEBUG_CONCIDENT |
michael@0 | 154 | if (count > 0) { |
michael@0 | 155 | SkDebugf("%s count=%d\n", __FUNCTION__, count); |
michael@0 | 156 | } |
michael@0 | 157 | #endif |
michael@0 | 158 | for (int index = 0; index < count; ++index) { |
michael@0 | 159 | SkCoincidence& coincidence = fCoincidences[index]; |
michael@0 | 160 | calcCommonCoincidentWinding(coincidence); |
michael@0 | 161 | } |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | void SkOpContour::calcPartialCoincidentWinding() { |
michael@0 | 165 | int count = fPartialCoincidences.count(); |
michael@0 | 166 | #if DEBUG_CONCIDENT |
michael@0 | 167 | if (count > 0) { |
michael@0 | 168 | SkDebugf("%s count=%d\n", __FUNCTION__, count); |
michael@0 | 169 | } |
michael@0 | 170 | #endif |
michael@0 | 171 | for (int index = 0; index < count; ++index) { |
michael@0 | 172 | SkCoincidence& coincidence = fPartialCoincidences[index]; |
michael@0 | 173 | calcCommonCoincidentWinding(coincidence); |
michael@0 | 174 | } |
michael@0 | 175 | } |
michael@0 | 176 | |
michael@0 | 177 | void SkOpContour::joinCoincidence(const SkTArray<SkCoincidence, true>& coincidences, bool partial) { |
michael@0 | 178 | int count = coincidences.count(); |
michael@0 | 179 | #if DEBUG_CONCIDENT |
michael@0 | 180 | if (count > 0) { |
michael@0 | 181 | SkDebugf("%s count=%d\n", __FUNCTION__, count); |
michael@0 | 182 | } |
michael@0 | 183 | #endif |
michael@0 | 184 | // look for a lineup where the partial implies another adjoining coincidence |
michael@0 | 185 | for (int index = 0; index < count; ++index) { |
michael@0 | 186 | const SkCoincidence& coincidence = coincidences[index]; |
michael@0 | 187 | int thisIndex = coincidence.fSegments[0]; |
michael@0 | 188 | SkOpSegment& thisOne = fSegments[thisIndex]; |
michael@0 | 189 | SkOpContour* otherContour = coincidence.fOther; |
michael@0 | 190 | int otherIndex = coincidence.fSegments[1]; |
michael@0 | 191 | SkOpSegment& other = otherContour->fSegments[otherIndex]; |
michael@0 | 192 | double startT = coincidence.fTs[0][0]; |
michael@0 | 193 | double endT = coincidence.fTs[0][1]; |
michael@0 | 194 | if (startT == endT) { // this can happen in very large compares |
michael@0 | 195 | continue; |
michael@0 | 196 | } |
michael@0 | 197 | double oStartT = coincidence.fTs[1][0]; |
michael@0 | 198 | double oEndT = coincidence.fTs[1][1]; |
michael@0 | 199 | if (oStartT == oEndT) { |
michael@0 | 200 | continue; |
michael@0 | 201 | } |
michael@0 | 202 | bool swapStart = startT > endT; |
michael@0 | 203 | bool swapOther = oStartT > oEndT; |
michael@0 | 204 | if (swapStart) { |
michael@0 | 205 | SkTSwap<double>(startT, endT); |
michael@0 | 206 | SkTSwap<double>(oStartT, oEndT); |
michael@0 | 207 | } |
michael@0 | 208 | bool cancel = swapOther != swapStart; |
michael@0 | 209 | int step = swapStart ? -1 : 1; |
michael@0 | 210 | int oStep = swapOther ? -1 : 1; |
michael@0 | 211 | double oMatchStart = cancel ? oEndT : oStartT; |
michael@0 | 212 | if (partial ? startT != 0 || oMatchStart != 0 : (startT == 0) != (oMatchStart == 0)) { |
michael@0 | 213 | bool added = false; |
michael@0 | 214 | if (oMatchStart != 0) { |
michael@0 | 215 | added = thisOne.joinCoincidence(&other, oMatchStart, oStep, cancel); |
michael@0 | 216 | } |
michael@0 | 217 | if (!cancel && startT != 0 && !added) { |
michael@0 | 218 | (void) other.joinCoincidence(&thisOne, startT, step, cancel); |
michael@0 | 219 | } |
michael@0 | 220 | } |
michael@0 | 221 | double oMatchEnd = cancel ? oStartT : oEndT; |
michael@0 | 222 | if (partial ? endT != 1 || oMatchEnd != 1 : (endT == 1) != (oMatchEnd == 1)) { |
michael@0 | 223 | bool added = false; |
michael@0 | 224 | if (cancel && endT != 1 && !added) { |
michael@0 | 225 | (void) other.joinCoincidence(&thisOne, endT, -step, cancel); |
michael@0 | 226 | } |
michael@0 | 227 | } |
michael@0 | 228 | } |
michael@0 | 229 | } |
michael@0 | 230 | |
michael@0 | 231 | void SkOpContour::calcCommonCoincidentWinding(const SkCoincidence& coincidence) { |
michael@0 | 232 | int thisIndex = coincidence.fSegments[0]; |
michael@0 | 233 | SkOpSegment& thisOne = fSegments[thisIndex]; |
michael@0 | 234 | if (thisOne.done()) { |
michael@0 | 235 | return; |
michael@0 | 236 | } |
michael@0 | 237 | SkOpContour* otherContour = coincidence.fOther; |
michael@0 | 238 | int otherIndex = coincidence.fSegments[1]; |
michael@0 | 239 | SkOpSegment& other = otherContour->fSegments[otherIndex]; |
michael@0 | 240 | if (other.done()) { |
michael@0 | 241 | return; |
michael@0 | 242 | } |
michael@0 | 243 | double startT = coincidence.fTs[0][0]; |
michael@0 | 244 | double endT = coincidence.fTs[0][1]; |
michael@0 | 245 | const SkPoint* startPt = &coincidence.fPts[0]; |
michael@0 | 246 | const SkPoint* endPt = &coincidence.fPts[1]; |
michael@0 | 247 | bool cancelers; |
michael@0 | 248 | if ((cancelers = startT > endT)) { |
michael@0 | 249 | SkTSwap<double>(startT, endT); |
michael@0 | 250 | SkTSwap<const SkPoint*>(startPt, endPt); |
michael@0 | 251 | } |
michael@0 | 252 | if (startT == endT) { // if span is very large, the smaller may have collapsed to nothing |
michael@0 | 253 | if (endT <= 1 - FLT_EPSILON) { |
michael@0 | 254 | endT += FLT_EPSILON; |
michael@0 | 255 | SkASSERT(endT <= 1); |
michael@0 | 256 | } else { |
michael@0 | 257 | startT -= FLT_EPSILON; |
michael@0 | 258 | SkASSERT(startT >= 0); |
michael@0 | 259 | } |
michael@0 | 260 | } |
michael@0 | 261 | SkASSERT(!approximately_negative(endT - startT)); |
michael@0 | 262 | double oStartT = coincidence.fTs[1][0]; |
michael@0 | 263 | double oEndT = coincidence.fTs[1][1]; |
michael@0 | 264 | if (oStartT > oEndT) { |
michael@0 | 265 | SkTSwap<double>(oStartT, oEndT); |
michael@0 | 266 | cancelers ^= true; |
michael@0 | 267 | } |
michael@0 | 268 | SkASSERT(!approximately_negative(oEndT - oStartT)); |
michael@0 | 269 | if (cancelers) { |
michael@0 | 270 | thisOne.addTCancel(*startPt, *endPt, &other); |
michael@0 | 271 | } else { |
michael@0 | 272 | thisOne.addTCoincident(*startPt, *endPt, endT, &other); |
michael@0 | 273 | } |
michael@0 | 274 | #if DEBUG_CONCIDENT |
michael@0 | 275 | thisOne.debugShowTs("p"); |
michael@0 | 276 | other.debugShowTs("o"); |
michael@0 | 277 | #endif |
michael@0 | 278 | } |
michael@0 | 279 | |
michael@0 | 280 | void SkOpContour::sortSegments() { |
michael@0 | 281 | int segmentCount = fSegments.count(); |
michael@0 | 282 | fSortedSegments.push_back_n(segmentCount); |
michael@0 | 283 | for (int test = 0; test < segmentCount; ++test) { |
michael@0 | 284 | fSortedSegments[test] = &fSegments[test]; |
michael@0 | 285 | } |
michael@0 | 286 | SkTQSort<SkOpSegment>(fSortedSegments.begin(), fSortedSegments.end() - 1); |
michael@0 | 287 | fFirstSorted = 0; |
michael@0 | 288 | } |
michael@0 | 289 | |
michael@0 | 290 | void SkOpContour::toPath(SkPathWriter* path) const { |
michael@0 | 291 | int segmentCount = fSegments.count(); |
michael@0 | 292 | const SkPoint& pt = fSegments.front().pts()[0]; |
michael@0 | 293 | path->deferredMove(pt); |
michael@0 | 294 | for (int test = 0; test < segmentCount; ++test) { |
michael@0 | 295 | fSegments[test].addCurveTo(0, 1, path, true); |
michael@0 | 296 | } |
michael@0 | 297 | path->close(); |
michael@0 | 298 | } |
michael@0 | 299 | |
michael@0 | 300 | void SkOpContour::topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, |
michael@0 | 301 | SkOpSegment** topStart) { |
michael@0 | 302 | int segmentCount = fSortedSegments.count(); |
michael@0 | 303 | SkASSERT(segmentCount > 0); |
michael@0 | 304 | int sortedIndex = fFirstSorted; |
michael@0 | 305 | fDone = true; // may be cleared below |
michael@0 | 306 | for ( ; sortedIndex < segmentCount; ++sortedIndex) { |
michael@0 | 307 | SkOpSegment* testSegment = fSortedSegments[sortedIndex]; |
michael@0 | 308 | if (testSegment->done()) { |
michael@0 | 309 | if (sortedIndex == fFirstSorted) { |
michael@0 | 310 | ++fFirstSorted; |
michael@0 | 311 | } |
michael@0 | 312 | continue; |
michael@0 | 313 | } |
michael@0 | 314 | fDone = false; |
michael@0 | 315 | SkPoint testXY = testSegment->activeLeftTop(true, NULL); |
michael@0 | 316 | if (*topStart) { |
michael@0 | 317 | if (testXY.fY < topLeft.fY) { |
michael@0 | 318 | continue; |
michael@0 | 319 | } |
michael@0 | 320 | if (testXY.fY == topLeft.fY && testXY.fX < topLeft.fX) { |
michael@0 | 321 | continue; |
michael@0 | 322 | } |
michael@0 | 323 | if (bestXY->fY < testXY.fY) { |
michael@0 | 324 | continue; |
michael@0 | 325 | } |
michael@0 | 326 | if (bestXY->fY == testXY.fY && bestXY->fX < testXY.fX) { |
michael@0 | 327 | continue; |
michael@0 | 328 | } |
michael@0 | 329 | } |
michael@0 | 330 | *topStart = testSegment; |
michael@0 | 331 | *bestXY = testXY; |
michael@0 | 332 | } |
michael@0 | 333 | } |
michael@0 | 334 | |
michael@0 | 335 | SkOpSegment* SkOpContour::undoneSegment(int* start, int* end) { |
michael@0 | 336 | int segmentCount = fSegments.count(); |
michael@0 | 337 | for (int test = 0; test < segmentCount; ++test) { |
michael@0 | 338 | SkOpSegment* testSegment = &fSegments[test]; |
michael@0 | 339 | if (testSegment->done()) { |
michael@0 | 340 | continue; |
michael@0 | 341 | } |
michael@0 | 342 | testSegment->undoneSpan(start, end); |
michael@0 | 343 | return testSegment; |
michael@0 | 344 | } |
michael@0 | 345 | return NULL; |
michael@0 | 346 | } |
michael@0 | 347 | |
michael@0 | 348 | #if DEBUG_SHOW_WINDING |
michael@0 | 349 | int SkOpContour::debugShowWindingValues(int totalSegments, int ofInterest) { |
michael@0 | 350 | int count = fSegments.count(); |
michael@0 | 351 | int sum = 0; |
michael@0 | 352 | for (int index = 0; index < count; ++index) { |
michael@0 | 353 | sum += fSegments[index].debugShowWindingValues(totalSegments, ofInterest); |
michael@0 | 354 | } |
michael@0 | 355 | // SkDebugf("%s sum=%d\n", __FUNCTION__, sum); |
michael@0 | 356 | return sum; |
michael@0 | 357 | } |
michael@0 | 358 | |
michael@0 | 359 | void SkOpContour::debugShowWindingValues(const SkTArray<SkOpContour*, true>& contourList) { |
michael@0 | 360 | // int ofInterest = 1 << 1 | 1 << 5 | 1 << 9 | 1 << 13; |
michael@0 | 361 | // int ofInterest = 1 << 4 | 1 << 8 | 1 << 12 | 1 << 16; |
michael@0 | 362 | int ofInterest = 1 << 5 | 1 << 8; |
michael@0 | 363 | int total = 0; |
michael@0 | 364 | int index; |
michael@0 | 365 | for (index = 0; index < contourList.count(); ++index) { |
michael@0 | 366 | total += contourList[index]->segments().count(); |
michael@0 | 367 | } |
michael@0 | 368 | int sum = 0; |
michael@0 | 369 | for (index = 0; index < contourList.count(); ++index) { |
michael@0 | 370 | sum += contourList[index]->debugShowWindingValues(total, ofInterest); |
michael@0 | 371 | } |
michael@0 | 372 | // SkDebugf("%s total=%d\n", __FUNCTION__, sum); |
michael@0 | 373 | } |
michael@0 | 374 | #endif |
michael@0 | 375 | |
michael@0 | 376 | void SkOpContour::setBounds() { |
michael@0 | 377 | int count = fSegments.count(); |
michael@0 | 378 | if (count == 0) { |
michael@0 | 379 | SkDebugf("%s empty contour\n", __FUNCTION__); |
michael@0 | 380 | SkASSERT(0); |
michael@0 | 381 | // FIXME: delete empty contour? |
michael@0 | 382 | return; |
michael@0 | 383 | } |
michael@0 | 384 | fBounds = fSegments.front().bounds(); |
michael@0 | 385 | for (int index = 1; index < count; ++index) { |
michael@0 | 386 | fBounds.add(fSegments[index].bounds()); |
michael@0 | 387 | } |
michael@0 | 388 | } |