Bug 1876335 - use GRADLE_MAVEN_REPOSITORIES in more places. r=owlish,geckoview-review...
[gecko.git] / gfx / 2d / SkConvolver.h
blob5ea8ab9b5d82e54be9def8705f4005f60d980b24
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 // Copyright (c) 2011-2016 Google Inc.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the gfx/skia/LICENSE file.
7 #ifndef MOZILLA_GFX_SKCONVOLVER_H_
8 #define MOZILLA_GFX_SKCONVOLVER_H_
10 #include "mozilla/Assertions.h"
11 #include <cfloat>
12 #include <cmath>
13 #include <vector>
15 namespace skia {
17 class SkBitmapFilter {
18 public:
19 explicit SkBitmapFilter(float width) : fWidth(width) {}
20 virtual ~SkBitmapFilter() = default;
22 float width() const { return fWidth; }
23 virtual float evaluate(float x) const = 0;
25 protected:
26 float fWidth;
29 class SkBoxFilter final : public SkBitmapFilter {
30 public:
31 explicit SkBoxFilter(float width = 0.5f) : SkBitmapFilter(width) {}
33 float evaluate(float x) const override {
34 return (x >= -fWidth && x < fWidth) ? 1.0f : 0.0f;
38 class SkLanczosFilter final : public SkBitmapFilter {
39 public:
40 explicit SkLanczosFilter(float width = 3.0f) : SkBitmapFilter(width) {}
42 float evaluate(float x) const override {
43 if (x <= -fWidth || x >= fWidth) {
44 return 0.0f; // Outside of the window.
46 if (x > -FLT_EPSILON && x < FLT_EPSILON) {
47 return 1.0f; // Special case the discontinuity at the origin.
49 float xpi = x * float(M_PI);
50 return (sinf(xpi) / xpi) * // sinc(x)
51 sinf(xpi / fWidth) / (xpi / fWidth); // sinc(x/fWidth)
55 // Represents a filter in one dimension. Each output pixel has one entry in this
56 // object for the filter values contributing to it. You build up the filter
57 // list by calling AddFilter for each output pixel (in order).
59 // We do 2-dimensional convolution by first convolving each row by one
60 // SkConvolutionFilter1D, then convolving each column by another one.
62 // Entries are stored in ConvolutionFixed point, shifted left by kShiftBits.
63 class SkConvolutionFilter1D {
64 public:
65 using ConvolutionFixed = short;
67 // The number of bits that ConvolutionFixed point values are shifted by.
68 enum { kShiftBits = 14 };
70 SkConvolutionFilter1D();
71 ~SkConvolutionFilter1D();
73 // Convert between floating point and our ConvolutionFixed point
74 // representation.
75 static ConvolutionFixed ToFixed(float f) {
76 return static_cast<ConvolutionFixed>(f * (1 << kShiftBits));
79 // Returns the maximum pixel span of a filter.
80 int maxFilter() const { return fMaxFilter; }
82 // Returns the number of filters in this filter. This is the dimension of the
83 // output image.
84 int numValues() const { return static_cast<int>(fFilters.size()); }
86 void reserveAdditional(int filterCount, int filterValueCount) {
87 fFilters.reserve(fFilters.size() + filterCount);
88 fFilterValues.reserve(fFilterValues.size() + filterValueCount);
91 // Appends the given list of scaling values for generating a given output
92 // pixel. |filterOffset| is the distance from the edge of the image to where
93 // the scaling factors start. The scaling factors apply to the source pixels
94 // starting from this position, and going for the next |filterLength| pixels.
96 // You will probably want to make sure your input is normalized (that is,
97 // all entries in |filterValuesg| sub to one) to prevent affecting the overall
98 // brighness of the image.
100 // The filterLength must be > 0.
101 void AddFilter(int filterOffset, const ConvolutionFixed* filterValues,
102 int filterLength);
104 // Retrieves a filter for the given |valueOffset|, a position in the output
105 // image in the direction we're convolving. The offset and length of the
106 // filter values are put into the corresponding out arguments (see AddFilter
107 // above for what these mean), and a pointer to the first scaling factor is
108 // returned. There will be |filterLength| values in this array.
109 inline const ConvolutionFixed* FilterForValue(int valueOffset,
110 int* filterOffset,
111 int* filterLength) const {
112 const FilterInstance& filter = fFilters[valueOffset];
113 *filterOffset = filter.fOffset;
114 *filterLength = filter.fTrimmedLength;
115 if (filter.fTrimmedLength == 0) {
116 return nullptr;
118 return &fFilterValues[filter.fDataLocation];
121 bool ComputeFilterValues(const SkBitmapFilter& aBitmapFilter,
122 int32_t aSrcSize, int32_t aDstSize);
124 private:
125 struct FilterInstance {
126 // Offset within filterValues for this instance of the filter.
127 int fDataLocation;
129 // Distance from the left of the filter to the center. IN PIXELS
130 int fOffset;
132 // Number of values in this filter instance.
133 int fTrimmedLength;
135 // Filter length as specified. Note that this may be different from
136 // 'trimmed_length' if leading/trailing zeros of the original floating
137 // point form were clipped differently on each tail.
138 int fLength;
141 // Stores the information for each filter added to this class.
142 std::vector<FilterInstance> fFilters;
144 // We store all the filter values in this flat list, indexed by
145 // |FilterInstance.data_location| to avoid the mallocs required for storing
146 // each one separately.
147 std::vector<ConvolutionFixed> fFilterValues;
149 // The maximum size of any filter we've added.
150 int fMaxFilter;
153 void convolve_horizontally(const unsigned char* srcData,
154 const SkConvolutionFilter1D& filter,
155 unsigned char* outRow, bool hasAlpha);
157 void convolve_vertically(
158 const SkConvolutionFilter1D::ConvolutionFixed* filterValues,
159 int filterLength, unsigned char* const* sourceDataRows, int pixelWidth,
160 unsigned char* outRow, bool hasAlpha);
162 bool BGRAConvolve2D(const unsigned char* sourceData, int sourceByteRowStride,
163 bool sourceHasAlpha, const SkConvolutionFilter1D& filterX,
164 const SkConvolutionFilter1D& filterY,
165 int outputByteRowStride, unsigned char* output);
167 } // namespace skia
169 #endif /* MOZILLA_GFX_SKCONVOLVER_H_ */