// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.text.measure.getActualBoundingBox.tentative
// Description:
// Note:

importScripts("/resources/testharness.js");
importScripts("/html/canvas/resources/canvas-tests.js");

promise_test(async t => {
  const canvas = new OffscreenCanvas(800, 200);
  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
    };
  }

  // Returns a string a replaces the characters in text that are not in the
  // range [start, end) with spaces.
  function buildTestString(text, start, end) {
    let ret = '';
    for (let i = 0; i < text.length; ++i) {
      if (start <= i && i < end)
        ret += text[i];
      else
        ret += ' ';
    }
    return ret;
  }

  function checkRectsMatch(rect_a, rect_b, text, start, end) {
    assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
    assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
    assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
    assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
  }

  function testForSubstring(text, start, end) {
    const textMetrics = ctx.measureText(text);
    const rect_from_api = textMetrics.getActualBoundingBox(start, end);
    const rect_from_full_bounds = getFullTextBoundingBox(
                                    buildTestString(text, start, end));
    checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
  }

  var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
  f.load();
  self.fonts.add(f);
  await self.fonts.ready;
  ctx.textAlign = 'left';
  ctx.letterSpacing = '0px';

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

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

  ctx.font = '50px CanvasTest';
  const text = 'ABCDE';
  for (const align of kAligns) {
    for (const baseline of kBaselines) {
      ctx.textAlign = align;
      ctx.textBaseline = baseline;
      // Full string.
      testForSubstring(text, 0, text.length);
      // Intermediate string.
      testForSubstring(text, 1, text.length - 1);
      // First character.
      testForSubstring(text, 0, 1);
      // Intermediate character.
      testForSubstring(text, 2, 3);
    }
  }
}, "Test TextMetrics::getActualBoundingBox(), with text align left , and 0px letter spacing.");

promise_test(async t => {
  const canvas = new OffscreenCanvas(800, 200);
  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
    };
  }

  // Returns a string a replaces the characters in text that are not in the
  // range [start, end) with spaces.
  function buildTestString(text, start, end) {
    let ret = '';
    for (let i = 0; i < text.length; ++i) {
      if (start <= i && i < end)
        ret += text[i];
      else
        ret += ' ';
    }
    return ret;
  }

  function checkRectsMatch(rect_a, rect_b, text, start, end) {
    assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
    assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
    assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
    assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
  }

  function testForSubstring(text, start, end) {
    const textMetrics = ctx.measureText(text);
    const rect_from_api = textMetrics.getActualBoundingBox(start, end);
    const rect_from_full_bounds = getFullTextBoundingBox(
                                    buildTestString(text, start, end));
    checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
  }

  var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
  f.load();
  self.fonts.add(f);
  await self.fonts.ready;
  ctx.textAlign = 'center';
  ctx.letterSpacing = '0px';

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

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

  ctx.font = '50px CanvasTest';
  const text = 'ABCDE';
  for (const align of kAligns) {
    for (const baseline of kBaselines) {
      ctx.textAlign = align;
      ctx.textBaseline = baseline;
      // Full string.
      testForSubstring(text, 0, text.length);
      // Intermediate string.
      testForSubstring(text, 1, text.length - 1);
      // First character.
      testForSubstring(text, 0, 1);
      // Intermediate character.
      testForSubstring(text, 2, 3);
    }
  }
}, "Test TextMetrics::getActualBoundingBox(), with text align center , and 0px letter spacing.");

promise_test(async t => {
  const canvas = new OffscreenCanvas(800, 200);
  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
    };
  }

  // Returns a string a replaces the characters in text that are not in the
  // range [start, end) with spaces.
  function buildTestString(text, start, end) {
    let ret = '';
    for (let i = 0; i < text.length; ++i) {
      if (start <= i && i < end)
        ret += text[i];
      else
        ret += ' ';
    }
    return ret;
  }

  function checkRectsMatch(rect_a, rect_b, text, start, end) {
    assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
    assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
    assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
    assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
  }

  function testForSubstring(text, start, end) {
    const textMetrics = ctx.measureText(text);
    const rect_from_api = textMetrics.getActualBoundingBox(start, end);
    const rect_from_full_bounds = getFullTextBoundingBox(
                                    buildTestString(text, start, end));
    checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
  }

  var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
  f.load();
  self.fonts.add(f);
  await self.fonts.ready;
  ctx.textAlign = 'right';
  ctx.letterSpacing = '0px';

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

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

  ctx.font = '50px CanvasTest';
  const text = 'ABCDE';
  for (const align of kAligns) {
    for (const baseline of kBaselines) {
      ctx.textAlign = align;
      ctx.textBaseline = baseline;
      // Full string.
      testForSubstring(text, 0, text.length);
      // Intermediate string.
      testForSubstring(text, 1, text.length - 1);
      // First character.
      testForSubstring(text, 0, 1);
      // Intermediate character.
      testForSubstring(text, 2, 3);
    }
  }
}, "Test TextMetrics::getActualBoundingBox(), with text align right , and 0px letter spacing.");

