diff --git a/CHANGELOG.md b/CHANGELOG.md
index 821beb28c02c..f2e4e1213ecf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -47,6 +47,12 @@
- [Fixed developer console error about failing to decode a notification
"executionContext/visualisationEvaluationFailed"][3193]
+#### EnsoGL (rendering engine)
+
+- [You can change font and set letters bold in the text::Area
+ component][3385]. Use the set_font
and
+ set_bold_bytes
respectively.
+
#### Enso Standard Library
- [Implemented `Vector.distinct` allowing to remove duplicate elements from a
@@ -152,6 +158,7 @@
[3379]: https://github.com/enso-org/enso/pull/3379
[3381]: https://github.com/enso-org/enso/pull/3381
[3383]: https://github.com/enso-org/enso/pull/3383
+[3385]: https://github.com/enso-org/enso/pull/3385
[3392]: https://github.com/enso-org/enso/pull/3392
#### Enso Compiler
diff --git a/Cargo.lock b/Cargo.lock
index cf0b88b1a48e..4406bfc8e182 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -565,6 +565,26 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "const_format"
+version = "0.2.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22bc6cd49b0ec407b680c3e380182b6ac63b73991cb7602de350352fc309b614"
+dependencies = [
+ "const_format_proc_macros",
+]
+
+[[package]]
+name = "const_format_proc_macros"
+version = "0.2.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef196d5d972878a48da7decb7686eded338b4858fbabeed513d63a7c98b2b82d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
[[package]]
name = "convert_case"
version = "0.4.0"
@@ -1679,6 +1699,7 @@ dependencies = [
name = "ensogl-text"
version = "0.1.0"
dependencies = [
+ "const_format",
"enso-frp",
"enso-prelude",
"enso-shapely",
diff --git a/lib/rust/ensogl/component/text/Cargo.toml b/lib/rust/ensogl/component/text/Cargo.toml
index 6327a66b9116..e32eb66fefbd 100644
--- a/lib/rust/ensogl/component/text/Cargo.toml
+++ b/lib/rust/ensogl/component/text/Cargo.toml
@@ -17,6 +17,7 @@ ensogl-core = { path = "../../core" }
ensogl-text-embedded-fonts = { path = "embedded-fonts" }
ensogl-text-msdf-sys = { path = "msdf-sys" }
ensogl-hardcoded-theme = { path = "../../app/theme/hardcoded" }
+const_format = "0.2.22"
xi-rope = { version = "0.3.0" }
[dev-dependencies]
diff --git a/lib/rust/ensogl/component/text/src/buffer/style.rs b/lib/rust/ensogl/component/text/src/buffer/style.rs
index 4323f66353e8..54fdaae3cc8e 100644
--- a/lib/rust/ensogl/component/text/src/buffer/style.rs
+++ b/lib/rust/ensogl/component/text/src/buffer/style.rs
@@ -225,6 +225,7 @@ def_style_property!(Size(f32));
def_style_property!(Bold(bool));
def_style_property!(Italic(bool));
def_style_property!(Underline(bool));
+def_style_property!(SdfBold(f32));
impl Default for Size {
fn default() -> Self {
@@ -247,12 +248,19 @@ impl Default for Underline {
}
}
+impl Default for SdfBold {
+ fn default() -> Self {
+ Self::new(0.0)
+ }
+}
+
define_styles! {
size : Size,
color : color::Rgba,
bold : Bold,
italics : Italic,
underline : Underline,
+ sdf_bold : SdfBold,
}
diff --git a/lib/rust/ensogl/component/text/src/buffer/view.rs b/lib/rust/ensogl/component/text/src/buffer/view.rs
index c1048f16d667..2a1816efe013 100644
--- a/lib/rust/ensogl/component/text/src/buffer/view.rs
+++ b/lib/rust/ensogl/component/text/src/buffer/view.rs
@@ -368,7 +368,8 @@ ensogl_core::define_endpoints! {
redo (),
set_default_color (color::Rgba),
set_default_text_size (style::Size),
- set_color_bytes (buffer::Range,color::Rgba),
+ set_color_bytes (buffer::Range, color::Rgba),
+ set_sdf_bold (buffer::Range, style::SdfBold),
}
Output {
@@ -449,6 +450,7 @@ impl View {
eval input.set_default_color ((t) m.set_default(*t));
eval input.set_default_text_size ((t) m.set_default(*t));
eval input.set_color_bytes (((range,color)) m.replace(range,*color));
+ eval input.set_sdf_bold (((range,value)) m.replace(range,*value));
eval input.set_default_color ((color) m.set_default(*color));
output.source.selection_edit_mode <+ sel_on_modification;
diff --git a/lib/rust/ensogl/component/text/src/component/area.rs b/lib/rust/ensogl/component/text/src/component/area.rs
index 07dd11d35573..137143614fd4 100644
--- a/lib/rust/ensogl/component/text/src/component/area.rs
+++ b/lib/rust/ensogl/component/text/src/component/area.rs
@@ -260,9 +260,16 @@ ensogl_core::define_endpoints! {
insert (String),
set_color_bytes (buffer::Range,color::Rgba),
set_color_all (color::Rgba),
+ set_sdf_bold (buffer::Range,style::SdfBold),
set_default_color (color::Rgba),
set_selection_color (color::Rgb),
set_default_text_size (style::Size),
+ /// Set font in the text area. The name will be looked up in [`typeface::font::Registry`].
+ ///
+ /// Note, that this is a relatively heavy operation - it requires not only redrawing all
+ /// lines, but also re-load internal structures for rendering (like WebGL buffers,
+ /// MSDF texture, etc.).
+ set_font (String),
set_content (String),
}
Output {
@@ -474,6 +481,11 @@ impl Area {
input.remove_all_cursors();
});
+ // === Font ===
+
+ eval input.set_font ((t) m.set_font(t));
+
+
// === Colors ===
eval input.set_default_color ((t) m.buffer.frp.set_default_color(*t));
@@ -495,6 +507,13 @@ impl Area {
});
self.frp.source.selection_color <+ self.frp.set_selection_color;
+
+ // === Style ===
+
+ m.buffer.frp.set_sdf_bold <+ input.set_sdf_bold;
+ eval_ input.set_sdf_bold (m.redraw(false));
+
+
// === Changes ===
// The `content` event should be fired first, as any listener for `changed` may want to
@@ -545,7 +564,7 @@ impl Area {
#[cfg(target_arch = "wasm32")]
fn symbols(&self) -> SmallVec<[display::Symbol; 1]> {
- let text_symbol = self.data.glyph_system.sprite_system().symbol.clone_ref();
+ let text_symbol = self.data.glyph_system.borrow().sprite_system().symbol.clone_ref();
let shapes = &self.data.app.display.default_scene.shapes;
let selection_system = shapes.shape_system(PhantomData::);
let _selection_symbol = selection_system.shape_system.symbol.clone_ref();
@@ -573,7 +592,7 @@ pub struct AreaModel {
buffer: buffer::View,
display_object: display::object::Instance,
#[cfg(target_arch = "wasm32")]
- glyph_system: glyph::System,
+ glyph_system: Rc>,
lines: Lines,
single_line: Rc>,
selection_map: Rc>,
@@ -586,21 +605,20 @@ impl AreaModel {
let scene = &app.display.default_scene;
let logger = Logger::new("text_area");
let selection_map = default();
+ let display_object = display::object::Instance::new(&logger);
#[cfg(target_arch = "wasm32")]
let glyph_system = {
let fonts = scene.extension::();
let font = fonts.load("DejaVuSansMono");
- typeface::glyph::System::new(&scene, font)
+ let glyph_system = typeface::glyph::System::new(&scene, font);
+ display_object.add_child(&glyph_system);
+ Rc::new(RefCell::new(glyph_system))
};
- let display_object = display::object::Instance::new(&logger);
let buffer = default();
let lines = default();
let single_line = default();
let camera = Rc::new(CloneRefCell::new(scene.camera().clone_ref()));
- #[cfg(target_arch = "wasm32")]
- display_object.add_child(&glyph_system);
-
// FIXME[WD]: These settings should be managed wiser. They should be set up during
// initialization of the shape system, not for every area creation. To be improved during
// refactoring of the architecture some day.
@@ -792,12 +810,13 @@ impl AreaModel {
let line_object = line.display_object().clone_ref();
let line_range = self.buffer.byte_range_of_view_line_index_snapped(view_line_index.into());
let mut line_style = self.buffer.sub_style(line_range.start..line_range.end).iter();
- let mut pen = pen::Pen::new(&self.glyph_system.font);
+ let glyph_system = self.glyph_system.borrow();
+ let mut pen = pen::Pen::new(&glyph_system.font);
let mut divs = vec![];
let mut column = 0.column();
let mut last_cursor = None;
let mut last_cursor_target = default();
- line.resize_with(content.chars().count(), || self.glyph_system.new_glyph());
+ line.resize_with(content.chars().count(), || glyph_system.new_glyph());
let mut iter = line.glyphs.iter_mut().zip(content.chars());
loop {
let next = iter.next();
@@ -822,15 +841,16 @@ impl AreaModel {
Some((glyph, chr)) => {
let chr_bytes: Bytes = chr.len_utf8().into();
line_style.drop(chr_bytes - 1.bytes());
- let glyph_info = self.glyph_system.font.glyph_info(chr);
- let size = glyph_info.scale.scale(chr_size);
+ let glyph_info = glyph_system.font.glyph_info(chr);
let glyph_offset = glyph_info.offset.scale(chr_size);
let glyph_x = info.offset + glyph_offset.x;
let glyph_y = glyph_offset.y;
glyph.set_position_xy(Vector2(glyph_x, glyph_y));
glyph.set_char(chr);
glyph.set_color(style.color);
- glyph.size.set(size);
+ glyph.set_bold(style.bold.raw);
+ glyph.set_sdf_bold(style.sdf_bold.raw);
+ glyph.set_font_size(chr_size);
match &last_cursor {
None => line_object.add_child(glyph),
Some(cursor) => {
@@ -920,6 +940,24 @@ impl AreaModel {
let end = self.buffer.snap_location(selection.end);
selection.with_start(start).with_end(end)
}
+
+ #[cfg(target_arch = "wasm32")]
+ fn set_font(&self, font_name: &str) {
+ let app = &self.app;
+ let scene = &app.display.default_scene;
+ let fonts = scene.extension::();
+ let font = fonts.load(font_name);
+ let glyph_system = typeface::glyph::System::new(&scene, font);
+ self.display_object.add_child(&glyph_system);
+ let old_glyph_system = self.glyph_system.replace(glyph_system);
+ self.display_object.remove_child(&old_glyph_system);
+ // Remove old Glyph structures, as they still refer to the old Glyph System.
+ self.lines.rc.take();
+ self.redraw(true);
+ }
+
+ #[cfg(not(target_arch = "wasm32"))]
+ fn set_font(&self, _font_name: &str) {}
}
impl display::Object for AreaModel {
diff --git a/lib/rust/ensogl/component/text/src/typeface/glsl/glyph.glsl b/lib/rust/ensogl/component/text/src/typeface/glsl/glyph.glsl
index edadc18f570f..879671c7d4fc 100644
--- a/lib/rust/ensogl/component/text/src/typeface/glsl/glyph.glsl
+++ b/lib/rust/ensogl/component/text/src/typeface/glsl/glyph.glsl
@@ -1,8 +1,15 @@
+// A factor describing much the bold letters will be fattened, expressed as the fraction of font size.
+const float BOLD_FATTING = 0.04;
+
highp float median(highp vec3 v) {
return max(min(v.x, v.y), min(max(v.x, v.y), v.z));
}
-highp vec2 get_scaled_uv() {
+/// Compute the uv coordinates of the MSDF texture fragment where it should be sampled.
+///
+/// Essentially, it's an input_uv which is a bit transformed to "cut off" the half of the MSDF cell from each side. This
+/// way we have better pixel alignment on low resolutions.
+highp vec2 msdf_fragment_uv() {
highp vec2 msdf_cell_size = 1.0/input_msdf_size;
highp vec2 offset = msdf_cell_size/2.0;
highp vec2 scale = 1.0 - msdf_cell_size;
@@ -10,9 +17,17 @@ highp vec2 get_scaled_uv() {
}
highp vec2 get_texture_coord() {
- highp vec2 msdf_fragment_size = input_msdf_size / vec2(textureSize(input_atlas,0));
+ highp vec2 msdf_fragment_size = input_msdf_size / vec2(textureSize(input_atlas, 0));
highp vec2 offset = vec2(0.0, input_atlas_index) * msdf_fragment_size;
- return offset + get_scaled_uv() * msdf_fragment_size;
+ return offset + msdf_fragment_uv() * msdf_fragment_size;
+}
+
+highp float get_fatting() {
+ bool glyph_is_bold = (input_style & STYLE_BOLD_FLAG) != 0;
+ highp vec2 local_to_px_ratio = 1.0 / fwidth(input_local.xy);
+ highp float font_size_px = input_font_size * (local_to_px_ratio.x + local_to_px_ratio.y) / 2.0;
+ highp float fatting = (glyph_is_bold ? BOLD_FATTING : 0.0) + input_sdf_bold;
+ return font_size_px * fatting;
}
highp float msdf_alpha() {
@@ -23,12 +38,11 @@ highp float msdf_alpha() {
// We use this parameter to fatten somewhat font on low resolutions. The thershold and exact
// value of this fattening was picked by trial an error, searching for best rendering effect.
- highp float dpi_dilate = avg_msdf_unit_px < input_msdf_range*0.49 ? 1.0 : 0.0;
-
- highp vec3 msdf_sample = texture(input_atlas,tex_coord).rgb;
- highp float sig_dist = median(msdf_sample) - 0.5;
- highp float sig_dist_px = sig_dist * avg_msdf_unit_px;
- highp float opacity = 0.5 + sig_dist_px + dpi_dilate * 0.08;
+ highp float dpi_dilate = avg_msdf_unit_px < input_msdf_range*0.49 ? 1.0 : 0.0;
+ highp vec3 msdf_sample = texture(input_atlas,tex_coord).rgb;
+ highp float sig_dist = median(msdf_sample) - 0.5;
+ highp float sig_dist_px = sig_dist * avg_msdf_unit_px + get_fatting();
+ highp float opacity = 0.5 + sig_dist_px + dpi_dilate * 0.08;
opacity = clamp(opacity, 0.0, 1.0);
return opacity;
}
diff --git a/lib/rust/ensogl/component/text/src/typeface/glsl/glyph_mac.glsl b/lib/rust/ensogl/component/text/src/typeface/glsl/glyph_mac.glsl
index 113f9dd44bd4..da3880755c38 100644
--- a/lib/rust/ensogl/component/text/src/typeface/glsl/glyph_mac.glsl
+++ b/lib/rust/ensogl/component/text/src/typeface/glsl/glyph_mac.glsl
@@ -1,20 +1,36 @@
+// A factor describing much the bold letters will be fattened, expressed as the fraction of font size.
+const float BOLD_FATTING = 0.04;
+
highp float median(highp vec3 v) {
return max(min(v.x, v.y), min(max(v.x, v.y), v.z));
}
-highp vec2 get_scaled_uv() {
+/// Compute the uv coordinates of the MSDF texture fragment where it should be sampled.
+///
+/// Essentially, it's an input_uv which is a bit transformed to "cut off" the half of the MSDF cell from each side. This
+/// way we have better pixel alignment on low resolutions.
+highp vec2 msdf_fragment_uv() {
highp vec2 msdf_cell_size = 1.0/input_msdf_size;
highp vec2 offset = msdf_cell_size/2.0;
highp vec2 scale = 1.0 - msdf_cell_size;
return offset + input_uv * scale;
}
+
highp vec2 get_texture_coord() {
highp vec2 msdf_fragment_size = input_msdf_size / vec2(textureSize(input_atlas,0));
highp vec2 offset = vec2(0.0, input_atlas_index) * msdf_fragment_size;
return offset + get_scaled_uv() * msdf_fragment_size;
}
+highp float get_fatting() {
+ bool glyph_is_bold = (input_style & STYLE_BOLD_FLAG) != 0;
+ highp vec2 local_to_px_ratio = 1.0 / fwidth(input_local.xy);
+ highp float font_size_px = input_font_size * (local_to_px_ratio.x + local_to_px_ratio.y) / 2.0;
+ highp float fatting = (glyph_is_bold ? BOLD_FATTING : 0.0) + input_sdf_bold;
+ return font_size_px * fatting;
+}
+
// FIXME
// The following function uses non-standard font adjustiments (lines marked with FIXME). They make
// the font bolder and more crisp. It was designed to look nice on nodes in the GUI but leaves the
@@ -28,12 +44,11 @@ highp float msdf_alpha() {
// We use this parameter to fatten somewhat font on low resolutions. The thershold and exact
// value of this fattening was picked by trial an error, searching for best rendering effect.
- highp float dpi_dilate = avg_msdf_unit_px < input_msdf_range*0.49 ? 1.0 : 0.0;
-
- highp vec3 msdf_sample = texture(input_atlas,tex_coord).rgb;
- highp float sig_dist = median(msdf_sample) - 0.5;
- highp float sig_dist_px = sig_dist * avg_msdf_unit_px;
- highp float opacity = 0.5 + sig_dist_px + dpi_dilate * 0.08;
+ highp float dpi_dilate = avg_msdf_unit_px < input_msdf_range*0.49 ? 1.0 : 0.0;
+ highp vec3 msdf_sample = texture(input_atlas,tex_coord).rgb;
+ highp float sig_dist = median(msdf_sample) - 0.5;
+ highp float sig_dist_px = sig_dist * avg_msdf_unit_px + get_fatting();
+ highp float opacity = 0.5 + sig_dist_px + dpi_dilate * 0.08;
opacity += 0.6; // FIXME: Widen + sharpen
opacity = clamp(opacity, 0.0, 1.0);
opacity = pow(opacity,3.0); // FIXME: sharpen
diff --git a/lib/rust/ensogl/component/text/src/typeface/glyph.rs b/lib/rust/ensogl/component/text/src/typeface/glyph.rs
index a5ed1146cf66..8561822ed2d2 100644
--- a/lib/rust/ensogl/component/text/src/typeface/glyph.rs
+++ b/lib/rust/ensogl/component/text/src/typeface/glyph.rs
@@ -2,21 +2,36 @@
//! but can differ in all other aspects.
use crate::prelude::*;
-use ensogl_core::display::world::*;
-use super::font;
+use crate::typeface::font;
+
+use const_format::concatcp;
use ensogl_core::data::color::Rgba;
use ensogl_core::display;
use ensogl_core::display::layout::Alignment;
use ensogl_core::display::scene::Scene;
use ensogl_core::display::symbol::material::Material;
use ensogl_core::display::symbol::shader::builder::CodeTemplate;
+use ensogl_core::display::world::*;
use ensogl_core::system::gpu;
use ensogl_core::system::gpu::texture;
use font::Font;
use font::GlyphRenderInfo;
+// =================
+// === Constants ===
+// =================
+
+mod style_flag {
+ use const_format::concatcp;
+
+ pub const BOLD: i32 = 1 << 0;
+
+ pub const GLSL_DEFINITIONS: &str = concatcp!("const int STYLE_BOLD_FLAG = ", BOLD, ";\n");
+}
+
+
// =============
// === Glyph ===
@@ -25,17 +40,21 @@ use font::GlyphRenderInfo;
/// Glyph texture. Contains all letters encoded in MSDF format.
pub type Texture = gpu::Texture;
-/// A glyph rendered on screen. The displayed character will be stretched to fit the entire size of
-/// underlying sprite.
-#[derive(Clone, CloneRef, Debug, Shrinkwrap)]
+/// A glyph rendered on screen.
+///
+/// The underlying sprite's size is automatically adjusted depending on char and font size set.
+#[derive(Clone, CloneRef, Debug)]
pub struct Glyph {
- #[shrinkwrap(main_field)]
sprite: Sprite,
context: Context,
font: Font,
+ font_size: Attribute,
color: Attribute>,
+ style: Attribute,
+ sdf_bold: Attribute,
atlas_index: Attribute,
atlas: Uniform,
+ char: Rc>,
}
impl Glyph {
@@ -48,11 +67,40 @@ impl Glyph {
self.color.set(color.into().into())
}
+ pub fn is_bold(&self) -> bool {
+ self.style.get() & style_flag::BOLD != 0
+ }
+
+ pub fn set_bold(&self, value: bool) {
+ self.style.modify(|v| if value { *v |= style_flag::BOLD } else { *v &= !style_flag::BOLD });
+ }
+
+ pub fn sdf_bold(&self) -> f32 {
+ self.sdf_bold.get()
+ }
+
+ pub fn set_sdf_bold(&self, value: f32) {
+ self.sdf_bold.set(value);
+ }
+
+ pub fn font_size(&self) -> f32 {
+ self.font_size.get()
+ }
+
+ pub fn set_font_size(&self, size: f32) {
+ self.font_size.set(size);
+ let glyph_info = self.font.glyph_info(self.char.get());
+ self.sprite.size.set(glyph_info.scale.scale(size));
+ }
+
/// Change the displayed character.
pub fn set_char(&self, ch: char) {
+ self.char.set(ch);
let glyph_info = self.font.glyph_info(ch);
self.atlas_index.set(glyph_info.msdf_texture_glyph_id as f32);
self.update_msdf_texture();
+ let font_size = self.font_size();
+ self.sprite.size.set(glyph_info.scale.scale(font_size));
}
// FIXME: How does it work? Replace with better checking.
@@ -90,7 +138,10 @@ pub struct System {
context: Context,
sprite_system: SpriteSystem,
pub font: Font,
+ font_size: Buffer,
color: Buffer>,
+ style: Buffer,
+ sdf_bold: Buffer,
atlas_index: Buffer,
atlas: Uniform,
}
@@ -119,7 +170,10 @@ impl System {
sprite_system,
font,
atlas: symbol.variables().add_or_panic("atlas", texture),
+ font_size: mesh.instance_scope().add_buffer("font_size"),
color: mesh.instance_scope().add_buffer("color"),
+ style: mesh.instance_scope().add_buffer("style"),
+ sdf_bold: mesh.instance_scope().add_buffer("sdf_bold"),
atlas_index: mesh.instance_scope().add_buffer("atlas_index"),
}
}
@@ -130,13 +184,17 @@ impl System {
let context = self.context.clone();
let sprite = self.sprite_system.new_instance();
let instance_id = sprite.instance_id;
+ let font_size = self.font_size.at(instance_id);
let color = self.color.at(instance_id);
+ let style = self.style.at(instance_id);
+ let sdf_bold = self.sdf_bold.at(instance_id);
let atlas_index = self.atlas_index.at(instance_id);
let font = self.font.clone_ref();
let atlas = self.atlas.clone();
+ let char = default();
color.set(Vector4::new(0.0, 0.0, 0.0, 0.0));
atlas_index.set(0.0);
- Glyph { sprite, context, font, color, atlas_index, atlas }
+ Glyph { sprite, context, font, font_size, color, style, sdf_bold, atlas_index, atlas, char }
}
/// Get underlying sprite system.
@@ -154,9 +212,10 @@ impl display::Object for System {
// === Material ===
#[cfg(target_os = "macos")]
-const FUNCTIONS: &str = include_str!("glsl/glyph_mac.glsl");
+const FUNCTIONS: &str =
+ concatcp!(style_flag::GLSL_DEFINITIONS, include_str!("glsl/glyph_mac.glsl"));
#[cfg(not(target_os = "macos"))]
-const FUNCTIONS: &str = include_str!("glsl/glyph.glsl");
+const FUNCTIONS: &str = concatcp!(style_flag::GLSL_DEFINITIONS, include_str!("glsl/glyph.glsl"));
const MAIN: &str = "output_color = color_from_msdf(); output_id=vec4(0.0,0.0,0.0,0.0);";
@@ -170,7 +229,10 @@ impl System {
material.add_input("pixel_ratio", 1.0);
material.add_input("z_zoom_1", 1.0);
material.add_input("msdf_range", GlyphRenderInfo::MSDF_PARAMS.range as f32);
+ material.add_input("font_size", 10.0);
material.add_input("color", Vector4::new(0.0, 0.0, 0.0, 1.0));
+ material.add_input("style", 0);
+ material.add_input("sdf_bold", 0.0);
// FIXME We need to use this output, as we need to declare the same amount of shader
// FIXME outputs as the number of attachments to framebuffer. We should manage this more
// FIXME intelligent. For example, we could allow defining output shader fragments,
diff --git a/lib/rust/ensogl/example/glyph-system/src/lib.rs b/lib/rust/ensogl/example/glyph-system/src/lib.rs
index dd1b2aa8689f..6968396be39f 100644
--- a/lib/rust/ensogl/example/glyph-system/src/lib.rs
+++ b/lib/rust/ensogl/example/glyph-system/src/lib.rs
@@ -28,7 +28,7 @@ use wasm_bindgen::prelude::*;
use ensogl_core::data::color;
use ensogl_text_msdf_sys::run_once_initialized;
-
+const CHARS_TO_TEST: &[&str] = &["abcdqwerty", "ABCDQUERTY"];
/// Main example runner.
#[entry_point]
@@ -37,20 +37,41 @@ pub fn main() {
run_once_initialized(|| init(&World::new().displayed_in("root")));
}
+
fn init(world: &World) {
let fonts = world.default_scene.extension::();
let font = fonts.load("DejaVuSans");
let glyph_system = glyph::System::new(&world.default_scene, font);
let height = 32.0;
let color = color::Rgba::new(0.5, 0.0, 0.0, 1.0);
- let glyph = glyph_system.new_glyph();
- glyph.set_char('Q');
- glyph.set_color(color);
- glyph.size.set(Vector2(height, height));
+ let start_pos = Vector2(-300.0, -300.0);
+
+ for (line_ind, line) in CHARS_TO_TEST.iter().enumerate() {
+ for (char_ind, char) in line.chars().enumerate() {
+ let glyph = glyph_system.new_glyph();
+ let bold_glyph = glyph_system.new_glyph();
+ glyph.set_char(char);
+ glyph.set_color(color);
+ glyph.set_font_size(height);
+
+ bold_glyph.set_char(char);
+ bold_glyph.set_color(color);
+ bold_glyph.set_font_size(height);
+ bold_glyph.set_bold(true);
+
+ let x = char_ind as f32 * (height + 4.0);
+ let y = line_ind as f32 * (height * 2.0 + 8.0);
+ let bold_y = y + height + 4.0;
+ glyph.set_position_xy(start_pos + Vector2(x, y));
+ bold_glyph.set_position_xy(start_pos + Vector2(x, bold_y));
+ world.add_child(&glyph);
+ world.add_child(&bold_glyph);
+ std::mem::forget(glyph);
+ std::mem::forget(bold_glyph);
+ }
+ }
world.add_child(&glyph_system);
- world.add_child(&glyph);
world.keep_alive_forever();
std::mem::forget(glyph_system);
- std::mem::forget(glyph);
}
diff --git a/lib/rust/ensogl/example/text-area/src/lib.rs b/lib/rust/ensogl/example/text-area/src/lib.rs
index ed3d70d0608f..811200104da9 100644
--- a/lib/rust/ensogl/example/text-area/src/lib.rs
+++ b/lib/rust/ensogl/example/text-area/src/lib.rs
@@ -25,6 +25,8 @@ use wasm_bindgen::prelude::*;
use ensogl_core::application::Application;
use ensogl_core::display::navigation::navigator::Navigator;
+use ensogl_text::style;
+use ensogl_text::traits::*;
use ensogl_text::Area;
use ensogl_text_msdf_sys::run_once_initialized;
@@ -40,27 +42,35 @@ pub fn entry_point_text_area() {
}
fn init(app: Application) {
+ use ensogl_text::Bytes;
+ use ensogl_text::Range;
+
let area = app.new_view::();
area.set_position_x(-100.0);
- area.set_content(
- "Et Eärello Endorenna utúlien.\nSinome maruvan ar Hildinyar tenn' Ambar-metta",
- );
+ let quote = "Et Eärello Endorenna utúlien.\nSinome maruvan ar Hildinyar tenn' Ambar-metta\n";
+ let snowman = "\u{2603}";
+ let zalgo = "Z̮̞̠͙͔ͅḀ̗̞͈̻̗Ḷ͙͎̯̹̞͓G̻O̭̗̮";
+ let text = quote.to_string() + snowman + zalgo;
+ area.set_content(text.clone() + "\n" + text.as_str());
+ area.set_font("DejaVuSans");
area.focus();
area.hover();
area.set_cursor_at_end();
+ area.set_sdf_bold(Range::new(4.bytes(), 6.bytes()), style::SdfBold(0.02));
+ area.set_sdf_bold(Range::new(7.bytes(), 15.bytes()), style::SdfBold(0.04));
+ area.set_sdf_bold(Range::new(24.bytes(), 26.bytes()), style::SdfBold(0.02));
+ area.set_sdf_bold(Range::new(37.bytes(), 41.bytes()), style::SdfBold(0.05));
+ area.set_sdf_bold(Range::new(55.bytes(), 56.bytes()), style::SdfBold(0.03));
+ let quote_length = Bytes::from(quote.len());
+ let text_length = Bytes::from(text.len());
+ area.set_sdf_bold(Range::new(quote_length, text_length), style::SdfBold(0.02));
+
let scene = &app.display.default_scene;
let navigator = Navigator::new(scene, &scene.camera());
app.display.default_scene.add_child(&area);
- let keep = Some(area);
- app.display
- .on
- .before_frame
- .add(move |_frame| {
- let _ = &keep;
- })
- .forget();
mem::forget(navigator);
mem::forget(app);
+ mem::forget(area);
}
| |