This commit is contained in:
Akko
2025-08-04 18:57:35 +02:00
parent 8cf6e78a79
commit 9495868c2e
5030 changed files with 518594 additions and 17609 deletions

177
node_modules/pixi.js/lib/scene/text/AbstractText.d.ts generated vendored Normal file
View File

@@ -0,0 +1,177 @@
import { ObservablePoint } from '../../maths/point/ObservablePoint';
import { ViewContainer } from '../view/View';
import type { Size } from '../../maths/misc/Size';
import type { PointData } from '../../maths/point/PointData';
import type { View } from '../../rendering/renderers/shared/view/View';
import type { Bounds } from '../container/bounds/Bounds';
import type { ContainerOptions } from '../container/Container';
import type { Optional } from '../container/container-mixins/measureMixin';
import type { DestroyOptions } from '../container/destroyTypes';
import type { HTMLTextStyle, HTMLTextStyleOptions } from '../text-html/HtmlTextStyle';
import type { TextStyle, TextStyleOptions } from './TextStyle';
/**
* A string or number that can be used as text.
* @memberof text
*/
export type TextString = string | number | {
toString: () => string;
};
/**
* A union of all text styles, including HTML, Bitmap and Canvas text styles.
* @memberof text
* @see text.TextStyle
* @see text.HTMLTextStyle
*/
export type AnyTextStyle = TextStyle | HTMLTextStyle;
/**
* A union of all text style options, including HTML, Bitmap and Canvas text style options.
* @memberof text
* @see text.TextStyleOptions
* @see text.HTMLTextStyleOptions
*/
export type AnyTextStyleOptions = TextStyleOptions | HTMLTextStyleOptions;
/**
* Options for the {@link scene.Text} class.
* @example
* const text = new Text({
* text: 'Hello Pixi!',
* style: {
* fontFamily: 'Arial',
* fontSize: 24,
* fill: 0xff1010,
* align: 'center',
* }
* });
* @memberof text
*/
export interface TextOptions<TEXT_STYLE extends TextStyle = TextStyle, TEXT_STYLE_OPTIONS extends TextStyleOptions = TextStyleOptions> extends ContainerOptions {
/** The anchor point of the text. */
anchor?: PointData | number;
/** The copy for the text object. To split a line you can use '\n'. */
text?: TextString;
/** The resolution of the text. */
resolution?: number;
/**
* The text style
* @type {
* text.TextStyle |
* Partial<text.TextStyle> |
* text.TextStyleOptions |
* text.HTMLTextStyle |
* Partial<text.HTMLTextStyle> |
* text.HTMLTextStyleOptions
* }
*/
style?: TEXT_STYLE | TEXT_STYLE_OPTIONS;
/** Whether or not to round the x/y position. */
roundPixels?: boolean;
}
/**
* An abstract Text class, used by all text type in Pixi. This includes Canvas, HTML, and Bitmap Text.
* @see scene.Text
* @see scene.BitmapText
* @see scene.HTMLText
* @memberof scene
*/
export declare abstract class AbstractText<TEXT_STYLE extends TextStyle = TextStyle, TEXT_STYLE_OPTIONS extends TextStyleOptions = TextStyleOptions> extends ViewContainer implements View {
batched: boolean;
_anchor: ObservablePoint;
_resolution: number;
_autoResolution: boolean;
_style: TEXT_STYLE;
_didTextUpdate: boolean;
protected _text: string;
private readonly _styleClass;
constructor(options: TextOptions<TEXT_STYLE, TEXT_STYLE_OPTIONS>, styleClass: new (options: TEXT_STYLE_OPTIONS) => TEXT_STYLE);
/**
* The anchor sets the origin point of the text.
* The default is `(0,0)`, this means the text's origin is the top left.
*
* Setting the anchor to `(0.5,0.5)` means the text's origin is centered.
*
* Setting the anchor to `(1,1)` would mean the text's origin point will be the bottom right corner.
*
* If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
* @example
* import { Text } from 'pixi.js';
*
* const text = new Text('hello world');
* text.anchor.set(0.5); // This will set the origin to center. (0.5) is same as (0.5, 0.5).
*/
get anchor(): ObservablePoint;
set anchor(value: PointData | number);
/** Set the copy for the text object. To split a line you can use '\n'. */
set text(value: TextString);
get text(): string;
/**
* The resolution / device pixel ratio of the canvas.
* @default 1
*/
set resolution(value: number);
get resolution(): number;
get style(): TEXT_STYLE;
/**
* Set the style of the text.
*
* Set up an event listener to listen for changes on the style object and mark the text as dirty.
*
* If setting the `style` can also be partial {@link AnyTextStyleOptions}.
* @type {
* text.TextStyle |
* Partial<text.TextStyle> |
* text.TextStyleOptions |
* text.HTMLTextStyle |
* Partial<text.HTMLTextStyle> |
* text.HTMLTextStyleOptions
* }
*/
set style(style: TEXT_STYLE | Partial<TEXT_STYLE> | TEXT_STYLE_OPTIONS);
/**
* The local bounds of the Text.
* @type {rendering.Bounds}
*/
get bounds(): Bounds;
/** The width of the sprite, setting this will actually modify the scale to achieve the value set. */
get width(): number;
set width(value: number);
/** The height of the sprite, setting this will actually modify the scale to achieve the value set. */
get height(): number;
set height(value: number);
/**
* Retrieves the size of the Text as a [Size]{@link Size} object.
* This is faster than get the width and height separately.
* @param out - Optional object to store the size in.
* @returns - The size of the Text.
*/
getSize(out?: Size): Size;
/**
* Sets the size of the Text to the specified width and height.
* This is faster than setting the width and height separately.
* @param value - This can be either a number or a [Size]{@link Size} object.
* @param height - The height to set. Defaults to the value of `width` if not provided.
*/
setSize(value: number | Optional<Size, 'height'>, height?: number): void;
/**
* Adds the bounds of this text to the bounds object.
* @param bounds - The output bounds object.
*/
addBounds(bounds: Bounds): void;
/**
* Checks if the text contains the given point.
* @param point - The point to check
*/
containsPoint(point: PointData): boolean;
onViewUpdate(): void;
_getKey(): string;
protected abstract _updateBounds(): void;
/**
* Destroys this text renderable and optionally its style texture.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the texture of the text style
* @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the text style
* @param {boolean} [options.style=false] - Should it destroy the style of the text
*/
destroy(options?: DestroyOptions): void;
}
export declare function ensureOptions<TEXT_STYLE extends TextStyle, TEXT_STYLE_OPTIONS extends TextStyleOptions>(args: any[], name: string): TextOptions<TEXT_STYLE, TEXT_STYLE_OPTIONS>;

242
node_modules/pixi.js/lib/scene/text/AbstractText.js generated vendored Normal file
View File

@@ -0,0 +1,242 @@
'use strict';
var ObservablePoint = require('../../maths/point/ObservablePoint.js');
var deprecation = require('../../utils/logging/deprecation.js');
var View = require('../view/View.js');
"use strict";
class AbstractText extends View.ViewContainer {
constructor(options, styleClass) {
const { text, resolution, style, anchor, width, height, roundPixels, ...rest } = options;
super({
...rest
});
this.batched = true;
this._resolution = null;
this._autoResolution = true;
this._didTextUpdate = true;
this._styleClass = styleClass;
this.text = text ?? "";
this.style = style;
this.resolution = resolution ?? null;
this.allowChildren = false;
this._anchor = new ObservablePoint.ObservablePoint(
{
_onUpdate: () => {
this.onViewUpdate();
}
}
);
if (anchor)
this.anchor = anchor;
this.roundPixels = roundPixels ?? false;
if (width !== void 0)
this.width = width;
if (height !== void 0)
this.height = height;
}
/**
* The anchor sets the origin point of the text.
* The default is `(0,0)`, this means the text's origin is the top left.
*
* Setting the anchor to `(0.5,0.5)` means the text's origin is centered.
*
* Setting the anchor to `(1,1)` would mean the text's origin point will be the bottom right corner.
*
* If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
* @example
* import { Text } from 'pixi.js';
*
* const text = new Text('hello world');
* text.anchor.set(0.5); // This will set the origin to center. (0.5) is same as (0.5, 0.5).
*/
get anchor() {
return this._anchor;
}
set anchor(value) {
typeof value === "number" ? this._anchor.set(value) : this._anchor.copyFrom(value);
}
/** Set the copy for the text object. To split a line you can use '\n'. */
set text(value) {
value = value.toString();
if (this._text === value)
return;
this._text = value;
this.onViewUpdate();
}
get text() {
return this._text;
}
/**
* The resolution / device pixel ratio of the canvas.
* @default 1
*/
set resolution(value) {
this._autoResolution = value === null;
this._resolution = value;
this.onViewUpdate();
}
get resolution() {
return this._resolution;
}
get style() {
return this._style;
}
/**
* Set the style of the text.
*
* Set up an event listener to listen for changes on the style object and mark the text as dirty.
*
* If setting the `style` can also be partial {@link AnyTextStyleOptions}.
* @type {
* text.TextStyle |
* Partial<text.TextStyle> |
* text.TextStyleOptions |
* text.HTMLTextStyle |
* Partial<text.HTMLTextStyle> |
* text.HTMLTextStyleOptions
* }
*/
set style(style) {
style = style || {};
this._style?.off("update", this.onViewUpdate, this);
if (style instanceof this._styleClass) {
this._style = style;
} else {
this._style = new this._styleClass(style);
}
this._style.on("update", this.onViewUpdate, this);
this.onViewUpdate();
}
/**
* The local bounds of the Text.
* @type {rendering.Bounds}
*/
get bounds() {
if (this._boundsDirty) {
this._updateBounds();
this._boundsDirty = false;
}
return this._bounds;
}
/** The width of the sprite, setting this will actually modify the scale to achieve the value set. */
get width() {
return Math.abs(this.scale.x) * this.bounds.width;
}
set width(value) {
this._setWidth(value, this.bounds.width);
}
/** The height of the sprite, setting this will actually modify the scale to achieve the value set. */
get height() {
return Math.abs(this.scale.y) * this.bounds.height;
}
set height(value) {
this._setHeight(value, this.bounds.height);
}
/**
* Retrieves the size of the Text as a [Size]{@link Size} object.
* This is faster than get the width and height separately.
* @param out - Optional object to store the size in.
* @returns - The size of the Text.
*/
getSize(out) {
out || (out = {});
out.width = Math.abs(this.scale.x) * this.bounds.width;
out.height = Math.abs(this.scale.y) * this.bounds.height;
return out;
}
/**
* Sets the size of the Text to the specified width and height.
* This is faster than setting the width and height separately.
* @param value - This can be either a number or a [Size]{@link Size} object.
* @param height - The height to set. Defaults to the value of `width` if not provided.
*/
setSize(value, height) {
if (typeof value === "object") {
height = value.height ?? value.width;
value = value.width;
} else {
height ?? (height = value);
}
value !== void 0 && this._setWidth(value, this.bounds.width);
height !== void 0 && this._setHeight(height, this.bounds.height);
}
/**
* Adds the bounds of this text to the bounds object.
* @param bounds - The output bounds object.
*/
addBounds(bounds) {
const _bounds = this.bounds;
bounds.addFrame(
_bounds.minX,
_bounds.minY,
_bounds.maxX,
_bounds.maxY
);
}
/**
* Checks if the text contains the given point.
* @param point - The point to check
*/
containsPoint(point) {
const width = this.bounds.width;
const height = this.bounds.height;
const x1 = -width * this.anchor.x;
let y1 = 0;
if (point.x >= x1 && point.x <= x1 + width) {
y1 = -height * this.anchor.y;
if (point.y >= y1 && point.y <= y1 + height)
return true;
}
return false;
}
onViewUpdate() {
this._didViewChangeTick++;
this._boundsDirty = true;
if (this.didViewUpdate)
return;
this.didViewUpdate = true;
this._didTextUpdate = true;
const renderGroup = this.renderGroup || this.parentRenderGroup;
if (renderGroup) {
renderGroup.onChildViewUpdate(this);
}
}
_getKey() {
return `${this.text}:${this._style.styleKey}:${this._resolution}`;
}
/**
* Destroys this text renderable and optionally its style texture.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the texture of the text style
* @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the text style
* @param {boolean} [options.style=false] - Should it destroy the style of the text
*/
destroy(options = false) {
super.destroy(options);
this.owner = null;
this._bounds = null;
this._anchor = null;
if (typeof options === "boolean" ? options : options?.style) {
this._style.destroy(options);
}
this._style = null;
this._text = null;
}
}
function ensureOptions(args, name) {
let options = args[0] ?? {};
if (typeof options === "string" || args[1]) {
deprecation.deprecation(deprecation.v8_0_0, `use new ${name}({ text: "hi!", style }) instead`);
options = {
text: options,
style: args[1]
};
}
return options;
}
exports.AbstractText = AbstractText;
exports.ensureOptions = ensureOptions;
//# sourceMappingURL=AbstractText.js.map

File diff suppressed because one or more lines are too long

239
node_modules/pixi.js/lib/scene/text/AbstractText.mjs generated vendored Normal file
View File

@@ -0,0 +1,239 @@
import { ObservablePoint } from '../../maths/point/ObservablePoint.mjs';
import { deprecation, v8_0_0 } from '../../utils/logging/deprecation.mjs';
import { ViewContainer } from '../view/View.mjs';
"use strict";
class AbstractText extends ViewContainer {
constructor(options, styleClass) {
const { text, resolution, style, anchor, width, height, roundPixels, ...rest } = options;
super({
...rest
});
this.batched = true;
this._resolution = null;
this._autoResolution = true;
this._didTextUpdate = true;
this._styleClass = styleClass;
this.text = text ?? "";
this.style = style;
this.resolution = resolution ?? null;
this.allowChildren = false;
this._anchor = new ObservablePoint(
{
_onUpdate: () => {
this.onViewUpdate();
}
}
);
if (anchor)
this.anchor = anchor;
this.roundPixels = roundPixels ?? false;
if (width !== void 0)
this.width = width;
if (height !== void 0)
this.height = height;
}
/**
* The anchor sets the origin point of the text.
* The default is `(0,0)`, this means the text's origin is the top left.
*
* Setting the anchor to `(0.5,0.5)` means the text's origin is centered.
*
* Setting the anchor to `(1,1)` would mean the text's origin point will be the bottom right corner.
*
* If you pass only single parameter, it will set both x and y to the same value as shown in the example below.
* @example
* import { Text } from 'pixi.js';
*
* const text = new Text('hello world');
* text.anchor.set(0.5); // This will set the origin to center. (0.5) is same as (0.5, 0.5).
*/
get anchor() {
return this._anchor;
}
set anchor(value) {
typeof value === "number" ? this._anchor.set(value) : this._anchor.copyFrom(value);
}
/** Set the copy for the text object. To split a line you can use '\n'. */
set text(value) {
value = value.toString();
if (this._text === value)
return;
this._text = value;
this.onViewUpdate();
}
get text() {
return this._text;
}
/**
* The resolution / device pixel ratio of the canvas.
* @default 1
*/
set resolution(value) {
this._autoResolution = value === null;
this._resolution = value;
this.onViewUpdate();
}
get resolution() {
return this._resolution;
}
get style() {
return this._style;
}
/**
* Set the style of the text.
*
* Set up an event listener to listen for changes on the style object and mark the text as dirty.
*
* If setting the `style` can also be partial {@link AnyTextStyleOptions}.
* @type {
* text.TextStyle |
* Partial<text.TextStyle> |
* text.TextStyleOptions |
* text.HTMLTextStyle |
* Partial<text.HTMLTextStyle> |
* text.HTMLTextStyleOptions
* }
*/
set style(style) {
style = style || {};
this._style?.off("update", this.onViewUpdate, this);
if (style instanceof this._styleClass) {
this._style = style;
} else {
this._style = new this._styleClass(style);
}
this._style.on("update", this.onViewUpdate, this);
this.onViewUpdate();
}
/**
* The local bounds of the Text.
* @type {rendering.Bounds}
*/
get bounds() {
if (this._boundsDirty) {
this._updateBounds();
this._boundsDirty = false;
}
return this._bounds;
}
/** The width of the sprite, setting this will actually modify the scale to achieve the value set. */
get width() {
return Math.abs(this.scale.x) * this.bounds.width;
}
set width(value) {
this._setWidth(value, this.bounds.width);
}
/** The height of the sprite, setting this will actually modify the scale to achieve the value set. */
get height() {
return Math.abs(this.scale.y) * this.bounds.height;
}
set height(value) {
this._setHeight(value, this.bounds.height);
}
/**
* Retrieves the size of the Text as a [Size]{@link Size} object.
* This is faster than get the width and height separately.
* @param out - Optional object to store the size in.
* @returns - The size of the Text.
*/
getSize(out) {
out || (out = {});
out.width = Math.abs(this.scale.x) * this.bounds.width;
out.height = Math.abs(this.scale.y) * this.bounds.height;
return out;
}
/**
* Sets the size of the Text to the specified width and height.
* This is faster than setting the width and height separately.
* @param value - This can be either a number or a [Size]{@link Size} object.
* @param height - The height to set. Defaults to the value of `width` if not provided.
*/
setSize(value, height) {
if (typeof value === "object") {
height = value.height ?? value.width;
value = value.width;
} else {
height ?? (height = value);
}
value !== void 0 && this._setWidth(value, this.bounds.width);
height !== void 0 && this._setHeight(height, this.bounds.height);
}
/**
* Adds the bounds of this text to the bounds object.
* @param bounds - The output bounds object.
*/
addBounds(bounds) {
const _bounds = this.bounds;
bounds.addFrame(
_bounds.minX,
_bounds.minY,
_bounds.maxX,
_bounds.maxY
);
}
/**
* Checks if the text contains the given point.
* @param point - The point to check
*/
containsPoint(point) {
const width = this.bounds.width;
const height = this.bounds.height;
const x1 = -width * this.anchor.x;
let y1 = 0;
if (point.x >= x1 && point.x <= x1 + width) {
y1 = -height * this.anchor.y;
if (point.y >= y1 && point.y <= y1 + height)
return true;
}
return false;
}
onViewUpdate() {
this._didViewChangeTick++;
this._boundsDirty = true;
if (this.didViewUpdate)
return;
this.didViewUpdate = true;
this._didTextUpdate = true;
const renderGroup = this.renderGroup || this.parentRenderGroup;
if (renderGroup) {
renderGroup.onChildViewUpdate(this);
}
}
_getKey() {
return `${this.text}:${this._style.styleKey}:${this._resolution}`;
}
/**
* Destroys this text renderable and optionally its style texture.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the texture of the text style
* @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the text style
* @param {boolean} [options.style=false] - Should it destroy the style of the text
*/
destroy(options = false) {
super.destroy(options);
this.owner = null;
this._bounds = null;
this._anchor = null;
if (typeof options === "boolean" ? options : options?.style) {
this._style.destroy(options);
}
this._style = null;
this._text = null;
}
}
function ensureOptions(args, name) {
let options = args[0] ?? {};
if (typeof options === "string" || args[1]) {
deprecation(v8_0_0, `use new ${name}({ text: "hi!", style }) instead`);
options = {
text: options,
style: args[1]
};
}
return options;
}
export { AbstractText, ensureOptions };
//# sourceMappingURL=AbstractText.mjs.map

File diff suppressed because one or more lines are too long

40
node_modules/pixi.js/lib/scene/text/Text.d.ts generated vendored Normal file
View File

@@ -0,0 +1,40 @@
import { AbstractText } from './AbstractText';
import { TextStyle } from './TextStyle';
import type { View } from '../../rendering/renderers/shared/view/View';
import type { TextOptions, TextString } from './AbstractText';
import type { TextStyleOptions } from './TextStyle';
/**
* A Text Object will create a line or multiple lines of text.
*
* To split a line you can use '\n' in your text string, or, on the `style` object,
* change its `wordWrap` property to true and and givae the `wordWrapWidth` property a value.
*
* The primary advantage of this class over BitmapText is that you have great control over the style of the text,
* which you can change at runtime.
*
* The primary disadvantages is that each piece of text has it's own texture, which can use more memory.
* When text changes, this texture has to be re-generated and re-uploaded to the GPU, taking up time.
* @example
* import { Text } from 'pixi.js';
*
* const text = new Text({
* text: 'Hello Pixi!',
* style: {
* fontFamily: 'Arial',
* fontSize: 24,
* fill: 0xff1010,
* align: 'center',
* }
* });
* @memberof scene
*/
export declare class Text extends AbstractText<TextStyle, TextStyleOptions> implements View {
readonly renderPipeId: string;
/**
* @param {text.TextOptions} options - The options of the text.
*/
constructor(options?: TextOptions);
/** @deprecated since 8.0.0 */
constructor(text?: TextString, options?: Partial<TextStyle>);
protected _updateBounds(): void;
}

30
node_modules/pixi.js/lib/scene/text/Text.js generated vendored Normal file
View File

@@ -0,0 +1,30 @@
'use strict';
var AbstractText = require('./AbstractText.js');
var CanvasTextMetrics = require('./canvas/CanvasTextMetrics.js');
var TextStyle = require('./TextStyle.js');
"use strict";
class Text extends AbstractText.AbstractText {
constructor(...args) {
const options = AbstractText.ensureOptions(args, "Text");
super(options, TextStyle.TextStyle);
this.renderPipeId = "text";
}
_updateBounds() {
const bounds = this._bounds;
const anchor = this._anchor;
const canvasMeasurement = CanvasTextMetrics.CanvasTextMetrics.measureText(
this._text,
this._style
);
const { width, height } = canvasMeasurement;
bounds.minX = -anchor._x * width;
bounds.maxX = bounds.minX + width;
bounds.minY = -anchor._y * height;
bounds.maxY = bounds.minY + height;
}
}
exports.Text = Text;
//# sourceMappingURL=Text.js.map

1
node_modules/pixi.js/lib/scene/text/Text.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"Text.js","sources":["../../../src/scene/text/Text.ts"],"sourcesContent":["import { AbstractText, ensureOptions } from './AbstractText';\nimport { CanvasTextMetrics } from './canvas/CanvasTextMetrics';\nimport { TextStyle } from './TextStyle';\n\nimport type { View } from '../../rendering/renderers/shared/view/View';\nimport type { TextOptions, TextString } from './AbstractText';\nimport type { TextStyleOptions } from './TextStyle';\n\n/**\n * A Text Object will create a line or multiple lines of text.\n *\n * To split a line you can use '\\n' in your text string, or, on the `style` object,\n * change its `wordWrap` property to true and and givae the `wordWrapWidth` property a value.\n *\n * The primary advantage of this class over BitmapText is that you have great control over the style of the text,\n * which you can change at runtime.\n *\n * The primary disadvantages is that each piece of text has it's own texture, which can use more memory.\n * When text changes, this texture has to be re-generated and re-uploaded to the GPU, taking up time.\n * @example\n * import { Text } from 'pixi.js';\n *\n * const text = new Text({\n * text: 'Hello Pixi!',\n * style: {\n * fontFamily: 'Arial',\n * fontSize: 24,\n * fill: 0xff1010,\n * align: 'center',\n * }\n * });\n * @memberof scene\n */\nexport class Text\n extends AbstractText<TextStyle, TextStyleOptions>\n implements View\n{\n public readonly renderPipeId: string = 'text';\n\n /**\n * @param {text.TextOptions} options - The options of the text.\n */\n constructor(options?: TextOptions);\n /** @deprecated since 8.0.0 */\n constructor(text?: TextString, options?: Partial<TextStyle>);\n constructor(...args: [TextOptions?] | [TextString, Partial<TextStyle>])\n {\n const options = ensureOptions(args, 'Text');\n\n super(options, TextStyle);\n }\n\n protected _updateBounds()\n {\n const bounds = this._bounds;\n const anchor = this._anchor;\n\n const canvasMeasurement = CanvasTextMetrics.measureText(\n this._text,\n this._style\n );\n\n const { width, height } = canvasMeasurement;\n\n bounds.minX = (-anchor._x * width);\n bounds.maxX = bounds.minX + width;\n bounds.minY = (-anchor._y * height);\n bounds.maxY = bounds.minY + height;\n }\n}\n"],"names":["AbstractText","ensureOptions","TextStyle","CanvasTextMetrics"],"mappings":";;;;;;;AAiCO,MAAM,aACDA,yBAEZ,CAAA;AAAA,EASI,eAAe,IACf,EAAA;AACI,IAAM,MAAA,OAAA,GAAUC,0BAAc,CAAA,IAAA,EAAM,MAAM,CAAA,CAAA;AAE1C,IAAA,KAAA,CAAM,SAASC,mBAAS,CAAA,CAAA;AAZ5B,IAAA,IAAA,CAAgB,YAAuB,GAAA,MAAA,CAAA;AAAA,GAavC;AAAA,EAEU,aACV,GAAA;AACI,IAAA,MAAM,SAAS,IAAK,CAAA,OAAA,CAAA;AACpB,IAAA,MAAM,SAAS,IAAK,CAAA,OAAA,CAAA;AAEpB,IAAA,MAAM,oBAAoBC,mCAAkB,CAAA,WAAA;AAAA,MACxC,IAAK,CAAA,KAAA;AAAA,MACL,IAAK,CAAA,MAAA;AAAA,KACT,CAAA;AAEA,IAAM,MAAA,EAAE,KAAO,EAAA,MAAA,EAAW,GAAA,iBAAA,CAAA;AAE1B,IAAO,MAAA,CAAA,IAAA,GAAQ,CAAC,MAAA,CAAO,EAAK,GAAA,KAAA,CAAA;AAC5B,IAAO,MAAA,CAAA,IAAA,GAAO,OAAO,IAAO,GAAA,KAAA,CAAA;AAC5B,IAAO,MAAA,CAAA,IAAA,GAAQ,CAAC,MAAA,CAAO,EAAK,GAAA,MAAA,CAAA;AAC5B,IAAO,MAAA,CAAA,IAAA,GAAO,OAAO,IAAO,GAAA,MAAA,CAAA;AAAA,GAChC;AACJ;;;;"}

28
node_modules/pixi.js/lib/scene/text/Text.mjs generated vendored Normal file
View File

@@ -0,0 +1,28 @@
import { AbstractText, ensureOptions } from './AbstractText.mjs';
import { CanvasTextMetrics } from './canvas/CanvasTextMetrics.mjs';
import { TextStyle } from './TextStyle.mjs';
"use strict";
class Text extends AbstractText {
constructor(...args) {
const options = ensureOptions(args, "Text");
super(options, TextStyle);
this.renderPipeId = "text";
}
_updateBounds() {
const bounds = this._bounds;
const anchor = this._anchor;
const canvasMeasurement = CanvasTextMetrics.measureText(
this._text,
this._style
);
const { width, height } = canvasMeasurement;
bounds.minX = -anchor._x * width;
bounds.maxX = bounds.minX + width;
bounds.minY = -anchor._y * height;
bounds.maxY = bounds.minY + height;
}
}
export { Text };
//# sourceMappingURL=Text.mjs.map

1
node_modules/pixi.js/lib/scene/text/Text.mjs.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"Text.mjs","sources":["../../../src/scene/text/Text.ts"],"sourcesContent":["import { AbstractText, ensureOptions } from './AbstractText';\nimport { CanvasTextMetrics } from './canvas/CanvasTextMetrics';\nimport { TextStyle } from './TextStyle';\n\nimport type { View } from '../../rendering/renderers/shared/view/View';\nimport type { TextOptions, TextString } from './AbstractText';\nimport type { TextStyleOptions } from './TextStyle';\n\n/**\n * A Text Object will create a line or multiple lines of text.\n *\n * To split a line you can use '\\n' in your text string, or, on the `style` object,\n * change its `wordWrap` property to true and and givae the `wordWrapWidth` property a value.\n *\n * The primary advantage of this class over BitmapText is that you have great control over the style of the text,\n * which you can change at runtime.\n *\n * The primary disadvantages is that each piece of text has it's own texture, which can use more memory.\n * When text changes, this texture has to be re-generated and re-uploaded to the GPU, taking up time.\n * @example\n * import { Text } from 'pixi.js';\n *\n * const text = new Text({\n * text: 'Hello Pixi!',\n * style: {\n * fontFamily: 'Arial',\n * fontSize: 24,\n * fill: 0xff1010,\n * align: 'center',\n * }\n * });\n * @memberof scene\n */\nexport class Text\n extends AbstractText<TextStyle, TextStyleOptions>\n implements View\n{\n public readonly renderPipeId: string = 'text';\n\n /**\n * @param {text.TextOptions} options - The options of the text.\n */\n constructor(options?: TextOptions);\n /** @deprecated since 8.0.0 */\n constructor(text?: TextString, options?: Partial<TextStyle>);\n constructor(...args: [TextOptions?] | [TextString, Partial<TextStyle>])\n {\n const options = ensureOptions(args, 'Text');\n\n super(options, TextStyle);\n }\n\n protected _updateBounds()\n {\n const bounds = this._bounds;\n const anchor = this._anchor;\n\n const canvasMeasurement = CanvasTextMetrics.measureText(\n this._text,\n this._style\n );\n\n const { width, height } = canvasMeasurement;\n\n bounds.minX = (-anchor._x * width);\n bounds.maxX = bounds.minX + width;\n bounds.minY = (-anchor._y * height);\n bounds.maxY = bounds.minY + height;\n }\n}\n"],"names":[],"mappings":";;;;;AAiCO,MAAM,aACD,YAEZ,CAAA;AAAA,EASI,eAAe,IACf,EAAA;AACI,IAAM,MAAA,OAAA,GAAU,aAAc,CAAA,IAAA,EAAM,MAAM,CAAA,CAAA;AAE1C,IAAA,KAAA,CAAM,SAAS,SAAS,CAAA,CAAA;AAZ5B,IAAA,IAAA,CAAgB,YAAuB,GAAA,MAAA,CAAA;AAAA,GAavC;AAAA,EAEU,aACV,GAAA;AACI,IAAA,MAAM,SAAS,IAAK,CAAA,OAAA,CAAA;AACpB,IAAA,MAAM,SAAS,IAAK,CAAA,OAAA,CAAA;AAEpB,IAAA,MAAM,oBAAoB,iBAAkB,CAAA,WAAA;AAAA,MACxC,IAAK,CAAA,KAAA;AAAA,MACL,IAAK,CAAA,MAAA;AAAA,KACT,CAAA;AAEA,IAAM,MAAA,EAAE,KAAO,EAAA,MAAA,EAAW,GAAA,iBAAA,CAAA;AAE1B,IAAO,MAAA,CAAA,IAAA,GAAQ,CAAC,MAAA,CAAO,EAAK,GAAA,KAAA,CAAA;AAC5B,IAAO,MAAA,CAAA,IAAA,GAAO,OAAO,IAAO,GAAA,KAAA,CAAA;AAC5B,IAAO,MAAA,CAAA,IAAA,GAAQ,CAAC,MAAA,CAAO,EAAK,GAAA,MAAA,CAAA;AAC5B,IAAO,MAAA,CAAA,IAAA,GAAO,OAAO,IAAO,GAAA,MAAA,CAAA;AAAA,GAChC;AACJ;;;;"}

