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 #687 from yurydelendik/fonts-1
Browse files Browse the repository at this point in the history
Fixes font leading/metrics; hacks to resolve font face
  • Loading branch information
yurydelendik committed Sep 19, 2013
2 parents ce35c9f + 6a16c52 commit 26c032b
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 31 deletions.
19 changes: 15 additions & 4 deletions src/flash/display/Loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,7 @@ var LoaderDefinition = (function () {
if (charset) {
style.insertRule(
'@font-face{' +
'font-family:"' + symbol.name + '";' +
'font-family:"' + symbol.uniqueName + '";' +
'src:url(data:font/opentype;base64,' + btoa(symbol.data) + ')' +
'}',
style.cssRules.length
Expand All @@ -921,7 +921,7 @@ var LoaderDefinition = (function () {
var testDiv = document.createElement('div');
testDiv.setAttribute('style', 'position: absolute; top: 0; right: 0;' +
'visibility: hidden; z-index: -500;' +
'font-family:"' + symbol.name + '";');
'font-family:"' + symbol.uniqueName + '";');
testDiv.textContent = 'font test';
document.body.appendChild(testDiv);

Expand All @@ -932,9 +932,13 @@ var LoaderDefinition = (function () {
}, 200);
promiseQueue.push(fontPromise);
}

className = 'flash.text.Font';
}
className = 'flash.text.Font';
props.name = symbol.name;
props.uniqueName = symbol.uniqueName;
props.charset = symbol.charset;
props.metrics = symbol.metrics;
this._registerFont(className, props);
break;
case 'image':
var img = new Image();
Expand Down Expand Up @@ -1084,6 +1088,13 @@ var LoaderDefinition = (function () {
});
});
},
_registerFont: function (className, props) {
this._vmPromise.then(function () {
var fontClass = avm2.applicationDomain.getClass(className);
var font = fontClass.createAsSymbol(props);
fontClass.instanceConstructor.call(font);
});
},
_init: function (info) {
var loader = this;
var loaderInfo = loader.contentLoaderInfo;
Expand Down
20 changes: 17 additions & 3 deletions src/flash/text/Font.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@
*/

var FontDefinition = (function () {
var fonts = [];

var def = {
__class__: 'flash.text.Font',

initialize: function () {
var s = this.symbol;
if (s) {
this._fontName = s.name || null;
this._uniqueName = s.uniqueName;
this._metrics = s.metrics;
fonts.push(this);
}
},

Expand All @@ -41,14 +46,22 @@ var FontDefinition = (function () {
},
};

function enumerateFonts() {
return []; // TODO
function enumerateFonts(device) {
return fonts.slice();
}

function registerFont(font) {
throw 'Not implemented: registerFont';
}

function findFont(fn) {
var font;
fonts.some(function (f) {
return fn(f) && (font = f, true);
});
return font;
}

var desc = Object.getOwnPropertyDescriptor;

def.__glue__ = {
Expand All @@ -61,7 +74,8 @@ var FontDefinition = (function () {
},
static: {
enumerateFonts: enumerateFonts,
registerFont: registerFont
registerFont: registerFont,
_findFont: findFont
}
}
};
Expand Down
67 changes: 51 additions & 16 deletions src/flash/text/TextField.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ var TextFieldDefinition = (function () {
// The outermost node is always a <P>, with an ALIGN attribute
var trunk = {type: 'P', format: {ALIGN: initialFormat.align}, children: []};
// The first child is then a <FONT>, with FACE, LETTERSPACING and KERNING
var fontAttributes = { FACE: initialFormat.font,
var fontAttributes = { FACE: initialFormat.face,
LETTERSPACING: initialFormat.letterSpacing,
KERNING: initialFormat.kerning,
LEADING: initialFormat.leading
Expand Down Expand Up @@ -282,23 +282,27 @@ var TextFieldDefinition = (function () {
}
function addTextRun(state, text, width) {
// `y` is set by `finishLine`
var run = {type: 't', text: text, x: state.x, y: 0};
var size = state.currentFormat.size;
var run = {type: 't', text: text, x: state.x, y: 0, size: size};
state.runs.push(run);
state.line.push(run);
state.x += width;
if (state.currentFormat.size > state.lineHeight) {
state.lineHeight = state.currentFormat.size;
if (size > state.lineHeight) {
state.lineHeight = size;
}
}
function finishLine(state) {
if (state.lineHeight === 0) {
return;
}
state.y += state.lineHeight;
var fontLeading = state.currentFormat.metrics ? state.currentFormat.metrics.leading : 0;
state.y += state.lineHeight - fontLeading;
var y = state.y;
var runs = state.line;
for (var i = runs.length; i--;) {
runs[i].y = y;
var run, i;
for (i = runs.length; i--;) {
run = runs[i];
run.y = y;
}
var align = (state.currentFormat.align || '').toLowerCase();
if (state.combinedAlign === null) {
Expand Down Expand Up @@ -327,6 +331,7 @@ var TextFieldDefinition = (function () {
function pushFormat(state, node) {
var attributes = node.format;
var format = Object.create(state.formats[state.formats.length - 1]);
var metricsChanged = false;
switch (node.type) {
case 'P':
if (attributes.ALIGN === format.align) {
Expand All @@ -341,10 +346,12 @@ var TextFieldDefinition = (function () {
format.color = attributes.COLOR;
}
if ('FACE' in attributes) {
format.face = convertFontFamily(attributes.FACE);
format.face = convertFontFamily(attributes.FACE, true);
metricsChanged = true;
}
if ('SIZE' in attributes) {
format.size = parseFloat(attributes.SIZE);
metricsChanged = true;
}
if ('LETTERSPACING' in attributes) {
format.letterspacing = parseFloat(attributes.LETTERSPACING);
Expand Down Expand Up @@ -372,6 +379,9 @@ var TextFieldDefinition = (function () {
format.color = rgbIntAlphaToStr(state.textColor, 1);
}
format.str = makeFormatString(format);
if (metricsChanged) {
updateFontMetrics(format);
}
state.formats.push(format);
state.runs.push({type: 'f', format: format});
state.currentFormat = format;
Expand All @@ -387,16 +397,16 @@ var TextFieldDefinition = (function () {
//TODO: verify that px is the right unit
// order of the font arguments: <style> <weight> <size> <family>
var boldItalic = '';
if (format.bold) {
boldItalic = 'bold';
}
if (format.italic) {
boldItalic += ' italic';
boldItalic += 'italic';
}
if (format.bold) {
boldItalic += ' bold';
}
return boldItalic + format.size + 'px ' + format.face;
}

function convertFontFamily(face) {
function convertFontFamily(face, translateToUnique) {
//TODO: adapt to embedded font names
var family;
if (face.indexOf('_') === 0) {
Expand All @@ -408,17 +418,40 @@ var TextFieldDefinition = (function () {
} else if (face.indexOf('_typewriter') === 0) {
family = 'monospace';
}
} else if (translateToUnique) {
var font = flash.text.Font.class.native.static._findFont(function (f) {
return f._fontName === face;
});
if (font) {
family = font._uniqueName;
}
}
return family || face;
}

function updateFontMetrics(format) {
var font = flash.text.Font.class.native.static._findFont(function (f) {
return f._uniqueName === format.face;
});
var metrics = font && font._metrics;
if (!metrics) {
format.metrics = null;
return;
}
format.metrics = {
leading: format.size * metrics.leading,
ascent: format.size * metrics.ascent,
descent: format.size * metrics.descent
};
}

var def = {
__class__: 'flash.text.TextField',

initialize: function () {
var initialFormat = this._defaultTextFormat = {
align: 'LEFT', font: 'serif', size: 12,
letterspacing: 0, kerning: 0, color: "black", leading: 2
align: 'LEFT', face: 'serif', size: 12,
letterspacing: 0, kerning: 0, color: "black", leading: 0
};
this._type = 'dynamic';
this._selectable = true;
Expand Down Expand Up @@ -458,7 +491,7 @@ var TextFieldDefinition = (function () {
initialFormat.color = rgbaObjToStr(tag.color);
}
if (tag.hasFont) {
initialFormat.font = convertFontFamily(tag.font);
initialFormat.face = convertFontFamily(tag.font);
}
initialFormat.str = makeFormatString(initialFormat);

Expand All @@ -475,6 +508,8 @@ var TextFieldDefinition = (function () {
this._border = !!tag.border;
// TODO: Find out how the IDE causes textfields to have a background

updateFontMetrics(initialFormat);

if (tag.initialText) {
if (tag.html) {
this.htmlText = tag.initialText;
Expand Down
21 changes: 15 additions & 6 deletions src/swf/font.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ function defineFont(tag, dictionary) {
ranges.push([UAC_OFFSET, UAC_OFFSET + glyphCount - 1, indices]);
}

var ascent = tag.ascent || 1024;
var descent = tag.descent || 1024;
var ascent = Math.ceil(tag.ascent / 20) || 1024;
var descent = -Math.ceil(tag.descent / 20) || 0;
var leading = Math.floor(tag.leading / 20) || 0;
tables['OS/2'] =
'\x00\x01' + // version
'\x00\x00' + // xAvgCharWidth
Expand Down Expand Up @@ -109,9 +110,9 @@ function defineFont(tag, dictionary) {
toString16(codes[codes.length - 1]) + // usLastCharIndex
toString16(ascent) + // sTypoAscender
toString16(descent) + // sTypoDescender
'\x00\x00' + // sTypoLineGap
toString16(leading) + // sTypoLineGap
toString16(ascent) + // usWinAscent
toString16(descent) + // usWinDescent
toString16(-descent) + // usWinDescent
'\x00\x00\x00\x00' + // ulCodePageRange1
'\x00\x00\x00\x00' // ulCodePageRange2
;
Expand Down Expand Up @@ -327,7 +328,7 @@ function defineFont(tag, dictionary) {
'\x00\x01\x00\x00' + // version
toString16(ascent) + // ascender
toString16(descent) + // descender
'\x00\x00' + // lineGap
toString16(leading) + // lineGap
toString16(advance ? max.apply(null, advance) : 1024) + // advanceWidthMax
'\x00\x00' + // minLeftSidebearing
'\x00\x00' + // minRightSidebearing
Expand Down Expand Up @@ -474,12 +475,20 @@ function defineFont(tag, dictionary) {
offset += length;
}
var otf = header + data;
var unitPerEm = 1024;
var metrics = {
ascent: ascent / unitPerEm,
descent: descent / unitPerEm,
leading: leading / unitPerEm
};

return {
type: 'font',
id: tag.id,
name: psName + uniqueId,
name: fontName,
uniqueName: psName + uniqueId,
codes: codes,
metrics: metrics,
data: otf
};
}
2 changes: 1 addition & 1 deletion src/swf/label.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function defineLabel(tag, dictionary) {
var font = dictionary[record.fontId];
assert(font, 'undefined font', 'label');
codes = font.codes;
cmds.push('c.font="' + record.fontHeight + 'px \'' + font.name + '\'"');
cmds.push('c.font="' + record.fontHeight + 'px \'' + font.uniqueName + '\'"');
dependencies.push(font.id);
}

Expand Down
2 changes: 1 addition & 1 deletion src/swf/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function defineText(tag, dictionary) {
if (tag.hasFont) {
var font = dictionary[tag.fontId];
assert(font, 'undefined font', 'label');
tag.font = font.name;
tag.font = font.uniqueName;
dependencies.push(font.id);
}

Expand Down

0 comments on commit 26c032b

Please sign in to comment.