home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / vos2-121.zip / v / srcos2 / vfont.cpp < prev    next >
C/C++ Source or Header  |  1999-02-19  |  20KB  |  592 lines

  1. //===============================================================
  2. // vfont.cxx - The font class - Windows
  3. //
  4. // Copyright (C) 1995,1996,1997,1998  Bruce E. Wampler
  5. //
  6. // This file is part of the V C++ GUI Framework, and is covered
  7. // under the terms of the GNU Library General Public License,
  8. // Version 2. This library has NO WARRANTY. See the source file
  9. // vapp.cxx for more complete information about license terms.
  10. //===============================================================
  11.  
  12. #include <v/vos2.h>        // for OS/2 stuff
  13. #include <v/vapp.h>
  14. #include <v/vfont.h>
  15. #include <math.h>
  16.  
  17. //=======================>>> vFont::vFont <<<=============================
  18.   vFont::vFont(vFontID fam, int size, vFontID sty, vFontID wt, int und, int ang)
  19.   {
  20.     SysDebug(Constructor,"vFont::vFont() constructor\n")
  21.  
  22.     _family = fam;
  23.     _pointSize = size;
  24.     _style = sty;
  25.     _weight = wt;
  26.     _underlined = und;
  27.     _angle = ang;
  28.     _isFromFntDlg = 0;
  29.     memset(&_fat, 0, sizeof(FATTRS));             // clear structure
  30.     _fat.usRecordLength = sizeof(FATTRS);
  31.     memset(&_status, 0, sizeof(_status));   // clear structure
  32.  
  33.   }
  34.  
  35. //=====================>>> vFont::vFont <<<===========================
  36.   vFont::vFont(const vFont& ft)
  37.   {
  38.     // Copy constructor - needs to delete object if already
  39.     // created, and copy the values as needed
  40.  
  41.     _family = ft._family;
  42.     _pointSize = ft._pointSize;
  43.     _style = ft._style;
  44.     _weight = ft._weight;
  45.     _underlined = ft._underlined;
  46.     _angle = ft._angle;
  47.     _isFromFntDlg = ft._isFromFntDlg;
  48.     // copy over the selected file attribute and status structures
  49.     memcpy(&_fat, &ft._fat, sizeof(FATTRS));
  50.     memcpy(&_status, &ft._status, sizeof(_status));
  51.   }
  52.  
  53. //=====================>>> vFont::= <<<===========================
  54.   vFont& vFont::operator =(const vFont& ft)
  55.   {
  56.     if (this == &ft)     // assigning to self
  57.     {
  58.       return *this;
  59.     }
  60.     // just like the copy constructor
  61.     _family = ft._family;
  62.     _pointSize = ft._pointSize;
  63.     _style = ft._style;
  64.     _weight = ft._weight;
  65.     _underlined = ft._underlined;
  66.     _angle = ft._angle;
  67.     _isFromFntDlg = ft._isFromFntDlg;
  68.  
  69.     // copy over the selected file attribute structure
  70.     memcpy(&_fat, &ft._fat, sizeof(FATTRS));
  71.     memcpy(&_status, &ft._status, sizeof(_status));
  72.  
  73.     return *this;
  74.   }
  75.  
  76. //=====================>>> vFont::SetFontValues <<<===========================
  77.   void vFont::SetFontValues(vFontID fam, int size, vFontID sty, vFontID wt,
  78.     int und)
  79.   {
  80.     // delete the old font from all assigned dc's
  81.     for (int i=0; i<MAXPS; i++)
  82.     {
  83.       if (_status[i].dc != 0)
  84.       {
  85.     GpiSetCharSet(_status[i].dc, LCID_DEFAULT);     // restore default font
  86.     GpiDeleteSetId(_status[i].dc, _status[i].fid);  // destroy logical font
  87.       }
  88.     }
  89.     _family = fam;
  90.     _pointSize = size;
  91.     _style = sty;
  92.     _weight = wt;
  93.     _underlined = und;
  94.     _isFromFntDlg = 0;
  95.     memset(&_fat, 0, sizeof(FATTRS));             // clear structure
  96.     _fat.usRecordLength = sizeof(FATTRS);
  97.     memset(&_status, 0, sizeof(_status));         // clear structure
  98.   }
  99.  
  100.  
  101. //=====================>>> vFont::SetWinFontValues <<<========================
  102. // This is the entry point from the font dialog box and is the typical
  103. // way an app will set the desired font
  104. void vFont::SetWinFontValues(VCONST FONTDLG& fdlg)
  105. {
  106.   // delete the old font from all assigned dc's
  107.   for (int i=0; i<MAXPS; i++)
  108.   {
  109.     if (_status[i].dc != 0)
  110.     {
  111.       GpiSetCharSet(_status[i].dc, LCID_DEFAULT);     // restore default font
  112.       GpiDeleteSetId(_status[i].dc, _status[i].fid);  // destroy logical font
  113.     }
  114.   }
  115.   memset(&_status, 0, sizeof(_status));           // clear structure
  116.  
  117.   _isFromFntDlg = 1;        // font selection is from dialog box
  118.  
  119.   // copy over the selected file attribute structure
  120.   memcpy(&_fat, &fdlg.fAttrs, sizeof(FATTRS));
  121. /*
  122.   _fat.usRecordLength = sizeof(FATTRS);
  123.   _fat.fsSelection = fdlg.fAttrs.fsSelection;
  124.   _fat.lMatch = fdlg.fAttrs.lMatch;
  125.   strcpy(_fat.szFacename, fdlg.fAttrs.szFacename);
  126.   _fat.idRegistry = fdlg.fAttrs.idRegistry;
  127.   _fat.usCodePage = fdlg.fAttrs.usCodePage;
  128.   _fat.lMaxBaselineExt = fdlg.fAttrs.lMaxBaselineExt;
  129.   _fat.lAveCharWidth = fdlg.fAttrs.lAveCharWidth;
  130.   _fat.fsType = fdlg.fAttrs.fsType;
  131.   _fat.fsFontUse = fdlg.fAttrs.fsFontUse;
  132. */
  133.  
  134.   // now fill in the V font variables
  135.   _pointSize = FIXEDINT(fdlg.fxPointSize);
  136.  
  137.   if (_fat.fsSelection & FATTR_SEL_UNDERSCORE)
  138.     _underlined = 1;
  139.   else
  140.     _underlined = 0;
  141.  
  142.   // fsSelection will indicate Bold and Italic only for synthesized
  143.   // (ie. bitmap) fonts and will not be set for regular Adobe outline fonts
  144.   // For outline fonts must use FONTMETRICS to determine these properties
  145.   // in vfont::loadfont
  146.   if (_fat.fsFontUse & FATTR_FONTUSE_OUTLINE)  // its an outline font
  147.   {
  148.     if (fdlg.usWeight >= FWEIGHT_BOLD)
  149.       _weight = vfBold;
  150.     else
  151.       _weight = vfNormal;
  152.  
  153.     if (_fat.fsSelection & FATTR_SEL_ITALIC)
  154.       _style = vfItalic;
  155.     else
  156.       _style = vfNormal;
  157.   }
  158.   else  // an image font
  159.   {
  160.     if (_fat.fsSelection & FATTR_SEL_ITALIC)
  161.       _style = vfItalic;
  162.     else
  163.       _style = vfNormal;
  164.  
  165.     if (_fat.fsSelection & FATTR_SEL_BOLD)
  166.       _weight = vfBold;
  167.     else
  168.       _weight = vfNormal;
  169.   }
  170.  
  171.   // Now, determine if it is a V family
  172.   // Serif fonts
  173.   if (strcmp(_fat.szFacename, "Times New Roman") == 0 ||
  174.       strcmp(_fat.szFacename, "Tms Rmn") == 0)
  175.   {
  176.     _family = vfSerif;
  177.     _weight = vfNormal;
  178.     _style = vfNormal;
  179.   }
  180.   else if (strcmp(_fat.szFacename, "Times New Roman Italic") == 0 ||
  181.        strcmp(_fat.szFacename, "Tms Rmn Italic") == 0)
  182.   {
  183.     _family = vfSerif;
  184.     _weight = vfNormal;
  185.     _style = vfItalic;
  186.   }
  187.   else if (strcmp(_fat.szFacename, "Times New Roman Bold") == 0 ||
  188.        strcmp(_fat.szFacename, "Tms Rmn Bold") == 0)
  189.   {
  190.     _family = vfSerif;
  191.     _weight = vfBold;
  192.     _style = vfNormal;
  193.   }
  194.   else if (strcmp(_fat.szFacename, "Times New Roman Bold Italic") == 0 ||
  195.        strcmp(_fat.szFacename, "Tms Rmn Bold Italic") == 0)
  196.   {
  197.     _family = vfSerif;
  198.     _weight = vfBold;
  199.     _style = vfItalic;
  200.   }
  201.   //  Sans Serif fonts
  202.   else if (strcmp(_fat.szFacename, "Helvetica") == 0 ||
  203.        strcmp(_fat.szFacename, "Helv") == 0)
  204.   {
  205.     _family = vfSansSerif;
  206.     _weight = vfNormal;
  207.     _style = vfNormal;
  208.   }
  209.   else if (strcmp(_fat.szFacename, "Helvetica Bold") == 0 ||
  210.        strcmp(_fat.szFacename, "Helv Bold") == 0)
  211.   {
  212.     _family = vfSansSerif;
  213.     _weight = vfBold;
  214.     _style = vfNormal;
  215.   }
  216.   else if (strcmp(_fat.szFacename, "Helvetica Italic") == 0 ||
  217.        strcmp(_fat.szFacename, "Helv Italic") == 0)
  218.   {
  219.     _family = vfSansSerif;
  220.     _weight = vfNormal;
  221.     _style = vfItalic;
  222.   }
  223.   else if (strcmp(_fat.szFacename, "Helvetica Bold Italic") == 0 ||
  224.        strcmp(_fat.szFacename, "Helv Bold Italic") == 0)
  225.   {
  226.     _family = vfSansSerif;
  227.     _weight = vfBold;
  228.     _style = vfItalic;
  229.   }
  230.   //  fixed pitch fonts
  231.   else if (strcmp(_fat.szFacename, "Courier") == 0 )
  232.   {
  233.     _family = vfFixed;
  234.     _weight = vfNormal;
  235.     _style = vfNormal;
  236.   }
  237.   else if (strcmp(_fat.szFacename, "Courier Bold") == 0 )
  238.   {
  239.     _family = vfFixed;
  240.     _weight = vfBold;
  241.     _style = vfNormal;
  242.   }
  243.   else if (strcmp(_fat.szFacename, "Courier Italic") == 0 )
  244.   {
  245.     _family = vfFixed;
  246.     _weight = vfNormal;
  247.     _style = vfItalic;
  248.   }
  249.   else if (strcmp(_fat.szFacename, "Courier Bold Italic") == 0 )
  250.   {
  251.     _family = vfFixed;
  252.     _weight = vfBold;
  253.     _style = vfItalic;
  254.   }
  255.   // decorative font
  256.   else if (strcmp(_fat.szFacename, "Symbol Set") == 0 )
  257.   {
  258.     _family = vfDecorative;
  259.     _weight = vfNormal;
  260.     _style = vfNormal;
  261.   }
  262.   // default fixed pitch font
  263.   else if (strcmp(_fat.szFacename, "System Monospaced") == 0 )
  264.   {
  265.     _family = vfDefaultFixed;
  266.   }
  267.   // default proportional pitch font
  268.   else if (strcmp(_fat.szFacename, "System Proportional") == 0 )
  269.   {
  270.     _family = vfDefaultVariable;
  271.   }
  272.   // otherwise, it must be an 'other' font
  273.   else
  274.   {
  275.     _family = vfOtherFont;  // a Native OS/2 font
  276.   }
  277.  
  278.   // Finally, check things that might make it NOT a V font.
  279.   if (_fat.fsSelection & FATTR_SEL_STRIKEOUT ||
  280.       _fat.fsSelection & FATTR_SEL_OUTLINE)
  281.   {
  282.     _family = vfOtherFont;  // a Native OS/2 font
  283.   }
  284. }
  285.  
  286. //=======================>>> vFont::~vFont <<<=============================
  287.   vFont::~vFont()
  288.   {
  289.     SysDebug(Destructor,"vFont::~vFont() destructor\n")
  290.  
  291.     // delete the font from all assigned dc's
  292.     for (int i=0; i<MAXPS; i++)
  293.     {
  294.       if (_status[i].dc != 0)
  295.       {
  296.     GpiSetCharSet(_status[i].dc, LCID_DEFAULT);     // restore default font
  297.     GpiDeleteSetId(_status[i].dc, _status[i].fid);  // destroy logical font
  298.       }
  299.     }
  300.   }
  301.  
  302. //=======================>>> vFont::LoadFont <<<=============================
  303.   void vFont::LoadFont(HPS dc)
  304.   {
  305.     // if font already created, then just set to PS, otherwise need to create the
  306.     // logical font first
  307.     int i;
  308.     for (i=0; i< MAXPS; i++)
  309.     {
  310.       if (dc == _status[i].dc)
  311.       {
  312.     GpiSetCharSet(dc, _status[i].fid);
  313.     // get info on current font and load into font metrics
  314.     GpiQueryFontMetrics(dc, sizeof(_fm), &_fm);
  315.  
  316.     // set the char box size if its an Adobe (outline) font
  317.     if (_fm.fsDefn & FM_DEFN_OUTLINE)
  318.     {
  319.       GpiSetCharBox(dc, &_status[i].CharBoxSize);
  320.     }
  321.     return;  // font loaded, we are done
  322.       }
  323.     }
  324.     // else font not created yet
  325.  
  326.     // fill in the _fat structure and create the logical font
  327.     ULONG chrSet = theApp->AppCP();
  328.     switch (_family)
  329.     {
  330.       // make monospaced system default as per windows code
  331.       case vfDefaultSystem:
  332.       case vfDefaultFixed:
  333.         _fat.fsFontUse = 0;
  334.         _angle = 0;
  335.         strncpy(_fat.szFacename, "System Monospaced", FACESIZE);
  336.         break;
  337.  
  338.       case vfSerif:    // Serif font
  339.         _fat.fsFontUse = FATTR_FONTUSE_OUTLINE;
  340.         if (_weight == vfNormal && _style == vfNormal)
  341.           strncpy(_fat.szFacename, "Times New Roman", FACESIZE);
  342.         else if (_weight == vfBold && _style == vfNormal)
  343.           strncpy(_fat.szFacename, "Times New Roman Bold", FACESIZE);
  344.         else if (_weight == vfNormal && _style == vfItalic)
  345.           strncpy(_fat.szFacename, "Times New Roman Italic", FACESIZE);
  346.         else
  347.           strncpy(_fat.szFacename, "Times New Roman Bold Italic", FACESIZE);
  348.         break;
  349.  
  350.       case vfSansSerif:    // SansSerif Font
  351.         _fat.fsFontUse = FATTR_FONTUSE_OUTLINE;
  352.         if (_weight == vfNormal && _style == vfNormal)
  353.           strncpy(_fat.szFacename, "Helvetica", FACESIZE);
  354.         else if (_weight == vfBold && _style == vfNormal)
  355.           strncpy(_fat.szFacename, "Helvetica Bold", FACESIZE);
  356.         else if (_weight == vfNormal && _style == vfItalic)
  357.           strncpy(_fat.szFacename, "Helvetica Italic", FACESIZE);
  358.         else
  359.           strncpy(_fat.szFacename, "Helvetica Bold Italic", FACESIZE);
  360.         break;
  361.  
  362.       case vfFixed:        // Courier font
  363.  
  364.         _fat.fsFontUse = 0;
  365.         _angle = 0;
  366.         strncpy(_fat.szFacename, "System Monospaced", FACESIZE);
  367. /*
  368.         // Although Courier is a fixed space font, OS/2 may or may not
  369.         // work that way.  If you choose Courier at a font size of 10 or 12
  370.         // you get the desired monospace font (a bitmap font).
  371.         // For other point sizes, you get an "outline" Courier font that is proportional.
  372.         // Just another saga is the disgusting mess that OS/2 calls a font system.  Imagine
  373.         // having both outline and bitmap fonts with the same name.... uuughhh!
  374.         // Hence, we will use system monospace instead to avoid a debacle!
  375.         _fat.fsFontUse = FATTR_FONTUSE_OUTLINE;
  376.         if (_weight == vfNormal && _style == vfNormal)
  377.           strncpy(_fat.szFacename, "Courier", FACESIZE);
  378.         else if (_weight == vfBold && _style == vfNormal)
  379.           strncpy(_fat.szFacename, "Courier Bold", FACESIZE);
  380.         else if (_weight == vfNormal && _style == vfItalic)
  381.           strncpy(_fat.szFacename, "Courier Italic", FACESIZE);
  382.         else
  383.           strncpy(_fat.szFacename, "Courier Bold Italic", FACESIZE);
  384. */
  385.         break;
  386.  
  387.       case vfDecorative:    // Decorative
  388.         _fat.fsFontUse = FATTR_FONTUSE_OUTLINE;
  389.         strncpy(_fat.szFacename, "Symbol Set", FACESIZE);
  390.         chrSet = 65400;
  391.         break;
  392.  
  393.       case vfOtherFont:    // set by font picker dialog
  394.         if (_isFromFntDlg == 1 )
  395.         {
  396.           // all okay
  397.           break;
  398.         }
  399.         // otherwise fall through to default variable font
  400.  
  401.       case vfDefaultVariable:    // default font
  402.       default:
  403.         _fat.fsFontUse = 0;
  404.         _angle = 0;
  405.         strncpy(_fat.szFacename, "System Proportional",FACESIZE);
  406.         break;
  407.     }
  408.     // Now, set the rest of the font attributes
  409.     _fat.usCodePage = chrSet;
  410.  
  411.     // synthesize attributes if bitmap font
  412.     if (!(_fat.fsFontUse & FATTR_FONTUSE_OUTLINE))
  413.     {
  414.       if (_weight == vfNormal && _style == vfItalic)
  415.     _fat.fsSelection = FATTR_SEL_ITALIC;
  416.       else if (_weight == vfBold && _style == vfNormal)
  417.     _fat.fsSelection = FATTR_SEL_BOLD;
  418.       else if (_weight == vfBold && _style == vfItalic)
  419.     _fat.fsSelection = FATTR_SEL_BOLD | FATTR_SEL_ITALIC;
  420.  
  421.       // compute required pointsize if not from font dialog box
  422.       if (_isFromFntDlg == 0 )
  423.       {
  424.     // For bitmap (image) fonts we match the requested font point size
  425.         // to the os/2 font with the closest font size for the system dpi!
  426.         // But there's more to this nightmare.  We must query the bitmap font
  427.         // FONTMETRICS to get the exact value for MaxBaseLineExt and AveCharWidth.
  428.         // in order to select the font, otherwise the selection fails
  429.         // and we get the default font which is System Proportional!!!!!
  430.     // They must have been on heavy drugs when they came
  431.     // with this bizarre font API
  432.         LoadBitmapFont(dc);
  433.       }
  434.     }
  435.     // set underlining for all fonts
  436.     if (_underlined )
  437.       _fat.fsSelection |= FATTR_SEL_UNDERSCORE;
  438.  
  439.     // now create the logical font
  440.     // First, find an unused index in the _status array and save dc
  441.     for (i=0; i< MAXPS; i++)
  442.     {
  443.       if (_status[i].dc == 0)
  444.     break;
  445.     }
  446.     _status[i].dc = dc;
  447.     // Next, allocate an available LCID.  This routine will find the
  448.     // lowest numbered id not currently being used
  449.     LONG Count = GpiQueryNumberSetIds(dc);   // query the number of set ids
  450.     if (Count==0)
  451.       _status[i].fid = 1;            // none allocated yet, so choice is easy
  452.     else
  453.     {
  454.       // we need space for 3 arrays (LONG[Count], LONG[Count], STR8[Count])
  455.       PLONG pLcids = (PLONG) malloc((ULONG)((2 * sizeof(LONG) + sizeof(STR8)) * Count ));
  456.       PLONG pTypes = (PLONG)(pLcids + Count);  // start of 2nd array
  457.       PSTR8 pNames = (PSTR8)(pTypes + Count);  // start of 3rd array
  458.  
  459.       GpiQuerySetIds(dc, Count, pTypes, pNames, pLcids); // get all allocated ids
  460.  
  461.       // search over the entire set of ids
  462.       for (_status[i].fid=1; _status[i].fid<=LCID_MAX; _status[i].fid++)
  463.       {
  464.     // we check if any of the allocated ids are set to _status[i].fid
  465.         int j;
  466.     for (j=0; (j<Count) && (pLcids[j]!=_status[i].fid); j++);
  467.     // if j==Count then none of the allocated ids matched _status[i].fid,
  468.     // and thus _status[i].fid is available for assignment, otherwise keep looking
  469.     if (j==Count)
  470.       break;
  471.       }
  472.       free(pLcids);
  473.     }
  474.  
  475.     // now create the logical font
  476.     int rc = GpiCreateLogFont(dc, (PSTR8)NULL, _status[i].fid, &_fat);
  477.     SysDebug3(Text,"vFont::LoadFont %s size=%u (GpiCreateLogFont=%u)\n",
  478.       _fat.szFacename, _pointSize, rc);
  479.  
  480.     GpiSetCharSet(dc, _status[i].fid);
  481.  
  482.     // we set the character angle here
  483.     // note that bitmap fonts do not work very well with angles
  484.     // other than 0 degrees.
  485.     LONG dx, dy;
  486.     dx = (LONG)( (2^16) * cos(_angle*PI/180.) );
  487.     dy = (LONG)( (2^16) * sin(_angle*PI/180.) );
  488.     GRADIENTL grAngle={dx,dy};
  489.     GpiSetCharAngle(dc, &grAngle);
  490.  
  491.     // get info on current font and load into font metrics
  492.     GpiQueryFontMetrics(dc, sizeof(_fm), &_fm);
  493.  
  494.     // now set the character box (pointsize) if its an outline font
  495.     if (_fm.fsDefn & FM_DEFN_OUTLINE)
  496.     {
  497.       // get the device resolution in pels/meter
  498.       POINTL points[2];
  499.       SIZEF CharBoxSize;
  500.  
  501.       // compute the point size in pels
  502.       // get dc resolution pels/meter
  503.       HDC hDevCxt = GpiQueryDevice(dc);
  504.       DevQueryCaps(hDevCxt, CAPS_HORIZONTAL_RESOLUTION, 1L, &_XDeviceRes);
  505.       DevQueryCaps(hDevCxt, CAPS_VERTICAL_RESOLUTION, 1L, &_YDeviceRes);
  506.       // compute equivalent pointsize in pels
  507.       // we add half DPM to get correct round-off behaviour
  508.       points[0].x = 0;
  509.       points[0].y = 0;
  510.       points[1].x = (_pointSize * 10 * _XDeviceRes + DPM/2)/DPM;
  511.       points[1].y = (_pointSize * 10 * _YDeviceRes + DPM/2)/DPM;
  512.       // this is probably a unity transform but play it safe...
  513.       GpiConvert(dc, CVTC_DEVICE, CVTC_WORLD, 2L, points);
  514.       // transform to type fixed
  515.       CharBoxSize.cx = MAKEFIXED((points[1].x - points[0].x), 0);
  516.       CharBoxSize.cy = MAKEFIXED((points[1].y - points[0].y), 0);
  517.       GpiSetCharBox(dc, &CharBoxSize);
  518.       // save for future loads
  519.       _status[i].CharBoxSize.cx = CharBoxSize.cx;
  520.       _status[i].CharBoxSize.cy = CharBoxSize.cy;
  521.  
  522.     }
  523.   }
  524.  
  525.  
  526. //====================>>> vFont::loadBitmapFont <<<==========================
  527.   // finds the nearest bitmap font to the requested pointsize and
  528.   // facename.  This is for internal use only. Minimal error
  529.   // checking is done.
  530.   void vFont::LoadBitmapFont( HPS dc )
  531.   {
  532.     PFONTMETRICS pFM, pCurFM;
  533.     LONG Count = 0L;
  534.     int  i;
  535.  
  536.     // Do any fonts with the requested facename exist
  537.     Count = GpiQueryFonts (dc, QF_PUBLIC | QF_PRIVATE, _fat.szFacename,
  538.       &Count, (LONG)sizeof(FONTMETRICS), 0);
  539.  
  540.     if (Count)
  541.     {
  542.       // If so allocate memory and retrieve their metrics
  543.       DosAllocMem ((PPVOID)&pFM, sizeof(FONTMETRICS) * (USHORT)Count,
  544.         OBJ_TILE | PAG_READ | PAG_WRITE | PAG_COMMIT);
  545.  
  546.       GpiQueryFonts (dc,QF_PUBLIC | QF_PRIVATE, _fat.szFacename,
  547.         &Count, (LONG)sizeof(FONTMETRICS), pFM);
  548.  
  549.       // get the font resolution (dpi) of the display
  550.       HDC hDevCxt = GpiQueryDevice(dc);
  551.       LONG   cxFontRes, cyFontRes;
  552.       DevQueryCaps(hDevCxt, CAPS_VERTICAL_FONT_RES, 1L, &cyFontRes);
  553.       DevQueryCaps(hDevCxt, CAPS_HORIZONTAL_FONT_RES, 1L, &cxFontRes);
  554.  
  555.       // Look through the list trying to find a match
  556.       pCurFM = pFM;
  557.       int BestDelta = 9999999;   // set to something huge
  558.  
  559.       while (Count)
  560.       {
  561.         if (pCurFM->fsDefn & FM_DEFN_OUTLINE)
  562.         {
  563.           // this should not happen, since this is intended to be used
  564.           // only for finding bitmap fonts
  565.           Count--;
  566.           continue;
  567.         }
  568.         // check if resolution is what we are looking for +/- some slop
  569.         else if ( (pCurFM->sYDeviceRes == cyFontRes) &&
  570.           (pCurFM->sXDeviceRes == cxFontRes) )
  571.         {
  572.           int Delta = abs((pCurFM->sNominalPointSize / 10) - _pointSize);
  573.           if (Delta <= BestDelta)
  574.           {
  575.             BestDelta = Delta;
  576.             pFM = pCurFM;
  577.           }
  578.         }
  579.         Count--;
  580.         if (Count)
  581.           pCurFM++;
  582.       // now set the font attributes to those of the best match
  583.       _fat.lAveCharWidth = pFM->lAveCharWidth;
  584.       _fat.lMaxBaselineExt = pFM->lMaxBaselineExt;
  585.  
  586.       SysDebug3(Text,"vFont::LoadBitmapFont %s CharWidth=%u (Delta=%u)\n",
  587.         _fat.szFacename, pFM->lAveCharWidth, BestDelta);
  588.       }
  589.       DosFreeMem(pFM);
  590.     }
  591.   }
  592.