phaser
Version:
A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.
145 lines (115 loc) • 3.43 kB
JavaScript
/**
* @author Richard Davey <rich@phaser.io>
* @copyright 2013-2025 Phaser Studio Inc.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var CanvasPool = require('../../display/canvas/CanvasPool');
/**
* Calculates the ascent, descent and fontSize of a given font style.
*
* @function Phaser.GameObjects.MeasureText
* @since 3.0.0
*
* @param {Phaser.GameObjects.TextStyle} textStyle - The TextStyle object to measure.
*
* @return {Phaser.Types.GameObjects.Text.TextMetrics} An object containing the ascent, descent and fontSize of the TextStyle.
*/
var MeasureText = function (textStyle)
{
var canvas = CanvasPool.create(this);
var context = canvas.getContext('2d', { willReadFrequently: true });
textStyle.syncFont(canvas, context);
var metrics = context.measureText(textStyle.testString);
if ('actualBoundingBoxAscent' in metrics)
{
var ascent = metrics.actualBoundingBoxAscent;
var descent = metrics.actualBoundingBoxDescent;
CanvasPool.remove(canvas);
return {
ascent: ascent,
descent: descent,
fontSize: ascent + descent
};
}
var width = Math.ceil(metrics.width * textStyle.baselineX);
var baseline = width;
var height = 2 * baseline;
baseline = baseline * textStyle.baselineY | 0;
canvas.width = width;
canvas.height = height;
context.fillStyle = '#f00';
context.fillRect(0, 0, width, height);
context.font = textStyle._font;
context.textBaseline = 'alphabetic';
context.fillStyle = '#000';
context.fillText(textStyle.testString, 0, baseline);
var output = {
ascent: 0,
descent: 0,
fontSize: 0
};
var imagedata = context.getImageData(0, 0, width, height);
if (!imagedata)
{
output.ascent = baseline;
output.descent = baseline + 6;
output.fontSize = output.ascent + output.descent;
CanvasPool.remove(canvas);
return output;
}
var pixels = imagedata.data;
var numPixels = pixels.length;
var line = width * 4;
var i;
var j;
var idx = 0;
var stop = false;
// ascent. scan from top to bottom until we find a non red pixel
for (i = 0; i < baseline; i++)
{
for (j = 0; j < line; j += 4)
{
if (pixels[idx + j] !== 255)
{
stop = true;
break;
}
}
if (!stop)
{
idx += line;
}
else
{
break;
}
}
output.ascent = baseline - i;
idx = numPixels - line;
stop = false;
// descent. scan from bottom to top until we find a non red pixel
for (i = height; i > baseline; i--)
{
for (j = 0; j < line; j += 4)
{
if (pixels[idx + j] !== 255)
{
stop = true;
break;
}
}
if (!stop)
{
idx -= line;
}
else
{
break;
}
}
output.descent = (i - baseline);
output.fontSize = output.ascent + output.descent;
CanvasPool.remove(canvas);
return output;
};
module.exports = MeasureText;