xref: /aosp_15_r20/external/skia/src/core/SkSamplingPriv.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2020 Google Inc.
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 
8 #ifndef SkSamplingPriv_DEFINED
9 #define SkSamplingPriv_DEFINED
10 
11 #include "include/core/SkSamplingOptions.h"
12 
13 class SkReadBuffer;
14 class SkWriteBuffer;
15 
16 // Given a src rect in texels to be filtered, this number of surrounding texels are needed by
17 // the kernel in x and y.
18 static constexpr int kBicubicFilterTexelPad = 2;
19 
20 // Private copy of SkFilterQuality, just for legacy deserialization
21 // Matches values in SkFilterQuality
22 enum SkLegacyFQ {
23     kNone_SkLegacyFQ   = 0,    //!< nearest-neighbor; fastest but lowest quality
24     kLow_SkLegacyFQ    = 1,    //!< bilerp
25     kMedium_SkLegacyFQ = 2,    //!< bilerp + mipmaps; good for down-scaling
26     kHigh_SkLegacyFQ   = 3,    //!< bicubic resampling; slowest but good quality
27 
28     kLast_SkLegacyFQ = kHigh_SkLegacyFQ,
29 };
30 
31 // Matches values in SkSamplingOptions::MediumBehavior
32 enum SkMediumAs {
33     kNearest_SkMediumAs,
34     kLinear_SkMediumAs,
35 };
36 
37 class SkSamplingPriv {
38 public:
FlatSize(const SkSamplingOptions & options)39     static size_t FlatSize(const SkSamplingOptions& options) {
40         size_t size = sizeof(uint32_t);  // maxAniso
41         if (!options.isAniso()) {
42             size += 3 * sizeof(uint32_t);  // bool32 + [2 floats | 2 ints]
43         }
44         return size;
45     }
46 
47     // Returns true if the sampling can be ignored when the CTM is identity.
NoChangeWithIdentityMatrix(const SkSamplingOptions & sampling)48     static bool NoChangeWithIdentityMatrix(const SkSamplingOptions& sampling) {
49         // If B == 0, the cubic resampler should have no effect for identity matrices
50         // https://entropymine.com/imageworsener/bicubic/
51         // We assume aniso has no effect with an identity transform.
52         return !sampling.useCubic || sampling.cubic.B == 0;
53     }
54 
55     // Makes a fallback SkSamplingOptions for cases where anisotropic filtering is not allowed.
56     // anisotropic filtering can access mip levels if present, but we don't add mipmaps to non-
57     // mipmapped images when the user requests anisotropic. So we shouldn't fall back to a
58     // sampling that would trigger mip map creation.
AnisoFallback(bool imageIsMipped)59     static SkSamplingOptions AnisoFallback(bool imageIsMipped) {
60         auto mm = imageIsMipped ? SkMipmapMode::kLinear : SkMipmapMode::kNone;
61         return SkSamplingOptions(SkFilterMode::kLinear, mm);
62     }
63 
64     static SkSamplingOptions FromFQ(SkLegacyFQ fq, SkMediumAs behavior = kNearest_SkMediumAs) {
65         switch (fq) {
66             case kHigh_SkLegacyFQ:
67                 return SkSamplingOptions(SkCubicResampler{1/3.0f, 1/3.0f});
68             case kMedium_SkLegacyFQ:
69                 return SkSamplingOptions(SkFilterMode::kLinear,
70                                           behavior == kNearest_SkMediumAs ? SkMipmapMode::kNearest
71                                                                           : SkMipmapMode::kLinear);
72             case kLow_SkLegacyFQ:
73                 return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone);
74             case kNone_SkLegacyFQ:
75                 break;
76         }
77         return SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone);
78     }
79 };
80 
81 #endif
82