Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Char spacing #4642

Merged
merged 26 commits into from
May 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a177f04
Fixed nested stencil masks not rendering correctly.
Aug 7, 2017
44fc6ec
Merge branch 'dev' of https://github.com/ceco-fmedia/pixi.js into dev
Aug 7, 2017
d350dfc
Fixed jslint errors.
Aug 8, 2017
208141e
Merge branch 'dev' into dev
ceco-fmedia Aug 8, 2017
9da7205
Merge branch 'dev' into dev
bigtimebuddy Aug 18, 2017
79e7988
Documented the changes.
Aug 19, 2017
d14c7f4
Merge remote-tracking branch 'upstream/dev' into dev
Jan 26, 2018
3287f11
Additional property: letterSpacing in BitmapText to set extra amount …
Jan 26, 2018
53d4cda
Fixed lint errors.
Jan 26, 2018
8f535bb
Fixed _maxWidth used instead of _letterSpacing.
Jan 26, 2018
609ae3f
Merge branch 'char_spacing' of https://github.com/ceco-fmedia/pixi.js…
Jan 26, 2018
c904b9e
Merge branch 'dev' of https://github.com/pixijs/pixi.js into dev
Jan 31, 2018
e1e0d49
Merge branch 'dev' of https://github.com/pixijs/pixi.js into char_spa…
Feb 1, 2018
c38b506
Merge branch 'dev' into char_spacing
Feb 1, 2018
25d0f95
Fixed word not moved to the next line when the next character is space.
Feb 1, 2018
7b3ece1
Break line after the following characters: -\/.,?!;:;
Feb 1, 2018
9875aff
Merge remote-tracking branch 'remotes/upstream/dev' into char_spacing
ceco-fmedia Feb 17, 2018
76bf9fd
Fixed last line width when last character is space.
ceco-fmedia Feb 17, 2018
6c2435c
Fixed typo.
ceco-fmedia Feb 17, 2018
e6351fb
Merge remote-tracking branch 'remotes/upstream/dev' into char_spacing
ceco-fmedia Mar 10, 2018
79b349b
Merge branch 'dev' into char_spacing
ceco-fmedia Mar 10, 2018
eab47d2
Fixed line break characters not incrementing spacesRemoved.
ceco-fmedia Mar 10, 2018
ce8fea3
Merge branch 'char_spacing' of https://github.com/ceco-fmedia/pixi.js…
ceco-fmedia Mar 10, 2018
824cca3
Merge branch 'dev' into char_spacing
bigtimebuddy May 22, 2018
f35fe1d
Merge branch 'dev' into char_spacing
ceco-fmedia May 25, 2018
729f5f7
Merge branch 'dev' into char_spacing
bigtimebuddy May 25, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
100 changes: 70 additions & 30 deletions src/extras/BitmapText.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ export default class BitmapText extends core.Container
*/
this._maxLineHeight = 0;

/**
* Letter spacing. This is useful for setting the space between characters.
* @member {number}
* @private
*/
this._letterSpacing = 0;

