1use alloc::{boxed::Box, rc::Rc, string::String, vec::Vec};
2use core::{
3 cell::{Cell, RefCell},
4 num::NonZeroUsize,
5};
6
7use hashbrown::HashMap;
8
9#[cfg(feature = "wasm-entrance")]
10use wasm_bindgen::prelude::*;
11#[cfg(feature = "wasm-entrance")]
12use wasm_bindgen::JsCast;
13
14use crate::{
15 length_num::LengthNum,
16 parser::{WarningKind, DEFAULT_INPUT_CSS_EXTENSION},
17 sheet::{FontFace, KeyFrames},
18};
19
20use super::parser::Warning;
21use super::property::*;
22use super::query::*;
23#[cfg(any(feature = "serialize", feature = "deserialize"))]
24use super::sheet::borrow_resource;
25use super::sheet::{CompiledStyleSheet, LinkedStyleSheet, Rule};
26
27#[cfg(feature = "deserialize")]
28use super::sheet::borrow;
29
30pub(crate) fn drop_css_extension(path: &str) -> &str {
31 path.strip_suffix(DEFAULT_INPUT_CSS_EXTENSION)
32 .unwrap_or(path)
33}
34
35#[cfg_attr(feature = "wasm-entrance", wasm_bindgen)]
37#[derive(Default)]
38pub struct StyleSheetResource {
39 pub(crate) refs: HashMap<String, RefCell<CompiledStyleSheet>>,
40 panic_on_warning: bool,
41}
42
43#[cfg_attr(feature = "wasm-entrance", wasm_bindgen)]
44impl StyleSheetResource {
45 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(constructor))]
47 pub fn new() -> Self {
48 Self::default()
49 }
50
51 #[cfg_attr(
53 feature = "wasm-entrance",
54 wasm_bindgen(js_name = "generateImportIndexes")
55 )]
56 pub fn generate_import_indexes(&self) -> StyleSheetImportIndex {
57 let deps = self
58 .refs
59 .iter()
60 .map(|(k, v)| {
61 (
62 k.clone(),
63 (
64 v.borrow().list_deps().into_iter().collect::<Vec<String>>(),
65 false,
66 Cell::new(false),
67 ),
68 )
69 })
70 .collect::<HashMap<_, _>>();
71 StyleSheetImportIndex { deps }
72 }
73
74 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "addTagNamePrefix"))]
76 pub fn js_add_tag_name_prefix(&mut self, path: &str, prefix: &str) {
77 self.add_tag_name_prefix(path, prefix)
78 }
79
80 #[cfg(feature = "wasm-entrance")]
82 #[cfg_attr(
83 feature = "wasm-entrance",
84 wasm_bindgen(js_name = "directDependencies")
85 )]
86 pub fn js_direct_dependencies(&self, path: &str) -> Vec<JsValue> {
87 self.direct_dependencies(drop_css_extension(path))
88 .into_iter()
89 .map(|x| JsValue::from_str(&x))
90 .collect()
91 }
92
93 #[doc(hidden)]
94 #[cfg(all(feature = "serialize", feature = "serialize_json"))]
95 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "serializeJson"))]
96 pub fn serialize_json(&self, path: &str) -> Option<String> {
97 let path = drop_css_extension(path);
98 self.refs.get(path).map(|ss| ss.borrow().serialize_json())
99 }
100
101 #[cfg(feature = "serialize")]
103 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "serializeBincode"))]
104 pub fn serialize_bincode(&self, path: &str) -> Option<Vec<u8>> {
105 let path = drop_css_extension(path);
106 self.refs
107 .get(path)
108 .map(|ss| ss.borrow().serialize_bincode())
109 }
110
111 #[cfg(feature = "wasm-entrance")]
112 unsafe fn convert_warnings_to_js_unsafe(warnings: Vec<Warning>) -> JsValue {
113 let ret = js_sys::Array::new();
114 for warning in warnings {
115 let item = js_sys::Object::new();
116 js_sys::Reflect::set(
117 &item,
118 &JsValue::from("message"),
119 &JsValue::from(warning.message.as_str()),
120 )
121 .unwrap();
122 js_sys::Reflect::set(
123 &item,
124 &JsValue::from("startLine"),
125 &JsValue::from(warning.start_line),
126 )
127 .unwrap();
128 js_sys::Reflect::set(
129 &item,
130 &JsValue::from("startCol"),
131 &JsValue::from(warning.start_col),
132 )
133 .unwrap();
134 js_sys::Reflect::set(
135 &item,
136 &JsValue::from("endLine"),
137 &JsValue::from(warning.end_line),
138 )
139 .unwrap();
140 js_sys::Reflect::set(
141 &item,
142 &JsValue::from("endCol"),
143 &JsValue::from(warning.end_col),
144 )
145 .unwrap();
146
147 ret.push(&item);
148 }
149 ret.dyn_into().unwrap()
150 }
151
152 #[cfg(feature = "wasm-entrance")]
153 fn convert_warnings_to_js(warnings: Vec<Warning>) -> JsValue {
154 unsafe { Self::convert_warnings_to_js_unsafe(warnings) }
155 }
156
157 #[cfg(feature = "wasm-entrance")]
159 #[wasm_bindgen(js_name = "addSource")]
160 pub fn js_add_source(&mut self, path: &str, source: &str) -> JsValue {
161 let ret = self.add_source(path, source);
162 Self::convert_warnings_to_js(ret)
163 }
164
165 #[doc(hidden)]
166 #[cfg(all(
167 feature = "wasm-entrance",
168 feature = "deserialize",
169 feature = "deserialize_json"
170 ))]
171 #[wasm_bindgen(js_name = "addJson")]
172 pub fn js_add_json(&mut self, path: &str, json: &str) -> JsValue {
173 let ret = self.add_json(path, json);
174 Self::convert_warnings_to_js(ret)
175 }
176
177 #[cfg(all(feature = "wasm-entrance", feature = "deserialize"))]
179 #[wasm_bindgen(js_name = "addBincode")]
180 pub fn js_add_bincode(&mut self, path: &str, bincode: Vec<u8>) -> JsValue {
181 let ret = self.add_bincode(path, bincode);
182 Self::convert_warnings_to_js(ret)
183 }
184}
185
186impl StyleSheetResource {
187 pub fn direct_dependencies(&self, path: &str) -> Vec<String> {
189 match self.refs.get(path) {
190 None => vec![],
191 Some(v) => v.borrow().list_deps(),
192 }
193 }
194
195 fn add(&mut self, path: &str, sheet: CompiledStyleSheet) {
196 let path = drop_css_extension(path).into();
197 self.refs.insert(path, RefCell::new(sheet));
198 }
199
200 pub fn add_tag_name_prefix(&mut self, path: &str, prefix: &str) {
202 let path = drop_css_extension(path);
203 if let Some(ss) = self.refs.get(path) {
204 ss.borrow_mut().add_tag_name_prefix(prefix);
205 }
206 }
207
208 pub fn set_panic_on_warning(&mut self, panic_on_warning: bool) {
210 self.panic_on_warning = panic_on_warning;
211 }
212
213 pub(crate) fn link(
214 &self,
215 path: &str,
216 scope: Option<NonZeroUsize>,
217 ) -> (LinkedStyleSheet, Vec<Warning>) {
218 let (ss, warnings) = self
219 .refs
220 .get(path)
221 .map(|ss| ss.borrow_mut().link(self, scope))
222 .unwrap_or_else(|| {
223 let warnings = vec![Warning {
224 kind: WarningKind::MissingImportTarget,
225 message: format!("Target style sheet {:?} is not found.", path).into(),
226 start_line: 0,
227 start_col: 0,
228 end_line: 0,
229 end_col: 0,
230 }];
231 (LinkedStyleSheet::new_empty(), warnings)
232 });
233 if self.panic_on_warning {
234 if let Some(w) = warnings.last() {
235 panic!("{:?}", w);
236 }
237 }
238 (ss, warnings)
239 }
240
241 pub fn add_source(&mut self, path: &str, source: &str) -> Vec<Warning> {
243 self.add_source_with_hooks(path, source, None)
244 }
245
246 pub fn add_source_with_hooks(
248 &mut self,
249 path: &str,
250 source: &str,
251 hooks: Option<Box<dyn crate::parser::hooks::Hooks>>,
252 ) -> Vec<Warning> {
253 let path = drop_css_extension(path);
255 let (sheet, warning) = crate::parser::parse_style_sheet_with_hooks(path, source, hooks);
256 if self.panic_on_warning {
257 if let Some(w) = warning.last() {
258 panic!("{:?}", w);
259 }
260 }
261 self.add(path, sheet);
262 warning
263 }
264
265 #[cfg(feature = "deserialize")]
266 fn deserialize_failed_warning(msg: String) -> Vec<Warning> {
267 vec![Warning {
268 kind: WarningKind::DeserializationFailed,
269 message: format!(
270 "failed to deserialize bincode formatted style sheet: {}",
271 msg
272 )
273 .into(),
274 start_line: 0,
275 start_col: 0,
276 end_line: 0,
277 end_col: 0,
278 }]
279 }
280
281 #[doc(hidden)]
282 #[cfg(all(feature = "deserialize", feature = "deserialize_json"))]
283 pub fn add_json(&mut self, path: &str, json: &str) -> Vec<Warning> {
284 let ss = CompiledStyleSheet::deserialize_json(json);
285 let ret = match ss {
286 Ok(ss) => {
287 self.add(path, ss);
288 Vec::with_capacity(0)
289 }
290 Err(err) => Self::deserialize_failed_warning(err),
291 };
292 if self.panic_on_warning {
293 if let Some(w) = ret.last() {
294 panic!("{:?}", w);
295 }
296 }
297 ret
298 }
299
300 #[doc(hidden)]
301 #[cfg(all(feature = "deserialize", feature = "deserialize_json"))]
312 pub unsafe fn add_json_zero_copy(
313 &mut self,
314 path: &str,
315 ptr: *mut [u8],
316 drop_callback: impl 'static + FnOnce(),
317 ) -> Vec<Warning> {
318 let ss = CompiledStyleSheet::deserialize_json_zero_copy(ptr, drop_callback);
319 let ret = match ss {
320 Ok(ss) => {
321 self.add(path, ss);
322 Vec::with_capacity(0)
323 }
324 Err(err) => Self::deserialize_failed_warning(err),
325 };
326 if self.panic_on_warning {
327 if let Some(w) = ret.last() {
328 panic!("{:?}", w);
329 }
330 }
331 ret
332 }
333
334 #[cfg(feature = "deserialize")]
336 pub fn add_bincode(&mut self, path: &str, bincode: Vec<u8>) -> Vec<Warning> {
337 let ss = CompiledStyleSheet::deserialize_bincode(bincode);
338 let ret = match ss {
339 Ok(ss) => {
340 self.add(path, ss);
341 Vec::with_capacity(0)
342 }
343 Err(err) => Self::deserialize_failed_warning(err),
344 };
345 if self.panic_on_warning {
346 if let Some(w) = ret.last() {
347 panic!("{:?}", w);
348 }
349 }
350 ret
351 }
352
353 #[cfg(feature = "deserialize")]
359 pub unsafe fn add_bincode_zero_copy(
360 &mut self,
361 path: &str,
362 ptr: *const [u8],
363 drop_callback: impl 'static + FnOnce(),
364 ) -> Vec<Warning> {
365 let ss = CompiledStyleSheet::deserialize_bincode_zero_copy(ptr, drop_callback);
366 let ret = match ss {
367 Ok(ss) => {
368 self.add(path, ss);
369 Vec::with_capacity(0)
370 }
371 Err(err) => Self::deserialize_failed_warning(err),
372 };
373 if self.panic_on_warning {
374 if let Some(w) = ret.last() {
375 panic!("{:?}", w);
376 }
377 }
378 ret
379 }
380}
381
382#[cfg_attr(feature = "wasm-entrance", wasm_bindgen)]
384#[derive(Debug, Default)]
385pub struct StyleSheetImportIndex {
386 pub(crate) deps: HashMap<String, (Vec<String>, bool, Cell<bool>)>,
387}
388
389impl StyleSheetImportIndex {
390 pub fn new() -> Self {
392 Self::default()
393 }
394
395 pub fn query_and_mark_dependencies(&mut self, path: &str) -> Vec<String> {
400 let mut ret = vec![];
401 let path = drop_css_extension(path);
402 fn rec(
403 deps: &mut HashMap<String, (Vec<String>, bool, Cell<bool>)>,
404 path: &str,
405 ret: &mut Vec<String>,
406 ) {
407 let x = if let Some((x, marked, _)) = deps.get_mut(path) {
408 if *marked {
409 return;
410 }
411 *marked = true;
412 x.clone()
413 } else {
414 return;
415 };
416 for x in x.into_iter() {
417 rec(deps, &x, ret);
418 }
419 ret.push(path.into());
420 }
421 rec(&mut self.deps, path, &mut ret);
422 ret
423 }
424
425 pub fn list_dependencies(&self, path: &str, recursive: bool) -> Vec<String> {
429 let mut ret = vec![];
430 let path = drop_css_extension(path);
431 fn rec(
432 deps: &HashMap<String, (Vec<String>, bool, Cell<bool>)>,
433 path: &str,
434 ret: &mut Vec<String>,
435 recursive: bool,
436 ) {
437 if let Some((x, _, rec_marked)) = deps.get(path) {
438 if rec_marked.get() {
439 return;
440 }
441 rec_marked.set(true);
442 if recursive {
443 for x in x.iter().map(|x| x.as_str()) {
444 rec(deps, x, ret, recursive);
445 }
446 }
447 ret.push(path.into());
448 rec_marked.set(false);
449 }
450 }
451 rec(&self.deps, path, &mut ret, recursive);
452 ret
453 }
454}
455
456#[cfg_attr(feature = "wasm-entrance", wasm_bindgen)]
457impl StyleSheetImportIndex {
458 #[cfg(feature = "wasm-entrance")]
460 #[wasm_bindgen(js_name = "queryAndMarkDependencies")]
461 pub fn js_query_and_mark_dependencies(&mut self, path: &str) -> JsValue {
462 let deps = self.query_and_mark_dependencies(path);
463 let ret = js_sys::Array::new_with_length(deps.len() as u32);
464 for dep in deps {
465 ret.push(&JsValue::from(dep));
466 }
467 ret.dyn_into().unwrap()
468 }
469
470 #[doc(hidden)]
471 #[cfg(all(feature = "serialize", feature = "serialize_json"))]
472 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "serializeJson"))]
473 pub fn serialize_json(&self) -> String {
474 let s = borrow_resource::StyleSheetImportIndex::from_sheet(self);
475 serde_json::to_string(&s).unwrap()
476 }
477
478 #[doc(hidden)]
479 #[cfg(all(feature = "deserialize", feature = "deserialize_json"))]
480 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "deserializeJson"))]
481 pub fn deserialize_json(s: &str) -> Self {
482 let s: Result<borrow_resource::StyleSheetImportIndex, _> = serde_json::from_str(s);
483 match s {
484 Ok(ss) => ss.into_sheet(),
485 Err(_) => {
486 error!("Failed to deserialize json formatted style sheet import index. Use empty content instead.");
487 Self {
488 deps: hashbrown::HashMap::default(),
489 }
490 }
491 }
492 }
493
494 #[cfg(feature = "serialize")]
496 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "serializeBincode"))]
497 pub fn serialize_bincode(&self) -> Vec<u8> {
498 use float_pigment_consistent_bincode::Options;
499 let s = borrow_resource::StyleSheetImportIndex::from_sheet(self);
500 float_pigment_consistent_bincode::DefaultOptions::new()
501 .allow_trailing_bytes()
502 .serialize(&s)
503 .unwrap()
504 }
505
506 #[cfg(feature = "deserialize")]
508 #[cfg_attr(
509 feature = "wasm-entrance",
510 wasm_bindgen(js_name = "deserializeBincode")
511 )]
512 pub fn deserialize_bincode(s: Vec<u8>) -> Self {
513 use float_pigment_consistent_bincode::Options;
514 let s: Result<borrow_resource::StyleSheetImportIndex, _> =
515 float_pigment_consistent_bincode::DefaultOptions::new()
516 .allow_trailing_bytes()
517 .deserialize(&s);
518 match s {
519 Ok(ss) => ss.into_sheet(),
520 Err(_) => {
521 error!("Failed to deserialize bincode formatted style sheet import index. Use empty content instead.");
522 Self {
523 deps: HashMap::default(),
524 }
525 }
526 }
527 }
528
529 #[cfg(feature = "deserialize")]
531 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "mergeBincode"))]
532 pub fn merge_bincode(&mut self, s: Vec<u8>) {
533 use float_pigment_consistent_bincode::Options;
534 let s: Result<borrow_resource::StyleSheetImportIndex, _> =
535 float_pigment_consistent_bincode::DefaultOptions::new()
536 .allow_trailing_bytes()
537 .deserialize(&s);
538 match s {
539 Ok(ss) => ss.merge_to_sheet(self),
540 Err(_) => {
541 error!("Failed to merge bincode formatted style sheet import index. Use empty content instead.");
542 }
543 }
544 }
545}
546
547impl StyleSheetImportIndex {
548 #[cfg(feature = "deserialize")]
554 pub unsafe fn deserialize_bincode_zero_copy(
555 ptr: *mut [u8],
556 drop_callback: impl 'static + FnOnce(),
557 ) -> Self {
558 use float_pigment_consistent_bincode::Options;
559 borrow::de_static_ref_zero_copy_env(
560 ptr,
561 |s| {
562 let s: Result<borrow_resource::StyleSheetImportIndex, _> =
563 float_pigment_consistent_bincode::DefaultOptions::new()
564 .allow_trailing_bytes()
565 .deserialize(s);
566 match s {
567 Ok(ss) => ss.into_sheet(),
568 Err(_) => {
569 error!("Failed to deserialize bincode formatted style sheet import index. Use empty content instead.");
570 Self {
571 deps: HashMap::default(),
572 }
573 }
574 }
575 },
576 drop_callback,
577 )
578 }
579
580 #[cfg(feature = "deserialize")]
586 pub unsafe fn merge_bincode_zero_copy(
587 &mut self,
588 ptr: *mut [u8],
589 drop_callback: impl 'static + FnOnce(),
590 ) {
591 use float_pigment_consistent_bincode::Options;
592 borrow::de_static_ref_zero_copy_env(
593 ptr,
594 |s| {
595 let s: Result<borrow_resource::StyleSheetImportIndex, _> =
596 float_pigment_consistent_bincode::DefaultOptions::new()
597 .allow_trailing_bytes()
598 .deserialize(s);
599 match s {
600 Ok(ss) => ss.merge_to_sheet(self),
601 Err(_) => {
602 error!("Failed to merge bincode formatted style sheet import index. Use empty content instead.");
603 }
604 }
605 },
606 drop_callback,
607 )
608 }
609
610 #[doc(hidden)]
611 #[cfg(all(feature = "deserialize", feature = "deserialize_json"))]
615 pub unsafe fn deserialize_json_zero_copy(
616 ptr: *mut [u8],
617 drop_callback: impl 'static + FnOnce(),
618 ) -> Self {
619 borrow::de_static_ref_zero_copy_env(
620 ptr,
621 |s| {
622 let s: Result<borrow_resource::StyleSheetImportIndex, _> =
623 serde_json::from_str(std::str::from_utf8_unchecked(s));
624 match s {
625 Ok(ss) => ss.into_sheet(),
626 Err(_) => {
627 error!("Failed to deserialize json formatted style sheet import index. Use empty content instead.");
628 Self {
629 deps: hashbrown::HashMap::default(),
630 }
631 }
632 }
633 },
634 drop_callback,
635 )
636 }
637}
638
639pub const TEMP_SHEET_INDEX: u16 = u16::MAX;
641
642#[cfg_attr(feature = "wasm-entrance", wasm_bindgen)]
644#[derive(Default, Clone)]
645pub struct StyleSheetGroup {
646 sheets: Vec<LinkedStyleSheet>,
647 temp_sheet: Option<LinkedStyleSheet>,
648}
649
650impl StyleSheetGroup {
651 pub fn new() -> Self {
653 Self::default()
654 }
655
656 pub fn len(&self) -> u16 {
658 self.sheets.len() as u16
659 }
660
661 pub fn is_empty(&self) -> bool {
663 self.sheets.is_empty()
664 }
665
666 pub fn append(&mut self, sheet: LinkedStyleSheet) -> u16 {
668 let ret = self.sheets.len();
669 if Self::is_invalid_index(ret) {
670 panic!("The number of stylesheets has reached the maximum limit.")
671 }
672 self.sheets.push(sheet);
673 ret as u16
674 }
675
676 pub fn replace(&mut self, index: u16, sheet: LinkedStyleSheet) {
678 self.sheets[index as usize] = sheet;
679 }
680
681 pub fn append_from_resource(
683 &mut self,
684 res: &StyleSheetResource,
685 path: &str,
686 scope: Option<NonZeroUsize>,
687 ) -> u16 {
688 self.append_from_resource_with_warnings(res, path, scope).0
689 }
690
691 pub fn append_from_resource_with_warnings(
693 &mut self,
694 res: &StyleSheetResource,
695 path: &str,
696 scope: Option<NonZeroUsize>,
697 ) -> (u16, Vec<Warning>) {
698 let path = drop_css_extension(path);
699 let (ss, warnings) = res.link(path, scope);
700 let ret = self.sheets.len();
701 if Self::is_invalid_index(ret) {
702 panic!("The number of stylesheets has reached the maximum limit.")
703 }
704 self.sheets.push(ss);
705 (ret as u16, warnings)
706 }
707
708 pub fn replace_from_resource(
710 &mut self,
711 index: u16,
712 res: &StyleSheetResource,
713 path: &str,
714 scope: Option<NonZeroUsize>,
715 ) {
716 let path = drop_css_extension(path);
717 let (ss, _warnings) = res.link(path, scope);
718 self.sheets[index as usize] = ss;
719 }
720
721 pub fn clear(&mut self) {
723 self.sheets.truncate(0);
724 }
725
726 pub fn style_sheet(&self, sheet_index: u16) -> Option<&LinkedStyleSheet> {
728 if sheet_index != TEMP_SHEET_INDEX {
729 self.sheets.get(sheet_index as usize)
730 } else {
731 self.temp_sheet.as_ref()
732 }
733 }
734
735 pub fn get_font_face(&self, sheet_index: u16) -> Option<Vec<Rc<FontFace>>> {
737 self.style_sheet(sheet_index)
738 .map(|sheet| sheet.get_font_face())
739 }
740
741 pub fn get_rule(&self, sheet_index: u16, rule_index: u32) -> Option<Rc<Rule>> {
745 if let Some(sheet) = self.style_sheet(sheet_index) {
746 sheet.get_rule(rule_index)
747 } else {
748 None
749 }
750 }
751
752 pub fn add_rule(&mut self, rule: Box<Rule>) -> u32 {
759 if self.temp_sheet.is_none() {
760 self.temp_sheet = Some(LinkedStyleSheet::new_empty());
761 }
762 let sheet = self.temp_sheet.as_mut().unwrap();
763 sheet.add_rule(rule)
764 }
765
766 pub fn replace_rule(
773 &mut self,
774 sheet_index: u16,
775 rule_index: u32,
776 rule: Box<Rule>,
777 ) -> Result<Rc<Rule>, Box<Rule>> {
778 let sheet = if sheet_index != TEMP_SHEET_INDEX {
779 self.sheets.get_mut(sheet_index as usize)
780 } else {
781 self.temp_sheet.as_mut()
782 };
783 if let Some(sheet) = sheet {
784 sheet.replace_rule(rule_index, rule)
785 } else {
786 Err(rule)
787 }
788 }
789
790 pub fn query_single<L: LengthNum, T: StyleNode>(
794 &self,
795 query: T,
796 media_query_status: &MediaQueryStatus<L>,
797 node_properties: &mut NodeProperties,
798 ) {
799 self.query_ancestor_path(&[query], media_query_status, node_properties, None)
800 }
801
802 pub fn for_each_matched_rule<L: LengthNum, T: StyleNode>(
806 &self,
807 query: &[T],
808 media_query_status: &MediaQueryStatus<L>,
809 mut f: impl FnMut(MatchedRuleRef, Option<&LinkedStyleSheet>),
810 ) {
811 for (index, sheet) in self.sheets.iter().enumerate() {
812 sheet.for_each_matched_rule(
813 query,
814 media_query_status,
815 index.min((TEMP_SHEET_INDEX - 1) as usize) as u16,
816 |r| f(r, Some(sheet)),
817 );
818 }
819 if let Some(sheet) = self.temp_sheet.as_ref() {
820 sheet.for_each_matched_rule(query, media_query_status, u16::MAX, |r| f(r, None));
821 }
822 }
823
824 pub fn query_matched_rules<L: LengthNum, T: StyleNode>(
828 &self,
829 query: &[T],
830 media_query_status: &MediaQueryStatus<L>,
831 ) -> MatchedRuleList {
832 let mut rules = vec![];
833 self.for_each_matched_rule(query, media_query_status, |matched_rule, style_sheet| {
834 let r = MatchedRule {
835 rule: matched_rule.rule.clone(),
836 weight: matched_rule.weight,
837 style_scope: style_sheet.and_then(|x| x.scope()),
838 };
839 rules.push(r);
840 });
841 MatchedRuleList { rules }
842 }
843
844 pub fn query_ancestor_path<L: LengthNum, T: StyleNode>(
849 &self,
850 query: &[T],
851 media_query_status: &MediaQueryStatus<L>,
852 node_properties: &mut NodeProperties,
853 parent_node_properties: Option<&NodeProperties>,
854 ) {
855 let default_font_size = media_query_status.base_font_size.to_f32();
856 let parent_font_size = match parent_node_properties {
857 None => default_font_size,
858 Some(x) => x
859 .font_size_ref()
860 .resolve_to_f32(media_query_status, default_font_size, true)
861 .unwrap_or(default_font_size),
862 };
863 let rules = self.query_matched_rules(query, media_query_status);
864 let current_font_size = rules.get_current_font_size(
865 parent_font_size,
866 parent_node_properties,
867 &[],
868 media_query_status,
869 );
870 rules.merge_node_properties(
871 node_properties,
872 parent_node_properties,
873 current_font_size,
874 &[],
875 );
876 }
877
878 fn is_invalid_index(idx: usize) -> bool {
879 idx > (u16::MAX as usize)
880 }
881
882 pub fn search_keyframes<L: LengthNum>(
884 &self,
885 style_scope: Option<NonZeroUsize>,
886 name: &str,
887 media_query_status: &MediaQueryStatus<L>,
888 ) -> Option<Rc<KeyFrames>> {
889 if let Some(sheet) = self.temp_sheet.as_ref() {
890 if let Some(x) = sheet.search_keyframes(style_scope, name, media_query_status) {
891 return Some(x);
892 }
893 }
894 for sheet in self.sheets.iter().rev() {
895 if let Some(x) = sheet.search_keyframes(style_scope, name, media_query_status) {
896 return Some(x);
897 }
898 }
899 None
900 }
901}