16
node_modules/pixi.js/lib/scene/text/TextMixins.d.ts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
declare global
{
namespace PixiMixins
{
interface RendererSystems
{
canvasText: import('./canvas/CanvasTextSystem').CanvasTextSystem;
}
interface RendererPipes
{
text: import('./canvas/CanvasTextPipe').CanvasTextPipe;
}
}
}
export {};

258
node_modules/pixi.js/lib/scene/text/TextStyle.d.ts generated vendored Normal file
View File

@@ -0,0 +1,258 @@
import EventEmitter from 'eventemitter3';
import { type ColorSource } from '../../color/Color';
import type { TextureDestroyOptions, TypeOrBool } from '../container/destroyTypes';
import type { ConvertedFillStyle, ConvertedStrokeStyle, FillInput, StrokeInput } from '../graphics/shared/FillTypes';
export type TextStyleAlign = 'left' | 'center' | 'right' | 'justify';
export type TextStyleFill = string | string[] | number | number[] | CanvasGradient | CanvasPattern;
export type TextStyleFontStyle = 'normal' | 'italic' | 'oblique';
export type TextStyleFontVariant = 'normal' | 'small-caps';
export type TextStyleFontWeight = 'normal' | 'bold' | 'bolder' | 'lighter' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
export type TextStyleLineJoin = 'miter' | 'round' | 'bevel';
export type TextStyleTextBaseline = 'alphabetic' | 'top' | 'hanging' | 'middle' | 'ideographic' | 'bottom';
export type TextStyleWhiteSpace = 'normal' | 'pre' | 'pre-line';
/**
* A collection of text related classes.
* @namespace text
*/
/**
* A drop shadow effect.
* @memberof text
*/
export type TextDropShadow = {
/** Set alpha for the drop shadow */
alpha: number;
/** Set a angle of the drop shadow */
angle: number;
/** Set a shadow blur radius */
blur: number;
/** A fill style to be used on the e.g., 'red', '#00FF00' */
color: ColorSource;
/** Set a distance of the drop shadow */
distance: number;
};
/**
* Constructor options used for `TextStyle` instances.
* ```js
* const textStyle = new TextStyle({
* fontSize: 12,
* fill: 'black',
* });
* ```
* @see {@link text.TextStyle}
* @memberof text
*/
export interface TextStyleOptions {
/**
* Alignment for multiline text, does not affect single line text
* @type {'left'|'center'|'right'|'justify'}
*/
align?: TextStyleAlign;
/** Indicates if lines can be wrapped within words, it needs `wordWrap` to be set to `true` */
breakWords?: boolean;
/** Set a drop shadow for the text */
dropShadow?: boolean | Partial<TextDropShadow>;
/**
* A canvas fillstyle that will be used on the text e.g., 'red', '#00FF00'.
* Can be an array to create a gradient, e.g., `['#000000','#FFFFFF']`
* {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle|MDN}
* @type {string|string[]|number|number[]|CanvasGradient|CanvasPattern}
*/
fill?: FillInput;
/** The font family, can be a single font name, or a list of names where the first is the preferred font. */
fontFamily?: string | string[];
/** The font size (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') */
fontSize?: number | string;
/**
* The font style.
* @type {'normal'|'italic'|'oblique'}
*/
fontStyle?: TextStyleFontStyle;
/**
* The font variant.
* @type {'normal'|'small-caps'}
*/
fontVariant?: TextStyleFontVariant;
/**
* The font weight.
* @type {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'}
*/
fontWeight?: TextStyleFontWeight;
/** The height of the line, a number that represents the vertical space that a letter uses. */
leading?: number;
/** The amount of spacing between letters, default is 0 */
letterSpacing?: number;
/** The line height, a number that represents the vertical space that a letter uses */
lineHeight?: number;
/**
* Occasionally some fonts are cropped. Adding some padding will prevent this from
* happening by adding padding to all sides of the text.
*/
padding?: number;
/** A canvas fillstyle that will be used on the text stroke, e.g., 'blue', '#FCFF00' */
stroke?: StrokeInput;
/**
* The baseline of the text that is rendered.
* @type {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'}
*/
textBaseline?: TextStyleTextBaseline;
trim?: boolean;
/**
* Determines whether newlines & spaces are collapsed or preserved "normal"
* (collapse, collapse), "pre" (preserve, preserve) | "pre-line" (preserve,
* collapse). It needs wordWrap to be set to true.
* @type {'normal'|'pre'|'pre-line'}
*/
whiteSpace?: TextStyleWhiteSpace;
/** Indicates if word wrap should be used */
wordWrap?: boolean;
/** The width at which text will wrap, it needs wordWrap to be set to true */
wordWrapWidth?: number;
}
/**
* A TextStyle Object contains information to decorate a Text objects.
*
* An instance can be shared between multiple Text objects; then changing the style will update all text objects using it.
* @memberof text
* @example
* import { TextStyle } from 'pixi.js';
* const style = new TextStyle({
* fontFamily: ['Helvetica', 'Arial', 'sans-serif'],
* fontSize: 36,
* });
*/
export declare class TextStyle extends EventEmitter<{
update: TextDropShadow;
}> {
/** The default drop shadow settings */
static defaultDropShadow: TextDropShadow;
/** The default text style settings */
static defaultTextStyle: TextStyleOptions;
_fill: ConvertedFillStyle;
private _originalFill;
_stroke: ConvertedStrokeStyle;
private _originalStroke;
private _dropShadow;
private _fontFamily;
private _fontSize;
private _fontStyle;
private _fontVariant;
private _fontWeight;
private _breakWords;
private _align;
private _leading;
private _letterSpacing;
private _lineHeight;
private _textBaseline;
private _whiteSpace;
private _wordWrap;
private _wordWrapWidth;
private _padding;
protected _styleKey: string;
private _trim;
constructor(style?: Partial<TextStyleOptions>);
/**
* Alignment for multiline text, does not affect single line text.
* @member {'left'|'center'|'right'|'justify'}
*/
get align(): TextStyleAlign;
set align(value: TextStyleAlign);
/** Indicates if lines can be wrapped within words, it needs wordWrap to be set to true. */
get breakWords(): boolean;
set breakWords(value: boolean);
/** Set a drop shadow for the text. */
get dropShadow(): TextDropShadow;
set dropShadow(value: boolean | TextDropShadow);
/** The font family, can be a single font name, or a list of names where the first is the preferred font. */
get fontFamily(): string | string[];
set fontFamily(value: string | string[]);
/** The font size (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') */
get fontSize(): number;
set fontSize(value: string | number);
/**
* The font style.
* @member {'normal'|'italic'|'oblique'}
*/
get fontStyle(): TextStyleFontStyle;
set fontStyle(value: TextStyleFontStyle);
/**
* The font variant.
* @member {'normal'|'small-caps'}
*/
get fontVariant(): TextStyleFontVariant;
set fontVariant(value: TextStyleFontVariant);
/**
* The font weight.
* @member {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'}
*/
get fontWeight(): TextStyleFontWeight;
set fontWeight(value: TextStyleFontWeight);
/** The space between lines. */
get leading(): number;
set leading(value: number);
/** The amount of spacing between letters, default is 0. */
get letterSpacing(): number;
set letterSpacing(value: number);
/** The line height, a number that represents the vertical space that a letter uses. */
get lineHeight(): number;
set lineHeight(value: number);
/**
* Occasionally some fonts are cropped. Adding some padding will prevent this from happening
* by adding padding to all sides of the text.
*/
get padding(): number;
set padding(value: number);
/** Trim transparent borders. This is an expensive operation so only use this if you have to! */
get trim(): boolean;
set trim(value: boolean);
/**
* The baseline of the text that is rendered.
* @member {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'}
*/
get textBaseline(): TextStyleTextBaseline;
set textBaseline(value: TextStyleTextBaseline);
/**
* How newlines and spaces should be handled.
* Default is 'pre' (preserve, preserve).
*
* value | New lines | Spaces
* --- | --- | ---
* 'normal' | Collapse | Collapse
* 'pre' | Preserve | Preserve
* 'pre-line' | Preserve | Collapse
* @member {'normal'|'pre'|'pre-line'}
*/
get whiteSpace(): TextStyleWhiteSpace;
set whiteSpace(value: TextStyleWhiteSpace);
/** Indicates if word wrap should be used. */
get wordWrap(): boolean;
set wordWrap(value: boolean);
/** The width at which text will wrap, it needs wordWrap to be set to true. */
get wordWrapWidth(): number;
set wordWrapWidth(value: number);
/** A fillstyle that will be used on the text e.g., 'red', '#00FF00'. */
get fill(): FillInput;
set fill(value: FillInput);
/** A fillstyle that will be used on the text stroke, e.g., 'blue', '#FCFF00'. */
get stroke(): StrokeInput;
set stroke(value: StrokeInput);
protected _generateKey(): string;
update(): void;
/** Resets all properties to the default values */
reset(): void;
get styleKey(): string;
/**
* Creates a new TextStyle object with the same values as this one.
* @returns New cloned TextStyle object
*/
clone(): TextStyle;
/**
* Destroys this text style.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the texture of the this style
* @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the this style
*/
destroy(options?: TypeOrBool<TextureDestroyOptions>): void;
private _createProxy;
private _isFillStyle;
}

464
node_modules/pixi.js/lib/scene/text/TextStyle.js generated vendored Normal file
View File

@@ -0,0 +1,464 @@
'use strict';
var EventEmitter = require('eventemitter3');
var Color = require('../../color/Color.js');
var deprecation = require('../../utils/logging/deprecation.js');
var FillGradient = require('../graphics/shared/fill/FillGradient.js');
var FillPattern = require('../graphics/shared/fill/FillPattern.js');
var GraphicsContext = require('../graphics/shared/GraphicsContext.js');
var convertFillInputToFillStyle = require('../graphics/shared/utils/convertFillInputToFillStyle.js');
var generateTextStyleKey = require('./utils/generateTextStyleKey.js');
"use strict";
const _TextStyle = class _TextStyle extends EventEmitter {
constructor(style = {}) {
super();
convertV7Tov8Style(style);
const fullStyle = { ..._TextStyle.defaultTextStyle, ...style };
for (const key in fullStyle) {
const thisKey = key;
this[thisKey] = fullStyle[key];
}
this.update();
}
/**
* Alignment for multiline text, does not affect single line text.
* @member {'left'|'center'|'right'|'justify'}
*/
get align() {
return this._align;
}
set align(value) {
this._align = value;
this.update();
}
/** Indicates if lines can be wrapped within words, it needs wordWrap to be set to true. */
get breakWords() {
return this._breakWords;
}
set breakWords(value) {
this._breakWords = value;
this.update();
}
/** Set a drop shadow for the text. */
get dropShadow() {
return this._dropShadow;
}
set dropShadow(value) {
if (value !== null && typeof value === "object") {
this._dropShadow = this._createProxy({ ..._TextStyle.defaultDropShadow, ...value });
} else {
this._dropShadow = value ? this._createProxy({ ..._TextStyle.defaultDropShadow }) : null;
}
this.update();
}
/** The font family, can be a single font name, or a list of names where the first is the preferred font. */
get fontFamily() {
return this._fontFamily;
}
set fontFamily(value) {
this._fontFamily = value;
this.update();
}
/** The font size (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') */
get fontSize() {
return this._fontSize;
}
set fontSize(value) {
if (typeof value === "string") {
this._fontSize = parseInt(value, 10);
} else {
this._fontSize = value;
}
this.update();
}
/**
* The font style.
* @member {'normal'|'italic'|'oblique'}
*/
get fontStyle() {
return this._fontStyle;
}
set fontStyle(value) {
this._fontStyle = value;
this.update();
}
/**
* The font variant.
* @member {'normal'|'small-caps'}
*/
get fontVariant() {
return this._fontVariant;
}
set fontVariant(value) {
this._fontVariant = value;
this.update();
}
/**
* The font weight.
* @member {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'}
*/
get fontWeight() {
return this._fontWeight;
}
set fontWeight(value) {
this._fontWeight = value;
this.update();
}
/** The space between lines. */
get leading() {
return this._leading;
}
set leading(value) {
this._leading = value;
this.update();
}
/** The amount of spacing between letters, default is 0. */
get letterSpacing() {
return this._letterSpacing;
}
set letterSpacing(value) {
this._letterSpacing = value;
this.update();
}
/** The line height, a number that represents the vertical space that a letter uses. */
get lineHeight() {
return this._lineHeight;
}
set lineHeight(value) {
this._lineHeight = value;
this.update();
}
/**
* Occasionally some fonts are cropped. Adding some padding will prevent this from happening
* by adding padding to all sides of the text.
*/
get padding() {
return this._padding;
}
set padding(value) {
this._padding = value;
this.update();
}
/** Trim transparent borders. This is an expensive operation so only use this if you have to! */
get trim() {
return this._trim;
}
set trim(value) {
this._trim = value;
this.update();
}
/**
* The baseline of the text that is rendered.
* @member {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'}
*/
get textBaseline() {
return this._textBaseline;
}
set textBaseline(value) {
this._textBaseline = value;
this.update();
}
/**
* How newlines and spaces should be handled.
* Default is 'pre' (preserve, preserve).
*
* value | New lines | Spaces
* --- | --- | ---
* 'normal' | Collapse | Collapse
* 'pre' | Preserve | Preserve
* 'pre-line' | Preserve | Collapse
* @member {'normal'|'pre'|'pre-line'}
*/
get whiteSpace() {
return this._whiteSpace;
}
set whiteSpace(value) {
this._whiteSpace = value;
this.update();
}
/** Indicates if word wrap should be used. */
get wordWrap() {
return this._wordWrap;
}
set wordWrap(value) {
this._wordWrap = value;
this.update();
}
/** The width at which text will wrap, it needs wordWrap to be set to true. */
get wordWrapWidth() {
return this._wordWrapWidth;
}
set wordWrapWidth(value) {
this._wordWrapWidth = value;
this.update();
}
/** A fillstyle that will be used on the text e.g., 'red', '#00FF00'. */
get fill() {
return this._originalFill;
}
set fill(value) {
if (value === this._originalFill)
return;
this._originalFill = value;
if (this._isFillStyle(value)) {
this._originalFill = this._createProxy({ ...GraphicsContext.GraphicsContext.defaultFillStyle, ...value }, () => {
this._fill = convertFillInputToFillStyle.toFillStyle(
{ ...this._originalFill },
GraphicsContext.GraphicsContext.defaultFillStyle
);
});
}
this._fill = convertFillInputToFillStyle.toFillStyle(
value === 0 ? "black" : value,
GraphicsContext.GraphicsContext.defaultFillStyle
);
this.update();
}
/** A fillstyle that will be used on the text stroke, e.g., 'blue', '#FCFF00'. */
get stroke() {
return this._originalStroke;
}
set stroke(value) {
if (value === this._originalStroke)
return;
this._originalStroke = value;
if (this._isFillStyle(value)) {
this._originalStroke = this._createProxy({ ...GraphicsContext.GraphicsContext.defaultStrokeStyle, ...value }, () => {
this._stroke = convertFillInputToFillStyle.toStrokeStyle(
{ ...this._originalStroke },
GraphicsContext.GraphicsContext.defaultStrokeStyle
);
});
}
this._stroke = convertFillInputToFillStyle.toStrokeStyle(value, GraphicsContext.GraphicsContext.defaultStrokeStyle);
this.update();
}
_generateKey() {
this._styleKey = generateTextStyleKey.generateTextStyleKey(this);
return this._styleKey;
}
update() {
this._styleKey = null;
this.emit("update", this);
}
/** Resets all properties to the default values */
reset() {
const defaultStyle = _TextStyle.defaultTextStyle;
for (const key in defaultStyle) {
this[key] = defaultStyle[key];
}
}
get styleKey() {
return this._styleKey || this._generateKey();
}
/**
* Creates a new TextStyle object with the same values as this one.
* @returns New cloned TextStyle object
*/
clone() {
return new _TextStyle({
align: this.align,
breakWords: this.breakWords,
dropShadow: this._dropShadow ? { ...this._dropShadow } : null,
fill: this._fill,
fontFamily: this.fontFamily,
fontSize: this.fontSize,
fontStyle: this.fontStyle,
fontVariant: this.fontVariant,
fontWeight: this.fontWeight,
leading: this.leading,
letterSpacing: this.letterSpacing,
lineHeight: this.lineHeight,
padding: this.padding,
stroke: this._stroke,
textBaseline: this.textBaseline,
whiteSpace: this.whiteSpace,
wordWrap: this.wordWrap,
wordWrapWidth: this.wordWrapWidth
});
}
/**
* Destroys this text style.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the texture of the this style
* @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the this style
*/
destroy(options = false) {
this.removeAllListeners();
const destroyTexture = typeof options === "boolean" ? options : options?.texture;
if (destroyTexture) {
const destroyTextureSource = typeof options === "boolean" ? options : options?.textureSource;
if (this._fill?.texture) {
this._fill.texture.destroy(destroyTextureSource);
}
if (this._originalFill?.texture) {
this._originalFill.texture.destroy(destroyTextureSource);
}
if (this._stroke?.texture) {
this._stroke.texture.destroy(destroyTextureSource);
}
if (this._originalStroke?.texture) {
this._originalStroke.texture.destroy(destroyTextureSource);
}
}
this._fill = null;
this._stroke = null;
this.dropShadow = null;
this._originalStroke = null;
this._originalFill = null;
}
_createProxy(value, cb) {
return new Proxy(value, {
set: (target, property, newValue) => {
target[property] = newValue;
cb?.(property, newValue);
this.update();
return true;
}
});
}
_isFillStyle(value) {
return (value ?? null) !== null && !(Color.Color.isColorLike(value) || value instanceof FillGradient.FillGradient || value instanceof FillPattern.FillPattern);
}
};
/** The default drop shadow settings */
_TextStyle.defaultDropShadow = {
/** Set alpha for the drop shadow */
alpha: 1,
/** Set a angle of the drop shadow */
angle: Math.PI / 6,
/** Set a shadow blur radius */
blur: 0,
/** A fill style to be used on the e.g., 'red', '#00FF00' */
color: "black",
/** Set a distance of the drop shadow */
distance: 5
};
/** The default text style settings */
_TextStyle.defaultTextStyle = {
/**
* See {@link TextStyle.align}
* @type {'left'|'center'|'right'|'justify'}
*/
align: "left",
/** See {@link TextStyle.breakWords} */
breakWords: false,
/** See {@link TextStyle.dropShadow} */
dropShadow: null,
/**
* See {@link TextStyle.fill}
* @type {string|string[]|number|number[]|CanvasGradient|CanvasPattern}
*/
fill: "black",
/**
* See {@link TextStyle.fontFamily}
* @type {string|string[]}
*/
fontFamily: "Arial",
/**
* See {@link TextStyle.fontSize}
* @type {number|string}
*/
fontSize: 26,
/**
* See {@link TextStyle.fontStyle}
* @type {'normal'|'italic'|'oblique'}
*/
fontStyle: "normal",
/**
* See {@link TextStyle.fontVariant}
* @type {'normal'|'small-caps'}
*/
fontVariant: "normal",
/**
* See {@link TextStyle.fontWeight}
* @type {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'}
*/
fontWeight: "normal",
/** See {@link TextStyle.leading} */
leading: 0,
/** See {@link TextStyle.letterSpacing} */
letterSpacing: 0,
/** See {@link TextStyle.lineHeight} */
lineHeight: 0,
/** See {@link TextStyle.padding} */
padding: 0,
/**
* See {@link TextStyle.stroke}
* @type {string|number}
*/
stroke: null,
/**
* See {@link TextStyle.textBaseline}
* @type {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'}
*/
textBaseline: "alphabetic",
/** See {@link TextStyle.trim} */
trim: false,
/**
* See {@link TextStyle.whiteSpace}
* @type {'normal'|'pre'|'pre-line'}
*/
whiteSpace: "pre",
/** See {@link TextStyle.wordWrap} */
wordWrap: false,
/** See {@link TextStyle.wordWrapWidth} */
wordWrapWidth: 100
};
let TextStyle = _TextStyle;
function convertV7Tov8Style(style) {
const oldStyle = style;
if (typeof oldStyle.dropShadow === "boolean" && oldStyle.dropShadow) {
const defaults = TextStyle.defaultDropShadow;
style.dropShadow = {
alpha: oldStyle.dropShadowAlpha ?? defaults.alpha,
angle: oldStyle.dropShadowAngle ?? defaults.angle,
blur: oldStyle.dropShadowBlur ?? defaults.blur,
color: oldStyle.dropShadowColor ?? defaults.color,
distance: oldStyle.dropShadowDistance ?? defaults.distance
};
}
if (oldStyle.strokeThickness !== void 0) {
deprecation.deprecation(deprecation.v8_0_0, "strokeThickness is now a part of stroke");
const color = oldStyle.stroke;
let obj = {};
if (Color.Color.isColorLike(color)) {
obj.color = color;
} else if (color instanceof FillGradient.FillGradient || color instanceof FillPattern.FillPattern) {
obj.fill = color;
} else if (Object.hasOwnProperty.call(color, "color") || Object.hasOwnProperty.call(color, "fill")) {
obj = color;
} else {
throw new Error("Invalid stroke value.");
}
style.stroke = {
...obj,
width: oldStyle.strokeThickness
};
}
if (Array.isArray(oldStyle.fillGradientStops)) {
deprecation.deprecation(deprecation.v8_0_0, "gradient fill is now a fill pattern: `new FillGradient(...)`");
let fontSize;
if (style.fontSize == null) {
style.fontSize = TextStyle.defaultTextStyle.fontSize;
} else if (typeof style.fontSize === "string") {
fontSize = parseInt(style.fontSize, 10);
} else {
fontSize = style.fontSize;
}
const gradientFill = new FillGradient.FillGradient(0, 0, 0, fontSize * 1.7);
const fills = oldStyle.fillGradientStops.map((color) => Color.Color.shared.setValue(color).toNumber());
fills.forEach((number, index) => {
const ratio = index / (fills.length - 1);
gradientFill.addColorStop(ratio, number);
});
style.fill = {
fill: gradientFill
};
}
}
exports.TextStyle = TextStyle;
//# sourceMappingURL=TextStyle.js.map

1
node_modules/pixi.js/lib/scene/text/TextStyle.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

462
node_modules/pixi.js/lib/scene/text/TextStyle.mjs generated vendored Normal file
View File

