mirror of
https://github.com/konvajs/konva.git
synced 2025-06-28 15:23:44 +08:00
Merge branch 'EugeneSqr-kerning'
This commit is contained in:
commit
a2fef6624a
39
konva.js
39
konva.js
@ -16598,6 +16598,7 @@
|
|||||||
* @param {String} [config.fontVariant] can be normal or small-caps. Default is normal
|
* @param {String} [config.fontVariant] can be normal or small-caps. Default is normal
|
||||||
* @param {String} config.text
|
* @param {String} config.text
|
||||||
* @param {String} config.data SVG data string
|
* @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 {String} [config.fill] fill color
|
||||||
* @param {Image} [config.fillPatternImage] fill pattern image
|
* @param {Image} [config.fillPatternImage] fill pattern image
|
||||||
* @param {Number} [config.fillPatternX]
|
* @param {Number} [config.fillPatternX]
|
||||||
@ -16670,6 +16671,19 @@
|
|||||||
* @param {Number} [config.dragDistance]
|
* @param {Number} [config.dragDistance]
|
||||||
* @param {Function} [config.dragBoundFunc]
|
* @param {Function} [config.dragBoundFunc]
|
||||||
* @example
|
* @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({
|
* var textpath = new Konva.TextPath({
|
||||||
* x: 100,
|
* x: 100,
|
||||||
* y: 50,
|
* y: 50,
|
||||||
@ -16677,7 +16691,10 @@
|
|||||||
* fontSize: '24',
|
* fontSize: '24',
|
||||||
* fontFamily: 'Arial',
|
* fontFamily: 'Arial',
|
||||||
* text: 'All the world\'s a stage, and all the men and women merely players.',
|
* 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) {
|
Konva.TextPath = function(config) {
|
||||||
@ -16696,6 +16713,7 @@
|
|||||||
var that = this;
|
var that = this;
|
||||||
this.dummyCanvas = Konva.Util.createCanvasElement();
|
this.dummyCanvas = Konva.Util.createCanvasElement();
|
||||||
this.dataArray = [];
|
this.dataArray = [];
|
||||||
|
this.getKerning = config.getKerning;
|
||||||
|
|
||||||
// call super constructor
|
// call super constructor
|
||||||
Konva.Shape.call(this, config);
|
Konva.Shape.call(this, config);
|
||||||
@ -17079,11 +17097,20 @@
|
|||||||
|
|
||||||
var width = Konva.Path.getLineLength(p0.x, p0.y, p1.x, p1.y);
|
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;
|
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(
|
var midpoint = Konva.Path.getPointOnLine(
|
||||||
kern + width / 2.0,
|
kern + width / 2.0,
|
||||||
@ -18357,7 +18384,7 @@
|
|||||||
var rotation = Konva.getAngle(node.rotation());
|
var rotation = Konva.getAngle(node.rotation());
|
||||||
|
|
||||||
var dx = rect.x * node.scaleX() - node.offsetX();
|
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 {
|
return {
|
||||||
x: node.x() + dx * Math.cos(rotation) + dy * Math.sin(-rotation),
|
x: node.x() + dx * Math.cos(rotation) + dy * Math.sin(-rotation),
|
||||||
|
2
konva.min.js
vendored
2
konva.min.js
vendored
File diff suppressed because one or more lines are too long
@ -17,9 +17,23 @@
|
|||||||
* @param {String} [config.fontVariant] can be normal or small-caps. Default is normal
|
* @param {String} [config.fontVariant] can be normal or small-caps. Default is normal
|
||||||
* @param {String} config.text
|
* @param {String} config.text
|
||||||
* @param {String} config.data SVG data string
|
* @param {String} config.data SVG data string
|
||||||
|
* @param {Function} config.getKerning a getter for kerning values for the specified characters
|
||||||
* @@shapeParams
|
* @@shapeParams
|
||||||
* @@nodeParams
|
* @@nodeParams
|
||||||
* @example
|
* @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({
|
* var textpath = new Konva.TextPath({
|
||||||
* x: 100,
|
* x: 100,
|
||||||
* y: 50,
|
* y: 50,
|
||||||
@ -27,7 +41,10 @@
|
|||||||
* fontSize: '24',
|
* fontSize: '24',
|
||||||
* fontFamily: 'Arial',
|
* fontFamily: 'Arial',
|
||||||
* text: 'All the world\'s a stage, and all the men and women merely players.',
|
* 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) {
|
Konva.TextPath = function(config) {
|
||||||
@ -46,6 +63,7 @@
|
|||||||
var that = this;
|
var that = this;
|
||||||
this.dummyCanvas = Konva.Util.createCanvasElement();
|
this.dummyCanvas = Konva.Util.createCanvasElement();
|
||||||
this.dataArray = [];
|
this.dataArray = [];
|
||||||
|
this.getKerning = config.getKerning;
|
||||||
|
|
||||||
// call super constructor
|
// call super constructor
|
||||||
Konva.Shape.call(this, config);
|
Konva.Shape.call(this, config);
|
||||||
@ -429,11 +447,20 @@
|
|||||||
|
|
||||||
var width = Konva.Path.getLineLength(p0.x, p0.y, p1.x, p1.y);
|
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;
|
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(
|
var midpoint = Konva.Path.getPointOnLine(
|
||||||
kern + width / 2.0,
|
kern + width / 2.0,
|
||||||
|
@ -83,7 +83,7 @@
|
|||||||
var rotation = Konva.getAngle(node.rotation());
|
var rotation = Konva.getAngle(node.rotation());
|
||||||
|
|
||||||
var dx = rect.x * node.scaleX() - node.offsetX();
|
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 {
|
return {
|
||||||
x: node.x() + dx * Math.cos(rotation) + dy * Math.sin(-rotation),
|
x: node.x() + dx * Math.cos(rotation) + dy * Math.sin(-rotation),
|
||||||
|
@ -368,4 +368,85 @@ suite('TextPath', function() {
|
|||||||
stage.add(layer);
|
stage.add(layer);
|
||||||
showHit(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');
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user