no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / gfx / 2d / ConvolutionFilter.cpp
blob31ace83dc71fb2c6fde8ad3c416a0573b2394fc1
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 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ConvolutionFilter.h"
8 #include "HelpersSkia.h"
9 #include "SkConvolver.h"
10 #include "skia/include/core/SkBitmap.h"
12 namespace mozilla::gfx {
14 ConvolutionFilter::ConvolutionFilter()
15 : mFilter(MakeUnique<skia::SkConvolutionFilter1D>()) {}
17 ConvolutionFilter::~ConvolutionFilter() = default;
19 int32_t ConvolutionFilter::MaxFilter() const { return mFilter->maxFilter(); }
21 int32_t ConvolutionFilter::NumValues() const { return mFilter->numValues(); }
23 bool ConvolutionFilter::GetFilterOffsetAndLength(int32_t aRowIndex,
24 int32_t* aResultOffset,
25 int32_t* aResultLength) {
26 if (aRowIndex >= mFilter->numValues()) {
27 return false;
29 mFilter->FilterForValue(aRowIndex, aResultOffset, aResultLength);
30 return true;
33 void ConvolutionFilter::ConvolveHorizontally(const uint8_t* aSrc, uint8_t* aDst,
34 bool aHasAlpha) {
35 skia::convolve_horizontally(aSrc, *mFilter, aDst, aHasAlpha);
38 void ConvolutionFilter::ConvolveVertically(uint8_t* const* aSrc, uint8_t* aDst,
39 int32_t aRowIndex, int32_t aRowSize,
40 bool aHasAlpha) {
41 MOZ_ASSERT(aRowIndex < mFilter->numValues());
43 int32_t filterOffset;
44 int32_t filterLength;
45 auto filterValues =
46 mFilter->FilterForValue(aRowIndex, &filterOffset, &filterLength);
47 skia::convolve_vertically(filterValues, filterLength, aSrc, aRowSize, aDst,
48 aHasAlpha);
51 bool ConvolutionFilter::ComputeResizeFilter(ResizeMethod aResizeMethod,
52 int32_t aSrcSize,
53 int32_t aDstSize) {
54 if (aSrcSize < 0 || aDstSize < 0) {
55 return false;
58 switch (aResizeMethod) {
59 case ResizeMethod::BOX:
60 return mFilter->ComputeFilterValues(skia::SkBoxFilter(), aSrcSize,
61 aDstSize);
62 case ResizeMethod::LANCZOS3:
63 return mFilter->ComputeFilterValues(skia::SkLanczosFilter(), aSrcSize,
64 aDstSize);
65 default:
66 return false;
70 bool Scale(uint8_t* srcData, int32_t srcWidth, int32_t srcHeight,
71 int32_t srcStride, uint8_t* dstData, int32_t dstWidth,
72 int32_t dstHeight, int32_t dstStride, SurfaceFormat format) {
73 if (!srcData || !dstData || srcWidth < 1 || srcHeight < 1 || dstWidth < 1 ||
74 dstHeight < 1) {
75 return false;
78 SkPixmap srcPixmap(MakeSkiaImageInfo(IntSize(srcWidth, srcHeight), format),
79 srcData, srcStride);
81 // Rescaler is compatible with N32 only. Convert to N32 if needed.
82 SkBitmap tmpBitmap;
83 if (srcPixmap.colorType() != kN32_SkColorType) {
84 if (!tmpBitmap.tryAllocPixels(
85 SkImageInfo::MakeN32Premul(srcWidth, srcHeight)) ||
86 !tmpBitmap.writePixels(srcPixmap) ||
87 !tmpBitmap.peekPixels(&srcPixmap)) {
88 return false;
92 ConvolutionFilter xFilter;
93 ConvolutionFilter yFilter;
94 ConvolutionFilter* xOrYFilter = &xFilter;
95 bool isSquare = srcWidth == srcHeight && dstWidth == dstHeight;
96 if (!xFilter.ComputeResizeFilter(ConvolutionFilter::ResizeMethod::LANCZOS3,
97 srcWidth, dstWidth)) {
98 return false;
100 if (!isSquare) {
101 if (!yFilter.ComputeResizeFilter(ConvolutionFilter::ResizeMethod::LANCZOS3,
102 srcHeight, dstHeight)) {
103 return false;
105 xOrYFilter = &yFilter;
108 return skia::BGRAConvolve2D(
109 static_cast<const uint8_t*>(srcPixmap.addr()), int(srcPixmap.rowBytes()),
110 !srcPixmap.isOpaque(), xFilter.GetSkiaFilter(),
111 xOrYFilter->GetSkiaFilter(), int(dstStride), dstData);
114 } // namespace mozilla::gfx