text.rs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use async_trait::async_trait;
  19. use rand::{rngs::OsRng, Rng};
  20. use std::sync::{Arc, Mutex as SyncMutex, OnceLock, Weak};
  21. use crate::{
  22. gfx::{
  23. GfxDrawCall, GfxDrawInstruction, GfxDrawMesh, GfxTextureId, ManagedTexturePtr, Rectangle,
  24. RenderApi,
  25. },
  26. mesh::{Color, MeshBuilder, MeshInfo, COLOR_BLUE, COLOR_RED, COLOR_WHITE},
  27. prop::{
  28. PropertyBool, PropertyColor, PropertyFloat32, PropertyPtr, PropertyRect, PropertyStr,
  29. PropertyUint32, Role,
  30. },
  31. scene::{Pimpl, SceneNodePtr, SceneNodeWeak},
  32. text::{self, GlyphPositionIter, TextShaper, TextShaperPtr},
  33. util::unixtime,
  34. ExecutorPtr,
  35. };
  36. use super::{DrawUpdate, OnModify, UIObject};
  37. pub type TextPtr = Arc<Text>;
  38. #[derive(Clone)]
  39. struct TextRenderInfo {
  40. mesh: MeshInfo,
  41. texture: ManagedTexturePtr,
  42. }
  43. pub struct Text {
  44. node: SceneNodeWeak,
  45. render_api: RenderApi,
  46. text_shaper: TextShaperPtr,
  47. tasks: OnceLock<Vec<smol::Task<()>>>,
  48. dc_key: u64,
  49. rect: PropertyRect,
  50. z_index: PropertyUint32,
  51. text: PropertyStr,
  52. font_size: PropertyFloat32,
  53. text_color: PropertyColor,
  54. baseline: PropertyFloat32,
  55. debug: PropertyBool,
  56. window_scale: PropertyFloat32,
  57. parent_rect: SyncMutex<Option<Rectangle>>,
  58. }
  59. impl Text {
  60. pub async fn new(
  61. node: SceneNodeWeak,
  62. window_scale: PropertyFloat32,
  63. render_api: RenderApi,
  64. text_shaper: TextShaperPtr,
  65. ex: ExecutorPtr,
  66. ) -> Pimpl {
  67. debug!(target: "ui::text", "Text::new()");
  68. let node_ref = &node.upgrade().unwrap();
  69. let rect = PropertyRect::wrap(node_ref, Role::Internal, "rect").unwrap();
  70. let z_index = PropertyUint32::wrap(node_ref, Role::Internal, "z_index", 0).unwrap();
  71. let text = PropertyStr::wrap(node_ref, Role::Internal, "text", 0).unwrap();
  72. let font_size = PropertyFloat32::wrap(node_ref, Role::Internal, "font_size", 0).unwrap();
  73. let text_color = PropertyColor::wrap(node_ref, Role::Internal, "text_color").unwrap();
  74. let baseline = PropertyFloat32::wrap(node_ref, Role::Internal, "baseline", 0).unwrap();
  75. let debug = PropertyBool::wrap(node_ref, Role::Internal, "debug", 0).unwrap();
  76. let node_name = node_ref.name.clone();
  77. let node_id = node_ref.id;
  78. let self_ = Arc::new(Self {
  79. node,
  80. render_api,
  81. text_shaper,
  82. tasks: OnceLock::new(),
  83. dc_key: OsRng.gen(),
  84. rect,
  85. z_index,
  86. text,
  87. font_size,
  88. text_color,
  89. baseline,
  90. debug,
  91. window_scale,
  92. parent_rect: SyncMutex::new(None),
  93. });
  94. Pimpl::Text(self_)
  95. }
  96. fn regen_mesh(&self) -> TextRenderInfo {
  97. let text = self.text.get();
  98. let font_size = self.font_size.get();
  99. let text_color = self.text_color.get();
  100. let baseline = self.baseline.get();
  101. let debug = self.debug.get();
  102. let window_scale = self.window_scale.get();
  103. debug!(target: "ui::text", "Rendering label '{}'", text);
  104. let glyphs = self.text_shaper.shape(text, font_size, window_scale);
  105. let atlas = text::make_texture_atlas(&self.render_api, &glyphs);
  106. let mut mesh = MeshBuilder::new();
  107. let glyph_pos_iter = GlyphPositionIter::new(font_size, window_scale, &glyphs, baseline);
  108. for (mut glyph_rect, glyph) in glyph_pos_iter.zip(glyphs.iter()) {
  109. let uv_rect = atlas.fetch_uv(glyph.glyph_id).expect("missing glyph UV rect");
  110. if debug {
  111. mesh.draw_outline(&glyph_rect, COLOR_BLUE, 2.);
  112. }
  113. let mut color = text_color.clone();
  114. if glyph.sprite.has_color {
  115. color = COLOR_WHITE;
  116. }
  117. mesh.draw_box(&glyph_rect, color, uv_rect);
  118. }
  119. if debug {
  120. let mut rect = self.rect.get();
  121. rect.x = 0.;
  122. rect.y = 0.;
  123. mesh.draw_outline(&rect, COLOR_RED, 1.);
  124. }
  125. let mesh = mesh.alloc(&self.render_api);
  126. TextRenderInfo { mesh, texture: atlas.texture }
  127. }
  128. async fn redraw(self: Arc<Self>) {
  129. let timest = unixtime();
  130. debug!(target: "ui::text", "Text::redraw({:?})", self.node.upgrade().unwrap());
  131. let Some(parent_rect) = self.parent_rect.lock().unwrap().clone() else { return };
  132. let Some(draw_update) = self.get_draw_calls(parent_rect).await else {
  133. error!(target: "ui::text", "Text failed to draw");
  134. return;
  135. };
  136. self.render_api.replace_draw_calls(timest, draw_update.draw_calls);
  137. debug!(target: "ui::text", "replace draw calls done");
  138. }
  139. async fn get_draw_calls(&self, parent_rect: Rectangle) -> Option<DrawUpdate> {
  140. self.rect.eval(&parent_rect).ok()?;
  141. let rect = self.rect.get();
  142. let render_info = self.regen_mesh();
  143. let mesh = GfxDrawMesh {
  144. vertex_buffer: render_info.mesh.vertex_buffer,
  145. index_buffer: render_info.mesh.index_buffer,
  146. texture: Some(render_info.texture),
  147. num_elements: render_info.mesh.num_elements,
  148. };
  149. Some(DrawUpdate {
  150. key: self.dc_key,
  151. draw_calls: vec![(
  152. self.dc_key,
  153. GfxDrawCall {
  154. instrs: vec![
  155. GfxDrawInstruction::Move(rect.pos()),
  156. GfxDrawInstruction::Draw(mesh),
  157. ],
  158. dcs: vec![],
  159. z_index: self.z_index.get(),
  160. },
  161. )],
  162. })
  163. }
  164. }
  165. #[async_trait]
  166. impl UIObject for Text {
  167. fn z_index(&self) -> u32 {
  168. self.z_index.get()
  169. }
  170. async fn start(self: Arc<Self>, ex: ExecutorPtr) {
  171. let me = Arc::downgrade(&self);
  172. let node_ref = &self.node.upgrade().unwrap();
  173. let node_name = node_ref.name.clone();
  174. let node_id = node_ref.id;
  175. let mut on_modify = OnModify::new(ex, node_name, node_id, me.clone());
  176. on_modify.when_change(self.rect.prop(), Self::redraw);
  177. on_modify.when_change(self.z_index.prop(), Self::redraw);
  178. on_modify.when_change(self.text.prop(), Self::redraw);
  179. on_modify.when_change(self.font_size.prop(), Self::redraw);
  180. on_modify.when_change(self.text_color.prop(), Self::redraw);
  181. on_modify.when_change(self.debug.prop(), Self::redraw);
  182. on_modify.when_change(self.baseline.prop(), Self::redraw);
  183. self.tasks.set(on_modify.tasks);
  184. }
  185. async fn draw(&self, parent_rect: Rectangle) -> Option<DrawUpdate> {
  186. debug!(target: "ui::text", "Text::draw({:?})", self.node.upgrade().unwrap());
  187. *self.parent_rect.lock().unwrap() = Some(parent_rect);
  188. self.get_draw_calls(parent_rect).await
  189. }
  190. }
  191. impl Drop for Text {
  192. fn drop(&mut self) {
  193. self.render_api.replace_draw_calls(unixtime(), vec![(self.dc_key, Default::default())]);
  194. }
  195. }