0

I need help with the Graphics#drawString method:
I want to correctly draw it and need correct calculations for text width/height and text position.

These are my two test texts:
<text id="first-text" x="100" y="100" underline="true" border-color="#FFFFFF" border-width="1" font-size="32">Test Text</text>

enter image description here

<text id="second-text" x="300" y="100" underline="true" border-color="#FFFFFF" border-width="1">Test Text</text>

enter image description here

Note: The drawn red dot is a debug pixel drawn to show the x, y coordinates passed into the drawString method.

First Problem:

I want to get this width and height (underline height included) seen here:

enter image description here
using paint.net shows me that the result height is different, I checked the debugger and font metrics stuff and nothing is exactly 27px or 23px (height without underline offset + width):

enter image description here

FontMetrics debugger:
enter image description here

oracle description of FontMetrics:

enter image description here
https://docs.oracle.com/javase/tutorial/2d/text/measuringtext.html

according to this picture I would get the 24px (height of text) via this calculation:
metrics.getMaxAcsent() + metrics.getMaxDescent
but this already gives me 40px, when the real height with underline is only 27px

I also looked at string bounds:
enter image description here

and I looked into line metrics, which actually gives me underline information which is wrong though, as the underline offset and underline thickness is 4px together:
enter image description here

enter image description here

So I have multiple problems getting correct values for this and I will continue asking questions about correct position if I fixed the height problem. If you need anymore specific information just ask.

xml schema (font default values):

<xs:attributeGroup name="font">
    <xs:attribute name="font" type="xs:string" default="Sans Serif"/>
    <xs:attribute name="font-size" type="xs:positiveInteger" default="12"/>
    <xs:attribute name="font-color" type="hexType" default="#FFFFFF"/>
    <xs:attribute name="bold" type="xs:boolean" default="false"/>
    <xs:attribute name="italic" type="xs:boolean" default="false"/>
    <xs:attribute name="underline" type="xs:boolean" default="false"/>
</xs:attributeGroup>

Draw method:

  @Override
    public void draw(Graphics2D graphics, int rootX, int rootY, int rootWidth, int rootHeight) {
        Font derivedFont = font.font().deriveFont(Map.of(TextAttribute.SIZE, font.fontSize()));
        if (font.bold()) {
            derivedFont = derivedFont.deriveFont(Font.BOLD);
        }

        if (font.italic()) {
            derivedFont = derivedFont.deriveFont(Font.ITALIC);
        }

        if (font.underline()) {
            derivedFont = derivedFont.deriveFont(Map.of(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON));
        }

        // FIXME: 12/04/2023 fix calculations
        FontMetrics fontMetrics = graphics.getFontMetrics(derivedFont);
        int textWidth = fontMetrics.charsWidth(text.toCharArray(), 0, text.length());
        int textHeight = derivedFont.getSize();

        BufferedImage textImage = new BufferedImage(textWidth + (border.width()*2) + 3, textHeight + (border.width()*2) + 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D textGraphics = textImage.createGraphics();
        textGraphics.setComposite(AlphaComposite.Clear);
        textGraphics.fillRect(0, 0, textImage.getWidth(), textImage.getHeight());
        textGraphics.setComposite(AlphaComposite.SrcOver);

        border.draw(textGraphics, 0, 0, textImage.getWidth()-1, textImage.getHeight()-1, textImage.getWidth(), textImage.getHeight());
        textGraphics.setFont(derivedFont);
        textGraphics.setColor(font.fontColor());
        textGraphics.drawString(text, border.width() + 1, fontMetrics.getHeight()/2 + 5); // TODO: 12/04/2023 calculate correct y + correct height of full box

        textGraphics.setColor(new Color(255, 0, 0));
        textGraphics.drawOval(border.width() + 1, fontMetrics.getHeight()/2 + 5, 1, 1);

        textGraphics.dispose();
   }

Edit:
I just noticed aswell that the underline is not working correctly: enter image description here

SquidXTV
  • 74
  • 9

0 Answers0