chromium/third_party/blink/web_tests/external/wpt/html/canvas/element/text/2d.text.measure.getActualBoundingBox-full-text.tentative.html

<!DOCTYPE html>
<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
<title>Canvas test: 2d.text.measure.getActualBoundingBox-full-text.tentative</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/html/canvas/resources/canvas-tests.js"></script>
<link rel="stylesheet" href="/html/canvas/resources/canvas-tests.css">

<h1>2d.text.measure.getActualBoundingBox-full-text.tentative</h1>

<script>

test(t => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  // Use measureText to create a rect for the whole text
  function getFullTextBoundingBox(text) {
    const tm = ctx.measureText(text);
    return {
      x: -tm.actualBoundingBoxLeft,
      y: -tm.actualBoundingBoxAscent,
      width: tm.actualBoundingBoxLeft + tm.actualBoundingBoxRight,
      height: tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
    };
  }

  function checkRectsMatch(rect_a, rect_b) {
    assert_approx_equals(rect_a.x, rect_b.x, 1.0);
    assert_approx_equals(rect_a.y, rect_b.y, 1.0);
    assert_approx_equals(rect_a.width, rect_b.width, 1.0);
    assert_approx_equals(rect_a.height, rect_b.height, 1.0);
  }

  const kAligns = [
    'left',
    'center',
    'right',
  ];

  const kBaselines = [
    'top',
    'hanging',
    'middle',
    'alphabetic',
    'ideographic',
    'bottom',
  ];

  const kTexts = [
    'UNAVAILABLE',
    '🏁🎢🏁',
    'οΌ‰οΌˆγ‚οΌ‰οΌˆ',
    '-abcd '
  ]

  ctx.font = '50px sans-serif';
  ctx.direction = 'ltr';
  for (const align of kAligns) {
    for (const baseline of kBaselines) {
      ctx.textAlign = align;
      ctx.textBaseline = baseline;
      for (text of kTexts) {
        const tm = ctx.measureText(text);
        const rect_from_api = tm.getActualBoundingBox(0, text.length);
        const rect_from_full_bounds = getFullTextBoundingBox(text);
        checkRectsMatch(rect_from_api, rect_from_full_bounds)
      }
    }
  }
}, "Test TextMetrics::getActualBoundingBox() for the full length of the string for some edge cases, with direction ltr and no-directional-override");

test(t => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  // Use measureText to create a rect for the whole text
  function getFullTextBoundingBox(text) {
    const tm = ctx.measureText(text);
    return {
      x: -tm.actualBoundingBoxLeft,
      y: -tm.actualBoundingBoxAscent,
      width: tm.actualBoundingBoxLeft + tm.actualBoundingBoxRight,
      height: tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
    };
  }

  function checkRectsMatch(rect_a, rect_b) {
    assert_approx_equals(rect_a.x, rect_b.x, 1.0);
    assert_approx_equals(rect_a.y, rect_b.y, 1.0);
    assert_approx_equals(rect_a.width, rect_b.width, 1.0);
    assert_approx_equals(rect_a.height, rect_b.height, 1.0);
  }

  const kAligns = [
    'left',
    'center',
    'right',
  ];

  const kBaselines = [
    'top',
    'hanging',
    'middle',
    'alphabetic',
    'ideographic',
    'bottom',
  ];

  const kTexts = [
    'UNAVAILABLE',
    '🏁🎢🏁',
    'οΌ‰οΌˆγ‚οΌ‰οΌˆ',
    '-abcd '
  ]

  ctx.font = '50px sans-serif';
  ctx.direction = 'rtl';
  for (const align of kAligns) {
    for (const baseline of kBaselines) {
      ctx.textAlign = align;
      ctx.textBaseline = baseline;
      for (text of kTexts) {
        const tm = ctx.measureText(text);
        const rect_from_api = tm.getActualBoundingBox(0, text.length);
        const rect_from_full_bounds = getFullTextBoundingBox(text);
        checkRectsMatch(rect_from_api, rect_from_full_bounds)
      }
    }
  }
}, "Test TextMetrics::getActualBoundingBox() for the full length of the string for some edge cases, with direction rtl and no-directional-override");

