Fix Rect coordinate space

This commit is contained in:
mars 2022-11-05 15:00:51 -06:00
parent 681b884b74
commit eb32163b24
4 changed files with 84 additions and 109 deletions

View File

@ -305,10 +305,10 @@ impl DrawContext {
rect
};
let v1 = rect.bl;
let v2 = Vec2::new(rect.bl.x, rect.tr.y);
let v3 = Vec2::new(rect.tr.x, rect.bl.y);
let v4 = rect.tr;
let v1 = rect.tl;
let v2 = Vec2::new(rect.tl.x, rect.br.y);
let v3 = Vec2::new(rect.br.x, rect.tl.y);
let v4 = rect.br;
self.draw_triangle_noclip(v1, v2, v3, color);
self.draw_triangle_noclip(v2, v3, v4, color);
@ -333,47 +333,48 @@ impl DrawContext {
let mut inner_rect = rect;
let inset = rect.inset(radius);
if corners.intersects(CornerFlags::TOP) {
inner_rect.tl.y += radius;
let mut top_edge = Rect {
tl: rect.tl,
br: Vec2::new(rect.br.x, rect.tl.y + radius),
};
if corners.contains(CornerFlags::TOP_LEFT) {
top_edge.tl.x += radius;
self.draw_quarter_circle(Corner::TopLeft, inset.tl, radius, color);
}
if corners.contains(CornerFlags::TOP_RIGHT) {
top_edge.br.x -= radius;
self.draw_quarter_circle(Corner::TopRight, inset.tr(), radius, color);
}
self.draw_rect(top_edge, color);
}
if corners.intersects(CornerFlags::BOTTOM) {
inner_rect.bl.y += radius;
inner_rect.br.y -= radius;
let mut bottom_edge = Rect {
bl: rect.bl,
tr: Vec2::new(rect.tr.x, rect.bl.y + radius),
tl: Vec2::new(rect.tl.x, rect.br.y - radius),
br: rect.br,
};
if corners.contains(CornerFlags::BOTTOM_LEFT) {
bottom_edge.bl.x += radius;
self.draw_quarter_circle(Corner::BottomLeft, inset.bl, radius, color);
bottom_edge.tl.x += radius;
self.draw_quarter_circle(Corner::BottomLeft, inset.bl(), radius, color);
}
if corners.contains(CornerFlags::BOTTOM_RIGHT) {
bottom_edge.tr.x -= radius;
self.draw_quarter_circle(Corner::BottomRight, inset.br(), radius, color);
bottom_edge.br.x -= radius;
self.draw_quarter_circle(Corner::BottomRight, inset.br, radius, color);
}
self.draw_rect(bottom_edge, color);
}
if corners.intersects(CornerFlags::TOP) {
inner_rect.tr.y -= radius;
let mut top_edge = Rect {
bl: Vec2::new(rect.bl.x, rect.tr.y - radius),
tr: rect.tr,
};
if corners.contains(CornerFlags::TOP_LEFT) {
top_edge.bl.x += radius;
self.draw_quarter_circle(Corner::TopLeft, inset.tl(), radius, color);
}
if corners.contains(CornerFlags::TOP_RIGHT) {
top_edge.tr.x -= radius;
self.draw_quarter_circle(Corner::TopRight, inset.tr, radius, color);
}
self.draw_rect(top_edge, color);
}
self.draw_rect(inner_rect, color);
}

View File

