如何在 Processing 或 Java 中找出 PFont 字符串的高度和宽度?
The best thing you can do when you have a question like this is to read through the Processing reference .
Specifically you're probably looking for the textWidth()
, textAscent()
, and textDescent()
functions.
size(400, 400);
textSize(36);
String str = "Hello world";
float x = 100;
float y = 100;
float strWidth = textWidth(str);
float strAscent = textAscent();
float strDescent = textDescent();
float strHeight = strAscent + strDescent;
rect(x, y - strAscent, strWidth, strHeight);
fill(0);
text(str, x, y);
Using the inbuilt functions textWidth()
, textAscent()
, and textDescent()
are an easy way to get a good approximate result for the height and width of a string, but they are not exact .
Why?
textAscent()
returns text height above the line based on the letter 'd' textDescent()
returns text height below the line based on the letter 'p' . textWidth()
includes glyph whitespace (aka padding; ideally we want to ignore this for the first and last characters) textAscent() + textDescent()
therefore measures the maximum height of a string in a given font and font size, and not the height of a specific string. In other words, if your text doesn't include both 'd' and 'p' characters, then using these methods to determine text height will overestimate the result (as we see in Kevin's screenshot).
We can use this approach to get an exact result for height:
Note you'll need to explicitly create a PFont
for this.
String string = "Hello world";
PFont font = createFont("Arial", 96, true); // arial, size 96
textFont(font);
float minY = Float.MAX_VALUE;
float maxY = Float.NEGATIVE_INFINITY;
for (Character c : string.toCharArray()) {
PShape character = font.getShape(c); // create character vector
for (int i = 0; i < character.getVertexCount(); i++) {
minY = min(character.getVertex(i).y, minY);
maxY = max(character.getVertex(i).y, maxY);
}
}
final float textHeight = maxY - minY;
Result
(Note we're still using textWidth()
for width here)
text(string, mouseX, mouseY);
rect(mouseX, mouseY, textWidth("Hello world"), -textHeight);
String string = "Hello world";
PFont font = createFont("Arial", 96, true); // arial, size 96
textFont(font);
float textWidth = textWidth(string); // call Processing method
float whitespace = (font.width(string.charAt(string.length() - 1)) * font.getSize()
- font.getGlyph(string.charAt(string.length() - 1)).width) / 2;
textWidth -= whitespace; // subtract whitespace of last character
whitespace = (font.width(string.charAt(0)) * font.getSize() - font.getGlyph(string.charAt(0)).width) / 2;
textWidth -= whitespace; // subtract whitespace of first character
Result
(Putting the two together...)
text(string, mouseX, mouseY);
rect(mouseX + whitespace, mouseY, textWidth, -textHeight);
A rectangle drawn around "Hello world"
happens to be aligned because none of the glyphs descend below the baseline .
With a string like @#'pdXW\\
, both @
and p
descend below the baseline such that the rectangle, although it is the correct height, is out of alignment with the string on the y-axis, as below:
A programmatic way to determine the y-offset would be to find the Y-coordinate of the lowest (although remember Processing's y-axis extends downwards so we're actually looking for the highest value) vertex . Fortunately, this was calculated as part of finding the exact height.
We can simply use the maxY
value that was calculated there to offset the text bounding box.
Result
text(string, mouseX, mouseY);
rect(mouseX + whitespace, mouseY + maxY, textWidth, -textHeight);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.