OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
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 "SkLinearBitmapPipeline.h" | 8 #include "SkLinearBitmapPipeline.h" |
9 #include "SkPM4f.h" | 9 #include "SkPM4f.h" |
10 | 10 |
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 , fXMax{X(max) - 1.0f} | 367 , fXMax{X(max) - 1.0f} |
368 , fYMax{Y(max) - 1.0f} { } | 368 , fYMax{Y(max) - 1.0f} { } |
369 | 369 |
370 void processPoints(Sk4f* xs, Sk4f* ys) { | 370 void processPoints(Sk4f* xs, Sk4f* ys) { |
371 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); | 371 *xs = Sk4f::Min(Sk4f::Max(*xs, fXMin), fXMax); |
372 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); | 372 *ys = Sk4f::Min(Sk4f::Max(*ys, fYMin), fYMax); |
373 } | 373 } |
374 | 374 |
375 template <typename Next> | 375 template <typename Next> |
376 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { | 376 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
377 return false; | 377 SkScalar xMin = fXMin[0]; |
mtklein
2016/02/23 15:51:56
It's occurred to me that we should probably be usi
herb_g
2016/02/23 21:10:23
Done.
| |
378 SkScalar xMax = fXMax[0]; | |
379 SkScalar yMin = fYMin[0]; | |
380 SkScalar yMax = fYMax[0]; | |
381 SkScalar x = X(start); | |
382 SkScalar y = std::min(std::max(yMin, start.fY), yMax); | |
mtklein
2016/02/23 15:51:56
Weird to write X(start) and start.fY...
herb_g
2016/02/23 21:10:23
Done.
| |
383 | |
mtklein
2016/02/23 15:51:56
Some ideas:
- invert the logic so the easy case
herb_g
2016/02/23 21:10:23
I did this a totally different way. Please re-revi
| |
384 int beforeCount = 0; | |
385 int middleCount = count; | |
386 int afterCount = 0; | |
387 if (x < xMin || x + length > xMax) { | |
388 SkScalar dx = length / (count - 1); | |
f(malita)
2016/02/23 20:53:48
'count' is the span/pixel count, right - why (coun
f(malita)
2016/02/23 21:04:08
A more general comment re. dx and dst->src mapping
| |
389 | |
390 if (x < xMin) { | |
391 SkScalar overLength = xMin - x; | |
392 beforeCount = SkScalarFloorToInt(overLength / dx) + 1; | |
393 middleCount -= beforeCount; | |
394 length = length - dx * beforeCount; | |
395 x = xMin; | |
396 } | |
397 | |
398 if (x + length > xMax) { | |
399 SkScalar overLength = (x + length) - xMax; | |
400 afterCount = SkScalarFloorToInt(overLength / dx) + 1; | |
401 middleCount -= afterCount; | |
402 length = length - dx * afterCount; | |
403 } | |
404 auto SendSpan = [&](SkPoint start, SkScalar length, int count) { | |
f(malita)
2016/02/23 20:53:48
Looks like we only need to capture 'next' here.
herb_g
2016/02/23 21:30:35
This is gone. I made Span handle count == 1.
| |
405 if (count > 0) { | |
406 if (count == 1) { | |
407 next->pointListFew(1, Sk4f{X(start)}, Sk4f{Y(start)}); | |
mtklein
2016/02/23 15:51:56
Why can't pointSpan handle count == 1?
herb_g
2016/02/23 21:30:35
There was a NaN problem with the division in a dee
| |
408 } else { | |
409 next->pointSpan(start, length, count); | |
410 } | |
411 } | |
412 }; | |
413 SendSpan(SkPoint{xMin, y}, 0.0f, beforeCount); | |
414 SendSpan(SkPoint{x, y}, length, middleCount); | |
415 SendSpan(SkPoint{xMax - 1, y}, 0.0f, afterCount); | |
416 } else { | |
417 next->pointSpan(start, length, count); | |
418 } | |
419 | |
420 return true; | |
378 } | 421 } |
379 | 422 |
380 private: | 423 private: |
381 const Sk4f fXMin{SK_FloatNegativeInfinity}; | 424 const Sk4f fXMin{SK_FloatNegativeInfinity}; |
382 const Sk4f fYMin{SK_FloatNegativeInfinity}; | 425 const Sk4f fYMin{SK_FloatNegativeInfinity}; |
383 const Sk4f fXMax{SK_FloatInfinity}; | 426 const Sk4f fXMax{SK_FloatInfinity}; |
384 const Sk4f fYMax{SK_FloatInfinity}; | 427 const Sk4f fYMax{SK_FloatInfinity}; |
385 }; | 428 }; |
386 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> | 429 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> |
387 using Clamp = BilerpProcessor<ClampStrategy, Next>; | 430 using Clamp = BilerpProcessor<ClampStrategy, Next>; |
388 | 431 |
432 // It would be nice to use fmod, but it uses trunc based rounding where floor ro unding is needed. | |
433 static float tile_mod(float l, float base) { | |
mtklein
2016/02/23 15:51:56
I think you might want to pick a different letter-
herb_g
2016/02/23 21:10:23
Done.
| |
434 return l - std::floor(l / base) * base; | |
mtklein
2016/02/23 15:51:56
We're getting a little loosey-goosey about SkScala
herb_g
2016/02/23 21:10:23
Done.
| |
435 } | |
436 | |
389 class RepeatStrategy { | 437 class RepeatStrategy { |
390 public: | 438 public: |
391 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } | 439 RepeatStrategy(X max) : fXMax{max}, fXInvMax{1.0f/max} { } |
392 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } | 440 RepeatStrategy(Y max) : fYMax{max}, fYInvMax{1.0f/max} { } |
393 RepeatStrategy(SkSize max) | 441 RepeatStrategy(SkSize max) |
394 : fXMax{X(max)} | 442 : fXMax{X(max)} |
395 , fXInvMax{1.0f / X(max)} | 443 , fXInvMax{1.0f / X(max)} |
396 , fYMax{Y(max)} | 444 , fYMax{Y(max)} |
397 , fYInvMax{1.0f / Y(max)} { } | 445 , fYInvMax{1.0f / Y(max)} { } |
398 | 446 |
399 void processPoints(Sk4f* xs, Sk4f* ys) { | 447 void processPoints(Sk4f* xs, Sk4f* ys) { |
400 Sk4f divX = (*xs * fXInvMax).floor(); | 448 Sk4f divX = (*xs * fXInvMax).floor(); |
401 Sk4f divY = (*ys * fYInvMax).floor(); | 449 Sk4f divY = (*ys * fYInvMax).floor(); |
402 Sk4f baseX = (divX * fXMax); | 450 Sk4f baseX = (divX * fXMax); |
403 Sk4f baseY = (divY * fYMax); | 451 Sk4f baseY = (divY * fYMax); |
404 *xs = *xs - baseX; | 452 *xs = *xs - baseX; |
405 *ys = *ys - baseY; | 453 *ys = *ys - baseY; |
406 } | 454 } |
407 | 455 |
408 template <typename Next> | 456 template <typename Next> |
409 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { | 457 bool maybeProcessSpan(SkPoint start, SkScalar length, int count, Next* next) { |
410 return false; | 458 SkScalar x = tile_mod(X(start), fXMax[0]); |
459 SkScalar y = tile_mod(Y(start), fYMax[0]); | |
460 SkScalar dx = length / (count - 1); | |
f(malita)
2016/02/23 20:53:48
Same question re count - 1.
herb_g
2016/02/23 21:30:35
Added much documentation. See if that answers the
| |
461 auto SendSpan = [&](SkPoint start, SkScalar length, int count) { | |
462 if (count > 0) { | |
463 if (count == 1) { | |
464 next->pointListFew(1, Sk4f{X(start)}, Sk4f{Y(start)}); | |
465 } else { | |
466 next->pointSpan(start, length, count); | |
467 } | |
468 } | |
469 }; | |
470 while (x + length > fXMax[0]) { | |
mtklein
2016/02/23 15:51:56
Explain how this works?
herb_g
2016/02/23 21:10:23
Done.
| |
471 SkScalar lengthForTile = std::min(fXMax[0] - x, length); | |
472 int countForTile = SkScalarFloorToInt(lengthForTile / dx); | |
f(malita)
2016/02/23 20:53:48
I noticed we always pad one to the count in the cl
herb_g
2016/02/23 21:30:35
If the source is 1 pixel wide, then this should ma
| |
473 SkScalar lengthForDx = countForTile * dx; | |
474 SendSpan({x, y}, lengthForDx, countForTile); | |
475 length -= lengthForDx; | |
476 count -= countForTile; | |
f(malita)
2016/02/23 20:53:48
Looks like we only track count in order to handle
herb_g
2016/02/23 21:30:35
That would mean a bunch of calculation in the comm
| |
477 x = 0; | |
478 } | |
479 SendSpan({x, y}, length, count); | |
480 | |
481 return true; | |
411 } | 482 } |
412 | 483 |
413 private: | 484 private: |
414 const Sk4f fXMax{0.0f}; | 485 const Sk4f fXMax{0.0f}; |
415 const Sk4f fXInvMax{0.0f}; | 486 const Sk4f fXInvMax{0.0f}; |
416 const Sk4f fYMax{0.0f}; | 487 const Sk4f fYMax{0.0f}; |
417 const Sk4f fYInvMax{0.0f}; | 488 const Sk4f fYInvMax{0.0f}; |
418 }; | 489 }; |
419 | 490 |
420 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> | 491 template <typename Next = SkLinearBitmapPipeline::BilerpProcessorInterface> |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
701 if (count == 1) { | 772 if (count == 1) { |
702 fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f}); | 773 fFirstStage->pointListFew(1, Sk4f{x + 0.5f}, Sk4f{y + 0.5f}); |
703 } else { | 774 } else { |
704 // The count and length arguments start out in a precise relation in ord er to keep the | 775 // The count and length arguments start out in a precise relation in ord er to keep the |
705 // math correct through the different stages. Count is the number of pix el to produce. | 776 // math correct through the different stages. Count is the number of pix el to produce. |
706 // Since the code samples at pixel centers, length is the distance from the center of the | 777 // Since the code samples at pixel centers, length is the distance from the center of the |
707 // first pixel to the center of the last pixel. This implies that length is count-1. | 778 // first pixel to the center of the last pixel. This implies that length is count-1. |
708 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count); | 779 fFirstStage->pointSpan(SkPoint{x + 0.5f, y + 0.5f}, count - 1, count); |
709 } | 780 } |
710 } | 781 } |
OLD | NEW |