OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkRegionPriv.h" | 8 #include "SkRegionPriv.h" |
9 #include "SkBlitter.h" | 9 #include "SkBlitter.h" |
10 #include "SkScan.h" | 10 #include "SkScan.h" |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 2, // kQuad_VerbB | 261 2, // kQuad_VerbB |
262 2, // kConic_VerbB | 262 2, // kConic_VerbB |
263 3, // kCubic_Verb | 263 3, // kCubic_Verb |
264 0, // kClose_Verb | 264 0, // kClose_Verb |
265 0 // kDone_Verb | 265 0 // kDone_Verb |
266 }; | 266 }; |
267 SkASSERT((unsigned)verb < SK_ARRAY_COUNT(gPathVerbToMaxEdges)); | 267 SkASSERT((unsigned)verb < SK_ARRAY_COUNT(gPathVerbToMaxEdges)); |
268 return gPathVerbToMaxEdges[verb]; | 268 return gPathVerbToMaxEdges[verb]; |
269 } | 269 } |
270 | 270 |
271 | 271 // If returns 0, ignore itop and ibot |
272 static int count_path_runtype_values(const SkPath& path, int* itop, int* ibot) { | 272 static int count_path_runtype_values(const SkPath& path, int* itop, int* ibot) { |
273 SkPath::Iter iter(path, true); | 273 SkPath::Iter iter(path, true); |
274 SkPoint pts[4]; | 274 SkPoint pts[4]; |
275 SkPath::Verb verb; | 275 SkPath::Verb verb; |
276 | 276 |
277 int maxEdges = 0; | 277 int maxEdges = 0; |
278 SkScalar top = SkIntToScalar(SK_MaxS16); | 278 SkScalar top = SkIntToScalar(SK_MaxS16); |
279 SkScalar bot = SkIntToScalar(SK_MinS16); | 279 SkScalar bot = SkIntToScalar(SK_MinS16); |
280 | 280 |
281 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { | 281 while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { |
282 maxEdges += verb_to_max_edges(verb); | 282 maxEdges += verb_to_max_edges(verb); |
283 | 283 |
284 int lastIndex = verb_to_initial_last_index(verb); | 284 int lastIndex = verb_to_initial_last_index(verb); |
285 if (lastIndex > 0) { | 285 if (lastIndex > 0) { |
286 for (int i = 1; i <= lastIndex; i++) { | 286 for (int i = 1; i <= lastIndex; i++) { |
287 if (top > pts[i].fY) { | 287 if (top > pts[i].fY) { |
288 top = pts[i].fY; | 288 top = pts[i].fY; |
289 } else if (bot < pts[i].fY) { | 289 } else if (bot < pts[i].fY) { |
290 bot = pts[i].fY; | 290 bot = pts[i].fY; |
291 } | 291 } |
292 } | 292 } |
293 } else if (SkPath::kMove_Verb == verb) { | 293 } else if (SkPath::kMove_Verb == verb) { |
294 if (top > pts[0].fY) { | 294 if (top > pts[0].fY) { |
295 top = pts[0].fY; | 295 top = pts[0].fY; |
296 } else if (bot < pts[0].fY) { | 296 } else if (bot < pts[0].fY) { |
297 bot = pts[0].fY; | 297 bot = pts[0].fY; |
298 } | 298 } |
299 } | 299 } |
300 } | 300 } |
| 301 if (0 == maxEdges) { |
| 302 return 0; // we have only moves+closes |
| 303 } |
| 304 |
301 SkASSERT(top <= bot); | 305 SkASSERT(top <= bot); |
302 | |
303 *itop = SkScalarRoundToInt(top); | 306 *itop = SkScalarRoundToInt(top); |
304 *ibot = SkScalarRoundToInt(bot); | 307 *ibot = SkScalarRoundToInt(bot); |
305 return maxEdges; | 308 return maxEdges; |
306 } | 309 } |
307 | 310 |
| 311 static bool check_inverse_on_empty_return(SkRegion* dst, const SkPath& path, con
st SkRegion& clip) { |
| 312 if (path.isInverseFillType()) { |
| 313 return dst->set(clip); |
| 314 } else { |
| 315 return dst->setEmpty(); |
| 316 } |
| 317 } |
| 318 |
308 bool SkRegion::setPath(const SkPath& path, const SkRegion& clip) { | 319 bool SkRegion::setPath(const SkPath& path, const SkRegion& clip) { |
309 SkDEBUGCODE(this->validate();) | 320 SkDEBUGCODE(this->validate();) |
310 | 321 |
311 if (clip.isEmpty()) { | 322 if (clip.isEmpty()) { |
312 return this->setEmpty(); | 323 return this->setEmpty(); |
313 } | 324 } |
314 | 325 |
315 if (path.isEmpty()) { | 326 if (path.isEmpty()) { |
316 if (path.isInverseFillType()) { | 327 return check_inverse_on_empty_return(this, path, clip); |
317 return this->set(clip); | |
318 } else { | |
319 return this->setEmpty(); | |
320 } | |
321 } | 328 } |
322 | 329 |
323 // compute worst-case rgn-size for the path | 330 // compute worst-case rgn-size for the path |
324 int pathTop, pathBot; | 331 int pathTop, pathBot; |
325 int pathTransitions = count_path_runtype_values(path, &pathTop, &pathBot); | 332 int pathTransitions = count_path_runtype_values(path, &pathTop, &pathBot); |
| 333 if (0 == pathTransitions) { |
| 334 return check_inverse_on_empty_return(this, path, clip); |
| 335 } |
| 336 |
326 int clipTop, clipBot; | 337 int clipTop, clipBot; |
327 int clipTransitions; | 338 int clipTransitions = clip.count_runtype_values(&clipTop, &clipBot); |
328 | |
329 clipTransitions = clip.count_runtype_values(&clipTop, &clipBot); | |
330 | 339 |
331 int top = SkMax32(pathTop, clipTop); | 340 int top = SkMax32(pathTop, clipTop); |
332 int bot = SkMin32(pathBot, clipBot); | 341 int bot = SkMin32(pathBot, clipBot); |
333 | 342 if (top >= bot) { |
334 if (top >= bot) | 343 return check_inverse_on_empty_return(this, path, clip); |
335 return this->setEmpty(); | 344 } |
336 | 345 |
337 SkRgnBuilder builder; | 346 SkRgnBuilder builder; |
338 | 347 |
339 if (!builder.init(bot - top, | 348 if (!builder.init(bot - top, |
340 SkMax32(pathTransitions, clipTransitions), | 349 SkMax32(pathTransitions, clipTransitions), |
341 path.isInverseFillType())) { | 350 path.isInverseFillType())) { |
342 // can't allocate working space, so return false | 351 // can't allocate working space, so return false |
343 return this->setEmpty(); | 352 return this->setEmpty(); |
344 } | 353 } |
345 | 354 |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 #endif | 527 #endif |
519 | 528 |
520 path->incReserve(count << 1); | 529 path->incReserve(count << 1); |
521 do { | 530 do { |
522 SkASSERT(count > 1); | 531 SkASSERT(count > 1); |
523 count -= extract_path(start, stop, path); | 532 count -= extract_path(start, stop, path); |
524 } while (count > 0); | 533 } while (count > 0); |
525 | 534 |
526 return true; | 535 return true; |
527 } | 536 } |
OLD | NEW |