Skip to content
This repository has been archived by the owner on Jul 3, 2019. It is now read-only.

Commit

Permalink
Merge pull request #2276 from tobytailor/text
Browse files Browse the repository at this point in the history
Support negative leading and letter-spacing in text fields.
  • Loading branch information
Tobias Schneider committed Jun 10, 2015
2 parents 42f9566 + 4e567b9 commit d863f71
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 33 deletions.
21 changes: 16 additions & 5 deletions src/TextContent.ts
Expand Up @@ -202,16 +202,22 @@ module Shumway {
var color = ColorUtilities.isValidHexColor(attributes.color) ? ColorUtilities.hexToRGB(attributes.color) : textFormat.color;
var font = attributes.face || textFormat.font;
var size = isNaN(attributes.size) ? textFormat.size : +attributes.size;
var letterSpacing = isNaN(attributes.letterspacing) ? textFormat.letterSpacing : +attributes.letterspacing;
var kerning = isNaN(attributes.kerning) ? textFormat.kerning : +attributes.kerning;
if (color !== textFormat.color ||
font !== textFormat.font ||
size !== textFormat.size)
size !== textFormat.size ||
letterSpacing !== textFormat.letterSpacing ||
kerning !== textFormat.kerning)
{
if (!hasStyle) {
textFormat = textFormat.clone();
}
textFormat.color = color;
textFormat.font = font;
textFormat.size = size;
textFormat.letterSpacing = letterSpacing;
textFormat.kerning = kerning;
}
break;
case 'img':
Expand Down Expand Up @@ -582,14 +588,16 @@ module Shumway {
var shift = newEndIndex - endIndex;
for (var i = 0; i < textRuns.length; i++) {
var run = textRuns[i];
var isLast = i >= textRuns.length - 1;
if (beginIndex < run.endIndex) {
// Skip all following steps (including adding the current run to the new list of runs) if
// the inserted text overlaps the current run.
if (beginIndex <= run.beginIndex && newEndIndex >= run.endIndex) {
// the inserted text overlaps the current run, which is not the last one.
if (!isLast && beginIndex <= run.beginIndex && newEndIndex >= run.endIndex) {
continue;
}
var containsBeginIndex = run.containsIndex(beginIndex);
var containsEndIndex = run.containsIndex(endIndex);
var containsEndIndex = run.containsIndex(endIndex) ||
(isLast && endIndex >= run.endIndex);
if (containsBeginIndex && containsEndIndex) {
// The current run spans over the inserted text.
if (format) {
Expand Down Expand Up @@ -622,7 +630,10 @@ module Shumway {
run.endIndex += shift;
}
}
newTextRuns.push(run);
// Ignore empty runs.
if (run.endIndex > run.beginIndex) {
newTextRuns.push(run);
}
}

this._plainText = plainText.substring(0, beginIndex) + newText + plainText.substring(endIndex);
Expand Down
2 changes: 2 additions & 0 deletions src/flash/text/TextField.ts
Expand Up @@ -128,6 +128,8 @@ module Shumway.AVMX.AS.flash.text {
'',
TextFormatAlign.LEFT
);
defaultTextFormat.letterSpacing = 0;
defaultTextFormat.kerning = 0;
this._textContent = new Shumway.TextContent(this.sec, defaultTextFormat);
}

Expand Down
44 changes: 29 additions & 15 deletions src/flash/text/TextFormat.ts
Expand Up @@ -44,6 +44,13 @@ module Shumway.AVMX.AS.flash.text {
this.rightMargin = rightMargin;
this.indent = indent;
this.leading = leading;

this._blockIndent = null;
this._bullet = null;
this._display = TextFormatDisplay.BLOCK;
this._kerning = null;
this._letterSpacing = null;
this._tabStops = null;
}

private static measureTextField: flash.text.TextField;
Expand Down Expand Up @@ -186,7 +193,7 @@ module Shumway.AVMX.AS.flash.text {
}

set letterSpacing(value: Object) {
this._letterSpacing = TextFormat.coerceBoolean(value);
this._letterSpacing = TextFormat.coerceNumber(value);
}

get rightMargin(): Object {
Expand Down Expand Up @@ -271,21 +278,28 @@ module Shumway.AVMX.AS.flash.text {
}

clone(): TextFormat {
return new this.sec.flash.text.TextFormat(
this.font,
this.size,
this.color,
this.bold,
this.italic,
this.underline,
this.url,
this.target,
this.align,
this.leftMargin,
this.rightMargin,
this.indent,
this.leading
var tf = new this.sec.flash.text.TextFormat(
this._font,
this._size,
this._color,
this._bold,
this._italic,
this._underline,
this._url,
this._target,
this._align,
this._leftMargin,
this._rightMargin,
this._indent,
this._leading
);
tf._blockIndent = this._blockIndent;
tf._bullet = this._bullet;
tf._display = this._display;
tf._kerning = this._kerning;
tf._letterSpacing = this._letterSpacing;
tf._tabStops = this._tabStops;
return tf;
}

public equals(other: TextFormat): boolean {
Expand Down
48 changes: 35 additions & 13 deletions src/gfx/renderables/renderables.ts
Expand Up @@ -1238,12 +1238,13 @@ module Shumway.GFX {
return TextLine._measureContext;
}

addRun(font: string, fillStyle: string, text: string, underline: boolean) {
addRun(font: string, fillStyle: string, text: string,
letterSpacing: number, underline: boolean) {
if (text) {
var measureContext = TextLine._getMeasureContext();
measureContext.font = font;
var width = measureContext.measureText(text).width | 0;
this.runs.push(new TextRun(font, fillStyle, text, width, underline));
var width = measureText(measureContext, text, letterSpacing);
this.runs.push(new TextRun(font, fillStyle, text, width, letterSpacing, underline));
this.width += width;
}
}
Expand All @@ -1270,13 +1271,14 @@ module Shumway.GFX {
for (var j = 0; j < words.length; j++) {
var word = words[j];
var chunk = text.substr(offset, word.length + 1);
var wordWidth = measureContext.measureText(chunk).width | 0;
var letterSpacing = run.letterSpacing;
var wordWidth = measureText(measureContext, chunk, letterSpacing);
if (wordWidth > spaceLeft) {
do {
if (run.text) {
currentLine.runs.push(run);
currentLine.width += run.width;
run = new TextRun(run.font, run.fillStyle, '', 0, run.underline);
run = new TextRun(run.font, run.fillStyle, '', 0, run.letterSpacing, run.underline);
var newLine = new TextLine();
newLine.y = (currentLine.y + currentLine.descent + currentLine.leading + currentLine.ascent) | 0;
newLine.ascent = currentLine.ascent;
Expand All @@ -1294,15 +1296,15 @@ module Shumway.GFX {
while (k > 1) {
k--;
t = chunk.substr(0, k);
w = measureContext.measureText(t).width | 0;
w = measureText(measureContext, t, letterSpacing);
if (w <= maxWidth) {
break;
}
}
run.text = t;
run.width = w;
chunk = chunk.substr(k);
wordWidth = measureContext.measureText(chunk).width | 0;
wordWidth = measureText(measureContext, chunk, letterSpacing);
}
} while (chunk && spaceLeft < 0);
} else {
Expand Down Expand Up @@ -1330,11 +1332,21 @@ module Shumway.GFX {
public fillStyle: string = '',
public text: string = '',
public width: number = 0,
public letterSpacing: number = 0,
public underline: boolean = false)
{

}
}

function measureText(context: CanvasRenderingContext2D, text: string,
letterSpacing: number): number {
var width = context.measureText(text).width | 0;
if (letterSpacing > 0) {
width += text.length * letterSpacing;
}
return width;
}

export class RenderableText extends Renderable {

Expand Down Expand Up @@ -1408,7 +1420,7 @@ module Shumway.GFX {
var maxWidth = 0;
var maxAscent = 0;
var maxDescent = 0;
var maxLeading = 0;
var maxLeading = -0xffffffff;
var firstAlign = -1;

var finishLine = function () {
Expand Down Expand Up @@ -1513,14 +1525,14 @@ module Shumway.GFX {
continue;
}
}
currentLine.addRun(font, fillStyle, text, underline);
currentLine.addRun(font, fillStyle, text, letterSpacing, underline);
finishLine();
text = '';

if (eof) {
maxAscent = 0;
maxDescent = 0;
maxLeading = 0;
maxLeading = -0xffffffff;
firstAlign = -1;
break;
}
Expand All @@ -1529,7 +1541,7 @@ module Shumway.GFX {
i++;
}
}
currentLine.addRun(font, fillStyle, text, underline);
currentLine.addRun(font, fillStyle, text, letterSpacing, underline);
}

// Append an additional empty line if we find a line break character at the end of the text.
Expand Down Expand Up @@ -1725,8 +1737,18 @@ module Shumway.GFX {
if (run.underline) {
context.fillRect(x, (y + (line.descent / 2)) | 0, run.width, 1);
}
context.fillText(run.text, x, y);
x += run.width;
context.textAlign = "left";
context.textBaseline = "alphabetic";
if (run.letterSpacing > 0) {
var text = run.text;
for (var k = 0; k < text.length; k++) {
context.fillText(text[k], x, y);
x += measureText(context, text[k], run.letterSpacing);
}
} else {
context.fillText(run.text, x, y);
x += run.width;
}
}
}
}
Expand Down
Binary file added test/swfs/acid/acid-text-4.fla
Binary file not shown.
Binary file added test/swfs/acid/acid-text-4.swf
Binary file not shown.
5 changes: 5 additions & 0 deletions test/test_manifest.json
Expand Up @@ -149,6 +149,11 @@
"swf": "swfs/acid/acid-text-3.swf",
"type": "eq"
},
{ "id": "acid-text-4",
"frames": [1],
"swf": "swfs/acid/acid-text-4.swf",
"type": "eq"
},
{ "id": "acid-text-6",
"frames": [1, 20],
"swf": "swfs/acid/acid-text-6.swf",
Expand Down

0 comments on commit d863f71

Please sign in to comment.