Implemented selection for showText()
This commit is contained in:
parent
46a48a56b7
commit
9ebec03ddc
153
src/canvas.js
153
src/canvas.js
@ -453,7 +453,58 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
nextLine: function canvasGraphicsNextLine() {
|
nextLine: function canvasGraphicsNextLine() {
|
||||||
this.moveText(0, this.current.leading);
|
this.moveText(0, this.current.leading);
|
||||||
},
|
},
|
||||||
showText: function canvasGraphicsShowText(text) {
|
applyTextTransforms: function canvasApplyTransforms() {
|
||||||
|
var ctx = this.ctx;
|
||||||
|
var current = this.current;
|
||||||
|
var textHScale = current.textHScale;
|
||||||
|
var font = current.font;
|
||||||
|
|
||||||
|
ctx.transform.apply(ctx, current.textMatrix);
|
||||||
|
ctx.scale(1, -1);
|
||||||
|
ctx.translate(current.x, -1 * current.y);
|
||||||
|
ctx.transform.apply(ctx, font.fontMatrix || IDENTITY_MATRIX);
|
||||||
|
ctx.scale(1 / textHScale, 1);
|
||||||
|
},
|
||||||
|
getTextGeometry: function canvasGetTextGeometry() {
|
||||||
|
var geom = {};
|
||||||
|
var ctx = this.ctx;
|
||||||
|
var font = this.current.font;
|
||||||
|
var ctxMatrix = ctx.mozCurrentTransform;
|
||||||
|
if (ctxMatrix) {
|
||||||
|
var bl = Util.applyTransform([0, 0], ctxMatrix);
|
||||||
|
var tr = Util.applyTransform([1, 1], ctxMatrix);
|
||||||
|
geom.x = bl[0];
|
||||||
|
geom.y = bl[1];
|
||||||
|
geom.hScale = tr[0] - bl[0];
|
||||||
|
geom.vScale = tr[1] - bl[1];
|
||||||
|
}
|
||||||
|
var spaceGlyph = font.charsToGlyphs(' ', true);
|
||||||
|
// Hack (sometimes space is not encoded)
|
||||||
|
if (spaceGlyph.length === 0 || spaceGlyph[0].width === 0)
|
||||||
|
spaceGlyph = font.charsToGlyphs('i', true);
|
||||||
|
// Fallback
|
||||||
|
if (spaceGlyph.length === 0 || spaceGlyph[0].width === 0)
|
||||||
|
spaceGlyph = [ {width:0} ];
|
||||||
|
geom.spaceWidth = spaceGlyph[0].width;
|
||||||
|
return geom;
|
||||||
|
},
|
||||||
|
pushTextDivs: function canvasGraphicsPushTextDivs(text) {
|
||||||
|
var div = document.createElement('div');
|
||||||
|
var fontSize = this.current.fontSize;
|
||||||
|
var fontHeight = text.geom.vScale * fontSize;
|
||||||
|
|
||||||
|
div.style.fontSize = fontHeight + 'px';
|
||||||
|
// TODO: family should be '= font.loadedName', but some fonts don't
|
||||||
|
// have spacing info (cf. fonts.js > Font > fields > htmx)
|
||||||
|
div.style.fontFamily = 'serif';
|
||||||
|
div.style.left = text.geom.x + 'px';
|
||||||
|
div.style.top = (text.geom.y - fontHeight) + 'px';
|
||||||
|
div.innerHTML = text.str;
|
||||||
|
div.dataset.canvasWidth = text.canvasWidth * text.geom.hScale;
|
||||||
|
div.dataset.textLength = text.length;
|
||||||
|
this.textDivs.push(div);
|
||||||
|
},
|
||||||
|
showText: function canvasGraphicsShowText(str, skipTextSelection) {
|
||||||
function unicodeToChar(unicode) {
|
function unicodeToChar(unicode) {
|
||||||
return (unicode >= 0x10000) ?
|
return (unicode >= 0x10000) ?
|
||||||
String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10),
|
String.fromCharCode(0xD800 | ((unicode - 0x10000) >> 10),
|
||||||
@ -463,14 +514,24 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
var ctx = this.ctx;
|
var ctx = this.ctx;
|
||||||
var current = this.current;
|
var current = this.current;
|
||||||
var font = current.font;
|
var font = current.font;
|
||||||
var glyphs = font.charsToGlyphs(text);
|
var glyphs = font.charsToGlyphs(str);
|
||||||
var fontSize = current.fontSize;
|
var fontSize = current.fontSize;
|
||||||
var charSpacing = current.charSpacing;
|
var charSpacing = current.charSpacing;
|
||||||
var wordSpacing = current.wordSpacing;
|
var wordSpacing = current.wordSpacing;
|
||||||
var textHScale = current.textHScale;
|
var textHScale = current.textHScale;
|
||||||
var glyphsLength = glyphs.length;
|
var glyphsLength = glyphs.length;
|
||||||
var text = { chars:'', width:0 };
|
var textLayer = this.textLayer;
|
||||||
|
var text = { str:'', length:0, canvasWidth:0, geom:{}};
|
||||||
|
var textSelection = textLayer && !skipTextSelection ? true : false;
|
||||||
|
|
||||||
|
if (textSelection) {
|
||||||
|
ctx.save();
|
||||||
|
this.applyTextTransforms();
|
||||||
|
text.geom = this.getTextGeometry();
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type3 fonts - each glyph is a "mini-PDF"
|
||||||
if (font.coded) {
|
if (font.coded) {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.transform.apply(ctx, current.textMatrix);
|
ctx.transform.apply(ctx, current.textMatrix);
|
||||||
@ -498,17 +559,14 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
ctx.translate(charWidth, 0);
|
ctx.translate(charWidth, 0);
|
||||||
current.x += charWidth;
|
current.x += charWidth;
|
||||||
|
|
||||||
text.chars += unicodeToChar(glyph.unicode);
|
text.str += unicodeToChar(glyph.unicode);
|
||||||
text.width += charWidth;
|
text.canvasWidth += charWidth;
|
||||||
|
text.length++;
|
||||||
}
|
}
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
} else {
|
} else {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.transform.apply(ctx, current.textMatrix);
|
this.applyTextTransforms();
|
||||||
ctx.scale(1, -1);
|
|
||||||
ctx.translate(current.x, -1 * current.y);
|
|
||||||
ctx.transform.apply(ctx, font.fontMatrix || IDENTITY_MATRIX);
|
|
||||||
ctx.scale(1 / textHScale, 1);
|
|
||||||
|
|
||||||
var width = 0;
|
var width = 0;
|
||||||
for (var i = 0; i < glyphsLength; ++i) {
|
for (var i = 0; i < glyphsLength; ++i) {
|
||||||
@ -524,12 +582,18 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
ctx.fillText(char, width, 0);
|
ctx.fillText(char, width, 0);
|
||||||
width += charWidth;
|
width += charWidth;
|
||||||
|
|
||||||
text.chars += char;
|
text.str += char;
|
||||||
text.width += charWidth;
|
text.canvasWidth += charWidth;
|
||||||
|
text.length++;
|
||||||
}
|
}
|
||||||
|
|
||||||
current.x += width;
|
current.x += width;
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (textSelection)
|
||||||
|
this.pushTextDivs(text);
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
showSpacedText: function canvasGraphicsShowSpacedText(arr) {
|
showSpacedText: function canvasGraphicsShowSpacedText(arr) {
|
||||||
@ -540,32 +604,13 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
var arrLength = arr.length;
|
var arrLength = arr.length;
|
||||||
var textLayer = this.textLayer;
|
var textLayer = this.textLayer;
|
||||||
var font = current.font;
|
var font = current.font;
|
||||||
var text = {str:'', length:0, canvasWidth:0, spaceWidth:0, geom:{}};
|
var text = {str:'', length:0, canvasWidth:0, geom:{}};
|
||||||
|
var textSelection = textLayer ? true : false;
|
||||||
|
|
||||||
if (textLayer) {
|
if (textSelection) {
|
||||||
text.spaceWidth = this.current.font.charsToGlyphs(' ')[0].width;
|
|
||||||
if (!text.spaceWidth>0) {
|
|
||||||
// Hack (space is sometimes not encoded)
|
|
||||||
text.spaceWidth = this.current.font.charsToGlyphs('i')[0].width;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute text.geom
|
|
||||||
// TODO: refactor the series of transformations below, and share it with showText()
|
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.transform.apply(ctx, current.textMatrix);
|
this.applyTextTransforms();
|
||||||
ctx.scale(1, -1);
|
text.geom = this.getTextGeometry();
|
||||||
ctx.translate(current.x, -1 * current.y);
|
|
||||||
ctx.transform.apply(ctx, font.fontMatrix || IDENTITY_MATRIX);
|
|
||||||
ctx.scale(1 / textHScale, 1);
|
|
||||||
var ctxMatrix = ctx.mozCurrentTransform;
|
|
||||||
if (ctxMatrix) {
|
|
||||||
var bl = Util.applyTransform([0, 0], ctxMatrix);
|
|
||||||
var tr = Util.applyTransform([1, 1], ctxMatrix);
|
|
||||||
text.geom.x = bl[0];
|
|
||||||
text.geom.y = bl[1];
|
|
||||||
text.geom.xFactor = tr[0] - bl[0];
|
|
||||||
text.geom.yFactor = tr[1] - bl[1];
|
|
||||||
}
|
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,47 +620,35 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
var spacingLength = -e * 0.001 * fontSize * textHScale;
|
var spacingLength = -e * 0.001 * fontSize * textHScale;
|
||||||
current.x += spacingLength;
|
current.x += spacingLength;
|
||||||
|
|
||||||
if (textLayer) {
|
if (textSelection) {
|
||||||
// Emulate precise spacing via HTML spaces
|
// Emulate precise spacing via HTML spaces
|
||||||
text.canvasWidth += spacingLength;
|
text.canvasWidth += spacingLength;
|
||||||
if (e<0 && text.spaceWidth>0) { // avoid div by zero
|
if (e<0 && text.geom.spaceWidth>0) { // avoid div by zero
|
||||||
var numFakeSpaces = Math.round(-e / text.spaceWidth);
|
var numFakeSpaces = Math.round(-e / text.geom.spaceWidth);
|
||||||
for (var j = 0; j < numFakeSpaces; ++j)
|
for (var j = 0; j < numFakeSpaces; ++j)
|
||||||
text.str += ' ';
|
text.str += ' ';
|
||||||
text.length += numFakeSpaces>0 ? 1 : 0;
|
text.length += numFakeSpaces>0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (isString(e)) {
|
} else if (isString(e)) {
|
||||||
var shownText = this.showText(e);
|
var shownText = this.showText(e, true);
|
||||||
|
|
||||||
if (textLayer) {
|
if (textSelection) {
|
||||||
if (shownText.chars === ' ') {
|
if (shownText.str === ' ') {
|
||||||
text.str += ' ';
|
text.str += ' ';
|
||||||
} else {
|
} else {
|
||||||
text.str += shownText.chars;
|
text.str += shownText.str;
|
||||||
}
|
}
|
||||||
text.canvasWidth += shownText.width;
|
text.canvasWidth += shownText.canvasWidth;
|
||||||
text.length += e.length;
|
text.length += e.length;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
malformed('TJ array element ' + e + ' is not string or num');
|
malformed('TJ array element ' + e + ' is not string or num');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textLayer) {
|
if (textSelection)
|
||||||
var div = document.createElement('div');
|
this.pushTextDivs(text);
|
||||||
var fontHeight = text.geom.yFactor * fontSize;
|
|
||||||
div.style.fontSize = fontHeight + 'px';
|
|
||||||
// TODO: family should be '= font.loadedName', but some fonts don't
|
|
||||||
// have spacing info (cf. fonts.js > Font > fields > htmx)
|
|
||||||
div.style.fontFamily = 'serif';
|
|
||||||
div.style.left = text.geom.x + 'px';
|
|
||||||
div.style.top = (text.geom.y - fontHeight) + 'px';
|
|
||||||
div.innerHTML = text.str;
|
|
||||||
div.dataset.canvasWidth = text.canvasWidth * text.geom.xFactor;
|
|
||||||
div.dataset.textLength = text.length;
|
|
||||||
this.textDivs.push(div);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
nextLineShowText: function canvasGraphicsNextLineShowText(text) {
|
nextLineShowText: function canvasGraphicsNextLineShowText(text) {
|
||||||
this.nextLine();
|
this.nextLine();
|
||||||
|
@ -1797,7 +1797,7 @@ var Font = (function Font() {
|
|||||||
return rule;
|
return rule;
|
||||||
},
|
},
|
||||||
|
|
||||||
charsToGlyphs: function fonts_chars2Glyphs(chars) {
|
charsToGlyphs: function fonts_chars2Glyphs(chars, suppressWarnings) {
|
||||||
var charsCache = this.charsCache;
|
var charsCache = this.charsCache;
|
||||||
var glyphs;
|
var glyphs;
|
||||||
|
|
||||||
@ -1830,7 +1830,8 @@ var Font = (function Font() {
|
|||||||
var charcode = int16([chars.charCodeAt(i++), chars.charCodeAt(i)]);
|
var charcode = int16([chars.charCodeAt(i++), chars.charCodeAt(i)]);
|
||||||
var glyph = encoding[charcode];
|
var glyph = encoding[charcode];
|
||||||
if ('undefined' == typeof(glyph)) {
|
if ('undefined' == typeof(glyph)) {
|
||||||
warn('Unencoded charcode ' + charcode);
|
if (!suppressWarnings)
|
||||||
|
warn('Unencoded charcode ' + charcode);
|
||||||
glyph = {
|
glyph = {
|
||||||
unicode: charcode,
|
unicode: charcode,
|
||||||
width: this.defaultWidth
|
width: this.defaultWidth
|
||||||
@ -1847,7 +1848,8 @@ var Font = (function Font() {
|
|||||||
var charcode = chars.charCodeAt(i);
|
var charcode = chars.charCodeAt(i);
|
||||||
var glyph = encoding[charcode];
|
var glyph = encoding[charcode];
|
||||||
if ('undefined' == typeof(glyph)) {
|
if ('undefined' == typeof(glyph)) {
|
||||||
warn('Unencoded charcode ' + charcode);
|
if (!suppressWarnings)
|
||||||
|
warn('Unencoded charcode ' + charcode);
|
||||||
glyph = {
|
glyph = {
|
||||||
unicode: charcode,
|
unicode: charcode,
|
||||||
width: this.defaultWidth
|
width: this.defaultWidth
|
||||||
|
Loading…
x
Reference in New Issue
Block a user