diff --git a/lib/text/loading.js b/lib/text/loading.js index c2f8cee..2a33758 100644 --- a/lib/text/loading.js +++ b/lib/text/loading.js @@ -5,6 +5,7 @@ var domain = require('domain'); var fs = require('fs'); var util = require('util'); +var async = require('async'); var vg = require('openvg'); var ft = require('./freetype'); @@ -115,139 +116,154 @@ var loadFont = loading.loadFont = function (fontBuffer, callback) { f.characterMap = new Array(MAX_PRELOADED_CHARACTER + 1); var glyphs = 0; - for (var cc = 0; cc <= MAX_PRELOADED_CHARACTER; cc++) { - f.characterMap[cc] = -1; // initially nonexistent - - if (cc < 32) continue; // discard the first 32 characters - - var glyphIndex = ft.getCharIndex(face, cc); - - ft.loadGlyph(face, - glyphIndex, - ft.LOAD_NO_BITMAP | ft.LOAD_NO_HINTING | ft.LOAD_IGNORE_TRANSFORM); - - var path = vg.createPath(vg.VG_PATH_FORMAT_STANDARD, - vg.VGPathDatatype.VG_PATH_DATATYPE_S_32, - 1.0 / 65536.0 /* scale */, - 0.0 /* bias */, - 0, 0, /* segment, capacity hints */ - vg.VGPathCapabilities.VG_PATH_CAPABILITY_ALL); - f.glyphs[glyphs] = path; - f.characterMap[cc] = glyphs++; - - f.glyphAdvances.push(scaleOut(scaleIn(face.glyph.advance.x))); - - var outline = face.glyph.outline; - if (cc == 32) { - gpvecindices.push(gpvec.length); - givecindices.push(givec.length); - - gpvecsizes.push(0); - givecsizes.push(0); - - gbbox.push({ minX: 0, minY: 0, maxX: 0, maxY: 0 }); - - continue; - } - - var pvec = []; - var ivec = []; - var minX = 10000000.0, minY = 100000000.0, maxX = -10000000.0, maxY = -10000000.0; - var s = 0, e; - var on; - var last, v, nv; - for (var con = 0; con < outline.nContours; ++con) { - var pnts = 1; - e = outline.contours[con] + 1; - last = scaleInVector(toVector(outline.points, s)); - - // read the contour start point - ivec.push(vg.VGPathCommand.VG_MOVE_TO_ABS); - pushPoint(pvec, last); - - i = s + 1; - while (i <= e) { - var c = (i == e) ? s : i; - var n = (i == e - 1) ? s : (i + 1); - v = scaleInVector(toVector(outline.points, c)); - on = isOn(outline.tags[c]); - if (on) { // line - ++i; - ivec.push(vg.VGPathCommand.VG_LINE_TO_ABS); - pushPoint(pvec, v); - pnts += 1; - } else { // spline - if (isOn(outline.tags[n])) { // next on - nv = scaleInVector(toVector(outline.points, n)); - i += 2; - } else { // next off, use middle point - nv = mult(add(v, scaleInVector(toVector(outline.points, n))), 0.5); - ++i; - } - ivec.push(vg.VGPathCommand.VG_QUAD_TO_ABS); - pushPoint(pvec, v); - pushPoint(pvec, nv); - pnts += 2; - } - last = nv; - } - ivec.push(vg.VGPathSegment.VG_CLOSE_PATH); - s = e; - } - - for (i = 0; i < pvec.length / 2; ++i) { - if (pvec[i * 2 ] < minX) minX = pvec[i * 2 ]; - if (pvec[i * 2 ] > maxX) maxX = pvec[i * 2 ]; - if (pvec[i * 2 + 1] < minY) minY = pvec[i * 2 + 1]; - if (pvec[i * 2 + 1] > maxY) maxY = pvec[i * 2 + 1]; - } - if (!pvec.length) { - minX = 0.0; - minY = 0.0; - maxX = 0.0; - maxY = 0.0; - } - - gpvecindices.push(gpvec.length); - givecindices.push(givec.length); - - gpvecsizes.push(pvec.length); - givecsizes.push(ivec.length); - - gbbox.push({ minX: minX, minY: minY, maxX: maxX, maxY: maxY }); - - gpvec = gpvec.concat(pvec); - givec = givec.concat(ivec); - } - - f.glyphCount = glyphs; - - f.ascender = scaleOut(face.ascender / face.units_per_EM); - f.descender = -scaleOut(face.descender / face.units_per_EM); - - var glyphPoints = new Int32Array(gpvec); - var glyphInstructions = new Uint8Array(givec); - - for (i = 0; i < glyphs; i++) { - var instructionCounts = givecsizes[i]; - var glyphPath = f.glyphs[i]; - - if (instructionCounts) { - var offset = gpvecindices[i]; - - vg.appendPathDataO(glyphPath, instructionCounts, - glyphInstructions, givecindices[i], - glyphPoints, gpvecindices[i] * 4); - } - - // vg.setGlyphToPath(font, i, glyphPath, false /* VG_FALSE*/ /* isHinted*/, - // new Float32Array([0,0]) /* glyphOrigin */, - // new Float32Array([f.glyphAdvances[i],0]) /* escapement */); - } - - if (callback) { - callback(undefined, f); - } + + //#mod - created iterator function + var loaderMapFn = function(val,cc,cb){ + + f.characterMap[cc] = -1; // initially nonexistent + + + if (cc < 32){ // discard the first 32 characters + cb(null); //#mod - callback blank returns and continue async loop + }else{ + + var glyphIndex = ft.getCharIndex(face, cc); + + ft.loadGlyph(face,glyphIndex, ft.LOAD_NO_BITMAP | ft.LOAD_NO_HINTING | ft.LOAD_IGNORE_TRANSFORM); + + var path = vg.createPath(vg.VG_PATH_FORMAT_STANDARD, + vg.VGPathDatatype.VG_PATH_DATATYPE_S_32, + 1.0 / 65536.0 /* scale */, + 0.0 /* bias */, + 0, 0, /* segment, capacity hints */ + vg.VGPathCapabilities.VG_PATH_CAPABILITY_ALL); + f.glyphs[glyphs] = path; + f.characterMap[cc] = glyphs++; + + f.glyphAdvances.push(scaleOut(scaleIn(face.glyph.advance.x))); + + var outline = face.glyph.outline; + + + if (cc == 32) { + gpvecindices.push(gpvec.length); + givecindices.push(givec.length); + + gpvecsizes.push(0); + givecsizes.push(0); + + gbbox.push({ minX: 0, minY: 0, maxX: 0, maxY: 0 }); + + }else{ + + var pvec = []; + var ivec = []; + var minX = 10000000.0, minY = 100000000.0, maxX = -10000000.0, maxY = -10000000.0; + var s = 0, e; + var on; + var last, v, nv; + for (var con = 0; con < outline.nContours; ++con) { + var pnts = 1; + e = outline.contours[con] + 1; + last = scaleInVector(toVector(outline.points, s)); + + // read the contour start point + ivec.push(vg.VGPathCommand.VG_MOVE_TO_ABS); + pushPoint(pvec, last); + + i = s + 1; + while (i <= e) { + var c = (i == e) ? s : i; + var n = (i == e - 1) ? s : (i + 1); + v = scaleInVector(toVector(outline.points, c)); + on = isOn(outline.tags[c]); + if (on) { // line + ++i; + ivec.push(vg.VGPathCommand.VG_LINE_TO_ABS); + pushPoint(pvec, v); + pnts += 1; + } else { // spline + if (isOn(outline.tags[n])) { // next on + nv = scaleInVector(toVector(outline.points, n)); + i += 2; + } else { // next off, use middle point + nv = mult(add(v, scaleInVector(toVector(outline.points, n))), 0.5); + ++i; + } + ivec.push(vg.VGPathCommand.VG_QUAD_TO_ABS); + pushPoint(pvec, v); + pushPoint(pvec, nv); + pnts += 2; + } + last = nv; + } + ivec.push(vg.VGPathSegment.VG_CLOSE_PATH); + s = e; + } + + for (i = 0; i < pvec.length / 2; ++i) { + if (pvec[i * 2 ] < minX) minX = pvec[i * 2 ]; + if (pvec[i * 2 ] > maxX) maxX = pvec[i * 2 ]; + if (pvec[i * 2 + 1] < minY) minY = pvec[i * 2 + 1]; + if (pvec[i * 2 + 1] > maxY) maxY = pvec[i * 2 + 1]; + } + if (!pvec.length) { + minX = 0.0; + minY = 0.0; + maxX = 0.0; + maxY = 0.0; + } + + gpvecindices.push(gpvec.length); + givecindices.push(givec.length); + + gpvecsizes.push(pvec.length); + givecsizes.push(ivec.length); + + gbbox.push({ minX: minX, minY: minY, maxX: maxX, maxY: maxY }); + + gpvec = gpvec.concat(pvec); + givec = givec.concat(ivec); + } + cb(null); //done + } + + } + + + async.forEachOf(f.characterMap, loaderMapFn, function(err){ + + f.glyphCount = glyphs; + + f.ascender = scaleOut(face.ascender / face.units_per_EM); + f.descender = -scaleOut(face.descender / face.units_per_EM); + + var glyphPoints = new Int32Array(gpvec); + var glyphInstructions = new Uint8Array(givec); + + for (i = 0; i < glyphs; i++) { + var instructionCounts = givecsizes[i]; + var glyphPath = f.glyphs[i]; + + if (instructionCounts) { + var offset = gpvecindices[i]; + + vg.appendPathDataO(glyphPath, instructionCounts, + glyphInstructions, givecindices[i], + glyphPoints, gpvecindices[i] * 4); + } + + // vg.setGlyphToPath(font, i, glyphPath, false /* VG_FALSE*/ /* isHinted*/, + // new Float32Array([0,0]) /* glyphOrigin */, + // new Float32Array([f.glyphAdvances[i],0]) /* escapement */); + } + + if (callback) { + callback(undefined, f); + } + + }); + }; // unloadfont frees font path data diff --git a/package.json b/package.json index d7e1e38..a27d595 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "openvg-canvas", - "preferGlobal" : "true", + "preferGlobal": "true", "version": "1.1.7", "author": "Luis Reis (http://luismreis.com/)", "description": "Canvas on node-openvg", "bin": { - "node-canvas" : "./bin/node-canvas" + "node-canvas": "./bin/node-canvas" }, "main": "lib/canvas.js", "repository": { @@ -18,12 +18,13 @@ "canvas" ], "dependencies": { - "openvg" : "~0.4.4" + "async": "^2.0.0-rc.5", + "openvg": "~0.4.4" }, "devDependencies": { "tap": "*" }, - "license" : "MIT", + "license": "MIT", "engines": { "node": ">=0.8" },