OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkRegionPriv.h" | 10 #include "SkRegionPriv.h" |
11 #include "SkBlitter.h" | 11 #include "SkBlitter.h" |
12 #include "SkScan.h" | 12 #include "SkScan.h" |
13 #include "SkTDArray.h" | 13 #include "SkTDArray.h" |
14 #include "SkPath.h" | 14 #include "SkPath.h" |
15 | 15 |
16 class SkRgnBuilder : public SkBlitter { | 16 class SkRgnBuilder : public SkBlitter { |
17 public: | 17 public: |
18 virtual ~SkRgnBuilder(); | 18 virtual ~SkRgnBuilder(); |
19 | 19 |
20 // returns true if it could allocate the working storage needed | 20 // returns true if it could allocate the working storage needed |
21 bool init(int maxHeight, int maxTransitions); | 21 bool init(int maxHeight, int maxTransitions, bool pathIsInverse); |
22 | 22 |
23 void done() { | 23 void done() { |
24 if (fCurrScanline != NULL) { | 24 if (fCurrScanline != NULL) { |
25 fCurrScanline->fXCount = (SkRegion::RunType)((int)(fCurrXPtr - fCurr
Scanline->firstX())); | 25 fCurrScanline->fXCount = (SkRegion::RunType)((int)(fCurrXPtr - fCurr
Scanline->firstX())); |
26 if (!this->collapsWithPrev()) { // flush the last line | 26 if (!this->collapsWithPrev()) { // flush the last line |
27 fCurrScanline = fCurrScanline->nextScanline(); | 27 fCurrScanline = fCurrScanline->nextScanline(); |
28 } | 28 } |
29 } | 29 } |
30 } | 30 } |
31 | 31 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 return true; | 95 return true; |
96 } | 96 } |
97 return false; | 97 return false; |
98 } | 98 } |
99 }; | 99 }; |
100 | 100 |
101 SkRgnBuilder::~SkRgnBuilder() { | 101 SkRgnBuilder::~SkRgnBuilder() { |
102 sk_free(fStorage); | 102 sk_free(fStorage); |
103 } | 103 } |
104 | 104 |
105 bool SkRgnBuilder::init(int maxHeight, int maxTransitions) { | 105 bool SkRgnBuilder::init(int maxHeight, int maxTransitions, bool pathIsInverse) { |
106 if ((maxHeight | maxTransitions) < 0) { | 106 if ((maxHeight | maxTransitions) < 0) { |
107 return false; | 107 return false; |
108 } | 108 } |
109 | 109 |
110 Sk64 count, size; | 110 Sk64 count, size; |
111 | 111 |
| 112 if (pathIsInverse) { |
| 113 // allow for additional X transitions to "invert" each scanline |
| 114 // [ L' ... normal transitions ... R' ] |
| 115 // |
| 116 maxTransitions += 2; |
| 117 } |
| 118 |
112 // compute the count with +1 and +3 slop for the working buffer | 119 // compute the count with +1 and +3 slop for the working buffer |
113 count.setMul(maxHeight + 1, 3 + maxTransitions); | 120 count.setMul(maxHeight + 1, 3 + maxTransitions); |
| 121 |
| 122 if (pathIsInverse) { |
| 123 // allow for two "empty" rows for the top and bottom |
| 124 // [ Y, 1, L, R, S] == 5 (*2 for top and bottom) |
| 125 count.add(10); |
| 126 } |
| 127 |
114 if (!count.is32() || count.isNeg()) { | 128 if (!count.is32() || count.isNeg()) { |
115 return false; | 129 return false; |
116 } | 130 } |
117 fStorageCount = count.get32(); | 131 fStorageCount = count.get32(); |
118 | 132 |
119 size.setMul(fStorageCount, sizeof(SkRegion::RunType)); | 133 size.setMul(fStorageCount, sizeof(SkRegion::RunType)); |
120 if (!size.is32() || size.isNeg()) { | 134 if (!size.is32() || size.isNeg()) { |
121 return false; | 135 return false; |
122 } | 136 } |
123 | 137 |
124 fStorage = (SkRegion::RunType*)sk_malloc_flags(size.get32(), 0); | 138 fStorage = (SkRegion::RunType*)sk_malloc_flags(size.get32(), 0); |
125 if (NULL == fStorage) { | 139 if (NULL == fStorage) { |
126 return false; | 140 return false; |
127 } | 141 } |
128 | 142 |
129 fCurrScanline = NULL; // signal empty collection | 143 fCurrScanline = NULL; // signal empty collection |
130 fPrevScanline = NULL; // signal first scanline | 144 fPrevScanline = NULL; // signal first scanline |
131 return true; | 145 return true; |
132 } | 146 } |
133 | 147 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 clipTransitions = clip.count_runtype_values(&clipTop, &clipBot); | 319 clipTransitions = clip.count_runtype_values(&clipTop, &clipBot); |
306 | 320 |
307 int top = SkMax32(pathTop, clipTop); | 321 int top = SkMax32(pathTop, clipTop); |
308 int bot = SkMin32(pathBot, clipBot); | 322 int bot = SkMin32(pathBot, clipBot); |
309 | 323 |
310 if (top >= bot) | 324 if (top >= bot) |
311 return this->setEmpty(); | 325 return this->setEmpty(); |
312 | 326 |
313 SkRgnBuilder builder; | 327 SkRgnBuilder builder; |
314 | 328 |
315 if (!builder.init(bot - top, SkMax32(pathTransitions, clipTransitions))) { | 329 if (!builder.init(bot - top, |
| 330 SkMax32(pathTransitions, clipTransitions), |
| 331 path.isInverseFillType())) { |
316 // can't allocate working space, so return false | 332 // can't allocate working space, so return false |
317 return this->setEmpty(); | 333 return this->setEmpty(); |
318 } | 334 } |
319 | 335 |
320 SkScan::FillPath(path, clip, &builder); | 336 SkScan::FillPath(path, clip, &builder); |
321 builder.done(); | 337 builder.done(); |
322 | 338 |
323 int count = builder.computeRunCount(); | 339 int count = builder.computeRunCount(); |
324 if (count == 0) { | 340 if (count == 0) { |
325 return this->setEmpty(); | 341 return this->setEmpty(); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 #endif | 508 #endif |
493 | 509 |
494 path->incReserve(count << 1); | 510 path->incReserve(count << 1); |
495 do { | 511 do { |
496 SkASSERT(count > 1); | 512 SkASSERT(count > 1); |
497 count -= extract_path(start, stop, path); | 513 count -= extract_path(start, stop, path); |
498 } while (count > 0); | 514 } while (count > 0); |
499 | 515 |
500 return true; | 516 return true; |
501 } | 517 } |
OLD | NEW |