@@ -0,0 +1,462 @@
import EventEmitter from 'eventemitter3';
import { Color } from '../../color/Color.mjs';
import { deprecation, v8_0_0 } from '../../utils/logging/deprecation.mjs';
import { FillGradient } from '../graphics/shared/fill/FillGradient.mjs';
import { FillPattern } from '../graphics/shared/fill/FillPattern.mjs';
import { GraphicsContext } from '../graphics/shared/GraphicsContext.mjs';
import { toFillStyle, toStrokeStyle } from '../graphics/shared/utils/convertFillInputToFillStyle.mjs';
import { generateTextStyleKey } from './utils/generateTextStyleKey.mjs';
"use strict";
const _TextStyle = class _TextStyle extends EventEmitter {
constructor(style = {}) {
super();
convertV7Tov8Style(style);
const fullStyle = { ..._TextStyle.defaultTextStyle, ...style };
for (const key in fullStyle) {
const thisKey = key;
this[thisKey] = fullStyle[key];
}
this.update();
}
/**
* Alignment for multiline text, does not affect single line text.
* @member {'left'|'center'|'right'|'justify'}
*/
get align() {
return this._align;
}
set align(value) {
this._align = value;
this.update();
}
/** Indicates if lines can be wrapped within words, it needs wordWrap to be set to true. */
get breakWords() {
return this._breakWords;
}
set breakWords(value) {
this._breakWords = value;
this.update();
}
/** Set a drop shadow for the text. */
get dropShadow() {
return this._dropShadow;
}
set dropShadow(value) {
if (value !== null && typeof value === "object") {
this._dropShadow = this._createProxy({ ..._TextStyle.defaultDropShadow, ...value });
} else {
this._dropShadow = value ? this._createProxy({ ..._TextStyle.defaultDropShadow }) : null;
}
this.update();
}
/** The font family, can be a single font name, or a list of names where the first is the preferred font. */
get fontFamily() {
return this._fontFamily;
}
set fontFamily(value) {
this._fontFamily = value;
this.update();
}
/** The font size (as a number it converts to px, but as a string, equivalents are '26px','20pt','160%' or '1.6em') */
get fontSize() {
return this._fontSize;
}
set fontSize(value) {
if (typeof value === "string") {
this._fontSize = parseInt(value, 10);
} else {
this._fontSize = value;
}
this.update();
}
/**
* The font style.
* @member {'normal'|'italic'|'oblique'}
*/
get fontStyle() {
return this._fontStyle;
}
set fontStyle(value) {
this._fontStyle = value;
this.update();
}
/**
* The font variant.
* @member {'normal'|'small-caps'}
*/
get fontVariant() {
return this._fontVariant;
}
set fontVariant(value) {
this._fontVariant = value;
this.update();
}
/**
* The font weight.
* @member {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'}
*/
get fontWeight() {
return this._fontWeight;
}
set fontWeight(value) {
this._fontWeight = value;
this.update();
}
/** The space between lines. */
get leading() {
return this._leading;
}
set leading(value) {
this._leading = value;
this.update();
}
/** The amount of spacing between letters, default is 0. */
get letterSpacing() {
return this._letterSpacing;
}
set letterSpacing(value) {
this._letterSpacing = value;
this.update();
}
/** The line height, a number that represents the vertical space that a letter uses. */
get lineHeight() {
return this._lineHeight;
}
set lineHeight(value) {
this._lineHeight = value;
this.update();
}
/**
* Occasionally some fonts are cropped. Adding some padding will prevent this from happening
* by adding padding to all sides of the text.
*/
get padding() {
return this._padding;
}
set padding(value) {
this._padding = value;
this.update();
}
/** Trim transparent borders. This is an expensive operation so only use this if you have to! */
get trim() {
return this._trim;
}
set trim(value) {
this._trim = value;
this.update();
}
/**
* The baseline of the text that is rendered.
* @member {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'}
*/
get textBaseline() {
return this._textBaseline;
}
set textBaseline(value) {
this._textBaseline = value;
this.update();
}
/**
* How newlines and spaces should be handled.
* Default is 'pre' (preserve, preserve).
*
* value | New lines | Spaces
* --- | --- | ---
* 'normal' | Collapse | Collapse
* 'pre' | Preserve | Preserve
* 'pre-line' | Preserve | Collapse
* @member {'normal'|'pre'|'pre-line'}
*/
get whiteSpace() {
return this._whiteSpace;
}
set whiteSpace(value) {
this._whiteSpace = value;
this.update();
}
/** Indicates if word wrap should be used. */
get wordWrap() {
return this._wordWrap;
}
set wordWrap(value) {
this._wordWrap = value;
this.update();
}
/** The width at which text will wrap, it needs wordWrap to be set to true. */
get wordWrapWidth() {
return this._wordWrapWidth;
}
set wordWrapWidth(value) {
this._wordWrapWidth = value;
this.update();
}
/** A fillstyle that will be used on the text e.g., 'red', '#00FF00'. */
get fill() {
return this._originalFill;
}
set fill(value) {
if (value === this._originalFill)
return;
this._originalFill = value;
if (this._isFillStyle(value)) {
this._originalFill = this._createProxy({ ...GraphicsContext.defaultFillStyle, ...value }, () => {
this._fill = toFillStyle(
{ ...this._originalFill },
GraphicsContext.defaultFillStyle
);
});
}
this._fill = toFillStyle(
value === 0 ? "black" : value,
GraphicsContext.defaultFillStyle
);
this.update();
}
/** A fillstyle that will be used on the text stroke, e.g., 'blue', '#FCFF00'. */
get stroke() {
return this._originalStroke;
}
set stroke(value) {
if (value === this._originalStroke)
return;
this._originalStroke = value;
if (this._isFillStyle(value)) {
this._originalStroke = this._createProxy({ ...GraphicsContext.defaultStrokeStyle, ...value }, () => {
this._stroke = toStrokeStyle(
{ ...this._originalStroke },
GraphicsContext.defaultStrokeStyle
);
});
}
this._stroke = toStrokeStyle(value, GraphicsContext.defaultStrokeStyle);
this.update();
}
_generateKey() {
this._styleKey = generateTextStyleKey(this);
return this._styleKey;
}
update() {
this._styleKey = null;
this.emit("update", this);
}
/** Resets all properties to the default values */
reset() {
const defaultStyle = _TextStyle.defaultTextStyle;
for (const key in defaultStyle) {
this[key] = defaultStyle[key];
}
}
get styleKey() {
return this._styleKey || this._generateKey();
}
/**
* Creates a new TextStyle object with the same values as this one.
* @returns New cloned TextStyle object
*/
clone() {
return new _TextStyle({
align: this.align,
breakWords: this.breakWords,
dropShadow: this._dropShadow ? { ...this._dropShadow } : null,
fill: this._fill,
fontFamily: this.fontFamily,
fontSize: this.fontSize,
fontStyle: this.fontStyle,
fontVariant: this.fontVariant,
fontWeight: this.fontWeight,
leading: this.leading,
letterSpacing: this.letterSpacing,
lineHeight: this.lineHeight,
padding: this.padding,
stroke: this._stroke,
textBaseline: this.textBaseline,
whiteSpace: this.whiteSpace,
wordWrap: this.wordWrap,
wordWrapWidth: this.wordWrapWidth
});
}
/**
* Destroys this text style.
* @param options - Options parameter. A boolean will act as if all options
* have been set to that value
* @param {boolean} [options.texture=false] - Should it destroy the texture of the this style
* @param {boolean} [options.textureSource=false] - Should it destroy the textureSource of the this style
*/
destroy(options = false) {
this.removeAllListeners();
const destroyTexture = typeof options === "boolean" ? options : options?.texture;
if (destroyTexture) {
const destroyTextureSource = typeof options === "boolean" ? options : options?.textureSource;
if (this._fill?.texture) {
this._fill.texture.destroy(destroyTextureSource);
}
if (this._originalFill?.texture) {
this._originalFill.texture.destroy(destroyTextureSource);
}
if (this._stroke?.texture) {
this._stroke.texture.destroy(destroyTextureSource);
}
if (this._originalStroke?.texture) {
this._originalStroke.texture.destroy(destroyTextureSource);
}
}
this._fill = null;
this._stroke = null;
this.dropShadow = null;
this._originalStroke = null;
this._originalFill = null;
}
_createProxy(value, cb) {
return new Proxy(value, {
set: (target, property, newValue) => {
target[property] = newValue;
cb?.(property, newValue);
this.update();
return true;
}
});
}
_isFillStyle(value) {
return (value ?? null) !== null && !(Color.isColorLike(value) || value instanceof FillGradient || value instanceof FillPattern);
}
};
/** The default drop shadow settings */
_TextStyle.defaultDropShadow = {
/** Set alpha for the drop shadow */
alpha: 1,
/** Set a angle of the drop shadow */
angle: Math.PI / 6,
/** Set a shadow blur radius */
blur: 0,
/** A fill style to be used on the e.g., 'red', '#00FF00' */
color: "black",
/** Set a distance of the drop shadow */
distance: 5
};
/** The default text style settings */
_TextStyle.defaultTextStyle = {
/**
* See {@link TextStyle.align}
* @type {'left'|'center'|'right'|'justify'}
*/
align: "left",
/** See {@link TextStyle.breakWords} */
breakWords: false,
/** See {@link TextStyle.dropShadow} */
dropShadow: null,
/**
* See {@link TextStyle.fill}
* @type {string|string[]|number|number[]|CanvasGradient|CanvasPattern}
*/
fill: "black",
/**
* See {@link TextStyle.fontFamily}
* @type {string|string[]}
*/
fontFamily: "Arial",
/**
* See {@link TextStyle.fontSize}
* @type {number|string}
*/
fontSize: 26,
/**
* See {@link TextStyle.fontStyle}
* @type {'normal'|'italic'|'oblique'}
*/
fontStyle: "normal",
/**
* See {@link TextStyle.fontVariant}
* @type {'normal'|'small-caps'}
*/
fontVariant: "normal",
/**
* See {@link TextStyle.fontWeight}
* @type {'normal'|'bold'|'bolder'|'lighter'|'100'|'200'|'300'|'400'|'500'|'600'|'700'|'800'|'900'}
*/
fontWeight: "normal",
/** See {@link TextStyle.leading} */
leading: 0,
/** See {@link TextStyle.letterSpacing} */
letterSpacing: 0,
/** See {@link TextStyle.lineHeight} */
lineHeight: 0,
/** See {@link TextStyle.padding} */
padding: 0,
/**
* See {@link TextStyle.stroke}
* @type {string|number}
*/
stroke: null,
/**
* See {@link TextStyle.textBaseline}
* @type {'alphabetic'|'top'|'hanging'|'middle'|'ideographic'|'bottom'}
*/
textBaseline: "alphabetic",
/** See {@link TextStyle.trim} */
trim: false,
/**
* See {@link TextStyle.whiteSpace}
* @type {'normal'|'pre'|'pre-line'}
*/
whiteSpace: "pre",
/** See {@link TextStyle.wordWrap} */
wordWrap: false,
/** See {@link TextStyle.wordWrapWidth} */
wordWrapWidth: 100
};
let TextStyle = _TextStyle;
function convertV7Tov8Style(style) {
const oldStyle = style;
if (typeof oldStyle.dropShadow === "boolean" && oldStyle.dropShadow) {
const defaults = TextStyle.defaultDropShadow;
style.dropShadow = {
alpha: oldStyle.dropShadowAlpha ?? defaults.alpha,
angle: oldStyle.dropShadowAngle ?? defaults.angle,
blur: oldStyle.dropShadowBlur ?? defaults.blur,
color: oldStyle.dropShadowColor ?? defaults.color,
distance: oldStyle.dropShadowDistance ?? defaults.distance
};
}
if (oldStyle.strokeThickness !== void 0) {
deprecation(v8_0_0, "strokeThickness is now a part of stroke");
const color = oldStyle.stroke;
let obj = {};
if (Color.isColorLike(color)) {
obj.color = color;
} else if (color instanceof FillGradient || color instanceof FillPattern) {
obj.fill = color;
} else if (Object.hasOwnProperty.call(color, "color") || Object.hasOwnProperty.call(color, "fill")) {
obj = color;
} else {
throw new Error("Invalid stroke value.");
}
style.stroke = {
...obj,
width: oldStyle.strokeThickness
};
}
if (Array.isArray(oldStyle.fillGradientStops)) {
deprecation(v8_0_0, "gradient fill is now a fill pattern: `new FillGradient(...)`");
let fontSize;
if (style.fontSize == null) {
style.fontSize = TextStyle.defaultTextStyle.fontSize;
} else if (typeof style.fontSize === "string") {
fontSize = parseInt(style.fontSize, 10);
} else {
fontSize = style.fontSize;
}
const gradientFill = new FillGradient(0, 0, 0, fontSize * 1.7);
const fills = oldStyle.fillGradientStops.map((color) => Color.shared.setValue(color).toNumber());
fills.forEach((number, index) => {
const ratio = index / (fills.length - 1);
gradientFill.addColorStop(ratio, number);
});
style.fill = {
fill: gradientFill
};
}
}
export { TextStyle };
//# sourceMappingURL=TextStyle.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,246 @@
import type { ICanvas } from '../../../environment/canvas/ICanvas';
import type { ICanvasRenderingContext2D } from '../../../environment/canvas/ICanvasRenderingContext2D';
import type { TextStyle } from '../TextStyle';
/**
* A number, or a string containing a number.
* @memberof text
* @typedef {object} FontMetrics
* @property {number} ascent - Font ascent
* @property {number} descent - Font descent
* @property {number} fontSize - Font size
*/
export interface FontMetrics {
ascent: number;
descent: number;
fontSize: number;
}
/**
* The TextMetrics object represents the measurement of a block of text with a specified style.
* @example
* import { TextMetrics, TextStyle } from 'pixi.js';
*
* const style = new TextStyle({
* fontFamily: 'Arial',
* fontSize: 24,
* fill: 0xff1010,
* align: 'center',
* });
* const textMetrics = TextMetrics.measureText('Your text', style);
* @memberof text
*/
export declare class CanvasTextMetrics {
/** The text that was measured. */
text: string;
/** The style that was measured. */
style: TextStyle;
/** The measured width of the text. */
width: number;
/** The measured height of the text. */
height: number;
/** An array of lines of the text broken by new lines and wrapping is specified in style. */
lines: string[];
/** An array of the line widths for each line matched to `lines`. */
lineWidths: number[];
/** The measured line height for this style. */
lineHeight: number;
/** The maximum line width for all measured lines. */
maxLineWidth: number;
/** The font properties object from TextMetrics.measureFont. */
fontProperties: FontMetrics;
/**
* String used for calculate font metrics.
* These characters are all tall to help calculate the height required for text.
*/
static METRICS_STRING: string;
/** Baseline symbol for calculate font metrics. */
static BASELINE_SYMBOL: string;
/** Baseline multiplier for calculate font metrics. */
static BASELINE_MULTIPLIER: number;
/** Height multiplier for setting height of canvas to calculate font metrics. */
static HEIGHT_MULTIPLIER: number;
/**
* A Unicode "character", or "grapheme cluster", can be composed of multiple Unicode code points,
* such as letters with diacritical marks (e.g. `'\u0065\u0301'`, letter e with acute)
* or emojis with modifiers (e.g. `'\uD83E\uDDD1\u200D\uD83D\uDCBB'`, technologist).
* The new `Intl.Segmenter` API in ES2022 can split the string into grapheme clusters correctly. If it is not available,
* PixiJS will fallback to use the iterator of String, which can only spilt the string into code points.
* If you want to get full functionality in environments that don't support `Intl.Segmenter` (such as Firefox),
* you can use other libraries such as [grapheme-splitter]{@link https://www.npmjs.com/package/grapheme-splitter}
* or [graphemer]{@link https://www.npmjs.com/package/graphemer} to create a polyfill. Since these libraries can be
* relatively large in size to handle various Unicode grapheme clusters properly, PixiJS won't use them directly.
*/
static graphemeSegmenter: (s: string) => string[];
static _experimentalLetterSpacingSupported?: boolean;
/**
* Checking that we can use modern canvas 2D API.
*
* Note: This is an unstable API, Chrome < 94 use `textLetterSpacing`, later versions use `letterSpacing`.
* @see TextMetrics.experimentalLetterSpacing
* @see https://developer.mozilla.org/en-US/docs/Web/API/ICanvasRenderingContext2D/letterSpacing
* @see https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441
*/
static get experimentalLetterSpacingSupported(): boolean;
/**
* New rendering behavior for letter-spacing which uses Chrome's new native API. This will
* lead to more accurate letter-spacing results because it does not try to manually draw
* each character. However, this Chrome API is experimental and may not serve all cases yet.
* @see TextMetrics.experimentalLetterSpacingSupported
*/
static experimentalLetterSpacing: boolean;
/** Cache of {@see TextMetrics.FontMetrics} objects. */
private static _fonts;
/** Cache of new line chars. */
private static readonly _newlines;
/** Cache of breaking spaces. */
private static readonly _breakingSpaces;
private static __canvas;
private static __context;
private static readonly _measurementCache;
/**
* @param text - the text that was measured
* @param style - the style that was measured
* @param width - the measured width of the text
* @param height - the measured height of the text
* @param lines - an array of the lines of text broken by new lines and wrapping if specified in style
* @param lineWidths - an array of the line widths for each line matched to `lines`
* @param lineHeight - the measured line height for this style
* @param maxLineWidth - the maximum line width for all measured lines
* @param {FontMetrics} fontProperties - the font properties object from TextMetrics.measureFont
*/
constructor(text: string, style: TextStyle, width: number, height: number, lines: string[], lineWidths: number[], lineHeight: number, maxLineWidth: number, fontProperties: FontMetrics);
/**
* Measures the supplied string of text and returns a Rectangle.
* @param text - The text to measure.
* @param style - The text style to use for measuring
* @param canvas - optional specification of the canvas to use for measuring.
* @param wordWrap
* @returns Measured width and height of the text.
*/
static measureText(text: string, style: TextStyle, canvas?: ICanvas, wordWrap?: boolean): CanvasTextMetrics;
private static _measureText;
/**
* Applies newlines to a string to have it optimally fit into the horizontal
* bounds set by the Text object's wordWrapWidth property.
* @param text - String to apply word wrapping to
* @param style - the style to use when wrapping
* @param canvas - optional specification of the canvas to use for measuring.
* @returns New string with new lines applied where required
*/
private static _wordWrap;
/**
* Convenience function for logging each line added during the wordWrap method.
* @param line - The line of text to add
* @param newLine - Add new line character to end
* @returns A formatted line
*/
private static _addLine;
/**
* Gets & sets the widths of calculated characters in a cache object
* @param key - The key
* @param letterSpacing - The letter spacing
* @param cache - The cache
* @param context - The canvas context
* @returns The from cache.
*/
private static _getFromCache;
/**
* Determines whether we should collapse breaking spaces.
* @param whiteSpace - The TextStyle property whiteSpace
* @returns Should collapse
*/
private static _collapseSpaces;
/**
* Determines whether we should collapse newLine chars.
* @param whiteSpace - The white space
* @returns should collapse
*/
private static _collapseNewlines;
/**
* Trims breaking whitespaces from string.
* @param text - The text
* @returns Trimmed string
*/
private static _trimRight;
/**
* Determines if char is a newline.
* @param char - The character
* @returns True if newline, False otherwise.
*/
private static _isNewline;
/**
* Determines if char is a breaking whitespace.
*
* It allows one to determine whether char should be a breaking whitespace
* For example certain characters in CJK langs or numbers.
* It must return a boolean.
* @param char - The character
* @param [_nextChar] - The next character
* @returns True if whitespace, False otherwise.
*/
static isBreakingSpace(char: string, _nextChar?: string): boolean;
/**
* Splits a string into words, breaking-spaces and newLine characters
* @param text - The text
* @returns A tokenized array
*/
private static _tokenize;
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It allows one to customise which words should break
* Examples are if the token is CJK or numbers.
* It must return a boolean.
* @param _token - The token
* @param breakWords - The style attr break words
* @returns Whether to break word or not
*/
static canBreakWords(_token: string, breakWords: boolean): boolean;
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It allows one to determine whether a pair of characters
* should be broken by newlines
* For example certain characters in CJK langs or numbers.
* It must return a boolean.
* @param _char - The character
* @param _nextChar - The next character
* @param _token - The token/word the characters are from
* @param _index - The index in the token of the char
* @param _breakWords - The style attr break words
* @returns whether to break word or not
*/
static canBreakChars(_char: string, _nextChar: string, _token: string, _index: number, _breakWords: boolean): boolean;
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It is called when a token (usually a word) has to be split into separate pieces
* in order to determine the point to break a word.
* It must return an array of characters.
* @param token - The token to split
* @returns The characters of the token
* @see CanvasTextMetrics.graphemeSegmenter
*/
static wordWrapSplit(token: string): string[];
/**
* Calculates the ascent, descent and fontSize of a given font-style
* @param font - String representing the style of the font
* @returns Font properties object
*/
static measureFont(font: string): FontMetrics;
/**
* Clear font metrics in metrics cache.
* @param {string} [font] - font name. If font name not set then clear cache for all fonts.
*/
static clearMetrics(font?: string): void;
/**
* Cached canvas element for measuring text
* TODO: this should be private, but isn't because of backward compat, will fix later.
* @ignore
*/
static get _canvas(): ICanvas;
/**
* TODO: this should be private, but isn't because of backward compat, will fix later.
* @ignore
*/
static get _context(): ICanvasRenderingContext2D;
}

View File

