Here the CSS width is specified. The program flows the text in it automatically.
I am very thankful to Peter Wiegel for his amazing Leipzig Fraktur font.
An underscore should appear at the end of each word part (in zusammengesetzten Wörter).
That's it. Gothic ligatures are fully automatic. Examples:
-l 32 -h 10000 /*global dojo*/
/* -*- coding: utf-8 -*- */
dojo.require('dojox.gfx');
dojo.require('dojox.gfx.VectorText');
function main () {
patch_dojox_gfx_vectorfont();
var someUri = 'Leipzig-Fraktur-Normal.font.svg'; console.log(someUri);
var myfont = dojox.gfx.getVectorFont(someUri); console.log(myfont);
dojo.global.myfont = myfont;
size = '1em';
scale = myfont._getSizeFactor( size ); console.log('size:', size, ' -> scale:', scale);
var f = {};
f.b = myfont.getBaseline( scale );
f.c = myfont.getCenterline( scale );
f.h = myfont.getLineHeight( scale );
f.d = f.b - f.h;
console.log('baseline:', f.b, ' centerline:', f.c, ' lineheight:', f.h, ' descent:', f.d );
//
var convert_node = function ( someNode ) {
if ( dojo.hasClass( someNode, 'rendered' ) ) {
return;
}
var size,s,g,n,phrase,rawtext,text,w; console.log( 'Converting node: ', someNode );
rawtext = someNode.textContent; console.log( ' -> rawtext: ', rawtext );
var desired_width = someNode.style.width; // Optional
// Copy the text
text = prepare_for_gothic( rawtext );
// Prepare the gothic SVG
svg_node = document.createElement( 'span' );
w = myfont.getWidth( text, scale ) || ( dojo.coords( someNode ).w * 2 );
// A bit generous on the height,
// so that the bottom of letters does not get cut.
h = f.h - f.d; console.log("scale, w, h:", scale, w, h);
// Estimate the number of lines.
var nlines = 1;
if ( desired_width ) {
// xxx Something to fix here
nlines = 2 * Math.ceil( /^\d+/.exec( w )[ 0 ] / ( /^\d+/.exec( desired_width )[ 0 ] ) );
console.log( 'desired_width:', desired_width, ', nlines:', nlines, ', nlines * h:', nlines * h);
}
svg_node.style.position = 'relative';
svg_node.style.top = ( -2 * f.d ) + 'px'; // -2 * to compensate the above generosity
s = dojox.gfx.createSurface( svg_node, desired_width || w, nlines * h );
g = s.createGroup();
phrase = myfont.draw(
g,
{
text: text,
align: 'left',
fitting: dojox.gfx.vectorFontFitting[ desired_width ? "FIT" : "NONE" ],
width: /^\d+/.exec( desired_width || w )[0],
height: ( nlines * h )
},
{
size: size,
width: desired_width || w
},
'black' );
// Empty the text node
dojo.empty( someNode );
// Try to make text search possible
n = dojo.create( 'span', { innerHTML: rawtext.replace( /_(?!_)/g, '' ),
style: 'font-size: 0.01px; vertical-align: top;' } );
someNode.appendChild( n );
// Append the rendered gothic SVG
someNode.appendChild( svg_node );
someNode.className += " rendered";
//
};
// --- Applicative part
// Non-interactive part: convert only once
(function () {
var do_it = function ( q ) {
convert_node( q.slice( 0, 1 )[ 0 ] );
window.setTimeout( dojo.partial( do_it, q.slice( 1 ) ), 10 );
};
do_it( dojo.query( '.gothic' ) );
})();
// Interactive text area "Write your own text"
window.setTimeout( function () {
var convert_own_text = function ( node_in, node_out ) {
dojo.empty( node_out );
dojo.removeClass( node_out, 'rendered' );
node_out.innerHTML = node_in.value;
convert_node( node_out );
};
dojo.query( '.write-group' ).forEach( function ( node_cont ) {
dojo.query( '.write-area', node_cont ).forEach( function ( node_in ) {
node_in.value = "Knecht Markus war verschwiegen, war ein dunkler Ehrenmann, " +
"aber das sagte er mir, wenn ich mich mit Sengen und Brennen auf den Etzel hinaus_spielen wolle, " +
"so täte er es dem Kaiser schreiben, daß er mich recht_zeitig köpfen lasse. " +
"(\"Als ich noch der Waldbauernbub war\", von Peter Rosegger)";
dojo.query( '.write-output', node_cont ).forEach( function ( node_out ) {
dojo.query( '.write-area-ok', node_cont ).onclick( function () {
convert_own_text( node_in, node_out );
});
convert_own_text( node_in, node_out );
} );
} );
} );
}, 200 );
};
function patch_dojox_gfx_vectorfont() {
// Try to patch dojox.gfx.VectorFont for hexadecimal glyph names.
// This patch is meaningful until the following issue is resolved:
// http://bugs.dojotoolkit.org/ticket/10508
var o = dojox.gfx.VectorFont.prototype,
s = "_decodeEntitySequence",
f = o[ s ];
if ( !f ) return;
o[ s ] = function ( str ) {
var mo, rx = new RegExp( '\u0026\u0023x([^;]+);' );
while ( ( mo = rx.exec( str ) ) ) {
str = str.substr( 0, mo.index ) + '\u0026\u0023' + parseInt( mo[1], 16 ) + ';' + str.substr( mo.index + mo[ 0 ].length );
}
return f.call( this, str );
};
};
function prepare_for_gothic( text ) {
var ret = text;
dojo.forEach( [
// We use the underscore character "_" to prevent transformations (ligatures, gothic S etc.)
[ /s(?=([\W_]|$))/g, '$' ],
[ /sch/g, '\u00c0' ],
[ /ch/g, '\u00e0' ],
[ /ck/g, '\u00e1' ],
[ /ß/g, '\u00df' ],
[ /ff/g, '\u00e8' ],
[ /fi/g, '\u00e9' ],
[ /fl/g, '\u00ec' ],
[ /ft/g, '\u00ed' ],
[ /ss/g, '\u00f3' ],
[ /st/g, '\u00f9' ],
[ /tz/g, '\u00fa' ],
[ /_(?!_)/g, '' ] // Last step: remove the single "_" (this will be important in the future for t_z and tz ligature etc.)
], function ( x ) {
ret = ret.replace( x[ 0 ], x[ 1 ] );
});
return ret;
};
dojo.addOnLoad( main );
Produced on 2010-01-19 by dojox_gfx_vectorfont_example.scm - by Guillaume Lathoud (glathoud _at_ yahoo _dot_ fr)