mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-01 02:18:12 +08:00
Improve text overlay styling and fix artboard label positioning bug (#2032)
* Improve text overlays * I can't test code
This commit is contained in:
@@ -83,6 +83,7 @@ pub const COLOR_OVERLAY_GREEN: &str = "#63ce63";
|
|||||||
pub const COLOR_OVERLAY_RED: &str = "#ef5454";
|
pub const COLOR_OVERLAY_RED: &str = "#ef5454";
|
||||||
pub const COLOR_OVERLAY_GRAY: &str = "#cccccc";
|
pub const COLOR_OVERLAY_GRAY: &str = "#cccccc";
|
||||||
pub const COLOR_OVERLAY_WHITE: &str = "#ffffff";
|
pub const COLOR_OVERLAY_WHITE: &str = "#ffffff";
|
||||||
|
pub const COLOR_OVERLAY_SNAP_BACKGROUND: &str = "#000000cc";
|
||||||
|
|
||||||
// Document
|
// Document
|
||||||
pub const DEFAULT_DOCUMENT_NAME: &str = "Untitled Document";
|
pub const DEFAULT_DOCUMENT_NAME: &str = "Untitled Document";
|
||||||
|
|||||||
@@ -384,11 +384,12 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
|
|||||||
|
|
||||||
let name = self.network_interface.frontend_display_name(&layer.to_node(), &[]);
|
let name = self.network_interface.frontend_display_name(&layer.to_node(), &[]);
|
||||||
|
|
||||||
let (scale, angle, translation) = self.metadata().document_to_viewport.to_scale_angle_translation();
|
let transform = self.metadata().document_to_viewport
|
||||||
let translation = translation + scale * bounds[0].min(bounds[1]) - DVec2::Y * 4.;
|
* DAffine2::from_translation(bounds[0].min(bounds[1]))
|
||||||
let transform = DAffine2::from_angle_translation(angle, translation);
|
* DAffine2::from_scale(DVec2::splat(self.document_ptz.zoom().recip()))
|
||||||
|
* DAffine2::from_translation(-DVec2::Y * 4.);
|
||||||
|
|
||||||
overlay_context.text_with_transform(&name, COLOR_OVERLAY_GRAY, None, transform, Pivot::BottomLeft);
|
overlay_context.text(&name, COLOR_OVERLAY_GRAY, None, transform, 0., [Pivot::Start, Pivot::End]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DocumentMessage::DuplicateSelectedLayers => {
|
DocumentMessage::DuplicateSelectedLayers => {
|
||||||
|
|||||||
@@ -247,52 +247,41 @@ impl OverlayContext {
|
|||||||
self.render_context.stroke();
|
self.render_context.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text(&self, text: &str, font_color: &str, background_color: Option<&str>, pos: DVec2) {
|
pub fn text(&self, text: &str, font_color: &str, background_color: Option<&str>, transform: DAffine2, padding: f64, pivot: [Pivot; 2]) {
|
||||||
let metrics = self.render_context.measure_text(text).expect("Failed to measure the text dimensions");
|
let metrics = self.render_context.measure_text(text).expect("Failed to measure the text dimensions");
|
||||||
let local_position = pos.round();
|
let x = match pivot[0] {
|
||||||
|
Pivot::Start => padding,
|
||||||
self.draw_text(background_color, local_position, metrics, font_color, text);
|
Pivot::Middle => -(metrics.actual_bounding_box_right() + metrics.actual_bounding_box_left()) / 2.,
|
||||||
}
|
Pivot::End => -padding - metrics.actual_bounding_box_right() + metrics.actual_bounding_box_left(),
|
||||||
|
};
|
||||||
pub fn text_with_transform(&self, text: &str, font_color: &str, background_color: Option<&str>, transform: DAffine2, origin: Pivot) {
|
let y = match pivot[1] {
|
||||||
let [a, b, c, d, e, f] = transform.to_cols_array();
|
Pivot::Start => padding + metrics.font_bounding_box_ascent() - metrics.font_bounding_box_descent(),
|
||||||
self.render_context.set_transform(a, b, c, d, e, f).expect("Failed to rotate the render context to the specified angle");
|
Pivot::Middle => (metrics.font_bounding_box_ascent() + metrics.font_bounding_box_descent()) / 2.,
|
||||||
|
Pivot::End => -padding,
|
||||||
let metrics = self.render_context.measure_text(text).expect("Failed to measure the text dimensions");
|
|
||||||
let local_position = match origin {
|
|
||||||
Pivot::CenterLeft => DVec2::new(0., (metrics.actual_bounding_box_ascent() + metrics.actual_bounding_box_descent()) / 2.),
|
|
||||||
Pivot::TopCenter => DVec2::new(-(metrics.actual_bounding_box_right() + metrics.actual_bounding_box_left()) / 2., metrics.font_bounding_box_ascent()),
|
|
||||||
Pivot::BottomLeft => DVec2::ZERO,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.draw_text(background_color, local_position, metrics, font_color, text);
|
let [a, b, c, d, e, f] = (transform * DAffine2::from_translation(DVec2::new(x, y))).to_cols_array();
|
||||||
|
self.render_context.set_transform(a, b, c, d, e, f).expect("Failed to rotate the render context to the specified angle");
|
||||||
|
|
||||||
self.render_context.reset_transform().expect("Failed to reset the render context transform");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_text(&self, background_color: Option<&str>, local_position: DVec2, metrics: web_sys::TextMetrics, font_color: &str, text: &str) {
|
|
||||||
// Render background
|
|
||||||
if let Some(background) = background_color {
|
if let Some(background) = background_color {
|
||||||
self.render_context.set_fill_style_str(background);
|
self.render_context.set_fill_style_str(background);
|
||||||
self.render_context.fill_rect(
|
self.render_context.fill_rect(
|
||||||
local_position.x + metrics.actual_bounding_box_left(),
|
-padding,
|
||||||
local_position.y - metrics.font_bounding_box_ascent() - metrics.font_bounding_box_descent(),
|
padding,
|
||||||
metrics.actual_bounding_box_right() - metrics.actual_bounding_box_left(),
|
metrics.actual_bounding_box_right() - metrics.actual_bounding_box_left() + padding * 2.,
|
||||||
metrics.font_bounding_box_ascent() + metrics.font_bounding_box_descent(),
|
metrics.font_bounding_box_descent() - metrics.font_bounding_box_ascent() - padding * 2.,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render text
|
|
||||||
self.render_context.set_font("12px Source Sans Pro, Arial, sans-serif");
|
self.render_context.set_font("12px Source Sans Pro, Arial, sans-serif");
|
||||||
self.render_context.set_fill_style_str(font_color);
|
self.render_context.set_fill_style_str(font_color);
|
||||||
self.render_context
|
self.render_context.fill_text(text, 0., 0.).expect("Failed to draw the text at the calculated position");
|
||||||
.fill_text(text, local_position.x, local_position.y - metrics.font_bounding_box_descent())
|
self.render_context.reset_transform().expect("Failed to reset the render context transform");
|
||||||
.expect("Failed to draw the text on the canvas");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Pivot {
|
pub enum Pivot {
|
||||||
TopCenter,
|
Start,
|
||||||
CenterLeft,
|
Middle,
|
||||||
BottomLeft,
|
End,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::consts::COLOR_OVERLAY_BLUE;
|
use crate::consts::COLOR_OVERLAY_BLUE;
|
||||||
use crate::messages::portfolio::document::overlays::utility_types::{self, OverlayContext};
|
use crate::messages::portfolio::document::overlays::utility_types::{OverlayContext, Pivot};
|
||||||
use crate::messages::tool::tool_messages::tool_prelude::*;
|
use crate::messages::tool::tool_messages::tool_prelude::*;
|
||||||
|
|
||||||
use graphene_std::renderer::Rect;
|
use graphene_std::renderer::Rect;
|
||||||
@@ -25,7 +25,7 @@ pub fn overlay(selected_bounds: Rect, hovered_bounds: Rect, transform: DAffine2,
|
|||||||
let length = format!("{:.2}", transform_to_document.transform_vector2(DVec2::X * (turn_x - selected_x)).length());
|
let length = format!("{:.2}", transform_to_document.transform_vector2(DVec2::X * (turn_x - selected_x)).length());
|
||||||
let direction = -(min_viewport - max_viewport).normalize_or_zero();
|
let direction = -(min_viewport - max_viewport).normalize_or_zero();
|
||||||
let transform = DAffine2::from_translation((min_viewport + max_viewport) / 2.) * DAffine2::from_angle(-direction.angle_to(DVec2::X));
|
let transform = DAffine2::from_translation((min_viewport + max_viewport) / 2.) * DAffine2::from_angle(-direction.angle_to(DVec2::X));
|
||||||
overlay_context.text_with_transform(&length, COLOR_OVERLAY_BLUE, None, transform, utility_types::Pivot::TopCenter);
|
overlay_context.text(&length, COLOR_OVERLAY_BLUE, None, transform, 5., [Pivot::Middle, Pivot::Start]);
|
||||||
}
|
}
|
||||||
if turn_y != hovered_y {
|
if turn_y != hovered_y {
|
||||||
let min_viewport = transform.transform_point2(DVec2::new(turn_x, turn_y.min(hovered_y)));
|
let min_viewport = transform.transform_point2(DVec2::new(turn_x, turn_y.min(hovered_y)));
|
||||||
@@ -34,6 +34,6 @@ pub fn overlay(selected_bounds: Rect, hovered_bounds: Rect, transform: DAffine2,
|
|||||||
let length = format!("{:.2}", transform_to_document.transform_vector2(DVec2::Y * (turn_y - hovered_y)).length());
|
let length = format!("{:.2}", transform_to_document.transform_vector2(DVec2::Y * (turn_y - hovered_y)).length());
|
||||||
let direction = (min_viewport - max_viewport).normalize_or_zero().perp();
|
let direction = (min_viewport - max_viewport).normalize_or_zero().perp();
|
||||||
let transform = DAffine2::from_translation((min_viewport + max_viewport) / 2.) * DAffine2::from_angle(-direction.angle_to(DVec2::X));
|
let transform = DAffine2::from_translation((min_viewport + max_viewport) / 2.) * DAffine2::from_angle(-direction.angle_to(DVec2::X));
|
||||||
overlay_context.text_with_transform(&length, COLOR_OVERLAY_BLUE, None, transform, utility_types::Pivot::CenterLeft);
|
overlay_context.text(&length, COLOR_OVERLAY_BLUE, None, transform, 5., [Pivot::Start, Pivot::Middle]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ mod layer_snapper;
|
|||||||
mod snap_results;
|
mod snap_results;
|
||||||
pub use {alignment_snapper::*, distribution_snapper::*, grid_snapper::*, layer_snapper::*, snap_results::*};
|
pub use {alignment_snapper::*, distribution_snapper::*, grid_snapper::*, layer_snapper::*, snap_results::*};
|
||||||
|
|
||||||
use crate::consts::{COLOR_OVERLAY_BLUE, COLOR_OVERLAY_WHITE};
|
use crate::consts::{COLOR_OVERLAY_BLUE, COLOR_OVERLAY_SNAP_BACKGROUND, COLOR_OVERLAY_WHITE};
|
||||||
use crate::messages::portfolio::document::overlays::utility_types::OverlayContext;
|
use crate::messages::portfolio::document::overlays::utility_types::{OverlayContext, Pivot};
|
||||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||||
use crate::messages::portfolio::document::utility_types::misc::{BoundingBoxSnapTarget, GeometrySnapTarget, GridSnapTarget, SnapTarget};
|
use crate::messages::portfolio::document::utility_types::misc::{BoundingBoxSnapTarget, GeometrySnapTarget, GridSnapTarget, SnapTarget};
|
||||||
use crate::messages::prelude::*;
|
use crate::messages::prelude::*;
|
||||||
@@ -467,7 +467,8 @@ impl SnapManager {
|
|||||||
|
|
||||||
if !any_align && ind.distribution_equal_distance_x.is_none() && ind.distribution_equal_distance_y.is_none() {
|
if !any_align && ind.distribution_equal_distance_x.is_none() && ind.distribution_equal_distance_y.is_none() {
|
||||||
let text = format!("{:?} to {:?}", ind.source, ind.target);
|
let text = format!("{:?} to {:?}", ind.source, ind.target);
|
||||||
overlay_context.text(&text, COLOR_OVERLAY_BLUE, Some(COLOR_OVERLAY_WHITE), viewport - DVec2::new(0., 5.));
|
let transform = DAffine2::from_translation(viewport - DVec2::new(0., 5.));
|
||||||
|
overlay_context.text(&text, COLOR_OVERLAY_WHITE, Some(COLOR_OVERLAY_SNAP_BACKGROUND), transform, 5., [Pivot::Start, Pivot::End]);
|
||||||
overlay_context.square(viewport, Some(4.), Some(COLOR_OVERLAY_BLUE), Some(COLOR_OVERLAY_BLUE));
|
overlay_context.square(viewport, Some(4.), Some(COLOR_OVERLAY_BLUE), Some(COLOR_OVERLAY_BLUE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user