如何在Processing或Java中获取PFont字符串的高度和宽度?

huangapple go评论85阅读模式
英文:

How do you find out the height and width of a PFont string in Processing or Java?

问题

你怎么样才能在Processing或Java中找出PFont字符串的高度和宽度?

英文:

How do you find out the height and width of a PFont string in Processing or Java?

答案1

得分: 4

以下是翻译好的内容:

当你有这样的问题时,最好的做法是阅读Processing参考文档

具体而言,你可能在寻找textWidth()textAscent()textDescent()函数。

size(400, 400);
textSize(36);

String str = "你好,世界";
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);

如何在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);

如何在Processing或Java中获取PFont字符串的高度和宽度?

答案2

得分: 4

使用内置函数textWidth()textAscent()textDescent()是获取字符串高度和宽度的一个良好近似方法,但它们并不是精确的

为什么呢?

  • textAscent()返回基于字母'd'的文本行上方的高度。
  • textDescent()返回基于字母'p'的文本行下方的高度。
  • textWidth()包括字形的空白区域(也称为填充;理想情况下,我们希望忽略第一个和最后一个字符的填充)。

因此,textAscent() + textDescent()测量了给定字体和字号下字符串的最大高度,而不是特定字符串的高度。换句话说,如果您的文本中不同时包含'd'和'p'字符,那么使用这些方法来确定文本高度将会高估结果(正如我们在Kevin的截图中看到的)。

获取精确的高度

我们可以使用以下方法来获取精确的高度结果:

  1. 获取每个字符的矢量表示。
  2. 遍历矢量的顶点,找到:
    • 具有最高Y位置的顶点。
    • 具有最低Y位置的顶点。
  3. 从最高Y位置减去最低Y位置,以确定精确的字符串高度。

代码示例

请注意,您需要明确地创建一个PFont

String string = "Hello world";

PFont font = createFont("Arial", 96, true); // Arial字体,大小96
textFont(font);

float minY = Float.MAX_VALUE;
float maxY = Float.NEGATIVE_INFINITY;

for (char c : string.toCharArray()) {
  PShape character = font.getShape(c); // 创建字符矢量
  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;

结果

(请注意,我们在这里仍然使用了textWidth()来获取宽度)

text(string, mouseX, mouseY);
rect(mouseX, mouseY, textWidth("Hello world"), -textHeight);

获取精确的宽度

代码示例

String string = "Hello world";

PFont font = createFont("Arial", 96, true); // Arial字体,大小96
textFont(font);

float textWidth = textWidth(string); // 调用Processing方法

float whitespace = (font.width(string.charAt(string.length() - 1)) * font.getSize()
    - font.getGlyph(string.charAt(string.length() - 1)).width) / 2;
textWidth -= whitespace; // 减去最后一个字符的空白

whitespace = (font.width(string.charAt(0)) * font.getSize() - font.getGlyph(string.charAt(0)).width) / 2;
textWidth -= whitespace; // 减去第一个字符的空白

结果

(将两者结合起来...)

text(string, mouseX, mouseY);
rect(mouseX + whitespace, mouseY, textWidth, -textHeight);

Y轴对齐

绘制在"Hello world"周围的矩形之所以对齐,是因为没有任何字形在基线以下。

对于像@#&#39;pdXW\这样的字符串,@p都会在基线以下下降,使得矩形虽然具有正确的高度,但在y轴上与字符串不对齐,如下所示:

(下图省略)

程序化确定y偏移的一种方法是找到最低顶点的Y坐标(尽管请记住Processing的y轴向下延伸,因此实际上我们实际上正在寻找最高值)。幸运的是,这在计算精确高度的时候已经计算过了。

我们只需使用在那里计算的maxY值来偏移文本边界框。

结果

text(string, mouseX, mouseY);
rect(mouseX + whitespace, mouseY + maxY, textWidth, -textHeight);
英文:

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).


Getting the exact height

We can use this approach to get an exact result for height:

  1. Get a vector representation of each character
  2. Iterate over the vector's vertices, finding:
    • The vertex with highest Y position
    • The vertex with lowest Y position
  3. Subtract the highest Y position from the lowest Y position to determine the exact string height

Code Example

Note you'll need to explicitly create a PFont for this.

String string = &quot;Hello world&quot;;

PFont font = createFont(&quot;Arial&quot;, 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 &lt; 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(&quot;Hello world&quot;), -textHeight);

如何在Processing或Java中获取PFont字符串的高度和宽度?

Getting the exact width

Code Example

String string = &quot;Hello world&quot;;

PFont font = createFont(&quot;Arial&quot;, 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);

如何在Processing或Java中获取PFont字符串的高度和宽度?

Y-Axis Alignment

A rectangle drawn around &quot;Hello world&quot; happens to be aligned because none of the glyphs descend below the baseline.

With a string like @#&#39;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:

如何在Processing或Java中获取PFont字符串的高度和宽度?

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);

如何在Processing或Java中获取PFont字符串的高度和宽度?

huangapple
  • 本文由 发表于 2020年10月1日 07:11:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/64146977.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定