Flutter Impeller
nine_patch_converter.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <vector>
6 
8 
9 namespace impeller {
10 
12 
14 
15 std::vector<double> NinePatchConverter::InitSlices(double img0,
16  double imgC0,
17  double imgC1,
18  double img1,
19  double dst0,
20  double dst1) {
21  auto imageDim = img1 - img0;
22  auto destDim = dst1 - dst0;
23 
24  if (imageDim == destDim) {
25  // If the src and dest are the same size then we do not need scaling
26  // We return 4 values for a single slice
27  return {img0, dst0, img1, dst1};
28  }
29 
30  auto edge0Dim = imgC0 - img0;
31  auto edge1Dim = img1 - imgC1;
32  auto edgesDim = edge0Dim + edge1Dim;
33 
34  if (edgesDim >= destDim) {
35  // the center portion has disappeared, leaving only the edges to scale to a
36  // common center position in the destination this produces only 2 slices
37  // which is 8 values
38  auto dstC = dst0 + destDim * edge0Dim / edgesDim;
39  // clang-format off
40  return {
41  img0, dst0, imgC0, dstC,
42  imgC1, dstC, img1, dst1,
43  };
44  // clang-format on
45  }
46 
47  // center portion is nonEmpty and only that part is scaled
48  // we need 3 slices which is 12 values
49  auto dstC0 = dst0 + edge0Dim;
50  auto dstC1 = dst1 - edge1Dim;
51  // clang-format off
52  return {
53  img0, dst0, imgC0, dstC0,
54  imgC0, dstC0, imgC1, dstC1,
55  imgC1, dstC1, img1, dst1,
56  };
57  // clang-format on
58 }
59 
60 void NinePatchConverter::DrawNinePatch(const std::shared_ptr<Texture>& image,
61  Rect center,
62  Rect dst,
63  const SamplerDescriptor& sampler,
64  Canvas* canvas,
65  Paint* paint) {
66  if (dst.IsEmpty()) {
67  return;
68  }
69  auto image_size = image->GetSize();
70  auto hSlices = InitSlices(0, center.GetLeft(), center.GetRight(),
71  image_size.width, dst.GetLeft(), dst.GetRight());
72  auto vSlices = InitSlices(0, center.GetTop(), center.GetBottom(),
73  image_size.height, dst.GetTop(), dst.GetBottom());
74 
75  for (size_t yi = 0; yi < vSlices.size(); yi += 4) {
76  auto srcY0 = vSlices[yi];
77  auto dstY0 = vSlices[yi + 1];
78  auto srcY1 = vSlices[yi + 2];
79  auto dstY1 = vSlices[yi + 3];
80  for (size_t xi = 0; xi < hSlices.size(); xi += 4) {
81  auto srcX0 = hSlices[xi];
82  auto dstX0 = hSlices[xi + 1];
83  auto srcX1 = hSlices[xi + 2];
84  auto dstX1 = hSlices[xi + 3];
85  // TODO(jonahwilliams): consider converting this into a single call to
86  // DrawImageAtlas.
87  canvas->DrawImageRect(image, Rect::MakeLTRB(srcX0, srcY0, srcX1, srcY1),
88  Rect::MakeLTRB(dstX0, dstY0, dstX1, dstY1), *paint,
90  }
91  }
92 }
93 
94 } // namespace impeller
void DrawImageRect(const std::shared_ptr< Texture > &image, Rect source, Rect dest, const Paint &paint, const SamplerDescriptor &sampler={}, SourceRectConstraint src_rect_constraint=SourceRectConstraint::kFast)
Definition: canvas.cc:939
void DrawNinePatch(const std::shared_ptr< Texture > &image, Rect center, Rect dst, const SamplerDescriptor &sampler, Canvas *canvas, Paint *paint)
@ kStrict
Sample only within the source rectangle. May be slower.
constexpr auto GetBottom() const
Definition: rect.h:361
constexpr auto GetTop() const
Definition: rect.h:357
constexpr bool IsEmpty() const
Returns true if either of the width or height are 0, negative, or NaN.
Definition: rect.h:301
constexpr auto GetLeft() const
Definition: rect.h:355
constexpr auto GetRight() const
Definition: rect.h:359
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129