@@ -0,0 +1,532 @@
'use strict';
var adapter = require('../../../environment/adapter.js');
var fontStringFromTextStyle = require('./utils/fontStringFromTextStyle.js');
"use strict";
const contextSettings = {
// TextMetrics requires getImageData readback for measuring fonts.
willReadFrequently: true
};
const _CanvasTextMetrics = class _CanvasTextMetrics {
/**
* Checking that we can use modern canvas 2D API.
*
* Note: This is an unstable API, Chrome < 94 use `textLetterSpacing`, later versions use `letterSpacing`.
* @see TextMetrics.experimentalLetterSpacing
* @see https://developer.mozilla.org/en-US/docs/Web/API/ICanvasRenderingContext2D/letterSpacing
* @see https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441
*/
static get experimentalLetterSpacingSupported() {
let result = _CanvasTextMetrics._experimentalLetterSpacingSupported;
if (result !== void 0) {
const proto = adapter.DOMAdapter.get().getCanvasRenderingContext2D().prototype;
result = _CanvasTextMetrics._experimentalLetterSpacingSupported = "letterSpacing" in proto || "textLetterSpacing" in proto;
}
return result;
}
/**
* @param text - the text that was measured
* @param style - the style that was measured
* @param width - the measured width of the text
* @param height - the measured height of the text
* @param lines - an array of the lines of text broken by new lines and wrapping if specified in style
* @param lineWidths - an array of the line widths for each line matched to `lines`
* @param lineHeight - the measured line height for this style
* @param maxLineWidth - the maximum line width for all measured lines
* @param {FontMetrics} fontProperties - the font properties object from TextMetrics.measureFont
*/
constructor(text, style, width, height, lines, lineWidths, lineHeight, maxLineWidth, fontProperties) {
this.text = text;
this.style = style;
this.width = width;
this.height = height;
this.lines = lines;
this.lineWidths = lineWidths;
this.lineHeight = lineHeight;
this.maxLineWidth = maxLineWidth;
this.fontProperties = fontProperties;
}
/**
* Measures the supplied string of text and returns a Rectangle.
* @param text - The text to measure.
* @param style - The text style to use for measuring
* @param canvas - optional specification of the canvas to use for measuring.
* @param wordWrap
* @returns Measured width and height of the text.
*/
static measureText(text = " ", style, canvas = _CanvasTextMetrics._canvas, wordWrap = style.wordWrap) {
const textKey = `${text}:${style.styleKey}`;
if (_CanvasTextMetrics._measurementCache[textKey])
return _CanvasTextMetrics._measurementCache[textKey];
const font = fontStringFromTextStyle.fontStringFromTextStyle(style);
const fontProperties = _CanvasTextMetrics.measureFont(font);
if (fontProperties.fontSize === 0) {
fontProperties.fontSize = style.fontSize;
fontProperties.ascent = style.fontSize;
}
const context = _CanvasTextMetrics.__context;
context.font = font;
const outputText = wordWrap ? _CanvasTextMetrics._wordWrap(text, style, canvas) : text;
const lines = outputText.split(/(?:\r\n|\r|\n)/);
const lineWidths = new Array(lines.length);
let maxLineWidth = 0;
for (let i = 0; i < lines.length; i++) {
const lineWidth = _CanvasTextMetrics._measureText(lines[i], style.letterSpacing, context);
lineWidths[i] = lineWidth;
maxLineWidth = Math.max(maxLineWidth, lineWidth);
}
const strokeWidth = style._stroke?.width || 0;
let width = maxLineWidth + strokeWidth;
if (style.dropShadow) {
width += style.dropShadow.distance;
}
const lineHeight = style.lineHeight || fontProperties.fontSize;
let height = Math.max(lineHeight, fontProperties.fontSize + strokeWidth) + (lines.length - 1) * (lineHeight + style.leading);
if (style.dropShadow) {
height += style.dropShadow.distance;
}
const measurements = new _CanvasTextMetrics(
text,
style,
width,
height,
lines,
lineWidths,
lineHeight + style.leading,
maxLineWidth,
fontProperties
);
return measurements;
}
static _measureText(text, letterSpacing, context) {
let useExperimentalLetterSpacing = false;
if (_CanvasTextMetrics.experimentalLetterSpacingSupported) {
if (_CanvasTextMetrics.experimentalLetterSpacing) {
context.letterSpacing = `${letterSpacing}px`;
context.textLetterSpacing = `${letterSpacing}px`;
useExperimentalLetterSpacing = true;
} else {
context.letterSpacing = "0px";
context.textLetterSpacing = "0px";
}
}
let width = context.measureText(text).width;
if (width > 0) {
if (useExperimentalLetterSpacing) {
width -= letterSpacing;
} else {
width += (_CanvasTextMetrics.graphemeSegmenter(text).length - 1) * letterSpacing;
}
}
return width;
}
/**
* Applies newlines to a string to have it optimally fit into the horizontal
* bounds set by the Text object's wordWrapWidth property.
* @param text - String to apply word wrapping to
* @param style - the style to use when wrapping
* @param canvas - optional specification of the canvas to use for measuring.
* @returns New string with new lines applied where required
*/
static _wordWrap(text, style, canvas = _CanvasTextMetrics._canvas) {
const context = canvas.getContext("2d", contextSettings);
let width = 0;
let line = "";
let lines = "";
const cache = /* @__PURE__ */ Object.create(null);
const { letterSpacing, whiteSpace } = style;
const collapseSpaces = _CanvasTextMetrics._collapseSpaces(whiteSpace);
const collapseNewlines = _CanvasTextMetrics._collapseNewlines(whiteSpace);
let canPrependSpaces = !collapseSpaces;
const wordWrapWidth = style.wordWrapWidth + letterSpacing;
const tokens = _CanvasTextMetrics._tokenize(text);
for (let i = 0; i < tokens.length; i++) {
let token = tokens[i];
if (_CanvasTextMetrics._isNewline(token)) {
if (!collapseNewlines) {
lines += _CanvasTextMetrics._addLine(line);
canPrependSpaces = !collapseSpaces;
line = "";
width = 0;
continue;
}
token = " ";
}
if (collapseSpaces) {
const currIsBreakingSpace = _CanvasTextMetrics.isBreakingSpace(token);
const lastIsBreakingSpace = _CanvasTextMetrics.isBreakingSpace(line[line.length - 1]);
if (currIsBreakingSpace && lastIsBreakingSpace) {
continue;
}
}
const tokenWidth = _CanvasTextMetrics._getFromCache(token, letterSpacing, cache, context);
if (tokenWidth > wordWrapWidth) {
if (line !== "") {
lines += _CanvasTextMetrics._addLine(line);
line = "";
width = 0;
}
if (_CanvasTextMetrics.canBreakWords(token, style.breakWords)) {
const characters = _CanvasTextMetrics.wordWrapSplit(token);
for (let j = 0; j < characters.length; j++) {
let char = characters[j];
let lastChar = char;
let k = 1;
while (characters[j + k]) {
const nextChar = characters[j + k];
if (!_CanvasTextMetrics.canBreakChars(lastChar, nextChar, token, j, style.breakWords)) {
char += nextChar;
} else {
break;
}
lastChar = nextChar;
k++;
}
j += k - 1;
const characterWidth = _CanvasTextMetrics._getFromCache(char, letterSpacing, cache, context);
if (characterWidth + width > wordWrapWidth) {
lines += _CanvasTextMetrics._addLine(line);
canPrependSpaces = false;
line = "";
width = 0;
}
line += char;
width += characterWidth;
}
} else {
if (line.length > 0) {
lines += _CanvasTextMetrics._addLine(line);
line = "";
width = 0;
}
const isLastToken = i === tokens.length - 1;
lines += _CanvasTextMetrics._addLine(token, !isLastToken);
canPrependSpaces = false;
line = "";
width = 0;
}
} else {
if (tokenWidth + width > wordWrapWidth) {
canPrependSpaces = false;
lines += _CanvasTextMetrics._addLine(line);
line = "";
width = 0;
}
if (line.length > 0 || !_CanvasTextMetrics.isBreakingSpace(token) || canPrependSpaces) {
line += token;
width += tokenWidth;
}
}
}
lines += _CanvasTextMetrics._addLine(line, false);
return lines;
}
/**
* Convenience function for logging each line added during the wordWrap method.
* @param line - The line of text to add
* @param newLine - Add new line character to end
* @returns A formatted line
*/
static _addLine(line, newLine = true) {
line = _CanvasTextMetrics._trimRight(line);
line = newLine ? `${line}
` : line;
return line;
}
/**
* Gets & sets the widths of calculated characters in a cache object
* @param key - The key
* @param letterSpacing - The letter spacing
* @param cache - The cache
* @param context - The canvas context
* @returns The from cache.
*/
static _getFromCache(key, letterSpacing, cache, context) {
let width = cache[key];
if (typeof width !== "number") {
width = _CanvasTextMetrics._measureText(key, letterSpacing, context) + letterSpacing;
cache[key] = width;
}
return width;
}
/**
* Determines whether we should collapse breaking spaces.
* @param whiteSpace - The TextStyle property whiteSpace
* @returns Should collapse
*/
static _collapseSpaces(whiteSpace) {
return whiteSpace === "normal" || whiteSpace === "pre-line";
}
/**
* Determines whether we should collapse newLine chars.
* @param whiteSpace - The white space
* @returns should collapse
*/
static _collapseNewlines(whiteSpace) {
return whiteSpace === "normal";
}
/**
* Trims breaking whitespaces from string.
* @param text - The text
* @returns Trimmed string
*/
static _trimRight(text) {
if (typeof text !== "string") {
return "";
}
for (let i = text.length - 1; i >= 0; i--) {
const char = text[i];
if (!_CanvasTextMetrics.isBreakingSpace(char)) {
break;
}
text = text.slice(0, -1);
}
return text;
}
/**
* Determines if char is a newline.
* @param char - The character
* @returns True if newline, False otherwise.
*/
static _isNewline(char) {
if (typeof char !== "string") {
return false;
}
return _CanvasTextMetrics._newlines.includes(char.charCodeAt(0));
}
/**
* Determines if char is a breaking whitespace.
*
* It allows one to determine whether char should be a breaking whitespace
* For example certain characters in CJK langs or numbers.
* It must return a boolean.
* @param char - The character
* @param [_nextChar] - The next character
* @returns True if whitespace, False otherwise.
*/
static isBreakingSpace(char, _nextChar) {
if (typeof char !== "string") {
return false;
}
return _CanvasTextMetrics._breakingSpaces.includes(char.charCodeAt(0));
}
/**
* Splits a string into words, breaking-spaces and newLine characters
* @param text - The text
* @returns A tokenized array
*/
static _tokenize(text) {
const tokens = [];
let token = "";
if (typeof text !== "string") {
return tokens;
}
for (let i = 0; i < text.length; i++) {
const char = text[i];
const nextChar = text[i + 1];
if (_CanvasTextMetrics.isBreakingSpace(char, nextChar) || _CanvasTextMetrics._isNewline(char)) {
if (token !== "") {
tokens.push(token);
token = "";
}
tokens.push(char);
continue;
}
token += char;
}
if (token !== "") {
tokens.push(token);
}
return tokens;
}
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It allows one to customise which words should break
* Examples are if the token is CJK or numbers.
* It must return a boolean.
* @param _token - The token
* @param breakWords - The style attr break words
* @returns Whether to break word or not
*/
static canBreakWords(_token, breakWords) {
return breakWords;
}
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It allows one to determine whether a pair of characters
* should be broken by newlines
* For example certain characters in CJK langs or numbers.
* It must return a boolean.
* @param _char - The character
* @param _nextChar - The next character
* @param _token - The token/word the characters are from
* @param _index - The index in the token of the char
* @param _breakWords - The style attr break words
* @returns whether to break word or not
*/
static canBreakChars(_char, _nextChar, _token, _index, _breakWords) {
return true;
}
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It is called when a token (usually a word) has to be split into separate pieces
* in order to determine the point to break a word.
* It must return an array of characters.
* @param token - The token to split
* @returns The characters of the token
* @see CanvasTextMetrics.graphemeSegmenter
*/
static wordWrapSplit(token) {
return _CanvasTextMetrics.graphemeSegmenter(token);
}
/**
* Calculates the ascent, descent and fontSize of a given font-style
* @param font - String representing the style of the font
* @returns Font properties object
*/
static measureFont(font) {
if (_CanvasTextMetrics._fonts[font]) {
return _CanvasTextMetrics._fonts[font];
}
const context = _CanvasTextMetrics._context;
context.font = font;
const metrics = context.measureText(_CanvasTextMetrics.METRICS_STRING + _CanvasTextMetrics.BASELINE_SYMBOL);
const properties = {
ascent: metrics.actualBoundingBoxAscent,
descent: metrics.actualBoundingBoxDescent,
fontSize: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
};
_CanvasTextMetrics._fonts[font] = properties;
return properties;
}
/**
* Clear font metrics in metrics cache.
* @param {string} [font] - font name. If font name not set then clear cache for all fonts.
*/
static clearMetrics(font = "") {
if (font) {
delete _CanvasTextMetrics._fonts[font];
} else {
_CanvasTextMetrics._fonts = {};
}
}
/**
* Cached canvas element for measuring text
* TODO: this should be private, but isn't because of backward compat, will fix later.
* @ignore
*/
static get _canvas() {
if (!_CanvasTextMetrics.__canvas) {
let canvas;
try {
const c = new OffscreenCanvas(0, 0);
const context = c.getContext("2d", contextSettings);
if (context?.measureText) {
_CanvasTextMetrics.__canvas = c;
return c;
}
canvas = adapter.DOMAdapter.get().createCanvas();
} catch (ex) {
canvas = adapter.DOMAdapter.get().createCanvas();
}
canvas.width = canvas.height = 10;
_CanvasTextMetrics.__canvas = canvas;
}
return _CanvasTextMetrics.__canvas;
}
/**
* TODO: this should be private, but isn't because of backward compat, will fix later.
* @ignore
*/
static get _context() {
if (!_CanvasTextMetrics.__context) {
_CanvasTextMetrics.__context = _CanvasTextMetrics._canvas.getContext("2d", contextSettings);
}
return _CanvasTextMetrics.__context;
}
};
/**
* String used for calculate font metrics.
* These characters are all tall to help calculate the height required for text.
*/
_CanvasTextMetrics.METRICS_STRING = "|\xC9q\xC5";
/** Baseline symbol for calculate font metrics. */
_CanvasTextMetrics.BASELINE_SYMBOL = "M";
/** Baseline multiplier for calculate font metrics. */
_CanvasTextMetrics.BASELINE_MULTIPLIER = 1.4;
/** Height multiplier for setting height of canvas to calculate font metrics. */
_CanvasTextMetrics.HEIGHT_MULTIPLIER = 2;
/**
* A Unicode "character", or "grapheme cluster", can be composed of multiple Unicode code points,
* such as letters with diacritical marks (e.g. `'\u0065\u0301'`, letter e with acute)
* or emojis with modifiers (e.g. `'\uD83E\uDDD1\u200D\uD83D\uDCBB'`, technologist).
* The new `Intl.Segmenter` API in ES2022 can split the string into grapheme clusters correctly. If it is not available,
* PixiJS will fallback to use the iterator of String, which can only spilt the string into code points.
* If you want to get full functionality in environments that don't support `Intl.Segmenter` (such as Firefox),
* you can use other libraries such as [grapheme-splitter]{@link https://www.npmjs.com/package/grapheme-splitter}
* or [graphemer]{@link https://www.npmjs.com/package/graphemer} to create a polyfill. Since these libraries can be
* relatively large in size to handle various Unicode grapheme clusters properly, PixiJS won't use them directly.
*/
_CanvasTextMetrics.graphemeSegmenter = (() => {
if (typeof Intl?.Segmenter === "function") {
const segmenter = new Intl.Segmenter();
return (s) => [...segmenter.segment(s)].map((x) => x.segment);
}
return (s) => [...s];
})();
/**
* New rendering behavior for letter-spacing which uses Chrome's new native API. This will
* lead to more accurate letter-spacing results because it does not try to manually draw
* each character. However, this Chrome API is experimental and may not serve all cases yet.
* @see TextMetrics.experimentalLetterSpacingSupported
*/
_CanvasTextMetrics.experimentalLetterSpacing = false;
/** Cache of {@see TextMetrics.FontMetrics} objects. */
_CanvasTextMetrics._fonts = {};
/** Cache of new line chars. */
_CanvasTextMetrics._newlines = [
10,
// line feed
13
// carriage return
];
/** Cache of breaking spaces. */
_CanvasTextMetrics._breakingSpaces = [
9,
// character tabulation
32,
// space
8192,
// en quad
8193,
// em quad
8194,
// en space
8195,
// em space
8196,
// three-per-em space
8197,
// four-per-em space
8198,
// six-per-em space
8200,
// punctuation space
8201,
// thin space
8202,
// hair space
8287,
// medium mathematical space
12288
// ideographic space
];
_CanvasTextMetrics._measurementCache = {};
let CanvasTextMetrics = _CanvasTextMetrics;
exports.CanvasTextMetrics = CanvasTextMetrics;
//# sourceMappingURL=CanvasTextMetrics.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,530 @@
import { DOMAdapter } from '../../../environment/adapter.mjs';
import { fontStringFromTextStyle } from './utils/fontStringFromTextStyle.mjs';
"use strict";
const contextSettings = {
// TextMetrics requires getImageData readback for measuring fonts.
willReadFrequently: true
};
const _CanvasTextMetrics = class _CanvasTextMetrics {
/**
* Checking that we can use modern canvas 2D API.
*
* Note: This is an unstable API, Chrome < 94 use `textLetterSpacing`, later versions use `letterSpacing`.
* @see TextMetrics.experimentalLetterSpacing
* @see https://developer.mozilla.org/en-US/docs/Web/API/ICanvasRenderingContext2D/letterSpacing
* @see https://developer.chrome.com/origintrials/#/view_trial/3585991203293757441
*/
static get experimentalLetterSpacingSupported() {
let result = _CanvasTextMetrics._experimentalLetterSpacingSupported;
if (result !== void 0) {
const proto = DOMAdapter.get().getCanvasRenderingContext2D().prototype;
result = _CanvasTextMetrics._experimentalLetterSpacingSupported = "letterSpacing" in proto || "textLetterSpacing" in proto;
}
return result;
}
/**
* @param text - the text that was measured
* @param style - the style that was measured
* @param width - the measured width of the text
* @param height - the measured height of the text
* @param lines - an array of the lines of text broken by new lines and wrapping if specified in style
* @param lineWidths - an array of the line widths for each line matched to `lines`
* @param lineHeight - the measured line height for this style
* @param maxLineWidth - the maximum line width for all measured lines
* @param {FontMetrics} fontProperties - the font properties object from TextMetrics.measureFont
*/
constructor(text, style, width, height, lines, lineWidths, lineHeight, maxLineWidth, fontProperties) {
this.text = text;
this.style = style;
this.width = width;
this.height = height;
this.lines = lines;
this.lineWidths = lineWidths;
this.lineHeight = lineHeight;
this.maxLineWidth = maxLineWidth;
this.fontProperties = fontProperties;
}
/**
* Measures the supplied string of text and returns a Rectangle.
* @param text - The text to measure.
* @param style - The text style to use for measuring
* @param canvas - optional specification of the canvas to use for measuring.
* @param wordWrap
* @returns Measured width and height of the text.
*/
static measureText(text = " ", style, canvas = _CanvasTextMetrics._canvas, wordWrap = style.wordWrap) {
const textKey = `${text}:${style.styleKey}`;
if (_CanvasTextMetrics._measurementCache[textKey])
return _CanvasTextMetrics._measurementCache[textKey];
const font = fontStringFromTextStyle(style);
const fontProperties = _CanvasTextMetrics.measureFont(font);
if (fontProperties.fontSize === 0) {
fontProperties.fontSize = style.fontSize;
fontProperties.ascent = style.fontSize;
}
const context = _CanvasTextMetrics.__context;
context.font = font;
const outputText = wordWrap ? _CanvasTextMetrics._wordWrap(text, style, canvas) : text;
const lines = outputText.split(/(?:\r\n|\r|\n)/);
const lineWidths = new Array(lines.length);
let maxLineWidth = 0;
for (let i = 0; i < lines.length; i++) {
const lineWidth = _CanvasTextMetrics._measureText(lines[i], style.letterSpacing, context);
lineWidths[i] = lineWidth;
maxLineWidth = Math.max(maxLineWidth, lineWidth);
}
const strokeWidth = style._stroke?.width || 0;
let width = maxLineWidth + strokeWidth;
if (style.dropShadow) {
width += style.dropShadow.distance;
}
const lineHeight = style.lineHeight || fontProperties.fontSize;
let height = Math.max(lineHeight, fontProperties.fontSize + strokeWidth) + (lines.length - 1) * (lineHeight + style.leading);
if (style.dropShadow) {
height += style.dropShadow.distance;
}
const measurements = new _CanvasTextMetrics(
text,
style,
width,
height,
lines,
lineWidths,
lineHeight + style.leading,
maxLineWidth,
fontProperties
);
return measurements;
}
static _measureText(text, letterSpacing, context) {
let useExperimentalLetterSpacing = false;
if (_CanvasTextMetrics.experimentalLetterSpacingSupported) {
if (_CanvasTextMetrics.experimentalLetterSpacing) {
context.letterSpacing = `${letterSpacing}px`;
context.textLetterSpacing = `${letterSpacing}px`;
useExperimentalLetterSpacing = true;
} else {
context.letterSpacing = "0px";
context.textLetterSpacing = "0px";
}
}
let width = context.measureText(text).width;
if (width > 0) {
if (useExperimentalLetterSpacing) {
width -= letterSpacing;
} else {
width += (_CanvasTextMetrics.graphemeSegmenter(text).length - 1) * letterSpacing;
}
}
return width;
}
/**
* Applies newlines to a string to have it optimally fit into the horizontal
* bounds set by the Text object's wordWrapWidth property.
* @param text - String to apply word wrapping to
* @param style - the style to use when wrapping
* @param canvas - optional specification of the canvas to use for measuring.
* @returns New string with new lines applied where required
*/
static _wordWrap(text, style, canvas = _CanvasTextMetrics._canvas) {
const context = canvas.getContext("2d", contextSettings);
let width = 0;
let line = "";
let lines = "";
const cache = /* @__PURE__ */ Object.create(null);
const { letterSpacing, whiteSpace } = style;
const collapseSpaces = _CanvasTextMetrics._collapseSpaces(whiteSpace);
const collapseNewlines = _CanvasTextMetrics._collapseNewlines(whiteSpace);
let canPrependSpaces = !collapseSpaces;
const wordWrapWidth = style.wordWrapWidth + letterSpacing;
const tokens = _CanvasTextMetrics._tokenize(text);
for (let i = 0; i < tokens.length; i++) {
let token = tokens[i];
if (_CanvasTextMetrics._isNewline(token)) {
if (!collapseNewlines) {
lines += _CanvasTextMetrics._addLine(line);
canPrependSpaces = !collapseSpaces;
line = "";
width = 0;
continue;
}
token = " ";
}
if (collapseSpaces) {
const currIsBreakingSpace = _CanvasTextMetrics.isBreakingSpace(token);
const lastIsBreakingSpace = _CanvasTextMetrics.isBreakingSpace(line[line.length - 1]);
if (currIsBreakingSpace && lastIsBreakingSpace) {
continue;
}
}
const tokenWidth = _CanvasTextMetrics._getFromCache(token, letterSpacing, cache, context);
if (tokenWidth > wordWrapWidth) {
if (line !== "") {
lines += _CanvasTextMetrics._addLine(line);
line = "";
width = 0;
}
if (_CanvasTextMetrics.canBreakWords(token, style.breakWords)) {
const characters = _CanvasTextMetrics.wordWrapSplit(token);
for (let j = 0; j < characters.length; j++) {
let char = characters[j];
let lastChar = char;
let k = 1;
while (characters[j + k]) {
const nextChar = characters[j + k];
if (!_CanvasTextMetrics.canBreakChars(lastChar, nextChar, token, j, style.breakWords)) {
char += nextChar;
} else {
break;
}
lastChar = nextChar;
k++;
}
j += k - 1;
const characterWidth = _CanvasTextMetrics._getFromCache(char, letterSpacing, cache, context);
if (characterWidth + width > wordWrapWidth) {
lines += _CanvasTextMetrics._addLine(line);
canPrependSpaces = false;
line = "";
width = 0;
}
line += char;
width += characterWidth;
}
} else {
if (line.length > 0) {
lines += _CanvasTextMetrics._addLine(line);
line = "";
width = 0;
}
const isLastToken = i === tokens.length - 1;
lines += _CanvasTextMetrics._addLine(token, !isLastToken);
canPrependSpaces = false;
line = "";
width = 0;
}
} else {
if (tokenWidth + width > wordWrapWidth) {
canPrependSpaces = false;
lines += _CanvasTextMetrics._addLine(line);
line = "";
width = 0;
}
if (line.length > 0 || !_CanvasTextMetrics.isBreakingSpace(token) || canPrependSpaces) {
line += token;
width += tokenWidth;
}
}
}
lines += _CanvasTextMetrics._addLine(line, false);
return lines;
}
/**
* Convenience function for logging each line added during the wordWrap method.
* @param line - The line of text to add
* @param newLine - Add new line character to end
* @returns A formatted line
*/
static _addLine(line, newLine = true) {
line = _CanvasTextMetrics._trimRight(line);
line = newLine ? `${line}
` : line;
return line;
}
/**
* Gets & sets the widths of calculated characters in a cache object
* @param key - The key
* @param letterSpacing - The letter spacing
* @param cache - The cache
* @param context - The canvas context
* @returns The from cache.
*/
static _getFromCache(key, letterSpacing, cache, context) {
let width = cache[key];
if (typeof width !== "number") {
width = _CanvasTextMetrics._measureText(key, letterSpacing, context) + letterSpacing;
cache[key] = width;
}
return width;
}
/**
* Determines whether we should collapse breaking spaces.
* @param whiteSpace - The TextStyle property whiteSpace
* @returns Should collapse
*/
static _collapseSpaces(whiteSpace) {
return whiteSpace === "normal" || whiteSpace === "pre-line";
}
/**
* Determines whether we should collapse newLine chars.
* @param whiteSpace - The white space
* @returns should collapse
*/
static _collapseNewlines(whiteSpace) {
return whiteSpace === "normal";
}
/**
* Trims breaking whitespaces from string.
* @param text - The text
* @returns Trimmed string
*/
static _trimRight(text) {
if (typeof text !== "string") {
return "";
}
for (let i = text.length - 1; i >= 0; i--) {
const char = text[i];
if (!_CanvasTextMetrics.isBreakingSpace(char)) {
break;
}
text = text.slice(0, -1);
}
return text;
}
/**
* Determines if char is a newline.
* @param char - The character
* @returns True if newline, False otherwise.
*/
static _isNewline(char) {
if (typeof char !== "string") {
return false;
}
return _CanvasTextMetrics._newlines.includes(char.charCodeAt(0));
}
/**
* Determines if char is a breaking whitespace.
*
* It allows one to determine whether char should be a breaking whitespace
* For example certain characters in CJK langs or numbers.
* It must return a boolean.
* @param char - The character
* @param [_nextChar] - The next character
* @returns True if whitespace, False otherwise.
*/
static isBreakingSpace(char, _nextChar) {
if (typeof char !== "string") {
return false;
}
return _CanvasTextMetrics._breakingSpaces.includes(char.charCodeAt(0));
}
/**
* Splits a string into words, breaking-spaces and newLine characters
* @param text - The text
* @returns A tokenized array
*/
static _tokenize(text) {
const tokens = [];
let token = "";
if (typeof text !== "string") {
return tokens;
}
for (let i = 0; i < text.length; i++) {
const char = text[i];
const nextChar = text[i + 1];
if (_CanvasTextMetrics.isBreakingSpace(char, nextChar) || _CanvasTextMetrics._isNewline(char)) {
if (token !== "") {
tokens.push(token);
token = "";
}
tokens.push(char);
continue;
}
token += char;
}
if (token !== "") {
tokens.push(token);
}
return tokens;
}
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It allows one to customise which words should break
* Examples are if the token is CJK or numbers.
* It must return a boolean.
* @param _token - The token
* @param breakWords - The style attr break words
* @returns Whether to break word or not
*/
static canBreakWords(_token, breakWords) {
return breakWords;
}
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It allows one to determine whether a pair of characters
* should be broken by newlines
* For example certain characters in CJK langs or numbers.
* It must return a boolean.
* @param _char - The character
* @param _nextChar - The next character
* @param _token - The token/word the characters are from
* @param _index - The index in the token of the char
* @param _breakWords - The style attr break words
* @returns whether to break word or not
*/
static canBreakChars(_char, _nextChar, _token, _index, _breakWords) {
return true;
}
/**
* Overridable helper method used internally by TextMetrics, exposed to allow customizing the class's behavior.
*
* It is called when a token (usually a word) has to be split into separate pieces
* in order to determine the point to break a word.
* It must return an array of characters.
* @param token - The token to split
* @returns The characters of the token
* @see CanvasTextMetrics.graphemeSegmenter
*/
static wordWrapSplit(token) {
return _CanvasTextMetrics.graphemeSegmenter(token);
}
/**
* Calculates the ascent, descent and fontSize of a given font-style
* @param font - String representing the style of the font
* @returns Font properties object
*/
static measureFont(font) {
if (_CanvasTextMetrics._fonts[font]) {
return _CanvasTextMetrics._fonts[font];
}
const context = _CanvasTextMetrics._context;
context.font = font;
const metrics = context.measureText(_CanvasTextMetrics.METRICS_STRING + _CanvasTextMetrics.BASELINE_SYMBOL);
const properties = {
ascent: metrics.actualBoundingBoxAscent,
descent: metrics.actualBoundingBoxDescent,
fontSize: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent
};
_CanvasTextMetrics._fonts[font] = properties;
return properties;
}
/**
* Clear font metrics in metrics cache.
* @param {string} [font] - font name. If font name not set then clear cache for all fonts.
*/
static clearMetrics(font = "") {
if (font) {
delete _CanvasTextMetrics._fonts[font];
} else {
_CanvasTextMetrics._fonts = {};
}
}
/**
* Cached canvas element for measuring text
* TODO: this should be private, but isn't because of backward compat, will fix later.
* @ignore
*/
static get _canvas() {
if (!_CanvasTextMetrics.__canvas) {
let canvas;
try {
const c = new OffscreenCanvas(0, 0);
const context = c.getContext("2d", contextSettings);
if (context?.measureText) {
_CanvasTextMetrics.__canvas = c;
return c;
}
canvas = DOMAdapter.get().createCanvas();
} catch (ex) {
canvas = DOMAdapter.get().createCanvas();
}
canvas.width = canvas.height = 10;
_CanvasTextMetrics.__canvas = canvas;
}
return _CanvasTextMetrics.__canvas;
}
/**
* TODO: this should be private, but isn't because of backward compat, will fix later.
* @ignore
*/
static get _context() {
if (!_CanvasTextMetrics.__context) {
_CanvasTextMetrics.__context = _CanvasTextMetrics._canvas.getContext("2d", contextSettings);
}
return _CanvasTextMetrics.__context;
}
};
/**
* String used for calculate font metrics.
* These characters are all tall to help calculate the height required for text.
*/
_CanvasTextMetrics.METRICS_STRING = "|\xC9q\xC5";
/** Baseline symbol for calculate font metrics. */
_CanvasTextMetrics.BASELINE_SYMBOL = "M";
/** Baseline multiplier for calculate font metrics. */
_CanvasTextMetrics.BASELINE_MULTIPLIER = 1.4;
/** Height multiplier for setting height of canvas to calculate font metrics. */
_CanvasTextMetrics.HEIGHT_MULTIPLIER = 2;
/**
* A Unicode "character", or "grapheme cluster", can be composed of multiple Unicode code points,
* such as letters with diacritical marks (e.g. `'\u0065\u0301'`, letter e with acute)
* or emojis with modifiers (e.g. `'\uD83E\uDDD1\u200D\uD83D\uDCBB'`, technologist).
* The new `Intl.Segmenter` API in ES2022 can split the string into grapheme clusters correctly. If it is not available,
* PixiJS will fallback to use the iterator of String, which can only spilt the string into code points.
* If you want to get full functionality in environments that don't support `Intl.Segmenter` (such as Firefox),
* you can use other libraries such as [grapheme-splitter]{@link https://www.npmjs.com/package/grapheme-splitter}
* or [graphemer]{@link https://www.npmjs.com/package/graphemer} to create a polyfill. Since these libraries can be
* relatively large in size to handle various Unicode grapheme clusters properly, PixiJS won't use them directly.
*/
_CanvasTextMetrics.graphemeSegmenter = (() => {
if (typeof Intl?.Segmenter === "function") {
const segmenter = new Intl.Segmenter();
return (s) => [...segmenter.segment(s)].map((x) => x.segment);
}
return (s) => [...s];
})();
/**
* New rendering behavior for letter-spacing which uses Chrome's new native API. This will
* lead to more accurate letter-spacing results because it does not try to manually draw
* each character. However, this Chrome API is experimental and may not serve all cases yet.
* @see TextMetrics.experimentalLetterSpacingSupported
*/
_CanvasTextMetrics.experimentalLetterSpacing = false;
/** Cache of {@see TextMetrics.FontMetrics} objects. */
_CanvasTextMetrics._fonts = {};
/** Cache of new line chars. */
_CanvasTextMetrics._newlines = [
10,
// line feed
13
// carriage return
];
/** Cache of breaking spaces. */
_CanvasTextMetrics._breakingSpaces = [
9,
// character tabulation
32,
// space
8192,
// en quad
8193,
// em quad
8194,
// en space
8195,
// em space
8196,
// three-per-em space
8197,
// four-per-em space
8198,
// six-per-em space
8200,
// punctuation space
8201,
// thin space
8202,
// hair space
8287,
// medium mathematical space
12288
// ideographic space
];
_CanvasTextMetrics._measurementCache = {};
let CanvasTextMetrics = _CanvasTextMetrics;
export { CanvasTextMetrics };
//# sourceMappingURL=CanvasTextMetrics.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
import { ExtensionType } from '../../../extensions/Extensions';
import { BatchableSprite } from '../../sprite/BatchableSprite';
import type { InstructionSet } from '../../../rendering/renderers/shared/instructions/InstructionSet';
import type { RenderPipe } from '../../../rendering/renderers/shared/instructions/RenderPipe';
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
import type { Renderer } from '../../../rendering/renderers/types';
import type { Text } from '../Text';
export declare class CanvasTextPipe implements RenderPipe<Text> {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGLPipes, ExtensionType.WebGPUPipes, ExtensionType.CanvasPipes];
readonly name: "text";
};
private _renderer;
private _gpuText;
private readonly _destroyRenderableBound;
constructor(renderer: Renderer);
resolutionChange(): void;
validateRenderable(text: Text): boolean;
addRenderable(text: Text, instructionSet: InstructionSet): void;
updateRenderable(text: Text): void;
destroyRenderable(text: Text): void;
private _destroyRenderableById;
private _updateText;
private _updateGpuText;
private _getGpuText;
initGpuText(text: Text): {
texture: Texture<import("../../..").TextureSource<any>>;
currentKey: string;
batchableSprite: BatchableSprite;
};
destroy(): void;
}

View File

@@ -0,0 +1,132 @@
'use strict';
var Extensions = require('../../../extensions/Extensions.js');
var updateQuadBounds = require('../../../utils/data/updateQuadBounds.js');
var PoolGroup = require('../../../utils/pool/PoolGroup.js');
var BatchableSprite = require('../../sprite/BatchableSprite.js');
"use strict";
class CanvasTextPipe {
constructor(renderer) {
this._gpuText = /* @__PURE__ */ Object.create(null);
this._destroyRenderableBound = this.destroyRenderable.bind(this);
this._renderer = renderer;
this._renderer.runners.resolutionChange.add(this);
}
resolutionChange() {
for (const i in this._gpuText) {
const gpuText = this._gpuText[i];
if (!gpuText)
continue;
const text = gpuText.batchableSprite.renderable;
if (text._autoResolution) {
text._resolution = this._renderer.resolution;
text.onViewUpdate();
}
}
}
validateRenderable(text) {
const gpuText = this._getGpuText(text);
const newKey = text._getKey();
if (gpuText.currentKey !== newKey) {
const { width, height } = this._renderer.canvasText.getTextureSize(
text.text,
text.resolution,
text._style
);
if (
// is only being used by this text:
this._renderer.canvasText.getReferenceCount(gpuText.currentKey) === 1 && width === gpuText.texture._source.width && height === gpuText.texture._source.height
) {
return false;
}
return true;
}
return false;
}
addRenderable(text, instructionSet) {
const gpuText = this._getGpuText(text);
const batchableSprite = gpuText.batchableSprite;
if (text._didTextUpdate) {
this._updateText(text);
}
this._renderer.renderPipes.batch.addToBatch(batchableSprite, instructionSet);
}
updateRenderable(text) {
const gpuText = this._getGpuText(text);
const batchableSprite = gpuText.batchableSprite;
if (text._didTextUpdate) {
this._updateText(text);
}
batchableSprite._batcher.updateElement(batchableSprite);
}
destroyRenderable(text) {
text.off("destroyed", this._destroyRenderableBound);
this._destroyRenderableById(text.uid);
}
_destroyRenderableById(textUid) {
const gpuText = this._gpuText[textUid];
this._renderer.canvasText.decreaseReferenceCount(gpuText.currentKey);
PoolGroup.BigPool.return(gpuText.batchableSprite);
this._gpuText[textUid] = null;
}
_updateText(text) {
const newKey = text._getKey();
const gpuText = this._getGpuText(text);
const batchableSprite = gpuText.batchableSprite;
if (gpuText.currentKey !== newKey) {
this._updateGpuText(text);
}
text._didTextUpdate = false;
const padding = text._style.padding;
updateQuadBounds.updateQuadBounds(batchableSprite.bounds, text._anchor, batchableSprite.texture, padding);
}
_updateGpuText(text) {
const gpuText = this._getGpuText(text);
const batchableSprite = gpuText.batchableSprite;
if (gpuText.texture) {
this._renderer.canvasText.decreaseReferenceCount(gpuText.currentKey);
}
gpuText.texture = batchableSprite.texture = this._renderer.canvasText.getManagedTexture(text);
gpuText.currentKey = text._getKey();
batchableSprite.texture = gpuText.texture;
}
_getGpuText(text) {
return this._gpuText[text.uid] || this.initGpuText(text);
}
initGpuText(text) {
const gpuTextData = {
texture: null,
currentKey: "--",
batchableSprite: PoolGroup.BigPool.get(BatchableSprite.BatchableSprite)
};
gpuTextData.batchableSprite.renderable = text;
gpuTextData.batchableSprite.transform = text.groupTransform;
gpuTextData.batchableSprite.bounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 };
gpuTextData.batchableSprite.roundPixels = this._renderer._roundPixels | text._roundPixels;
this._gpuText[text.uid] = gpuTextData;
text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
this._updateText(text);
text.on("destroyed", this._destroyRenderableBound);
return gpuTextData;
}
destroy() {
for (const i in this._gpuText) {
this._destroyRenderableById(i);
}
this._gpuText = null;
this._renderer = null;
}
}
/** @ignore */
CanvasTextPipe.extension = {
type: [
Extensions.ExtensionType.WebGLPipes,
Extensions.ExtensionType.WebGPUPipes,
Extensions.ExtensionType.CanvasPipes
],
name: "text"
};
exports.CanvasTextPipe = CanvasTextPipe;
//# sourceMappingURL=CanvasTextPipe.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,130 @@
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { updateQuadBounds } from '../../../utils/data/updateQuadBounds.mjs';
import { BigPool } from '../../../utils/pool/PoolGroup.mjs';
import { BatchableSprite } from '../../sprite/BatchableSprite.mjs';
"use strict";
class CanvasTextPipe {
constructor(renderer) {
this._gpuText = /* @__PURE__ */ Object.create(null);
this._destroyRenderableBound = this.destroyRenderable.bind(this);
this._renderer = renderer;
this._renderer.runners.resolutionChange.add(this);
}
resolutionChange() {
for (const i in this._gpuText) {
const gpuText = this._gpuText[i];
if (!gpuText)
continue;
const text = gpuText.batchableSprite.renderable;
if (text._autoResolution) {
text._resolution = this._renderer.resolution;
text.onViewUpdate();
}
}
}
validateRenderable(text) {
const gpuText = this._getGpuText(text);
const newKey = text._getKey();
if (gpuText.currentKey !== newKey) {
const { width, height } = this._renderer.canvasText.getTextureSize(
text.text,
text.resolution,
text._style
);
if (
// is only being used by this text:
this._renderer.canvasText.getReferenceCount(gpuText.currentKey) === 1 && width === gpuText.texture._source.width && height === gpuText.texture._source.height
) {
return false;
}
return true;
}
return false;
}
addRenderable(text, instructionSet) {
const gpuText = this._getGpuText(text);
const batchableSprite = gpuText.batchableSprite;
if (text._didTextUpdate) {
this._updateText(text);
}
this._renderer.renderPipes.batch.addToBatch(batchableSprite, instructionSet);
}
updateRenderable(text) {
const gpuText = this._getGpuText(text);
const batchableSprite = gpuText.batchableSprite;
if (text._didTextUpdate) {
this._updateText(text);
}
batchableSprite._batcher.updateElement(batchableSprite);
}
destroyRenderable(text) {
text.off("destroyed", this._destroyRenderableBound);
this._destroyRenderableById(text.uid);
}
_destroyRenderableById(textUid) {
const gpuText = this._gpuText[textUid];
this._renderer.canvasText.decreaseReferenceCount(gpuText.currentKey);
BigPool.return(gpuText.batchableSprite);
this._gpuText[textUid] = null;
}
_updateText(text) {
const newKey = text._getKey();
const gpuText = this._getGpuText(text);
const batchableSprite = gpuText.batchableSprite;
if (gpuText.currentKey !== newKey) {
this._updateGpuText(text);
}
text._didTextUpdate = false;
const padding = text._style.padding;
updateQuadBounds(batchableSprite.bounds, text._anchor, batchableSprite.texture, padding);
}
_updateGpuText(text) {
const gpuText = this._getGpuText(text);
const batchableSprite = gpuText.batchableSprite;
if (gpuText.texture) {
this._renderer.canvasText.decreaseReferenceCount(gpuText.currentKey);
}
gpuText.texture = batchableSprite.texture = this._renderer.canvasText.getManagedTexture(text);
gpuText.currentKey = text._getKey();
batchableSprite.texture = gpuText.texture;
}
_getGpuText(text) {
return this._gpuText[text.uid] || this.initGpuText(text);
}
initGpuText(text) {
const gpuTextData = {
texture: null,
currentKey: "--",
batchableSprite: BigPool.get(BatchableSprite)
};
gpuTextData.batchableSprite.renderable = text;
gpuTextData.batchableSprite.transform = text.groupTransform;
gpuTextData.batchableSprite.bounds = { minX: 0, maxX: 1, minY: 0, maxY: 0 };
gpuTextData.batchableSprite.roundPixels = this._renderer._roundPixels | text._roundPixels;
this._gpuText[text.uid] = gpuTextData;
text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
this._updateText(text);
text.on("destroyed", this._destroyRenderableBound);
return gpuTextData;
}
destroy() {
for (const i in this._gpuText) {
this._destroyRenderableById(i);
}
this._gpuText = null;
this._renderer = null;
}
}
/** @ignore */
CanvasTextPipe.extension = {
type: [
ExtensionType.WebGLPipes,
ExtensionType.WebGPUPipes,
ExtensionType.CanvasPipes
],
name: "text"
};
export { CanvasTextPipe };
//# sourceMappingURL=CanvasTextPipe.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,80 @@
import { ExtensionType } from '../../../extensions/Extensions';
import { TextStyle } from '../TextStyle';
import type { ICanvas } from '../../../environment/canvas/ICanvas';
import type { ICanvasRenderingContext2D } from '../../../environment/canvas/ICanvasRenderingContext2D';
import type { System } from '../../../rendering/renderers/shared/system/System';
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
import type { Renderer } from '../../../rendering/renderers/types';
import type { TextOptions } from '../AbstractText';
import type { Text } from '../Text';
interface CanvasAndContext {
canvas: ICanvas;
context: ICanvasRenderingContext2D;
}
/**
* System plugin to the renderer to manage canvas text.
* @memberof rendering
*/
export declare class CanvasTextSystem implements System {
/** @ignore */
static extension: {
readonly type: readonly [ExtensionType.WebGLSystem, ExtensionType.WebGPUSystem, ExtensionType.CanvasSystem];
readonly name: "canvasText";
};
private _activeTextures;
private readonly _renderer;
constructor(_renderer: Renderer);
getTextureSize(text: string, resolution: number, style: TextStyle): {
width: number;
height: number;
};
/**
* This is a function that will create a texture from a text string, style and resolution.
* Useful if you want to make a texture of your text and use if for various other pixi things!
* @param options - The options of the text that will be used to generate the texture.
* @param options.text - the text to render
* @param options.style - the style of the text
* @param options.resolution - the resolution of the texture
* @returns the newly created texture
*/
/** @deprecated since 8.0.0 */
getTexture(text: string, resolution: number, style: TextStyle, textKey: string): Texture;
getTexture(options: TextOptions): Texture;
createTextureAndCanvas(options: {
text: string;
style: TextStyle;
resolution?: number;
}): {
texture: Texture<import("../../..").TextureSource<any>>;
canvasAndContext: import("../../../rendering/renderers/shared/texture/CanvasPool").CanvasAndContext;
};
getManagedTexture(text: Text): Texture<import("../../..").TextureSource<any>>;
private _increaseReferenceCount;
decreaseReferenceCount(textKey: string): void;
getReferenceCount(textKey: string): number;
/**
* Renders text to its canvas, and updates its texture.
*
* By default this is used internally to ensure the texture is correct before rendering,
* but it can be used called externally, for example from this class to 'pre-generate' the texture from a piece of text,
* and then shared across multiple Sprites.
* @param text
* @param style
* @param resolution
* @param canvasAndContext
*/
renderTextToCanvas(text: string, style: TextStyle, resolution: number, canvasAndContext: CanvasAndContext): void;
/**
* Render the text with letter-spacing.
* @param text - The text to draw
* @param style
* @param canvasAndContext
* @param x - Horizontal position to draw the text
* @param y - Vertical position to draw the text
* @param isStroke - Is this drawing for the outside stroke of the
* text? If not, it's for the inside fill
*/
private _drawLetterSpacing;
destroy(): void;
}
export {};

