Skip to content

Commit

Permalink
Merge pull request #1970 from processing/dhowe-fix-to-bounds-detection
Browse files Browse the repository at this point in the history
Fixes bug in bounds detection
  • Loading branch information
lmccart authored Jun 1, 2017
2 parents 9ac17cf + d10bf4f commit 16f87eb
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 69 deletions.
59 changes: 13 additions & 46 deletions src/typography/p5.Font.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,8 @@ var constants = require('../core/constants');

/*
* TODO:
*
* API:
* -- textBounds()
* -- getPath()
* -- getPoints()
*
* ===========================================
* -- PFont functions:
* PFont.list()
*
* -- kerning
* -- alignment: justified?
* -- integrate p5.dom? (later)
*/

/**
Expand Down Expand Up @@ -106,44 +95,27 @@ p5.Font.prototype.textBounds = function(str, x, y, fontSize, options) {
// settings. Default alignment should match opentype's origin: left-aligned &
// alphabetic baseline.
var p = (options && options.renderer && options.renderer._pInst) ||
this.parent,
ctx = p._renderer.drawingContext,
this.parent, ctx = p._renderer.drawingContext,
alignment = ctx.textAlign || constants.LEFT,
baseline = ctx.textBaseline || constants.BASELINE;
var result = this.cache[cacheKey('textBounds', str, x, y, fontSize, alignment,
baseline)];
baseline = ctx.textBaseline || constants.BASELINE,
key = cacheKey('textBounds', str, x, y, fontSize, alignment, baseline),
result = this.cache[key];

if (!result) {

var xCoords = [], yCoords = [], self = this,
scale = this._scale(fontSize), minX, minY, maxX, maxY;
var minX, minY, maxX, maxY, pos, xCoords = [], yCoords = [],
scale = this._scale(fontSize);

this.font.forEachGlyph(str, x, y, fontSize, options,
function(glyph, gX, gY, gFontSize) {

xCoords.push(gX);
yCoords.push(gY);

var gm = glyph.getMetrics();

if (glyph.name !== 'space' && glyph.unicode !== 32) {

xCoords.push(gX + (gm.xMax * scale));
yCoords.push(gY + (-gm.yMin * scale));
yCoords.push(gY + (-gm.yMax * scale));

} else { // NOTE: deals with broken metrics for spaces in opentype.js

xCoords.push(gX + self.font.charToGlyph(' ').advanceWidth *
self._scale(fontSize));
}
xCoords.push(gX + (gm.xMin * scale));
xCoords.push(gX + (gm.xMax * scale));
yCoords.push(gY + (-gm.yMin * scale));
yCoords.push(gY + (-gm.yMax * scale));
});

// fix to #1409 (not sure why these max() functions were here)
/*minX = Math.max(0, Math.min.apply(null, xCoords));
minY = Math.max(0, Math.min.apply(null, yCoords));
maxX = Math.max(0, Math.max.apply(null, xCoords));
maxY = Math.max(0, Math.max.apply(null, yCoords));*/
minX = Math.min.apply(null, xCoords);
minY = Math.min.apply(null, yCoords);
maxX = Math.max.apply(null, xCoords);
Expand All @@ -158,15 +130,15 @@ p5.Font.prototype.textBounds = function(str, x, y, fontSize, options) {
};

// Bounds are now calculated, so shift the x & y to match alignment settings
var textWidth = result.w + result.advance;
var pos = this._handleAlignment(p, ctx, str, result.x, result.y, textWidth);
pos = this._handleAlignment(p, ctx, str, result.x, result.y,
result.w + result.advance);

result.x = pos.x;
result.y = pos.y;

this.cache[cacheKey('textBounds', str, x, y, fontSize, alignment,
baseline)] = result;
}
//else console.log('cache-hit');

