diff --git a/packages/engine/Source/Core/writeTextToCanvas.js b/packages/engine/Source/Core/writeTextToCanvas.js index 1db8a0ba0d1f..b6a16cebf315 100644 --- a/packages/engine/Source/Core/writeTextToCanvas.js +++ b/packages/engine/Source/Core/writeTextToCanvas.js @@ -3,98 +3,6 @@ import defaultValue from "./defaultValue.js"; import defined from "./defined.js"; import DeveloperError from "./DeveloperError.js"; -function measureText(context2D, textString, font, stroke, fill) { - const metrics = context2D.measureText(textString); - const isSpace = !/\S/.test(textString); - - if (!isSpace) { - const fontSize = document.defaultView - .getComputedStyle(context2D.canvas) - .getPropertyValue("font-size") - .replace("px", ""); - const canvas = document.createElement("canvas"); - const padding = 100; - const width = (metrics.width + padding) | 0; - const height = 3 * fontSize; - const baseline = height / 2; - canvas.width = width; - canvas.height = height; - - const ctx = canvas.getContext("2d"); - ctx.font = font; - ctx.fillStyle = "white"; - ctx.fillRect(0, 0, canvas.width + 1, canvas.height + 1); - - if (stroke) { - ctx.strokeStyle = "black"; - ctx.lineWidth = context2D.lineWidth; - ctx.strokeText(textString, padding / 2, baseline); - } - - if (fill) { - ctx.fillStyle = "black"; - ctx.fillText(textString, padding / 2, baseline); - } - - // Context image data has width * height * 4 elements, because - // each pixel's R, G, B and A are consecutive values in the array. - const pixelData = ctx.getImageData(0, 0, width, height).data; - const length = pixelData.length; - const width4 = width * 4; - let i, j; - - let ascent, descent; - // Find the number of rows (from the top) until the first non-white pixel - for (i = 0; i < length; ++i) { - if (pixelData[i] !== 255) { - ascent = (i / width4) | 0; - break; - } - } - - // Find the number of rows (from the bottom) until the first non-white pixel - for (i = length - 1; i >= 0; --i) { - if (pixelData[i] !== 255) { - descent = (i / width4) | 0; - break; - } - } - - let minx = -1; - // For each column, for each row, check for first non-white pixel - for (i = 0; i < width && minx === -1; ++i) { - for (j = 0; j < height; ++j) { - const pixelIndex = i * 4 + j * width4; - if ( - pixelData[pixelIndex] !== 255 || - pixelData[pixelIndex + 1] !== 255 || - pixelData[pixelIndex + 2] !== 255 || - pixelData[pixelIndex + 3] !== 255 - ) { - minx = i; - break; - } - } - } - - return { - width: metrics.width, - height: descent - ascent, - ascent: baseline - ascent, - descent: descent - baseline, - minx: minx - padding / 2, - }; - } - - return { - width: metrics.width, - height: 0, - ascent: 0, - descent: 0, - minx: 0, - }; -} - let imageSmoothingEnabledName; /** @@ -168,7 +76,15 @@ function writeTextToCanvas(text, options) { canvas.style.visibility = "hidden"; document.body.appendChild(canvas); - const dimensions = measureText(context2D, text, font, stroke, fill); + const metrics = context2D.measureText(text); + const dimensions = { + width: metrics.width, + height: metrics.actualBoundingBoxDescent + metrics.actualBoundingBoxAscent, + ascent: metrics.actualBoundingBoxAscent, + descent: metrics.actualBoundingBoxDescent, + minx: metrics.actualBoundingBoxLeft, + }; + // Set canvas.dimensions to be accessed in LabelCollection canvas.dimensions = dimensions; diff --git a/packages/engine/Source/Scene/LabelCollection.js b/packages/engine/Source/Scene/LabelCollection.js index 314db367fba3..b6fdcfe74dcf 100644 --- a/packages/engine/Source/Scene/LabelCollection.js +++ b/packages/engine/Source/Scene/LabelCollection.js @@ -23,6 +23,20 @@ import GraphemeSplitter from "grapheme-splitter"; // not have a billboard, depending on whether the texture info has an index into // the the label collection's texture atlas. Invisible characters have no texture, and // no billboard. However, it always has a valid dimensions object. +// +// A valid 'dimensions' object is an object that has the properties that are +// derived from a https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics +// object (in pixels) +// - width: The width of the glyph, as given by TextMetrics.width +// - ascent: The the distance from the 'textBaseline' attribute to +// the top of the bounding rectangle of the glyph, as given by +// TextMetrics.actualBoundingBoxAscent +// - descent: The the distance from the 'textBaseline' attribute to +// the bottom of the bounding rectangle of the glyph, as given by +// TextMetrics.actualBoundingBoxDescent +// - minx: The distance of the alignment point given by the 'textAlign' +// property to the left side of the bounding rectangle of the glyph, +// as given by TextMetrics.actualBoundingBoxLeft function Glyph() { this.textureInfo = undefined; this.dimensions = undefined; @@ -33,6 +47,7 @@ function Glyph() { // shared and reference counted across all labels. It may or may not have an // index into the label collection's texture atlas, depending on whether the character // has both width and height, but it always has a valid dimensions object. +// (See notes above about what that means) function GlyphTextureInfo(labelCollection, index, dimensions) { this.labelCollection = labelCollection; this.index = index;