/src/skia/src/core/SkPixmapDraw.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2023 Google LLC |
3 | | * |
4 | | * Use of this source code is governed by a BSD-style license that can be |
5 | | * found in the LICENSE file. |
6 | | * |
7 | | * This file contains implementations of SkPixmap methods which require the CPU backend. |
8 | | */ |
9 | | |
10 | | #include "include/core/SkAlphaType.h" |
11 | | #include "include/core/SkBitmap.h" |
12 | | #include "include/core/SkBlendMode.h" |
13 | | #include "include/core/SkCanvas.h" |
14 | | #include "include/core/SkImageInfo.h" |
15 | | #include "include/core/SkMatrix.h" |
16 | | #include "include/core/SkPaint.h" |
17 | | #include "include/core/SkPixmap.h" |
18 | | #include "include/core/SkRect.h" |
19 | | #include "include/core/SkRefCnt.h" |
20 | | #include "include/core/SkShader.h" |
21 | | #include "include/core/SkSurface.h" |
22 | | #include "include/core/SkTileMode.h" |
23 | | #include "src/shaders/SkImageShader.h" |
24 | | |
25 | | #include <utility> |
26 | | |
27 | | struct SkSamplingOptions; |
28 | | |
29 | 0 | bool SkPixmap::scalePixels(const SkPixmap& actualDst, const SkSamplingOptions& sampling) const { |
30 | | // We may need to tweak how we interpret these just a little below, so we make copies. |
31 | 0 | SkPixmap src = *this, |
32 | 0 | dst = actualDst; |
33 | | |
34 | | // Can't do anthing with empty src or dst |
35 | 0 | if (src.width() <= 0 || src.height() <= 0 || |
36 | 0 | dst.width() <= 0 || dst.height() <= 0) { |
37 | 0 | return false; |
38 | 0 | } |
39 | | |
40 | | // no scaling involved? |
41 | 0 | if (src.width() == dst.width() && src.height() == dst.height()) { |
42 | 0 | return src.readPixels(dst); |
43 | 0 | } |
44 | | |
45 | | // If src and dst are both unpremul, we'll fake the source out to appear as if premul, |
46 | | // and mark the destination as opaque. This odd combination allows us to scale unpremul |
47 | | // pixels without ever premultiplying them (perhaps losing information in the color channels). |
48 | | // This is an idiosyncratic feature of scalePixels(), and is tested by scalepixels_unpremul GM. |
49 | 0 | bool clampAsIfUnpremul = false; |
50 | 0 | if (src.alphaType() == kUnpremul_SkAlphaType && |
51 | 0 | dst.alphaType() == kUnpremul_SkAlphaType) { |
52 | 0 | src.reset(src.info().makeAlphaType(kPremul_SkAlphaType), src.addr(), src.rowBytes()); |
53 | 0 | dst.reset(dst.info().makeAlphaType(kOpaque_SkAlphaType), dst.addr(), dst.rowBytes()); |
54 | | |
55 | | // We'll need to tell the image shader to clamp to [0,1] instead of the |
56 | | // usual [0,a] when using a bicubic scaling (kHigh_SkFilterQuality). |
57 | 0 | clampAsIfUnpremul = true; |
58 | 0 | } |
59 | |
|
60 | 0 | SkBitmap bitmap; |
61 | 0 | if (!bitmap.installPixels(src)) { |
62 | 0 | return false; |
63 | 0 | } |
64 | 0 | bitmap.setImmutable(); // Don't copy when we create an image. |
65 | |
|
66 | 0 | SkMatrix scale = SkMatrix::RectToRect(SkRect::Make(src.bounds()), SkRect::Make(dst.bounds())); |
67 | |
|
68 | 0 | sk_sp<SkShader> shader = SkImageShader::Make(bitmap.asImage(), |
69 | 0 | SkTileMode::kClamp, |
70 | 0 | SkTileMode::kClamp, |
71 | 0 | sampling, |
72 | 0 | &scale, |
73 | 0 | clampAsIfUnpremul); |
74 | |
|
75 | 0 | sk_sp<SkSurface> surface = |
76 | 0 | SkSurfaces::WrapPixels(dst.info(), dst.writable_addr(), dst.rowBytes()); |
77 | 0 | if (!shader || !surface) { |
78 | 0 | return false; |
79 | 0 | } |
80 | | |
81 | 0 | SkPaint paint; |
82 | 0 | paint.setBlendMode(SkBlendMode::kSrc); |
83 | 0 | paint.setShader(std::move(shader)); |
84 | 0 | surface->getCanvas()->drawPaint(paint); |
85 | 0 | return true; |
86 | 0 | } |