View File

@@ -0,0 +1,264 @@
'use strict';
var Color = require('../../../color/Color.js');
var Extensions = require('../../../extensions/Extensions.js');
var pow2 = require('../../../maths/misc/pow2.js');
var CanvasPool = require('../../../rendering/renderers/shared/texture/CanvasPool.js');
var TexturePool = require('../../../rendering/renderers/shared/texture/TexturePool.js');
var getCanvasBoundingBox = require('../../../utils/canvas/getCanvasBoundingBox.js');
var deprecation = require('../../../utils/logging/deprecation.js');
var TextStyle = require('../TextStyle.js');
var getPo2TextureFromSource = require('../utils/getPo2TextureFromSource.js');
var CanvasTextMetrics = require('./CanvasTextMetrics.js');
var fontStringFromTextStyle = require('./utils/fontStringFromTextStyle.js');
var getCanvasFillStyle = require('./utils/getCanvasFillStyle.js');
"use strict";
class CanvasTextSystem {
constructor(_renderer) {
this._activeTextures = {};
this._renderer = _renderer;
}
getTextureSize(text, resolution, style) {
const measured = CanvasTextMetrics.CanvasTextMetrics.measureText(text || " ", style);
let width = Math.ceil(Math.ceil(Math.max(1, measured.width) + style.padding * 2) * resolution);
let height = Math.ceil(Math.ceil(Math.max(1, measured.height) + style.padding * 2) * resolution);
width = Math.ceil(width - 1e-6);
height = Math.ceil(height - 1e-6);
width = pow2.nextPow2(width);
height = pow2.nextPow2(height);
return { width, height };
}
getTexture(options, resolution, style, _textKey) {
if (typeof options === "string") {
deprecation.deprecation("8.0.0", "CanvasTextSystem.getTexture: Use object TextOptions instead of separate arguments");
options = {
text: options,
style,
resolution
};
}
if (!(options.style instanceof TextStyle.TextStyle)) {
options.style = new TextStyle.TextStyle(options.style);
}
const { texture, canvasAndContext } = this.createTextureAndCanvas(
options
);
this._renderer.texture.initSource(texture._source);
CanvasPool.CanvasPool.returnCanvasAndContext(canvasAndContext);
return texture;
}
createTextureAndCanvas(options) {
const { text, style } = options;
const resolution = options.resolution ?? this._renderer.resolution;
const measured = CanvasTextMetrics.CanvasTextMetrics.measureText(text || " ", style);
const width = Math.ceil(Math.ceil(Math.max(1, measured.width) + style.padding * 2) * resolution);
const height = Math.ceil(Math.ceil(Math.max(1, measured.height) + style.padding * 2) * resolution);
const canvasAndContext = CanvasPool.CanvasPool.getOptimalCanvasAndContext(width, height);
const { canvas } = canvasAndContext;
this.renderTextToCanvas(text, style, resolution, canvasAndContext);
const texture = getPo2TextureFromSource.getPo2TextureFromSource(canvas, width, height, resolution);
if (style.trim) {
const trimmed = getCanvasBoundingBox.getCanvasBoundingBox(canvas, resolution);
texture.frame.copyFrom(trimmed);
texture.updateUvs();
}
return { texture, canvasAndContext };
}
getManagedTexture(text) {
text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
const textKey = text._getKey();
if (this._activeTextures[textKey]) {
this._increaseReferenceCount(textKey);
return this._activeTextures[textKey].texture;
}
const { texture, canvasAndContext } = this.createTextureAndCanvas(text);
this._activeTextures[textKey] = {
canvasAndContext,
texture,
usageCount: 1
};
return texture;
}
_increaseReferenceCount(textKey) {
this._activeTextures[textKey].usageCount++;
}
decreaseReferenceCount(textKey) {
const activeTexture = this._activeTextures[textKey];
activeTexture.usageCount--;
if (activeTexture.usageCount === 0) {
CanvasPool.CanvasPool.returnCanvasAndContext(activeTexture.canvasAndContext);
TexturePool.TexturePool.returnTexture(activeTexture.texture);
const source = activeTexture.texture.source;
source.resource = null;
source.uploadMethodId = "unknown";
source.alphaMode = "no-premultiply-alpha";
this._activeTextures[textKey] = null;
}
}
getReferenceCount(textKey) {
return this._activeTextures[textKey].usageCount;
}
/**
* Renders text to its canvas, and updates its texture.
*
* By default this is used internally to ensure the texture is correct before rendering,
* but it can be used called externally, for example from this class to 'pre-generate' the texture from a piece of text,
* and then shared across multiple Sprites.
* @param text
* @param style
* @param resolution
* @param canvasAndContext
*/
renderTextToCanvas(text, style, resolution, canvasAndContext) {
const { canvas, context } = canvasAndContext;
const font = fontStringFromTextStyle.fontStringFromTextStyle(style);
const measured = CanvasTextMetrics.CanvasTextMetrics.measureText(text || " ", style);
const lines = measured.lines;
const lineHeight = measured.lineHeight;
const lineWidths = measured.lineWidths;
const maxLineWidth = measured.maxLineWidth;
const fontProperties = measured.fontProperties;
const height = canvas.height;
context.resetTransform();
context.scale(resolution, resolution);
const padding = style.padding * 2;
context.clearRect(0, 0, measured.width + 4 + padding, measured.height + 4 + padding);
if (style._stroke?.width) {
const strokeStyle = style._stroke;
context.lineWidth = strokeStyle.width;
context.miterLimit = strokeStyle.miterLimit;
context.lineJoin = strokeStyle.join;
context.lineCap = strokeStyle.cap;
}
context.font = font;
let linePositionX;
let linePositionY;
const passesCount = style.dropShadow ? 2 : 1;
for (let i = 0; i < passesCount; ++i) {
const isShadowPass = style.dropShadow && i === 0;
const dsOffsetText = isShadowPass ? Math.ceil(Math.max(1, height) + style.padding * 2) : 0;
const dsOffsetShadow = dsOffsetText * resolution;
if (isShadowPass) {
context.fillStyle = "black";
context.strokeStyle = "black";
const shadowOptions = style.dropShadow;
const dropShadowColor = shadowOptions.color;
const dropShadowAlpha = shadowOptions.alpha;
context.shadowColor = Color.Color.shared.setValue(dropShadowColor).setAlpha(dropShadowAlpha).toRgbaString();
const dropShadowBlur = shadowOptions.blur * resolution;
const dropShadowDistance = shadowOptions.distance * resolution;
context.shadowBlur = dropShadowBlur;
context.shadowOffsetX = Math.cos(shadowOptions.angle) * dropShadowDistance;
context.shadowOffsetY = Math.sin(shadowOptions.angle) * dropShadowDistance + dsOffsetShadow;
} else {
context.globalAlpha = style._fill?.alpha ?? 1;
context.fillStyle = style._fill ? getCanvasFillStyle.getCanvasFillStyle(style._fill, context) : null;
if (style._stroke?.width) {
context.strokeStyle = getCanvasFillStyle.getCanvasFillStyle(style._stroke, context);
}
context.shadowColor = "black";
}
let linePositionYShift = (lineHeight - fontProperties.fontSize) / 2;
if (lineHeight - fontProperties.fontSize < 0) {
linePositionYShift = 0;
}
const strokeWidth = style._stroke?.width ?? 0;
for (let i2 = 0; i2 < lines.length; i2++) {
linePositionX = strokeWidth / 2;
linePositionY = strokeWidth / 2 + i2 * lineHeight + fontProperties.ascent + linePositionYShift;
if (style.align === "right") {
linePositionX += maxLineWidth - lineWidths[i2];
} else if (style.align === "center") {
linePositionX += (maxLineWidth - lineWidths[i2]) / 2;
}
if (style._stroke?.width) {
this._drawLetterSpacing(
lines[i2],
style,
canvasAndContext,
linePositionX + style.padding,
linePositionY + style.padding - dsOffsetText,
true
);
}
if (style._fill !== void 0) {
this._drawLetterSpacing(
lines[i2],
style,
canvasAndContext,
linePositionX + style.padding,
linePositionY + style.padding - dsOffsetText
);
}
}
}
}
/**
* Render the text with letter-spacing.
* @param text - The text to draw
* @param style
* @param canvasAndContext
* @param x - Horizontal position to draw the text
* @param y - Vertical position to draw the text
* @param isStroke - Is this drawing for the outside stroke of the
* text? If not, it's for the inside fill
*/
_drawLetterSpacing(text, style, canvasAndContext, x, y, isStroke = false) {
const { context } = canvasAndContext;
const letterSpacing = style.letterSpacing;
let useExperimentalLetterSpacing = false;
if (CanvasTextMetrics.CanvasTextMetrics.experimentalLetterSpacingSupported) {
if (CanvasTextMetrics.CanvasTextMetrics.experimentalLetterSpacing) {
context.letterSpacing = `${letterSpacing}px`;
context.textLetterSpacing = `${letterSpacing}px`;
useExperimentalLetterSpacing = true;
} else {
context.letterSpacing = "0px";
context.textLetterSpacing = "0px";
}
}
if (letterSpacing === 0 || useExperimentalLetterSpacing) {
if (isStroke) {
context.strokeText(text, x, y);
} else {
context.fillText(text, x, y);
}
return;
}
let currentPosition = x;
const stringArray = CanvasTextMetrics.CanvasTextMetrics.graphemeSegmenter(text);
let previousWidth = context.measureText(text).width;
let currentWidth = 0;
for (let i = 0; i < stringArray.length; ++i) {
const currentChar = stringArray[i];
if (isStroke) {
context.strokeText(currentChar, currentPosition, y);
} else {
context.fillText(currentChar, currentPosition, y);
}
let textStr = "";
for (let j = i + 1; j < stringArray.length; ++j) {
textStr += stringArray[j];
}
currentWidth = context.measureText(textStr).width;
currentPosition += previousWidth - currentWidth + letterSpacing;
previousWidth = currentWidth;
}
}
destroy() {
this._activeTextures = null;
}
}
/** @ignore */
CanvasTextSystem.extension = {
type: [
Extensions.ExtensionType.WebGLSystem,
Extensions.ExtensionType.WebGPUSystem,
Extensions.ExtensionType.CanvasSystem
],
name: "canvasText"
};
exports.CanvasTextSystem = CanvasTextSystem;
//# sourceMappingURL=CanvasTextSystem.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,262 @@
import { Color } from '../../../color/Color.mjs';
import { ExtensionType } from '../../../extensions/Extensions.mjs';
import { nextPow2 } from '../../../maths/misc/pow2.mjs';
import { CanvasPool } from '../../../rendering/renderers/shared/texture/CanvasPool.mjs';
import { TexturePool } from '../../../rendering/renderers/shared/texture/TexturePool.mjs';
import { getCanvasBoundingBox } from '../../../utils/canvas/getCanvasBoundingBox.mjs';
import { deprecation } from '../../../utils/logging/deprecation.mjs';
import { TextStyle } from '../TextStyle.mjs';
import { getPo2TextureFromSource } from '../utils/getPo2TextureFromSource.mjs';
import { CanvasTextMetrics } from './CanvasTextMetrics.mjs';
import { fontStringFromTextStyle } from './utils/fontStringFromTextStyle.mjs';
import { getCanvasFillStyle } from './utils/getCanvasFillStyle.mjs';
"use strict";
class CanvasTextSystem {
constructor(_renderer) {
this._activeTextures = {};
this._renderer = _renderer;
}
getTextureSize(text, resolution, style) {
const measured = CanvasTextMetrics.measureText(text || " ", style);
let width = Math.ceil(Math.ceil(Math.max(1, measured.width) + style.padding * 2) * resolution);
let height = Math.ceil(Math.ceil(Math.max(1, measured.height) + style.padding * 2) * resolution);
width = Math.ceil(width - 1e-6);
height = Math.ceil(height - 1e-6);
width = nextPow2(width);
height = nextPow2(height);
return { width, height };
}
getTexture(options, resolution, style, _textKey) {
if (typeof options === "string") {
deprecation("8.0.0", "CanvasTextSystem.getTexture: Use object TextOptions instead of separate arguments");
options = {
text: options,
style,
resolution
};
}
if (!(options.style instanceof TextStyle)) {
options.style = new TextStyle(options.style);
}
const { texture, canvasAndContext } = this.createTextureAndCanvas(
options
);
this._renderer.texture.initSource(texture._source);
CanvasPool.returnCanvasAndContext(canvasAndContext);
return texture;
}
createTextureAndCanvas(options) {
const { text, style } = options;
const resolution = options.resolution ?? this._renderer.resolution;
const measured = CanvasTextMetrics.measureText(text || " ", style);
const width = Math.ceil(Math.ceil(Math.max(1, measured.width) + style.padding * 2) * resolution);
const height = Math.ceil(Math.ceil(Math.max(1, measured.height) + style.padding * 2) * resolution);
const canvasAndContext = CanvasPool.getOptimalCanvasAndContext(width, height);
const { canvas } = canvasAndContext;
this.renderTextToCanvas(text, style, resolution, canvasAndContext);
const texture = getPo2TextureFromSource(canvas, width, height, resolution);
if (style.trim) {
const trimmed = getCanvasBoundingBox(canvas, resolution);
texture.frame.copyFrom(trimmed);
texture.updateUvs();
}
return { texture, canvasAndContext };
}
getManagedTexture(text) {
text._resolution = text._autoResolution ? this._renderer.resolution : text.resolution;
const textKey = text._getKey();
if (this._activeTextures[textKey]) {
this._increaseReferenceCount(textKey);
return this._activeTextures[textKey].texture;
}
const { texture, canvasAndContext } = this.createTextureAndCanvas(text);
this._activeTextures[textKey] = {
canvasAndContext,
texture,
usageCount: 1
};
return texture;
}
_increaseReferenceCount(textKey) {
this._activeTextures[textKey].usageCount++;
}
decreaseReferenceCount(textKey) {
const activeTexture = this._activeTextures[textKey];
activeTexture.usageCount--;
if (activeTexture.usageCount === 0) {
CanvasPool.returnCanvasAndContext(activeTexture.canvasAndContext);
TexturePool.returnTexture(activeTexture.texture);
const source = activeTexture.texture.source;
source.resource = null;
source.uploadMethodId = "unknown";
source.alphaMode = "no-premultiply-alpha";
this._activeTextures[textKey] = null;
}
}
getReferenceCount(textKey) {
return this._activeTextures[textKey].usageCount;
}
/**
* Renders text to its canvas, and updates its texture.
*
* By default this is used internally to ensure the texture is correct before rendering,
* but it can be used called externally, for example from this class to 'pre-generate' the texture from a piece of text,
* and then shared across multiple Sprites.
* @param text
* @param style
* @param resolution
* @param canvasAndContext
*/
renderTextToCanvas(text, style, resolution, canvasAndContext) {
const { canvas, context } = canvasAndContext;
const font = fontStringFromTextStyle(style);
const measured = CanvasTextMetrics.measureText(text || " ", style);
const lines = measured.lines;
const lineHeight = measured.lineHeight;
const lineWidths = measured.lineWidths;
const maxLineWidth = measured.maxLineWidth;
const fontProperties = measured.fontProperties;
const height = canvas.height;
context.resetTransform();
context.scale(resolution, resolution);
const padding = style.padding * 2;
context.clearRect(0, 0, measured.width + 4 + padding, measured.height + 4 + padding);
if (style._stroke?.width) {
const strokeStyle = style._stroke;
context.lineWidth = strokeStyle.width;
context.miterLimit = strokeStyle.miterLimit;
context.lineJoin = strokeStyle.join;
context.lineCap = strokeStyle.cap;
}
context.font = font;
let linePositionX;
let linePositionY;
const passesCount = style.dropShadow ? 2 : 1;
for (let i = 0; i < passesCount; ++i) {
const isShadowPass = style.dropShadow && i === 0;
const dsOffsetText = isShadowPass ? Math.ceil(Math.max(1, height) + style.padding * 2) : 0;
const dsOffsetShadow = dsOffsetText * resolution;
if (isShadowPass) {
context.fillStyle = "black";
context.strokeStyle = "black";
const shadowOptions = style.dropShadow;
const dropShadowColor = shadowOptions.color;
const dropShadowAlpha = shadowOptions.alpha;
context.shadowColor = Color.shared.setValue(dropShadowColor).setAlpha(dropShadowAlpha).toRgbaString();
const dropShadowBlur = shadowOptions.blur * resolution;
const dropShadowDistance = shadowOptions.distance * resolution;
context.shadowBlur = dropShadowBlur;
context.shadowOffsetX = Math.cos(shadowOptions.angle) * dropShadowDistance;
context.shadowOffsetY = Math.sin(shadowOptions.angle) * dropShadowDistance + dsOffsetShadow;
} else {
context.globalAlpha = style._fill?.alpha ?? 1;
context.fillStyle = style._fill ? getCanvasFillStyle(style._fill, context) : null;
if (style._stroke?.width) {
context.strokeStyle = getCanvasFillStyle(style._stroke, context);
}
context.shadowColor = "black";
}
let linePositionYShift = (lineHeight - fontProperties.fontSize) / 2;
if (lineHeight - fontProperties.fontSize < 0) {
linePositionYShift = 0;
}
const strokeWidth = style._stroke?.width ?? 0;
for (let i2 = 0; i2 < lines.length; i2++) {
linePositionX = strokeWidth / 2;
linePositionY = strokeWidth / 2 + i2 * lineHeight + fontProperties.ascent + linePositionYShift;
if (style.align === "right") {
linePositionX += maxLineWidth - lineWidths[i2];
} else if (style.align === "center") {
linePositionX += (maxLineWidth - lineWidths[i2]) / 2;
}
if (style._stroke?.width) {
this._drawLetterSpacing(
lines[i2],
style,
canvasAndContext,
linePositionX + style.padding,
linePositionY + style.padding - dsOffsetText,
true
);
}
if (style._fill !== void 0) {
this._drawLetterSpacing(
lines[i2],
style,
canvasAndContext,
linePositionX + style.padding,
linePositionY + style.padding - dsOffsetText
);
}
}
}
}
/**
* Render the text with letter-spacing.
* @param text - The text to draw
* @param style
* @param canvasAndContext
* @param x - Horizontal position to draw the text
* @param y - Vertical position to draw the text
* @param isStroke - Is this drawing for the outside stroke of the
* text? If not, it's for the inside fill
*/
_drawLetterSpacing(text, style, canvasAndContext, x, y, isStroke = false) {
const { context } = canvasAndContext;
const letterSpacing = style.letterSpacing;
let useExperimentalLetterSpacing = false;
if (CanvasTextMetrics.experimentalLetterSpacingSupported) {
if (CanvasTextMetrics.experimentalLetterSpacing) {
context.letterSpacing = `${letterSpacing}px`;
context.textLetterSpacing = `${letterSpacing}px`;
useExperimentalLetterSpacing = true;
} else {
context.letterSpacing = "0px";
context.textLetterSpacing = "0px";
}
}
if (letterSpacing === 0 || useExperimentalLetterSpacing) {
if (isStroke) {
context.strokeText(text, x, y);
} else {
context.fillText(text, x, y);
}
return;
}
let currentPosition = x;
const stringArray = CanvasTextMetrics.graphemeSegmenter(text);
let previousWidth = context.measureText(text).width;
let currentWidth = 0;
for (let i = 0; i < stringArray.length; ++i) {
const currentChar = stringArray[i];
if (isStroke) {
context.strokeText(currentChar, currentPosition, y);
} else {
context.fillText(currentChar, currentPosition, y);
}
let textStr = "";
for (let j = i + 1; j < stringArray.length; ++j) {
textStr += stringArray[j];
}
currentWidth = context.measureText(textStr).width;
currentPosition += previousWidth - currentWidth + letterSpacing;
previousWidth = currentWidth;
}
}
destroy() {
this._activeTextures = null;
}
}
/** @ignore */
CanvasTextSystem.extension = {
type: [
ExtensionType.WebGLSystem,
ExtensionType.WebGPUSystem,
ExtensionType.CanvasSystem
],
name: "canvasText"
};
export { CanvasTextSystem };
//# sourceMappingURL=CanvasTextSystem.mjs.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,7 @@
import type { TextStyle } from '../../TextStyle';
/**
* Generates a font style string to use for `TextMetrics.measureFont()`.
* @param style
* @returns Font style string, for passing to `TextMetrics.measureFont()`
*/
export declare function fontStringFromTextStyle(style: TextStyle): string;

View File

@@ -0,0 +1,29 @@
'use strict';
"use strict";
const genericFontFamilies = [
"serif",
"sans-serif",
"monospace",
"cursive",
"fantasy",
"system-ui"
];
function fontStringFromTextStyle(style) {
const fontSizeString = typeof style.fontSize === "number" ? `${style.fontSize}px` : style.fontSize;
let fontFamilies = style.fontFamily;
if (!Array.isArray(style.fontFamily)) {
fontFamilies = style.fontFamily.split(",");
}
for (let i = fontFamilies.length - 1; i >= 0; i--) {
let fontFamily = fontFamilies[i].trim();
if (!/([\"\'])[^\'\"]+\1/.test(fontFamily) && !genericFontFamilies.includes(fontFamily)) {
fontFamily = `"${fontFamily}"`;
}
fontFamilies[i] = fontFamily;
}
return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(",")}`;
}
exports.fontStringFromTextStyle = fontStringFromTextStyle;
//# sourceMappingURL=fontStringFromTextStyle.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"fontStringFromTextStyle.js","sources":["../../../../../src/scene/text/canvas/utils/fontStringFromTextStyle.ts"],"sourcesContent":["import type { TextStyle } from '../../TextStyle';\n\nconst genericFontFamilies = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n];\n\n/**\n * Generates a font style string to use for `TextMetrics.measureFont()`.\n * @param style\n * @returns Font style string, for passing to `TextMetrics.measureFont()`\n */\nexport function fontStringFromTextStyle(style: TextStyle): string\n{\n // build canvas api font setting from individual components. Convert a numeric style.fontSize to px\n const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize;\n\n // Clean-up fontFamily property by quoting each font name\n // this will support font names with spaces\n let fontFamilies: string | string[] = style.fontFamily;\n\n if (!Array.isArray(style.fontFamily))\n {\n fontFamilies = style.fontFamily.split(',');\n }\n\n for (let i = fontFamilies.length - 1; i >= 0; i--)\n {\n // Trim any extra white-space\n let fontFamily = fontFamilies[i].trim();\n\n // Check if font already contains strings\n if (!(/([\\\"\\'])[^\\'\\\"]+\\1/).test(fontFamily) && !genericFontFamilies.includes(fontFamily))\n {\n fontFamily = `\"${fontFamily}\"`;\n }\n (fontFamilies as string[])[i] = fontFamily;\n }\n\n // eslint-disable-next-line max-len\n return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${(fontFamilies as string[]).join(',')}`;\n}\n"],"names":[],"mappings":";;;AAEA,MAAM,mBAAsB,GAAA;AAAA,EACxB,OAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AACJ,CAAA,CAAA;AAOO,SAAS,wBAAwB,KACxC,EAAA;AAEI,EAAM,MAAA,cAAA,GAAkB,OAAO,KAAM,CAAA,QAAA,KAAa,WAAY,CAAG,EAAA,KAAA,CAAM,QAAQ,CAAA,EAAA,CAAA,GAAO,KAAM,CAAA,QAAA,CAAA;AAI5F,EAAA,IAAI,eAAkC,KAAM,CAAA,UAAA,CAAA;AAE5C,EAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,KAAA,CAAM,UAAU,CACnC,EAAA;AACI,IAAe,YAAA,GAAA,KAAA,CAAM,UAAW,CAAA,KAAA,CAAM,GAAG,CAAA,CAAA;AAAA,GAC7C;AAEA,EAAA,KAAA,IAAS,IAAI,YAAa,CAAA,MAAA,GAAS,CAAG,EAAA,CAAA,IAAK,GAAG,CAC9C,EAAA,EAAA;AAEI,IAAA,IAAI,UAAa,GAAA,YAAA,CAAa,CAAC,CAAA,CAAE,IAAK,EAAA,CAAA;AAGtC,IAAI,IAAA,CAAE,qBAAsB,IAAK,CAAA,UAAU,KAAK,CAAC,mBAAA,CAAoB,QAAS,CAAA,UAAU,CACxF,EAAA;AACI,MAAA,UAAA,GAAa,IAAI,UAAU,CAAA,CAAA,CAAA,CAAA;AAAA,KAC/B;AACA,IAAC,YAAA,CAA0B,CAAC,CAAI,GAAA,UAAA,CAAA;AAAA,GACpC;AAGA,EAAA,OAAO,CAAG,EAAA,KAAA,CAAM,SAAS,CAAA,CAAA,EAAI,MAAM,WAAW,CAAA,CAAA,EAAI,KAAM,CAAA,UAAU,IAAI,cAAc,CAAA,CAAA,EAAK,YAA0B,CAAA,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,CAAA;AAChI;;;;"}

View File

