How to measure space between lines of text drawn on screen? - winapi

We have an end-user application that allows you to write multiple lines of text into a text box, it persists this information to a text file. Upon the next session that information is retrieved from the file to display the text. The problem is sometimes on the next session the bounds of the text box are cutting of the text so the user is having to manually resize the textbox. I'd like to programmatically figure out if the text box needs to be resized.
GetTextExtentPoint32() seems to work well for measuring the actual drawn width of the line based on the current font selected into the Device Context. However now I'm tackling the need to resize the textbox bounds in the vertical direction. GetTextExtentPoint32() does give me the height, which seems correct, but the total height I get is a bit too small. I believe I need to measure the space between each line, but I'm not quite sure?
Update: It looks like I'm looking for TEXTMETRIC.tmExternalLeading and TEXTMETRIC.tmInternalLeading. What's interesting is for some fonts and sizes, the calculation is spot on and I can fit my text perfectly. But for some fonts and sizes, the calculation is a bit too small, in that case it seems the leading is too small or 0?

As long as I remember you can use GetTextMetrics function and (Metrics.tmAscent + Metrics.tmDescent) should be the value you're looking for

Related

DirectWrite renders issues and metric scaling inaccuracy

I have DirectWrite setup to render single glyphs and then shape them programmatically based on the glyph run and font metrics. (Due to my use case, I can't store every full texture in an OpenGL texture otherwise it's essentially a memory leak. So we store each glyph into one texture to lay them out glyph by glyph.)
However, I have two issues:
Inconsistent rendering results.
Scaling metrics leads to inconsistent distances between glyphs.
These results are are transferred to a bitmap using Direct2D and WIC bitmap (CreateWicBitmapRenderTarget).
Let's look at an example, font size 12 with Segoe UI.
Full string rendered 1st line is rendered using DrawTextLayout drawn with D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT. 2nd line is drawn with each Glyph using DrawGlyphRun with DWRITE_MEASURING_MODE_NATURAL. 3rd is rendered with paint.net just for reference.
This leads to the second issue, the distance between each letter can be off. I am not sure if this is a symptom of the previous issue. You can see the distance between s and P is now 2 pixels when drawn separately. Because i is no longer 3 pixels wide, it visually looks too close to c now when zoomed out. p and e look too close.
I have checked the metrics, and I am receiving the right metrics from the font from shaping. Above string metrics from DirectWrite : [1088.0, 1204.0, 1071.0, 946.0, 496.0, 1071.0, 869.0]. I am comparing output with Harfbuzz: [S=0+1088|p=1+1204|e=2+1071|c=3+946|i=4+496|e=5+1071|s=6+869] which is correct.
To convert to DIP I am using this formula for the ratio multiplier: (size * dpi) / 72 / metrics.designUnitsPerEm
So with a default DPI of 96 and default size of 12 we get the following ratio: 0.0078125.
Let's look at S is 1088. So the advance should be 1088 * 0.0078125 = 8.5. Since we can't write between half a pixel, which way do we go? I tried every value from the lsb, to the advance, to render offset in every combination of flooring, ceiling, rounding, converting to int. Whichever way I choose, even if it fixes it for one situation, I'll test with another font, or another size, it will be one or two pixels too close in another string. I just can't seem to find a proper balance that is universal.
I am not really sure where to go from here. Any suggestions are appreciated. Here is the code: https://github.com/pyglet/pyglet/blob/master/pyglet/font/directwrite.py#L1736
EDIT: After a suggestion of using DrawGlyphRun using the full run, it does appear exactly what the DrawTextLayout outputs. So the DrawGlyphRun should produce the same appearance. Here's where it gets interesting:
Line1: DrawTextLayout
Line2: Single glyphs drawn by DrawGlyphRun
Line3: All glyphs drawn using DrawGlyphRun
You can see something interesting. If I render each 'c' by itself (right side), you can see that it has 4 pixels on the left of the character by itself. But in the strings it looks like it's missing. Actually, taking a deeper look, and a color dropper, it appears the color is indeed there, but it's much darker. So somehow each glyph is affecting the blend of the pixels around it. I am not really sure how it's doing this.
EDIT2: Talking with another, I think we narrowed this down to anti-aliasing. Applying the antialias to the whole string vs each character produces a different result. Setting D2D1_TEXT_ANTIALIAS_MODE_ALIASED each character looks and appears exactly the same now compared to both.

Shrink Text in PDF using Ghostscript