return result;
};
Expand Down Expand Up @@ -409,11 +381,6 @@ p5.Font.prototype._renderPath = function(line, x, y, options) {

p5.Font.prototype._textWidth = function(str, fontSize) {

if (str === ' ') { // special case for now

return this.font.charToGlyph(' ').advanceWidth * this._scale(fontSize);
}

var bounds = this.textBounds(str, 0, 0, fontSize);
return bounds.w + bounds.advance;
};
Expand Down
Binary file added test/manual-test-examples/p5.Font/AndaleMono.ttf
Binary file not shown.
7 changes: 6 additions & 1 deletion test/manual-test-examples/p5.Font/simple/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,15 @@
<meta charset="UTF-8">
<script language="javascript" type="text/javascript" src="../../../../lib/p5.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<style> body {padding: 0; margin: 0;} canvas{border: 1px solid #f0f0f0; display: block;} img{ border: 1px solid #f0f;} div{ margin: 10px 0px;}</style>
<style> body {padding: 0; margin: 0; font-size: 10px } canvas{border: 1px solid #f0f0f0; display: block;} img{ border: 1px solid #f0f;} div{ margin: 10px 0px;}</style>
</head>

<body>
<div id='textSketch'></div>
Note: (tight) bounds for a text string <i>may</i> start to the right of the its x-position (blue line)<br />
<div id='textSketchMono'></div><br />&nbsp;<br />
Issue #1958:
<div id='textSketch1958'></div>
<!--div id='textSketch1957'></div-->
</body>
</html>
157 changes: 135 additions & 22 deletions test/manual-test-examples/p5.Font/simple/sketch.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,152 @@
var _setup = function(p, font) {
var txt, tb, tw, x = 20, y = 50;

p.createCanvas(240, 160);
p.textFont(font);
p.textSize(20);

p.stroke("blue");
p.line(x, 0, x, p.height);

txt = " leading space";
tb = font.textBounds(txt, x, y);
tw = p.textWidth(txt);
p.stroke("black");
p.rect(tb.x, tb.y, tb.w, tb.h);
p.noStroke();
p.text(txt, x, y);
p.stroke("red");
p.line(x, y + 6, x + tw, y + 6);

y = 80;
txt = "traction waste";
tb = font.textBounds(txt, x, y);
tw = p.textWidth(txt);
p.stroke("black");
p.rect(tb.x, tb.y, tb.w, tb.h);
p.noStroke();
p.text(txt, x, y);
p.stroke("red");
p.line(x, y + 6, x + tw, y + 6);

y = 110;
txt = "trailing space ";
tb = font.textBounds(txt, x, y);
tw = p.textWidth(txt);
p.stroke("black");
p.rect(tb.x, tb.y, tb.w, tb.h);
p.noStroke();
p.text(txt, x, y);
p.stroke("red");
p.line(x, y + 6, x + tw, y + 6);

y = 140;
txt = " ";
tb = font.textBounds(txt, x, y);
tw = p.textWidth(txt);
p.stroke("black");
p.rect(tb.x, tb.y, tb.w, p.max(tb.h, 3));
p.noStroke();
p.text(txt, x, y);
p.stroke("red");
p.line(x, y + 6, x + tw, y + 6);
};

var textSketch = function(p) {
p.setup = function() {
p.loadFont("../acmesa.ttf", function(f) {
_setup(p, f);
});
};
};

var font, txt, tb;
var textSketchMono = function(p) {
p.setup = function() {
p.loadFont("../AndaleMono.ttf", function(f) {
_setup(p, f);
});
};
};

var textSketch1958 = function(p) { // issue #1958
var font, lineW, words = "swimming back to the rock";

p.preload = function() {
font = p.loadFont("../acmesa.ttf");
font = p.loadFont("../OpenSans-Regular.ttf");
};

p.setup = function() {
function textAsWords(words, x, y) {
var tw, spaceW = p.textWidth(" ");
console.log(spaceW);
for (var i = 0; i < words.length; i++) {
if (i != 0) {
tw = p.textWidth(words[i - 1]);
x += tw + spaceW;
p.stroke(0);
p.noFill();
p.rect(x - spaceW, y + 5, spaceW, -25);
}
p.fill(0);
p.noStroke();
p.text(words[i], x, y);
}
}

p.createCanvas(240, 160);
p.textFont(font);
p.textSize(20);
p.createCanvas(300, 200);
p.background(255);

txt = ' space first';
var tb = font.textBounds(txt,50,50,20);
p.rect(tb.x,tb.y,tb.w,tb.h);
p.text(txt, 50, 50);
p.textSize(20); // Case 1: Default font
p.noStroke();
p.text(words, 20, 50);
textAsWords(words.split(" "), 20, 80);

txt = 'trailing space?'
tb = font.textBounds(txt,50,80,20);
p.rect(tb.x,tb.y,tb.w,tb.h);
p.text(txt, 50, 80);
p.stroke(255, 0, 0);
p.line(20, 0, 20, p.height);

txt = 'trailing space? '
tb = font.textBounds(txt,50,110,20);
p.rect(tb.x,tb.y,tb.w,tb.h);
p.text(txt, 50, 110);
lineW = p.textWidth(words);
p.line(20 + lineW, 0, 20 + lineW, 90);

var tw = font._textWidth(txt);
tb = font.textBounds(' ',50,140,20);
p.rect(tb.x,tb.y,tb.w,tb.h);
};
p.textFont(font, 20); // Case 2: OpenSans
p.noStroke();
p.text(words, 20, 120);
textAsWords(words.split(" "), 20, 150);

p.stroke(255, 0, 0);
lineW = p.textWidth(words);
p.line(20 + lineW, 100, 20 + lineW, p.height - 20);

p.stroke(0);
p.line(20, 160, 20 + p.textWidth(" "), 160);
};
};

/*var textSketch1957 = function(p) { // issue #1957
var font;
p.preload = function() {
font = p.loadFont("../AndaleMono.ttf");
};
p.setup = function() {
p.createCanvas(300, 400);
p.textFont(font, 80);
p.text("a", 0, 100);
p.text("b", 0, 200);
p.text("c", 0, 300);
p.stroke(255,0,0);
p.line(p.textWidth("a"), 0, p.textWidth("a"), p.height);
p.line(p.textWidth("b"), 0, p.textWidth("b"), p.height);
p.line(p.textWidth("c"), 0, p.textWidth("c"), p.height);
p.noStroke();
p.textSize(10);
p.text("a="+p.textWidth("a")+" b="+p.textWidth("b")+" c="+p.textWidth("c"), 10, 350);
console.log(font);
}
}
new p5(textSketch1957, "textSketch1957");*/

new p5(textSketch, 'textSketch');
new p5(textSketch, "textSketch");
new p5(textSketchMono, "textSketchMono");
new p5(textSketch1958, "textSketch1958");

0 comments on commit 16f87eb

Please sign in to comment.