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 | 9 |
10 #include "SkPM4f.h" | 10 #include "SkPM4f.h" |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 this->bilerpPoint(xs[1], ys[1]); | 231 this->bilerpPoint(xs[1], ys[1]); |
232 this->bilerpPoint(xs[2], ys[2]); | 232 this->bilerpPoint(xs[2], ys[2]); |
233 this->bilerpPoint(xs[3], ys[3]); | 233 this->bilerpPoint(xs[3], ys[3]); |
234 } | 234 } |
235 | 235 |
236 struct Wrapper { | 236 struct Wrapper { |
237 void pointSpan(Span span) { | 237 void pointSpan(Span span) { |
238 processor->breakIntoEdges(span); | 238 processor->breakIntoEdges(span); |
239 } | 239 } |
240 | 240 |
| 241 void repeatSpan(Span span, int32_t repeatCount) { |
| 242 while (repeatCount --> 0) { |
| 243 processor->pointSpan(span); |
| 244 } |
| 245 } |
| 246 |
241 BilerpTileStage* processor; | 247 BilerpTileStage* processor; |
242 }; | 248 }; |
243 | 249 |
244 // The span you pass must not be empty. | 250 // The span you pass must not be empty. |
245 void pointSpan(Span span) override { | 251 void pointSpan(Span span) override { |
246 SkASSERT(!span.isEmpty()); | 252 SkASSERT(!span.isEmpty()); |
247 | 253 |
248 Wrapper wrapper = {this}; | 254 Wrapper wrapper = {this}; |
249 if (!fXStrategy.maybeProcessSpan(span, &wrapper)) { | 255 if (!fXStrategy.maybeProcessSpan(span, &wrapper)) { |
250 span_fallback(span, this); | 256 span_fallback(span, this); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 break; | 363 break; |
358 } | 364 } |
359 }; | 365 }; |
360 | 366 |
361 static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( | 367 static SkLinearBitmapPipeline::PointProcessorInterface* choose_tiler( |
362 SkLinearBitmapPipeline::SampleProcessorInterface* next, | 368 SkLinearBitmapPipeline::SampleProcessorInterface* next, |
363 SkISize dimensions, | 369 SkISize dimensions, |
364 SkShader::TileMode xMode, | 370 SkShader::TileMode xMode, |
365 SkShader::TileMode yMode, | 371 SkShader::TileMode yMode, |
366 SkFilterQuality filterQuality, | 372 SkFilterQuality filterQuality, |
367 SkLinearBitmapPipeline::TileStage* tileStage) { | 373 SkScalar dx, |
| 374 SkLinearBitmapPipeline::TileStage* tileStage) |
| 375 { |
368 switch (xMode) { | 376 switch (xMode) { |
369 case SkShader::kClamp_TileMode: | 377 case SkShader::kClamp_TileMode: |
370 choose_tiler_ymode<XClampStrategy>(yMode, filterQuality, dimensions,
next, tileStage); | 378 choose_tiler_ymode<XClampStrategy>(yMode, filterQuality, dimensions,
next, tileStage); |
371 break; | 379 break; |
372 case SkShader::kRepeat_TileMode: | 380 case SkShader::kRepeat_TileMode: |
373 choose_tiler_ymode<XRepeatStrategy>(yMode, filterQuality, dimensions
, next, tileStage); | 381 if (dx == 1.0f && filterQuality == kNone_SkFilterQuality) { |
| 382 choose_tiler_ymode<XRepeatUnitScaleStrategy>( |
| 383 yMode, kNone_SkFilterQuality, dimensions, next, tileStage); |
| 384 } else { |
| 385 choose_tiler_ymode<XRepeatStrategy>( |
| 386 yMode, filterQuality, dimensions, next, tileStage); |
| 387 } |
374 break; | 388 break; |
375 case SkShader::kMirror_TileMode: | 389 case SkShader::kMirror_TileMode: |
376 choose_tiler_ymode<XMirrorStrategy>(yMode, filterQuality, dimensions
, next, tileStage); | 390 choose_tiler_ymode<XMirrorStrategy>(yMode, filterQuality, dimensions
, next, tileStage); |
377 break; | 391 break; |
378 } | 392 } |
379 | 393 |
380 return tileStage->get(); | 394 return tileStage->get(); |
381 } | 395 } |
382 | 396 |
383 | 397 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 if (inverse.getScaleX() >= 0.0f) { | 595 if (inverse.getScaleX() >= 0.0f) { |
582 adjustedInverse.setTranslateX( | 596 adjustedInverse.setTranslateX( |
583 nextafterf(inverse.getTranslateX(), std::floor(inverse.getTransl
ateX()))); | 597 nextafterf(inverse.getTranslateX(), std::floor(inverse.getTransl
ateX()))); |
584 } | 598 } |
585 if (inverse.getScaleY() >= 0.0f) { | 599 if (inverse.getScaleY() >= 0.0f) { |
586 adjustedInverse.setTranslateY( | 600 adjustedInverse.setTranslateY( |
587 nextafterf(inverse.getTranslateY(), std::floor(inverse.getTransl
ateY()))); | 601 nextafterf(inverse.getTranslateY(), std::floor(inverse.getTransl
ateY()))); |
588 } | 602 } |
589 } | 603 } |
590 | 604 |
| 605 SkScalar dx = adjustedInverse.getScaleX(); |
| 606 |
591 // If it is an index 8 color type, the sampler converts to unpremul for bett
er fidelity. | 607 // If it is an index 8 color type, the sampler converts to unpremul for bett
er fidelity. |
592 SkAlphaType alphaType = srcImageInfo.alphaType(); | 608 SkAlphaType alphaType = srcImageInfo.alphaType(); |
593 if (srcPixmap.colorType() == kIndex_8_SkColorType) { | 609 if (srcPixmap.colorType() == kIndex_8_SkColorType) { |
594 alphaType = kUnpremul_SkAlphaType; | 610 alphaType = kUnpremul_SkAlphaType; |
595 } | 611 } |
596 | 612 |
597 // As the stages are built, the chooser function may skip a stage. For examp
le, with the | 613 // As the stages are built, the chooser function may skip a stage. For examp
le, with the |
598 // identity matrix, the matrix stage is skipped, and the tilerStage is the f
irst stage. | 614 // identity matrix, the matrix stage is skipped, and the tilerStage is the f
irst stage. |
599 auto placementStage = choose_pixel_placer(alphaType, postAlpha, &fPixelStage
); | 615 auto placementStage = choose_pixel_placer(alphaType, postAlpha, &fPixelStage
); |
600 auto samplerStage = choose_pixel_sampler(placementStage, | 616 auto samplerStage = choose_pixel_sampler(placementStage, |
601 filterQuality, srcPixmap, &fSampl
eStage); | 617 filterQuality, srcPixmap, &fSampl
eStage); |
602 auto tilerStage = choose_tiler(samplerStage, | 618 auto tilerStage = choose_tiler(samplerStage, |
603 dimensions, xTile, yTile, filterQuality,
&fTiler); | 619 dimensions, xTile, yTile, filterQuality,
dx, &fTiler); |
604 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixSta
ge); | 620 fFirstStage = choose_matrix(tilerStage, adjustedInverse, &fMatrixSta
ge); |
605 } | 621 } |
606 | 622 |
607 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { | 623 void SkLinearBitmapPipeline::shadeSpan4f(int x, int y, SkPM4f* dst, int count) { |
608 SkASSERT(count > 0); | 624 SkASSERT(count > 0); |
609 fPixelStage->setDestination(dst); | 625 fPixelStage->setDestination(dst); |
610 // The count and length arguments start out in a precise relation in order t
o keep the | 626 // The count and length arguments start out in a precise relation in order t
o keep the |
611 // math correct through the different stages. Count is the number of pixel t
o produce. | 627 // math correct through the different stages. Count is the number of pixel t
o produce. |
612 // Since the code samples at pixel centers, length is the distance from the
center of the | 628 // Since the code samples at pixel centers, length is the distance from the
center of the |
613 // first pixel to the center of the last pixel. This implies that length is
count-1. | 629 // first pixel to the center of the last pixel. This implies that length is
count-1. |
614 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); | 630 fFirstStage->pointSpan(Span{{x + 0.5f, y + 0.5f}, count - 1.0f, count}); |
615 } | 631 } |
OLD | NEW |