17 FlutterRect CalculateBounds(
const FlutterLayer** layers,
size_t layers_count) {
18 double x_min = HUGE_VAL;
19 double x_max = -HUGE_VAL;
20 double y_min = HUGE_VAL;
21 double y_max = -HUGE_VAL;
22 for (
const FlutterLayer** layer = layers; layer < layers + layers_count;
24 const FlutterPoint& offset = (*layer)->offset;
25 const FlutterSize& size = (*layer)->size;
26 x_min = std::min(x_min, offset.x);
27 y_min = std::min(y_min, offset.y);
28 x_max = std::max(x_max, offset.x + size.width);
29 y_max = std::max(y_max, offset.y + size.height);
31 return FlutterRect{x_min, y_min, x_max, y_max};
36 void BlendLayer(std::vector<uint32_t>& allocation,
37 const FlutterLayer& layer,
42 FML_DCHECK(layer.type == kFlutterLayerContentTypeBackingStore);
43 auto& backing_store = *layer.backing_store;
44 FML_DCHECK(backing_store.type == kFlutterBackingStoreTypeSoftware);
46 static_cast<const uint32_t*
>(backing_store.software.allocation);
47 const FlutterPoint& offset = layer.offset;
48 const FlutterSize& size = layer.size;
51 int y_src_min = std::max(0., y_min - offset.y);
52 int y_src_max = std::min(size.height, height + y_min - offset.y);
53 int x_src_min = std::max(0., x_min - offset.x);
54 int x_src_max = std::min(size.width, width + x_min - offset.x);
55 for (
int y_src = y_src_min; y_src < y_src_max; y_src++) {
56 int y_dst = y_src + offset.y - y_min;
57 for (
int x_src = x_src_min; x_src < x_src_max; x_src++) {
58 int x_dst = x_src + offset.x + x_min;
59 size_t i_src = y_src * size.width + x_src;
60 size_t i_dst = y_dst * width + x_dst;
61 uint32_t src = src_data[i_src];
62 uint32_t dst = allocation[i_dst];
64 int r_src = (src >> 0) & 0xff;
65 int g_src = (src >> 8) & 0xff;
66 int b_src = (src >> 16) & 0xff;
67 int a_src = (src >> 24) & 0xff;
69 int r_dst = (dst >> 0) & 0xff;
70 int g_dst = (dst >> 8) & 0xff;
71 int b_dst = (dst >> 16) & 0xff;
73 int r = (r_dst * 255 + (r_src - r_dst) * a_src) / 255;
74 int g = (g_dst * 255 + (g_src - g_dst) * a_src) / 255;
75 int b = (b_dst * 255 + (b_src - b_dst) * a_src) / 255;
77 allocation[i_dst] = (r << 0) | (g << 8) | (b << 16) | (0xff << 24);
87 const FlutterBackingStoreConfig& config,
88 FlutterBackingStore* result) {
89 size_t size = config.size.width * config.size.height * 4;
90 void* allocation = std::calloc(size,
sizeof(uint8_t));
95 result->type = kFlutterBackingStoreTypeSoftware;
96 result->software.allocation = allocation;
97 result->software.height = config.size.height;
98 result->software.row_bytes = config.size.width * 4;
99 result->software.user_data =
nullptr;
100 result->software.destruction_callback = [](
void*
user_data) {
108 std::free(
const_cast<void*
>(store->software.allocation));
113 const FlutterLayer** layers,
114 size_t layers_count) {
115 FML_DCHECK(view !=
nullptr);
118 if (layers_count == 0) {
123 if (layers_count == 1) {
124 const FlutterLayer* layer = layers[0];
125 FML_DCHECK(layer !=
nullptr);
126 if (layer->type == kFlutterLayerContentTypeBackingStore &&
127 layer->offset.x == 0 && layer->offset.y == 0) {
128 auto& backing_store = *layer->backing_store;
129 FML_DCHECK(backing_store.type == kFlutterBackingStoreTypeSoftware);
130 auto& software = backing_store.software;
132 software.row_bytes, software.height);
137 FlutterRect bounds = CalculateBounds(layers, layers_count);
139 int x_min =
static_cast<int>(bounds.left);
140 int x_max =
static_cast<int>(bounds.right);
141 int y_min =
static_cast<int>(bounds.top);
142 int y_max =
static_cast<int>(bounds.bottom);
144 int width = x_max - x_min;
145 int height = y_max - y_min;
146 std::vector<uint32_t> allocation(width * height,
kOpaqueBlack);
148 for (
const FlutterLayer** layer = layers; layer < layers + layers_count;
152 if ((*layer)->type == kFlutterLayerContentTypeBackingStore) {
153 BlendLayer(allocation, **layer, x_min, y_min, width, height);
161 width *
sizeof(uint32_t), height);