fonts_traits/
system_font_service_proxy.rs1use std::collections::HashMap;
6
7use ipc_channel::ipc::{self, IpcSender};
8use log::debug;
9use malloc_size_of_derive::MallocSizeOf;
10use parking_lot::RwLock;
11use profile_traits::mem::ReportsChan;
12use serde::{Deserialize, Serialize};
13use style::values::computed::font::SingleFontFamily;
14use webrender_api::units::Au;
15use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey, FontVariation};
16
17use crate::{FontDescriptor, FontIdentifier, FontTemplate, FontTemplateRef};
18
19#[derive(Debug, Deserialize, Serialize)]
21pub enum SystemFontServiceMessage {
22 GetFontTemplates(
23 Option<FontDescriptor>,
24 SingleFontFamily,
25 IpcSender<Vec<FontTemplate>>,
26 ),
27 GetFontInstance(
28 FontIdentifier,
29 Au,
30 FontInstanceFlags,
31 Vec<FontVariation>,
32 IpcSender<FontInstanceKey>,
33 ),
34 GetFontKey(IpcSender<FontKey>),
35 GetFontInstanceKey(IpcSender<FontInstanceKey>),
36 CollectMemoryReport(ReportsChan),
37 Exit(IpcSender<()>),
38 Ping,
39}
40
41#[derive(Clone, Deserialize, Serialize)]
42pub struct SystemFontServiceProxySender(pub IpcSender<SystemFontServiceMessage>);
43
44impl SystemFontServiceProxySender {
45 pub fn to_proxy(&self) -> SystemFontServiceProxy {
46 SystemFontServiceProxy {
47 sender: self.0.clone(),
48 templates: Default::default(),
49 }
50 }
51}
52
53#[derive(Debug, Eq, Hash, MallocSizeOf, PartialEq)]
54struct FontTemplateCacheKey {
55 font_descriptor: Option<FontDescriptor>,
56 family_descriptor: SingleFontFamily,
57}
58
59#[derive(Debug, MallocSizeOf)]
62pub struct SystemFontServiceProxy {
63 sender: IpcSender<SystemFontServiceMessage>,
64 templates: RwLock<HashMap<FontTemplateCacheKey, Vec<FontTemplateRef>>>,
65}
66
67impl SystemFontServiceProxy {
68 pub fn exit(&self) {
69 let (response_chan, response_port) = ipc::channel().unwrap();
70 self.sender
71 .send(SystemFontServiceMessage::Exit(response_chan))
72 .expect("Couldn't send SystemFontService exit message");
73 response_port
74 .recv()
75 .expect("Couldn't receive SystemFontService reply");
76 }
77
78 pub fn to_sender(&self) -> SystemFontServiceProxySender {
79 SystemFontServiceProxySender(self.sender.clone())
80 }
81
82 pub fn get_system_font_instance(
83 &self,
84 identifier: FontIdentifier,
85 size: Au,
86 flags: FontInstanceFlags,
87 variations: Vec<FontVariation>,
88 ) -> FontInstanceKey {
89 let (response_chan, response_port) = ipc::channel().expect("failed to create IPC channel");
90 self.sender
91 .send(SystemFontServiceMessage::GetFontInstance(
92 identifier,
93 size,
94 flags,
95 variations,
96 response_chan,
97 ))
98 .expect("failed to send message to system font service");
99
100 let instance_key = response_port.recv();
101 if instance_key.is_err() {
102 let font_thread_has_closed = self.sender.send(SystemFontServiceMessage::Ping).is_err();
103 assert!(
104 font_thread_has_closed,
105 "Failed to receive a response from live font cache"
106 );
107 panic!("SystemFontService has already exited.");
108 }
109 instance_key.unwrap()
110 }
111
112 pub fn find_matching_font_templates(
113 &self,
114 descriptor_to_match: Option<&FontDescriptor>,
115 family_descriptor: &SingleFontFamily,
116 ) -> Vec<FontTemplateRef> {
117 let cache_key = FontTemplateCacheKey {
118 font_descriptor: descriptor_to_match.cloned(),
119 family_descriptor: family_descriptor.clone(),
120 };
121 if let Some(templates) = self.templates.read().get(&cache_key).cloned() {
122 return templates;
123 }
124
125 debug!(
126 "SystemFontServiceProxy: cache miss for template_descriptor={:?} family_descriptor={:?}",
127 descriptor_to_match, family_descriptor
128 );
129
130 let (response_chan, response_port) = ipc::channel().expect("failed to create IPC channel");
131 self.sender
132 .send(SystemFontServiceMessage::GetFontTemplates(
133 descriptor_to_match.cloned(),
134 family_descriptor.clone(),
135 response_chan,
136 ))
137 .expect("failed to send message to system font service");
138
139 let Ok(templates) = response_port.recv() else {
140 let font_thread_has_closed = self.sender.send(SystemFontServiceMessage::Ping).is_err();
141 assert!(
142 font_thread_has_closed,
143 "Failed to receive a response from live font cache"
144 );
145 panic!("SystemFontService has already exited.");
146 };
147
148 let templates: Vec<_> = templates.into_iter().map(FontTemplateRef::new).collect();
149 self.templates.write().insert(cache_key, templates.clone());
150
151 templates
152 }
153
154 pub fn generate_font_key(&self) -> FontKey {
155 let (result_sender, result_receiver) =
156 ipc::channel().expect("failed to create IPC channel");
157 self.sender
158 .send(SystemFontServiceMessage::GetFontKey(result_sender))
159 .expect("failed to send message to system font service");
160 result_receiver
161 .recv()
162 .expect("Failed to communicate with system font service.")
163 }
164
165 pub fn generate_font_instance_key(&self) -> FontInstanceKey {
166 let (result_sender, result_receiver) =
167 ipc::channel().expect("failed to create IPC channel");
168 self.sender
169 .send(SystemFontServiceMessage::GetFontInstanceKey(result_sender))
170 .expect("failed to send message to system font service");
171 result_receiver
172 .recv()
173 .expect("Failed to communicate with system font service.")
174 }
175}