tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

font-computed.html (6545B)


      1 <!DOCTYPE html>
      2 <html>
      3 <head>
      4 <meta charset="utf-8">
      5 <title>CSS Fonts Module Level 4: getComputedStyle().font</title>
      6 <link rel="help" href="https://drafts.csswg.org/css-fonts-4/#font-prop">
      7 <meta name="assert" content="font computed value round-trips.">
      8 <script src="/resources/testharness.js"></script>
      9 <script src="/resources/testharnessreport.js"></script>
     10 <script src="/css/support/computed-testcommon.js"></script>
     11 <style>
     12  #container {
     13    font-weight: 800;
     14    font-size: 40px;
     15  }
     16 </style>
     17 </head>
     18 <body>
     19 <div id="container">
     20  <div id="target"></div>
     21 </div>
     22 <script>
     23 'use strict';
     24 
     25 // Firefox and Edge 18 serialize these as supplied.
     26 // Blink and Safari have implementation-dependent or platform-dependent serializations.
     27 function test_system_font(keyword) {
     28  test(() => {
     29    const target = document.getElementById('target');
     30    const previousValue = 'italic xx-large/0px fantasy';
     31    target.style.font = previousValue;
     32    target.style.font = keyword;
     33    const readValue = getComputedStyle(target).font;
     34    assert_not_equals(readValue, '', 'font should be set');
     35    assert_not_equals(readValue, previousValue, 'font should be updated');
     36    target.style.font = previousValue;
     37    target.style.font = readValue;
     38    assert_equals(getComputedStyle(target).font, readValue, "serialization should round-trip");
     39  }, keyword + ' should be a supported system font.');
     40 }
     41 
     42 test_system_font('caption');
     43 test_system_font('icon');
     44 test_system_font('menu');
     45 test_system_font('message-box');
     46 test_system_font('small-caption');
     47 test_system_font('status-bar');
     48 
     49 // a value other than normal
     50 const generate_style = () => 'italic';
     51 
     52 // value other than normal
     53 const generate_variant = () => 'small-caps';
     54 
     55 // values other than normal
     56 const generate_weight = (() => {
     57  const alternatives = [
     58    'bold',
     59    'bolder',
     60    'lighter',
     61    '100',
     62    '900'
     63  ];
     64  let counter = 0;
     65  return () => alternatives[counter++ % alternatives.length];
     66 })();
     67 
     68 const compute_weight = (() => {
     69  const cache = {}
     70  return (weight) => {
     71    if (!(weight in cache)) {
     72      const weight_reference = document.createElement('div');
     73      document.getElementById('container').appendChild(weight_reference);
     74      weight_reference.style.fontWeight = weight;
     75      cache[weight] = getComputedStyle(weight_reference).fontWeight;
     76      weight_reference.remove();
     77    }
     78    return cache[weight];
     79  }
     80 })();
     81 
     82 // values other than normal
     83 const generate_stretch = (() => {
     84  const alternatives = [
     85    'ultra-condensed',
     86    'extra-condensed',
     87    'condensed',
     88    'semi-condensed',
     89    'semi-expanded',
     90    'expanded',
     91    'extra-expanded',
     92    'ultra-expanded'
     93  ];
     94  let counter = 0;
     95  return () => alternatives[counter++ % alternatives.length];
     96 })();
     97 
     98 const generate_size = (() => {
     99  const alternatives = [
    100    // <absolute-size>
    101    'xx-small',
    102    'medium',
    103    'xx-large',
    104 
    105    // <relative-size>
    106    'larger',
    107    'smaller',
    108 
    109    // <length-percentage>
    110    '10px',
    111    '20%',
    112    'calc(30% - 40px)',
    113  ];
    114  let counter = 0;
    115  return () => alternatives[counter++ % alternatives.length];
    116 })();
    117 
    118 const generate_line_height = (() => {
    119  const alternatives = [
    120    null,
    121    'normal',
    122    '1.2',
    123    'calc(120% + 1.2em)'
    124  ];
    125  let counter = 0;
    126  return () => alternatives[counter++ % alternatives.length];
    127 })();
    128 
    129 const generate_family = (() => {
    130  const alternatives = [
    131    'serif',
    132    'sans-serif',
    133    'cursive',
    134    'fantasy',
    135    'monospace',
    136    'Menu',
    137    '"Non-Generic Example Family Name"'
    138  ];
    139  let counter = 0;
    140  return () => alternatives[counter++ % alternatives.length];
    141 })();
    142 
    143 function test_specific(prefix) {
    144  const reference = document.createElement('div');
    145  document.getElementById('container').appendChild(reference);
    146 
    147  let parts = [];
    148  let canonical = [];
    149  let style = null;
    150  let variant = null;
    151  let weight = null;
    152  let stretch = null;
    153  for (let entry of prefix) {
    154    if (entry === 'style') {
    155      style = generate_style();
    156      parts.push(style);
    157    } else if (entry === 'variant') {
    158      variant = generate_variant();
    159      parts.push(variant);
    160    } else if (entry === 'weight') {
    161      weight = generate_weight();
    162      parts.push(weight);
    163    } else if (entry === 'stretch') {
    164      stretch = generate_stretch();
    165      parts.push(stretch);
    166    } else {
    167      // normal
    168      parts.push('normal');
    169    }
    170  }
    171 
    172  if (style) {
    173    canonical.push(style);
    174    reference.style.fontStyle = style;
    175  }
    176 
    177  if (variant) {
    178    canonical.push(variant);
    179    reference.style.fontVariant = style;
    180  }
    181  if (weight) {
    182    canonical.push(compute_weight(weight));
    183    reference.style.fontWeight = style;
    184  }
    185  if (stretch) {
    186    canonical.push(stretch);
    187    reference.style.fontStretch = style;
    188  }
    189 
    190  const size = generate_size();
    191  reference.style.fontSize = size;
    192  const line_height = generate_line_height();
    193  if (line_height) {
    194    parts.push(size + '/' + line_height);
    195    reference.style.lineHeight = line_height;
    196  } else {
    197    parts.push(size);
    198  }
    199 
    200  const family = generate_family();
    201  parts.push(family);
    202  reference.style.fontFamily = family;
    203 
    204  if (!line_height || line_height === 'normal') {
    205    canonical.push(getComputedStyle(reference).fontSize);
    206  } else {
    207    // Implementations differ on adjacent space when serializing '/'
    208    // https://github.com/w3c/csswg-drafts/issues/4282
    209    canonical.push(getComputedStyle(reference).fontSize + ' / ' + getComputedStyle(reference).lineHeight);
    210  }
    211 
    212  canonical.push(family);
    213 
    214  reference.remove();
    215 
    216  test_computed_value('font', parts.join(' '), canonical.join(' '));
    217 }
    218 
    219 // Font style, variant, weight and stretch may appear in any order.
    220 // Any or all may be omitted. Each accepts the keyword 'normal'.
    221 // We generate every permutation of these four properties, treating
    222 // the cases of a property value being omitted or being explicitly
    223 // 'normal' as being distinct permutations from when the property
    224 // has a value other than 'normal'.
    225 function test_various(prefix) {
    226  test_specific(prefix);
    227  if (prefix.length === 4) {
    228    // Font style, variant, weight and stretch may not appear
    229    // more than once.
    230    return;
    231  }
    232 
    233  const alternatives = [
    234    'normal',
    235    'style',
    236    'variant',
    237    'weight',
    238    'stretch'
    239  ];
    240  for (let alternative of alternatives) {
    241    // Since this is called recursively, check prefix for existing
    242    // alternatives, otherwise we may have two styles or two variants, etc.
    243    if (alternative === 'normal' || !prefix.includes(alternative))
    244      test_various(prefix.concat(alternative));
    245  }
    246 }
    247 
    248 test_various([]);
    249 </script>
    250 </body>
    251 </html>