blob: 3bcb5e9f1cd5211859b83c0e114648885e2cfaca [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 "impeller/display_list/vertices_converter.h"
#include "flutter/display_list/display_list_vertices.h"
#include "impeller/entity/entity.h"
#include "impeller/geometry/point.h"
namespace impeller {
static Rect ToRect(const SkRect& rect) {
return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
}
static std::vector<Color> fromColors(const flutter::DlVertices* vertices) {
std::vector<Color> colors;
auto* dl_colors = vertices->colors();
if (dl_colors == nullptr) {
return colors;
}
auto color_count = vertices->vertex_count();
colors.reserve(color_count);
for (int i = 0; i < color_count; i++) {
auto dl_color = dl_colors[i];
colors.push_back({
dl_color.getRedF(),
dl_color.getGreenF(),
dl_color.getBlueF(),
dl_color.getAlphaF(),
});
}
return colors;
}
static std::vector<Point> fromPoints(const flutter::DlVertices* vertices) {
std::vector<Point> points;
auto vertex_count = vertices->vertex_count();
auto* dl_vertices = vertices->vertices();
points.reserve(vertex_count);
for (int i = 0; i < vertex_count; i++) {
auto point = dl_vertices[i];
points.push_back(Point(point.x(), point.y()));
}
return points;
}
// Fan mode isn't natively supported. Unroll into triangle mode by
// manipulating the index array.
//
// In Triangle fan, the first vertex is shared across all triangles, and then
// each sliding window of two vertices plus that first vertex defines a
// triangle.
static std::vector<uint16_t> fromFanIndices(
const flutter::DlVertices* vertices) {
FML_DCHECK(vertices->vertex_count() >= 3);
FML_DCHECK(vertices->mode() == flutter::DlVertexMode::kTriangleFan);
std::vector<uint16_t> indices;
// Un-fan index buffer if provided.
if (vertices->index_count() > 0) {
auto* dl_indices = vertices->indices();
auto center_point = dl_indices[0];
for (int i = 1; i < vertices->index_count() - 1; i++) {
indices.push_back(center_point);
indices.push_back(dl_indices[i]);
indices.push_back(dl_indices[i + 1]);
}
} else {
// If indices were not provided, create an index buffer that unfans
// triangles instead of re-writing points, colors, et cetera.
for (int i = 1; i < vertices->vertex_count() - 1; i++) {
indices.push_back(0);
indices.push_back(i);
indices.push_back(i + 1);
}
}
return indices;
}
static std::vector<uint16_t> fromIndices(const flutter::DlVertices* vertices) {
if (vertices->mode() == flutter::DlVertexMode::kTriangleFan) {
return fromFanIndices(vertices);
}
std::vector<uint16_t> indices;
auto index_count = vertices->index_count();
auto* dl_indices = vertices->indices();
indices.reserve(index_count);
for (int i = 0; i < index_count; i++) {
auto index = dl_indices[i];
indices.push_back(index);
}
return indices;
}
Vertices ToVertices(const flutter::DlVertices* vertices) {
std::vector<uint16_t> indices = fromIndices(vertices);
std::vector<Point> points = fromPoints(vertices);
std::vector<Color> colors = fromColors(vertices);
VertexMode mode;
switch (vertices->mode()) {
case flutter::DlVertexMode::kTriangles:
mode = VertexMode::kTriangle;
break;
case flutter::DlVertexMode::kTriangleStrip:
mode = VertexMode::kTriangleStrip;
break;
case flutter::DlVertexMode::kTriangleFan:
// Unrolled into triangle mode by fromIndices.
mode = VertexMode::kTriangle;
break;
}
auto bounds = vertices->bounds();
return Vertices(std::move(points), std::move(indices), std::move(colors),
mode, ToRect(bounds));
}
} // namespace impeller