@@ -0,0 +1,27 @@
"use strict";
const genericFontFamilies = [
"serif",
"sans-serif",
"monospace",
"cursive",
"fantasy",
"system-ui"
];
function fontStringFromTextStyle(style) {
const fontSizeString = typeof style.fontSize === "number" ? `${style.fontSize}px` : style.fontSize;
let fontFamilies = style.fontFamily;
if (!Array.isArray(style.fontFamily)) {
fontFamilies = style.fontFamily.split(",");
}
for (let i = fontFamilies.length - 1; i >= 0; i--) {
let fontFamily = fontFamilies[i].trim();
if (!/([\"\'])[^\'\"]+\1/.test(fontFamily) && !genericFontFamilies.includes(fontFamily)) {
fontFamily = `"${fontFamily}"`;
}
fontFamilies[i] = fontFamily;
}
return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${fontFamilies.join(",")}`;
}
export { fontStringFromTextStyle };
//# sourceMappingURL=fontStringFromTextStyle.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"fontStringFromTextStyle.mjs","sources":["../../../../../src/scene/text/canvas/utils/fontStringFromTextStyle.ts"],"sourcesContent":["import type { TextStyle } from '../../TextStyle';\n\nconst genericFontFamilies = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n];\n\n/**\n * Generates a font style string to use for `TextMetrics.measureFont()`.\n * @param style\n * @returns Font style string, for passing to `TextMetrics.measureFont()`\n */\nexport function fontStringFromTextStyle(style: TextStyle): string\n{\n // build canvas api font setting from individual components. Convert a numeric style.fontSize to px\n const fontSizeString = (typeof style.fontSize === 'number') ? `${style.fontSize}px` : style.fontSize;\n\n // Clean-up fontFamily property by quoting each font name\n // this will support font names with spaces\n let fontFamilies: string | string[] = style.fontFamily;\n\n if (!Array.isArray(style.fontFamily))\n {\n fontFamilies = style.fontFamily.split(',');\n }\n\n for (let i = fontFamilies.length - 1; i >= 0; i--)\n {\n // Trim any extra white-space\n let fontFamily = fontFamilies[i].trim();\n\n // Check if font already contains strings\n if (!(/([\\\"\\'])[^\\'\\\"]+\\1/).test(fontFamily) && !genericFontFamilies.includes(fontFamily))\n {\n fontFamily = `\"${fontFamily}\"`;\n }\n (fontFamilies as string[])[i] = fontFamily;\n }\n\n // eslint-disable-next-line max-len\n return `${style.fontStyle} ${style.fontVariant} ${style.fontWeight} ${fontSizeString} ${(fontFamilies as string[]).join(',')}`;\n}\n"],"names":[],"mappings":";AAEA,MAAM,mBAAsB,GAAA;AAAA,EACxB,OAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AACJ,CAAA,CAAA;AAOO,SAAS,wBAAwB,KACxC,EAAA;AAEI,EAAM,MAAA,cAAA,GAAkB,OAAO,KAAM,CAAA,QAAA,KAAa,WAAY,CAAG,EAAA,KAAA,CAAM,QAAQ,CAAA,EAAA,CAAA,GAAO,KAAM,CAAA,QAAA,CAAA;AAI5F,EAAA,IAAI,eAAkC,KAAM,CAAA,UAAA,CAAA;AAE5C,EAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,KAAA,CAAM,UAAU,CACnC,EAAA;AACI,IAAe,YAAA,GAAA,KAAA,CAAM,UAAW,CAAA,KAAA,CAAM,GAAG,CAAA,CAAA;AAAA,GAC7C;AAEA,EAAA,KAAA,IAAS,IAAI,YAAa,CAAA,MAAA,GAAS,CAAG,EAAA,CAAA,IAAK,GAAG,CAC9C,EAAA,EAAA;AAEI,IAAA,IAAI,UAAa,GAAA,YAAA,CAAa,CAAC,CAAA,CAAE,IAAK,EAAA,CAAA;AAGtC,IAAI,IAAA,CAAE,qBAAsB,IAAK,CAAA,UAAU,KAAK,CAAC,mBAAA,CAAoB,QAAS,CAAA,UAAU,CACxF,EAAA;AACI,MAAA,UAAA,GAAa,IAAI,UAAU,CAAA,CAAA,CAAA,CAAA;AAAA,KAC/B;AACA,IAAC,YAAA,CAA0B,CAAC,CAAI,GAAA,UAAA,CAAA;AAAA,GACpC;AAGA,EAAA,OAAO,CAAG,EAAA,KAAA,CAAM,SAAS,CAAA,CAAA,EAAI,MAAM,WAAW,CAAA,CAAA,EAAI,KAAM,CAAA,UAAU,IAAI,cAAc,CAAA,CAAA,EAAK,YAA0B,CAAA,IAAA,CAAK,GAAG,CAAC,CAAA,CAAA,CAAA;AAChI;;;;"}

View File

@@ -0,0 +1,3 @@
import type { ICanvasRenderingContext2D } from '../../../../environment/canvas/ICanvasRenderingContext2D';
import type { ConvertedFillStyle } from '../../../graphics/shared/FillTypes';
export declare function getCanvasFillStyle(fillStyle: ConvertedFillStyle, context: ICanvasRenderingContext2D): string | CanvasGradient | CanvasPattern;

View File

@@ -0,0 +1,50 @@
'use strict';
var Color = require('../../../../color/Color.js');
var Matrix = require('../../../../maths/matrix/Matrix.js');
var Texture = require('../../../../rendering/renderers/shared/texture/Texture.js');
var warn = require('../../../../utils/logging/warn.js');
var FillGradient = require('../../../graphics/shared/fill/FillGradient.js');
var FillPattern = require('../../../graphics/shared/fill/FillPattern.js');
"use strict";
function getCanvasFillStyle(fillStyle, context) {
if (fillStyle.texture === Texture.Texture.WHITE && !fillStyle.fill) {
return Color.Color.shared.setValue(fillStyle.color).setAlpha(fillStyle.alpha ?? 1).toHexa();
} else if (!fillStyle.fill) {
const pattern = context.createPattern(fillStyle.texture.source.resource, "repeat");
const tempMatrix = fillStyle.matrix.copyTo(Matrix.Matrix.shared);
tempMatrix.scale(fillStyle.texture.frame.width, fillStyle.texture.frame.height);
pattern.setTransform(tempMatrix);
return pattern;
} else if (fillStyle.fill instanceof FillPattern.FillPattern) {
const fillPattern = fillStyle.fill;
const pattern = context.createPattern(fillPattern.texture.source.resource, "repeat");
const tempMatrix = fillPattern.transform.copyTo(Matrix.Matrix.shared);
tempMatrix.scale(
fillPattern.texture.frame.width,
fillPattern.texture.frame.height
);
pattern.setTransform(tempMatrix);
return pattern;
} else if (fillStyle.fill instanceof FillGradient.FillGradient) {
const fillGradient = fillStyle.fill;
if (fillGradient.type === "linear") {
const gradient = context.createLinearGradient(
fillGradient.x0,
fillGradient.y0,
fillGradient.x1,
fillGradient.y1
);
fillGradient.gradientStops.forEach((stop) => {
gradient.addColorStop(stop.offset, Color.Color.shared.setValue(stop.color).toHex());
});
return gradient;
}
}
warn.warn("FillStyle not recognised", fillStyle);
return "red";
}
exports.getCanvasFillStyle = getCanvasFillStyle;
//# sourceMappingURL=getCanvasFillStyle.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getCanvasFillStyle.js","sources":["../../../../../src/scene/text/canvas/utils/getCanvasFillStyle.ts"],"sourcesContent":["import { Color } from '../../../../color/Color';\nimport { Matrix } from '../../../../maths/matrix/Matrix';\nimport { Texture } from '../../../../rendering/renderers/shared/texture/Texture';\nimport { warn } from '../../../../utils/logging/warn';\nimport { FillGradient } from '../../../graphics/shared/fill/FillGradient';\nimport { FillPattern } from '../../../graphics/shared/fill/FillPattern';\n\nimport type { ICanvasRenderingContext2D } from '../../../../environment/canvas/ICanvasRenderingContext2D';\nimport type { ConvertedFillStyle } from '../../../graphics/shared/FillTypes';\n\nexport function getCanvasFillStyle(\n fillStyle: ConvertedFillStyle,\n context: ICanvasRenderingContext2D): string | CanvasGradient | CanvasPattern\n{\n if (fillStyle.texture === Texture.WHITE && !fillStyle.fill)\n {\n return Color.shared.setValue(fillStyle.color).setAlpha(fillStyle.alpha ?? 1).toHexa();\n }\n else if (!fillStyle.fill)\n {\n // fancy set up...\n const pattern = context.createPattern(fillStyle.texture.source.resource, 'repeat');\n\n // create an inverted scale matrix..\n const tempMatrix = fillStyle.matrix.copyTo(Matrix.shared);\n\n tempMatrix.scale(fillStyle.texture.frame.width, fillStyle.texture.frame.height);\n\n pattern.setTransform(tempMatrix);\n\n return pattern;\n }\n else if (fillStyle.fill instanceof FillPattern)\n {\n const fillPattern = fillStyle.fill;\n\n const pattern = context.createPattern(fillPattern.texture.source.resource, 'repeat');\n\n const tempMatrix = fillPattern.transform.copyTo(Matrix.shared);\n\n tempMatrix.scale(\n fillPattern.texture.frame.width,\n fillPattern.texture.frame.height\n );\n\n pattern.setTransform(tempMatrix);\n\n return pattern;\n }\n else if (fillStyle.fill instanceof FillGradient)\n {\n const fillGradient = fillStyle.fill;\n\n if (fillGradient.type === 'linear')\n {\n const gradient = context.createLinearGradient(\n fillGradient.x0,\n fillGradient.y0,\n fillGradient.x1,\n fillGradient.y1\n );\n\n fillGradient.gradientStops.forEach((stop) =>\n {\n gradient.addColorStop(stop.offset, Color.shared.setValue(stop.color).toHex());\n });\n\n return gradient;\n }\n }\n\n // #if _DEBUG\n warn('FillStyle not recognised', fillStyle);\n // #endif\n\n return 'red';\n}\n"],"names":["Texture","Color","Matrix","FillPattern","FillGradient","warn"],"mappings":";;;;;;;;;;AAUgB,SAAA,kBAAA,CACZ,WACA,OACJ,EAAA;AACI,EAAA,IAAI,UAAU,OAAY,KAAAA,eAAA,CAAQ,KAAS,IAAA,CAAC,UAAU,IACtD,EAAA;AACI,IAAO,OAAAC,WAAA,CAAM,MAAO,CAAA,QAAA,CAAS,SAAU,CAAA,KAAK,CAAE,CAAA,QAAA,CAAS,SAAU,CAAA,KAAA,IAAS,CAAC,CAAA,CAAE,MAAO,EAAA,CAAA;AAAA,GACxF,MAAA,IACS,CAAC,SAAA,CAAU,IACpB,EAAA;AAEI,IAAA,MAAM,UAAU,OAAQ,CAAA,aAAA,CAAc,UAAU,OAAQ,CAAA,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAGjF,IAAA,MAAM,UAAa,GAAA,SAAA,CAAU,MAAO,CAAA,MAAA,CAAOC,cAAO,MAAM,CAAA,CAAA;AAExD,IAAW,UAAA,CAAA,KAAA,CAAM,UAAU,OAAQ,CAAA,KAAA,CAAM,OAAO,SAAU,CAAA,OAAA,CAAQ,MAAM,MAAM,CAAA,CAAA;AAE9E,IAAA,OAAA,CAAQ,aAAa,UAAU,CAAA,CAAA;AAE/B,IAAO,OAAA,OAAA,CAAA;AAAA,GACX,MAAA,IACS,SAAU,CAAA,IAAA,YAAgBC,uBACnC,EAAA;AACI,IAAA,MAAM,cAAc,SAAU,CAAA,IAAA,CAAA;AAE9B,IAAA,MAAM,UAAU,OAAQ,CAAA,aAAA,CAAc,YAAY,OAAQ,CAAA,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAEnF,IAAA,MAAM,UAAa,GAAA,WAAA,CAAY,SAAU,CAAA,MAAA,CAAOD,cAAO,MAAM,CAAA,CAAA;AAE7D,IAAW,UAAA,CAAA,KAAA;AAAA,MACP,WAAA,CAAY,QAAQ,KAAM,CAAA,KAAA;AAAA,MAC1B,WAAA,CAAY,QAAQ,KAAM,CAAA,MAAA;AAAA,KAC9B,CAAA;AAEA,IAAA,OAAA,CAAQ,aAAa,UAAU,CAAA,CAAA;AAE/B,IAAO,OAAA,OAAA,CAAA;AAAA,GACX,MAAA,IACS,SAAU,CAAA,IAAA,YAAgBE,yBACnC,EAAA;AACI,IAAA,MAAM,eAAe,SAAU,CAAA,IAAA,CAAA;AAE/B,IAAI,IAAA,YAAA,CAAa,SAAS,QAC1B,EAAA;AACI,MAAA,MAAM,WAAW,OAAQ,CAAA,oBAAA;AAAA,QACrB,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,OACjB,CAAA;AAEA,MAAa,YAAA,CAAA,aAAA,CAAc,OAAQ,CAAA,CAAC,IACpC,KAAA;AACI,QAAS,QAAA,CAAA,YAAA,CAAa,IAAK,CAAA,MAAA,EAAQH,WAAM,CAAA,MAAA,CAAO,SAAS,IAAK,CAAA,KAAK,CAAE,CAAA,KAAA,EAAO,CAAA,CAAA;AAAA,OAC/E,CAAA,CAAA;AAED,MAAO,OAAA,QAAA,CAAA;AAAA,KACX;AAAA,GACJ;AAGA,EAAAI,SAAA,CAAK,4BAA4B,SAAS,CAAA,CAAA;AAG1C,EAAO,OAAA,KAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,48 @@
import { Color } from '../../../../color/Color.mjs';
import { Matrix } from '../../../../maths/matrix/Matrix.mjs';
import { Texture } from '../../../../rendering/renderers/shared/texture/Texture.mjs';
import { warn } from '../../../../utils/logging/warn.mjs';
import { FillGradient } from '../../../graphics/shared/fill/FillGradient.mjs';
import { FillPattern } from '../../../graphics/shared/fill/FillPattern.mjs';
"use strict";
function getCanvasFillStyle(fillStyle, context) {
if (fillStyle.texture === Texture.WHITE && !fillStyle.fill) {
return Color.shared.setValue(fillStyle.color).setAlpha(fillStyle.alpha ?? 1).toHexa();
} else if (!fillStyle.fill) {
const pattern = context.createPattern(fillStyle.texture.source.resource, "repeat");
const tempMatrix = fillStyle.matrix.copyTo(Matrix.shared);
tempMatrix.scale(fillStyle.texture.frame.width, fillStyle.texture.frame.height);
pattern.setTransform(tempMatrix);
return pattern;
} else if (fillStyle.fill instanceof FillPattern) {
const fillPattern = fillStyle.fill;
const pattern = context.createPattern(fillPattern.texture.source.resource, "repeat");
const tempMatrix = fillPattern.transform.copyTo(Matrix.shared);
tempMatrix.scale(
fillPattern.texture.frame.width,
fillPattern.texture.frame.height
);
pattern.setTransform(tempMatrix);
return pattern;
} else if (fillStyle.fill instanceof FillGradient) {
const fillGradient = fillStyle.fill;
if (fillGradient.type === "linear") {
const gradient = context.createLinearGradient(
fillGradient.x0,
fillGradient.y0,
fillGradient.x1,
fillGradient.y1
);
fillGradient.gradientStops.forEach((stop) => {
gradient.addColorStop(stop.offset, Color.shared.setValue(stop.color).toHex());
});
return gradient;
}
}
warn("FillStyle not recognised", fillStyle);
return "red";
}
export { getCanvasFillStyle };
//# sourceMappingURL=getCanvasFillStyle.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getCanvasFillStyle.mjs","sources":["../../../../../src/scene/text/canvas/utils/getCanvasFillStyle.ts"],"sourcesContent":["import { Color } from '../../../../color/Color';\nimport { Matrix } from '../../../../maths/matrix/Matrix';\nimport { Texture } from '../../../../rendering/renderers/shared/texture/Texture';\nimport { warn } from '../../../../utils/logging/warn';\nimport { FillGradient } from '../../../graphics/shared/fill/FillGradient';\nimport { FillPattern } from '../../../graphics/shared/fill/FillPattern';\n\nimport type { ICanvasRenderingContext2D } from '../../../../environment/canvas/ICanvasRenderingContext2D';\nimport type { ConvertedFillStyle } from '../../../graphics/shared/FillTypes';\n\nexport function getCanvasFillStyle(\n fillStyle: ConvertedFillStyle,\n context: ICanvasRenderingContext2D): string | CanvasGradient | CanvasPattern\n{\n if (fillStyle.texture === Texture.WHITE && !fillStyle.fill)\n {\n return Color.shared.setValue(fillStyle.color).setAlpha(fillStyle.alpha ?? 1).toHexa();\n }\n else if (!fillStyle.fill)\n {\n // fancy set up...\n const pattern = context.createPattern(fillStyle.texture.source.resource, 'repeat');\n\n // create an inverted scale matrix..\n const tempMatrix = fillStyle.matrix.copyTo(Matrix.shared);\n\n tempMatrix.scale(fillStyle.texture.frame.width, fillStyle.texture.frame.height);\n\n pattern.setTransform(tempMatrix);\n\n return pattern;\n }\n else if (fillStyle.fill instanceof FillPattern)\n {\n const fillPattern = fillStyle.fill;\n\n const pattern = context.createPattern(fillPattern.texture.source.resource, 'repeat');\n\n const tempMatrix = fillPattern.transform.copyTo(Matrix.shared);\n\n tempMatrix.scale(\n fillPattern.texture.frame.width,\n fillPattern.texture.frame.height\n );\n\n pattern.setTransform(tempMatrix);\n\n return pattern;\n }\n else if (fillStyle.fill instanceof FillGradient)\n {\n const fillGradient = fillStyle.fill;\n\n if (fillGradient.type === 'linear')\n {\n const gradient = context.createLinearGradient(\n fillGradient.x0,\n fillGradient.y0,\n fillGradient.x1,\n fillGradient.y1\n );\n\n fillGradient.gradientStops.forEach((stop) =>\n {\n gradient.addColorStop(stop.offset, Color.shared.setValue(stop.color).toHex());\n });\n\n return gradient;\n }\n }\n\n // #if _DEBUG\n warn('FillStyle not recognised', fillStyle);\n // #endif\n\n return 'red';\n}\n"],"names":[],"mappings":";;;;;;;;AAUgB,SAAA,kBAAA,CACZ,WACA,OACJ,EAAA;AACI,EAAA,IAAI,UAAU,OAAY,KAAA,OAAA,CAAQ,KAAS,IAAA,CAAC,UAAU,IACtD,EAAA;AACI,IAAO,OAAA,KAAA,CAAM,MAAO,CAAA,QAAA,CAAS,SAAU,CAAA,KAAK,CAAE,CAAA,QAAA,CAAS,SAAU,CAAA,KAAA,IAAS,CAAC,CAAA,CAAE,MAAO,EAAA,CAAA;AAAA,GACxF,MAAA,IACS,CAAC,SAAA,CAAU,IACpB,EAAA;AAEI,IAAA,MAAM,UAAU,OAAQ,CAAA,aAAA,CAAc,UAAU,OAAQ,CAAA,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAGjF,IAAA,MAAM,UAAa,GAAA,SAAA,CAAU,MAAO,CAAA,MAAA,CAAO,OAAO,MAAM,CAAA,CAAA;AAExD,IAAW,UAAA,CAAA,KAAA,CAAM,UAAU,OAAQ,CAAA,KAAA,CAAM,OAAO,SAAU,CAAA,OAAA,CAAQ,MAAM,MAAM,CAAA,CAAA;AAE9E,IAAA,OAAA,CAAQ,aAAa,UAAU,CAAA,CAAA;AAE/B,IAAO,OAAA,OAAA,CAAA;AAAA,GACX,MAAA,IACS,SAAU,CAAA,IAAA,YAAgB,WACnC,EAAA;AACI,IAAA,MAAM,cAAc,SAAU,CAAA,IAAA,CAAA;AAE9B,IAAA,MAAM,UAAU,OAAQ,CAAA,aAAA,CAAc,YAAY,OAAQ,CAAA,MAAA,CAAO,UAAU,QAAQ,CAAA,CAAA;AAEnF,IAAA,MAAM,UAAa,GAAA,WAAA,CAAY,SAAU,CAAA,MAAA,CAAO,OAAO,MAAM,CAAA,CAAA;AAE7D,IAAW,UAAA,CAAA,KAAA;AAAA,MACP,WAAA,CAAY,QAAQ,KAAM,CAAA,KAAA;AAAA,MAC1B,WAAA,CAAY,QAAQ,KAAM,CAAA,MAAA;AAAA,KAC9B,CAAA;AAEA,IAAA,OAAA,CAAQ,aAAa,UAAU,CAAA,CAAA;AAE/B,IAAO,OAAA,OAAA,CAAA;AAAA,GACX,MAAA,IACS,SAAU,CAAA,IAAA,YAAgB,YACnC,EAAA;AACI,IAAA,MAAM,eAAe,SAAU,CAAA,IAAA,CAAA;AAE/B,IAAI,IAAA,YAAA,CAAa,SAAS,QAC1B,EAAA;AACI,MAAA,MAAM,WAAW,OAAQ,CAAA,oBAAA;AAAA,QACrB,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,QACb,YAAa,CAAA,EAAA;AAAA,OACjB,CAAA;AAEA,MAAa,YAAA,CAAA,aAAA,CAAc,OAAQ,CAAA,CAAC,IACpC,KAAA;AACI,QAAS,QAAA,CAAA,YAAA,CAAa,IAAK,CAAA,MAAA,EAAQ,KAAM,CAAA,MAAA,CAAO,SAAS,IAAK,CAAA,KAAK,CAAE,CAAA,KAAA,EAAO,CAAA,CAAA;AAAA,OAC/E,CAAA,CAAA;AAED,MAAO,OAAA,QAAA,CAAA;AAAA,KACX;AAAA,GACJ;AAGA,EAAA,IAAA,CAAK,4BAA4B,SAAS,CAAA,CAAA;AAG1C,EAAO,OAAA,KAAA,CAAA;AACX;;;;"}

1
node_modules/pixi.js/lib/scene/text/init.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export {};

10
node_modules/pixi.js/lib/scene/text/init.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
'use strict';
var Extensions = require('../../extensions/Extensions.js');
var CanvasTextPipe = require('./canvas/CanvasTextPipe.js');
var CanvasTextSystem = require('./canvas/CanvasTextSystem.js');
"use strict";
Extensions.extensions.add(CanvasTextSystem.CanvasTextSystem);
Extensions.extensions.add(CanvasTextPipe.CanvasTextPipe);
//# sourceMappingURL=init.js.map

1
node_modules/pixi.js/lib/scene/text/init.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"init.js","sources":["../../../src/scene/text/init.ts"],"sourcesContent":["import { extensions } from '../../extensions/Extensions';\nimport { CanvasTextPipe } from './canvas/CanvasTextPipe';\nimport { CanvasTextSystem } from './canvas/CanvasTextSystem';\n\nextensions.add(CanvasTextSystem);\nextensions.add(CanvasTextPipe);\n"],"names":["extensions","CanvasTextSystem","CanvasTextPipe"],"mappings":";;;;;;;AAIAA,qBAAA,CAAW,IAAIC,iCAAgB,CAAA,CAAA;AAC/BD,qBAAA,CAAW,IAAIE,6BAAc,CAAA;;"}

8
node_modules/pixi.js/lib/scene/text/init.mjs generated vendored Normal file
View File

@@ -0,0 +1,8 @@
import { extensions } from '../../extensions/Extensions.mjs';
import { CanvasTextPipe } from './canvas/CanvasTextPipe.mjs';
import { CanvasTextSystem } from './canvas/CanvasTextSystem.mjs';
"use strict";
extensions.add(CanvasTextSystem);
extensions.add(CanvasTextPipe);
//# sourceMappingURL=init.mjs.map

1
node_modules/pixi.js/lib/scene/text/init.mjs.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"init.mjs","sources":["../../../src/scene/text/init.ts"],"sourcesContent":["import { extensions } from '../../extensions/Extensions';\nimport { CanvasTextPipe } from './canvas/CanvasTextPipe';\nimport { CanvasTextSystem } from './canvas/CanvasTextSystem';\n\nextensions.add(CanvasTextSystem);\nextensions.add(CanvasTextPipe);\n"],"names":[],"mappings":";;;;;AAIA,UAAA,CAAW,IAAI,gBAAgB,CAAA,CAAA;AAC/B,UAAA,CAAW,IAAI,cAAc,CAAA"}

View File

@@ -0,0 +1,4 @@
import { Shader } from '../../../rendering/renderers/shared/shader/Shader';
export declare class SdfShader extends Shader {
constructor();
}

View File

@@ -0,0 +1,59 @@
'use strict';
var Matrix = require('../../../maths/matrix/Matrix.js');
var maxRecommendedTextures = require('../../../rendering/batcher/gl/utils/maxRecommendedTextures.js');
var compileHighShaderToProgram = require('../../../rendering/high-shader/compileHighShaderToProgram.js');
var colorBit = require('../../../rendering/high-shader/shader-bits/colorBit.js');
var generateTextureBatchBit = require('../../../rendering/high-shader/shader-bits/generateTextureBatchBit.js');
var roundPixelsBit = require('../../../rendering/high-shader/shader-bits/roundPixelsBit.js');
var getBatchSamplersUniformGroup = require('../../../rendering/renderers/gl/shader/getBatchSamplersUniformGroup.js');
var Shader = require('../../../rendering/renderers/shared/shader/Shader.js');
var UniformGroup = require('../../../rendering/renderers/shared/shader/UniformGroup.js');
var localUniformMSDFBit = require('./shader-bits/localUniformMSDFBit.js');
var mSDFBit = require('./shader-bits/mSDFBit.js');
"use strict";
let gpuProgram;
let glProgram;
class SdfShader extends Shader.Shader {
constructor() {
const uniforms = new UniformGroup.UniformGroup({
uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
uTransformMatrix: { value: new Matrix.Matrix(), type: "mat3x3<f32>" },
uDistance: { value: 4, type: "f32" },
uRound: { value: 0, type: "f32" }
});
const maxTextures = maxRecommendedTextures.getMaxTexturesPerBatch();
gpuProgram ?? (gpuProgram = compileHighShaderToProgram.compileHighShaderGpuProgram({
name: "sdf-shader",
bits: [
colorBit.colorBit,
generateTextureBatchBit.generateTextureBatchBit(maxTextures),
localUniformMSDFBit.localUniformMSDFBit,
mSDFBit.mSDFBit,
roundPixelsBit.roundPixelsBit
]
}));
glProgram ?? (glProgram = compileHighShaderToProgram.compileHighShaderGlProgram({
name: "sdf-shader",
bits: [
colorBit.colorBitGl,
generateTextureBatchBit.generateTextureBatchBitGl(maxTextures),
localUniformMSDFBit.localUniformMSDFBitGl,
mSDFBit.mSDFBitGl,
roundPixelsBit.roundPixelsBitGl
]
}));
super({
glProgram,
gpuProgram,
resources: {
localUniforms: uniforms,
batchSamplers: getBatchSamplersUniformGroup.getBatchSamplersUniformGroup(maxTextures)
}
});
}
}
exports.SdfShader = SdfShader;
//# sourceMappingURL=SdfShader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"SdfShader.js","sources":["../../../../src/scene/text/sdfShader/SdfShader.ts"],"sourcesContent":["import { Matrix } from '../../../maths/matrix/Matrix';\nimport { getMaxTexturesPerBatch } from '../../../rendering/batcher/gl/utils/maxRecommendedTextures';\nimport {\n compileHighShaderGlProgram,\n compileHighShaderGpuProgram\n} from '../../../rendering/high-shader/compileHighShaderToProgram';\nimport { colorBit, colorBitGl } from '../../../rendering/high-shader/shader-bits/colorBit';\nimport {\n generateTextureBatchBit,\n generateTextureBatchBitGl\n} from '../../../rendering/high-shader/shader-bits/generateTextureBatchBit';\nimport { roundPixelsBit, roundPixelsBitGl } from '../../../rendering/high-shader/shader-bits/roundPixelsBit';\nimport { getBatchSamplersUniformGroup } from '../../../rendering/renderers/gl/shader/getBatchSamplersUniformGroup';\nimport { Shader } from '../../../rendering/renderers/shared/shader/Shader';\nimport { UniformGroup } from '../../../rendering/renderers/shared/shader/UniformGroup';\nimport { localUniformMSDFBit, localUniformMSDFBitGl } from './shader-bits/localUniformMSDFBit';\nimport { mSDFBit, mSDFBitGl } from './shader-bits/mSDFBit';\n\nimport type { GlProgram } from '../../../rendering/renderers/gl/shader/GlProgram';\nimport type { GpuProgram } from '../../../rendering/renderers/gpu/shader/GpuProgram';\n\nlet gpuProgram: GpuProgram;\nlet glProgram: GlProgram;\n\nexport class SdfShader extends Shader\n{\n constructor()\n {\n const uniforms = new UniformGroup({\n uColor: { value: new Float32Array([1, 1, 1, 1]), type: 'vec4<f32>' },\n uTransformMatrix: { value: new Matrix(), type: 'mat3x3<f32>' },\n uDistance: { value: 4, type: 'f32' },\n uRound: { value: 0, type: 'f32' },\n });\n\n const maxTextures = getMaxTexturesPerBatch();\n\n gpuProgram ??= compileHighShaderGpuProgram({\n name: 'sdf-shader',\n bits: [\n colorBit,\n generateTextureBatchBit(maxTextures),\n localUniformMSDFBit,\n mSDFBit,\n roundPixelsBit\n ]\n });\n\n glProgram ??= compileHighShaderGlProgram({\n name: 'sdf-shader',\n bits: [\n colorBitGl,\n generateTextureBatchBitGl(maxTextures),\n localUniformMSDFBitGl,\n mSDFBitGl,\n roundPixelsBitGl,\n ]\n });\n\n super({\n glProgram,\n gpuProgram,\n resources: {\n localUniforms: uniforms,\n batchSamplers: getBatchSamplersUniformGroup(maxTextures),\n }\n });\n }\n}\n"],"names":["Shader","UniformGroup","Matrix","getMaxTexturesPerBatch","compileHighShaderGpuProgram","colorBit","generateTextureBatchBit","localUniformMSDFBit","mSDFBit","roundPixelsBit","compileHighShaderGlProgram","colorBitGl","generateTextureBatchBitGl","localUniformMSDFBitGl","mSDFBitGl","roundPixelsBitGl","getBatchSamplersUniformGroup"],"mappings":";;;;;;;;;;;;;;;AAqBA,IAAI,UAAA,CAAA;AACJ,IAAI,SAAA,CAAA;AAEG,MAAM,kBAAkBA,aAC/B,CAAA;AAAA,EACI,WACA,GAAA;AACI,IAAM,MAAA,QAAA,GAAW,IAAIC,yBAAa,CAAA;AAAA,MAC9B,MAAQ,EAAA,EAAE,KAAO,EAAA,IAAI,YAAa,CAAA,CAAC,CAAG,EAAA,CAAA,EAAG,CAAG,EAAA,CAAC,CAAC,CAAA,EAAG,MAAM,WAAY,EAAA;AAAA,MACnE,kBAAkB,EAAE,KAAA,EAAO,IAAIC,aAAO,EAAA,EAAG,MAAM,aAAc,EAAA;AAAA,MAC7D,SAAW,EAAA,EAAE,KAAO,EAAA,CAAA,EAAG,MAAM,KAAM,EAAA;AAAA,MACnC,MAAQ,EAAA,EAAE,KAAO,EAAA,CAAA,EAAG,MAAM,KAAM,EAAA;AAAA,KACnC,CAAA,CAAA;AAED,IAAA,MAAM,cAAcC,6CAAuB,EAAA,CAAA;AAE3C,IAAA,UAAA,KAAA,UAAA,GAAeC,sDAA4B,CAAA;AAAA,MACvC,IAAM,EAAA,YAAA;AAAA,MACN,IAAM,EAAA;AAAA,QACFC,iBAAA;AAAA,QACAC,gDAAwB,WAAW,CAAA;AAAA,QACnCC,uCAAA;AAAA,QACAC,eAAA;AAAA,QACAC,6BAAA;AAAA,OACJ;AAAA,KACH,CAAA,CAAA,CAAA;AAED,IAAA,SAAA,KAAA,SAAA,GAAcC,qDAA2B,CAAA;AAAA,MACrC,IAAM,EAAA,YAAA;AAAA,MACN,IAAM,EAAA;AAAA,QACFC,mBAAA;AAAA,QACAC,kDAA0B,WAAW,CAAA;AAAA,QACrCC,yCAAA;AAAA,QACAC,iBAAA;AAAA,QACAC,+BAAA;AAAA,OACJ;AAAA,KACH,CAAA,CAAA,CAAA;AAED,IAAM,KAAA,CAAA;AAAA,MACF,SAAA;AAAA,MACA,UAAA;AAAA,MACA,SAAW,EAAA;AAAA,QACP,aAAe,EAAA,QAAA;AAAA,QACf,aAAA,EAAeC,0DAA6B,WAAW,CAAA;AAAA,OAC3D;AAAA,KACH,CAAA,CAAA;AAAA,GACL;AACJ;;;;"}

View File