promise_test(async t => {
  const canvas = new OffscreenCanvas(800, 200);
  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
    };
  }

  // Returns a string a replaces the characters in text that are not in the
  // range [start, end) with spaces.
  function buildTestString(text, start, end) {
    let ret = '';
    for (let i = 0; i < text.length; ++i) {
      if (start <= i && i < end)
        ret += text[i];
      else
        ret += ' ';
    }
    return ret;
  }

  function checkRectsMatch(rect_a, rect_b, text, start, end) {
    assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
    assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
    assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
    assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
  }

  function testForSubstring(text, start, end) {
    const textMetrics = ctx.measureText(text);
    const rect_from_api = textMetrics.getActualBoundingBox(start, end);
    const rect_from_full_bounds = getFullTextBoundingBox(
                                    buildTestString(text, start, end));
    checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
  }

  var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
  f.load();
  self.fonts.add(f);
  await self.fonts.ready;
  ctx.textAlign = 'left';
  ctx.letterSpacing = '10px';

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

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

  ctx.font = '50px CanvasTest';
  const text = 'ABCDE';
  for (const align of kAligns) {
    for (const baseline of kBaselines) {
      ctx.textAlign = align;
      ctx.textBaseline = baseline;
      // Full string.
      testForSubstring(text, 0, text.length);
      // Intermediate string.
      testForSubstring(text, 1, text.length - 1);
      // First character.
      testForSubstring(text, 0, 1);
      // Intermediate character.
      testForSubstring(text, 2, 3);
    }
  }
}, "Test TextMetrics::getActualBoundingBox(), with text align left , and 10px letter spacing.");

promise_test(async t => {
  const canvas = new OffscreenCanvas(800, 200);
  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
    };
  }

  // Returns a string a replaces the characters in text that are not in the
  // range [start, end) with spaces.
  function buildTestString(text, start, end) {
    let ret = '';
    for (let i = 0; i < text.length; ++i) {
      if (start <= i && i < end)
        ret += text[i];
      else
        ret += ' ';
    }
    return ret;
  }

  function checkRectsMatch(rect_a, rect_b, text, start, end) {
    assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
    assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
    assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
    assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
  }

  function testForSubstring(text, start, end) {
    const textMetrics = ctx.measureText(text);
    const rect_from_api = textMetrics.getActualBoundingBox(start, end);
    const rect_from_full_bounds = getFullTextBoundingBox(
                                    buildTestString(text, start, end));
    checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
  }

  var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
  f.load();
  self.fonts.add(f);
  await self.fonts.ready;
  ctx.textAlign = 'center';
  ctx.letterSpacing = '10px';

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

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

  ctx.font = '50px CanvasTest';
  const text = 'ABCDE';
  for (const align of kAligns) {
    for (const baseline of kBaselines) {
      ctx.textAlign = align;
      ctx.textBaseline = baseline;
      // Full string.
      testForSubstring(text, 0, text.length);
      // Intermediate string.
      testForSubstring(text, 1, text.length - 1);
      // First character.
      testForSubstring(text, 0, 1);
      // Intermediate character.
      testForSubstring(text, 2, 3);
    }
  }
}, "Test TextMetrics::getActualBoundingBox(), with text align center , and 10px letter spacing.");

promise_test(async t => {
  const canvas = new OffscreenCanvas(800, 200);
  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
    };
  }

  // Returns a string a replaces the characters in text that are not in the
  // range [start, end) with spaces.
  function buildTestString(text, start, end) {
    let ret = '';
    for (let i = 0; i < text.length; ++i) {
      if (start <= i && i < end)
        ret += text[i];
      else
        ret += ' ';
    }
    return ret;
  }

  function checkRectsMatch(rect_a, rect_b, text, start, end) {
    assert_approx_equals(rect_a.x, rect_b.x, 1.0, `${text} :: x :: ${start} to ${end}`);
    assert_approx_equals(rect_a.y, rect_b.y, 1.0, `${text} :: y :: ${start} to ${end}`);
    assert_approx_equals(rect_a.width, rect_b.width, 1.0, `${text} :: width :: ${start} to ${end}`);
    assert_approx_equals(rect_a.height, rect_b.height, 1.0, `${text} :: height :: ${start} to ${end}`);
  }

  function testForSubstring(text, start, end) {
    const textMetrics = ctx.measureText(text);
    const rect_from_api = textMetrics.getActualBoundingBox(start, end);
    const rect_from_full_bounds = getFullTextBoundingBox(
                                    buildTestString(text, start, end));
    checkRectsMatch(rect_from_api, rect_from_full_bounds, buildTestString(text, start, end), start, end);
  }

  var f = new FontFace("CanvasTest", "url('/fonts/CanvasTest.ttf')");
  f.load();
  self.fonts.add(f);
  await self.fonts.ready;
  ctx.textAlign = 'right';
  ctx.letterSpacing = '10px';

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

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

  ctx.font = '50px CanvasTest';
  const text = 'ABCDE';
  for (const align of kAligns) {
    for (const baseline of kBaselines) {
      ctx.textAlign = align;
      ctx.textBaseline = baseline;
      // Full string.
      testForSubstring(text, 0, text.length);
      // Intermediate string.
      testForSubstring(text, 1, text.length - 1);
      // First character.
      testForSubstring(text, 0, 1);
      // Intermediate character.
      testForSubstring(text, 2, 3);
    }
  }
}, "Test TextMetrics::getActualBoundingBox(), with text align right , and 10px letter spacing.");

done();
