载入中...
搜索中...
未找到
NinePatch.cpp
浏览该文件的文档.
1#include "ui/NinePatch.h"
2
3#include "image/ImageData.h"
4
5#include <algorithm>
6#include <utility>
7
8namespace eve::ui {
9namespace {
10
12
13bool marker(const Color &color) {
14 return color.a >= 0.5f && color.r <= 0.1f && color.g <= 0.1f &&
15 color.b <= 0.1f;
16}
17
18bool transparent(const Color &color) { return color.a <= 0.1f; }
19
20struct MarkerRun {
21 int first = -1;
22 int last = -1;
23};
24
25template <typename PixelAt>
26bool scanRun(int count, PixelAt pixelAt, bool required, const char *edge,
27 MarkerRun &run, std::string *error) {
28 bool ended = false;
29 for (int i = 0; i < count; ++i) {
30 const Color color = pixelAt(i);
31 if (marker(color)) {
32 if (ended) {
33 if (error) *error = std::string(edge) + " has multiple stretch runs";
34 return false;
35 }
36 if (run.first < 0) run.first = i;
37 run.last = i;
38 } else {
39 if (!transparent(color)) {
40 if (error) *error = std::string(edge) + " contains a non-marker pixel";
41 return false;
42 }
43 if (run.first >= 0) ended = true;
44 }
45 }
46 if (required && run.first < 0) {
47 if (error) *error = std::string(edge) + " is missing a stretch marker";
48 return false;
49 }
50 return true;
51}
52
53} // namespace
54
56 std::string *error) {
57 out = {};
58 if (source.getFormat() != "RGBA8") {
59 if (error) *error = ".9.png source must decode as RGBA8";
60 return false;
61 }
62 if (source.getWidth() < 3 || source.getHeight() < 3) {
63 if (error) *error = ".9.png must include a one-pixel frame around content";
64 return false;
65 }
66
67 const int width = source.getWidth() - 2;
68 const int height = source.getHeight() - 2;
69 for (const auto &[x, y] : {std::pair{0, 0}, std::pair{source.getWidth() - 1, 0},
70 std::pair{0, source.getHeight() - 1},
71 std::pair{source.getWidth() - 1,
72 source.getHeight() - 1}}) {
73 if (!transparent(source.getPixel(x, y))) {
74 if (error) *error = ".9.png corner marker pixels must be transparent";
75 return false;
76 }
77 }
78
79 MarkerRun stretchX;
80 MarkerRun stretchY;
81 MarkerRun contentX;
82 MarkerRun contentY;
83 if (!scanRun(width, [&](int i) { return source.getPixel(i + 1, 0); }, true,
84 "top edge", stretchX, error) ||
85 !scanRun(height, [&](int i) { return source.getPixel(0, i + 1); }, true,
86 "left edge", stretchY, error) ||
87 !scanRun(width,
88 [&](int i) { return source.getPixel(i + 1, source.getHeight() - 1); },
89 false, "bottom edge", contentX, error) ||
90 !scanRun(height,
91 [&](int i) { return source.getPixel(source.getWidth() - 1, i + 1); },
92 false, "right edge", contentY, error))
93 return false;
94
95 out.width = width;
96 out.height = height;
97 out.borderLeft = stretchX.first;
98 out.borderRight = width - stretchX.last - 1;
99 out.borderTop = stretchY.first;
100 out.borderBottom = height - stretchY.last - 1;
101 out.paddingLeft = contentX.first >= 0 ? contentX.first : out.borderLeft;
102 out.paddingRight = contentX.first >= 0 ? width - contentX.last - 1 : out.borderRight;
103 out.paddingTop = contentY.first >= 0 ? contentY.first : out.borderTop;
104 out.paddingBottom = contentY.first >= 0 ? height - contentY.last - 1
105 : out.borderBottom;
106 return true;
107}
108
109std::unique_ptr<image::ImageData> stripNinePatchBorder(
110 const image::ImageData &source) {
111 if (source.getWidth() < 3 || source.getHeight() < 3) return nullptr;
112 auto result = std::make_unique<image::ImageData>(source.getWidth() - 2,
113 source.getHeight() - 2,
114 source.getFormat());
115 result->paste(const_cast<image::ImageData *>(&source), 0, 0, 1, 1,
116 source.getWidth() - 2, source.getHeight() - 2);
117 return result;
118}
119
120} // namespace eve::ui
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
std::int32_t first
std::uint32_t height
std::uint32_t width
bool required
bool ended
std::weak_ptr< Run > run
Definition OnnxGpgpu.cpp:25
std::string error
Definition Package.cpp:60
const RoadEdge * edge
std::uint32_t count
const UnitySourceAsset & source
Represents raw pixel data.
Definition ImageData.h:38
medialoader::Colorf Colorf
Definition ImageData.h:41
bool parseNinePatch(const image::ImageData &source, NinePatchInfo &out, std::string *error)
Parse a raw, uncompiled Android .9.png image.
Definition NinePatch.cpp:55
std::unique_ptr< image::ImageData > stripNinePatchBorder(const image::ImageData &source)
Copy the drawable interior of a parsed .9.png without marker pixels.
Parsed Android-style .9.png stretch and content metadata.
Definition NinePatch.h:21
glm::vec4 color