@@ -0,0 +1,57 @@
import { Matrix } from '../../../maths/matrix/Matrix.mjs';
import { getMaxTexturesPerBatch } from '../../../rendering/batcher/gl/utils/maxRecommendedTextures.mjs';
import { compileHighShaderGpuProgram, compileHighShaderGlProgram } from '../../../rendering/high-shader/compileHighShaderToProgram.mjs';
import { colorBit, colorBitGl } from '../../../rendering/high-shader/shader-bits/colorBit.mjs';
import { generateTextureBatchBit, generateTextureBatchBitGl } from '../../../rendering/high-shader/shader-bits/generateTextureBatchBit.mjs';
import { roundPixelsBit, roundPixelsBitGl } from '../../../rendering/high-shader/shader-bits/roundPixelsBit.mjs';
import { getBatchSamplersUniformGroup } from '../../../rendering/renderers/gl/shader/getBatchSamplersUniformGroup.mjs';
import { Shader } from '../../../rendering/renderers/shared/shader/Shader.mjs';
import { UniformGroup } from '../../../rendering/renderers/shared/shader/UniformGroup.mjs';
import { localUniformMSDFBit, localUniformMSDFBitGl } from './shader-bits/localUniformMSDFBit.mjs';
import { mSDFBit, mSDFBitGl } from './shader-bits/mSDFBit.mjs';
"use strict";
let gpuProgram;
let glProgram;
class SdfShader extends Shader {
constructor() {
const uniforms = new UniformGroup({
uColor: { value: new Float32Array([1, 1, 1, 1]), type: "vec4<f32>" },
uTransformMatrix: { value: new Matrix(), type: "mat3x3<f32>" },
uDistance: { value: 4, type: "f32" },
uRound: { value: 0, type: "f32" }
});
const maxTextures = getMaxTexturesPerBatch();
gpuProgram ?? (gpuProgram = compileHighShaderGpuProgram({
name: "sdf-shader",
bits: [
colorBit,
generateTextureBatchBit(maxTextures),
localUniformMSDFBit,
mSDFBit,
roundPixelsBit
]
}));
glProgram ?? (glProgram = compileHighShaderGlProgram({
name: "sdf-shader",
bits: [
colorBitGl,
generateTextureBatchBitGl(maxTextures),
localUniformMSDFBitGl,
mSDFBitGl,
roundPixelsBitGl
]
}));
super({
glProgram,
gpuProgram,
resources: {
localUniforms: uniforms,
batchSamplers: getBatchSamplersUniformGroup(maxTextures)
}
});
}
}
export { SdfShader };
//# sourceMappingURL=SdfShader.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"SdfShader.mjs","sources":["../../../../src/scene/text/sdfShader/SdfShader.ts"],"sourcesContent":["import { Matrix } from '../../../maths/matrix/Matrix';\nimport { getMaxTexturesPerBatch } from '../../../rendering/batcher/gl/utils/maxRecommendedTextures';\nimport {\n compileHighShaderGlProgram,\n compileHighShaderGpuProgram\n} from '../../../rendering/high-shader/compileHighShaderToProgram';\nimport { colorBit, colorBitGl } from '../../../rendering/high-shader/shader-bits/colorBit';\nimport {\n generateTextureBatchBit,\n generateTextureBatchBitGl\n} from '../../../rendering/high-shader/shader-bits/generateTextureBatchBit';\nimport { roundPixelsBit, roundPixelsBitGl } from '../../../rendering/high-shader/shader-bits/roundPixelsBit';\nimport { getBatchSamplersUniformGroup } from '../../../rendering/renderers/gl/shader/getBatchSamplersUniformGroup';\nimport { Shader } from '../../../rendering/renderers/shared/shader/Shader';\nimport { UniformGroup } from '../../../rendering/renderers/shared/shader/UniformGroup';\nimport { localUniformMSDFBit, localUniformMSDFBitGl } from './shader-bits/localUniformMSDFBit';\nimport { mSDFBit, mSDFBitGl } from './shader-bits/mSDFBit';\n\nimport type { GlProgram } from '../../../rendering/renderers/gl/shader/GlProgram';\nimport type { GpuProgram } from '../../../rendering/renderers/gpu/shader/GpuProgram';\n\nlet gpuProgram: GpuProgram;\nlet glProgram: GlProgram;\n\nexport class SdfShader extends Shader\n{\n constructor()\n {\n const uniforms = new UniformGroup({\n uColor: { value: new Float32Array([1, 1, 1, 1]), type: 'vec4<f32>' },\n uTransformMatrix: { value: new Matrix(), type: 'mat3x3<f32>' },\n uDistance: { value: 4, type: 'f32' },\n uRound: { value: 0, type: 'f32' },\n });\n\n const maxTextures = getMaxTexturesPerBatch();\n\n gpuProgram ??= compileHighShaderGpuProgram({\n name: 'sdf-shader',\n bits: [\n colorBit,\n generateTextureBatchBit(maxTextures),\n localUniformMSDFBit,\n mSDFBit,\n roundPixelsBit\n ]\n });\n\n glProgram ??= compileHighShaderGlProgram({\n name: 'sdf-shader',\n bits: [\n colorBitGl,\n generateTextureBatchBitGl(maxTextures),\n localUniformMSDFBitGl,\n mSDFBitGl,\n roundPixelsBitGl,\n ]\n });\n\n super({\n glProgram,\n gpuProgram,\n resources: {\n localUniforms: uniforms,\n batchSamplers: getBatchSamplersUniformGroup(maxTextures),\n }\n });\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;AAqBA,IAAI,UAAA,CAAA;AACJ,IAAI,SAAA,CAAA;AAEG,MAAM,kBAAkB,MAC/B,CAAA;AAAA,EACI,WACA,GAAA;AACI,IAAM,MAAA,QAAA,GAAW,IAAI,YAAa,CAAA;AAAA,MAC9B,MAAQ,EAAA,EAAE,KAAO,EAAA,IAAI,YAAa,CAAA,CAAC,CAAG,EAAA,CAAA,EAAG,CAAG,EAAA,CAAC,CAAC,CAAA,EAAG,MAAM,WAAY,EAAA;AAAA,MACnE,kBAAkB,EAAE,KAAA,EAAO,IAAI,MAAO,EAAA,EAAG,MAAM,aAAc,EAAA;AAAA,MAC7D,SAAW,EAAA,EAAE,KAAO,EAAA,CAAA,EAAG,MAAM,KAAM,EAAA;AAAA,MACnC,MAAQ,EAAA,EAAE,KAAO,EAAA,CAAA,EAAG,MAAM,KAAM,EAAA;AAAA,KACnC,CAAA,CAAA;AAED,IAAA,MAAM,cAAc,sBAAuB,EAAA,CAAA;AAE3C,IAAA,UAAA,KAAA,UAAA,GAAe,2BAA4B,CAAA;AAAA,MACvC,IAAM,EAAA,YAAA;AAAA,MACN,IAAM,EAAA;AAAA,QACF,QAAA;AAAA,QACA,wBAAwB,WAAW,CAAA;AAAA,QACnC,mBAAA;AAAA,QACA,OAAA;AAAA,QACA,cAAA;AAAA,OACJ;AAAA,KACH,CAAA,CAAA,CAAA;AAED,IAAA,SAAA,KAAA,SAAA,GAAc,0BAA2B,CAAA;AAAA,MACrC,IAAM,EAAA,YAAA;AAAA,MACN,IAAM,EAAA;AAAA,QACF,UAAA;AAAA,QACA,0BAA0B,WAAW,CAAA;AAAA,QACrC,qBAAA;AAAA,QACA,SAAA;AAAA,QACA,gBAAA;AAAA,OACJ;AAAA,KACH,CAAA,CAAA,CAAA;AAED,IAAM,KAAA,CAAA;AAAA,MACF,SAAA;AAAA,MACA,UAAA;AAAA,MACA,SAAW,EAAA;AAAA,QACP,aAAe,EAAA,QAAA;AAAA,QACf,aAAA,EAAe,6BAA6B,WAAW,CAAA;AAAA,OAC3D;AAAA,KACH,CAAA,CAAA;AAAA,GACL;AACJ;;;;"}

View File

@@ -0,0 +1,24 @@
export declare const localUniformMSDFBit: {
name: string;
vertex: {
header: string;
main: string;
end: string;
};
fragment: {
header: string;
main: string;
};
};
export declare const localUniformMSDFBitGl: {
name: string;
vertex: {
header: string;
main: string;
end: string;
};
fragment: {
header: string;
main: string;
};
};

View File

@@ -0,0 +1,104 @@
'use strict';
"use strict";
const localUniformMSDFBit = {
name: "local-uniform-msdf-bit",
vertex: {
header: (
/* wgsl */
`
struct LocalUniforms {
uColor:vec4<f32>,
uTransformMatrix:mat3x3<f32>,
uDistance: f32,
uRound:f32,
}
@group(2) @binding(0) var<uniform> localUniforms : LocalUniforms;
`
),
main: (
/* wgsl */
`
vColor *= localUniforms.uColor;
modelMatrix *= localUniforms.uTransformMatrix;
`
),
end: (
/* wgsl */
`
if(localUniforms.uRound == 1)
{
vPosition = vec4(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);
}
`
)
},
fragment: {
header: (
/* wgsl */
`
struct LocalUniforms {
uColor:vec4<f32>,
uTransformMatrix:mat3x3<f32>,
uDistance: f32
}
@group(2) @binding(0) var<uniform> localUniforms : LocalUniforms;
`
),
main: (
/* wgsl */
`
outColor = vec4<f32>(calculateMSDFAlpha(outColor, localUniforms.uColor, localUniforms.uDistance));
`
)
}
};
const localUniformMSDFBitGl = {
name: "local-uniform-msdf-bit",
vertex: {
header: (
/* glsl */
`
uniform mat3 uTransformMatrix;
uniform vec4 uColor;
uniform float uRound;
`
),
main: (
/* glsl */
`
vColor *= uColor;
modelMatrix *= uTransformMatrix;
`
),
end: (
/* glsl */
`
if(uRound == 1.)
{
gl_Position.xy = roundPixels(gl_Position.xy, uResolution);
}
`
)
},
fragment: {
header: (
/* glsl */
`
uniform float uDistance;
`
),
main: (
/* glsl */
`
outColor = vec4(calculateMSDFAlpha(outColor, vColor, uDistance));
`
)
}
};
exports.localUniformMSDFBit = localUniformMSDFBit;
exports.localUniformMSDFBitGl = localUniformMSDFBitGl;
//# sourceMappingURL=localUniformMSDFBit.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"localUniformMSDFBit.js","sources":["../../../../../src/scene/text/sdfShader/shader-bits/localUniformMSDFBit.ts"],"sourcesContent":["// TODO eventually we should not use this bit, but instead use the localUniformBit\n// have the MSDF bit be merged in with the localUniformBit\n\nexport const localUniformMSDFBit = {\n name: 'local-uniform-msdf-bit',\n vertex: {\n header: /* wgsl */`\n struct LocalUniforms {\n uColor:vec4<f32>,\n uTransformMatrix:mat3x3<f32>,\n uDistance: f32,\n uRound:f32,\n }\n\n @group(2) @binding(0) var<uniform> localUniforms : LocalUniforms;\n `,\n main: /* wgsl */`\n vColor *= localUniforms.uColor;\n modelMatrix *= localUniforms.uTransformMatrix;\n `,\n end: /* wgsl */`\n if(localUniforms.uRound == 1)\n {\n vPosition = vec4(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);\n }\n `\n },\n fragment: {\n header: /* wgsl */`\n struct LocalUniforms {\n uColor:vec4<f32>,\n uTransformMatrix:mat3x3<f32>,\n uDistance: f32\n }\n\n @group(2) @binding(0) var<uniform> localUniforms : LocalUniforms;\n `,\n main: /* wgsl */` \n outColor = vec4<f32>(calculateMSDFAlpha(outColor, localUniforms.uColor, localUniforms.uDistance));\n `\n\n }\n};\n\nexport const localUniformMSDFBitGl = {\n name: 'local-uniform-msdf-bit',\n vertex: {\n header: /* glsl */`\n uniform mat3 uTransformMatrix;\n uniform vec4 uColor;\n uniform float uRound;\n `,\n main: /* glsl */`\n vColor *= uColor;\n modelMatrix *= uTransformMatrix;\n `,\n end: /* glsl */`\n if(uRound == 1.)\n {\n gl_Position.xy = roundPixels(gl_Position.xy, uResolution);\n }\n `\n },\n fragment: {\n header: /* glsl */`\n uniform float uDistance;\n `,\n main: /* glsl */` \n outColor = vec4(calculateMSDFAlpha(outColor, vColor, uDistance));\n `\n\n }\n};\n"],"names":[],"mappings":";;;AAGO,MAAM,mBAAsB,GAAA;AAAA,EAC/B,IAAM,EAAA,wBAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACJ,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,IAUlB,IAAA;AAAA;AAAA,MAAgB,CAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,IAIhB,GAAA;AAAA;AAAA,MAAe,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GAMnB;AAAA,EACA,QAAU,EAAA;AAAA,IACN,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,CAAA;AAAA,KAAA;AAAA,IASlB,IAAA;AAAA;AAAA,MAAgB,CAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GAIpB;AACJ,EAAA;AAEO,MAAM,qBAAwB,GAAA;AAAA,EACjC,IAAM,EAAA,wBAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACJ,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,IAKlB,IAAA;AAAA;AAAA,MAAgB,CAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,IAIhB,GAAA;AAAA;AAAA,MAAe,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GAMnB;AAAA,EACA,QAAU,EAAA;AAAA,IACN,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA,SAAA,CAAA;AAAA,KAAA;AAAA,IAGlB,IAAA;AAAA;AAAA,MAAgB,CAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GAIpB;AACJ;;;;;"}

View File

@@ -0,0 +1,101 @@
"use strict";
const localUniformMSDFBit = {
name: "local-uniform-msdf-bit",
vertex: {
header: (
/* wgsl */
`
struct LocalUniforms {
uColor:vec4<f32>,
uTransformMatrix:mat3x3<f32>,
uDistance: f32,
uRound:f32,
}
@group(2) @binding(0) var<uniform> localUniforms : LocalUniforms;
`
),
main: (
/* wgsl */
`
vColor *= localUniforms.uColor;
modelMatrix *= localUniforms.uTransformMatrix;
`
),
end: (
/* wgsl */
`
if(localUniforms.uRound == 1)
{
vPosition = vec4(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);
}
`
)
},
fragment: {
header: (
/* wgsl */
`
struct LocalUniforms {
uColor:vec4<f32>,
uTransformMatrix:mat3x3<f32>,
uDistance: f32
}
@group(2) @binding(0) var<uniform> localUniforms : LocalUniforms;
`
),
main: (
/* wgsl */
`
outColor = vec4<f32>(calculateMSDFAlpha(outColor, localUniforms.uColor, localUniforms.uDistance));
`
)
}
};
const localUniformMSDFBitGl = {
name: "local-uniform-msdf-bit",
vertex: {
header: (
/* glsl */
`
uniform mat3 uTransformMatrix;
uniform vec4 uColor;
uniform float uRound;
`
),
main: (
/* glsl */
`
vColor *= uColor;
modelMatrix *= uTransformMatrix;
`
),
end: (
/* glsl */
`
if(uRound == 1.)
{
gl_Position.xy = roundPixels(gl_Position.xy, uResolution);
}
`
)
},
fragment: {
header: (
/* glsl */
`
uniform float uDistance;
`
),
main: (
/* glsl */
`
outColor = vec4(calculateMSDFAlpha(outColor, vColor, uDistance));
`
)
}
};
export { localUniformMSDFBit, localUniformMSDFBitGl };
//# sourceMappingURL=localUniformMSDFBit.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"localUniformMSDFBit.mjs","sources":["../../../../../src/scene/text/sdfShader/shader-bits/localUniformMSDFBit.ts"],"sourcesContent":["// TODO eventually we should not use this bit, but instead use the localUniformBit\n// have the MSDF bit be merged in with the localUniformBit\n\nexport const localUniformMSDFBit = {\n name: 'local-uniform-msdf-bit',\n vertex: {\n header: /* wgsl */`\n struct LocalUniforms {\n uColor:vec4<f32>,\n uTransformMatrix:mat3x3<f32>,\n uDistance: f32,\n uRound:f32,\n }\n\n @group(2) @binding(0) var<uniform> localUniforms : LocalUniforms;\n `,\n main: /* wgsl */`\n vColor *= localUniforms.uColor;\n modelMatrix *= localUniforms.uTransformMatrix;\n `,\n end: /* wgsl */`\n if(localUniforms.uRound == 1)\n {\n vPosition = vec4(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);\n }\n `\n },\n fragment: {\n header: /* wgsl */`\n struct LocalUniforms {\n uColor:vec4<f32>,\n uTransformMatrix:mat3x3<f32>,\n uDistance: f32\n }\n\n @group(2) @binding(0) var<uniform> localUniforms : LocalUniforms;\n `,\n main: /* wgsl */` \n outColor = vec4<f32>(calculateMSDFAlpha(outColor, localUniforms.uColor, localUniforms.uDistance));\n `\n\n }\n};\n\nexport const localUniformMSDFBitGl = {\n name: 'local-uniform-msdf-bit',\n vertex: {\n header: /* glsl */`\n uniform mat3 uTransformMatrix;\n uniform vec4 uColor;\n uniform float uRound;\n `,\n main: /* glsl */`\n vColor *= uColor;\n modelMatrix *= uTransformMatrix;\n `,\n end: /* glsl */`\n if(uRound == 1.)\n {\n gl_Position.xy = roundPixels(gl_Position.xy, uResolution);\n }\n `\n },\n fragment: {\n header: /* glsl */`\n uniform float uDistance;\n `,\n main: /* glsl */` \n outColor = vec4(calculateMSDFAlpha(outColor, vColor, uDistance));\n `\n\n }\n};\n"],"names":[],"mappings":";AAGO,MAAM,mBAAsB,GAAA;AAAA,EAC/B,IAAM,EAAA,wBAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACJ,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,IAUlB,IAAA;AAAA;AAAA,MAAgB,CAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,IAIhB,GAAA;AAAA;AAAA,MAAe,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GAMnB;AAAA,EACA,QAAU,EAAA;AAAA,IACN,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAA,CAAA;AAAA,KAAA;AAAA,IASlB,IAAA;AAAA;AAAA,MAAgB,CAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GAIpB;AACJ,EAAA;AAEO,MAAM,qBAAwB,GAAA;AAAA,EACjC,IAAM,EAAA,wBAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACJ,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,IAKlB,IAAA;AAAA;AAAA,MAAgB,CAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,IAIhB,GAAA;AAAA;AAAA,MAAe,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GAMnB;AAAA,EACA,QAAU,EAAA;AAAA,IACN,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA,SAAA,CAAA;AAAA,KAAA;AAAA,IAGlB,IAAA;AAAA;AAAA,MAAgB,CAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GAIpB;AACJ;;;;"}

View File

@@ -0,0 +1,12 @@
export declare const mSDFBit: {
name: string;
fragment: {
header: string;
};
};
export declare const mSDFBitGl: {
name: string;
fragment: {
header: string;
};
};

View File

@@ -0,0 +1,79 @@
'use strict';
"use strict";
const mSDFBit = {
name: "msdf-bit",
fragment: {
header: (
/* wgsl */
`
fn calculateMSDFAlpha(msdfColor:vec4<f32>, shapeColor:vec4<f32>, distance:f32) -> f32 {
// MSDF
var median = msdfColor.r + msdfColor.g + msdfColor.b -
min(msdfColor.r, min(msdfColor.g, msdfColor.b)) -
max(msdfColor.r, max(msdfColor.g, msdfColor.b));
// SDF
median = min(median, msdfColor.a);
var screenPxDistance = distance * (median - 0.5);
var alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);
if (median < 0.01) {
alpha = 0.0;
} else if (median > 0.99) {
alpha = 1.0;
}
// Gamma correction for coverage-like alpha
var luma: f32 = dot(shapeColor.rgb, vec3<f32>(0.299, 0.587, 0.114));
var gamma: f32 = mix(1.0, 1.0 / 2.2, luma);
var coverage: f32 = pow(shapeColor.a * alpha, gamma);
return coverage;
}
`
)
}
};
const mSDFBitGl = {
name: "msdf-bit",
fragment: {
header: (
/* glsl */
`
float calculateMSDFAlpha(vec4 msdfColor, vec4 shapeColor, float distance) {
// MSDF
float median = msdfColor.r + msdfColor.g + msdfColor.b -
min(msdfColor.r, min(msdfColor.g, msdfColor.b)) -
max(msdfColor.r, max(msdfColor.g, msdfColor.b));
// SDF
median = min(median, msdfColor.a);
float screenPxDistance = distance * (median - 0.5);
float alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);
if (median < 0.01) {
alpha = 0.0;
} else if (median > 0.99) {
alpha = 1.0;
}
// Gamma correction for coverage-like alpha
float luma = dot(shapeColor.rgb, vec3(0.299, 0.587, 0.114));
float gamma = mix(1.0, 1.0 / 2.2, luma);
float coverage = pow(shapeColor.a * alpha, gamma);
return coverage;
}
`
)
}
};
exports.mSDFBit = mSDFBit;
exports.mSDFBitGl = mSDFBitGl;
//# sourceMappingURL=mSDFBit.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"mSDFBit.js","sources":["../../../../../src/scene/text/sdfShader/shader-bits/mSDFBit.ts"],"sourcesContent":["export const mSDFBit = {\n name: 'msdf-bit',\n fragment: {\n header: /* wgsl */`\n fn calculateMSDFAlpha(msdfColor:vec4<f32>, shapeColor:vec4<f32>, distance:f32) -> f32 {\n \n // MSDF\n var median = msdfColor.r + msdfColor.g + msdfColor.b -\n min(msdfColor.r, min(msdfColor.g, msdfColor.b)) -\n max(msdfColor.r, max(msdfColor.g, msdfColor.b));\n \n // SDF\n median = min(median, msdfColor.a);\n\n var screenPxDistance = distance * (median - 0.5);\n var alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);\n if (median < 0.01) {\n alpha = 0.0;\n } else if (median > 0.99) {\n alpha = 1.0;\n }\n\n // Gamma correction for coverage-like alpha\n var luma: f32 = dot(shapeColor.rgb, vec3<f32>(0.299, 0.587, 0.114));\n var gamma: f32 = mix(1.0, 1.0 / 2.2, luma);\n var coverage: f32 = pow(shapeColor.a * alpha, gamma);\n\n return coverage;\n \n }\n `,\n }\n\n};\n\nexport const mSDFBitGl = {\n name: 'msdf-bit',\n fragment: {\n header: /* glsl */`\n float calculateMSDFAlpha(vec4 msdfColor, vec4 shapeColor, float distance) {\n \n // MSDF\n float median = msdfColor.r + msdfColor.g + msdfColor.b -\n min(msdfColor.r, min(msdfColor.g, msdfColor.b)) -\n max(msdfColor.r, max(msdfColor.g, msdfColor.b));\n \n // SDF\n median = min(median, msdfColor.a);\n \n float screenPxDistance = distance * (median - 0.5);\n float alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);\n \n if (median < 0.01) {\n alpha = 0.0;\n } else if (median > 0.99) {\n alpha = 1.0;\n }\n\n // Gamma correction for coverage-like alpha\n float luma = dot(shapeColor.rgb, vec3(0.299, 0.587, 0.114));\n float gamma = mix(1.0, 1.0 / 2.2, luma);\n float coverage = pow(shapeColor.a * alpha, gamma); \n \n return coverage;\n }\n `,\n }\n\n};\n"],"names":[],"mappings":";;;AAAO,MAAM,OAAU,GAAA;AAAA,EACnB,IAAM,EAAA,UAAA;AAAA,EACN,QAAU,EAAA;AAAA,IACN,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GA4BtB;AAEJ,EAAA;AAEO,MAAM,SAAY,GAAA;AAAA,EACrB,IAAM,EAAA,UAAA;AAAA,EACN,QAAU,EAAA;AAAA,IACN,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GA4BtB;AAEJ;;;;;"}

View File

@@ -0,0 +1,76 @@
"use strict";
const mSDFBit = {
name: "msdf-bit",
fragment: {
header: (
/* wgsl */
`
fn calculateMSDFAlpha(msdfColor:vec4<f32>, shapeColor:vec4<f32>, distance:f32) -> f32 {
// MSDF
var median = msdfColor.r + msdfColor.g + msdfColor.b -
min(msdfColor.r, min(msdfColor.g, msdfColor.b)) -
max(msdfColor.r, max(msdfColor.g, msdfColor.b));
// SDF
median = min(median, msdfColor.a);
var screenPxDistance = distance * (median - 0.5);
var alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);
if (median < 0.01) {
alpha = 0.0;
} else if (median > 0.99) {
alpha = 1.0;
}
// Gamma correction for coverage-like alpha
var luma: f32 = dot(shapeColor.rgb, vec3<f32>(0.299, 0.587, 0.114));
var gamma: f32 = mix(1.0, 1.0 / 2.2, luma);
var coverage: f32 = pow(shapeColor.a * alpha, gamma);
return coverage;
}
`
)
}
};
const mSDFBitGl = {
name: "msdf-bit",
fragment: {
header: (
/* glsl */
`
float calculateMSDFAlpha(vec4 msdfColor, vec4 shapeColor, float distance) {
// MSDF
float median = msdfColor.r + msdfColor.g + msdfColor.b -
min(msdfColor.r, min(msdfColor.g, msdfColor.b)) -
max(msdfColor.r, max(msdfColor.g, msdfColor.b));
// SDF
median = min(median, msdfColor.a);
float screenPxDistance = distance * (median - 0.5);
float alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);
if (median < 0.01) {
alpha = 0.0;
} else if (median > 0.99) {
alpha = 1.0;
}
// Gamma correction for coverage-like alpha
float luma = dot(shapeColor.rgb, vec3(0.299, 0.587, 0.114));
float gamma = mix(1.0, 1.0 / 2.2, luma);
float coverage = pow(shapeColor.a * alpha, gamma);
return coverage;
}
`
)
}
};
export { mSDFBit, mSDFBitGl };
//# sourceMappingURL=mSDFBit.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"mSDFBit.mjs","sources":["../../../../../src/scene/text/sdfShader/shader-bits/mSDFBit.ts"],"sourcesContent":["export const mSDFBit = {\n name: 'msdf-bit',\n fragment: {\n header: /* wgsl */`\n fn calculateMSDFAlpha(msdfColor:vec4<f32>, shapeColor:vec4<f32>, distance:f32) -> f32 {\n \n // MSDF\n var median = msdfColor.r + msdfColor.g + msdfColor.b -\n min(msdfColor.r, min(msdfColor.g, msdfColor.b)) -\n max(msdfColor.r, max(msdfColor.g, msdfColor.b));\n \n // SDF\n median = min(median, msdfColor.a);\n\n var screenPxDistance = distance * (median - 0.5);\n var alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);\n if (median < 0.01) {\n alpha = 0.0;\n } else if (median > 0.99) {\n alpha = 1.0;\n }\n\n // Gamma correction for coverage-like alpha\n var luma: f32 = dot(shapeColor.rgb, vec3<f32>(0.299, 0.587, 0.114));\n var gamma: f32 = mix(1.0, 1.0 / 2.2, luma);\n var coverage: f32 = pow(shapeColor.a * alpha, gamma);\n\n return coverage;\n \n }\n `,\n }\n\n};\n\nexport const mSDFBitGl = {\n name: 'msdf-bit',\n fragment: {\n header: /* glsl */`\n float calculateMSDFAlpha(vec4 msdfColor, vec4 shapeColor, float distance) {\n \n // MSDF\n float median = msdfColor.r + msdfColor.g + msdfColor.b -\n min(msdfColor.r, min(msdfColor.g, msdfColor.b)) -\n max(msdfColor.r, max(msdfColor.g, msdfColor.b));\n \n // SDF\n median = min(median, msdfColor.a);\n \n float screenPxDistance = distance * (median - 0.5);\n float alpha = clamp(screenPxDistance + 0.5, 0.0, 1.0);\n \n if (median < 0.01) {\n alpha = 0.0;\n } else if (median > 0.99) {\n alpha = 1.0;\n }\n\n // Gamma correction for coverage-like alpha\n float luma = dot(shapeColor.rgb, vec3(0.299, 0.587, 0.114));\n float gamma = mix(1.0, 1.0 / 2.2, luma);\n float coverage = pow(shapeColor.a * alpha, gamma); \n \n return coverage;\n }\n `,\n }\n\n};\n"],"names":[],"mappings":";AAAO,MAAM,OAAU,GAAA;AAAA,EACnB,IAAM,EAAA,UAAA;AAAA,EACN,QAAU,EAAA;AAAA,IACN,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GA4BtB;AAEJ,EAAA;AAEO,MAAM,SAAY,GAAA;AAAA,EACrB,IAAM,EAAA,UAAA;AAAA,EACN,QAAU,EAAA;AAAA,IACN,MAAA;AAAA;AAAA,MAAkB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAAA,CAAA;AAAA,KAAA;AAAA,GA4BtB;AAEJ;;;;"}

View File

@@ -0,0 +1,12 @@
import { HTMLTextStyle } from '../../text-html/HtmlTextStyle';
import { TextStyle } from '../TextStyle';
import type { HTMLTextStyleOptions } from '../../text-html/HtmlTextStyle';
import type { TextStyleOptions } from '../TextStyle';
/**
* converts the style input into the correct type of TextStyle
* either HTMLTextStyle or TextStyle based on the renderMode.
* @param renderMode - The render mode to use
* @param style - The style to use
* @returns - The style class
*/
export declare function ensureTextStyle(renderMode: string, style: TextStyle | HTMLTextStyle | TextStyleOptions | HTMLTextStyleOptions): TextStyle;

View File

@@ -0,0 +1,15 @@
'use strict';
var HtmlTextStyle = require('../../text-html/HtmlTextStyle.js');
var TextStyle = require('../TextStyle.js');
"use strict";
function ensureTextStyle(renderMode, style) {
if (style instanceof TextStyle.TextStyle || style instanceof HtmlTextStyle.HTMLTextStyle) {
return style;
}
return renderMode === "html" ? new HtmlTextStyle.HTMLTextStyle(style) : new TextStyle.TextStyle(style);
}
exports.ensureTextStyle = ensureTextStyle;
//# sourceMappingURL=ensureTextStyle.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ensureTextStyle.js","sources":["../../../../src/scene/text/utils/ensureTextStyle.ts"],"sourcesContent":["import { HTMLTextStyle } from '../../text-html/HtmlTextStyle';\nimport { TextStyle } from '../TextStyle';\n\nimport type { HTMLTextStyleOptions } from '../../text-html/HtmlTextStyle';\nimport type { TextStyleOptions } from '../TextStyle';\n\n/**\n * converts the style input into the correct type of TextStyle\n * either HTMLTextStyle or TextStyle based on the renderMode.\n * @param renderMode - The render mode to use\n * @param style - The style to use\n * @returns - The style class\n */\nexport function ensureTextStyle(\n renderMode: string,\n style: TextStyle | HTMLTextStyle | TextStyleOptions | HTMLTextStyleOptions\n)\n{\n if (style instanceof TextStyle || style instanceof HTMLTextStyle)\n {\n return style;\n }\n\n return renderMode === 'html'\n ? new HTMLTextStyle(style)\n : new TextStyle(style);\n}\n"],"names":["TextStyle","HTMLTextStyle"],"mappings":";;;;;;AAagB,SAAA,eAAA,CACZ,YACA,KAEJ,EAAA;AACI,EAAI,IAAA,KAAA,YAAiBA,mBAAa,IAAA,KAAA,YAAiBC,2BACnD,EAAA;AACI,IAAO,OAAA,KAAA,CAAA;AAAA,GACX;AAEA,EAAO,OAAA,UAAA,KAAe,SAChB,IAAIA,2BAAA,CAAc,KAAK,CACvB,GAAA,IAAID,oBAAU,KAAK,CAAA,CAAA;AAC7B;;;;"}

View File

