toms@fcs260c2.ncifcrf.gov (Tom Schneider) (10/09/90)
I would like to make some characters of a precise size, for example, 10.3 cm high. I am being thwarted because fonts are not consistent between PostScript printers. That is, if I draw a character to fit just outside a rectangle and show it on NeWS, then the same program makes the character INSIDE the rectangle when printed to a LaserWriter ntxII. This Is Frustrating! :-( Is there any way to rescale the font so that it is the same size on all printers? For example, is there an easy way to get a hold of the exact character size so as to correct for these non-standard effects? (And I thought PostScript was supposed to be a standard language, hruummph! Aren't there people working on making this more standard?) Another way to do this would be to create my own fonts entirely from scratch. Examples are at the end of the cookbook, but I'd hate to type them in (;-). Does anyone have a copy or working example I could use? (I can't use it if it has a copyright restriction, but I always include original author information in the program.) If I could build a font from scratch, then it would solve another problem I have, which is that in the font I prefer (Helvetica-Bold), some of the characters reach above and below the line they rest on. That is, relative to an A, the letters C and G extend above and below the lines. This is a royal pain for what I'm doing. So far, I have had to empirically figure out scale factors to correct for this. It would be nice to have a clean solution, like a font which I have complete control over. Thanks in advance, Tom Schneider National Cancer Institute Laboratory of Mathematical Biology Frederick, Maryland 21702-1201 toms@ncifcrf.gov ps If you've gotten this far, you might want to know what it's for. I want to create stacks of letters. The height of the stack is pre-defined, as are the relative heights of each letter in the stack. You can get some examples by ftp from 'ncifcrf.gov' in 'pub/delila' get the compressed PostScript files: lambcro.logo.Z ribosome.logo.Z t7.logo.Z globin.logo.Z (Please send me email if you do pick them up.) These sacks are called 'sequence logos'. They are a new way to represent DNA, RNA or protein sequence patterns. We have a paper in press in Nucleic Acids Research, preprints are available.
kevina@apple.com (This space for rent) (10/10/90)
In article <1902@fcs280s.ncifcrf.gov> toms@fcs260c2.ncifcrf.gov (Tom Schneider) writes: > I would like to make some characters of a precise size, for example, > 10.3 cm high. I am being thwarted because fonts are not consistent > between PostScript printers. That is, if I draw a character to fit just > outside a rectangle and show it on NeWS, then the same program makes the > character INSIDE the rectangle when printed to a LaserWriter ntxII. > > This Is Frustrating! :-( > > Is there any way to rescale the font so that it is the same size on all > printers? For example, is there an easy way to get a hold of the exact > character size so as to correct for these non-standard effects? (And I > thought PostScript was supposed to be a standard language, hruummph! > Aren't there people working on making this more standard?) > The problem facing you is that, while the PostScript language is more or less standard, the font shapes depend on the designer, type vendor, or language implementation. The fonts used in NeWS are not exactly the same as those from Adobe, which are not the same as those from Bitstream, which are not the same as the original lead type, etc. (This is an industry-wide issue.) One way to compensate for this in PostScript is to use the charpath and pathbbox operators and scale appropriately. This routine takes a fontname, a string, and a height in points, and scales the font so that every character in the string prints at the same height. It also adjusts the currentpoint so that every character rests on the baseline (try it with "g"!). The results are pretty hideous for anything except what you are trying to do: /heightshow { % fontname string height heightshow - /ht exch def /str exch def /fnt exch def /s1 1 string def str { % for each char in the string s1 0 3 -1 roll put % convert char to string gsave newpath 0 0 moveto fnt findfont setfont s1 true charpath flattenpath pathbbox % compute bounding box of 1 pt. char 2 index sub % ury - lly = char height ht exch div % scale for char to match req. height /scalefactor exch def pop % don't need urx scalefactor mul % adjust lly so char sits on baseline /yadjust exch def pop % don't need llx grestore fnt findfont scalefactor scalefont setfont 0 yadjust neg rmoveto s1 show 0 yadjust rmoveto } forall } bind def /ptspercm 72.0 2.54 div def 36 36 moveto /Helvetica-Bold (C) 10.3 ptspercm mul heightshow showpage > If I could build a font from scratch, then it would solve another problem > I have, which is that in the font I prefer (Helvetica-Bold), some of the > characters reach above and below the line they rest on. That is, relative > to an A, the letters C and G extend above and below the lines. This is a > royal pain for what I'm doing. So far, I have had to empirically figure > out scale factors to correct for this. It would be nice to have a clean > solution, like a font which I have complete control over. > Having rounded characters extend above and below the lines may be a royal pain for what you are doing, but it is essential for legible typography. (To see this, print something like "CHEOPS" with the heightshow routine... the rounded characters will appear smaller than the non-rounded characters!) --Kevin Andresen [kevina@apple.com] "Technically, Sen. Helms is a member of the arachnid family."
toms@fcs260c2.ncifcrf.gov (Tom Schneider) (10/11/90)
In article <10628@goofy.Apple.COM> kevina@apple.com (This space for rent) writes: >In article <1902@fcs280s.ncifcrf.gov> toms@fcs260c2.ncifcrf.gov (Tom >Schneider) writes: >> I would like to make some characters of a precise size, for example, >> 10.3 cm high. > /heightshow { % fontname string height heightshow - This works beautifully! Thanks Kevin! >--Kevin Andresen [kevina@apple.com] Tom Schneider National Cancer Institute Laboratory of Mathematical Biology Frederick, Maryland 21702-1201 toms@ncifcrf.gov
shiva@well.sf.ca.us (Kenneth Porter) (10/11/90)
When I need to get characters to fit a pre-defined space (such as is the case on my business card), I always calculate the point size, sometimes with x and y computed independently. The x size can be calculated by using stringwidth after setting the font at 1 point. The y size can be calculated by iterating over the string and reading the metric info for each character. If you need to set x and y scale independently, use makefont instead of scalefont and provide a scale matrix. This allows me to substitute fonts ad hoc without digging out my calculator to recalculate all of the sizes. Just let the PS interpreter do the grunt work. Ken (shiva@well.sf.ca.us)
marsh@linus.mitre.org (Ralph Marshall) (10/11/90)
In article <21131@well.sf.ca.us> shiva@well.sf.ca.us (Kenneth Porter) writes: > > >When I need to get characters to fit a pre-defined space (such >as is the case on my business card), I always calculate the >point size, sometimes with x and y computed independently. The >x size can be calculated by using stringwidth after setting the >font at 1 point. The y size can be calculated by iterating >over the string and reading the metric info for each character. Of course, you can also get the height of the string from stringwidth (despite the somewhat misleading name). It leaves both the width and height of the string on the stack, taking into account all the usual things such as scales and rotations, actual font, font size, etc., so it should be suitable for most situations such as picking a scale size that will allow the text to fit on a business card. Ralph Marshall marsh@linus.mitre.org
glenn@heaven.woodside.ca.us (Glenn Reid) (10/12/90)
In article <122961@linus.mitre.org> marsh@darwin.UUCP (Ralph Marshall 617 271-8784) writes: >Of course, you can also get the height of the string from stringwidth >(despite the somewhat misleading name). It leaves both the width and >height of the string on the stack, taking into account .... No. The "stringwidth" operator returns the amount by which the current point will be displaced. It has nothing to do with the toner marks made on the page and how big they might be. For essentially all Roman fonts, "stringwidth" returns 0 for the Y component unless your coordinate system is rotated or something. You need to use "false charpath pathbbox" to get the actual visual width and height of the characters. /Glenn -- Glenn Reid RightBrain Software glenn@heaven.woodside.ca.us PostScript/NeXT developers ..{adobe,next}!heaven!glenn 415-851-1785
jpensar@ra.abo.fi (Johan Pensar RT) (10/12/90)
In article <122961@linus.mitre.org> marsh@darwin.UUCP (Ralph Marshall 617 271-8784) writes: >Of course, you can also get the height of the string from stringwidth >(despite the somewhat misleading name). It leaves both the width and >height of the string on the stack, taking into account all the usual >things such as scales and rotations, actual font, font size, etc., so >it should be suitable for most situations such as picking a scale size >that will allow the text to fit on a business card. > >Ralph Marshall >marsh@linus.mitre.org Ooohhh??, I have allways belived that stringwidth leaves (in a simplified vocabular) the changes of current point in x and y directions that would occur if the string was printed :-) That is, for normal characters, the lowest parameter left on the stack is allways zero, would be something else if japanese was printed (i guess they writes downwards?). Correct me if wrong. -------------------------------------------------------------------------- Johan Pensar Email: jpensar@ra.abo.fi Process Control Laboratory Abo Akademi University FINLAND
marsh@linus.mitre.org (Ralph Marshall) (10/12/90)
In an earlier incarnation, I misspoke myself as follows: >>Of course, you can also get the height of the string from stringwidth >>(despite the somewhat misleading name). It leaves both the width and >>height of the string on the stack, taking into account .... > To which Glenn pointed out that PostScript should only be used by professionals who know what they are doing, and not by those of us watching out in net-land who were bound to burn, shock, or lacerate ourselves due to the lack of proper training: >No. The "stringwidth" operator returns the amount by which the current >point will be displaced. It has nothing to do with the toner marks >made on the page and how big they might be. For essentially all Roman >fonts, "stringwidth" returns 0 for the Y component unless your coordinate >system is rotated or something. > >/Glenn --------------------------------------------------------------------------- Ralph Marshall (marsh@linus.mitre.org) Disclaimer: Often wrong but never in doubt... --------------------------------------------------------------------------- -- --------------------------------------------------------------------------- Ralph Marshall (marsh@linus.mitre.org) Disclaimer: Often wrong but never in doubt...
aas@boeygen.nr.no (Gisle Aas) (10/15/90)
In article <293@heaven.woodside.ca.us> glenn@heaven.woodside.ca.us (Glenn Reid) writes: > For essentially all Roman > fonts, "stringwidth" returns 0 for the Y component unless your coordinate > system is rotated or something. Can anybody enlighten me on this subject. Why should stringwidth return something else if your coordinate system is rotated or something? -- Gisle Aas | snail: Boks 114 Blindern, N-0314 Oslo, Norway Norsk Regnesentral | X.400: G=Gisle;S=Aas;O=nr;P=uninett;C=no voice: +47-2-453561 | inet: Gisle.Aas@nr.no
glenn@heaven.woodside.ca.us (Glenn Reid) (10/16/90)
In article <AAS.90Oct15092820@boeygen.nr.no> aas@boeygen.nr.no (Gisle Aas) writes: >In article <293@heaven.woodside.ca.us> glenn@heaven.woodside.ca.us (Glenn Reid) writes: > >> For essentially all Roman >> fonts, "stringwidth" returns 0 for the Y component unless your coordinate >> system is rotated or something. > >Can anybody enlighten me on this subject. Why should stringwidth >return something else if your coordinate system is rotated or >something? Sure, I can enlighten you :-) I was being brain-dead when I said that, and I was wrong. It doesn't matter if the coordinate system is rotated. You get 0 unless the font itself has a Y component in the width of the character, which is extremely rare in Roman fonts. In a weak defense of my earlier posting, and to try to convince you that I actually do test things before I post them to the net, I had (approximately) the following dialog with my PostScript interpreter, but failed to notice the negative exponent on the Y component. It's effectively 0, but due to arithmetic error and roundoff, it's not exactly 0: heaven> PS PostScript(r) Version 1006.24 PS>60 rotate PS>/Helvetica-Bold 120 selectfont PS>0 0 moveto (TESTING) stringwidth PS>pstack 6.10352e-05 520.08 PS>quit heaven> Sorry about the misinformation. (Glenn) cvn -- Glenn Reid RightBrain Software glenn@heaven.woodside.ca.us PostScript/NeXT developers ..{adobe,next}!heaven!glenn 415-851-1785
rcd@ico.isc.com (Dick Dunn) (10/16/90)
aas@boeygen.nr.no (Gisle Aas) writes: > glenn@heaven.woodside.ca.us (Glenn Reid) writes: > > For essentially all Roman > > fonts, "stringwidth" returns 0 for the Y component unless your coordinate > > system is rotated or something. > Can anybody enlighten me on this subject. Why should stringwidth > return something else if your coordinate system is rotated or > something? Glenn didn't really mean the coordinate system (he knows better than that:-) but rather the font transformation matrix. Rotation the page coord- inates doesn't affect anything, because stringwidth gives its result in page coordinates. However, if you start with a typical Roman font and transform it with "makefont", using a font transformation matrix [a b c d e f] where b is nonzero, you'll get a nonzero y component from stringwidth. (Note also that altering f *doesn't* give a nonzero y--although it displaces the text in the y direction, it does so by a constant amount for the whole string, so that the y "escapement" is still zero.) -- Dick Dunn rcd@ico.isc.com -or- ico!rcd Boulder, CO (303)449-2870 ...Never offend with style when you can offend with substance.
toms@fcs260c2.ncifcrf.gov (Tom Schneider) (10/16/90)
Thanks to Kevin Andresen [kevina@apple.com] I now know that it is possible to adjust character sizes. Unfortunately every time I try to modify his program I get tangled into some problem with one or the other postscript device I use. Grrr #1. NeWS (the old 1.0 kind I think) refuses to create small characters, and forces them to be bigger. This is design error, in which someone thought that it would to 'help' the user. By rotating my characters, I can to avoid the problem some of the time. Anyone at Sun know why this was done? Does NeWS 2.0 still have this stupid 'feature'? Grrr #2. The other device I use is an Apple Laserwriter IIntx; which is in general a great machine --- except that there is no way to reset the darn thing, short of turning it off and on again. (The best contender, control-d didn't seem to help at all.) I asked about this here about a month ago and have still not gotten a satisfactory solution. Is there anyone at Apple who KNOWS the solution? A satisfactory solution is one that works under Unix, and is complete tested code. (Ie, exactly what do I send to the printer to clear its little brain?) So here's the problem: draw a character of a specified height in cm, with its bounding box just to prove you have it under control. Have it function on any device. When I run the following code on NeWS, it works fine. When I send it to the printer, it works fine the first time. On the second shot I get a blank page. What am I doing wrong? How do I tell the printer to forget anything I ever told it before????? Tom Schneider National Cancer Institute Laboratory of Mathematical Biology Frederick, Maryland 21702-1201 toms@ncifcrf.gov .......................................................................... (version = 2.00 of charbox.ps 1990 October 15 \n) print initgraphics /cmfactor { 72 2.54 div } def % defines points -> centimeters /cm { cmfactor mul} def % defines centimeters erasepage 12 cm 10 cm translate 90 rotate 4 4 scale /Helvetica-Bold findfont 30 scalefont setfont gsave newpath 0 0 moveto (G) true charpath flattenpath pathbbox % compute bounding box of 1 pt. char => lx ly ux uy % the path is here, but toss it away ... grestore pstack /uy exch def /ux exch def /ly exch def /lx exch def 1 setlinewidth gsave newpath 0 0 moveto ux 0 lineto ux uy lineto 0 uy lineto 0 0 lineto stroke grestore gsave 0 0 moveto (G) show grestore showpage
stanley@fozzie.phoenix.com (John Stanley) (10/17/90)
shiva@well.sf.ca.us (Kenneth Porter) writes: > This is not true. stringwidth returns the change in current > point after a show of the specified string. For Roman > typefaces, only the x component is non-zero. The y component Only too true. I once wrote some ps functions to center strings on specified points. Y was always 0. > > If metric info is not available in the font dictionary, you can > use "charpath flattenpath pathbbox", but I think the resulting The results are in drawing coordinates. I.e. moving 1/2 the x value to the left will center the string l/r. Unfortunately, either charpath or flattenpath has problems with certain fonts (Courier is on of them) which prohibits its use. I forget which command is the problem, but it kept me from using my nice routines in a production environment. This is my signature. It doesn't contain my name at all!
shiva@well.sf.ca.us (Kenneth Porter) (10/17/90)
marsh@linus.mitre.org (Ralph Marshall) writes: > Of course, you can also get the height of the string from > stringwidth... This is not true. stringwidth returns the change in current point after a show of the specified string. For Roman typefaces, only the x component is non-zero. The y component is zero because the baseline doesn't change (as it might in a Japanese font). Actually, the resulting width is NOT the bounding box; it must be adjusted by the side bearings of the first and last characters. This is only a problem, however, if you need a pretty close fit around the string. If metric info is not available in the font dictionary, you can use "charpath flattenpath pathbbox", but I think the resulting bounding box is relative to device coordinates, so you want to do the pathbbox in a coordinate system that is aligned to device space (ie. not rotated or skewed). Ken (shiva@well.sf.ca.us)
toms@fcs260c2.ncifcrf.gov (Tom Schneider) (11/07/90)
In article <21131@well.sf.ca.us> shiva@well.sf.ca.us (Kenneth Porter) writes: > >When I need to get characters to fit a pre-defined space (such >as is the case on my business card), I always calculate the >point size, sometimes with x and y computed independently. The >x size can be calculated by using stringwidth after setting the >font at 1 point. The y size can be calculated by iterating >over the string and reading the metric info for each character. >If you need to set x and y scale independently, use makefont >instead of scalefont and provide a scale matrix. > >This allows me to substitute fonts ad hoc without digging out >my calculator to recalculate all of the sizes. Just let the PS >interpreter do the grunt work. > >Ken (shiva@well.sf.ca.us) Without an exact program, it is next to impossible to replicate what you do. I have ALMOST solved my problem, but not quite! To prove that I am able to control the character sizes, I decided to make the characters appear inside boxes. Unfortunately, they don't match the boxes exactly, and I don't know why. Following is my latest attempt. Can you tell me why the characters STILL don't fit the boxes exactly? What is the problem with this code, and how do I fix it? (I print this on a LaserWriter ntxII. NeWS 1.0 fails utterly.) Tom Schneider National Cancer Institute Laboratory of Mathematical Biology Frederick, Maryland 21702-1201 toms@ncifcrf.gov - snip - snip - snip - snip - snip - snip - snip - snip - snip - snip (version = 2.31 of charbox.ps TDS 1990 November 6 \n) dup print % Show the 4 characters ACGT surrounded by boxes that exactly match % the characters. Unfortunately, this version of the program ALMOST % works. The C and G characters are displaced downward by about 1mm % relative to A and T. The reason for this is unknown, can you figure % it out? % Tom Schneider % National Cancer Institute % Laboratory of Mathematical Biology % Frederick, Maryland 21702-1201 % toms@ncifcrf.gov /cmfactor {72 2.54 div} def % defines points -> centimeters conversion /cm {cmfactor mul} def % defines centimeters % Show the version number on the page initgraphics erasepage gsave /Helvetica findfont 14 scalefont setfont 1 cm 25 cm moveto show grestore 1 setlinewidth % define the width of the dashed lines 1 setflat % define the accurcy with which curved path segments % are to be rendered on the raster output device. % Even setting this to 0.01 makes no difference! % Set up the font for the graphics /fontsize 30 def /Helvetica-Bold findfont fontsize scalefont setfont /charparams { % char charparams => uy ux ly lx % takes a single character and returns the coordinates that (supposedly) % defines the outer bounds of where the ink goes gsave newpath 0 0 moveto % take the character off the stack and use it here: true charpath flattenpath pathbbox % compute bounding box of 1 pt. char => lx ly ux uy % the path is here, but toss it away ... grestore /uy exch def /ux exch def /ly exch def /lx exch def % print the parameters to the user: (lx) lx (ly) ly (ux) ux (uy) uy pstack clear % clean up the stack, having printed all that } bind def /box { % xsize ysize box - % draw a dashed box of xsize by ysize /ysize exch def % the x size of the box /xsize exch def % the y size of the box gsave newpath 0 0 moveto xsize 0 lineto xsize ysize lineto 0 ysize lineto 0 0 lineto % [3] 0 setdash stroke grestore } bind def /boxshow { % xsize ysize char boxshow % show the character with a box around it gsave /tc exch def % define the character /ysize exch def % the x size of the character /xsize exch def % the y size of the character xsize ysize box tc charparams ysize % desired size of character in points uy ly sub % height of character in points div % factor by which to scale up the character /ymulfactor exch def xsize % desired size of character in points ux lx sub % height of character in points div % factor by which to scale up the character /xmulfactor exch def /xmove xmulfactor lx mul neg def /ymove ymulfactor ly mul neg def newpath xmove ymove moveto xmulfactor ymulfactor scale tc show grestore } def gsave 2 cm 2 cm translate /size 22 def 3 cm 0 translate 0 0 moveto 1 cm size cm (A) boxshow 3 cm 0 translate 0 0 moveto 1 cm size cm (C) boxshow 3 cm 0 translate 0 0 moveto 1 cm size cm (G) boxshow 3 cm 0 translate 0 0 moveto 1 cm size cm (T) boxshow grestore showpage
shiva@well.sf.ca.us (Kenneth Porter) (11/13/90)
toms@fcs260c2.ncifcrf.gov (Tom Schneider) provided some code
demonstrating that scaling up a font bbox doesn't work. After
some experimentation with Tom's sample code, I found that fonts
don't scale uniformly. It is necessary to calculate the bbox
at the desired size, which leads to a chicken-and-egg problem.
Try setting the fontsize parameter in his code to first, 1
point, then 825 points. In the first case, the characters
don't fit their expected bbox at all. In the second case, they
fit quite well. The number 825 is a compromise among the
ymulfactors of the final characters.
My error in assuming simple scaling would work partly stems
from my ignorance that Tom needed this much accuracy. In my
own applications I could tolerate a fair amount of slop and I
was using small point sizes.
Apparently, to get a good fit, it is necessary to iterate the
bbox-calculating procedure a couple of times, using the result
from each iteration to compute the font scale factor for
scalefont for the next iteration. A couple of iterations
should get you pretty close to a good fit.
In pseudo-code:
fontscale = 1
do {
calculate character bbox
fontscale = fontscale * desired_bbox / calculated_bbox
} while abs(desired_bbox-calculated_bbox) > acceptable_error
Ken (shiva@well.sf.ca.us)
jef@well.sf.ca.us (Jef Poskanzer) (11/13/90)
In the referenced message, shiva@well.sf.ca.us (Kenneth Porter) wrote: }fontscale = 1 }do { } calculate character bbox } fontscale = fontscale * desired_bbox / calculated_bbox }} while abs(desired_bbox-calculated_bbox) > acceptable_error That's an excellent idea, except for one thing: if you want precisely-sized characters that are BIG, you'll get a limitcheck. I think you have to add in some code to put a cap on the trial font scale, and then run some tests to find a good value for the cap. --- Jef Jef Poskanzer jef@well.sf.ca.us {ucbvax, apple, hplabs}!well!jef A professor is one who talks in someone else's sleep.