Font Width Ratios: GetTextExtent32 versus Word and PDF - winapi

GetTextExtent32 returns different character width ratios (e.g., width of '9' versus space) than Word or Acrobat use when displaying the same font (e.g., 10-point Arial).
This matters because I'm trying to prepare clipboard strings that will get pasted into apps that don't support much formatting (no tabs or tables), but I still need to align certain columns of info. I'm trying to overcome this challenge by dynamically calculating the number of spaces I need to insert (remember, no tabs allowed!).
For example, calling GetTextExtent32 with a selected font of Arial 10-point gives a logical unit width of 7 for the digit '9', and a logical unit width of 4 for a space. This ratio proves correct when using something like DrawText.
However, when I export strings to Word or Acrobat, it turns out that 2 spaces in this example font exactly equals the width of one 9 (whether looking at a single 9, or nine contiguous 9s). I don't know much about fonts, but it doesn't appear to be any kind of juxtaposition issue; GetCharABCWidths shows 0 for both the a and c widths.
Does anyone know why Word and Acrobat are not showing the same proportions/measurements for a given font as Windows itself? Is there are a way to calculate this?

Related

GetCharABCWidthsFloat works for most of UNICODE, except CJKV characters

I am attempting to render a series of UNICODE characters onto a spritesheet. This all works quite well for most characters, including Cyrillic ones.
When using GetCharABCWidthsFloat with certain CJKV characters however, the ABCFLOAT::abcfB parameter provides a value lower than expected. It does not account for underhangs or overhangs, which is the exact purpose of the ABCs:
The B spacing is the width of the drawn portion of the character glyph.
Source: ABCFLOAT | Microsoft Docs
As you can see, all characters do not overlap left-to-right, except the last few characters:
I get around this by creating a customizable padding option, to handle such cases, but this bloats the rest of the glyphs and thus requires a larger surface:
Font being used is Arial. For the character 美, ABC returns (2, 10, 2), which sums to a advance of 14 pixels, when in fact, 17 pixels are needed.
I use TextOut to actually render the glyphs, but I do wonder if there is someone out there who's experienced this and came up with a universal solution.
Using functions like GetTextExtentPoint32W or DrawTextEx to get the rectangle does not allow precise per-character placement, which is the whole point of the ABC. And some unmentioned functions only work with TrueType fonts.
I question if certain characters shift to a different font under certain conditions, causing the results to be inaccurate. If that is the case, is there a way to determine if a character is not available for a font, knowing what Windows does automatically so I can reproduce the behaviour? That is, is there some sort of way to determine when a character should fall back on another font, and a way to determine what that font should be?
I have been on this problem for quite some time, so anyone with experience with these APIs would be greatly welcomed!
From the documentation on GetCharABCWidthsFloat:
The ABC widths of the default character are used for characters outside the range of the currently selected font.
Arial contains a lot of characters, including Cyrillic, but it does not contain CJKV ideographs. Other text-related calls may give you the false impression that it does have those characters (through a default/fallback font mechanism).
Before using (maybe before getting) the ABCFLOAT, you should first check that the characters you want metrics for are within the range of the currently selected font.

MacOS CALayer Character Spacing

I have a problem which I hope you can help me solving.
I'm creating a program using Xamarin.Mac (C# for Mac) and I need to draw a DNA sequence (ATGC and so on). However, I need to know the exact position of each character so I can draw several other objects which should be aligned with the characters in DNA sequence.
Screenshot of the Windows version of my app which illustrates the behavior I'm looking for:
Currently I'm looking to use the CALayer drawing method, which appears to be fast enough to render 12 lines of 70 characters in less than 50 ms. CALayers are not fast enough to render 1000 CATextLayers with one (A/T/G/C) character each, so (I think) I need to render them as lines with specific spacing. This means that I need to have exactly 10 (example) pixels between the center of each character.
However, I cannot find a way to do this.
The NSAttributedString Kerning seems be added to an unknown existing tracking (or spacing) of the font, and thus may be used with monospace fonts but still results in an unknown actual spacing.
I CAN get around the issue by trial and error until the letter spacing appears to match the desired spacing, but I'm not very confident in robustness of this method across different devices (screen resolutions). This requires that I use a monospace font, which is okay, but not optimal.
Is it possible to have specific character spacing using a single CATextLayer and what are my options if not? is it possible to have 1000 characters drawn individually without a huge performance impact?
Thank you.

How to calculate the width (in dots) of this zpl barcode?

