| <!DOCTYPE html> |
| <!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. --> |
| <meta charset="UTF-8"> |
| <title>OffscreenCanvas test: 2d.text.measure.index-from-offset.tentative</title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/html/canvas/resources/canvas-tests.js"></script> |
| |
| <h1>2d.text.measure.index-from-offset.tentative</h1> |
| |
| <script> |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('left' == 'center') { |
| offset -= width / 2; |
| } else if ('left' == 'right' || |
| ('ltr' == 'ltr' && 'left' == 'end') || |
| ('ltr' == 'rtl' && 'left' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('left' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('left' == 'right' || |
| ('ltr' == 'ltr' && 'left' == 'end') || |
| ('ltr' == 'rtl' && 'left' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'left'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align left, 0px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('left' == 'center') { |
| offset -= width / 2; |
| } else if ('left' == 'right' || |
| ('rtl' == 'ltr' && 'left' == 'end') || |
| ('rtl' == 'rtl' && 'left' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('left' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('left' == 'right' || |
| ('rtl' == 'ltr' && 'left' == 'end') || |
| ('rtl' == 'rtl' && 'left' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'left'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align left, 0px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('center' == 'center') { |
| offset -= width / 2; |
| } else if ('center' == 'right' || |
| ('ltr' == 'ltr' && 'center' == 'end') || |
| ('ltr' == 'rtl' && 'center' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('center' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('center' == 'right' || |
| ('ltr' == 'ltr' && 'center' == 'end') || |
| ('ltr' == 'rtl' && 'center' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'center'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align center, 0px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('center' == 'center') { |
| offset -= width / 2; |
| } else if ('center' == 'right' || |
| ('rtl' == 'ltr' && 'center' == 'end') || |
| ('rtl' == 'rtl' && 'center' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('center' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('center' == 'right' || |
| ('rtl' == 'ltr' && 'center' == 'end') || |
| ('rtl' == 'rtl' && 'center' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'center'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align center, 0px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('right' == 'center') { |
| offset -= width / 2; |
| } else if ('right' == 'right' || |
| ('ltr' == 'ltr' && 'right' == 'end') || |
| ('ltr' == 'rtl' && 'right' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('right' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('right' == 'right' || |
| ('ltr' == 'ltr' && 'right' == 'end') || |
| ('ltr' == 'rtl' && 'right' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'right'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align right, 0px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('right' == 'center') { |
| offset -= width / 2; |
| } else if ('right' == 'right' || |
| ('rtl' == 'ltr' && 'right' == 'end') || |
| ('rtl' == 'rtl' && 'right' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('right' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('right' == 'right' || |
| ('rtl' == 'ltr' && 'right' == 'end') || |
| ('rtl' == 'rtl' && 'right' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'right'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align right, 0px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('start' == 'center') { |
| offset -= width / 2; |
| } else if ('start' == 'right' || |
| ('ltr' == 'ltr' && 'start' == 'end') || |
| ('ltr' == 'rtl' && 'start' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('start' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('start' == 'right' || |
| ('ltr' == 'ltr' && 'start' == 'end') || |
| ('ltr' == 'rtl' && 'start' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'start'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align start, 0px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('start' == 'center') { |
| offset -= width / 2; |
| } else if ('start' == 'right' || |
| ('rtl' == 'ltr' && 'start' == 'end') || |
| ('rtl' == 'rtl' && 'start' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('start' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('start' == 'right' || |
| ('rtl' == 'ltr' && 'start' == 'end') || |
| ('rtl' == 'rtl' && 'start' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'start'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align start, 0px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('end' == 'center') { |
| offset -= width / 2; |
| } else if ('end' == 'right' || |
| ('ltr' == 'ltr' && 'end' == 'end') || |
| ('ltr' == 'rtl' && 'end' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('end' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('end' == 'right' || |
| ('ltr' == 'ltr' && 'end' == 'end') || |
| ('ltr' == 'rtl' && 'end' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'end'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align end, 0px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('end' == 'center') { |
| offset -= width / 2; |
| } else if ('end' == 'right' || |
| ('rtl' == 'ltr' && 'end' == 'end') || |
| ('rtl' == 'rtl' && 'end' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('end' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('end' == 'right' || |
| ('rtl' == 'ltr' && 'end' == 'end') || |
| ('rtl' == 'rtl' && 'end' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'end'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align end, 0px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('left' == 'center') { |
| offset -= width / 2; |
| } else if ('left' == 'right' || |
| ('ltr' == 'ltr' && 'left' == 'end') || |
| ('ltr' == 'rtl' && 'left' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('left' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('left' == 'right' || |
| ('ltr' == 'ltr' && 'left' == 'end') || |
| ('ltr' == 'rtl' && 'left' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'left'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align left, 10px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('left' == 'center') { |
| offset -= width / 2; |
| } else if ('left' == 'right' || |
| ('rtl' == 'ltr' && 'left' == 'end') || |
| ('rtl' == 'rtl' && 'left' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('left' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('left' == 'right' || |
| ('rtl' == 'ltr' && 'left' == 'end') || |
| ('rtl' == 'rtl' && 'left' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'left'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align left, 10px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('center' == 'center') { |
| offset -= width / 2; |
| } else if ('center' == 'right' || |
| ('ltr' == 'ltr' && 'center' == 'end') || |
| ('ltr' == 'rtl' && 'center' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('center' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('center' == 'right' || |
| ('ltr' == 'ltr' && 'center' == 'end') || |
| ('ltr' == 'rtl' && 'center' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'center'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align center, 10px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('center' == 'center') { |
| offset -= width / 2; |
| } else if ('center' == 'right' || |
| ('rtl' == 'ltr' && 'center' == 'end') || |
| ('rtl' == 'rtl' && 'center' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('center' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('center' == 'right' || |
| ('rtl' == 'ltr' && 'center' == 'end') || |
| ('rtl' == 'rtl' && 'center' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'center'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align center, 10px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('right' == 'center') { |
| offset -= width / 2; |
| } else if ('right' == 'right' || |
| ('ltr' == 'ltr' && 'right' == 'end') || |
| ('ltr' == 'rtl' && 'right' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('right' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('right' == 'right' || |
| ('ltr' == 'ltr' && 'right' == 'end') || |
| ('ltr' == 'rtl' && 'right' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'right'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align right, 10px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('right' == 'center') { |
| offset -= width / 2; |
| } else if ('right' == 'right' || |
| ('rtl' == 'ltr' && 'right' == 'end') || |
| ('rtl' == 'rtl' && 'right' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('right' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('right' == 'right' || |
| ('rtl' == 'ltr' && 'right' == 'end') || |
| ('rtl' == 'rtl' && 'right' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'right'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align right, 10px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('start' == 'center') { |
| offset -= width / 2; |
| } else if ('start' == 'right' || |
| ('ltr' == 'ltr' && 'start' == 'end') || |
| ('ltr' == 'rtl' && 'start' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('start' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('start' == 'right' || |
| ('ltr' == 'ltr' && 'start' == 'end') || |
| ('ltr' == 'rtl' && 'start' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'start'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align start, 10px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('start' == 'center') { |
| offset -= width / 2; |
| } else if ('start' == 'right' || |
| ('rtl' == 'ltr' && 'start' == 'end') || |
| ('rtl' == 'rtl' && 'start' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('start' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('start' == 'right' || |
| ('rtl' == 'ltr' && 'start' == 'end') || |
| ('rtl' == 'rtl' && 'start' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'start'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align start, 10px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('end' == 'center') { |
| offset -= width / 2; |
| } else if ('end' == 'right' || |
| ('ltr' == 'ltr' && 'end' == 'end') || |
| ('ltr' == 'rtl' && 'end' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('end' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('end' == 'right' || |
| ('ltr' == 'ltr' && 'end' == 'end') || |
| ('ltr' == 'rtl' && 'end' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'end'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align end, 10px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('end' == 'center') { |
| offset -= width / 2; |
| } else if ('end' == 'right' || |
| ('rtl' == 'ltr' && 'end' == 'end') || |
| ('rtl' == 'rtl' && 'end' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('end' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('end' == 'right' || |
| ('rtl' == 'ltr' && 'end' == 'end') || |
| ('rtl' == 'rtl' && 'end' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'end'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align end, 10px letter spacing and no-directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('left' == 'center') { |
| offset -= width / 2; |
| } else if ('left' == 'right' || |
| ('ltr' == 'ltr' && 'left' == 'end') || |
| ('ltr' == 'rtl' && 'left' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('left' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('left' == 'right' || |
| ('ltr' == 'ltr' && 'left' == 'end') || |
| ('ltr' == 'rtl' && 'left' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'left'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align left, 0px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('left' == 'center') { |
| offset -= width / 2; |
| } else if ('left' == 'right' || |
| ('rtl' == 'ltr' && 'left' == 'end') || |
| ('rtl' == 'rtl' && 'left' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('left' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('left' == 'right' || |
| ('rtl' == 'ltr' && 'left' == 'end') || |
| ('rtl' == 'rtl' && 'left' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'left'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align left, 0px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('center' == 'center') { |
| offset -= width / 2; |
| } else if ('center' == 'right' || |
| ('ltr' == 'ltr' && 'center' == 'end') || |
| ('ltr' == 'rtl' && 'center' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('center' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('center' == 'right' || |
| ('ltr' == 'ltr' && 'center' == 'end') || |
| ('ltr' == 'rtl' && 'center' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'center'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align center, 0px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('center' == 'center') { |
| offset -= width / 2; |
| } else if ('center' == 'right' || |
| ('rtl' == 'ltr' && 'center' == 'end') || |
| ('rtl' == 'rtl' && 'center' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('center' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('center' == 'right' || |
| ('rtl' == 'ltr' && 'center' == 'end') || |
| ('rtl' == 'rtl' && 'center' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'center'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align center, 0px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('right' == 'center') { |
| offset -= width / 2; |
| } else if ('right' == 'right' || |
| ('ltr' == 'ltr' && 'right' == 'end') || |
| ('ltr' == 'rtl' && 'right' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('right' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('right' == 'right' || |
| ('ltr' == 'ltr' && 'right' == 'end') || |
| ('ltr' == 'rtl' && 'right' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'right'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align right, 0px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('right' == 'center') { |
| offset -= width / 2; |
| } else if ('right' == 'right' || |
| ('rtl' == 'ltr' && 'right' == 'end') || |
| ('rtl' == 'rtl' && 'right' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('right' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('right' == 'right' || |
| ('rtl' == 'ltr' && 'right' == 'end') || |
| ('rtl' == 'rtl' && 'right' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'right'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align right, 0px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('start' == 'center') { |
| offset -= width / 2; |
| } else if ('start' == 'right' || |
| ('ltr' == 'ltr' && 'start' == 'end') || |
| ('ltr' == 'rtl' && 'start' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('start' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('start' == 'right' || |
| ('ltr' == 'ltr' && 'start' == 'end') || |
| ('ltr' == 'rtl' && 'start' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'start'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align start, 0px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('start' == 'center') { |
| offset -= width / 2; |
| } else if ('start' == 'right' || |
| ('rtl' == 'ltr' && 'start' == 'end') || |
| ('rtl' == 'rtl' && 'start' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('start' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('start' == 'right' || |
| ('rtl' == 'ltr' && 'start' == 'end') || |
| ('rtl' == 'rtl' && 'start' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'start'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align start, 0px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('end' == 'center') { |
| offset -= width / 2; |
| } else if ('end' == 'right' || |
| ('ltr' == 'ltr' && 'end' == 'end') || |
| ('ltr' == 'rtl' && 'end' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('end' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('end' == 'right' || |
| ('ltr' == 'ltr' && 'end' == 'end') || |
| ('ltr' == 'rtl' && 'end' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'end'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align end, 0px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('end' == 'center') { |
| offset -= width / 2; |
| } else if ('end' == 'right' || |
| ('rtl' == 'ltr' && 'end' == 'end') || |
| ('rtl' == 'rtl' && 'end' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '0px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('end' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('end' == 'right' || |
| ('rtl' == 'ltr' && 'end' == 'end') || |
| ('rtl' == 'rtl' && 'end' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'end'; |
| ctx.letterSpacing = '0px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('0px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align end, 0px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('left' == 'center') { |
| offset -= width / 2; |
| } else if ('left' == 'right' || |
| ('ltr' == 'ltr' && 'left' == 'end') || |
| ('ltr' == 'rtl' && 'left' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('left' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('left' == 'right' || |
| ('ltr' == 'ltr' && 'left' == 'end') || |
| ('ltr' == 'rtl' && 'left' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'left'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align left, 10px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('left' == 'center') { |
| offset -= width / 2; |
| } else if ('left' == 'right' || |
| ('rtl' == 'ltr' && 'left' == 'end') || |
| ('rtl' == 'rtl' && 'left' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('left' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('left' == 'right' || |
| ('rtl' == 'ltr' && 'left' == 'end') || |
| ('rtl' == 'rtl' && 'left' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'left'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align left, 10px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('center' == 'center') { |
| offset -= width / 2; |
| } else if ('center' == 'right' || |
| ('ltr' == 'ltr' && 'center' == 'end') || |
| ('ltr' == 'rtl' && 'center' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('center' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('center' == 'right' || |
| ('ltr' == 'ltr' && 'center' == 'end') || |
| ('ltr' == 'rtl' && 'center' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'center'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align center, 10px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('center' == 'center') { |
| offset -= width / 2; |
| } else if ('center' == 'right' || |
| ('rtl' == 'ltr' && 'center' == 'end') || |
| ('rtl' == 'rtl' && 'center' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('center' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('center' == 'right' || |
| ('rtl' == 'ltr' && 'center' == 'end') || |
| ('rtl' == 'rtl' && 'center' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'center'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align center, 10px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('right' == 'center') { |
| offset -= width / 2; |
| } else if ('right' == 'right' || |
| ('ltr' == 'ltr' && 'right' == 'end') || |
| ('ltr' == 'rtl' && 'right' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('right' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('right' == 'right' || |
| ('ltr' == 'ltr' && 'right' == 'end') || |
| ('ltr' == 'rtl' && 'right' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'right'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align right, 10px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('right' == 'center') { |
| offset -= width / 2; |
| } else if ('right' == 'right' || |
| ('rtl' == 'ltr' && 'right' == 'end') || |
| ('rtl' == 'rtl' && 'right' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('right' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('right' == 'right' || |
| ('rtl' == 'ltr' && 'right' == 'end') || |
| ('rtl' == 'rtl' && 'right' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'right'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align right, 10px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('start' == 'center') { |
| offset -= width / 2; |
| } else if ('start' == 'right' || |
| ('ltr' == 'ltr' && 'start' == 'end') || |
| ('ltr' == 'rtl' && 'start' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('start' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('start' == 'right' || |
| ('ltr' == 'ltr' && 'start' == 'end') || |
| ('ltr' == 'rtl' && 'start' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'start'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align start, 10px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('start' == 'center') { |
| offset -= width / 2; |
| } else if ('start' == 'right' || |
| ('rtl' == 'ltr' && 'start' == 'end') || |
| ('rtl' == 'rtl' && 'start' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('start' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('start' == 'right' || |
| ('rtl' == 'ltr' && 'start' == 'end') || |
| ('rtl' == 'rtl' && 'start' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'start'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align start, 10px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('end' == 'center') { |
| offset -= width / 2; |
| } else if ('end' == 'right' || |
| ('ltr' == 'ltr' && 'end' == 'end') || |
| ('ltr' == 'rtl' && 'end' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'ltr'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('end' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('end' == 'right' || |
| ('ltr' == 'ltr' && 'end' == 'end') || |
| ('ltr' == 'rtl' && 'end' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'ltr'; |
| ctx.textAlign = 'end'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction ltr, text align end, 10px letter spacing and directional-override."); |
| |
| test(t => { |
| const canvas = new OffscreenCanvas(100, 50); |
| const ctx = canvas.getContext('2d'); |
| |
| function alignOffset(offset, width) { |
| if ('end' == 'center') { |
| offset -= width / 2; |
| } else if ('end' == 'right' || |
| ('rtl' == 'ltr' && 'end' == 'end') || |
| ('rtl' == 'rtl' && 'end' == 'start')) { |
| offset -= width; |
| } |
| return offset; |
| } |
| |
| 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; |
| } |
| |
| function placeAndMeasureTextInDOM(text, text_width, point) { |
| const el = document.createElement("p"); |
| el.innerHTML = text; |
| el.style.font = '50px sans-serif'; |
| el.style.direction = 'rtl'; |
| el.style.letterSpacing = '10px'; |
| // Put the text top left to make offsets simpler. |
| el.style.padding = '0px'; |
| el.style.margin = '0px'; |
| el.style.position = 'absolute'; |
| el.style.x = '0px'; |
| el.style.y = '0px'; |
| document.body.appendChild(el); |
| text_bound = el.getBoundingClientRect(); |
| text_x = text_bound.x; |
| text_y = text_bound.y + text_bound.height / 2; |
| |
| // Offset to the requested point determined by textAlign and direction. |
| let text_align_dx = 0; |
| if ('end' == 'center') { |
| text_align_dx = text_width / 2; |
| } else if ('end' == 'right' || |
| ('rtl' == 'ltr' && 'end' == 'end') || |
| ('rtl' == 'rtl' && 'end' == 'start')) { |
| text_align_dx = text_width; |
| } |
| position = document.caretPositionFromPoint(point + text_align_dx + text_x, text_y); |
| _assertSame(position.offsetNode.parentNode, el, "position.offsetNode.parentNode", "el"); |
| |
| document.body.removeChild(el); |
| |
| return position.offset; |
| } |
| |
| ctx.font = '50px sans-serif'; |
| ctx.direction = 'rtl'; |
| ctx.textAlign = 'end'; |
| ctx.letterSpacing = '10px'; |
| |
| const kTexts = [ |
| 'UNAVAILABLE', |
| 'ππΆπ', |
| 'οΌοΌγοΌοΌ', |
| 'οΌοΌγγοΌοΌ', |
| 'γγοΌοΌγγ', |
| '--abcd__' |
| ] |
| |
| for (text of kTexts) { |
| text = addDirectionalOverrideCharacters(text, ctx.direction == 'ltr'); |
| const tm = ctx.measureText(text); |
| text_width = tm.width; |
| step = 30; |
| if ('10px' == '10px') { |
| step = 40; |
| } |
| |
| offset = step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 - 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width / 2 + 10; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| |
| offset = text_width - step; |
| adjusted_offset = alignOffset(offset, text_width); |
| tm_position = tm.getIndexFromOffset(adjusted_offset); |
| doc_position = placeAndMeasureTextInDOM(text, text_width, adjusted_offset); |
| assert_equals(tm_position, |
| doc_position, |
| "for " + text + " offset " + offset); |
| } |
| }, "Check that TextMetrics::getIndexFromOffset() matches its DOM equivalent, where possible, with direction rtl, text align end, 10px letter spacing and directional-override."); |
| |
| </script> |