@@ -9,6 +9,7 @@ use crate::properties::custom::CustomProperty;
99use crate :: macros:: enum_property;
1010use crate :: values:: { url:: Url } ;
1111use crate :: error:: { ParserError , PrinterError } ;
12+ use std:: fmt:: Write ;
1213
1314#[ derive( Debug , PartialEq , Clone ) ]
1415pub struct FontFaceRule < ' i > {
@@ -23,6 +24,7 @@ pub enum FontFaceProperty<'i> {
2324 FontStyle ( FontStyle ) ,
2425 FontWeight ( Size2D < FontWeight > ) ,
2526 FontStretch ( Size2D < FontStretch > ) ,
27+ UnicodeRange ( Vec < UnicodeRange > ) ,
2628 Custom ( CustomProperty < ' i > )
2729}
2830
@@ -254,6 +256,60 @@ impl ToCss for FontTechnology {
254256 }
255257}
256258
259+ impl < ' i > Parse < ' i > for UnicodeRange {
260+ fn parse < ' t > ( input : & mut Parser < ' i , ' t > ) -> Result < Self , ParseError < ' i , ParserError < ' i > > > {
261+ let range = UnicodeRange :: parse ( input) ?;
262+ Ok ( range)
263+ }
264+ }
265+
266+ impl ToCss for UnicodeRange {
267+ fn to_css < W > ( & self , dest : & mut Printer < W > ) -> Result < ( ) , PrinterError > where W : std:: fmt:: Write {
268+ // Attempt to optimize the range to use question mark syntax.
269+ if self . start != self . end {
270+ // Find the first hex digit that differs between the start and end values.
271+ let mut shift = 24 ;
272+ let mut mask = 0xf << shift;
273+ while shift > 0 {
274+ let c1 = self . start & mask;
275+ let c2 = self . end & mask;
276+ if c1 != c2 {
277+ break
278+ }
279+
280+ mask = mask >> 4 ;
281+ shift -= 4 ;
282+ }
283+
284+ // Get the remainder of the value. This must be 0x0 to 0xf for the rest
285+ // of the value to use the question mark syntax.
286+ let remainder_mask = ( 0xf << shift) - 1 | ( 1 << shift) ;
287+ let start_remainder = self . start & remainder_mask;
288+ let end_remainder = self . end & remainder_mask;
289+
290+ if start_remainder == 0 && end_remainder == remainder_mask {
291+ shift += 4 ;
292+ let start = ( self . start & !remainder_mask) >> shift;
293+ if start != 0 {
294+ write ! ( dest, "U+{:X}" , start) ?;
295+ } else {
296+ dest. write_str ( "U+" ) ?;
297+ }
298+
299+ while shift > 0 {
300+ dest. write_char ( '?' ) ?;
301+ shift -= 4 ;
302+ }
303+
304+ return Ok ( ( ) )
305+ }
306+ }
307+
308+ cssparser:: ToCss :: to_css ( self , dest) ?;
309+ Ok ( ( ) )
310+ }
311+ }
312+
257313pub ( crate ) struct FontFaceDeclarationParser ;
258314
259315/// Parse a declaration within {} block: `color: blue`
@@ -285,6 +341,7 @@ impl<'i> cssparser::DeclarationParser<'i> for FontFaceDeclarationParser {
285341 "font-weight" => property!( FontWeight , Size2D <FontWeight >) ,
286342 "font-style" => property!( FontStyle , FontStyle ) ,
287343 "font-stretch" => property!( FontStretch , Size2D <FontStretch >) ,
344+ "unicode-range" => property!( UnicodeRange , Vec <UnicodeRange >) ,
288345 _ => { }
289346 }
290347
@@ -350,6 +407,7 @@ impl<'i> ToCss for FontFaceProperty<'i> {
350407 FontStyle ( value) => property ! ( "font-style" , value) ,
351408 FontWeight ( value) => property ! ( "font-weight" , value) ,
352409 FontStretch ( value) => property ! ( "font-stretch" , value) ,
410+ UnicodeRange ( value) => property ! ( "unicode-range" , value) ,
353411 Custom ( custom) => {
354412 dest. write_str ( custom. name . as_ref ( ) ) ?;
355413 dest. delim ( ':' , false ) ?;
0 commit comments