blob: 0e94d1ccedb6ab36f8fdb54059058d09971267d1 [file] [log] [blame]
// Copyright 2017 The Fuchsia 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 "garnet/bin/ui/sketchy/stroke/divided_stroke_path.h"
#include "lib/escher/util/trace_macros.h"
#include "lib/fxl/logging.h"
namespace sketchy_service {
DividedStrokePath::DividedStrokePath(float half_width, float pixel_per_division)
: half_width_(half_width),
pixel_per_division_(pixel_per_division),
path_(std::make_unique<StrokePath>()) {}
void DividedStrokePath::SetPath(std::unique_ptr<StrokePath> path) {
Reset(path->segment_count());
path_ = std::move(path);
UpdateGeometry(*path_);
}
void DividedStrokePath::Extend(const StrokePath& delta_path) {
path_->ExtendWithPath(delta_path);
UpdateGeometry(delta_path);
}
void DividedStrokePath::Reset(size_t segment_count) {
path_->Reset(segment_count);
bbox_ = escher::BoundingBox();
vertex_count_ = 0;
index_count_ = 0;
division_count_ = 0;
vertex_counts_.clear();
division_counts_.clear();
cumulative_division_counts_.clear();
if (segment_count > 0) {
vertex_counts_.reserve(segment_count);
division_counts_.reserve(segment_count);
cumulative_division_counts_.reserve(segment_count);
}
}
std::vector<uint32_t> DividedStrokePath::ComputeCumulativeDivisionCounts(
uint32_t base_division_count) const {
auto cumulative_division_counts = cumulative_division_counts_;
for (size_t i = 0; i < cumulative_division_counts.size(); ++i) {
cumulative_division_counts[i] += base_division_count;
}
return cumulative_division_counts;
}
std::vector<uint32_t> DividedStrokePath::PrepareDivisionSegmentIndices(
const DividedStrokePath& trailing_path) {
TRACE_DURATION(
"gfx",
"sketchy_service::DividedStrokePath::PrepareDivisionSegmentIndices");
std::vector<uint32_t> division_segment_indices(division_count_ +
trailing_path.division_count_);
for (uint32_t i = 0; i < division_counts_.size(); ++i) {
auto begin =
division_segment_indices.begin() + cumulative_division_counts_[i];
auto end = begin + division_counts_[i];
std::fill(begin, end, i);
}
for (uint32_t i = 0; i < trailing_path.division_counts_.size(); ++i) {
auto begin = division_segment_indices.begin() + division_count_ +
trailing_path.cumulative_division_counts_[i];
auto end = begin + trailing_path.division_counts_[i];
std::fill(begin, end, division_counts_.size() + i);
}
return division_segment_indices;
}
void DividedStrokePath::UpdateGeometry(const StrokePath& delta_path) {
for (const auto& seg : delta_path.control_points()) {
glm::vec3 bmin = {
std::min({seg.pts[0].x, seg.pts[1].x, seg.pts[2].x, seg.pts[3].x}),
std::min({seg.pts[0].y, seg.pts[1].y, seg.pts[2].y, seg.pts[3].y}), 0};
glm::vec3 bmax = {
std::max({seg.pts[0].x, seg.pts[1].x, seg.pts[2].x, seg.pts[3].x}),
std::max({seg.pts[0].y, seg.pts[1].y, seg.pts[2].y, seg.pts[3].y}), 0};
bbox_.Join({bmin - half_width_, bmax + half_width_});
}
for (const auto& length : delta_path.segment_lengths()) {
uint32_t division_count =
std::max(1U, static_cast<uint32_t>(length / pixel_per_division_));
division_counts_.push_back(division_count);
cumulative_division_counts_.push_back(division_count_);
division_count_ += division_count;
uint32_t vertex_count = division_count * 2;
vertex_counts_.push_back(vertex_count);
vertex_count_ += vertex_count;
}
index_count_ = vertex_count_ * 3;
}
} // namespace sketchy_service