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 {path:?} is not found.").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!("failed to deserialize bincode formatted style sheet: {msg}").into(),
270 start_line: 0,
271 start_col: 0,
272 end_line: 0,
273 end_col: 0,
274 }]
275 }
276
277 #[doc(hidden)]
278 #[cfg(all(feature = "deserialize", feature = "deserialize_json"))]
279 pub fn add_json(&mut self, path: &str, json: &str) -> Vec<Warning> {
280 let ss = CompiledStyleSheet::deserialize_json(json);
281 let ret = match ss {
282 Ok(ss) => {
283 self.add(path, ss);
284 Vec::with_capacity(0)
285 }
286 Err(err) => Self::deserialize_failed_warning(err),
287 };
288 if self.panic_on_warning {
289 if let Some(w) = ret.last() {
290 panic!("{w:?}");
291 }
292 }
293 ret
294 }
295
296 #[doc(hidden)]
297 #[cfg(all(feature = "deserialize", feature = "deserialize_json"))]
308 pub unsafe fn add_json_zero_copy(
309 &mut self,
310 path: &str,
311 ptr: *mut [u8],
312 drop_callback: impl 'static + FnOnce(),
313 ) -> Vec<Warning> {
314 let ss = CompiledStyleSheet::deserialize_json_zero_copy(ptr, drop_callback);
315 let ret = match ss {
316 Ok(ss) => {
317 self.add(path, ss);
318 Vec::with_capacity(0)
319 }
320 Err(err) => Self::deserialize_failed_warning(err),
321 };
322 if self.panic_on_warning {
323 if let Some(w) = ret.last() {
324 panic!("{w:?}");
325 }
326 }
327 ret
328 }
329
330 #[cfg(feature = "deserialize")]
332 pub fn add_bincode(&mut self, path: &str, bincode: Vec<u8>) -> Vec<Warning> {
333 let ss = CompiledStyleSheet::deserialize_bincode(bincode);
334 let ret = match ss {
335 Ok(ss) => {
336 self.add(path, ss);
337 Vec::with_capacity(0)
338 }
339 Err(err) => Self::deserialize_failed_warning(err),
340 };
341 if self.panic_on_warning {
342 if let Some(w) = ret.last() {
343 panic!("{w:?}");
344 }
345 }
346 ret
347 }
348
349 #[cfg(feature = "deserialize")]
355 pub unsafe fn add_bincode_zero_copy(
356 &mut self,
357 path: &str,
358 ptr: *const [u8],
359 drop_callback: impl 'static + FnOnce(),
360 ) -> Vec<Warning> {
361 let ss = CompiledStyleSheet::deserialize_bincode_zero_copy(ptr, drop_callback);
362 let ret = match ss {
363 Ok(ss) => {
364 self.add(path, ss);
365 Vec::with_capacity(0)
366 }
367 Err(err) => Self::deserialize_failed_warning(err),
368 };
369 if self.panic_on_warning {
370 if let Some(w) = ret.last() {
371 panic!("{w:?}");
372 }
373 }
374 ret
375 }
376}
377
378#[cfg_attr(feature = "wasm-entrance", wasm_bindgen)]
380#[derive(Debug, Default)]
381pub struct StyleSheetImportIndex {
382 pub(crate) deps: HashMap<String, (Vec<String>, bool, Cell<bool>)>,
383}
384
385impl StyleSheetImportIndex {
386 pub fn new() -> Self {
388 Self::default()
389 }
390
391 pub fn query_and_mark_dependencies(&mut self, path: &str) -> Vec<String> {
396 let mut ret = vec![];
397 let path = drop_css_extension(path);
398 fn rec(
399 deps: &mut HashMap<String, (Vec<String>, bool, Cell<bool>)>,
400 path: &str,
401 ret: &mut Vec<String>,
402 ) {
403 let x = if let Some((x, marked, _)) = deps.get_mut(path) {
404 if *marked {
405 return;
406 }
407 *marked = true;
408 x.clone()
409 } else {
410 return;
411 };
412 for x in x.into_iter() {
413 rec(deps, &x, ret);
414 }
415 ret.push(path.into());
416 }
417 rec(&mut self.deps, path, &mut ret);
418 ret
419 }
420
421 pub fn list_dependencies(&self, path: &str, recursive: bool) -> Vec<String> {
425 let mut ret = vec![];
426 let path = drop_css_extension(path);
427 fn rec(
428 deps: &HashMap<String, (Vec<String>, bool, Cell<bool>)>,
429 path: &str,
430 ret: &mut Vec<String>,
431 recursive: bool,
432 ) {
433 if let Some((x, _, rec_marked)) = deps.get(path) {
434 if rec_marked.get() {
435 return;
436 }
437 rec_marked.set(true);
438 if recursive {
439 for x in x.iter().map(|x| x.as_str()) {
440 rec(deps, x, ret, recursive);
441 }
442 }
443 ret.push(path.into());
444 rec_marked.set(false);
445 }
446 }
447 rec(&self.deps, path, &mut ret, recursive);
448 ret
449 }
450}
451
452#[cfg_attr(feature = "wasm-entrance", wasm_bindgen)]
453impl StyleSheetImportIndex {
454 #[cfg(feature = "wasm-entrance")]
456 #[wasm_bindgen(js_name = "queryAndMarkDependencies")]
457 pub fn js_query_and_mark_dependencies(&mut self, path: &str) -> JsValue {
458 let deps = self.query_and_mark_dependencies(path);
459 let ret = js_sys::Array::new_with_length(deps.len() as u32);
460 for dep in deps {
461 ret.push(&JsValue::from(dep));
462 }
463 ret.dyn_into().unwrap()
464 }
465
466 #[doc(hidden)]
467 #[cfg(all(feature = "serialize", feature = "serialize_json"))]
468 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "serializeJson"))]
469 pub fn serialize_json(&self) -> String {
470 let s = borrow_resource::StyleSheetImportIndex::from_sheet(self);
471 serde_json::to_string(&s).unwrap()
472 }
473
474 #[doc(hidden)]
475 #[cfg(all(feature = "deserialize", feature = "deserialize_json"))]
476 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "deserializeJson"))]
477 pub fn deserialize_json(s: &str) -> Self {
478 let s: Result<borrow_resource::StyleSheetImportIndex, _> = serde_json::from_str(s);
479 match s {
480 Ok(ss) => ss.into_sheet(),
481 Err(_) => {
482 error!("Failed to deserialize json formatted style sheet import index. Use empty content instead.");
483 Self {
484 deps: hashbrown::HashMap::default(),
485 }
486 }
487 }
488 }
489
490 #[cfg(feature = "serialize")]
492 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "serializeBincode"))]
493 pub fn serialize_bincode(&self) -> Vec<u8> {
494 use float_pigment_consistent_bincode::Options;
495 let s = borrow_resource::StyleSheetImportIndex::from_sheet(self);
496 float_pigment_consistent_bincode::DefaultOptions::new()
497 .allow_trailing_bytes()
498 .serialize(&s)
499 .unwrap()
500 }
501
502 #[cfg(feature = "deserialize")]
504 #[cfg_attr(
505 feature = "wasm-entrance",
506 wasm_bindgen(js_name = "deserializeBincode")
507 )]
508 pub fn deserialize_bincode(s: Vec<u8>) -> Self {
509 use float_pigment_consistent_bincode::Options;
510 let s: Result<borrow_resource::StyleSheetImportIndex, _> =
511 float_pigment_consistent_bincode::DefaultOptions::new()
512 .allow_trailing_bytes()
513 .deserialize(&s);
514 match s {
515 Ok(ss) => ss.into_sheet(),
516 Err(_) => {
517 error!("Failed to deserialize bincode formatted style sheet import index. Use empty content instead.");
518 Self {
519 deps: HashMap::default(),
520 }
521 }
522 }
523 }
524
525 #[cfg(feature = "deserialize")]
527 #[cfg_attr(feature = "wasm-entrance", wasm_bindgen(js_name = "mergeBincode"))]
528 pub fn merge_bincode(&mut self, s: Vec<u8>) {
529 use float_pigment_consistent_bincode::Options;
530 let s: Result<borrow_resource::StyleSheetImportIndex, _> =
531 float_pigment_consistent_bincode::DefaultOptions::new()
532 .allow_trailing_bytes()
533 .deserialize(&s);
534 match s {
535 Ok(ss) => ss.merge_to_sheet(self),
536 Err(_) => {
537 error!("Failed to merge bincode formatted style sheet import index. Use empty content instead.");
538 }
539 }
540 }
541}
542
543impl StyleSheetImportIndex {
544 #[cfg(feature = "deserialize")]
550 pub unsafe fn deserialize_bincode_zero_copy(
551 ptr: *mut [u8],
552 drop_callback: impl 'static + FnOnce(),
553 ) -> Self {
554 use float_pigment_consistent_bincode::Options;
555 borrow::de_static_ref_zero_copy_env(
556 ptr,
557 |s| {
558 let s: Result<borrow_resource::StyleSheetImportIndex, _> =
559 float_pigment_consistent_bincode::DefaultOptions::new()
560 .allow_trailing_bytes()
561 .deserialize(s);
562 match s {
563 Ok(ss) => ss.into_sheet(),
564 Err(_) => {
565 error!("Failed to deserialize bincode formatted style sheet import index. Use empty content instead.");
566 Self {
567 deps: HashMap::default(),
568 }
569 }
570 }
571 },
572 drop_callback,
573 )
574 }
575
576 #[cfg(feature = "deserialize")]
582 pub unsafe fn merge_bincode_zero_copy(
583 &mut self,
584 ptr: *mut [u8],
585 drop_callback: impl 'static + FnOnce(),
586 ) {
587 use float_pigment_consistent_bincode::Options;
588 borrow::de_static_ref_zero_copy_env(
589 ptr,
590 |s| {
591 let s: Result<borrow_resource::StyleSheetImportIndex, _> =
592 float_pigment_consistent_bincode::DefaultOptions::new()
593 .allow_trailing_bytes()
594 .deserialize(s);
595 match s {
596 Ok(ss) => ss.merge_to_sheet(self),
597 Err(_) => {
598 error!("Failed to merge bincode formatted style sheet import index. Use empty content instead.");
599 }
600 }
601 },
602 drop_callback,
603 )
604 }
605
606 #[doc(hidden)]
607 #[cfg(all(feature = "deserialize", feature = "deserialize_json"))]
611 pub unsafe fn deserialize_json_zero_copy(
612 ptr: *mut [u8],
613 drop_callback: impl 'static + FnOnce(),
614 ) -> Self {
615 borrow::de_static_ref_zero_copy_env(
616 ptr,
617 |s| {
618 let s: Result<borrow_resource::StyleSheetImportIndex, _> =
619 serde_json::from_str(std::str::from_utf8_unchecked(s));
620 match s {
621 Ok(ss) => ss.into_sheet(),
622 Err(_) => {
623 error!("Failed to deserialize json formatted style sheet import index. Use empty content instead.");
624 Self {
625 deps: hashbrown::HashMap::default(),
626 }
627 }
628 }
629 },
630 drop_callback,
631 )
632 }
633}
634
635pub const TEMP_SHEET_INDEX: u16 = u16::MAX;
637
638#[cfg_attr(feature = "wasm-entrance", wasm_bindgen)]
640#[derive(Default, Clone)]
641pub struct StyleSheetGroup {
642 sheets: Vec<LinkedStyleSheet>,
643 temp_sheet: Option<LinkedStyleSheet>,
644}
645
646impl StyleSheetGroup {
647 pub fn new() -> Self {
649 Self::default()
650 }
651
652 pub fn len(&self) -> u16 {
654 self.sheets.len() as u16
655 }
656
657 pub fn is_empty(&self) -> bool {
659 self.sheets.is_empty()
660 }
661
662 pub fn append(&mut self, sheet: LinkedStyleSheet) -> u16 {
664 let ret = self.sheets.len();
665 if Self::is_invalid_index(ret) {
666 panic!("The number of stylesheets has reached the maximum limit.")
667 }
668 self.sheets.push(sheet);
669 ret as u16
670 }
671
672 pub fn replace(&mut self, index: u16, sheet: LinkedStyleSheet) {
674 self.sheets[index as usize] = sheet;
675 }
676
677 pub fn append_from_resource(
679 &mut self,
680 res: &StyleSheetResource,
681 path: &str,
682 scope: Option<NonZeroUsize>,
683 ) -> u16 {
684 self.append_from_resource_with_warnings(res, path, scope).0
685 }
686
687 pub fn append_from_resource_with_warnings(
689 &mut self,
690 res: &StyleSheetResource,
691 path: &str,
692 scope: Option<NonZeroUsize>,
693 ) -> (u16, Vec<Warning>) {
694 let path = drop_css_extension(path);
695 let (ss, warnings) = res.link(path, scope);
696 let ret = self.sheets.len();
697 if Self::is_invalid_index(ret) {
698 panic!("The number of stylesheets has reached the maximum limit.")
699 }
700 self.sheets.push(ss);
701 (ret as u16, warnings)
702 }
703
704 pub fn replace_from_resource(
706 &mut self,
707 index: u16,
708 res: &StyleSheetResource,
709 path: &str,
710 scope: Option<NonZeroUsize>,
711 ) {
712 let path = drop_css_extension(path);
713 let (ss, _warnings) = res.link(path, scope);
714 self.sheets[index as usize] = ss;
715 }
716
717 pub fn clear(&mut self) {
719 self.sheets.truncate(0);
720 }
721
722 pub fn style_sheet(&self, sheet_index: u16) -> Option<&LinkedStyleSheet> {
724 if sheet_index != TEMP_SHEET_INDEX {
725 self.sheets.get(sheet_index as usize)
726 } else {
727 self.temp_sheet.as_ref()
728 }
729 }
730
731 pub fn get_font_face(&self, sheet_index: u16) -> Option<Vec<Rc<FontFace>>> {
733 self.style_sheet(sheet_index)
734 .map(|sheet| sheet.get_font_face())
735 }
736
737 pub fn get_rule(&self, sheet_index: u16, rule_index: u32) -> Option<Rc<Rule>> {
741 if let Some(sheet) = self.style_sheet(sheet_index) {
742 sheet.get_rule(rule_index)
743 } else {
744 None
745 }
746 }
747
748 pub fn add_rule(&mut self, rule: Box<Rule>) -> u32 {
755 if self.temp_sheet.is_none() {
756 self.temp_sheet = Some(LinkedStyleSheet::new_empty());
757 }
758 let sheet = self.temp_sheet.as_mut().unwrap();
759 sheet.add_rule(rule)
760 }
761
762 pub fn replace_rule(
769 &mut self,
770 sheet_index: u16,
771 rule_index: u32,
772 rule: Box<Rule>,
773 ) -> Result<Rc<Rule>, Box<Rule>> {
774 let sheet = if sheet_index != TEMP_SHEET_INDEX {
775 self.sheets.get_mut(sheet_index as usize)
776 } else {
777 self.temp_sheet.as_mut()
778 };
779 if let Some(sheet) = sheet {
780 sheet.replace_rule(rule_index, rule)
781 } else {
782 Err(rule)
783 }
784 }
785
786 pub fn query_single<L: LengthNum, T: StyleNode>(
790 &self,
791 query: T,
792 media_query_status: &MediaQueryStatus<L>,
793 node_properties: &mut NodeProperties,
794 ) {
795 self.query_ancestor_path(&[query], media_query_status, node_properties, None)
796 }
797
798 pub fn for_each_matched_rule<L: LengthNum, T: StyleNode>(
802 &self,
803 query: &[T],
804 media_query_status: &MediaQueryStatus<L>,
805 mut f: impl FnMut(MatchedRuleRef, Option<&LinkedStyleSheet>),
806 ) {
807 for (index, sheet) in self.sheets.iter().enumerate() {
808 sheet.for_each_matched_rule(
809 query,
810 media_query_status,
811 index.min((TEMP_SHEET_INDEX - 1) as usize) as u16,
812 |r| f(r, Some(sheet)),
813 );
814 }
815 if let Some(sheet) = self.temp_sheet.as_ref() {
816 sheet.for_each_matched_rule(query, media_query_status, u16::MAX, |r| f(r, None));
817 }
818 }
819
820 pub fn query_matched_rules<L: LengthNum, T: StyleNode>(
824 &self,
825 query: &[T],
826 media_query_status: &MediaQueryStatus<L>,
827 ) -> MatchedRuleList {
828 let mut rules = vec![];
829 self.for_each_matched_rule(query, media_query_status, |matched_rule, style_sheet| {
830 let r = MatchedRule {
831 rule: matched_rule.rule.clone(),
832 weight: matched_rule.weight,
833 style_scope: style_sheet.and_then(|x| x.scope()),
834 };
835 rules.push(r);
836 });
837 MatchedRuleList { rules }
838 }
839
840 pub fn query_ancestor_path<L: LengthNum, T: StyleNode>(
845 &self,
846 query: &[T],
847 media_query_status: &MediaQueryStatus<L>,
848 node_properties: &mut NodeProperties,
849 parent_node_properties: Option<&NodeProperties>,
850 ) {
851 let default_font_size = media_query_status.base_font_size.to_f32();
852 let parent_font_size = match parent_node_properties {
853 None => default_font_size,
854 Some(x) => x
855 .font_size_ref()
856 .resolve_to_f32(media_query_status, default_font_size, true)
857 .unwrap_or(default_font_size),
858 };
859 let rules = self.query_matched_rules(query, media_query_status);
860 let current_font_size = rules.get_current_font_size(
861 parent_font_size,
862 parent_node_properties,
863 &[],
864 media_query_status,
865 );
866 rules.merge_node_properties(
867 node_properties,
868 parent_node_properties,
869 current_font_size,
870 &[],
871 );
872 }
873
874 fn is_invalid_index(idx: usize) -> bool {
875 idx > (u16::MAX as usize)
876 }
877
878 pub fn search_keyframes<L: LengthNum>(
880 &self,
881 style_scope: Option<NonZeroUsize>,
882 name: &str,
883 media_query_status: &MediaQueryStatus<L>,
884 ) -> Option<Rc<KeyFrames>> {
885 if let Some(sheet) = self.temp_sheet.as_ref() {
886 if let Some(x) = sheet.search_keyframes(style_scope, name, media_query_status) {
887 return Some(x);
888 }
889 }
890 for sheet in self.sheets.iter().rev() {
891 if let Some(x) = sheet.search_keyframes(style_scope, name, media_query_status) {
892 return Some(x);
893 }
894 }
895 None
896 }
897}