سؤال

I'm using DirectWrite to render some text to a window. Everything seems to work except positioning when using different font sizes: I'd expect 2 texts with font size v1 and v2 and both with (x, y) = (0, 0) to be at the top left but as you can see:

enter image description here

neither "Test" nor "X" are really at the top left.

Is there a way to make this work?

هل كانت مفيدة؟

المحلول

Welcome to the world of fonts. Fonts are probably the most difficult thing to use, because there is surprises in font themselves ( there is so many new standards that supposed to solves everything and just confuse more because almost no font support it at 100%, even some 'classic' font have partial/bad information in them) the GDI, GDI+, DirectDraw don't draw font at the same position in pixels because of math, coordinate rounding, anti-aliasing... ( you can have one more bonus if you do the math with freetype ).

When you try to print the font there are other pb. So the only way around this is for me. Don't even try to draw font at certain pixel coordinates. Do your job at drawing font, picture, lines on the screen that render well, do your best to convert them to printing coordinate for exports but never expect to control pixel in fonts, everything is round approximates.

PS : Don't trust internal fields in fonts. On Arial they are good on all other fonts some are missing or initialised to zero, but the "fun" part it's not always the same field which are not present it depends of the fonts. You could only use the fields if you try them before by font. Yes fonts are fantastic!

نصائح أخرى

The term @evilruff is referring to is called 'internal leading'. You can use IDWriteFontFace::GetMetrics or possibly IDWriteFontFace::GetDesignGlyphMetrics to get this value (for GetMetrics, the value you're looking for is most likely metrics.ascent - metrics.capHeight).

The values here are in Font Design Units, not pixels (of any sort). You can convert these values to em height by dividing by metrics.designUnitsPerEm; typically, font sizes in DirectWrite are specified by the pixel size of the (lowercase) m; so if you multiply the values in ems by the font size, you should get the values in pixels.

I'm assuming you are using an IDWriteTextLayout in conjunction with DrawTextLayout (rather than creating your own DWRITE_GLYPH_RUN). IDWriteTextLayout aligns glyphs to their layout cell (including the full ascent and line gap), not the glyph ink, and this is true of pretty much all text layouts, be they web browsers or word processors or simple edit controls. If they did not (instead aligning to the top of the letter), then diacritics in words like Ťhis would be clipped.

If you always want to align to the ink, create an IDWriteTextLayout, call IDWriteTextLayout::GetOverhangMetrics, and then call DrawTextLayout with an origin equal to negative DWRITE_OVERHANG_METRICS::left&top. If you want to align to the cap-height always (that way "hello" and "Hello" would both draw at the same vertical coordinate), then Eric's approach will work.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top