Font Kerning / ATSU question
|
|
Thread rating:  |
a.d. jensen - 30 Oct 2004 23:02 GMT (Sorry for the cross-post, I realized after posting that c.s.m.p.misc was probably not the best place for this... also, I'm using CW 9.3 on OS 10.3.5, if that makes any difference.)
I am writing the Mac OS side of a Windows/Mac application, and I'm having a major issue with font spacing. It's critical that this program prints exactly the same, regardless of which platform it's running on. For the most part, all is well, but several of the fonts that we're printing are SLIGHTLY different on the two platforms.
The fonts are printing fine on Windows, they're slightly expanded when printed on the Mac. Basically, they need to be 10 characters per inch, and they're coming out a little wider than that. Right now, I'm printing with QuickDraw, so it seems that my options of printing these items is limited. My testers indicate that printing out of TextEdit (or SimpleEdit, or something like that) has the same results as my program, while printing out of Microsoft Word for OS X is perfect (10 characters per inch.)
(As an aside, printing in "condense" style results in the characters being too close together.)
So, question one is whether there's any way to adjust font kerning or spacing when using Quickdraw.
Okay, going under the assumption that that wouldn't be an option, I went to look into Quartz and ATSU. Sure enough, there's a handy method for adjusting kerning. Unfortunately, I can't seem to get it working. Here's some code:
The two snippets below call the functions which follow them. The only thing different is the last bit of the "MakeATSUIStyle" call, which leaves kerning alone in the first iteration, says to inhibit it by half in the second.
When printed, these two text strings are exactly the same length, leading me to believe that my kerning call is doing absolutely nothing.
Any help would be appreciated -- I'm really in uncharted waters with these font issues!
iErr = MakeATSUIStyle(0, normal, 12, &theStyle, X2Frac(0)); CFStringRef ourString = CFStringCreateWithPascalString(NULL, "\pThis is a test", kCFStringEncodingMacRoman); iErr = RenderCFString(context, ourString, theStyle, thePoint.h, 0 - thePoint.v); CFRelease((CFTypeRef)ourString); thePoint.v += 20;
iErr = MakeATSUIStyle(0, normal, 12, &theStyle2, X2Frac(0.5)); ourString = CFStringCreateWithPascalString(NULL, "\pThis is a test", kCFStringEncodingMacRoman); iErr = RenderCFString(context, ourString, theStyle2, thePoint.h, 0 - thePoint.v); CFRelease((CFTypeRef)ourString);
static OSStatus MakeATSUIStyle(short fontFamily, Style fontStyle, short fontSize, ATSUStyle *theStyle, Fract kerningInhibitFactor) { OSStatus err; ATSUStyle localStyle; ATSUFontID atsuFont; Fixed atsuSize; short atsuOrientation; Boolean trueVar = true, falseVar = false;
/* Three parrallel arrays for setting up attributes. */ ATSUAttributeTag theTags[] = { kATSUFontTag, kATSUSizeTag, kATSUVerticalCharacterTag, kATSUQDBoldfaceTag, kATSUQDItalicTag, kATSUQDUnderlineTag, kATSUQDCondensedTag, kATSUQDExtendedTag }; ByteCount theSizes[] = { sizeof(ATSUFontID), sizeof(Fixed), sizeof(UInt16), sizeof(Boolean), sizeof(Boolean), sizeof(Boolean), sizeof(Boolean), sizeof(Boolean) }; ATSUAttributeValuePtr theValues[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
/* set up locals */ localStyle = NULL; atsuFont = 0; atsuSize = FixRatio(fontSize, 1); atsuOrientation = kATSUStronglyHorizontal; /* or atsuOrientation = kATSUStronglyVertical */
/* set the values array to point to our locals */ theValues[0] = &atsuFont; theValues[1] = &atsuSize; theValues[2] = &atsuOrientation; theValues[3] = ((fontStyle & bold) != 0 ? &trueVar : &falseVar); theValues[4] = ((fontStyle & italic) != 0 ? &trueVar : &falseVar); theValues[5] = ((fontStyle & underline) != 0 ? &trueVar : &falseVar); theValues[6] = ((fontStyle & condense) != 0 ? &trueVar : &falseVar); theValues[7] = ((fontStyle & extend) != 0 ? &trueVar : &falseVar);
err = ATSUFONDtoFontID( fontFamily, fontStyle, &atsuFont); if (err != noErr) goto bail;
/* create a style */ err = ATSUCreateStyle(&localStyle); if (err != noErr) goto bail;
/* set the style attributes */ err = ATSUSetAttributes( localStyle, sizeof(theTags)/sizeof(theTags[0]), theTags, theSizes, theValues ); if (err != noErr) goto bail; if (kerningInhibitFactor) { OSStatus status = noErr; ATSUAttributeTag theTag; ByteCount theSize; ATSUAttributeValuePtr theValue;
theTag = kATSUKerningInhibitFactorTag; theSize = (ByteCount) sizeof(Fract); theValue = (ATSUAttributeValuePtr) &kerningInhibitFactor;
status = ATSUSetAttributes(localStyle, 1, &theTag, &theSize, &theValue); }
/* store the new style for the caller */ *theStyle = localStyle; return noErr; bail: if (localStyle != NULL) ATSUDisposeStyle(localStyle); return err; }
static OSStatus RenderCFString(CGContextRef ctx, CFStringRef theString, ATSUStyle theStyle, short h, short v) { ATSUTextLayout theLayout = NULL; CFIndex textLength; OSStatus err = noErr; UniChar *uniBuffer; CFRange uniRange; /* set up our locals, verify parameters... */ if (theString == NULL || theStyle == NULL) return paramErr; uniBuffer = NULL; textLength = CFStringGetLength(theString); if (textLength == 0) return noErr; /* get our data */ uniRange = CFRangeMake(0, textLength); uniBuffer = (UniChar *) NewPtr( textLength * sizeof(UniChar) ); if (uniBuffer == NULL) { err = memFullErr; goto bail; } CFStringGetCharacters( theString, uniRange, uniBuffer);
/* create the ATSUI layout */ err = ATSUCreateTextLayoutWithTextPtr( uniBuffer, 0, textLength, textLength, 1, (unsigned long *) &textLength, &theStyle, &theLayout); if (err != noErr) goto bail;
if(!err) { // Assign the CGContext to the layout // so the text is imaged into the CG Context supplied ByteCount iSize = sizeof(CGContextRef); ATSUAttributeTag iTag = kATSUCGContextTag; ATSUAttributeValuePtr iValuePtr=&ctx; ATSUSetLayoutControls( theLayout, 1, &iTag, &iSize, &iValuePtr ); }
/* draw the text */ err = ATSUDrawText(theLayout, 0, textLength,// kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); FixRatio(h, 1), FixRatio(v, 1)); if (err != noErr) goto bail;
/* clean up */ bail: if (uniBuffer != NULL) DisposePtr((Ptr) uniBuffer); if (theLayout != NULL) ATSUDisposeTextLayout(theLayout); return err; }
Reinder Verlinde - 31 Oct 2004 09:38 GMT > I am writing the Mac OS side of a Windows/Mac application, and I'm > having a major issue with font spacing. It's critical that this program > prints exactly the same, regardless of which platform it's running on. > For the most part, all is well, but several of the fonts that we're > printing are SLIGHTLY different on the two platforms. If the fonts _are_ different, there is nothing you can do. I assume that you mean "we use the same fonts, but they print slightly different".
> The fonts are printing fine on Windows, they're slightly expanded when > printed on the Mac. Do you make this statement because your reference is the Windows printout, or because you have another way to deduce that?
> Basically, they need to be 10 characters per inch, > and they're coming out a little wider than that.
> Right now, I'm > printing with QuickDraw, so it seems that my options of printing these > items is limited. My testers indicate that printing out of TextEdit (or > SimpleEdit, or something like that) has the same results as my program, > while printing out of Microsoft Word for OS X is perfect (10 characters > per inch.) Microsoft probably went to great lengths to get consistent line breaks in Word across operating systems.
> So, question one is whether there's any way to adjust font kerning or > spacing when using Quickdraw. To mention a few:
DrawJustified <http://developer.apple.com/documentation/Carbon/Reference/QuickDraw_Text /qdtext_refchap/function_group_2.html#//apple_ref/doc/uid/TP30000026/F012 70>
CharExtra, SpaceExtra <http://developer.apple.com/documentation/Carbon/Reference/QuickDraw_Text /qdtext_refchap/function_group_5.html#//apple_ref/doc/uid/TP30000026/TPXR EF106>
SetFractEnable <http://developer.apple.com/documentation/Carbon/Reference/Font_Manager/i ndex.html> (it is unlikely that this will help)
This is not a simple subject. It will help/be necessary to read quite a bit 'around' the links I gave .
My guess is that DrawJustified will do the trick. Obtain a slop value from a call to TextWidth or MeasureText.
Reinder
a.d. jensen - 31 Oct 2004 17:04 GMT > > I am writing the Mac OS side of a Windows/Mac application, and I'm > > having a major issue with font spacing. It's critical that this program [quoted text clipped - 4 lines] > If the fonts _are_ different, there is nothing you can do. I assume that > you mean "we use the same fonts, but they print slightly different". Yes, sorry. The fonts are exactly the same, but they're not printing out the same with the Mac version.
> > The fonts are printing fine on Windows, they're slightly expanded when > > printed on the Mac. > > Do you make this statement because your reference is the Windows > printout, or because you have another way to deduce that? Yes. The fonts in question are indeed (to answer another poster's question) mono spaced fonts like Courier, and some bar codes, that will be read in by a scanner. I am told by the person in my QA department who's in charge of this issue that there is essentially no "give" on the issue -- the printing on Windows is "perfect" and certified by whoever does that sort of thing, and that, if the Mac version isn't exactly the same (eg: put both pages on a light table and see no differences at all) it won't work.
> > Basically, they need to be 10 characters per inch, > > and they're coming out a little wider than that. [quoted text clipped - 8 lines] > Microsoft probably went to great lengths to get consistent line breaks > in Word across operating systems. And, no doubt, I'll have to go through the same lengths :-) Sadly, the fact that they did draws an immediate assumption from non-programmers in QA that "if they did it, you can do it." True enough, I suppose, but I'm not a team of programmers at Microsoft.
> > So, question one is whether there's any way to adjust font kerning or > > spacing when using Quickdraw. [quoted text clipped - 20 lines] > My guess is that DrawJustified will do the trick. Obtain a slop value > from a call to TextWidth or MeasureText. Thanks for the links, I'll read up on the whole matter and play around with it. Being able to stay in QD will save a bunch of work, at the very least. So long as it works in QD, I'm happy to save the eventual Quartz conversion for another time.
dale
Eric Albert - 31 Oct 2004 19:17 GMT > Yes. The fonts in question are indeed (to answer another poster's > question) mono spaced fonts like Courier, and some bar codes, that will [quoted text clipped - 4 lines] > same (eg: put both pages on a light table and see no differences at all) > it won't work. If you haven't already, I'd suggest posting about this to Apple's carbon-development or quartz-dev mailing lists. You're likely to run into a few people there who have had exactly the same problem before.
See <http://lists.apple.com/> for Apple mailing list information.
-Eric
 Signature Eric Albert ejalbert@cs.stanford.edu http://outofcheese.org/
Michael Ash - 31 Oct 2004 19:22 GMT In comp.sys.mac.programmer.help a.d. jensen <adjensen@yahoo.com> wrote:
> Yes. The fonts in question are indeed (to answer another poster's > question) mono spaced fonts like Courier, and some bar codes, that will [quoted text clipped - 4 lines] > same (eg: put both pages on a light table and see no differences at all) > it won't work. It seems to me that since your requirements are so strict, it may not be too hard to do the layout yourself. That is, draw your strings character-by-character and figure out the location of each character yourself. Since you already know exactly how large each character should be for your application, that should work out fairly well.
a.d. jensen - 31 Oct 2004 21:21 GMT > DrawJustified > <http://developer.apple.com/documentation/Carbon/Reference/QuickDraw_Text > /qdtext_refchap/function_group_2.html#//apple_ref/doc/uid/TP30000026/F012 > 70> Well, this appears to do the trick. By modifying the "numer/denom" fields, I'm able to very finely adjust the spacing. Changing the "slop" parameter doesn't seem to affect it at all, but the others do. Now I'll just add some mechanism of allowing the QA people to modify the values themselves, and they can fine tune it to their hearts content.
Thanks!
Eric VERGNAUD - 31 Oct 2004 10:56 GMT dans l'article adjensen-1A0154.17022230102004@news.isp.giganews.com, a.d. jensen à adjensen@yahoo.com a écrit le 31/10/04 0:02 :
Very frankly, having dealt with this subject a lot, I've come to the conclusion that this goal is not achievable simply, for many reasons: - the fonts Used on Mac and Windows are not the same - the printer drivers on Mac and Windows are not the same - MacOS is wysiwyg, what you have on screen is what you get on the printer. On Windows, to achieve this, you need to adjust the kerning (the Win32 API says: wysiwyg is often "undesirable"). You need to use ExtTextOut and get the char widths from the printer, not the display.
The only reliable ways I know to ensure identity between the 2 platforms are the following: - adjust the kerning on the Windows side. The MacOS side is usually correct. - use a postscript printer and send postscript instructions - have your own built-in font kern tables for each commonly used font, and use these tables for displaying on screen and printing
I'm a little puzzled by your saying the font needs to be 10 characters per inch. This means you can anly use fixed-with fonts like Courier, because with regular fonts, iiiii will aways be narrower than mmmmm.
Now if TextEdit does the job, why not call TETextbox ?
> (Sorry for the cross-post, I realized after posting that c.s.m.p.misc > was probably not the best place for this... also, I'm using CW 9.3 on OS [quoted text clipped - 181 lines] > return err; > } Uli Kusterer - 31 Oct 2004 14:20 GMT > Now if TextEdit does the job, why not call TETextbox ? I think he meant TextEdit.app, which is an application that uses the Cocoa text system. Apart from that, even if I got him wrong and he really meant the good old TextEdit Manager, he could be annoyed by that not supporting Unicode or by its 32k limit ...
Just guessing, -- Uli http://www.zathras.de
a.d. jensen - 31 Oct 2004 17:29 GMT > Very frankly, having dealt with this subject a lot, I've come to the > conclusion that this goal is not achievable simply, for many reasons: [quoted text clipped - 12 lines] > - have your own built-in font kern tables for each commonly used font, and > use these tables for displaying on screen and printing Tragically, I've found pretty much zero buy in when I suggest this. But the Windows program has been shipping for several years, and the issue has largely been left up to me to fix.
> I'm a little puzzled by your saying the font needs to be 10 characters per > inch. This means you can anly use fixed-with fonts like Courier, because > with regular fonts, iiiii will aways be narrower than mmmmm. Yes, the text in question is monospaced font + bar codes, which need to be read by a scanner. I'm told that there is no margin for error -- what Windows prints out is exactly what needs to come out on the Mac side.
> Now if TextEdit does the job, why not call TETextbox ? Sorry, I guess I didn't make that very clear -- I'm told that it prints out WRONG from the TextEdit.app program. Given the font set, which is the same on Windows as Mac, the only application that my researchers have found prints the same on the Mac as it does on Windows is MS Word. Everything else prints it a little too wide.
Thanks for the info, I'll use it as a backup if I have to go back to them and say that it can't be done with the existing fonts.
Reinder Verlinde - 31 Oct 2004 17:53 GMT > Yes, the text in question is monospaced font + bar codes, which need to > be read by a scanner. I'm told that there is no margin for error -- > what Windows prints out is exactly what needs to come out on the Mac > side. I find it hard to believe that things are as rigid as you are suggesting. In real life, 'exactly' does not exist. That is why interconnection standards always allow margins on both sides, with some extra margin added for safety (say 'print must be within 9.8 and 10.2 cpi; scanners must handle anything between 9.5 and 10.5 cpi')
But back to your problem: what do you mean when you say "Everything else prints it a little too wide". Is this a matter of spacing or are the characters a little too wide? (can you print individual characters that satisfy your QA department? does this work for all characters, or are there exceptions?). If it is a matter of spacing, is it inter-word spacing (can you print words that satisfy your QA department?), inter-character spacing or both? (can you put some pdf's showing correct and incorrect prints of e.g. "the quick brown fox" data on the web?)
Reinder
Florian Zschocke - 31 Oct 2004 13:00 GMT Hi, i don't have so much experience with font rendering, but in general if I would like to have a similar output on different platforms, I would try to use pdf - generation with embedded fonts. Since this format was specially designed to avoid these problems. What I don't know is if there is api in windows you could use.
Florian --
|
|
|