summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-text/support/get-char-advances.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/css/css-text/support/get-char-advances.js
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/css/css-text/support/get-char-advances.js')
-rw-r--r--testing/web-platform/tests/css/css-text/support/get-char-advances.js70
1 files changed, 70 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-text/support/get-char-advances.js b/testing/web-platform/tests/css/css-text/support/get-char-advances.js
new file mode 100644
index 0000000000..0fd7332c4e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-text/support/get-char-advances.js
@@ -0,0 +1,70 @@
+'use strict';
+
+/**
+ * Returns an array of advances for all characters in the descendants
+ * of the specified element.
+ *
+ * Technically speaking, advances and glyph bounding boxes are different things,
+ * and advances are not exposed. This function computes approximate values from
+ * bounding boxes.
+ */
+function getCharAdvances(element) {
+ const style = getComputedStyle(element);
+ const is_vertical = style.writingMode.startsWith('vertical');
+ const range = document.createRange();
+ const all_bounds = []
+
+ function walk(element) {
+ for (const node of element.childNodes) {
+ const nodeType = node.nodeType;
+ if (nodeType === Node.TEXT_NODE) {
+ const text = node.nodeValue;
+ for (let i = 0; i < text.length; ++i) {
+ range.setStart(node, i);
+ range.setEnd(node, i + 1);
+ let bounds = range.getBoundingClientRect();
+ // Transpose if it's in vertical flow. Guarantee that top < bottom
+ // and left < right are always true.
+ if (is_vertical) {
+ bounds = {
+ left: bounds.top,
+ top: bounds.left,
+ right: bounds.bottom,
+ bottom: bounds.right
+ };
+ }
+ all_bounds.push(bounds);
+ }
+ } else if (nodeType === Node.ELEMENT_NODE) {
+ walk(node);
+ }
+ }
+ }
+ walk(element);
+ all_bounds.sort(function(bound_a, bound_b) {
+ if (bound_a.bottom <= bound_b.top) {
+ return -1;
+ }
+ if (bound_b.bottom <= bound_a.top) {
+ return 1;
+ }
+ return bound_a.left - bound_b.left;
+ });
+ let origin = undefined;
+ let blockEnd = -1;
+ const advances = [];
+ for (let bounds of all_bounds) {
+ // Check if this is on the same line.
+ if (bounds.top >= blockEnd) {
+ origin = undefined;
+ blockEnd = bounds.bottom;
+ }
+ // For the first character, the left bound is closest to the origin.
+ if (origin === undefined)
+ origin = bounds.left;
+ // The right bound is a good approximation of the next origin.
+ advances.push(bounds.right - origin);
+ origin = bounds.right;
+ }
+ return advances;
+}