^XA
^FO0,90^AD^BY3
^BCN,100,Y,N,Y,A
^MD10
^FD1458622235534^FS
^XZ
Using Label Viewer I was able to play around with ZPL and after reading some documentation figured out that ^FO0,90 is what positions the barcode. 0 is for the number of dots from the left and 90 is for the number of dots from the top.
My question is, how can the width of the above bar code be calcuated in dots? If I know the width of the barcode, I can then center it programmatically.
The printer's resolution is 203dpi and given a 3' (width) x 2' (length) tag, that is 610 dots across.
What is the formula to calculate the width of a ZPL Barcode?
The Code 128 barcode includes three modes. The "A" in your ^BC means that the barcode algorithm will automatically select the best mode based on the placement of where the letters are mixed in with the numbers, and/or how many numbers are in a row. This results in barcodes that vary in length depending on their content.
You can change that A to an N. This will make the width easy to estimate, even if it's not the most space efficient.
For the N option: count 106 dots, total, for the bookends, and 33 dots for each digit.
For the N + Subset C option: If you can say for sure that you will always have an even number of digits (no letters, spaces, or other symbols). You can force the barcode into subset C mode. Count 104 dots for the bookends, and 33 dots for every two digits. But you must have an even number of digits.
^BCN,100,Y,N,Y,N
^FD>;1422335544^FS
The >; tells ZPL to render this as subset C.
If you know that you will need to support alphanumeric barcodes, then stick with the A. This is where things get harder.
You will need to model the barcode algorithm in your programming language of choice. Perhaps you could find an existing library, as Code 128 is a very popular barcode. Use the library to render the barcode in memory. You may have to play with the parameters to get it to produce a barcode equal to your ZPL output. Then have your program use the output of the library to determine the width of the barcode.
If your barcode is always going to be 13 digits, then automatic centering is a moot point. The barcode will always be the same width, even in automatic mode. Find the ^FO that looks like it's centered on the label, and stick with that. This barcode is 368 dots wide. Try ^FO121,90.
I didn't calculate the width of the barcode, I measured it by rendering the label to a Gif and then examining the label in a paint program that would let me count the dots.
I suggest you have a look at the Code 128 wikipedia article for the details.
The natural unit of length for code 128 is the narrow bar width noted x (in your ZPL code set to 3 dots). A code 128 barcode (excluding the two 10x quiet zones) is made up of
a start character (11x wide)
n encoded character of width 11x
a CRC (11x wide)
a stop character (12x wide)
If your data takes n encoded characters, the length of the barcode is (34 + n*11)x. In your case, x is 3 dots, so at 8dot/mm the barcode will be (12.75 + n*4.125)mm wide.
You have to look into the encoding to figure out n. Minimal encodings are not unique, but in your case the data will be encoded with 8 barcode characters: 6 code C character (for 6 pairs of digits), 1 switch code character and 1 code A character (for the last digit). The barcode should be 45.75mm / 366dot wide.
There is a little issue with your ZPL. You specified a UCC checkcode on a non UCC barcode. I am not familiar with UCC/GS1-128 barcodes but that might introduce extra barcode characters or be irrelevant.
Also you might consider padding your timestamp with a leading 0. With Code 128, pairs of digit have a better encoding. A 14-digit barcode will be be 4.125mm shorter.
I just mentionned the quiet zone, barcode readers require them.

Tab length in Sublime Text on Mac not correct

I bought a new iMac 27 inch and one of the first things I did was installing my text editor of choice, Sublime Text. After a bit of writing code I noticed that the indentation with tabs is to wide. In the bottom left corner it says Tab Size: 4 but in fact one tab is as wide as 12 spaces. When changing the setting to Tab Size: 2 one tab is as wide as 6 spaces.
Could it be that Sublime multiplies the length of one tab with 3 because of the large resolution (2560 x 1440)? Does anybody know how to fix this issue?
EDIT:
I use the Ubuntu Mono font with 16px font size. When setting the option Indent Using Spaces everything works as expected. Here an image of the current situation with Tab Size: 4.
Sublime works fine on my iMac, so the screen resolution isn't the issue. Instead, I would suspect that you are using a proportional font instead of a fixed-width one. A likely cause of this is lacking the specified font on your new system - I use a non-system font with Sublime, and so need to install it on new computers before everything looks right to me.
With a proportional font, spaces tend to be rather small, especially when compared to "large" characters like D, W, e, s, etc., that take up a proportionally larger amount of horizontal space (hence the name proportional font). Additionally, a tab character may be calculated by Sublime to be a certain size as a function of the pixel size of the font, and so may bear no relation to the actual number of space characters it takes to equal the size of the tabstop. I know that in programs such as MS Word, tabstops are set in fractions of an inch (or cm, or pica, or whatever), and have no relation to the type or size of font being used.
All this is simplified with fixed-width fonts. All characters (even Unicode ones) take up the same horizontal width. Sublime calculates the width of tabs using the standard character width, so everything is consistent.
All that being said, how to fix your problem? The easiest way to determine if this actually is the problem is to set your "font_face" setting to Menlo, an Apple-designed fixed-width font that's been on all their systems since the early days of the Macintosh. If your code goes back to looking like normal, that was the issue. You can then search for whichever font you were using before, if you like, or take a look at my favorite font, linked above, or just keep using Menlo if you're not too picky.
Good luck!

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.

Resources