Annotation of pmsdk/samples/vectfont/vectfont.doc, revision 1.1

1.1     ! root        1: 
        !             2: 
        !             3: 
        !             4: 
        !             5: 
        !             6: 
        !             7:             The Presentation Manager Vector Fonts
        !             8:             by Charles Petzold
        !             9:             
        !            10:             
        !            11:             
        !            12:             Let's begin with a question: What graphics programming
        !            13:             language stores fonts as a lines and curves (rather than
        !            14:             bitmaps), and thus allows fonts to be arbitrarily stretched,
        !            15:             rotated, outlined, filled with different patterns, or even
        !            16:             used as clipping areas?
        !            17:             
        !            18:             One answer is obviously PostScript, Adobe Systems' page
        !            19:             composition language implemented on many high-end laser
        !            20:             printers (beginning with the Apple LaserWriter) and Allied
        !            21:             Corporation's Linotronic phototypesetters. Over the past few
        !            22:             years, PostScript has become the language of choice for
        !            23:             computer manipulation of fonts and text.
        !            24:             
        !            25:             But an equally valid answer is GPI -- the Graphics
        !            26:             Programming Interface component of the OS/2 Presentation
        !            27:             Manager. As we'll see, GPI has facilities to do virtually
        !            28:             everything with fonts that you can do with PostScript.
        !            29:             
        !            30:             
        !            31:             The Trouble With Text
        !            32:             
        !            33:             The display of text is always the most problematic part of a
        !            34:             graphics programming system. Unlike lines and polygons
        !            35:             (which are merely mathematical constructs), text is rooted
        !            36:             in a long tradition of aesthetic typography. In any computer
        !            37:             graphics system, the goal must always be to display text
        !            38:             that is as pleasing and as easy to read as a well-printed
        !            39:             book.
        !            40:             
        !            41:             Yet, most computer output devices (such as video displays
        !            42:             and printers) are digital media. The subtly shaped and
        !            43:             rounded characters that comprise traditional fonts must be
        !            44:             broken down into discrete pixels for storage and then
        !            45:             reassembled on the output device. This often causes
        !            46:             distortions in the appearance of the text.
        !            47:             
        !            48:             But one major advantage of using a computer for this job is
        !            49:             versatility:  We can use a wide variety of fonts in various
        !            50:             sizes and characteristics, and modify these fonts for
        !            51:             display.  The extent to which we can modify fonts is
        !            52:             dependent on the way in which the fonts are stored in
        !            53:             memory.
        !            54:             
        !            55:             
        !            56:             Images and Vectors
        !            57:             
        !            58:             A font is generally stored in computer (or printer) memory
        !            59:             in one of two very different ways:
        !            60:             
        !            61: 
        !            62: 
        !            63: 
        !            64: 
        !            65: 
        !            66: 
        !            67: 
        !            68: 
        !            69: 
        !            70: 
        !            71: 
        !            72: 
        !            73:             First, a font can be stored as an "image" or "bitmap." Each
        !            74:             character of the font is simply a rectanglar array of bits.
        !            75:             The 0 bits generally correspond to the background around the
        !            76:             character and the 1 bits correspond to the character itself.
        !            77:             
        !            78:             Secondly, a font can be stored in a "vector" or "outline"
        !            79:             format. Each character is defined as a series of lines and
        !            80:             curves that enclose areas. The character is displayed by
        !            81:             drawing the outline on the output device and filling the
        !            82:             enclosed areas.
        !            83:             
        !            84:             Image and vector fonts have distinct advantages and
        !            85:             disadvantages. Image font are always created for specific
        !            86:             font sizes and specific device resolutions. The size of a
        !            87:             particular image font cannot easily be changed. (For
        !            88:             example, enlarging an image font by doubling the rows and
        !            89:             columns of pixels often emphasizes the jaggedness of the
        !            90:             characters.) Also, image fonts cannot be rotated except
        !            91:             possibly by 90 degree increments.
        !            92:             
        !            93:             Vector fonts are much more malleable. Because they are
        !            94:             defined as a series of lines and curves, vector fonts can be
        !            95:             stretched or compressed to any size and can be rotated to
        !            96:             any angle. Vector fonts are not tied to a particular output
        !            97:             device resolution.
        !            98:             
        !            99:             In general, however, image fonts are more legible that
        !           100:             vector fonts. Various techniques are used to design image
        !           101:             fonts so they fool the eye into thinking the characters are
        !           102:             smoother than they actually are. Vector fonts --
        !           103:             particularly when displayed on low resolution devices and
        !           104:             scaled to small font sizes -- can be adjusted only by
        !           105:             mathematical algorithms, which currently are less capable
        !           106:             than human font designers. Another advantage of image fonts
        !           107:             is performance:  Vector fonts usually require much more
        !           108:             processing time to draw each character.
        !           109:             
        !           110:             Most conventional laser printers store fonts as images,
        !           111:             either within the printer or in font cartridges. The printer
        !           112:             is restricted to specific font sizes and the characters
        !           113:             cannot be arbitrarily rotated. Much more versatile are the
        !           114:             fonts stored in PostScript-based printers. These fonts are
        !           115:             stored as vectors. PostScript fonts can be stretched or
        !           116:             compressed to any size, they can be arbitrarily rotated,
        !           117:             filled with various patterns, and used for clipping.
        !           118:             
        !           119:             
        !           120:             The GPI Fonts
        !           121:             
        !           122:             The Graphics Programming Interface (GPI) of the OS/2
        !           123:             Presentation Manager can, of course, take advantage of fonts
        !           124:             that are stored in and supported by output devices such as
        !           125:             laser printers.
        !           126:             
        !           127: 
        !           128: 
        !           129: 
        !           130: 
        !           131: 
        !           132: 
        !           133: 
        !           134: 
        !           135: 
        !           136: 
        !           137: 
        !           138: 
        !           139:             But GPI also includes its own support of both image and
        !           140:             vector fonts. The image fonts are expected, of course,
        !           141:             because they are particularly suited for low resolution
        !           142:             video displays and dot matrix printers. Image fonts are an
        !           143:             important part of most graphics programming systems (such as
        !           144:             Microsoft Windows GDI).
        !           145:             
        !           146:             The addition of vector fonts in GPI is a real treat. GPI can
        !           147:             use these vector fonts with any output device. Thus, various
        !           148:             font techniques that previously have been restricted to
        !           149:             PostScript printers are now possible with other laser
        !           150:             printers and even the video display.
        !           151:             
        !           152:             This article shows you how to work with vector fonts in GPI
        !           153:             and demonstrates many PostScript-like techniques. Quite
        !           154:             simply, the font support in GPI is nearly as strong as that
        !           155:             in PostScript. However, GPI has a serious deficiency that
        !           156:             I'll discuss at the end of this article.
        !           157:             
        !           158:             OS/2 1.1 is shipped with three resource-only dyanamic link
        !           159:             libraries with a .FON extension. These are font files, and
        !           160:             the contents are shown in Figure 1.
        !           161:             
        !           162:             In addition, the video display device driver (DISPLAY.DLL)
        !           163:             and printer device drivers may also contain fonts designed
        !           164:             specifically for the device. For example, the default
        !           165:             "System Proportional" font is stored in DISPLAY.DLL.
        !           166:             
        !           167:             Important: If you want to use any of the fonts in the .FON
        !           168:             files, you must install the fonts from the Presentation
        !           169:             Manager Control Panel program. It is only necessary to
        !           170:             install one font from each of the three files, and you only
        !           171:             need do this once.
        !           172:             
        !           173:             Each font has a face name. This is shown in quotation marks
        !           174:             in Figure 1.  Each of the image fonts is available in
        !           175:             several point sizes and for several output devices: the CGA,
        !           176:             EGA, VGA (and 8514/A), and IBM Proprinter. GPI can syntesize
        !           177:             variations of these fonts, such as italic or boldfaced
        !           178:             versions.
        !           179:             
        !           180:             Vector fonts, however, need not be designed for a particular
        !           181:             output device and point size because they can be arbitrary
        !           182:             scaled. You'll note that italic and boldface versions of the
        !           183:             vector fonts are also included.
        !           184:             
        !           185:             The vector fonts in GPI are equivalent to the Courier,
        !           186:             Helvetica, and Times fonts included in most PostScript
        !           187:             printers. However, because Helvetica and Times are
        !           188:             registered trademarks, these names are not used to identify
        !           189:             the vector fonts in GPI.
        !           190:             
        !           191:             A little exploration of the font files will reveal that
        !           192:             vector fonts are encoded as a series of GPI drawing orders.
        !           193: 
        !           194: 
        !           195: 
        !           196: 
        !           197: 
        !           198: 
        !           199: 
        !           200: 
        !           201: 
        !           202: 
        !           203: 
        !           204: 
        !           205:             When drawing text with these fonts, GPI translates the
        !           206:             drawing orders into GPI functions, usually GpiPolyLine to
        !           207:             draw straight lines and GpiPolyFilletSharp to draw curves.
        !           208:             
        !           209:             
        !           210:             The VECTFONT Program
        !           211:             
        !           212:             The VECTFONT program demonstrates the use GPI vector fonts.
        !           213:             For purposes of clarity, I've divided the program into
        !           214:             several modules.
        !           215:             
        !           216:             The VECTFONT "Display" menu lists 16 options. The first
        !           217:             option (to display nothing) is the default. The other 15
        !           218:             options correspond to routines in the VF01.C through VF15.C
        !           219:             files (described below).  The VF00.C file contains some
        !           220:             "helper" functions used by the routines in VF01.C through
        !           221:             VF15.C.
        !           222:             
        !           223:             VECTFONT creates a micro presentation space during the
        !           224:             WM_CREATE message using page units of PU_TWIPS. ("Twips" is
        !           225:             fabricated word standing for "20th of a point." A printer's
        !           226:             point size is 1/72nd inch, so page units correspond to
        !           227:             1/1440 inch.) VECTFONT then modifies the page viewport
        !           228:             rectangle so that a page unit corresponds to 1 point, which
        !           229:             (as you may know) is the default coordinate system in
        !           230:             PostScript.
        !           231:             
        !           232:             Although VECTFONT displays output to the screen, vector
        !           233:             fonts are obviously more suited for laser printers. As you
        !           234:             will see, the appearance of the fonts -- even at 24 point
        !           235:             sizes -- is not nearly as good as the image fonts.
        !           236:             
        !           237:             You'll also notice that several of the demonstration
        !           238:             routines in VECTFONT requires a few seconds to run. For
        !           239:             anything other than a demonstration program, you'd probably
        !           240:             want to use a second thread of execution so as to not hold
        !           241:             up message processing.
        !           242:             
        !           243:             
        !           244:             Selecting an Outline Font
        !           245:             
        !           246:             To use an outline font in a Presentation Manager program,
        !           247:             you must first create a "logical font" and then select the
        !           248:             font into your presentation space.
        !           249:             
        !           250:             The GpiCreateLogFont function creates a logical font and
        !           251:             associates the font with a local ID (a number between 1L and
        !           252:             254L that you select). This function requires a pointer to a
        !           253:             structure of type FATTRS ("font attributes") that specifies
        !           254:             the attributes of the font you want.
        !           255:             
        !           256:             To create a vector font, most of the fields in this
        !           257:             structure can be set to zero. The most important fields are
        !           258:             szFacename (which is set to the face name of the font) and
        !           259: 
        !           260: 
        !           261: 
        !           262: 
        !           263: 
        !           264: 
        !           265: 
        !           266: 
        !           267: 
        !           268: 
        !           269: 
        !           270: 
        !           271:             fsFontUse, which is set to the constant identifiers
        !           272:             FATTR_FONTUSE_OUTLINE and FATTR_FONTUSE_TRANSFORMABLE,
        !           273:             combined with the C bitwise OR operator.
        !           274:             
        !           275:             You may prefer using the CreateVectorFont function in VF00.C
        !           276:             for creating a vector font. The VF00.C file contains several
        !           277:             other helpful functions that are used by the demonstration
        !           278:             routines in VF01.C through VF15.C.
        !           279:             
        !           280:             The CreateVectorFont function requires only the presentation
        !           281:             space handle, the local ID, and the face name:
        !           282:             
        !           283:             
        !           284:             CreateVectorFont(hps, lcid,
        !           285:                              szFacename);
        !           286:             
        !           287:             
        !           288:             After you create a logical font (using either
        !           289:             GpiCreateLogFont or CreateVectorFont), you can select the
        !           290:             font into the presentation space:
        !           291:             
        !           292:             
        !           293:             GpiSetCharSet(hps, lcid);
        !           294:             
        !           295:             
        !           296:             The lcid parameter is the local ID for the font. After the
        !           297:             font is selected in the presentation space, you can alter
        !           298:             the attributes of the font with various functions described
        !           299:             below, obtain information about the font by calling
        !           300:             GpiQueryFontMetrics, GpiQueryWidthTable, and
        !           301:             GpiQueryTextBox, and you can use the font for text output
        !           302:             with one of the text functions such as GpiCharStringAt.
        !           303:             
        !           304: 
        !           305: 
        !           306: 
        !           307: 
        !           308: 
        !           309: 
        !           310: 
        !           311: 
        !           312: 
        !           313: 
        !           314: 
        !           315: 
        !           316: 
        !           317: 
        !           318: 
        !           319: 
        !           320: 
        !           321: 
        !           322: 
        !           323: 
        !           324: 
        !           325: 
        !           326: 
        !           327: 
        !           328: 
        !           329: 
        !           330: 
        !           331: 
        !           332: 
        !           333: 
        !           334: 
        !           335: 
        !           336: 
        !           337:             When you no longer need the font, you select the default
        !           338:             font back into the presentation space:
        !           339:             
        !           340:             
        !           341:             GpiSetCharSet(
        !           342:                   hps,
        !           343:                   LCID_DEFAULT);
        !           344:             
        !           345:             
        !           346:             and then delete the local ID associated with the font:
        !           347:             
        !           348:             
        !           349:             GpiDeleteSetId(hps, lcid);
        !           350:             
        !           351:             
        !           352:             In VECTFONT, I always use the identifier LCID_MYFONT for the
        !           353:             local ID. This is defined in VECTFONT.H as 1L.
        !           354:             
        !           355:             
        !           356:             Scaling to a Point Size
        !           357:             
        !           358:             When you call GpiSetCharSet to select a vector font into the
        !           359:             prsentation space, the initial width and height of the font
        !           360:             are based on the GPI "character box," which defines a
        !           361:             character width and height in page units. The default
        !           362:             character box is based on the size of the default system
        !           363:             font. You can change the character box size by calling
        !           364:             GpiSetCharBox.
        !           365:             
        !           366:             Very important: To get a correctly proportioned vector font,
        !           367:             it is necessary to change the character box size. Do not use
        !           368:             the default Generally you set the height of the character
        !           369:             box to the desired height of the font. If you want the a
        !           370:             vector font to have a normal width, you set the width of the
        !           371:             character box equal to the height. For a skinnier font, set
        !           372:             the width of the character box less than the height; for a
        !           373:             fatter font, set the width greater than the height.
        !           374:             
        !           375:             If you're working in page units of PU_PELS, you must also
        !           376:             adjust the character box dimensions to account for
        !           377:             differences in horizontal and vertical resolution of the
        !           378:             output device. For this reason, it's much easier to work
        !           379:             with vector fonts if you use one of the metric page units
        !           380:             (PU_LOENGLISH, PU_HIENGLISH, PU_LOMETRIC, PU_HIMETRIC, or
        !           381:             PU_TWIPS). With these page units, horizontal and vertical
        !           382:             page units are the same.
        !           383:             
        !           384:             For example, suppose you're using page units of PU_TWIPS.
        !           385:             This means that one page unit is equal to 1/20 of a point or
        !           386:             1/1440 inch.  After selecting a vector font into the
        !           387:             presentation space, you want to scale the font to 24 points.
        !           388:             You first define a structure of type SIZEF:
        !           389:             
        !           390:             
        !           391: 
        !           392: 
        !           393: 
        !           394: 
        !           395: 
        !           396: 
        !           397: 
        !           398: 
        !           399: 
        !           400: 
        !           401: 
        !           402: 
        !           403:             SIZEF sizfx;
        !           404:             
        !           405:             
        !           406:             The two fields of this structure are named cx and cy and are
        !           407:             interpreted as 32-bit FIXED numbers, that is, the high 16-
        !           408:             bits are interpreted as an integer, and the low 16-bits are
        !           409:             interpreted as a fraction.
        !           410:             
        !           411:             If you want to scale the vector font to a 24 point height,
        !           412:             you can use the MAKEFIXED macro to set to the fields of the
        !           413:             structure like this:
        !           414:             
        !           415:             
        !           416:             sizfx.cx = MAKEFIXED(
        !           417:                          24 * 20, 0);
        !           418:             sizfx.cy = MAKEFIXED(
        !           419:                          24 * 20, 0);
        !           420:             
        !           421:             
        !           422:             Multiplying by 20 is necessary to convert the point size you
        !           423:             want to twips. Then call GpiSetCharBox:
        !           424:             
        !           425:             
        !           426:             GpiSetCharBox(hps, &sizfx);
        !           427:             
        !           428:             
        !           429:             After setting the character box, any character or text
        !           430:             dimensions you obtain from GpiQueryFontMetrics,
        !           431:             GpiQueryTextBox, and GpiQueryWidthTable will reflect the new
        !           432:             font size.
        !           433:             
        !           434:             The ScaleVectorFont routine in VF00.C can help in scaling a
        !           435:             vector font to a desired point size. The function will work
        !           436:             with any page units, even PU_PELS. The second and third
        !           437:             parameters to ScaleVectorFont specify a point size in units
        !           438:             of 0.1 points. (For example, use 240 for a 24-point size.)
        !           439:             If you want a normally proportioned vector font, set the
        !           440:             third parameter to ScaleVectorFont equal to the second
        !           441:             parameter.
        !           442:             
        !           443:             The VF01.C file shows how the functions discussed so far can
        !           444:             be used to display all the available vector fonts in 24
        !           445:             point sizes. You can run the function in VF01.C by selecting
        !           446:             the "24 Point Fonts" option from the VECTFONT "Display"
        !           447:             menu.
        !           448:             
        !           449:             
        !           450:             Arbitrary Stretching
        !           451:             
        !           452:             Besides scaling the vector font to a specific point size,
        !           453:             you can also scale vector fonts to fit within an arbitrary
        !           454:             rectangle. For example, you may want to scale a short text
        !           455:             string to fill the client window.
        !           456:             
        !           457: 
        !           458: 
        !           459: 
        !           460: 
        !           461: 
        !           462: 
        !           463: 
        !           464: 
        !           465: 
        !           466: 
        !           467: 
        !           468: 
        !           469:             The function shown in VF02.C shows how this is done. You can
        !           470:             run this function by selecting "Stretched Font" from
        !           471:             VECTFONT's menu. The function in VF02.C displays the word
        !           472:             "Hello!" in the "Tms Rmn Italic" font stretched to the size
        !           473:             of the client window.
        !           474:             
        !           475:             The ScaleFontToBox function in VF00.C helps out with this
        !           476:             job. This function first calls GpiQueryTextBox to obtain the
        !           477:             coordinates of a parallelogram that encompasses the text
        !           478:             string. The character box is then scaled based on the size
        !           479:             of this text box and the rectangle to which the font must be
        !           480:             stretched. The QueryStartPointInTextBox function in VF00.C
        !           481:             determines the starting point of the text string (that is,
        !           482:             the point at the baseline of the left side of the first
        !           483:             character) within this rectangle. This point is used in the
        !           484:             GpiCharStringAt function to display the text.
        !           485:             
        !           486:             
        !           487:             Mirror Images
        !           488:             
        !           489:             Besides scaling the font to a particular size, the character
        !           490:             box can also flip the characters around the horizontal or
        !           491:             vertical axis.
        !           492:             
        !           493:             If the character box height (the cy field of the SIZEF
        !           494:             structure) is negative, then the characters will be flipped
        !           495:             around the baseline and displayed upside down. If the
        !           496:             character box width (the cx field) is negative, the
        !           497:             individual characters are flipped around the vertical axis.
        !           498:             Moreover, GpiCharStringAt will draw a character string from
        !           499:             right to left. It's as if the whole character string is
        !           500:             flipped around the vertical line at the left side of the
        !           501:             first character.
        !           502:             
        !           503:             The function in VF03.C displays the same string four times,
        !           504:             using all possible combinations of negative and positive
        !           505:             character box dimensions. You can run this function by
        !           506:             selecting "Mirrored Font" from the VECTFONT menu.
        !           507:             
        !           508:             
        !           509:             Vector Fonts and Transformations
        !           510:             
        !           511:             Unlike image fonts, vector fonts can be scaled to any size
        !           512:             and sheared and rotated to any angle. The matrix transforms
        !           513:             described in my article "OS/2 Graphics Programming
        !           514:             Interface: An Introduction to Coordinate Spaces" (Microsoft
        !           515:             Systems Journal, Volume 3, Number 4) affect vector fonts in
        !           516:             the same way they affect the display of other graphics
        !           517:             primitives.
        !           518:             
        !           519:             In addition, GPI also supports several functions
        !           520:             specifically for performing transforms on vector fonts.
        !           521:             We've already seen how the GpiSetCharBox function allows
        !           522:             font characters to be scaled. The GpiSetCharAngle rotates
        !           523: 
        !           524: 
        !           525: 
        !           526: 
        !           527: 
        !           528: 
        !           529: 
        !           530: 
        !           531: 
        !           532: 
        !           533: 
        !           534: 
        !           535:             the font characters and the GpiSetCharShear performs x-
        !           536:             shear.
        !           537:             
        !           538:             
        !           539:             Character Angle and Rotation
        !           540:             
        !           541:             By default, the baseline of the vector font characters is
        !           542:             parallel to the x axis in world coordinates. You can change
        !           543:             this by calling GpiSetCharAngle. This rotates the vector
        !           544:             fonts characters.
        !           545:             
        !           546:             The character angle is specified using a GRADIENTL
        !           547:             structure, which has two fields named x and y of type LONG.
        !           548:             Imagine a line connecting the point (0,0) to the point (x,y)
        !           549:             in world coordinates. The baseline of each character is
        !           550:             parallel to this line. The direction of the text is the same
        !           551:             as the direction from (0,0) to (x,y).
        !           552:             
        !           553: 
        !           554: 
        !           555: 
        !           556: 
        !           557: 
        !           558: 
        !           559: 
        !           560: 
        !           561: 
        !           562: 
        !           563: 
        !           564: 
        !           565: 
        !           566: 
        !           567: 
        !           568: 
        !           569: 
        !           570: 
        !           571: 
        !           572: 
        !           573: 
        !           574: 
        !           575: 
        !           576: 
        !           577: 
        !           578: 
        !           579: 
        !           580: 
        !           581: 
        !           582: 
        !           583: 
        !           584: 
        !           585: 
        !           586: 
        !           587: 
        !           588: 
        !           589: 
        !           590: 
        !           591: 
        !           592: 
        !           593: 
        !           594: 
        !           595: 
        !           596: 
        !           597: 
        !           598: 
        !           599: 
        !           600: 
        !           601:             You can also think of this in trigonometric terms. The
        !           602:             baseline of the text is parallel to a line at angle a
        !           603:             measured counterclockwise from the x-axis, where:
        !           604:             
        !           605:             
        !           606:             a = arctan (y/x)
        !           607:             
        !           608:             
        !           609:             and y and x are the two fields of the GRADIENTL structure.
        !           610:             
        !           611:             
        !           612:             
        !           613:             The absolute magnitudes of y and x are not important. What's
        !           614:             important are the relative magnitudes and signs. The signs
        !           615:             of x and y determine the direction of the text string as
        !           616:             indicated in the following table:
        !           617:             
        !           618:             
        !           619:             x    y    Direction
        !           620:             -    -    ---------
        !           621:             
        !           622:             +    +    To upper right
        !           623:             -    +    To upper left
        !           624:             -    -    To lower left
        !           625:             +    -    To lower right
        !           626:             
        !           627:             
        !           628:             The function in VF04.C uses the GpiSetCharAngle function to
        !           629:             display eight text strings at 45 degree increments around
        !           630:             the center of the client window. Each string displays the
        !           631:             fields of the GRADIENTL structure that is used in the
        !           632:             GpiSetCharAngle call.
        !           633:             
        !           634:             In this example, the text strings begin with a blank
        !           635:             character so as not to make a mess of overlapping characters
        !           636:             in the center of the client window. The character angle does
        !           637:             not affect the interpretation of the starting position of
        !           638:             the string specified in the GpiCharStringAt function. If you
        !           639:             move your head so that a particular string is seen as
        !           640:             running left to right, the starting position still refers to
        !           641:             the point at the baseline of the left side of the first
        !           642:             character.
        !           643:             
        !           644:             You can make the characters in a text string follow a curved
        !           645:             path by individually calculating the starting position an
        !           646:             angle of each character and displaying the characters one at
        !           647:             a time. This is what is done in VF05.C to display "Hello,
        !           648:             world!" around the perimeter of a circle.
        !           649:             
        !           650:             The text string is scaled based on the circumference of a
        !           651:             circle that is positioned in the center of the window and
        !           652:             has a diameter half the width or height (whichever is less)
        !           653:             of the window. The GpiQueryWidthTable function is used to
        !           654: 
        !           655: 
        !           656: 
        !           657: 
        !           658: 
        !           659: 
        !           660: 
        !           661: 
        !           662: 
        !           663: 
        !           664: 
        !           665: 
        !           666: 
        !           667:             obtain the width of individual characters and then space
        !           668:             them around the circle.
        !           669:             
        !           670:             
        !           671:             Character Shear
        !           672:             
        !           673:             It is easy to confuse the character angle and character
        !           674:             shear. Lets look at the difference. The character angle
        !           675:             refers to the orientation of the baseline. Text displayed
        !           676:             with various character angles is rotated but otherwise not
        !           677:             distorted in any way.
        !           678:             
        !           679:             The character shear affects the appearance of the characters
        !           680:             themselves apart from any rotation. Character shear by
        !           681:             itself "bends" characters to the left or right, but the
        !           682:             bottom of each character remains parallel to the x-axis. You
        !           683:             can use character shear to create oblique (sometimes
        !           684:             mistakenly called italic) versions of a font.
        !           685:             
        !           686:             To set character shear you call the GpiSetCharShear
        !           687:             function. This function requires a pointer to a structure of
        !           688:             type POINTL, which has two fields named x and y. Imagine a
        !           689:             line drawn from (0,0) to the point (x,y) in world
        !           690:             coordinates. The left and right sides of each character are
        !           691:             parallel to this line.
        !           692:             
        !           693:             The function shown in in VF06.C displays seven text strings
        !           694:             using different character shears.
        !           695:             
        !           696:             You can run this function by selecting "Character Shear"
        !           697:             from the VECTFONT menu. Each string displays the x and y
        !           698:             values used in the POINTL structure to set the character
        !           699:             shear.
        !           700:             
        !           701:             The character shear is governed by the relative magnitudes
        !           702:             and signs of the x and y fields of the POINTL structure. If
        !           703:             the signs of both fields are the same, the characters tilt
        !           704:             to the right; if different, the characters tilt to the left.
        !           705:             The character shear does not cause characters to be flipped
        !           706:             upside down. For example, character shear using the point
        !           707:             (100,100) has the same effect as (-100,-100).
        !           708:             
        !           709:             The angle of the left and right sides of the characters from
        !           710:             the y axis is sometimes called the shear angle. In theory,
        !           711:             the shear angle can range to just above -180 degrees
        !           712:             (infinite left shear) to just under +180 degrees (infinite
        !           713:             right shear) and is equal to:
        !           714:             
        !           715:             
        !           716:             a = arctan (x/y)
        !           717:             
        !           718:             
        !           719:             where x and y are the two fields of the POINTL structure.
        !           720:             
        !           721: 
        !           722: 
        !           723: 
        !           724: 
        !           725: 
        !           726: 
        !           727: 
        !           728: 
        !           729: 
        !           730: 
        !           731: 
        !           732: 
        !           733:             When you set a non-default character shear, the
        !           734:             GpiQueryTextBox function returns an array of points that
        !           735:             define a parallelogram rather than a rectangle. However, the
        !           736:             top and bottom sides of this text box are the same width as
        !           737:             for a non-sheared text string, and the distance between the
        !           738:             top and bottom sides also remains the same.
        !           739:             
        !           740:             You can use character shear to draw an oblique shadow of a
        !           741:             text string. The function in VF07.C colors the background of
        !           742:             the client window blue, and displays the text string
        !           743:             "Shadow" twice.
        !           744:             
        !           745:             The first call to GpiCharStringAt displays the shadow. This
        !           746:             is drawn in dark blue using a positive character shear. The
        !           747:             second call to GpiCharStringAt draws the characters upright
        !           748:             in red with a slightly smaller character box height. You can
        !           749:             run this function by selecting "Font with Shadow" from the
        !           750:             VECTFONT menu.
        !           751:             
        !           752:             
        !           753:             A Primer on Paths
        !           754:             
        !           755:             To explore more capabilities of vector fonts, it's necessary
        !           756:             to become familiar with the GPI "path," which is similar to
        !           757:             a PostScript path. In GPI, you create a path by calling line
        !           758:             drawing functions between calls to the GpiBeginPath and
        !           759:             GpiEndPath functions:
        !           760:             
        !           761:             
        !           762:             GpiBeginPath(hps, idPath);
        !           763:                  <... call line
        !           764:                       drawing
        !           765:                       functions ... >
        !           766:             GpiEndPath (hps) ;
        !           767:             
        !           768:             
        !           769:             This is called a "path bracket." In OS/2 1.1, idPath must be
        !           770:             set equal to 1L. The functions that are valid within a path
        !           771:             bracket are listed in the documentation of the Presentation
        !           772:             Manager functions.
        !           773:             
        !           774:             The functions you call within the path bracket do not draw
        !           775:             anything. Instead, the lines that make up the path are
        !           776:             retained by the system. Often the lines you draw in a path
        !           777:             will enclose areas, but they don't have to.
        !           778:             
        !           779:             After the GpiEndPath call, you can do one of three things
        !           780:             with the path you've created:
        !           781:             
        !           782:                  *    Call GpiStrokePath to draw the lines that comprise
        !           783:                       the path. These lines are drawn using the
        !           784:                       geometric line width, joins, and ends (discussed
        !           785:                       shortly).
        !           786:             
        !           787: 
        !           788: 
        !           789: 
        !           790: 
        !           791: 
        !           792: 
        !           793: 
        !           794: 
        !           795: 
        !           796: 
        !           797: 
        !           798: 
        !           799:                  *    Call GpiFillPath to fill enclosed areas defined by
        !           800:                       the path. Any open areas are automatically
        !           801:                       closed. The area is filled with the current
        !           802:                       pattern.
        !           803:             
        !           804:                  *    Call GpiSetClipPath to make the enclosed areas of
        !           805:                       the path a clipping area. Any open areas are
        !           806:                       automatically closed. Subsequent GPI calls will
        !           807:                       only display output within the enclosed area
        !           808:                       defined by the path.
        !           809:             
        !           810:             Each of these three functions cause the path to be deleted.
        !           811:             Prior to calling any of these three functions you can call
        !           812:             GpiModifyPath, which I'll describe towards the end of this
        !           813:             article.
        !           814:             
        !           815:             Normally, GpiCharStringAt and the other text output
        !           816:             functions are not valid in a path bracket. The exception is
        !           817:             when a vector font is selected in the presentation space.
        !           818:             When called from within a path bracket, GpiCharStringAt does
        !           819:             not draw the text string. Instead, the outlines of the
        !           820:             characters become part of the path.
        !           821:             
        !           822:             This facility opens up a whole collection of PostScript-like
        !           823:             stylistic techniques that you can use with vector fonts.
        !           824:             
        !           825:             
        !           826:             Hollow Characters
        !           827:             
        !           828:             Let's begin by calling GpiCharStringAt in a path bracket and
        !           829:             then use GpiStrokePath to draw the lines of the path.
        !           830:             GpiStrokePath has the following syntax:
        !           831:             
        !           832:             
        !           833:             GpiStrokePath(
        !           834:                  hps, idPath, 0L);
        !           835:             
        !           836:             
        !           837:             In the initial version of the Presentation Manager, the last
        !           838:             parameter of the function must be set to 0L. When used to
        !           839:             stroke a path created by calling GpiCharStringAt, only the
        !           840:             outline is drawn and not the interiors. This creates hollow
        !           841:             characters.
        !           842:             
        !           843:             The function in VF08.C uses this technique to display the
        !           844:             outline of the characters in the text string "Hollow." You
        !           845:             can run this function by selecting "Hollow Font" from the
        !           846:             VECTFONT menu.
        !           847:             
        !           848:             You may want to display characters in one color with an
        !           849:             outline of another color. In this case, you must call
        !           850:             GpiCharStringAt twice, first to draw the interior in a
        !           851:             specific color, and secondly in a path bracket followed by a
        !           852:             GpiStrokeFont call to draw the outline.
        !           853: 
        !           854: 
        !           855: 
        !           856: 
        !           857: 
        !           858: 
        !           859: 
        !           860: 
        !           861: 
        !           862: 
        !           863: 
        !           864: 
        !           865:             
        !           866:             The function in VF09.C does something like this to draw text
        !           867:             with a drop shadow.
        !           868:             
        !           869:             The shadow is drawn first using a normal GpiCharStringAt
        !           870:             call. Another GpiCharStringAt functions draws the text again
        !           871:             in the current window background color at a 1/6 inch offset
        !           872:             to the first string. This is surrounded by an outline
        !           873:             created by a third GpiCharStringAt call in a path bracket
        !           874:             followed by GpiStrokeFont.
        !           875:             
        !           876:             Quite similar to this is the creation of characters that
        !           877:             look like solid blocks, as shown in the function in VF10.C.
        !           878:             Eighteen character strings are drawn at 1 point offsets
        !           879:             using CLR_DARKGREEN. This is capped by the character string
        !           880:             drawn again in CLR_GREEN and the border in CLR_DARKGREEN.
        !           881:             
        !           882:             
        !           883: 
        !           884: 
        !           885: 
        !           886: 
        !           887: 
        !           888: 
        !           889: 
        !           890: 
        !           891: 
        !           892: 
        !           893: 
        !           894: 
        !           895: 
        !           896: 
        !           897: 
        !           898: 
        !           899: 
        !           900: 
        !           901: 
        !           902: 
        !           903: 
        !           904: 
        !           905: 
        !           906: 
        !           907: 
        !           908: 
        !           909: 
        !           910: 
        !           911: 
        !           912: 
        !           913: 
        !           914: 
        !           915: 
        !           916: 
        !           917: 
        !           918: 
        !           919: 
        !           920: 
        !           921: 
        !           922: 
        !           923: 
        !           924: 
        !           925: 
        !           926: 
        !           927: 
        !           928: 
        !           929: 
        !           930: 
        !           931:             Geometrically Thick Lines
        !           932:             
        !           933:             At first, it may seem as if there is no difference between
        !           934:             drawing a line normally, like this:
        !           935:             
        !           936:             
        !           937:             GpiMove(hps, &ptlBeg);
        !           938:             GpiLine(hps, &ptlEnd);
        !           939:             
        !           940:             
        !           941:             and calling these same two functions within a path bracket
        !           942:             and then stroking the path, like this:
        !           943:             
        !           944:             
        !           945:             GpiBeginPath(hps, idPath);
        !           946:             GpiMove(hps, &ptlBeg);
        !           947:             GpiLine(hps, &ptlEnd);
        !           948:             GpiEndPath(hps)
        !           949:             GpiStrokePath(hps, idPath, 0);
        !           950:             
        !           951:             
        !           952:             There are, in fact, some very significant differences.
        !           953:             
        !           954:             First, the line drawn with the normal GpiLine function has
        !           955:             what is called a "cosmetic" line width. The default width of
        !           956:             the line is based on the resolution of the output device. It
        !           957:             is a device dependent width for a "normal" line. The width
        !           958:             of the line does not change when you use matrix transforms
        !           959:             to set different scaling factors in the coordinate space.
        !           960:             Although GPI provides a function called GpiSetLineWidth to
        !           961:             change the cosmetic line width, this function is not
        !           962:             implemented in OS/2 1.1.
        !           963:             
        !           964:             But a line drawn by stroking a path has a "geometric" line
        !           965:             width. This is a line width (in world coordinates) that you
        !           966:             set with the GpiSetLineWidthGeom function. Because this line
        !           967:             width is specified in world coordinates, it is affected by
        !           968:             any scaling that you set using matrix transforms.
        !           969:             
        !           970:             Secondly, a line draw with GpiLine can have different line
        !           971:             types that you set with the GpiSetLineType function. These
        !           972:             line types are various combinations of dots and dashes. The
        !           973:             line is drawn with the current line color and the current
        !           974:             line mix.
        !           975:             
        !           976:             But a line drawn by stroking a path does not use the line
        !           977:             type. The line is instead treated as an area that follows
        !           978:             the path of the line but which has a geometric width. This
        !           979:             area is filled with the pattern that you set with
        !           980:             GpiSetPattern, colored with the current pattern foreground
        !           981:             and background color, and the current pattern foreground and
        !           982:             background mix.
        !           983:             
        !           984: 
        !           985: 
        !           986: 
        !           987: 
        !           988: 
        !           989: 
        !           990: 
        !           991: 
        !           992: 
        !           993: 
        !           994: 
        !           995: 
        !           996: 
        !           997:             Third, a line drawn by stroking the path can have various
        !           998:             types of line "joins" and "ends." By calling GpiSetLineJoin
        !           999:             you can specify that lines meet with a rounded, square, or
        !          1000:             miter join. GpiSetLineEnd lets you specify rounded, square,
        !          1001:             or flat ends to the lines.
        !          1002:             
        !          1003:             The function in the VF11.C file demonstrates the use of
        !          1004:             geometrically thick lines filled with patterns to give the
        !          1005:             letters a kind of "neon" look.
        !          1006:             
        !          1007:             You can run this function by selecting "Neon Effect" from
        !          1008:             the VECTFONT menu. The function strokes the path using
        !          1009:             various geometric line widths filled with a PATSYM_HALFTONE
        !          1010:             pattern and several colors. The outline of the font is
        !          1011:             white, but surrounded with a halo of red.
        !          1012:             
        !          1013:             A better effect could be achieved on devices capable of more
        !          1014:             than 16 colors. In this case, you can use a solid pattern
        !          1015:             but color each stroke with a different shade of red.
        !          1016:             
        !          1017:             
        !          1018:             Filling the Path
        !          1019:             
        !          1020:             When introducing paths earlier in this article, I mentioned
        !          1021:             that you can do one of three things with a path: stroke it,
        !          1022:             fill it, or use it for clipping. Let's move on to the
        !          1023:             second: filling the path.
        !          1024:             
        !          1025:             To fill a path, you call:
        !          1026:             
        !          1027:             
        !          1028:             GpiFillPath(hps,
        !          1029:                  idPath, lOption);
        !          1030:             
        !          1031:             
        !          1032:             This fills the path with the current pattern. Any open areas
        !          1033:             of the path are automatically closed before being filled.
        !          1034:             The lOption parameter can be either FPATH_ALTERNATE or
        !          1035:             FPATH_WINDING to fill the path using alternate or winding
        !          1036:             modes. For vector fonts, FPATH_WINDING causes the interiors
        !          1037:             of some letters (such as "O") to be filled. You'll probably
        !          1038:             want to use FPATH_ALTERNATE instead.
        !          1039:             
        !          1040:             If the current area filling pattern is PATSYM_SOLID, then
        !          1041:             the code:
        !          1042:             
        !          1043:             
        !          1044:             GpiBeginPath(hps, idPath);
        !          1045:             GpiCharStringAt(hps, &ptl,
        !          1046:                             cch, szText);
        !          1047:             GpiEndPath(hps);
        !          1048:             GpiFillPath(hps,
        !          1049:                         idPath,
        !          1050:                         FPATH_ALTERNATE);
        !          1051: 
        !          1052: 
        !          1053: 
        !          1054: 
        !          1055: 
        !          1056: 
        !          1057: 
        !          1058: 
        !          1059: 
        !          1060: 
        !          1061: 
        !          1062: 
        !          1063:             
        !          1064:             
        !          1065:             does roughly the same thing with a vector font as a
        !          1066:             GpiCharStringAt by itself. When using GpiFillPath you'll
        !          1067:             want to set a pattern other than PATSYM_SOLID. (A bug in
        !          1068:             OS/2 1.1 causes the current pattern to be reset to
        !          1069:             PATSYM_SOLID during a path bracket in which GpiCharStringAt
        !          1070:             is called. You can get around this bug by calling
        !          1071:             GpiSetPattern after you end the path.)
        !          1072:             
        !          1073:             The function in VF12.C uses GpiFillPath to display the text
        !          1074:             string "Fade" eight times filled with the eight GPI shading
        !          1075:             patterns (PATSYM_DENSE1 through PATSYM_DENSE8) and then
        !          1076:             finishes by calling GpiCharStringAt outside of a path
        !          1077:             bracket. You can run this function by selecting "Fading
        !          1078:             Font" from the VECTFONT menu.
        !          1079:             
        !          1080:             
        !          1081:             Clipping to the Text Characters
        !          1082:             
        !          1083:             The third option after creating a path is to call
        !          1084:             GpiSetClipPath:
        !          1085:             
        !          1086:             
        !          1087:             GpiSetClipPath(hps, idPath,
        !          1088:                            lOption);
        !          1089:             
        !          1090:             The lOption parameter can be either SCP_RESET (which equals
        !          1091:             0L, so it's the default) or SCP_AND. The SCP_RESET option
        !          1092:             causes the clipping path to be reset so that no clipping
        !          1093:             occurs. The SCP_AND option sets the new clipping path to the
        !          1094:             intersection of the old clipping path and the path you've
        !          1095:             just defined in a path bracket. Any open areas in the path
        !          1096:             are automatically closed.
        !          1097:             
        !          1098:             You can combine the SCP_AND option with either SCP_ALTERNATE
        !          1099:             (the default) or SCP_WINDING. As with GpiFillPath, you'll
        !          1100:             probably want to use alternate mode when working with paths
        !          1101:             created from vector fonts
        !          1102:             
        !          1103:             The function in VF13.C calls GpiCharStringAt with the text
        !          1104:             string "WOW" within a path bracket. This is followed by a
        !          1105:             call to GpiSetClipPath. The clipping path is now the
        !          1106:             interior of the letters. The function draws a series of
        !          1107:             colored lines emanating from the center of the client
        !          1108:             window.
        !          1109:             
        !          1110:             The function in VF14.C uses a similar technique but draws a
        !          1111:             series of areas defined by splines.
        !          1112:             
        !          1113:             
        !          1114:             Modifying the Path
        !          1115:             
        !          1116: 
        !          1117: 
        !          1118: 
        !          1119: 
        !          1120: 
        !          1121: 
        !          1122: 
        !          1123: 
        !          1124: 
        !          1125: 
        !          1126: 
        !          1127: 
        !          1128: 
        !          1129:             Between the call to GpiEndPath to end the path and the call
        !          1130:             to GpiStrokePath, GpiFillPath, or GpiSetClipPath, you can
        !          1131:             call GpiModifyPath. This function uses the current geometric
        !          1132:             line width, line join, and line end to convert every line in
        !          1133:             the path to a new line that encloses an area around the old
        !          1134:             line.
        !          1135:             
        !          1136:             For example, suppose that the path contained a single
        !          1137:             straight line. After GpiModifyPath the path would contain a
        !          1138:             closed line in the shape of a hotdog. The width of this
        !          1139:             hotdog is the geometric line width. The ends of the hotdog
        !          1140:             could be round, square, or flat, depending on the current
        !          1141:             line end attribute.
        !          1142:             
        !          1143: 
        !          1144: 
        !          1145: 
        !          1146: 
        !          1147: 
        !          1148: 
        !          1149: 
        !          1150: 
        !          1151: 
        !          1152: 
        !          1153: 
        !          1154: 
        !          1155: 
        !          1156: 
        !          1157: 
        !          1158: 
        !          1159: 
        !          1160: 
        !          1161: 
        !          1162: 
        !          1163: 
        !          1164: 
        !          1165: 
        !          1166: 
        !          1167: 
        !          1168: 
        !          1169: 
        !          1170: 
        !          1171: 
        !          1172: 
        !          1173: 
        !          1174: 
        !          1175: 
        !          1176: 
        !          1177: 
        !          1178: 
        !          1179: 
        !          1180: 
        !          1181: 
        !          1182: 
        !          1183: 
        !          1184: 
        !          1185: 
        !          1186: 
        !          1187: 
        !          1188: 
        !          1189: 
        !          1190: 
        !          1191: 
        !          1192: 
        !          1193: 
        !          1194: 
        !          1195:             Following the creation of a path, these two functions in
        !          1196:             succession:
        !          1197:             
        !          1198:             
        !          1199:             GpiModifyPath(hps, ID_PATH,
        !          1200:                           MPATH_STROKE);
        !          1201:             GpiFillPath(hps, ID_PATH,
        !          1202:                         FPATH_WINDING) ;
        !          1203:             
        !          1204:             
        !          1205:             is usually equivalent to:
        !          1206:             
        !          1207:             
        !          1208:             GpiStrokePath(hps, ID_PATH,
        !          1209:                           0L);
        !          1210:             
        !          1211:             
        !          1212:             GpiModifyPath and GpiStrokePath are the only two functions
        !          1213:             that use the geometric line width, joins, and ends.
        !          1214:             
        !          1215:             In theory, you can call GpiStrokePath after GpiModifyPath,
        !          1216:             like this:
        !          1217:             
        !          1218:             
        !          1219:             GpiModifyPath(hps, ID_PATH,
        !          1220:                           MPATH_STROKE);
        !          1221:             GpiStrokePath(hps, ID_PATH,
        !          1222:                           0L);
        !          1223:             
        !          1224:             
        !          1225:             This should do something, and it should be rather
        !          1226:             interesting, but GPI usually reports that it can't create
        !          1227:             the path because it's too complex.
        !          1228:             
        !          1229:             Instead, let's look at GpiModifyPath followed by
        !          1230:             GpiSetClipPath. The function in VF15.C is almost the same as
        !          1231:             the one in VF13.C except that it sets the geometric line
        !          1232:             width to 6 (1/12 inch) and calls GpiModifyPath before
        !          1233:             calling GpiSetClipPath.
        !          1234:             
        !          1235:             Note that the colored lines are clipped not to the interior
        !          1236:             of the characters, but to their original outlines. By the
        !          1237:             use of GpiModifyPath, the outlines of the characters have
        !          1238:             themselves been made into a path that is 1/12 inch wide.
        !          1239:             This is the path that is used for clipping.
        !          1240:             
        !          1241:             
        !          1242:             Is It Enough?
        !          1243:             
        !          1244:             I think it's clear that the facilities provided by GPI for
        !          1245:             working with vector fonts equal -- and sometimes exceed --
        !          1246:             those in PostScript. The GPI interface is very powerful and
        !          1247:             very versatile.
        !          1248:             
        !          1249: 
        !          1250: 
        !          1251: 
        !          1252: 
        !          1253: 
        !          1254: 
        !          1255: 
        !          1256: 
        !          1257: 
        !          1258: 
        !          1259: 
        !          1260: 
        !          1261:             Is that enough?
        !          1262:             
        !          1263:             No, it's not. The implementation of vector fonts in GPI has
        !          1264:             a structural flaw that still leaves PostScript the king.
        !          1265:             
        !          1266:             Take a close look at the display of the "Helv" font. You'll
        !          1267:             notice that the two legs of the "H" are different in width
        !          1268:             by one pixel when they should be the same width. This is
        !          1269:             undoubtedly due to a rounding error. It's obviously more
        !          1270:             noticeable on a low-resolution video display than it would
        !          1271:             be on a 300 dpi laser printer, but even on a laser printer
        !          1272:             such errors will affect the legibility of the text.
        !          1273:             
        !          1274:             Errors such as this do not occur with PostScript fonts.
        !          1275:             PostScript fonts are true algorithms that are able to
        !          1276:             recognize and correct any anomalies in the rendition of the
        !          1277:             characters. In contrast, GPI fonts (which are encoded as a
        !          1278:             simple series of polylines and polyfillets) are drawn
        !          1279:             blindly without any feedback or correction.
        !          1280:             
        !          1281:             So, while we can rejoice in what we have in GPI, there is
        !          1282:             still the need to hope for improvement.
        !          1283:             
        !          1284:             
        !          1285: 
        !          1286: 
        !          1287: 
        !          1288: 
        !          1289: 
        !          1290: 
        !          1291: 
        !          1292: 
        !          1293: 
        !          1294: 
        !          1295: 
        !          1296: 
        !          1297: 
        !          1298: 
        !          1299: 
        !          1300: 
        !          1301: 
        !          1302: 
        !          1303: 
        !          1304: 
        !          1305: 
        !          1306: 
        !          1307: 
        !          1308: 
        !          1309: 
        !          1310: 
        !          1311: 
        !          1312: 
        !          1313: 
        !          1314: 
        !          1315: 
        !          1316: 
        !          1317: 
        !          1318: 
        !          1319: 
        !          1320: 
        !          1321: 
        !          1322: 
        !          1323: 
        !          1324: 
        !          1325: 
        !          1326: 
        !          1327:             Figure 1
        !          1328:             
        !          1329:             
        !          1330:             Dynamic Link
        !          1331:             Library File   Image Fonts             Vector Fonts
        !          1332:             ------------   -----------             ------------
        !          1333:             
        !          1334:             COURIER.FON    "Courier" (8, 10, and   "Courier"
        !          1335:                             12 points for CGA,     "Courier Bold"
        !          1336:                             EGA, VGA, and          "Courier Italic"
        !          1337:                             IBM Proprinter)        "Courier Bold Italic"
        !          1338:             
        !          1339:             HELV.FON       "Helv" (8, 10, 12, 14,  "Helv"
        !          1340:                             18, and 24 points      "Helv Bold"
        !          1341:                             for CGA, EGA, VGA,     "Helv Italic"
        !          1342:                             and IBM Proprinter)    "Helv Bold Italic"
        !          1343:             
        !          1344:             TIMES.FON      "Tms Rmn" (8, 10, 12,   "Tms Rmn"
        !          1345:                             14, 18, and 24 points  "Tms Rmn Bold"
        !          1346:                             for CGA, EGA, VGA,     "Tms Rmn Italic"
        !          1347:                             and IBM Proprinter)    "Tms Rmn Bold Italic"
        !          1348:             
        !          1349:             
        !          1350:             Caption:  The OS/2 1.1 dynamic link library files that
        !          1351:             Caption:                                              
        !          1352:             contain fonts. The font face names are shown in quotation
        !          1353:             marks.
        !          1354:             
        !          1355:             
        !          1356: 
        !          1357: 
        !          1358: 
        !          1359: 
        !          1360: 
        !          1361: 
        !          1362: 
        !          1363: 
        !          1364: 
        !          1365: 
        !          1366: 
        !          1367: 
        !          1368: 
        !          1369: 
        !          1370: 
        !          1371: 
        !          1372: 
        !          1373: 
        !          1374: 
        !          1375: 
        !          1376: 
        !          1377: 
        !          1378: 
        !          1379: 
        !          1380: 
        !          1381: 
        !          1382: 
        !          1383: 
        !          1384: 
        !          1385: 
        !          1386: 
        !          1387: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.