/**
* Text anchor. read-only
*
Expand Down Expand Up @@ -140,49 +147,37 @@ export default class BitmapText extends core.Container
const pos = new core.Point();
const chars = [];
const lineWidths = [];
const text = this.text.replace(/(?:\r\n|\r)/g, '\n');
const textLength = text.length;
const maxWidth = this._maxWidth * data.size / this._font.size;

let prevCharCode = null;
let lastLineWidth = 0;
let maxLineWidth = 0;
let line = 0;
let lastSpace = -1;
let lastSpaceWidth = 0;
let lastBreakPos = -1;
let lastBreakWidth = 0;
let spacesRemoved = 0;
let maxLineHeight = 0;

for (let i = 0; i < this.text.length; i++)
for (let i = 0; i < textLength; i++)
{
const charCode = this.text.charCodeAt(i);
const charCode = text.charCodeAt(i);
const char = text.charAt(i);

if (/(\s)/.test(this.text.charAt(i)))
if (/(?:\s)/.test(char))
{
lastSpace = i;
lastSpaceWidth = lastLineWidth;
lastBreakPos = i;
lastBreakWidth = lastLineWidth;
}

if (/(?:\r\n|\r|\n)/.test(this.text.charAt(i)))
if (char === '\r' || char === '\n')
{
lineWidths.push(lastLineWidth);
maxLineWidth = Math.max(maxLineWidth, lastLineWidth);
line++;

pos.x = 0;
pos.y += data.lineHeight;
prevCharCode = null;
continue;
}

if (lastSpace !== -1 && this._maxWidth > 0 && pos.x * scale > this._maxWidth)
{
core.utils.removeItems(chars, lastSpace - spacesRemoved, i - lastSpace);
i = lastSpace;
lastSpace = -1;
++line;
++spacesRemoved;

lineWidths.push(lastSpaceWidth);
maxLineWidth = Math.max(maxLineWidth, lastSpaceWidth);
line++;

pos.x = 0;
pos.y += data.lineHeight;
prevCharCode = null;
Expand All @@ -205,16 +200,42 @@ export default class BitmapText extends core.Container
texture: charData.texture,
line,
charCode,
position: new core.Point(pos.x + charData.xOffset, pos.y + charData.yOffset),
position: new core.Point(pos.x + charData.xOffset + (this._letterSpacing / 2), pos.y + charData.yOffset),
});
lastLineWidth = pos.x + (charData.texture.width + charData.xOffset);
pos.x += charData.xAdvance;
pos.x += charData.xAdvance + this._letterSpacing;
lastLineWidth = pos.x;
maxLineHeight = Math.max(maxLineHeight, (charData.yOffset + charData.texture.height));
prevCharCode = charCode;

if (lastBreakPos !== -1 && maxWidth > 0 && pos.x > maxWidth)
{
++spacesRemoved;
core.utils.removeItems(chars, 1 + lastBreakPos - spacesRemoved, 1 + i - lastBreakPos);
i = lastBreakPos;
lastBreakPos = -1;

lineWidths.push(lastBreakWidth);
maxLineWidth = Math.max(maxLineWidth, lastBreakWidth);
line++;

pos.x = 0;
pos.y += data.lineHeight;
prevCharCode = null;
}
}

lineWidths.push(lastLineWidth);
maxLineWidth = Math.max(maxLineWidth, lastLineWidth);
const lastChar = text.charAt(text.length - 1);

if (lastChar !== '\r' && lastChar !== '\n')
{
if (/(?:\s)/.test(lastChar))
{
lastLineWidth = lastBreakWidth;
}

lineWidths.push(lastLineWidth);
maxLineWidth = Math.max(maxLineWidth, lastLineWidth);
}

const lineAlignOffsets = [];

Expand Down Expand Up @@ -484,6 +505,25 @@ export default class BitmapText extends core.Container
return this._textWidth;
}

/**
* Additional space between characters.
*
* @member {number}
*/
get letterSpacing()
{
return this._letterSpacing;
}

set letterSpacing(value) // eslint-disable-line require-jsdoc
{
if (this._letterSpacing !== value)
{
this._letterSpacing = value;
this.dirty = true;
}
}

