Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion Groups
General
GeneralPortable MacsHardwareNetworking
Applications
Mac ApplicationsEudoraFirefox / MozillaInternet ExplorerOutlook ExpressMS OfficeEntourageExcelPowerPointWordVirtual PCMedia PlayerOther MS Products
Programming
Mac ProgrammingCodeWarriorPerl
Country Specific
Australian Mac GroupUK Mac Group

Mac Forum / Programming / Mac Programming / October 2004



Tip: Looking for answers? Try searching our database.

Font Kerning / ATSU question

Thread view: 
Enable EMail Alerts  Start New Thread
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
--
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.