blob: 2a9872e0ea8a3f80b17a727b2c3b082cd925bbea [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <vector>
#include "impeller/display_list/nine_patch_converter.h"
namespace impeller {
NinePatchConverter::NinePatchConverter() = default;
NinePatchConverter::~NinePatchConverter() = default;
std::vector<double> NinePatchConverter::InitSlices(double img0,
double imgC0,
double imgC1,
double img1,
double dst0,
double dst1) {
auto imageDim = img1 - img0;
auto destDim = dst1 - dst0;
if (imageDim == destDim) {
// If the src and dest are the same size then we do not need scaling
// We return 4 values for a single slice
return {img0, dst0, img1, dst1};
}
auto edge0Dim = imgC0 - img0;
auto edge1Dim = img1 - imgC1;
auto edgesDim = edge0Dim + edge1Dim;
if (edgesDim >= destDim) {
// the center portion has disappeared, leaving only the edges to scale to a
// common center position in the destination this produces only 2 slices
// which is 8 values
auto dstC = dst0 + destDim * edge0Dim / edgesDim;
// clang-format off
return {
img0, dst0, imgC0, dstC,
imgC1, dstC, img1, dst1,
};
// clang-format on
}
// center portion is nonEmpty and only that part is scaled
// we need 3 slices which is 12 values
auto dstC0 = dst0 + edge0Dim;
auto dstC1 = dst1 - edge1Dim;
// clang-format off
return {
img0, dst0, imgC0, dstC0,
imgC0, dstC0, imgC1, dstC1,
imgC1, dstC1, img1, dst1,
};
// clang-format on
}
void NinePatchConverter::DrawNinePatch(std::shared_ptr<Image> image,
Rect center,
Rect dst,
SamplerDescriptor sampler,
Canvas* canvas,
Paint* paint) {
if (dst.IsEmpty()) {
return;
}
auto image_size = image->GetSize();
auto hSlices = InitSlices(0, center.GetLeft(), center.GetRight(),
image_size.width, dst.GetLeft(), dst.GetRight());
auto vSlices = InitSlices(0, center.GetTop(), center.GetBottom(),
image_size.height, dst.GetTop(), dst.GetBottom());
for (size_t yi = 0; yi < vSlices.size(); yi += 4) {
auto srcY0 = vSlices[yi];
auto dstY0 = vSlices[yi + 1];
auto srcY1 = vSlices[yi + 2];
auto dstY1 = vSlices[yi + 3];
for (size_t xi = 0; xi < hSlices.size(); xi += 4) {
auto srcX0 = hSlices[xi];
auto dstX0 = hSlices[xi + 1];
auto srcX1 = hSlices[xi + 2];
auto dstX1 = hSlices[xi + 3];
// TODO(jonahwilliams): consider converting this into a single call to
// DrawImageAtlas.
canvas->DrawImageRect(image, Rect::MakeLTRB(srcX0, srcY0, srcX1, srcY1),
Rect::MakeLTRB(dstX0, dstY0, dstX1, dstY1), *paint,
sampler);
}
}
}
} // namespace impeller