/**
* The height of the overall text, different from fontSize,
* which is defined in the style object
Expand Down
104 changes: 104 additions & 0 deletions test/extras/BitmapText.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use strict';

const path = require('path');
const fs = require('fs');

describe('PIXI.extras.BitmapText', function ()
{
before(function (done)
{
this.fontXML = null;
this.fontImage = null;
this.font = null;

const resolveURL = (url) => path.resolve(this.resources, url);
const loadXML = (url) => new Promise((resolve) =>
fs.readFile(resolveURL(url), 'utf8', (err, data) =>
{
expect(err).to.be.null;
resolve((new window.DOMParser()).parseFromString(data, 'text/xml'));
}));

const loadImage = (url) => new Promise((resolve) =>
{
const image = new Image();

image.onload = () => resolve(image);
image.src = resolveURL(url);
});

this.resources = path.join(__dirname, 'resources');
Promise.all([
loadXML('font.fnt'),
loadImage('font.png'),
]).then(([
fontXML,
fontImage,
]) =>
{
this.fontXML = fontXML;
this.fontImage = fontImage;
const texture = new PIXI.Texture(new PIXI.BaseTexture(this.fontImage, null, 1));

this.font = PIXI.extras.BitmapText.registerFont(this.fontXML, texture);
done();
});
});

describe('text', function ()
{
it('should render text even if there are unsupported characters', function ()
{
const text = new PIXI.extras.BitmapText('ABCDEFG', {
font: this.font.font,
});

expect(text.children.length).to.equal(4);
});
it('should break line on space', function ()
{
const bmpText = new PIXI.extras.BitmapText('', {
font: this.font.font,
size: 24,
});

bmpText.maxWidth = 40;
bmpText.text = 'A A A A A A A ';
bmpText.updateText();

expect(bmpText.textWidth).to.lessThan(bmpText.maxWidth);

bmpText.maxWidth = 40;
bmpText.text = 'A A A A A A A';
bmpText.updateText();

expect(bmpText.textWidth).to.lessThan(bmpText.maxWidth);
});
it('letterSpacing should add extra space between characters', function ()
{
const text = 'ABCD zz DCBA';
const bmpText = new PIXI.extras.BitmapText(text, {
font: this.font.font,
});
const positions = [];
const renderedChars = bmpText.children.length;

for (let x = 0; x < renderedChars; ++x)
{
positions.push(bmpText.children[x].x);
}
for (let space = 1; space < 20; ++space)
{
bmpText.letterSpacing = space;
bmpText.updateText();
let prevPos = bmpText.children[0].x;

for (let char = 1; char < renderedChars; ++char)
{
expect(bmpText.children[char].x).to.equal(prevPos + space + positions[char] - positions[char - 1]);
prevPos = bmpText.children[char].x;
}
}
});
});
});
3 changes: 3 additions & 0 deletions test/extras/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'use strict';

require('./BitmapText');
29 changes: 29 additions & 0 deletions test/extras/resources/font.fnt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<font>
<info face="font" size="24" bold="0" italic="0" charset="" unicode="" stretchH="100" smooth="1" aa="1" padding="2,2,2,2" spacing="0,0" outline="0"/>
<common lineHeight="27" base="18" scaleW="46" scaleH="201" pages="1" packed="0"/>
<pages>
<page id="0" file="font.png"/>
</pages>
<chars count="15">
<char id="65" x="2" y="2" width="19" height="20" xoffset="0" yoffset="0" xadvance="16" page="0" chnl="15"/>
<char id="66" x="2" y="24" width="15" height="20" xoffset="2" yoffset="0" xadvance="16" page="0" chnl="15"/>
<char id="67" x="2" y="46" width="18" height="20" xoffset="1" yoffset="0" xadvance="17" page="0" chnl="15"/>
<char id="68" x="19" y="24" width="17" height="20" xoffset="2" yoffset="0" xadvance="17" page="0" chnl="15"/>
<char id="91" x="2" y="68" width="7" height="24" xoffset="2" yoffset="0" xadvance="7" page="0" chnl="15"/>
<char id="45" x="23" y="2" width="9" height="4" xoffset="1" yoffset="10" xadvance="8" page="0" chnl="15"/>
<char id="92" x="34" y="2" width="10" height="20" xoffset="-1" yoffset="0" xadvance="7" page="0" chnl="15"/>
<char id="47" x="2" y="94" width="10" height="20" xoffset="-1" yoffset="0" xadvance="7" page="0" chnl="15"/>
<char id="46" x="23" y="8" width="5" height="5" xoffset="2" yoffset="15" xadvance="7" page="0" chnl="15"/>
<char id="44" x="11" y="68" width="5" height="8" xoffset="2" yoffset="15" xadvance="7" page="0" chnl="15"/>
<char id="63" x="2" y="116" width="13" height="20" xoffset="1" yoffset="0" xadvance="13" page="0" chnl="15"/>
<char id="33" x="14" y="78" width="5" height="20" xoffset="2" yoffset="0" xadvance="7" page="0" chnl="15"/>
<char id="59" x="2" y="138" width="5" height="18" xoffset="2" yoffset="5" xadvance="7" page="0" chnl="15"/>
<char id="58" x="2" y="158" width="5" height="15" xoffset="2" yoffset="5" xadvance="7" page="0" chnl="15"/>
<char id="93" x="2" y="175" width="7" height="24" xoffset="0" yoffset="0" xadvance="7" page="0" chnl="15"/>
<char id="32" x="0" y="0" width="0" height="0" xoffset="0" yoffset="0" xadvance="7" page="0" chnl="15"/>
</chars>
<kernings count="2">
<kerning first="32" second="65" amount="-1"/>
<kerning first="65" second="32" amount="-1"/>
</kernings>
</font>
Binary file added test/extras/resources/font.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ describe('PIXI', function ()
require('./loaders');
require('./renders');
require('./prepare');
require('./extras');
});