@@ -0,0 +1,13 @@
import { HTMLTextStyle } from '../../text-html/HtmlTextStyle.mjs';
import { TextStyle } from '../TextStyle.mjs';
"use strict";
function ensureTextStyle(renderMode, style) {
if (style instanceof TextStyle || style instanceof HTMLTextStyle) {
return style;
}
return renderMode === "html" ? new HTMLTextStyle(style) : new TextStyle(style);
}
export { ensureTextStyle };
//# sourceMappingURL=ensureTextStyle.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ensureTextStyle.mjs","sources":["../../../../src/scene/text/utils/ensureTextStyle.ts"],"sourcesContent":["import { HTMLTextStyle } from '../../text-html/HtmlTextStyle';\nimport { TextStyle } from '../TextStyle';\n\nimport type { HTMLTextStyleOptions } from '../../text-html/HtmlTextStyle';\nimport type { TextStyleOptions } from '../TextStyle';\n\n/**\n * converts the style input into the correct type of TextStyle\n * either HTMLTextStyle or TextStyle based on the renderMode.\n * @param renderMode - The render mode to use\n * @param style - The style to use\n * @returns - The style class\n */\nexport function ensureTextStyle(\n renderMode: string,\n style: TextStyle | HTMLTextStyle | TextStyleOptions | HTMLTextStyleOptions\n)\n{\n if (style instanceof TextStyle || style instanceof HTMLTextStyle)\n {\n return style;\n }\n\n return renderMode === 'html'\n ? new HTMLTextStyle(style)\n : new TextStyle(style);\n}\n"],"names":[],"mappings":";;;;AAagB,SAAA,eAAA,CACZ,YACA,KAEJ,EAAA;AACI,EAAI,IAAA,KAAA,YAAiB,SAAa,IAAA,KAAA,YAAiB,aACnD,EAAA;AACI,IAAO,OAAA,KAAA,CAAA;AAAA,GACX;AAEA,EAAO,OAAA,UAAA,KAAe,SAChB,IAAI,aAAA,CAAc,KAAK,CACvB,GAAA,IAAI,UAAU,KAAK,CAAA,CAAA;AAC7B;;;;"}

View File

@@ -0,0 +1,7 @@
import type { TextStyle } from '../TextStyle';
/**
* Generates a unique key for the text style.
* @param style - The style to generate a key for.
* @returns the key for the style.
*/
export declare function generateTextStyleKey(style: TextStyle): string;

View File

@@ -0,0 +1,68 @@
'use strict';
var Color = require('../../../color/Color.js');
"use strict";
const valuesToIterateForKeys = [
"align",
"breakWords",
"cssOverrides",
"fontVariant",
"fontWeight",
"leading",
"letterSpacing",
"lineHeight",
"padding",
"textBaseline",
"trim",
"whiteSpace",
"wordWrap",
"wordWrapWidth",
"fontFamily",
"fontStyle",
"fontSize"
];
function generateTextStyleKey(style) {
const key = [];
let index = 0;
for (let i = 0; i < valuesToIterateForKeys.length; i++) {
const prop = `_${valuesToIterateForKeys[i]}`;
key[index++] = style[prop];
}
index = addFillStyleKey(style._fill, key, index);
index = addStokeStyleKey(style._stroke, key, index);
index = addDropShadowKey(style.dropShadow, key, index);
return key.join("-");
}
function addFillStyleKey(fillStyle, key, index) {
if (!fillStyle)
return index;
key[index++] = fillStyle.color;
key[index++] = fillStyle.alpha;
key[index++] = fillStyle.fill?.styleKey;
return index;
}
function addStokeStyleKey(strokeStyle, key, index) {
if (!strokeStyle)
return index;
index = addFillStyleKey(strokeStyle, key, index);
key[index++] = strokeStyle.width;
key[index++] = strokeStyle.alignment;
key[index++] = strokeStyle.cap;
key[index++] = strokeStyle.join;
key[index++] = strokeStyle.miterLimit;
return index;
}
function addDropShadowKey(dropShadow, key, index) {
if (!dropShadow)
return index;
key[index++] = dropShadow.alpha;
key[index++] = dropShadow.angle;
key[index++] = dropShadow.blur;
key[index++] = dropShadow.distance;
key[index++] = Color.Color.shared.setValue(dropShadow.color).toNumber();
return index;
}
exports.generateTextStyleKey = generateTextStyleKey;
//# sourceMappingURL=generateTextStyleKey.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateTextStyleKey.js","sources":["../../../../src/scene/text/utils/generateTextStyleKey.ts"],"sourcesContent":["import { Color } from '../../../color/Color';\n\nimport type { ConvertedFillStyle, ConvertedStrokeStyle } from '../../graphics/shared/FillTypes';\nimport type { HTMLTextStyle } from '../../text-html/HtmlTextStyle';\nimport type { TextStyle } from '../TextStyle';\n\nconst valuesToIterateForKeys: Partial<keyof TextStyle | keyof HTMLTextStyle>[] = [\n 'align',\n 'breakWords',\n 'cssOverrides',\n 'fontVariant',\n 'fontWeight',\n 'leading',\n 'letterSpacing',\n 'lineHeight',\n 'padding',\n 'textBaseline',\n 'trim',\n 'whiteSpace',\n 'wordWrap',\n 'wordWrapWidth',\n 'fontFamily',\n 'fontStyle',\n 'fontSize',\n] as const;\n\n/**\n * Generates a unique key for the text style.\n * @param style - The style to generate a key for.\n * @returns the key for the style.\n */\nexport function generateTextStyleKey(style: TextStyle): string\n{\n const key = [];\n\n let index = 0;\n\n for (let i = 0; i < valuesToIterateForKeys.length; i++)\n {\n const prop = `_${valuesToIterateForKeys[i]}`;\n\n key[index++] = style[prop as keyof typeof style];\n }\n\n index = addFillStyleKey(style._fill, key as string[], index);\n index = addStokeStyleKey(style._stroke, key as string[], index);\n index = addDropShadowKey(style.dropShadow, key as string[], index);\n\n return key.join('-');\n}\n\nfunction addFillStyleKey(fillStyle: ConvertedFillStyle, key: (number | string)[], index: number)\n{\n if (!fillStyle) return index;\n\n key[index++] = fillStyle.color;\n key[index++] = fillStyle.alpha;\n key[index++] = fillStyle.fill?.styleKey;\n\n return index;\n}\n\nfunction addStokeStyleKey(strokeStyle: ConvertedStrokeStyle, key: (number | string)[], index: number)\n{\n if (!strokeStyle) return index;\n\n index = addFillStyleKey(strokeStyle, key, index);\n\n key[index++] = strokeStyle.width;\n key[index++] = strokeStyle.alignment;\n key[index++] = strokeStyle.cap;\n key[index++] = strokeStyle.join;\n key[index++] = strokeStyle.miterLimit;\n\n return index;\n}\n\nfunction addDropShadowKey(dropShadow: TextStyle['dropShadow'], key: (number | string)[], index: number)\n{\n if (!dropShadow) return index;\n\n key[index++] = dropShadow.alpha;\n key[index++] = dropShadow.angle;\n key[index++] = dropShadow.blur;\n key[index++] = dropShadow.distance;\n key[index++] = Color.shared.setValue(dropShadow.color).toNumber();\n\n return index;\n}\n"],"names":["Color"],"mappings":";;;;;AAMA,MAAM,sBAA2E,GAAA;AAAA,EAC7E,OAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA,MAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AACJ,CAAA,CAAA;AAOO,SAAS,qBAAqB,KACrC,EAAA;AACI,EAAA,MAAM,MAAM,EAAC,CAAA;AAEb,EAAA,IAAI,KAAQ,GAAA,CAAA,CAAA;AAEZ,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,sBAAA,CAAuB,QAAQ,CACnD,EAAA,EAAA;AACI,IAAA,MAAM,IAAO,GAAA,CAAA,CAAA,EAAI,sBAAuB,CAAA,CAAC,CAAC,CAAA,CAAA,CAAA;AAE1C,IAAI,GAAA,CAAA,KAAA,EAAO,CAAI,GAAA,KAAA,CAAM,IAA0B,CAAA,CAAA;AAAA,GACnD;AAEA,EAAA,KAAA,GAAQ,eAAgB,CAAA,KAAA,CAAM,KAAO,EAAA,GAAA,EAAiB,KAAK,CAAA,CAAA;AAC3D,EAAA,KAAA,GAAQ,gBAAiB,CAAA,KAAA,CAAM,OAAS,EAAA,GAAA,EAAiB,KAAK,CAAA,CAAA;AAC9D,EAAA,KAAA,GAAQ,gBAAiB,CAAA,KAAA,CAAM,UAAY,EAAA,GAAA,EAAiB,KAAK,CAAA,CAAA;AAEjE,EAAO,OAAA,GAAA,CAAI,KAAK,GAAG,CAAA,CAAA;AACvB,CAAA;AAEA,SAAS,eAAA,CAAgB,SAA+B,EAAA,GAAA,EAA0B,KAClF,EAAA;AACI,EAAA,IAAI,CAAC,SAAA;AAAW,IAAO,OAAA,KAAA,CAAA;AAEvB,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,SAAU,CAAA,KAAA,CAAA;AACzB,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,SAAU,CAAA,KAAA,CAAA;AACzB,EAAI,GAAA,CAAA,KAAA,EAAO,CAAI,GAAA,SAAA,CAAU,IAAM,EAAA,QAAA,CAAA;AAE/B,EAAO,OAAA,KAAA,CAAA;AACX,CAAA;AAEA,SAAS,gBAAA,CAAiB,WAAmC,EAAA,GAAA,EAA0B,KACvF,EAAA;AACI,EAAA,IAAI,CAAC,WAAA;AAAa,IAAO,OAAA,KAAA,CAAA;AAEzB,EAAQ,KAAA,GAAA,eAAA,CAAgB,WAAa,EAAA,GAAA,EAAK,KAAK,CAAA,CAAA;AAE/C,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,WAAY,CAAA,KAAA,CAAA;AAC3B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,WAAY,CAAA,SAAA,CAAA;AAC3B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,WAAY,CAAA,GAAA,CAAA;AAC3B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,WAAY,CAAA,IAAA,CAAA;AAC3B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,WAAY,CAAA,UAAA,CAAA;AAE3B,EAAO,OAAA,KAAA,CAAA;AACX,CAAA;AAEA,SAAS,gBAAA,CAAiB,UAAqC,EAAA,GAAA,EAA0B,KACzF,EAAA;AACI,EAAA,IAAI,CAAC,UAAA;AAAY,IAAO,OAAA,KAAA,CAAA;AAExB,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,UAAW,CAAA,KAAA,CAAA;AAC1B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,UAAW,CAAA,KAAA,CAAA;AAC1B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,UAAW,CAAA,IAAA,CAAA;AAC1B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,UAAW,CAAA,QAAA,CAAA;AAC1B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAIA,WAAM,CAAA,MAAA,CAAO,SAAS,UAAW,CAAA,KAAK,EAAE,QAAS,EAAA,CAAA;AAEhE,EAAO,OAAA,KAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,66 @@
import { Color } from '../../../color/Color.mjs';
"use strict";
const valuesToIterateForKeys = [
"align",
"breakWords",
"cssOverrides",
"fontVariant",
"fontWeight",
"leading",
"letterSpacing",
"lineHeight",
"padding",
"textBaseline",
"trim",
"whiteSpace",
"wordWrap",
"wordWrapWidth",
"fontFamily",
"fontStyle",
"fontSize"
];
function generateTextStyleKey(style) {
const key = [];
let index = 0;
for (let i = 0; i < valuesToIterateForKeys.length; i++) {
const prop = `_${valuesToIterateForKeys[i]}`;
key[index++] = style[prop];
}
index = addFillStyleKey(style._fill, key, index);
index = addStokeStyleKey(style._stroke, key, index);
index = addDropShadowKey(style.dropShadow, key, index);
return key.join("-");
}
function addFillStyleKey(fillStyle, key, index) {
if (!fillStyle)
return index;
key[index++] = fillStyle.color;
key[index++] = fillStyle.alpha;
key[index++] = fillStyle.fill?.styleKey;
return index;
}
function addStokeStyleKey(strokeStyle, key, index) {
if (!strokeStyle)
return index;
index = addFillStyleKey(strokeStyle, key, index);
key[index++] = strokeStyle.width;
key[index++] = strokeStyle.alignment;
key[index++] = strokeStyle.cap;
key[index++] = strokeStyle.join;
key[index++] = strokeStyle.miterLimit;
return index;
}
function addDropShadowKey(dropShadow, key, index) {
if (!dropShadow)
return index;
key[index++] = dropShadow.alpha;
key[index++] = dropShadow.angle;
key[index++] = dropShadow.blur;
key[index++] = dropShadow.distance;
key[index++] = Color.shared.setValue(dropShadow.color).toNumber();
return index;
}
export { generateTextStyleKey };
//# sourceMappingURL=generateTextStyleKey.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"generateTextStyleKey.mjs","sources":["../../../../src/scene/text/utils/generateTextStyleKey.ts"],"sourcesContent":["import { Color } from '../../../color/Color';\n\nimport type { ConvertedFillStyle, ConvertedStrokeStyle } from '../../graphics/shared/FillTypes';\nimport type { HTMLTextStyle } from '../../text-html/HtmlTextStyle';\nimport type { TextStyle } from '../TextStyle';\n\nconst valuesToIterateForKeys: Partial<keyof TextStyle | keyof HTMLTextStyle>[] = [\n 'align',\n 'breakWords',\n 'cssOverrides',\n 'fontVariant',\n 'fontWeight',\n 'leading',\n 'letterSpacing',\n 'lineHeight',\n 'padding',\n 'textBaseline',\n 'trim',\n 'whiteSpace',\n 'wordWrap',\n 'wordWrapWidth',\n 'fontFamily',\n 'fontStyle',\n 'fontSize',\n] as const;\n\n/**\n * Generates a unique key for the text style.\n * @param style - The style to generate a key for.\n * @returns the key for the style.\n */\nexport function generateTextStyleKey(style: TextStyle): string\n{\n const key = [];\n\n let index = 0;\n\n for (let i = 0; i < valuesToIterateForKeys.length; i++)\n {\n const prop = `_${valuesToIterateForKeys[i]}`;\n\n key[index++] = style[prop as keyof typeof style];\n }\n\n index = addFillStyleKey(style._fill, key as string[], index);\n index = addStokeStyleKey(style._stroke, key as string[], index);\n index = addDropShadowKey(style.dropShadow, key as string[], index);\n\n return key.join('-');\n}\n\nfunction addFillStyleKey(fillStyle: ConvertedFillStyle, key: (number | string)[], index: number)\n{\n if (!fillStyle) return index;\n\n key[index++] = fillStyle.color;\n key[index++] = fillStyle.alpha;\n key[index++] = fillStyle.fill?.styleKey;\n\n return index;\n}\n\nfunction addStokeStyleKey(strokeStyle: ConvertedStrokeStyle, key: (number | string)[], index: number)\n{\n if (!strokeStyle) return index;\n\n index = addFillStyleKey(strokeStyle, key, index);\n\n key[index++] = strokeStyle.width;\n key[index++] = strokeStyle.alignment;\n key[index++] = strokeStyle.cap;\n key[index++] = strokeStyle.join;\n key[index++] = strokeStyle.miterLimit;\n\n return index;\n}\n\nfunction addDropShadowKey(dropShadow: TextStyle['dropShadow'], key: (number | string)[], index: number)\n{\n if (!dropShadow) return index;\n\n key[index++] = dropShadow.alpha;\n key[index++] = dropShadow.angle;\n key[index++] = dropShadow.blur;\n key[index++] = dropShadow.distance;\n key[index++] = Color.shared.setValue(dropShadow.color).toNumber();\n\n return index;\n}\n"],"names":[],"mappings":";;;AAMA,MAAM,sBAA2E,GAAA;AAAA,EAC7E,OAAA;AAAA,EACA,YAAA;AAAA,EACA,cAAA;AAAA,EACA,aAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAA;AAAA,EACA,cAAA;AAAA,EACA,MAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AACJ,CAAA,CAAA;AAOO,SAAS,qBAAqB,KACrC,EAAA;AACI,EAAA,MAAM,MAAM,EAAC,CAAA;AAEb,EAAA,IAAI,KAAQ,GAAA,CAAA,CAAA;AAEZ,EAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,sBAAA,CAAuB,QAAQ,CACnD,EAAA,EAAA;AACI,IAAA,MAAM,IAAO,GAAA,CAAA,CAAA,EAAI,sBAAuB,CAAA,CAAC,CAAC,CAAA,CAAA,CAAA;AAE1C,IAAI,GAAA,CAAA,KAAA,EAAO,CAAI,GAAA,KAAA,CAAM,IAA0B,CAAA,CAAA;AAAA,GACnD;AAEA,EAAA,KAAA,GAAQ,eAAgB,CAAA,KAAA,CAAM,KAAO,EAAA,GAAA,EAAiB,KAAK,CAAA,CAAA;AAC3D,EAAA,KAAA,GAAQ,gBAAiB,CAAA,KAAA,CAAM,OAAS,EAAA,GAAA,EAAiB,KAAK,CAAA,CAAA;AAC9D,EAAA,KAAA,GAAQ,gBAAiB,CAAA,KAAA,CAAM,UAAY,EAAA,GAAA,EAAiB,KAAK,CAAA,CAAA;AAEjE,EAAO,OAAA,GAAA,CAAI,KAAK,GAAG,CAAA,CAAA;AACvB,CAAA;AAEA,SAAS,eAAA,CAAgB,SAA+B,EAAA,GAAA,EAA0B,KAClF,EAAA;AACI,EAAA,IAAI,CAAC,SAAA;AAAW,IAAO,OAAA,KAAA,CAAA;AAEvB,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,SAAU,CAAA,KAAA,CAAA;AACzB,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,SAAU,CAAA,KAAA,CAAA;AACzB,EAAI,GAAA,CAAA,KAAA,EAAO,CAAI,GAAA,SAAA,CAAU,IAAM,EAAA,QAAA,CAAA;AAE/B,EAAO,OAAA,KAAA,CAAA;AACX,CAAA;AAEA,SAAS,gBAAA,CAAiB,WAAmC,EAAA,GAAA,EAA0B,KACvF,EAAA;AACI,EAAA,IAAI,CAAC,WAAA;AAAa,IAAO,OAAA,KAAA,CAAA;AAEzB,EAAQ,KAAA,GAAA,eAAA,CAAgB,WAAa,EAAA,GAAA,EAAK,KAAK,CAAA,CAAA;AAE/C,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,WAAY,CAAA,KAAA,CAAA;AAC3B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,WAAY,CAAA,SAAA,CAAA;AAC3B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,WAAY,CAAA,GAAA,CAAA;AAC3B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,WAAY,CAAA,IAAA,CAAA;AAC3B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,WAAY,CAAA,UAAA,CAAA;AAE3B,EAAO,OAAA,KAAA,CAAA;AACX,CAAA;AAEA,SAAS,gBAAA,CAAiB,UAAqC,EAAA,GAAA,EAA0B,KACzF,EAAA;AACI,EAAA,IAAI,CAAC,UAAA;AAAY,IAAO,OAAA,KAAA,CAAA;AAExB,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,UAAW,CAAA,KAAA,CAAA;AAC1B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,UAAW,CAAA,KAAA,CAAA;AAC1B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,UAAW,CAAA,IAAA,CAAA;AAC1B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,UAAW,CAAA,QAAA,CAAA;AAC1B,EAAI,GAAA,CAAA,KAAA,EAAO,IAAI,KAAM,CAAA,MAAA,CAAO,SAAS,UAAW,CAAA,KAAK,EAAE,QAAS,EAAA,CAAA;AAEhE,EAAO,OAAA,KAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,12 @@
import type { ICanvas } from '../../../environment/canvas/ICanvas';
import type { Texture } from '../../../rendering/renderers/shared/texture/Texture';
/**
* Takes an image and creates a texture from it, using a power of 2 texture from the texture pool.
* Remember to return the texture when you don't need it any more!
* @param image - The image to create a texture from
* @param width - the frame width of the texture
* @param height - the frame height of the texture
* @param resolution - The resolution of the texture
* @returns - The texture
*/
export declare function getPo2TextureFromSource(image: HTMLImageElement | HTMLCanvasElement | ICanvas, width: number, height: number, resolution: number): Texture;

View File

@@ -0,0 +1,31 @@
'use strict';
var TexturePool = require('../../../rendering/renderers/shared/texture/TexturePool.js');
var Bounds = require('../../container/bounds/Bounds.js');
"use strict";
const tempBounds = new Bounds.Bounds();
function getPo2TextureFromSource(image, width, height, resolution) {
const bounds = tempBounds;
bounds.minX = 0;
bounds.minY = 0;
bounds.maxX = image.width / resolution | 0;
bounds.maxY = image.height / resolution | 0;
const texture = TexturePool.TexturePool.getOptimalTexture(
bounds.width,
bounds.height,
resolution,
false
);
texture.source.uploadMethodId = "image";
texture.source.resource = image;
texture.source.alphaMode = "premultiply-alpha-on-upload";
texture.frame.width = width / resolution;
texture.frame.height = height / resolution;
texture.source.emit("update", texture.source);
texture.updateUvs();
return texture;
}
exports.getPo2TextureFromSource = getPo2TextureFromSource;
//# sourceMappingURL=getPo2TextureFromSource.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getPo2TextureFromSource.js","sources":["../../../../src/scene/text/utils/getPo2TextureFromSource.ts"],"sourcesContent":["import { TexturePool } from '../../../rendering/renderers/shared/texture/TexturePool';\nimport { Bounds } from '../../container/bounds/Bounds';\n\nimport type { ICanvas } from '../../../environment/canvas/ICanvas';\nimport type { Texture } from '../../../rendering/renderers/shared/texture/Texture';\n\nconst tempBounds = new Bounds();\n\n/**\n * Takes an image and creates a texture from it, using a power of 2 texture from the texture pool.\n * Remember to return the texture when you don't need it any more!\n * @param image - The image to create a texture from\n * @param width - the frame width of the texture\n * @param height - the frame height of the texture\n * @param resolution - The resolution of the texture\n * @returns - The texture\n */\nexport function getPo2TextureFromSource(\n image: HTMLImageElement | HTMLCanvasElement | ICanvas,\n width: number,\n height: number,\n resolution: number\n): Texture\n{\n const bounds = tempBounds;\n\n bounds.minX = 0;\n bounds.minY = 0;\n\n bounds.maxX = (image.width / resolution) | 0;\n bounds.maxY = (image.height / resolution) | 0;\n\n const texture = TexturePool.getOptimalTexture(\n bounds.width,\n bounds.height,\n resolution,\n false\n );\n\n texture.source.uploadMethodId = 'image';\n texture.source.resource = image;\n texture.source.alphaMode = 'premultiply-alpha-on-upload';\n\n texture.frame.width = width / resolution;\n texture.frame.height = height / resolution;\n\n // We want to update the resource on the GPU,\n // but we do not want to resize the texture.\n // calling `texture.source.update` will fit the resource to the texture\n // causing a resize of the texture on the GPU.\n // which is not what we want!\n texture.source.emit('update', texture.source);\n\n texture.updateUvs();\n\n return texture;\n}\n"],"names":["Bounds","TexturePool"],"mappings":";;;;;;AAMA,MAAM,UAAA,GAAa,IAAIA,aAAO,EAAA,CAAA;AAWvB,SAAS,uBACZ,CAAA,KAAA,EACA,KACA,EAAA,MAAA,EACA,UAEJ,EAAA;AACI,EAAA,MAAM,MAAS,GAAA,UAAA,CAAA;AAEf,EAAA,MAAA,CAAO,IAAO,GAAA,CAAA,CAAA;AACd,EAAA,MAAA,CAAO,IAAO,GAAA,CAAA,CAAA;AAEd,EAAO,MAAA,CAAA,IAAA,GAAQ,KAAM,CAAA,KAAA,GAAQ,UAAc,GAAA,CAAA,CAAA;AAC3C,EAAO,MAAA,CAAA,IAAA,GAAQ,KAAM,CAAA,MAAA,GAAS,UAAc,GAAA,CAAA,CAAA;AAE5C,EAAA,MAAM,UAAUC,uBAAY,CAAA,iBAAA;AAAA,IACxB,MAAO,CAAA,KAAA;AAAA,IACP,MAAO,CAAA,MAAA;AAAA,IACP,UAAA;AAAA,IACA,KAAA;AAAA,GACJ,CAAA;AAEA,EAAA,OAAA,CAAQ,OAAO,cAAiB,GAAA,OAAA,CAAA;AAChC,EAAA,OAAA,CAAQ,OAAO,QAAW,GAAA,KAAA,CAAA;AAC1B,EAAA,OAAA,CAAQ,OAAO,SAAY,GAAA,6BAAA,CAAA;AAE3B,EAAQ,OAAA,CAAA,KAAA,CAAM,QAAQ,KAAQ,GAAA,UAAA,CAAA;AAC9B,EAAQ,OAAA,CAAA,KAAA,CAAM,SAAS,MAAS,GAAA,UAAA,CAAA;AAOhC,EAAA,OAAA,CAAQ,MAAO,CAAA,IAAA,CAAK,QAAU,EAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAE5C,EAAA,OAAA,CAAQ,SAAU,EAAA,CAAA;AAElB,EAAO,OAAA,OAAA,CAAA;AACX;;;;"}

View File

@@ -0,0 +1,29 @@
import { TexturePool } from '../../../rendering/renderers/shared/texture/TexturePool.mjs';
import { Bounds } from '../../container/bounds/Bounds.mjs';
"use strict";
const tempBounds = new Bounds();
function getPo2TextureFromSource(image, width, height, resolution) {
const bounds = tempBounds;
bounds.minX = 0;
bounds.minY = 0;
bounds.maxX = image.width / resolution | 0;
bounds.maxY = image.height / resolution | 0;
const texture = TexturePool.getOptimalTexture(
bounds.width,
bounds.height,
resolution,
false
);
texture.source.uploadMethodId = "image";
texture.source.resource = image;
texture.source.alphaMode = "premultiply-alpha-on-upload";
texture.frame.width = width / resolution;
texture.frame.height = height / resolution;
texture.source.emit("update", texture.source);
texture.updateUvs();
return texture;
}
export { getPo2TextureFromSource };
//# sourceMappingURL=getPo2TextureFromSource.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getPo2TextureFromSource.mjs","sources":["../../../../src/scene/text/utils/getPo2TextureFromSource.ts"],"sourcesContent":["import { TexturePool } from '../../../rendering/renderers/shared/texture/TexturePool';\nimport { Bounds } from '../../container/bounds/Bounds';\n\nimport type { ICanvas } from '../../../environment/canvas/ICanvas';\nimport type { Texture } from '../../../rendering/renderers/shared/texture/Texture';\n\nconst tempBounds = new Bounds();\n\n/**\n * Takes an image and creates a texture from it, using a power of 2 texture from the texture pool.\n * Remember to return the texture when you don't need it any more!\n * @param image - The image to create a texture from\n * @param width - the frame width of the texture\n * @param height - the frame height of the texture\n * @param resolution - The resolution of the texture\n * @returns - The texture\n */\nexport function getPo2TextureFromSource(\n image: HTMLImageElement | HTMLCanvasElement | ICanvas,\n width: number,\n height: number,\n resolution: number\n): Texture\n{\n const bounds = tempBounds;\n\n bounds.minX = 0;\n bounds.minY = 0;\n\n bounds.maxX = (image.width / resolution) | 0;\n bounds.maxY = (image.height / resolution) | 0;\n\n const texture = TexturePool.getOptimalTexture(\n bounds.width,\n bounds.height,\n resolution,\n false\n );\n\n texture.source.uploadMethodId = 'image';\n texture.source.resource = image;\n texture.source.alphaMode = 'premultiply-alpha-on-upload';\n\n texture.frame.width = width / resolution;\n texture.frame.height = height / resolution;\n\n // We want to update the resource on the GPU,\n // but we do not want to resize the texture.\n // calling `texture.source.update` will fit the resource to the texture\n // causing a resize of the texture on the GPU.\n // which is not what we want!\n texture.source.emit('update', texture.source);\n\n texture.updateUvs();\n\n return texture;\n}\n"],"names":[],"mappings":";;;;AAMA,MAAM,UAAA,GAAa,IAAI,MAAO,EAAA,CAAA;AAWvB,SAAS,uBACZ,CAAA,KAAA,EACA,KACA,EAAA,MAAA,EACA,UAEJ,EAAA;AACI,EAAA,MAAM,MAAS,GAAA,UAAA,CAAA;AAEf,EAAA,MAAA,CAAO,IAAO,GAAA,CAAA,CAAA;AACd,EAAA,MAAA,CAAO,IAAO,GAAA,CAAA,CAAA;AAEd,EAAO,MAAA,CAAA,IAAA,GAAQ,KAAM,CAAA,KAAA,GAAQ,UAAc,GAAA,CAAA,CAAA;AAC3C,EAAO,MAAA,CAAA,IAAA,GAAQ,KAAM,CAAA,MAAA,GAAS,UAAc,GAAA,CAAA,CAAA;AAE5C,EAAA,MAAM,UAAU,WAAY,CAAA,iBAAA;AAAA,IACxB,MAAO,CAAA,KAAA;AAAA,IACP,MAAO,CAAA,MAAA;AAAA,IACP,UAAA;AAAA,IACA,KAAA;AAAA,GACJ,CAAA;AAEA,EAAA,OAAA,CAAQ,OAAO,cAAiB,GAAA,OAAA,CAAA;AAChC,EAAA,OAAA,CAAQ,OAAO,QAAW,GAAA,KAAA,CAAA;AAC1B,EAAA,OAAA,CAAQ,OAAO,SAAY,GAAA,6BAAA,CAAA;AAE3B,EAAQ,OAAA,CAAA,KAAA,CAAM,QAAQ,KAAQ,GAAA,UAAA,CAAA;AAC9B,EAAQ,OAAA,CAAA,KAAA,CAAM,SAAS,MAAS,GAAA,UAAA,CAAA;AAOhC,EAAA,OAAA,CAAQ,MAAO,CAAA,IAAA,CAAK,QAAU,EAAA,OAAA,CAAQ,MAAM,CAAA,CAAA;AAE5C,EAAA,OAAA,CAAQ,SAAU,EAAA,CAAA;AAElB,EAAO,OAAA,OAAA,CAAA;AACX;;;;"}