blob: a6eb8d0f69cf9b32e165f75c38547ae3079e375b [file] [log] [blame]
// Copyright 2018 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.
#ifndef SRC_UI_LIB_ESCHER_FLATLAND_RECTANGLE_RENDERABLE_H_
#define SRC_UI_LIB_ESCHER_FLATLAND_RECTANGLE_RENDERABLE_H_
#include "src/ui/lib/escher/geometry/types.h"
#include "src/ui/lib/escher/vk/texture.h"
namespace escher {
// Struct representing the region of an image that a
// rectangle covers. Each of the rectangle's four
// corners are explicitly listed, with the default
// values covering the whole texture with no rotation.
// UV Coordinates are stored in a union, so they can be
// accessed individually or as an array. Any rotations
// on the rectangle can be done implicitly by changing
// the uv coordinates here. Since the rectangles are
// always axis-aligned, only rotations that are multiples
// of 90 degrees are supported.
struct RectangleSourceSpec {
// The source spec has 4 UV coordinates for each of the
// four corners, starting at the top-left-hand corner of
// the rectangle, going clockwise. Rotations are handled
// by shifting the UV values For example, rotation by 90
// degrees would see each uv value shifted to the right
// by 1, and the uv at index 3 would wrap around to index
// 0. Rotations by 180 and 270 degrees work similary, with
// shifts of 2 and 3 respectively, instead of 1. Flipping
// the renderable about an axis can be accomplished by
// swapping UV values. For example, a horizontal flip is
// done by swapping uvs at indices 0 and 1, and at indices
// 2 and 3. A vertical flip is accomplished by swapping uvs
// at indices 0 and 3, and 1 and 2.
using ClockwiseUVs = std::array<vec2, 4>;
RectangleSourceSpec()
: uv_top_left(vec2(0, 0)),
uv_top_right(vec2(1, 0)),
uv_bottom_right(vec2(1, 1)),
uv_bottom_left(vec2(0, 1)) {}
RectangleSourceSpec(const ClockwiseUVs& uvs) : uv_coordinates_clockwise(uvs) {}
union {
struct {
vec2 uv_top_left;
vec2 uv_top_right;
vec2 uv_bottom_right;
vec2 uv_bottom_left;
};
// Clockwise starting at top-left.
ClockwiseUVs uv_coordinates_clockwise;
};
};
// Struct representing a rectangle renderable's
// dimensions on a screen. The origin represents
// the top-left-hand corner and the extent is the
// width and height. Values are given in pixels.
struct RectangleDestinationSpec {
vec2 origin = vec2(0, 0);
vec2 extent = vec2(0, 0);
};
// Struct representing a complete Rectangle Renderable.
// It contains both source and destination specs, a
// texture, a multiply color, and bool for transparency.
struct RectangleRenderable {
RectangleSourceSpec source;
RectangleDestinationSpec dest;
// Renderer never holds onto this pointer.
Texture* texture = nullptr;
vec4 color = vec4(1, 1, 1, 1);
// If this bool is false, the renderable will render
// as if it is opaque, even if its color or texture
// has an alpha value less than 1.
bool is_transparent = false;
// Ensures that a RectangleRenderable has valid data that can be used
// for rendering. This means making sure it has a valid texture, and
// the the range values for its uv coordinates, extent and multiply
// color are all within expected ranges.
static bool IsValid(const RectangleRenderable& renderable,
bool ignore_texture_for_testing = false);
// Rotates a rectangle renderable by the specified number of degrees, and then
// translates it so that it has the same top-left origin as the unrotated rect.
// In other words, this function leaves }renderable->dest.origin| unchanged. The
// resulting renderable is output to the same renderable provided. Rotations
// must be in multiples of 90 degrees.
// Returns true if the rotation was successful and false if there was some
// error such as providing a null renderable or a degree value that is not a
// multiple of 90.
static void Rotate(RectangleRenderable* renderable, uint32_t degrees);
// Mirrors the renderable across the vertical line through the destination
// rectangle's midpoint. This is done by mutating |renderable|, leaving the "dest"
// rectangle unchanged and modifying the "source" UV cooridnates.
static void FlipHorizontally(RectangleRenderable* renderable);
// Mirrors the renderable across the horizontal line through the destination
// rectangle's midpoint. This is done by mutating |renderable|, leaving the "dest"
// rectangle unchanged and modifying the "source" UV cooridnates.
// NOTE: flipping vertically is equivalent to rotating by 180 degrees and then
// flipping horizontally.
static void FlipVertically(RectangleRenderable* renderable);
};
} // namespace escher
#endif // SRC_UI_LIB_ESCHER_FLATLAND_RECTANGLE_RENDERABLE_H_