test(t => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  // Use measureText to create a rect for the whole text
  function getFullTextBoundingBox(text) {
    const tm = ctx.measureText(text);
    return {
      x: -tm.actualBoundingBoxLeft,
      y: -tm.actualBoundingBoxAscent,
      width: tm.actualBoundingBoxLeft + tm.actualBoundingBoxRight,
      height: tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
    };
  }

  function checkRectsMatch(rect_a, rect_b) {
    assert_approx_equals(rect_a.x, rect_b.x, 1.0);
    assert_approx_equals(rect_a.y, rect_b.y, 1.0);
    assert_approx_equals(rect_a.width, rect_b.width, 1.0);
    assert_approx_equals(rect_a.height, rect_b.height, 1.0);
  }

  function addDirectionalOverrideCharacters(text, direction_is_ltr) {
    // source: www.w3.org/International/questions/qa-bidi-unicode-controls.en
    const LTR_OVERRIDE = '\u202D';
    const RTL_OVERRIDE = '\u202E';
    const OVERRIDE_END = '\u202C';
    if (direction_is_ltr) {
      return LTR_OVERRIDE + text + OVERRIDE_END;
    }
    return RTL_OVERRIDE + text + OVERRIDE_END;
  }

  const kAligns = [
    'left',
    'center',
    'right',
  ];

  const kBaselines = [
    'top',
    'hanging',
    'middle',
    'alphabetic',
    'ideographic',
    'bottom',
  ];

  const kTexts = [
    'UNAVAILABLE',
    '🏁🎢🏁',
    'οΌ‰οΌˆγ‚οΌ‰οΌˆ',
    '-abcd '
  ]

  ctx.font = '50px sans-serif';
  ctx.direction = 'ltr';
  for (const align of kAligns) {
    for (const baseline of kBaselines) {
      ctx.textAlign = align;
      ctx.textBaseline = baseline;
      for (text of kTexts) {
        text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr');
        const tm = ctx.measureText(text);
        const rect_from_api = tm.getActualBoundingBox(0, text.length);
        const rect_from_full_bounds = getFullTextBoundingBox(text);
        checkRectsMatch(rect_from_api, rect_from_full_bounds)
      }
    }
  }
}, "Test TextMetrics::getActualBoundingBox() for the full length of the string for some edge cases, with direction ltr and directional-override");

test(t => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  // Use measureText to create a rect for the whole text
  function getFullTextBoundingBox(text) {
    const tm = ctx.measureText(text);
    return {
      x: -tm.actualBoundingBoxLeft,
      y: -tm.actualBoundingBoxAscent,
      width: tm.actualBoundingBoxLeft + tm.actualBoundingBoxRight,
      height: tm.actualBoundingBoxAscent + tm.actualBoundingBoxDescent
    };
  }

  function checkRectsMatch(rect_a, rect_b) {
    assert_approx_equals(rect_a.x, rect_b.x, 1.0);
    assert_approx_equals(rect_a.y, rect_b.y, 1.0);
    assert_approx_equals(rect_a.width, rect_b.width, 1.0);
    assert_approx_equals(rect_a.height, rect_b.height, 1.0);
  }

  function addDirectionalOverrideCharacters(text, direction_is_ltr) {
    // source: www.w3.org/International/questions/qa-bidi-unicode-controls.en
    const LTR_OVERRIDE = '\u202D';
    const RTL_OVERRIDE = '\u202E';
    const OVERRIDE_END = '\u202C';
    if (direction_is_ltr) {
      return LTR_OVERRIDE + text + OVERRIDE_END;
    }
    return RTL_OVERRIDE + text + OVERRIDE_END;
  }

  const kAligns = [
    'left',
    'center',
    'right',
  ];

  const kBaselines = [
    'top',
    'hanging',
    'middle',
    'alphabetic',
    'ideographic',
    'bottom',
  ];

  const kTexts = [
    'UNAVAILABLE',
    '🏁🎢🏁',
    'οΌ‰οΌˆγ‚οΌ‰οΌˆ',
    '-abcd '
  ]

  ctx.font = '50px sans-serif';
  ctx.direction = 'rtl';
  for (const align of kAligns) {
    for (const baseline of kBaselines) {
      ctx.textAlign = align;
      ctx.textBaseline = baseline;
      for (text of kTexts) {
        text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr');
        const tm = ctx.measureText(text);
        const rect_from_api = tm.getActualBoundingBox(0, text.length);
        const rect_from_full_bounds = getFullTextBoundingBox(text);
        checkRectsMatch(rect_from_api, rect_from_full_bounds)
      }
    }
  }
}, "Test TextMetrics::getActualBoundingBox() for the full length of the string for some edge cases, with direction rtl and directional-override");

</script>
</div>