Is it possible to shrink the size of text for a PDF Document using Ghostscript?
I've recently posted a question on how to shrink a two page pdf to one page, its close but I think If I can shrink the font a bit it would be perfect. I haven't been able to find anything online suggesting that you can shrink the size of the text... Is it capable of doing this?
Its possible, but it isn't easy and almost certainly won't help you.
You seem to be assuming that text in a PDF file works like it does in (eg) Word. If you change the size of the text then it all shuffles left a bit. In fact this is only partially the case. PDF files are intended to capture a particular layout, so the text description may include absolute positioning on the page, and white space addition/removal between words and glyphs. Changing the point size of the text wouldn't change the absolute positions, nor would it alter the white space which might lead to gaps, or to characters overlapping.
If you use -dPDFFitPage with a specific fixed media size, then you should be able to produce a resized PDF to fit the page you want.

What is the main idea of creating click heatmap?

in one of my projects, I would like to create heatmap of user clicks. I was searching a while and found this library - http://www.patrick-wied.at/static/heatmapjs/examples.html . That is basically exactly what I would like to make. I would like to create heatmap in SVG, if possible, that is only difference.
I would like to create my own heatmap and I'm just wondering how to do that. I have XY clicks position. Each click has mostly different XY position, but there can be exceptions time to time, a few clicks can have the came XY position.
I found a few solutions based on grid on website, where you have to check which clicks belong into the same column in this grid and according to these informations you are able to fill the most clicked columns with red or orange and so on. But it seems a little bit complicated to me and maybe slower for bigger grids.
So I'm wondering if there is another solution how to "calculate" heatmap colors or I would like to know the main idea used in library above.
Many thanks
To make this kind of heat map, you need some kind of writable array (or, as you put it, a "grid"). User clicks are added onto this array in a cumulative fashion, by adding a small "filter" sub-array (aligned around each click) to the writable array.
Unfortunately, this "grid" method seems to be the easiest, simplest way to get that kind of smooth, blobby appearance. Fortunately, this kind of operation is well-supported by software and hardware, under the name "computer graphics".
When considered as a computer graphics operation, the writable array is called an "accumulation buffer". The filter is what gives you the nice blobby appearance, even with a relatively small number of clicks -- you can tweak the size of the filter according to the needs of your application.
After accumulating the user clicks, you will need to convert from the raw accumulated values to some kind of visible color scale. This may involve looking through the entire accumulation buffer to find the largest value, and mapping your chosen color scale accordingly. Alternately, you could adjust your scale according to the number of mouse clicks, or (as in the demo you linked to) just choose a fixed scale regardless of the content of the buffer.
Finally, I should mention that SVG is not well-adapted to representing this kind of graphic. It should probably be saved as some kind of image file (.jpg or .png) instead.

Determine how wide a textbox or text area should be to hold three lines

I'm trying to figure out how to size a text box to closely fit three lines of wrapped text. I'm working in vb6, but I'll accept an answer in any language if I can understand it.
The problem is that I have a flexgrid with long headings and room for three lines of text in them, and I want to resize the text area to exactly fit three lines of text without the text wrapping to a fourth line and the text width should be as narrow as possible.
I realize that if I can figure out how to do it for a textbox or a label I will have more or less solved the problem. Possibly it can be done with the Windows API, but any advice will be appreciated.
I'm not as familiar with windows development but I have a .net assembly that prints labels and in the UI a user would use to add information to the label, I need to calculate the length of the overall text against the number of lines they say they want the text to fit on and if I determine the text is to long to fit on (x) number of lines based on the text they provide and the font size they specify, I shrink the font size, recalculate, and repeat until it all fits.
Depending on the font you are using, whether it's monospaced or not, the length is going to be different (monospace will obviously have the width of each character the same, non-monospaced will be different based on the character... like the different between M and I).
In my c#.net applications I'm using the Graphics.MeasureString (textString, font[name,size,style,units]) to tell me how wide my string is.
You may have something similar available. If you can calculate the width of the text string you can divide by 3 and apply the number of columns accordingly.

Visual Format Language - padding area

I have several objects that are static in size that hug the top and bottom of the screen. However, there is a blank area in the middle of the screen that I would like to stretch with orientation change.
I have solved an issue by adding an extra clear view [paddedView] that can be stretched but wanted to know if there was an easier way to do this without the paddedView just with Visual Format Language.
#"V:|-20-[topLabel(40)]-15-[anotherTopLabel(40)]-[paddedView]-[bottomView(73)]|";
Instead of a view used only for padding, you can either specify a lower priority to a distance or specify the constraint as "greater than or equal to".
Since what you want is a flexible space, the last option sounds like the best one:
#"V:|-20-[topLabel(40)]-15-[anotherTopLabel(40)]-(>=15)-[bottomView(73)]|"
The number 15 is of course just an example.

Resources