Merge branch 'kerning' of https://github.com/EugeneSqr/konva into EugeneSqr-kerning

This commit is contained in:
Anton Lavrenov 2018-02-10 13:02:00 +07:00
commit fd4b1aab45
5 changed files with 148 additions and 13 deletions

View File

@ -16598,6 +16598,7 @@
* @param {String} [config.fontVariant] can be normal or small-caps. Default is normal
* @param {String} config.text
* @param {String} config.data SVG data string
* @param {Function} config.getKerning a getter for kerning values for the specified characters
* @param {String} [config.fill] fill color
* @param {Image} [config.fillPatternImage] fill pattern image
* @param {Number} [config.fillPatternX]
@ -16670,6 +16671,19 @@
* @param {Number} [config.dragDistance]
* @param {Function} [config.dragBoundFunc]
* @example
* var kerningPairs = {
* 'A': {
* ' ': -0.05517578125,
* 'T': -0.07421875,
* 'V': -0.07421875,
* },
* 'V': {
* ',': -0.091796875,
* ":": -0.037109375,
* ";": -0.037109375,
* "A": -0.07421875,
* }
* }
* var textpath = new Konva.TextPath({
* x: 100,
* y: 50,
@ -16677,7 +16691,10 @@
* fontSize: '24',
* fontFamily: 'Arial',
* text: 'All the world\'s a stage, and all the men and women merely players.',
* data: 'M10,10 C0,0 10,150 100,100 S300,150 400,50'
* data: 'M10,10 C0,0 10,150 100,100 S300,150 400,50',
* getKerning: function(leftChar, rightChar) {
* return kerningPairs.hasOwnProperty(leftChar) ? pairs[leftChar][rightChar] || 0 : 0
* }
* });
*/
Konva.TextPath = function(config) {
@ -16696,6 +16713,7 @@
var that = this;
this.dummyCanvas = Konva.Util.createCanvasElement();
this.dataArray = [];
this.getKerning = config.getKerning;
// call super constructor
Konva.Shape.call(this, config);
@ -17079,11 +17097,20 @@
var width = Konva.Path.getLineLength(p0.x, p0.y, p1.x, p1.y);
// Note: Since glyphs are rendered one at a time, any kerning pair data built into the font will not be used.
// Can foresee having a rough pair table built in that the developer can override as needed.
var kern = 0;
// placeholder for future implementation
if (this.getKerning) {
try {
// getKerning is a user provided getter. Make sure it never breaks our logic
kern = this.getKerning(charArr[i - 1], charArr[i]) * this.fontSize();
}
catch(e) {
kern = 0;
}
}
p0.x += kern;
p1.x += kern;
this.textWidth += kern;
var midpoint = Konva.Path.getPointOnLine(
kern + width / 2.0,
@ -18357,7 +18384,7 @@
var rotation = Konva.getAngle(node.rotation());
var dx = rect.x * node.scaleX() - node.offsetX();
var dy = rect.y * node.scaleY() - node.offsetX();
var dy = rect.y * node.scaleY() - node.offsetY();
return {
x: node.x() + dx * Math.cos(rotation) + dy * Math.sin(-rotation),

2
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -17,9 +17,23 @@
* @param {String} [config.fontVariant] can be normal or small-caps. Default is normal
* @param {String} config.text
* @param {String} config.data SVG data string
* @param {Function} config.getKerning a getter for kerning values for the specified characters
* @@shapeParams
* @@nodeParams
* @example
* var kerningPairs = {
* 'A': {
* ' ': -0.05517578125,
* 'T': -0.07421875,
* 'V': -0.07421875,
* },
* 'V': {
* ',': -0.091796875,
* ":": -0.037109375,
* ";": -0.037109375,
* "A": -0.07421875,
* }
* }
* var textpath = new Konva.TextPath({
* x: 100,
* y: 50,
@ -27,7 +41,10 @@
* fontSize: '24',
* fontFamily: 'Arial',
* text: 'All the world\'s a stage, and all the men and women merely players.',
* data: 'M10,10 C0,0 10,150 100,100 S300,150 400,50'
* data: 'M10,10 C0,0 10,150 100,100 S300,150 400,50',
* getKerning: function(leftChar, rightChar) {
* return kerningPairs.hasOwnProperty(leftChar) ? pairs[leftChar][rightChar] || 0 : 0
* }
* });
*/
Konva.TextPath = function(config) {
@ -46,6 +63,7 @@
var that = this;
this.dummyCanvas = Konva.Util.createCanvasElement();
this.dataArray = [];
this.getKerning = config.getKerning;
// call super constructor
Konva.Shape.call(this, config);
@ -429,11 +447,20 @@
var width = Konva.Path.getLineLength(p0.x, p0.y, p1.x, p1.y);
// Note: Since glyphs are rendered one at a time, any kerning pair data built into the font will not be used.
// Can foresee having a rough pair table built in that the developer can override as needed.
var kern = 0;
// placeholder for future implementation
if (this.getKerning) {
try {
// getKerning is a user provided getter. Make sure it never breaks our logic
kern = this.getKerning(charArr[i - 1], charArr[i]) * this.fontSize();
}
catch(e) {
kern = 0;
}
}
p0.x += kern;
p1.x += kern;
this.textWidth += kern;
var midpoint = Konva.Path.getPointOnLine(
kern + width / 2.0,

View File

@ -83,7 +83,7 @@
var rotation = Konva.getAngle(node.rotation());
var dx = rect.x * node.scaleX() - node.offsetX();
var dy = rect.y * node.scaleY() - node.offsetX();
var dy = rect.y * node.scaleY() - node.offsetY();
return {
x: node.x() + dx * Math.cos(rotation) + dy * Math.sin(-rotation),

View File

@ -368,4 +368,85 @@ suite('TextPath', function() {
stage.add(layer);
showHit(layer);
});
test('Text with kerning', function() {
var stage = addStage();
// simulate lack of kerning support
stage.getContainer().style.fontKerning = 'none';
var layer = new Konva.Layer();
var pairs = {
'A': {
'V': -0.07421875,
},
'V': {
'A': -0.07421875,
},
}
const kernedText = new Konva.TextPath({
x : 0, y : 30,
fill: 'black',
text: 'AV',
fontSize: 60,
data: 'M0,0 L200,0',
getKerning: function(leftChar, rightChar) {
return pairs.hasOwnProperty(leftChar) ? pairs[leftChar][rightChar] || 0 : 0
},
});
const unkernedText = new Konva.TextPath({
x : 0, y : 90,
fill: 'black',
text: 'AV',
fontSize: 60,
data: 'M0,0 L200,0',
});
layer.add(kernedText);
layer.add(unkernedText);
stage.add(layer);
assert(
kernedText.getTextWidth() < unkernedText.getTextWidth(),
'kerned text lenght must be less then unkerned text length');
});
test('Text with invalid kerning getter should not fail (fallback to unkerned)', function() {
var stage = addStage();
// simulate lack of kerning support
stage.getContainer().style.fontKerning = 'none';
var layer = new Konva.Layer();
const kernedText = new Konva.TextPath({
x : 0, y : 30,
fill: 'black',
text: 'AV',
fontSize: 60,
data: 'M0,0 L200,0',
getKerning: function(leftChar, rightChar) {
// getter that fails
throw new Error("something went wrong");
},
});
const unkernedText = new Konva.TextPath({
x : 0, y : 90,
fill: 'black',
text: 'AV',
fontSize: 60,
data: 'M0,0 L200,0',
});
layer.add(kernedText);
layer.add(unkernedText);
stage.add(layer);
assert.equal(
kernedText.getTextWidth(), unkernedText.getTextWidth(),
'should gracefully fallback to unkerned text');
})
});