fontpath-wordwrap
Version:
simple word-wrapping tools for fontpath
139 lines (123 loc) • 3.38 kB
JavaScript
var tmpBounds = { x: 0, y: 0, width: 0, height: 0, glyphs: 0 };
var wordWrap = require('word-wrapper').lines
function isWhitespace(chr) {
return chr===' '
|| chr==='\n'
|| chr==='\r'
|| chr==='\t';
}
function idxOf(text, chr, start, end) {
var idx = text.indexOf(chr, start);
if (idx === -1 || idx > end)
return end;
return idx;
}
function WordWrap(text) {
/**
* The text being operated on.
* @param {String} text
*/
this.text = text||"";
/**
* An array of lines representing the state of this word wrapper.
* @param {Array} lines
*/
this.lines = [];
/**
* The newline character to break on, default '\n'
* @param {String} newline
*/
this.newline = '\n';
/**
* The mode for wordwrapping: 'pre', 'normal', or 'nowrap'.
*
* You can also use the `PRE`, `NORMAL`, and `NOWRAP` constants
* in `WordWrap.Mode`.
*
* @param {String} mode
*/
this.mode = WordWrap.Mode.NORMAL;
}
WordWrap.Mode = {
PRE: 'pre', //whitespace isn't collapsed
NORMAL: 'normal', //whitespace is collapsed
NOWRAP: 'nowrap' //only break on '\n'
};
/**
* Clears any multi-line layout by placing all the text in a single Line object.
*
* @param {GlyphIterator} iterator the iterator to use
* @method clearLayout
*/
WordWrap.prototype.clearLayout = function(iterator) {
this.lines.length = 0;
if (this.text.length > 0) {
iterator.getBounds(this.text, 0, this.text.length, undefined, tmpBounds);
var line = new WordWrap.Line(0, this.text.length, tmpBounds.width);
this.lines.push(line);
}
};
/**
* Resets the word wrapper by emptying all current lines.
* @method empty
*/
WordWrap.prototype.empty = function() {
this.lines.length = 0;
};
/**
* Word-wraps the given text into multiple lines.
* @param {[type]} iterator [description]
* @param {[type]} width [description]
* @param {[type]} start [description]
* @param {[type]} end [description]
* @return {[type]} [description]
*/
WordWrap.prototype.layout = function(iterator, wrapWidth, start, end) {
var text = this.text;
var measure = createMetrics(iterator);
var lines = wordWrap(text, {
start: start,
end: end,
width: wrapWidth,
measure: measure,
mode: this.mode
});
//append new lines
this.lines = this.lines.concat(lines);
};
/**
* A convenience method to return the maximum width of all current lines.
* This is useful for aligning blocks of text.
*
* @method getMaxLineWidth
* @return {Number} the maximum width of all lines
*/
WordWrap.prototype.getMaxLineWidth = function() {
var maxWidth = 0;
for (var i=0; i<this.lines.length; i++) {
var line = this.lines[i];
maxWidth = Math.max(line.width, maxWidth);
}
return maxWidth;
};
/**
* The Line object holds the start and end indices into the string,
* and the width as computed by GlyphIterator.
*
* @class WordWrap.Line
* @param {Number} start the start index, inclusive
* @param {Number} end the end index, exclusive
* @param {Number} width the computed width of this line
*/
WordWrap.Line = function(start, end, width) {
this.start = start;
this.end = end;
this.width = width;
};
module.exports = WordWrap;
function createMetrics(iterator) {
return function(text, start, end, width) {
iterator.getBounds(text, start, end, width, tmpBounds);
return new WordWrap.Line(start, start + tmpBounds.glyphs, tmpBounds.width);
}
}