1use api::{FontInstanceData, FontInstanceFlags, FontInstanceKey};
6use api::{FontInstanceOptions, FontInstancePlatformOptions};
7use api::{FontKey, FontRenderMode, FontSize, FontTemplate, FontVariation};
8use api::{ColorU, GlyphIndex, GlyphDimensions, SyntheticItalics};
9use api::{IdNamespace, BlobImageResources};
10use api::channel::crossbeam::{unbounded, Receiver, Sender};
11use api::units::*;
12use api::ImageFormat;
13use crate::platform::font::FontContext;
14use crate::profiler::GlyphRasterizeProfiler;
15use crate::types::{FastHashMap, FastHashSet};
16use crate::telemetry::Telemetry;
17use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
18use rayon::ThreadPool;
19use rayon::prelude::*;
20use euclid::approxeq::ApproxEq;
21use smallvec::SmallVec;
22use std::cmp;
23use std::cell::Cell;
24use std::hash::{Hash, Hasher};
25use std::mem;
26use std::ops::Deref;
27use std::sync::{Arc, Condvar, Mutex, MutexGuard, Weak};
28use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
29use std::sync::atomic::{AtomicBool, Ordering};
30
31pub static GLYPH_FLASHING: AtomicBool = AtomicBool::new(false);
32const GLYPH_BATCH_SIZE: usize = 32;
33
34impl FontContexts {
35 pub fn lock_current_context(&self) -> MutexGuard<FontContext> {
37 match self.current_worker_id() {
38 Some(id) => self.lock_context(id),
39 None => self.lock_any_context(),
40 }
41 }
42
43 pub(in super) fn current_worker_id(&self) -> Option<usize> {
44 self.workers.current_thread_index()
45 }
46}
47
48thread_local! {
49 pub static SEED: Cell<u32> = Cell::new(0);
50}
51
52fn random() -> u32 {
54 SEED.with(|seed| {
55 seed.set(seed.get().wrapping_mul(22695477).wrapping_add(1));
56 seed.get()
57 })
58}
59
60impl GlyphRasterizer {
61 pub fn request_glyphs<F>(
62 &mut self,
63 font: FontInstance,
64 glyph_keys: &[GlyphKey],
65 mut handle: F,
66 )
67 where F: FnMut(&GlyphKey) -> bool
68 {
69 assert!(self.has_font(font.font_key));
70
71 let mut batch_size = 0;
72
73 for key in glyph_keys {
75 if !handle(key) {
76 continue;
77 }
78
79 self.pending_glyph_count += 1;
82 self.glyph_request_count += 1;
83
84 match self.pending_glyph_requests.get_mut(&font) {
87 Some(container) => {
88 container.push(*key);
89 batch_size = container.len();
90 }
91 None => {
92 self.pending_glyph_requests.insert(
94 font.clone(),
95 smallvec![*key],
96 );
97 }
98 }
99 }
100
101 if batch_size >= GLYPH_BATCH_SIZE {
104 let container = self.pending_glyph_requests.get_mut(&font).unwrap();
105 let glyphs = mem::replace(container, SmallVec::new());
106 self.flush_glyph_requests(font, glyphs, true);
107 }
108 }
109
110 pub fn enable_multithreading(&mut self, enable: bool) {
111 self.enable_multithreading = enable;
112 }
113
114 fn flush_glyph_requests(
118 &mut self,
119 font: FontInstance,
120 glyphs: SmallVec<[GlyphKey; 16]>,
121 use_workers: bool,
122 ) {
123 let font = Arc::new(font);
124 let font_contexts = Arc::clone(&self.font_contexts);
125 self.pending_glyph_jobs += glyphs.len();
126 self.pending_glyph_count -= glyphs.len();
127
128 let can_use_r8_format = self.can_use_r8_format;
129
130 if let Some(thread) = &self.dedicated_thread {
133 let tx = self.glyph_tx.clone();
134 let _ = thread.tx.send(GlyphRasterMsg::Rasterize { font, glyphs, can_use_r8_format, tx });
135 } else if self.enable_multithreading && use_workers {
136 profile_scope!("spawning process_glyph jobs");
140 let tx = self.glyph_tx.clone();
141 self.workers.spawn(move || {
142 FontContext::begin_rasterize(&font);
143 if FontContext::distribute_across_threads() {
147 glyphs.par_iter().for_each(|key| {
148 let mut context = font_contexts.lock_current_context();
149 let job_font = font.clone();
150 let job = process_glyph(&mut context, can_use_r8_format, job_font, *key);
151 tx.send(job).unwrap();
152 });
153 } else {
154 for key in glyphs {
157 let mut context = font_contexts.lock_current_context();
158 let job_font = font.clone();
159 let job = process_glyph(&mut context, can_use_r8_format, job_font, key);
160 tx.send(job).unwrap();
161 }
162 }
163 FontContext::end_rasterize(&font);
164 });
165 } else {
166 FontContext::begin_rasterize(&font);
167 for key in glyphs {
168 let mut context = font_contexts.lock_current_context();
169 let job_font = font.clone();
170 let job = process_glyph(&mut context, can_use_r8_format, job_font, key);
171 self.glyph_tx.send(job).unwrap();
172 }
173 FontContext::end_rasterize(&font);
174 }
175 }
176
177 pub fn resolve_glyphs<F, G>(
178 &mut self,
179 mut handle: F,
180 profile: &mut G,
181 )
182 where
183 F: FnMut(GlyphRasterJob, bool),
184 G: GlyphRasterizeProfiler,
185 {
186 profile.start_time();
187 let timer_id = Telemetry::start_rasterize_glyphs_time();
188
189 let mut pending_glyph_requests = mem::replace(
191 &mut self.pending_glyph_requests,
192 FastHashMap::default(),
193 );
194 let use_workers = self.pending_glyph_count >= 8;
197 for (font, pending_glyphs) in pending_glyph_requests.drain() {
198 self.flush_glyph_requests(
199 font,
200 pending_glyphs,
201 use_workers,
202 );
203 }
204 self.pending_glyph_requests = pending_glyph_requests;
206 debug_assert_eq!(self.pending_glyph_count, 0);
207 debug_assert!(self.pending_glyph_requests.is_empty());
208
209 if self.glyph_request_count > 0 {
210 profile.set(self.glyph_request_count as f64);
211 self.glyph_request_count = 0;
212 }
213
214 profile_scope!("resolve_glyphs");
215 let mut jobs = {
220 profile_scope!("blocking wait on glyph_rx");
221 self.glyph_rx.iter().take(self.pending_glyph_jobs).collect::<Vec<_>>()
222 };
223 assert_eq!(jobs.len(), self.pending_glyph_jobs, "BUG: Didn't receive all pending glyphs!");
224 self.pending_glyph_jobs = 0;
225
226 jobs.sort_by(|a, b| (*a.font).cmp(&*b.font).then(a.key.cmp(&b.key)));
232
233 for job in jobs {
234 handle(job, self.can_use_r8_format);
235 }
236
237 self.remove_dead_fonts();
240
241 Telemetry::stop_and_accumulate_rasterize_glyphs_time(timer_id);
242 profile.end_time();
243 }
244}
245
246#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)]
247#[cfg_attr(feature = "capture", derive(Serialize))]
248#[cfg_attr(feature = "replay", derive(Deserialize))]
249pub struct FontTransform {
250 pub scale_x: f32,
251 pub skew_x: f32,
252 pub skew_y: f32,
253 pub scale_y: f32,
254}
255
256impl Eq for FontTransform {}
258impl Ord for FontTransform {
259 fn cmp(&self, other: &Self) -> cmp::Ordering {
260 self.partial_cmp(other).unwrap_or(cmp::Ordering::Equal)
261 }
262}
263impl Hash for FontTransform {
264 fn hash<H: Hasher>(&self, state: &mut H) {
265 self.scale_x.to_bits().hash(state);
267 self.skew_x.to_bits().hash(state);
268 self.skew_y.to_bits().hash(state);
269 self.scale_y.to_bits().hash(state);
270 }
271}
272
273impl FontTransform {
274 const QUANTIZE_SCALE: f32 = 1024.0;
275
276 pub fn new(scale_x: f32, skew_x: f32, skew_y: f32, scale_y: f32) -> Self {
277 FontTransform { scale_x, skew_x, skew_y, scale_y }
278 }
279
280 pub fn identity() -> Self {
281 FontTransform::new(1.0, 0.0, 0.0, 1.0)
282 }
283
284 #[allow(dead_code)]
285 pub fn is_identity(&self) -> bool {
286 *self == FontTransform::identity()
287 }
288
289 pub fn quantize(&self) -> Self {
290 FontTransform::new(
291 (self.scale_x * Self::QUANTIZE_SCALE).round() / Self::QUANTIZE_SCALE,
292 (self.skew_x * Self::QUANTIZE_SCALE).round() / Self::QUANTIZE_SCALE,
293 (self.skew_y * Self::QUANTIZE_SCALE).round() / Self::QUANTIZE_SCALE,
294 (self.scale_y * Self::QUANTIZE_SCALE).round() / Self::QUANTIZE_SCALE,
295 )
296 }
297
298 #[allow(dead_code)]
299 pub fn determinant(&self) -> f64 {
300 self.scale_x as f64 * self.scale_y as f64 - self.skew_y as f64 * self.skew_x as f64
301 }
302
303 #[allow(dead_code)]
304 pub fn compute_scale(&self) -> Option<(f64, f64)> {
305 let det = self.determinant();
306 if det != 0.0 {
307 let x_scale = (self.scale_x as f64).hypot(self.skew_y as f64);
308 let y_scale = det.abs() / x_scale;
309 Some((x_scale, y_scale))
310 } else {
311 None
312 }
313 }
314
315 #[allow(dead_code)]
316 pub fn pre_scale(&self, scale_x: f32, scale_y: f32) -> Self {
317 FontTransform::new(
318 self.scale_x * scale_x,
319 self.skew_x * scale_y,
320 self.skew_y * scale_x,
321 self.scale_y * scale_y,
322 )
323 }
324
325 #[allow(dead_code)]
326 pub fn scale(&self, scale: f32) -> Self { self.pre_scale(scale, scale) }
327
328 #[allow(dead_code)]
329 pub fn invert_scale(&self, x_scale: f64, y_scale: f64) -> Self {
330 self.pre_scale(x_scale.recip() as f32, y_scale.recip() as f32)
331 }
332
333 pub fn synthesize_italics(&self, angle: SyntheticItalics, size: f64, vertical: bool) -> (Self, (f64, f64)) {
334 let skew_factor = angle.to_skew();
335 if vertical {
336 let (tx, ty) = (0.0, -size * 0.5 * skew_factor as f64);
339 (FontTransform::new(
340 self.scale_x + self.skew_x * skew_factor,
341 self.skew_x,
342 self.skew_y + self.scale_y * skew_factor,
343 self.scale_y,
344 ), (self.scale_x as f64 * tx + self.skew_x as f64 * ty,
345 self.skew_y as f64 * tx + self.scale_y as f64 * ty))
346 } else {
347 (FontTransform::new(
348 self.scale_x,
349 self.skew_x - self.scale_x * skew_factor,
350 self.skew_y,
351 self.scale_y - self.skew_y * skew_factor,
352 ), (0.0, 0.0))
353 }
354 }
355
356 pub fn swap_xy(&self) -> Self {
357 FontTransform::new(self.skew_x, self.scale_x, self.scale_y, self.skew_y)
358 }
359
360 pub fn flip_x(&self) -> Self {
361 FontTransform::new(-self.scale_x, self.skew_x, -self.skew_y, self.scale_y)
362 }
363
364 pub fn flip_y(&self) -> Self {
365 FontTransform::new(self.scale_x, -self.skew_x, self.skew_y, -self.scale_y)
366 }
367
368 pub fn transform(&self, point: &LayoutPoint) -> DevicePoint {
369 DevicePoint::new(
370 self.scale_x * point.x + self.skew_x * point.y,
371 self.skew_y * point.x + self.scale_y * point.y,
372 )
373 }
374
375 pub fn get_subpx_dir(&self) -> SubpixelDirection {
376 if self.skew_y.approx_eq(&0.0) {
377 SubpixelDirection::Horizontal
379 } else if self.scale_x.approx_eq(&0.0) {
380 SubpixelDirection::Vertical
382 } else {
383 SubpixelDirection::Mixed
385 }
386 }
387}
388
389impl<'a> From<&'a LayoutToWorldTransform> for FontTransform {
390 fn from(xform: &'a LayoutToWorldTransform) -> Self {
391 FontTransform::new(xform.m11, xform.m21, xform.m12, xform.m22)
392 }
393}
394
395pub const FONT_SIZE_LIMIT: f32 = 320.0;
398
399#[derive(Clone, Debug, Ord, PartialOrd, MallocSizeOf)]
403#[cfg_attr(feature = "capture", derive(Serialize))]
404#[cfg_attr(feature = "replay", derive(Deserialize))]
405pub struct BaseFontInstance {
406 pub instance_key: FontInstanceKey,
408 pub font_key: FontKey,
410 pub size: FontSize,
412 pub options: FontInstanceOptions,
414 #[cfg_attr(any(feature = "capture", feature = "replay"), serde(skip))]
416 pub platform_options: Option<FontInstancePlatformOptions>,
417 pub variations: Vec<FontVariation>,
419}
420
421impl BaseFontInstance {
422 pub fn new(
423 instance_key: FontInstanceKey,
424 font_key: FontKey,
425 size: f32,
426 options: Option<FontInstanceOptions>,
427 platform_options: Option<FontInstancePlatformOptions>,
428 variations: Vec<FontVariation>,
429 ) -> Self {
430 BaseFontInstance {
431 instance_key,
432 font_key,
433 size: size.into(),
434 options: options.unwrap_or_default(),
435 platform_options,
436 variations,
437 }
438 }
439}
440
441impl Deref for BaseFontInstance {
442 type Target = FontInstanceOptions;
443 fn deref(&self) -> &FontInstanceOptions {
444 &self.options
445 }
446}
447
448impl Hash for BaseFontInstance {
449 fn hash<H: Hasher>(&self, state: &mut H) {
450 self.font_key.hash(state);
452 self.size.hash(state);
453 self.options.hash(state);
454 self.platform_options.hash(state);
455 self.variations.hash(state);
456 }
457}
458
459impl PartialEq for BaseFontInstance {
460 fn eq(&self, other: &BaseFontInstance) -> bool {
461 self.font_key == other.font_key &&
463 self.size == other.size &&
464 self.options == other.options &&
465 self.platform_options == other.platform_options &&
466 self.variations == other.variations
467 }
468}
469impl Eq for BaseFontInstance {}
470
471struct MappedFontKey {
472 font_key: FontKey,
473 template: FontTemplate,
474}
475
476struct FontKeyMapLocked {
477 namespace: IdNamespace,
478 next_id: u32,
479 template_map: FastHashMap<FontTemplate, Arc<MappedFontKey>>,
480 key_map: FastHashMap<FontKey, Arc<MappedFontKey>>,
481}
482
483#[derive(Clone)]
493pub struct FontKeyMap(Arc<RwLock<FontKeyMapLocked>>);
494
495impl FontKeyMap {
496 pub fn new(namespace: IdNamespace) -> Self {
497 FontKeyMap(Arc::new(RwLock::new(FontKeyMapLocked {
498 namespace,
499 next_id: 1,
500 template_map: FastHashMap::default(),
501 key_map: FastHashMap::default(),
502 })))
503 }
504
505 fn lock(&self) -> RwLockReadGuard<FontKeyMapLocked> {
506 self.0.read().unwrap()
507 }
508
509 fn lock_mut(&mut self) -> RwLockWriteGuard<FontKeyMapLocked> {
510 self.0.write().unwrap()
511 }
512
513 pub fn keys(&self) -> Vec<FontKey> {
514 self.lock().key_map.keys().cloned().collect()
515 }
516
517 pub fn map_key(&self, font_key: &FontKey) -> FontKey {
518 match self.lock().key_map.get(font_key) {
519 Some(mapped) => mapped.font_key,
520 None => *font_key,
521 }
522 }
523
524 pub fn add_key(&mut self, font_key: &FontKey, template: &FontTemplate) -> Option<FontKey> {
525 let mut locked = self.lock_mut();
526 if locked.key_map.contains_key(font_key) {
527 return None;
528 }
529 if let Some(mapped) = locked.template_map.get(template).cloned() {
530 locked.key_map.insert(*font_key, mapped);
531 return None;
532 }
533 let shared_key = FontKey::new(locked.namespace, locked.next_id);
534 locked.next_id += 1;
535 let mapped = Arc::new(MappedFontKey {
536 font_key: shared_key,
537 template: template.clone(),
538 });
539 locked.template_map.insert(template.clone(), mapped.clone());
540 locked.key_map.insert(*font_key, mapped);
541 Some(shared_key)
542 }
543
544 pub fn delete_key(&mut self, font_key: &FontKey) -> Option<FontKey> {
545 let mut locked = self.lock_mut();
546 let mapped = match locked.key_map.remove(font_key) {
547 Some(mapped) => mapped,
548 None => return Some(*font_key),
549 };
550 if Arc::strong_count(&mapped) <= 2 {
551 locked.template_map.remove(&mapped.template);
553 Some(mapped.font_key)
554 } else {
555 None
556 }
557 }
558
559 pub fn clear_namespace(&mut self, namespace: IdNamespace) -> Vec<FontKey> {
560 let mut locked = self.lock_mut();
561 locked.key_map.retain(|key, _| {
562 if key.0 == namespace {
563 false
564 } else {
565 true
566 }
567 });
568 let mut deleted_keys = Vec::new();
569 locked.template_map.retain(|_, mapped| {
570 if Arc::strong_count(mapped) <= 1 {
571 deleted_keys.push(mapped.font_key);
573 false
574 } else {
575 true
576 }
577 });
578 deleted_keys
579 }
580}
581
582type FontTemplateMapLocked = FastHashMap<FontKey, FontTemplate>;
583
584#[derive(Clone)]
587pub struct FontTemplateMap(Arc<RwLock<FontTemplateMapLocked>>);
588
589impl FontTemplateMap {
590 pub fn new() -> Self {
591 FontTemplateMap(Arc::new(RwLock::new(FastHashMap::default())))
592 }
593
594 pub fn lock(&self) -> RwLockReadGuard<FontTemplateMapLocked> {
595 self.0.read().unwrap()
596 }
597
598 fn lock_mut(&mut self) -> RwLockWriteGuard<FontTemplateMapLocked> {
599 self.0.write().unwrap()
600 }
601
602 pub fn clear(&mut self) {
603 self.lock_mut().clear();
604 }
605
606 pub fn len(&self) -> usize {
607 self.lock().len()
608 }
609
610 pub fn has_font(&self, key: &FontKey) -> bool {
611 self.lock().contains_key(key)
612 }
613
614 pub fn get_font(&self, key: &FontKey) -> Option<FontTemplate> {
615 self.lock().get(key).cloned()
616 }
617
618 pub fn add_font(&mut self, key: FontKey, template: FontTemplate) -> bool {
619 self.lock_mut().insert(key, template).is_none()
620 }
621
622 pub fn delete_font(&mut self, key: &FontKey) -> Option<FontTemplate> {
623 self.lock_mut().remove(key)
624 }
625
626 pub fn delete_fonts(&mut self, keys: &[FontKey]) {
627 if !keys.is_empty() {
628 let mut map = self.lock_mut();
629 for key in keys {
630 map.remove(key);
631 }
632 }
633 }
634
635 pub fn clear_namespace(&mut self, namespace: IdNamespace) -> Vec<FontKey> {
636 let mut deleted_keys = Vec::new();
637 self.lock_mut().retain(|key, _| {
638 if key.0 == namespace {
639 deleted_keys.push(*key);
640 false
641 } else {
642 true
643 }
644 });
645 deleted_keys
646 }
647}
648
649struct FontInstanceKeyMapLocked {
650 namespace: IdNamespace,
651 next_id: u32,
652 instances: FastHashSet<Arc<BaseFontInstance>>,
653 key_map: FastHashMap<FontInstanceKey, Weak<BaseFontInstance>>,
654}
655
656#[derive(Clone)]
666pub struct FontInstanceKeyMap(Arc<RwLock<FontInstanceKeyMapLocked>>);
667
668impl FontInstanceKeyMap {
669 pub fn new(namespace: IdNamespace) -> Self {
670 FontInstanceKeyMap(Arc::new(RwLock::new(FontInstanceKeyMapLocked {
671 namespace,
672 next_id: 1,
673 instances: FastHashSet::default(),
674 key_map: FastHashMap::default(),
675 })))
676 }
677
678 fn lock(&self) -> RwLockReadGuard<FontInstanceKeyMapLocked> {
679 self.0.read().unwrap()
680 }
681
682 fn lock_mut(&mut self) -> RwLockWriteGuard<FontInstanceKeyMapLocked> {
683 self.0.write().unwrap()
684 }
685
686 pub fn keys(&self) -> Vec<FontInstanceKey> {
687 self.lock().key_map.keys().cloned().collect()
688 }
689
690 pub fn map_key(&self, key: &FontInstanceKey) -> FontInstanceKey {
691 match self.lock().key_map.get(key).and_then(|weak| weak.upgrade()) {
692 Some(mapped) => mapped.instance_key,
693 None => *key,
694 }
695 }
696
697 pub fn add_key(&mut self, mut instance: BaseFontInstance) -> Option<Arc<BaseFontInstance>> {
698 let mut locked = self.lock_mut();
699 if locked.key_map.contains_key(&instance.instance_key) {
700 return None;
701 }
702 if let Some(weak) = locked.instances.get(&instance).map(|mapped| Arc::downgrade(mapped)) {
703 locked.key_map.insert(instance.instance_key, weak);
704 return None;
705 }
706 let unmapped_key = instance.instance_key;
707 instance.instance_key = FontInstanceKey::new(locked.namespace, locked.next_id);
708 locked.next_id += 1;
709 let shared_instance = Arc::new(instance);
710 locked.instances.insert(shared_instance.clone());
711 locked.key_map.insert(unmapped_key, Arc::downgrade(&shared_instance));
712 Some(shared_instance)
713 }
714
715 pub fn delete_key(&mut self, key: &FontInstanceKey) -> Option<FontInstanceKey> {
716 let mut locked = self.lock_mut();
717 let mapped = match locked.key_map.remove(key).and_then(|weak| weak.upgrade()) {
718 Some(mapped) => mapped,
719 None => return Some(*key),
720 };
721 if Arc::weak_count(&mapped) == 0 {
722 locked.instances.remove(&mapped);
724 Some(mapped.instance_key)
725 } else {
726 None
727 }
728 }
729
730 pub fn clear_namespace(&mut self, namespace: IdNamespace) -> Vec<FontInstanceKey> {
731 let mut locked = self.lock_mut();
732 locked.key_map.retain(|key, _| {
733 if key.0 == namespace {
734 false
735 } else {
736 true
737 }
738 });
739 let mut deleted_keys = Vec::new();
740 locked.instances.retain(|mapped| {
741 if Arc::weak_count(mapped) == 0 {
742 deleted_keys.push(mapped.instance_key);
744 false
745 } else {
746 true
747 }
748 });
749 deleted_keys
750 }
751}
752
753type FontInstanceMapLocked = FastHashMap<FontInstanceKey, Arc<BaseFontInstance>>;
754
755#[derive(Clone)]
757pub struct FontInstanceMap(Arc<RwLock<FontInstanceMapLocked>>);
758
759impl FontInstanceMap {
760 pub fn new() -> Self {
762 FontInstanceMap(Arc::new(RwLock::new(FastHashMap::default())))
763 }
764
765 pub fn lock(&self) -> RwLockReadGuard<FontInstanceMapLocked> {
767 self.0.read().unwrap()
768 }
769
770 fn lock_mut(&mut self) -> RwLockWriteGuard<FontInstanceMapLocked> {
772 self.0.write().unwrap()
773 }
774
775 pub fn clear(&mut self) {
777 self.lock_mut().clear();
778 }
779
780 pub fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData> {
782 match self.lock().get(&key) {
783 Some(instance) => Some(FontInstanceData {
784 font_key: instance.font_key,
785 size: instance.size.into(),
786 options: Some(FontInstanceOptions {
787 render_mode: instance.render_mode,
788 flags: instance.flags,
789 synthetic_italics: instance.synthetic_italics,
790 _padding: 0,
791 }),
792 platform_options: instance.platform_options,
793 variations: instance.variations.clone(),
794 }),
795 None => None,
796 }
797 }
798
799 pub fn get_font_instance(&self, instance_key: FontInstanceKey) -> Option<Arc<BaseFontInstance>> {
801 let instance_map = self.lock();
802 instance_map.get(&instance_key).cloned()
803 }
804
805 pub fn add_font_instance(&mut self, instance: Arc<BaseFontInstance>) {
807 self.lock_mut().insert(instance.instance_key, instance);
808 }
809
810 pub fn delete_font_instance(&mut self, instance_key: FontInstanceKey) {
812 self.lock_mut().remove(&instance_key);
813 }
814
815 pub fn delete_font_instances(&mut self, keys: &[FontInstanceKey]) {
817 if !keys.is_empty() {
818 let mut map = self.lock_mut();
819 for key in keys {
820 map.remove(key);
821 }
822 }
823 }
824
825 pub fn clear_namespace(&mut self, namespace: IdNamespace) {
827 self.lock_mut().retain(|key, _| key.0 != namespace);
828 }
829}
830
831#[derive(Clone)]
835pub struct SharedFontResources {
836 pub templates: FontTemplateMap,
837 pub instances: FontInstanceMap,
838 pub font_keys: FontKeyMap,
839 pub instance_keys: FontInstanceKeyMap,
840}
841
842impl SharedFontResources {
843 pub fn new(namespace: IdNamespace) -> Self {
844 SharedFontResources {
845 templates: FontTemplateMap::new(),
846 instances: FontInstanceMap::new(),
847 font_keys: FontKeyMap::new(namespace),
848 instance_keys: FontInstanceKeyMap::new(namespace),
849 }
850 }
851}
852
853impl BlobImageResources for SharedFontResources {
854 fn get_font_data(&self, key: FontKey) -> Option<FontTemplate> {
855 let shared_key = self.font_keys.map_key(&key);
856 self.templates.get_font(&shared_key)
857 }
858
859 fn get_font_instance_data(&self, key: FontInstanceKey) -> Option<FontInstanceData> {
860 let shared_key = self.instance_keys.map_key(&key);
861 self.instances.get_font_instance_data(shared_key)
862 }
863}
864
865#[derive(Clone, Debug, Ord, PartialOrd)]
870#[cfg_attr(feature = "capture", derive(Serialize))]
871#[cfg_attr(feature = "replay", derive(Deserialize))]
872pub struct FontInstance {
873 pub base: Arc<BaseFontInstance>,
874 pub transform: FontTransform,
875 pub render_mode: FontRenderMode,
876 pub flags: FontInstanceFlags,
877 pub color: ColorU,
878 pub size: FontSize,
881}
882
883impl Hash for FontInstance {
884 fn hash<H: Hasher>(&self, state: &mut H) {
885 self.base.instance_key.hash(state);
888 self.transform.hash(state);
889 self.render_mode.hash(state);
890 self.flags.hash(state);
891 self.color.hash(state);
892 self.size.hash(state);
893 }
894}
895
896impl PartialEq for FontInstance {
897 fn eq(&self, other: &FontInstance) -> bool {
898 self.base.instance_key == other.base.instance_key &&
900 self.transform == other.transform &&
901 self.render_mode == other.render_mode &&
902 self.flags == other.flags &&
903 self.color == other.color &&
904 self.size == other.size
905 }
906}
907impl Eq for FontInstance {}
908
909impl Deref for FontInstance {
910 type Target = BaseFontInstance;
911 fn deref(&self) -> &BaseFontInstance {
912 self.base.as_ref()
913 }
914}
915
916impl MallocSizeOf for FontInstance {
917 fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { 0 }
918}
919
920impl FontInstance {
921 pub fn new(
922 base: Arc<BaseFontInstance>,
923 color: ColorU,
924 render_mode: FontRenderMode,
925 flags: FontInstanceFlags,
926 ) -> Self {
927 FontInstance {
928 transform: FontTransform::identity(),
929 color,
930 size: base.size,
931 base,
932 render_mode,
933 flags,
934 }
935 }
936
937 pub fn from_base(
938 base: Arc<BaseFontInstance>,
939 ) -> Self {
940 let color = ColorU::new(0, 0, 0, 255);
941 let render_mode = base.render_mode;
942 let flags = base.flags;
943 Self::new(base, color, render_mode, flags)
944 }
945
946 pub fn use_texture_padding(&self) -> bool {
947 self.flags.contains(FontInstanceFlags::TEXTURE_PADDING)
948 }
949
950 pub fn use_transform_glyphs(&self) -> bool {
951 self.flags.contains(FontInstanceFlags::TRANSFORM_GLYPHS)
952 }
953
954 pub fn get_alpha_glyph_format(&self) -> GlyphFormat {
955 if self.use_transform_glyphs() { GlyphFormat::TransformedAlpha } else { GlyphFormat::Alpha }
956 }
957
958 pub fn get_subpixel_glyph_format(&self) -> GlyphFormat {
959 if self.use_transform_glyphs() { GlyphFormat::TransformedSubpixel } else { GlyphFormat::Subpixel }
960 }
961
962 pub fn disable_subpixel_aa(&mut self) {
963 self.render_mode = self.render_mode.limit_by(FontRenderMode::Alpha);
964 }
965
966 pub fn disable_subpixel_position(&mut self) {
967 self.flags.remove(FontInstanceFlags::SUBPIXEL_POSITION);
968 }
969
970 pub fn use_subpixel_position(&self) -> bool {
971 self.flags.contains(FontInstanceFlags::SUBPIXEL_POSITION) &&
972 self.render_mode != FontRenderMode::Mono
973 }
974
975 pub fn get_subpx_dir(&self) -> SubpixelDirection {
976 if self.use_subpixel_position() {
977 let mut subpx_dir = self.transform.get_subpx_dir();
978 if self.flags.contains(FontInstanceFlags::TRANSPOSE) {
979 subpx_dir = subpx_dir.swap_xy();
980 }
981 subpx_dir
982 } else {
983 SubpixelDirection::None
984 }
985 }
986
987 #[allow(dead_code)]
988 pub fn get_subpx_offset(&self, glyph: &GlyphKey) -> (f64, f64) {
989 if self.use_subpixel_position() {
990 let (dx, dy) = glyph.subpixel_offset();
991 (dx.into(), dy.into())
992 } else {
993 (0.0, 0.0)
994 }
995 }
996
997 #[allow(dead_code)]
998 pub fn get_glyph_format(&self) -> GlyphFormat {
999 match self.render_mode {
1000 FontRenderMode::Mono | FontRenderMode::Alpha => self.get_alpha_glyph_format(),
1001 FontRenderMode::Subpixel => self.get_subpixel_glyph_format(),
1002 }
1003 }
1004
1005 #[allow(dead_code)]
1006 pub fn get_extra_strikes(&self, flags: FontInstanceFlags, x_scale: f64) -> usize {
1007 if self.flags.intersects(flags) {
1008 let mut bold_offset = self.size.to_f64_px() / 48.0;
1009 if bold_offset < 1.0 {
1010 bold_offset = 0.25 + 0.75 * bold_offset;
1011 }
1012 (bold_offset * x_scale).max(1.0).round() as usize
1013 } else {
1014 0
1015 }
1016 }
1017
1018 pub fn synthesize_italics(&self, transform: FontTransform, size: f64) -> (FontTransform, (f64, f64)) {
1019 transform.synthesize_italics(self.synthetic_italics, size, self.flags.contains(FontInstanceFlags::VERTICAL))
1020 }
1021
1022 #[allow(dead_code)]
1023 pub fn get_transformed_size(&self) -> f64 {
1024 let (_, y_scale) = self.transform.compute_scale().unwrap_or((1.0, 1.0));
1025 self.size.to_f64_px() * y_scale
1026 }
1027}
1028
1029#[repr(u32)]
1030#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)]
1031pub enum SubpixelDirection {
1032 None = 0,
1033 Horizontal,
1034 Vertical,
1035 Mixed,
1036}
1037
1038impl SubpixelDirection {
1039 pub fn limit_by(self, glyph_format: GlyphFormat) -> Self {
1041 match glyph_format {
1042 GlyphFormat::Bitmap |
1043 GlyphFormat::ColorBitmap => SubpixelDirection::None,
1044 _ => self,
1045 }
1046 }
1047
1048 pub fn swap_xy(self) -> Self {
1049 match self {
1050 SubpixelDirection::None | SubpixelDirection::Mixed => self,
1051 SubpixelDirection::Horizontal => SubpixelDirection::Vertical,
1052 SubpixelDirection::Vertical => SubpixelDirection::Horizontal,
1053 }
1054 }
1055}
1056
1057#[repr(u8)]
1058#[derive(Hash, Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
1059#[cfg_attr(feature = "capture", derive(Serialize))]
1060#[cfg_attr(feature = "replay", derive(Deserialize))]
1061pub enum SubpixelOffset {
1062 Zero = 0,
1063 Quarter = 1,
1064 Half = 2,
1065 ThreeQuarters = 3,
1066}
1067
1068impl SubpixelOffset {
1069 fn quantize(pos: f32) -> Self {
1072 let apos = ((pos - pos.floor()) * 8.0) as i32;
1081
1082 match apos {
1083 1..=2 => SubpixelOffset::Quarter,
1084 3..=4 => SubpixelOffset::Half,
1085 5..=6 => SubpixelOffset::ThreeQuarters,
1086 _ => SubpixelOffset::Zero,
1087 }
1088 }
1089}
1090
1091impl Into<f64> for SubpixelOffset {
1092 fn into(self) -> f64 {
1093 match self {
1094 SubpixelOffset::Zero => 0.0,
1095 SubpixelOffset::Quarter => 0.25,
1096 SubpixelOffset::Half => 0.5,
1097 SubpixelOffset::ThreeQuarters => 0.75,
1098 }
1099 }
1100}
1101
1102#[derive(Copy, Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)]
1103#[cfg_attr(feature = "capture", derive(Serialize))]
1104#[cfg_attr(feature = "replay", derive(Deserialize))]
1105pub struct GlyphKey(u32);
1106
1107impl GlyphKey {
1108 pub fn new(
1109 index: u32,
1110 point: DevicePoint,
1111 subpx_dir: SubpixelDirection,
1112 ) -> Self {
1113 let (dx, dy) = match subpx_dir {
1114 SubpixelDirection::None => (0.0, 0.0),
1115 SubpixelDirection::Horizontal => (point.x, 0.0),
1116 SubpixelDirection::Vertical => (0.0, point.y),
1117 SubpixelDirection::Mixed => (point.x, point.y),
1118 };
1119 let sox = SubpixelOffset::quantize(dx);
1120 let soy = SubpixelOffset::quantize(dy);
1121 assert_eq!(0, index & 0xF0000000);
1122
1123 GlyphKey(index | (sox as u32) << 28 | (soy as u32) << 30)
1124 }
1125
1126 pub fn index(&self) -> GlyphIndex {
1127 self.0 & 0x0FFFFFFF
1128 }
1129
1130 fn subpixel_offset(&self) -> (SubpixelOffset, SubpixelOffset) {
1131 let x = (self.0 >> 28) as u8 & 3;
1132 let y = (self.0 >> 30) as u8 & 3;
1133 unsafe {
1134 (mem::transmute(x), mem::transmute(y))
1135 }
1136 }
1137}
1138
1139#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
1140#[cfg_attr(feature = "capture", derive(Serialize))]
1141#[cfg_attr(feature = "replay", derive(Deserialize))]
1142#[allow(dead_code)]
1143pub enum GlyphFormat {
1144 Alpha,
1145 TransformedAlpha,
1146 Subpixel,
1147 TransformedSubpixel,
1148 Bitmap,
1149 ColorBitmap,
1150}
1151
1152impl GlyphFormat {
1153 pub fn image_format(&self, can_use_r8_format: bool) -> ImageFormat {
1157 match *self {
1158 GlyphFormat::Alpha |
1159 GlyphFormat::TransformedAlpha |
1160 GlyphFormat::Bitmap => {
1161 if can_use_r8_format {
1162 ImageFormat::R8
1163 } else {
1164 ImageFormat::BGRA8
1165 }
1166 }
1167 GlyphFormat::Subpixel |
1168 GlyphFormat::TransformedSubpixel |
1169 GlyphFormat::ColorBitmap => ImageFormat::BGRA8,
1170 }
1171 }
1172}
1173
1174#[allow(dead_code)]
1175#[inline]
1176fn blend_strike_pixel(dest: u8, src: u32, src_alpha: u32) -> u8 {
1177 let x = src * 255 + dest as u32 * (255 - src_alpha) + 128;
1182 ((x + (x >> 8)) >> 8) as u8
1183}
1184
1185#[allow(dead_code)]
1189fn blend_strike(
1190 dest_bitmap: &mut [u8],
1191 src_bitmap: &[u8],
1192 width: usize,
1193 height: usize,
1194 subpixel_mask: bool,
1195 offset: f64,
1196) {
1197 let dest_stride = dest_bitmap.len() / height;
1198 let src_stride = width * 4;
1199 let offset_integer = offset.floor() as usize * 4;
1200 let offset_fract = (offset.fract() * 256.0) as u32;
1201 for (src_row, dest_row) in src_bitmap.chunks(src_stride).zip(dest_bitmap.chunks_mut(dest_stride)) {
1202 let mut prev_px = [0u32; 4];
1203 let dest_row_offset = &mut dest_row[offset_integer .. offset_integer + src_stride];
1204 for (src, dest) in src_row.chunks(4).zip(dest_row_offset.chunks_mut(4)) {
1205 let px = [src[0] as u32, src[1] as u32, src[2] as u32, src[3] as u32];
1206 let next_px = [px[0] * offset_fract,
1208 px[1] * offset_fract,
1209 px[2] * offset_fract,
1210 px[3] * offset_fract];
1211 let offset_px = [(((px[0] << 8) - next_px[0]) + prev_px[0] + 128) >> 8,
1212 (((px[1] << 8) - next_px[1]) + prev_px[1] + 128) >> 8,
1213 (((px[2] << 8) - next_px[2]) + prev_px[2] + 128) >> 8,
1214 (((px[3] << 8) - next_px[3]) + prev_px[3] + 128) >> 8];
1215 if subpixel_mask {
1216 dest[0] = blend_strike_pixel(dest[0], offset_px[0], offset_px[0]);
1218 dest[1] = blend_strike_pixel(dest[1], offset_px[1], offset_px[1]);
1219 dest[2] = blend_strike_pixel(dest[2], offset_px[2], offset_px[2]);
1220 dest[3] = blend_strike_pixel(dest[3], offset_px[3], offset_px[3]);
1221 } else {
1222 dest[0] = blend_strike_pixel(dest[0], offset_px[0], offset_px[3]);
1224 dest[1] = blend_strike_pixel(dest[1], offset_px[1], offset_px[3]);
1225 dest[2] = blend_strike_pixel(dest[2], offset_px[2], offset_px[3]);
1226 dest[3] = blend_strike_pixel(dest[3], offset_px[3], offset_px[3]);
1227 }
1228 prev_px = next_px;
1230 }
1231 if offset_fract > 0 {
1232 let dest = &mut dest_row[offset_integer + src_stride .. ];
1235 let offset_px = [(prev_px[0] + 128) >> 8,
1236 (prev_px[1] + 128) >> 8,
1237 (prev_px[2] + 128) >> 8,
1238 (prev_px[3] + 128) >> 8];
1239 if subpixel_mask {
1240 dest[0] = blend_strike_pixel(dest[0], offset_px[0], offset_px[0]);
1241 dest[1] = blend_strike_pixel(dest[1], offset_px[1], offset_px[1]);
1242 dest[2] = blend_strike_pixel(dest[2], offset_px[2], offset_px[2]);
1243 dest[3] = blend_strike_pixel(dest[3], offset_px[3], offset_px[3]);
1244 } else {
1245 dest[0] = blend_strike_pixel(dest[0], offset_px[0], offset_px[3]);
1246 dest[1] = blend_strike_pixel(dest[1], offset_px[1], offset_px[3]);
1247 dest[2] = blend_strike_pixel(dest[2], offset_px[2], offset_px[3]);
1248 dest[3] = blend_strike_pixel(dest[3], offset_px[3], offset_px[3]);
1249 }
1250 }
1251 }
1252}
1253
1254#[allow(dead_code)]
1260pub fn apply_multistrike_bold(
1261 src_bitmap: &[u8],
1262 width: usize,
1263 height: usize,
1264 subpixel_mask: bool,
1265 extra_strikes: usize,
1266 pixel_step: f64,
1267) -> (Vec<u8>, usize) {
1268 let src_stride = width * 4;
1269 let extra_width = (extra_strikes as f64 * pixel_step).ceil() as usize;
1271 let dest_width = width + extra_width;
1272 let dest_stride = dest_width * 4;
1273 let mut dest_bitmap = vec![0u8; dest_stride * height];
1275 for (src_row, dest_row) in src_bitmap.chunks(src_stride).zip(dest_bitmap.chunks_mut(dest_stride)) {
1276 dest_row[0 .. src_stride].copy_from_slice(src_row);
1278 }
1279 for i in 1 ..= extra_strikes {
1281 let offset = i as f64 * pixel_step;
1282 blend_strike(&mut dest_bitmap, src_bitmap, width, height, subpixel_mask, offset);
1283 }
1284 (dest_bitmap, dest_width)
1285}
1286
1287pub struct RasterizedGlyph {
1288 pub top: f32,
1289 pub left: f32,
1290 pub width: i32,
1291 pub height: i32,
1292 pub scale: f32,
1293 pub format: GlyphFormat,
1294 pub bytes: Vec<u8>,
1295}
1296
1297impl RasterizedGlyph {
1298 #[allow(dead_code)]
1299 pub fn downscale_bitmap_if_required(&mut self, font: &FontInstance) {
1300 match self.format {
1308 GlyphFormat::Bitmap | GlyphFormat::ColorBitmap => {},
1309 _ => return,
1310 }
1311 let (x_scale, y_scale) = font.transform.compute_scale().unwrap_or((1.0, 1.0));
1312 let upscaled = x_scale.max(y_scale) as f32;
1313 let mut new_scale = self.scale;
1314 if new_scale * upscaled <= 0.0 {
1315 return;
1316 }
1317 let mut steps = 0;
1318 while new_scale * upscaled <= 0.5 {
1319 new_scale *= 2.0;
1320 steps += 1;
1321 }
1322 if steps == 0 {
1324 return;
1325 }
1326
1327 let new_width = (self.width as usize + (1 << steps) - 1) >> steps;
1329 let new_height = (self.height as usize + (1 << steps) - 1) >> steps;
1330 let mut new_bytes: Vec<u8> = Vec::with_capacity(new_width * new_height * 4);
1331
1332 for y in 0 .. new_height {
1335 for x in 0 .. new_width {
1336 let src_y = y << steps;
1338 let src_x = x << steps;
1339 let y_samples = (1 << steps).min(self.height as usize - src_y);
1340 let x_samples = (1 << steps).min(self.width as usize - src_x);
1341 let num_samples = (x_samples * y_samples) as u32;
1342
1343 let mut src_idx = (src_y * self.width as usize + src_x) * 4;
1344 let mut accum = [num_samples / 2; 4];
1348 for _ in 0 .. y_samples {
1350 for _ in 0 .. x_samples {
1351 accum[0] += self.bytes[src_idx + 0] as u32;
1352 accum[1] += self.bytes[src_idx + 1] as u32;
1353 accum[2] += self.bytes[src_idx + 2] as u32;
1354 accum[3] += self.bytes[src_idx + 3] as u32;
1355 src_idx += 4;
1356 }
1357 src_idx += (self.width as usize - x_samples) * 4;
1358 }
1359
1360 new_bytes.extend_from_slice(&[
1362 (accum[0] / num_samples) as u8,
1363 (accum[1] / num_samples) as u8,
1364 (accum[2] / num_samples) as u8,
1365 (accum[3] / num_samples) as u8,
1366 ]);
1367 }
1368 }
1369
1370 self.top /= (1 << steps) as f32;
1372 self.left /= (1 << steps) as f32;
1373 self.width = new_width as i32;
1374 self.height = new_height as i32;
1375 self.scale = new_scale;
1376 self.bytes = new_bytes;
1377 }
1378}
1379
1380pub struct FontContexts {
1381 worker_contexts: Vec<Mutex<FontContext>>,
1384 #[allow(dead_code)]
1386 workers: Arc<ThreadPool>,
1387 locked_mutex: Mutex<bool>,
1388 locked_cond: Condvar,
1389}
1390
1391impl FontContexts {
1392 pub fn lock_context(&self, id: usize) -> MutexGuard<FontContext> {
1397 self.worker_contexts[id].lock().unwrap()
1398 }
1399
1400 pub fn lock_any_context(&self) -> MutexGuard<FontContext> {
1403 for context in &self.worker_contexts {
1404 if let Ok(mutex) = context.try_lock() {
1405 return mutex;
1406 }
1407 }
1408 self.lock_context(0)
1409 }
1410
1411 pub fn num_worker_contexts(&self) -> usize {
1413 self.worker_contexts.len()
1414 }
1415}
1416
1417pub trait AsyncForEach<T> {
1418 fn async_for_each<F: Fn(MutexGuard<T>) + Send + 'static>(&self, f: F);
1419}
1420
1421impl AsyncForEach<FontContext> for Arc<FontContexts> {
1422 fn async_for_each<F: Fn(MutexGuard<FontContext>) + Send + 'static>(&self, f: F) {
1423 let mut locked = self.locked_mutex.lock().unwrap();
1425 *locked = false;
1426
1427 let font_contexts = self.clone();
1429 self.workers.spawn(move || {
1431 let mut locks = Vec::with_capacity(font_contexts.num_worker_contexts());
1433 for i in 0 .. font_contexts.num_worker_contexts() {
1434 locks.push(font_contexts.lock_context(i));
1435 }
1436
1437 *font_contexts.locked_mutex.lock().unwrap() = true;
1439 font_contexts.locked_cond.notify_all();
1440
1441 for context in locks {
1443 f(context);
1444 }
1445 });
1446
1447 while !*locked {
1451 locked = self.locked_cond.wait(locked).unwrap();
1452 }
1453 }
1454}
1455
1456pub struct GlyphRasterizer {
1457 #[allow(dead_code)]
1458 workers: Arc<ThreadPool>,
1459 font_contexts: Arc<FontContexts>,
1460 dedicated_thread: Option<GlyphRasterThread>,
1461
1462 fonts: FastHashSet<FontKey>,
1464
1465 pending_glyph_count: usize,
1467
1468 pending_glyph_jobs: usize,
1470
1471 glyph_request_count: usize,
1473
1474 pending_glyph_requests: FastHashMap<FontInstance, SmallVec<[GlyphKey; 16]>>,
1476
1477 glyph_rx: Receiver<GlyphRasterJob>,
1479 glyph_tx: Sender<GlyphRasterJob>,
1480
1481 fonts_to_remove: Vec<FontKey>,
1486 font_instances_to_remove: Vec<FontInstance>,
1488
1489 enable_multithreading: bool,
1491
1492 can_use_r8_format: bool,
1494}
1495
1496impl GlyphRasterizer {
1497 pub fn new(workers: Arc<ThreadPool>, dedicated_thread: Option<GlyphRasterThread>, can_use_r8_format: bool) -> Self {
1498 let (glyph_tx, glyph_rx) = unbounded();
1499
1500 let num_workers = workers.current_num_threads();
1501 let mut contexts = Vec::with_capacity(num_workers);
1502
1503 for _ in 0 .. num_workers {
1504 contexts.push(Mutex::new(FontContext::new()));
1505 }
1506
1507 let font_context = FontContexts {
1508 worker_contexts: contexts,
1509 workers: Arc::clone(&workers),
1510 locked_mutex: Mutex::new(false),
1511 locked_cond: Condvar::new(),
1512 };
1513
1514 GlyphRasterizer {
1515 font_contexts: Arc::new(font_context),
1516 fonts: FastHashSet::default(),
1517 dedicated_thread,
1518 pending_glyph_jobs: 0,
1519 pending_glyph_count: 0,
1520 glyph_request_count: 0,
1521 glyph_rx,
1522 glyph_tx,
1523 workers,
1524 fonts_to_remove: Vec::new(),
1525 font_instances_to_remove: Vec::new(),
1526 enable_multithreading: true,
1527 pending_glyph_requests: FastHashMap::default(),
1528 can_use_r8_format,
1529 }
1530 }
1531
1532 pub fn add_font(&mut self, font_key: FontKey, template: FontTemplate) {
1533 if self.fonts.insert(font_key.clone()) {
1535 if let Some(thread) = &self.dedicated_thread {
1536 let _ = thread.tx.send(GlyphRasterMsg::AddFont { font_key, template });
1537 } else {
1538 self.font_contexts.async_for_each(move |mut context| {
1539 context.add_font(&font_key, &template);
1540 });
1541 }
1542 }
1543 }
1544
1545 pub fn delete_font(&mut self, font_key: FontKey) {
1546 self.fonts_to_remove.push(font_key);
1547 }
1548
1549 pub fn delete_fonts(&mut self, font_keys: &[FontKey]) {
1550 self.fonts_to_remove.extend_from_slice(font_keys);
1551 }
1552
1553 pub fn delete_font_instance(&mut self, instance: &FontInstance) {
1554 self.font_instances_to_remove.push(instance.clone());
1555 }
1556
1557 pub fn prepare_font(&self, font: &mut FontInstance) {
1558 FontContext::prepare_font(font);
1559
1560 font.transform = font.transform.quantize();
1566 }
1567
1568 pub fn has_font(&self, font_key: FontKey) -> bool {
1569 self.fonts.contains(&font_key)
1570 }
1571
1572 pub fn get_glyph_dimensions(
1573 &mut self,
1574 font: &FontInstance,
1575 glyph_index: GlyphIndex,
1576 ) -> Option<GlyphDimensions> {
1577 let glyph_key = GlyphKey::new(
1578 glyph_index,
1579 DevicePoint::zero(),
1580 SubpixelDirection::None,
1581 );
1582
1583 self.font_contexts
1584 .lock_any_context()
1585 .get_glyph_dimensions(font, &glyph_key)
1586 }
1587
1588 pub fn get_glyph_index(&mut self, font_key: FontKey, ch: char) -> Option<u32> {
1589 self.font_contexts
1590 .lock_any_context()
1591 .get_glyph_index(font_key, ch)
1592 }
1593
1594 fn remove_dead_fonts(&mut self) {
1595 if self.fonts_to_remove.is_empty() && self.font_instances_to_remove.is_empty() {
1596 return
1597 }
1598
1599 profile_scope!("remove_dead_fonts");
1600 let mut fonts_to_remove = mem::replace(& mut self.fonts_to_remove, Vec::new());
1601 fonts_to_remove.retain(|font| self.fonts.remove(font));
1603 let font_instances_to_remove = mem::replace(& mut self.font_instances_to_remove, Vec::new());
1604 if let Some(thread) = &self.dedicated_thread {
1605 for font_key in fonts_to_remove {
1606 let _ = thread.tx.send(GlyphRasterMsg::DeleteFont { font_key });
1607 }
1608 for instance in font_instances_to_remove {
1609 let _ = thread.tx.send(GlyphRasterMsg::DeleteFontInstance { instance });
1610 }
1611 } else {
1612 self.font_contexts.async_for_each(move |mut context| {
1613 for font_key in &fonts_to_remove {
1614 context.delete_font(font_key);
1615 }
1616 for instance in &font_instances_to_remove {
1617 context.delete_font_instance(instance);
1618 }
1619 });
1620 }
1621 }
1622
1623 #[cfg(feature = "replay")]
1624 pub fn reset(&mut self) {
1625 self.pending_glyph_jobs = 0;
1627 self.pending_glyph_count = 0;
1628 self.glyph_request_count = 0;
1629 self.fonts_to_remove.clear();
1630 self.font_instances_to_remove.clear();
1631 }
1632}
1633
1634trait AddFont {
1635 fn add_font(&mut self, font_key: &FontKey, template: &FontTemplate);
1636}
1637
1638impl AddFont for FontContext {
1639 fn add_font(&mut self, font_key: &FontKey, template: &FontTemplate) {
1640 match *template {
1641 FontTemplate::Raw(ref bytes, index) => {
1642 self.add_raw_font(font_key, bytes.clone(), index);
1643 }
1644 FontTemplate::Native(ref native_font_handle) => {
1645 self.add_native_font(font_key, (*native_font_handle).clone());
1646 }
1647 }
1648 }
1649}
1650
1651#[allow(dead_code)]
1652pub struct GlyphRasterJob {
1653 pub font: Arc<FontInstance>,
1654 pub key: GlyphKey,
1655 pub result: GlyphRasterResult,
1656}
1657
1658#[allow(dead_code)]
1659#[derive(Debug)]
1660pub enum GlyphRasterError {
1661 LoadFailed,
1662}
1663
1664#[allow(dead_code)]
1665pub type GlyphRasterResult = Result<RasterizedGlyph, GlyphRasterError>;
1666
1667#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
1668#[cfg_attr(feature = "capture", derive(Serialize))]
1669#[cfg_attr(feature = "replay", derive(Deserialize))]
1670pub struct GpuGlyphCacheKey(pub u32);
1671
1672fn process_glyph(
1673 context: &mut FontContext,
1674 can_use_r8_format: bool,
1675 font: Arc<FontInstance>,
1676 key: GlyphKey,
1677) -> GlyphRasterJob {
1678 profile_scope!("glyph-raster");
1679 let result = context.rasterize_glyph(&font, &key);
1680 let mut job = GlyphRasterJob {
1681 font: font,
1682 key: key.clone(),
1683 result,
1684 };
1685
1686 if let Ok(ref mut glyph) = job.result {
1687 let bpp = 4; assert_eq!(
1690 glyph.bytes.len(),
1691 bpp * (glyph.width * glyph.height) as usize
1692 );
1693
1694 fn over(dst: u8, src: u8) -> u8 {
1696 let a = src as u32;
1697 let a = 256 - a;
1698 let dst = ((dst as u32 * a) >> 8) as u8;
1699 src + dst
1700 }
1701
1702 if GLYPH_FLASHING.load(Ordering::Relaxed) {
1703 let color = (random() & 0xff) as u8;
1704 for i in &mut glyph.bytes {
1705 *i = over(*i, color);
1706 }
1707 }
1708
1709 assert_eq!((glyph.left.fract(), glyph.top.fract()), (0.0, 0.0));
1710
1711 glyph.downscale_bitmap_if_required(&job.font);
1713
1714 if glyph.format.image_format(can_use_r8_format).bytes_per_pixel() == 1 {
1718 glyph.bytes = glyph.bytes
1719 .chunks_mut(4)
1720 .map(|pixel| pixel[3])
1721 .collect::<Vec<_>>();
1722 }
1723 }
1724
1725 job
1726}
1727
1728
1729pub enum GlyphRasterMsg {
1730 Rasterize {
1731 font: Arc<FontInstance>,
1732 glyphs: SmallVec<[GlyphKey; 16]>,
1733 can_use_r8_format: bool,
1734 tx: Sender<GlyphRasterJob>,
1735 },
1736 AddFont { font_key: FontKey, template: FontTemplate },
1737 DeleteFont { font_key: FontKey },
1738 DeleteFontInstance { instance: FontInstance },
1739 ShutDown,
1740}
1741
1742#[derive(Clone)]
1743pub struct GlyphRasterThread {
1744 tx: Sender<GlyphRasterMsg>,
1745}
1746
1747impl GlyphRasterThread {
1748 pub fn new(
1749 on_start: impl FnOnce() + Send + 'static,
1750 on_end: impl FnOnce() + Send+ 'static,
1751 ) -> std::io::Result<Self> {
1752 let (tx, rx) = unbounded();
1753
1754 std::thread::Builder::new().name("Glyph rasterizer".to_string()).spawn(move || {
1755 on_start();
1756
1757 let mut context = FontContext::new();
1758
1759 loop {
1760 match rx.recv() {
1761 Ok(GlyphRasterMsg::Rasterize { font, glyphs, can_use_r8_format, tx }) => {
1762 for glyph in &glyphs {
1763 let job = process_glyph(&mut context, can_use_r8_format, font.clone(), *glyph);
1764 let _ = tx.send(job);
1765 }
1766 }
1767 Ok(GlyphRasterMsg::AddFont { font_key, template }) => {
1768 context.add_font(&font_key, &template)
1769 }
1770 Ok(GlyphRasterMsg::DeleteFont { font_key }) => {
1771 context.delete_font(&font_key)
1772 }
1773 Ok(GlyphRasterMsg::DeleteFontInstance { instance }) => {
1774 context.delete_font_instance(&instance)
1775 }
1776 Ok(GlyphRasterMsg::ShutDown) => {
1777 break;
1778 }
1779 Err(..) => {
1780 break;
1781 }
1782 }
1783 }
1784
1785 on_end();
1786 })?;
1787
1788 Ok(GlyphRasterThread {
1789 tx,
1790 })
1791 }
1792
1793 pub fn shut_down(&self) {
1794 let _ = self.tx.send(GlyphRasterMsg::ShutDown);
1795 }
1796}
1797
1798#[cfg(test)]
1799mod test_glyph_rasterizer {
1800 use crate::profiler::GlyphRasterizeProfiler;
1801
1802 struct Profiler;
1803 impl GlyphRasterizeProfiler for Profiler {
1804 fn start_time(&mut self) {}
1805 fn end_time(&mut self) -> f64 {
1806 0.
1807 }
1808 fn set(&mut self, _value: f64) {}
1809 }
1810
1811 #[test]
1812 fn rasterize_200_glyphs() {
1813 use rayon::ThreadPoolBuilder;
1817 use std::fs::File;
1818 use std::io::Read;
1819 use api::{FontKey, FontInstanceKey, FontTemplate, IdNamespace};
1820 use api::units::DevicePoint;
1821 use std::sync::Arc;
1822 use crate::rasterizer::{FontInstance, BaseFontInstance, GlyphKey, GlyphRasterizer};
1823
1824 let worker = ThreadPoolBuilder::new()
1825 .thread_name(|idx|{ format!("WRWorker#{}", idx) })
1826 .build();
1827 let workers = Arc::new(worker.unwrap());
1828 let mut glyph_rasterizer = GlyphRasterizer::new(workers, None, true);
1829 let mut font_file =
1830 File::open("../wrench/reftests/text/VeraBd.ttf").expect("Couldn't open font file");
1831 let mut font_data = vec![];
1832 font_file
1833 .read_to_end(&mut font_data)
1834 .expect("failed to read font file");
1835
1836 let font_key = FontKey::new(IdNamespace(0), 0);
1837 glyph_rasterizer.add_font(font_key, FontTemplate::Raw(Arc::new(font_data), 0));
1838
1839 let font = FontInstance::from_base(Arc::new(BaseFontInstance::new(
1840 FontInstanceKey::new(IdNamespace(0), 0),
1841 font_key,
1842 32.0,
1843 None,
1844 None,
1845 Vec::new(),
1846 )));
1847
1848 let subpx_dir = font.get_subpx_dir();
1849
1850 let mut glyph_keys = Vec::with_capacity(200);
1851 for i in 0 .. 200 {
1852 glyph_keys.push(GlyphKey::new(
1853 i,
1854 DevicePoint::zero(),
1855 subpx_dir,
1856 ));
1857 }
1858
1859 for i in 0 .. 4 {
1860 glyph_rasterizer.request_glyphs(
1861 font.clone(),
1862 &glyph_keys[(50 * i) .. (50 * (i + 1))],
1863 |_| true,
1864 );
1865 }
1866
1867 glyph_rasterizer.delete_font(font_key);
1868
1869 glyph_rasterizer.resolve_glyphs(
1870 |_, _| {},
1871 &mut Profiler,
1872 );
1873 }
1874
1875 #[test]
1876 fn rasterize_large_glyphs() {
1877 use rayon::ThreadPoolBuilder;
1880 use std::fs::File;
1881 use std::io::Read;
1882 use api::{FontKey, FontInstanceKey, FontTemplate, IdNamespace};
1883 use api::units::DevicePoint;
1884 use std::sync::Arc;
1885 use crate::rasterizer::{FontInstance, BaseFontInstance, GlyphKey, GlyphRasterizer};
1886
1887 let worker = ThreadPoolBuilder::new()
1888 .thread_name(|idx|{ format!("WRWorker#{}", idx) })
1889 .build();
1890 let workers = Arc::new(worker.unwrap());
1891 let mut glyph_rasterizer = GlyphRasterizer::new(workers, None, true);
1892 let mut font_file =
1893 File::open("../wrench/reftests/text/VeraBd.ttf").expect("Couldn't open font file");
1894 let mut font_data = vec![];
1895 font_file
1896 .read_to_end(&mut font_data)
1897 .expect("failed to read font file");
1898
1899 let font_key = FontKey::new(IdNamespace(0), 0);
1900 glyph_rasterizer.add_font(font_key, FontTemplate::Raw(Arc::new(font_data), 0));
1901
1902 let font = FontInstance::from_base(Arc::new(BaseFontInstance::new(
1903 FontInstanceKey::new(IdNamespace(0), 0),
1904 font_key,
1905 200.0,
1906 None,
1907 None,
1908 Vec::new(),
1909 )));
1910
1911 let subpx_dir = font.get_subpx_dir();
1912
1913 let mut glyph_keys = Vec::with_capacity(10);
1914 for i in 0 .. 10 {
1915 glyph_keys.push(GlyphKey::new(
1916 i,
1917 DevicePoint::zero(),
1918 subpx_dir,
1919 ));
1920 }
1921
1922 glyph_rasterizer.request_glyphs(
1923 font.clone(),
1924 &glyph_keys,
1925 |_| true,
1926 );
1927
1928 glyph_rasterizer.delete_font(font_key);
1929
1930 glyph_rasterizer.resolve_glyphs(
1931 |_, _| {},
1932 &mut Profiler,
1933 );
1934 }
1935
1936 #[test]
1937 fn test_subpx_quantize() {
1938 use crate::rasterizer::SubpixelOffset;
1939
1940 assert_eq!(SubpixelOffset::quantize(0.0), SubpixelOffset::Zero);
1941 assert_eq!(SubpixelOffset::quantize(-0.0), SubpixelOffset::Zero);
1942
1943 assert_eq!(SubpixelOffset::quantize(0.1), SubpixelOffset::Zero);
1944 assert_eq!(SubpixelOffset::quantize(0.01), SubpixelOffset::Zero);
1945 assert_eq!(SubpixelOffset::quantize(0.05), SubpixelOffset::Zero);
1946 assert_eq!(SubpixelOffset::quantize(0.12), SubpixelOffset::Zero);
1947 assert_eq!(SubpixelOffset::quantize(0.124), SubpixelOffset::Zero);
1948
1949 assert_eq!(SubpixelOffset::quantize(0.125), SubpixelOffset::Quarter);
1950 assert_eq!(SubpixelOffset::quantize(0.2), SubpixelOffset::Quarter);
1951 assert_eq!(SubpixelOffset::quantize(0.25), SubpixelOffset::Quarter);
1952 assert_eq!(SubpixelOffset::quantize(0.33), SubpixelOffset::Quarter);
1953 assert_eq!(SubpixelOffset::quantize(0.374), SubpixelOffset::Quarter);
1954
1955 assert_eq!(SubpixelOffset::quantize(0.375), SubpixelOffset::Half);
1956 assert_eq!(SubpixelOffset::quantize(0.4), SubpixelOffset::Half);
1957 assert_eq!(SubpixelOffset::quantize(0.5), SubpixelOffset::Half);
1958 assert_eq!(SubpixelOffset::quantize(0.58), SubpixelOffset::Half);
1959 assert_eq!(SubpixelOffset::quantize(0.624), SubpixelOffset::Half);
1960
1961 assert_eq!(SubpixelOffset::quantize(0.625), SubpixelOffset::ThreeQuarters);
1962 assert_eq!(SubpixelOffset::quantize(0.67), SubpixelOffset::ThreeQuarters);
1963 assert_eq!(SubpixelOffset::quantize(0.7), SubpixelOffset::ThreeQuarters);
1964 assert_eq!(SubpixelOffset::quantize(0.78), SubpixelOffset::ThreeQuarters);
1965 assert_eq!(SubpixelOffset::quantize(0.874), SubpixelOffset::ThreeQuarters);
1966
1967 assert_eq!(SubpixelOffset::quantize(0.875), SubpixelOffset::Zero);
1968 assert_eq!(SubpixelOffset::quantize(0.89), SubpixelOffset::Zero);
1969 assert_eq!(SubpixelOffset::quantize(0.91), SubpixelOffset::Zero);
1970 assert_eq!(SubpixelOffset::quantize(0.967), SubpixelOffset::Zero);
1971 assert_eq!(SubpixelOffset::quantize(0.999), SubpixelOffset::Zero);
1972
1973 assert_eq!(SubpixelOffset::quantize(-1.0), SubpixelOffset::Zero);
1974 assert_eq!(SubpixelOffset::quantize(1.0), SubpixelOffset::Zero);
1975 assert_eq!(SubpixelOffset::quantize(1.5), SubpixelOffset::Half);
1976 assert_eq!(SubpixelOffset::quantize(-1.625), SubpixelOffset::Half);
1977 assert_eq!(SubpixelOffset::quantize(-4.33), SubpixelOffset::ThreeQuarters);
1978 }
1979}