@ -11,78 +11,78 @@ pub mod api;
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Pod, Zeroable)]
pub struct Rect {
pub bl: Vec2,
pub tr: Vec2,
pub tl: Vec2,
pub br: Vec2,
}
impl Rect {
pub const NEG_INFINITY: Self = Self {
bl: Vec2::splat(f32::INFINITY),
tr: Vec2::splat(f32::NEG_INFINITY),
tl: Vec2::splat(f32::INFINITY),
br: Vec2::splat(f32::NEG_INFINITY),
};
pub fn from_xy_size(xy: Vec2, size: Vec2) -> Self {
Self {
bl: xy,
tr: xy + size,
tl: xy,
br: xy + size,
}
}
pub fn from_circle_bounds(center: Vec2, radius: f32) -> Self {
Self {
bl: center - radius,
tr: center + radius,
tl: center - radius,
br: center + radius,
}
}
pub fn from_triangle_bounds(tri: &ColoredTriangle) -> Self {
Self {
bl: tri.v1.min(tri.v2).min(tri.v3),
tr: tri.v1.max(tri.v2).max(tri.v3),
tl: tri.v1.min(tri.v2).min(tri.v3),
br: tri.v1.max(tri.v2).max(tri.v3),
}
}
pub fn inset(&self, d: f32) -> Self {
Self {
bl: self.bl + d,
tr: self.tr - d,
tl: self.tl + d,
br: self.br - d,
}
}
pub fn tl(&self) -> Vec2 {
Vec2::new(self.bl.x, self.tr.y)
pub fn bl(&self) -> Vec2 {
Vec2::new(self.tl.x, self.br.y)
}
pub fn br(&self) -> Vec2 {
Vec2::new(self.tr.x, self.bl.y)
pub fn tr(&self) -> Vec2 {
Vec2::new(self.br.x, self.tl.y)
}
pub fn offset(&self, offset: Vec2) -> Self {
Self {
bl: self.bl + offset,
tr: self.tr + offset,
tl: self.tl + offset,
br: self.br + offset,
}
}
pub fn scale(&self, scale: f32) -> Self {
Self {
bl: self.bl * scale,
tr: self.tr * scale,
tl: self.tl * scale,
br: self.br * scale,
}
}
pub fn is_valid(&self) -> bool {
self.bl.cmplt(self.tr).all()
self.tl.cmplt(self.br).all()
}
pub fn intersects_rect(&self, other: &Self) -> bool {
self.bl.cmple(other.tr).all() && self.tr.cmpge(other.bl).all()
self.tl.cmple(other.br).all() && self.br.cmpge(other.tl).all()
}
pub fn intersection(&self, other: &Self) -> Option<Self> {
let clipped = Self {
bl: self.bl.max(other.bl),
tr: self.tr.min(other.tr),
tl: self.tl.max(other.tl),
br: self.br.min(other.br),
};
if clipped.is_valid() {
@ -92,27 +92,41 @@ impl Rect {
}
}
pub fn union(&self, other: &Self) -> Self {
Self {
tl: self.tl.min(other.tl),
br: self.br.max(other.br),
}
}
pub fn union_point(&self, point: Vec2) -> Self {
Self {
tl: self.tl.min(point),
br: self.br.max(point),
}
}
pub fn contains_rect(&self, other: &Self) -> bool {
self.bl.x < other.bl.x
&& self.bl.y < other.bl.y
&& self.tr.x > other.tr.x
&& self.tr.y > other.tr.y
self.tl.x < other.tl.x
&& self.tl.y < other.tl.y
&& self.br.x > other.br.x
&& self.br.y > other.br.y
}
pub fn contains_point(&self, xy: Vec2) -> bool {
self.bl.x < xy.x && self.bl.y < xy.y && self.tr.x > xy.x && self.tr.y > xy.y
self.tl.x < xy.x && self.tl.y < xy.y && self.br.x > xy.x && self.br.y > xy.y
}
pub fn size(&self) -> Vec2 {
self.tr - self.bl
self.br - self.tl
}
pub fn width(&self) -> f32 {
self.tr.x - self.bl.x
self.br.x - self.tl.x
}
pub fn height(&self) -> f32 {
self.tr.y - self.bl.y
self.br.y - self.tl.y
}
}

View File

@ -133,26 +133,8 @@ impl OutlineSink {
fn pf_vector_to_lyon(&mut self, v: &Vector2F) -> lyon::geom::Point<f32> {
let point = lyon::geom::Point::<f32>::new(v.x(), -v.y()) / self.units_per_em;
// TODO clean this up with helper math methods?
let bb = &mut self.bounding_box;
if point.x < bb.bl.x {
bb.bl.x = point.x;
}
if point.x > bb.tr.x {
bb.tr.x = point.x;
}
if point.y < bb.tr.y {
bb.tr.y = point.y;
}
if point.y > bb.bl.y {
bb.bl.y = point.y;
}
let glam_point = Vec2::new(point.x, point.y);
self.bounding_box = self.bounding_box.union_point(glam_point);
point
}
}

View File

@ -73,31 +73,9 @@ impl Font {
xcur += position.hori_advance;
ycur += position.vert_advance;
let xpos = xpos as f32 / units_per_em;
let ypos = ypos as f32 / units_per_em;
let mut bb = glyphs.get(position.index as usize).unwrap().bounding_box;
bb.bl.x = bb.bl.x + xpos;
bb.bl.y = bb.bl.y + ypos;
bb.tr.x = bb.tr.x + xpos;
bb.tr.y = bb.tr.y + ypos;
// TODO use euclid instead
if bounds.bl.x > bb.bl.x {
bounds.bl.x = bb.bl.x;
}
if bounds.bl.y > bb.bl.y {
bounds.bl.y = bb.bl.y;
}
if bounds.tr.x < bb.tr.x {
bounds.tr.x = bb.tr.x;
}
if bounds.tr.y < bb.tr.y {
bounds.tr.y = bb.tr.y;
}
let pos = Vec2::new(xpos as f32, ypos as f32) / units_per_em;
let bb = glyphs.get(position.index as usize).unwrap().bounding_box;
bounds = bounds.union(&bb.offset(pos));
}
TextLayout {