home *** CD-ROM | disk | FTP | other *** search
- //===============================================================
- // vfont.cxx - The font class - Windows
- //
- // Copyright (C) 1995,1996,1997,1998 Bruce E. Wampler
- //
- // This file is part of the V C++ GUI Framework, and is covered
- // under the terms of the GNU Library General Public License,
- // Version 2. This library has NO WARRANTY. See the source file
- // vapp.cxx for more complete information about license terms.
- //===============================================================
-
- #include <v/vos2.h> // for OS/2 stuff
- #include <v/vapp.h>
- #include <v/vfont.h>
- #include <math.h>
-
- //=======================>>> vFont::vFont <<<=============================
- vFont::vFont(vFontID fam, int size, vFontID sty, vFontID wt, int und, int ang)
- {
- SysDebug(Constructor,"vFont::vFont() constructor\n")
-
- _family = fam;
- _pointSize = size;
- _style = sty;
- _weight = wt;
- _underlined = und;
- _angle = ang;
- _isFromFntDlg = 0;
- memset(&_fat, 0, sizeof(FATTRS)); // clear structure
- _fat.usRecordLength = sizeof(FATTRS);
- memset(&_status, 0, sizeof(_status)); // clear structure
-
- }
-
- //=====================>>> vFont::vFont <<<===========================
- vFont::vFont(const vFont& ft)
- {
- // Copy constructor - needs to delete object if already
- // created, and copy the values as needed
-
- _family = ft._family;
- _pointSize = ft._pointSize;
- _style = ft._style;
- _weight = ft._weight;
- _underlined = ft._underlined;
- _angle = ft._angle;
- _isFromFntDlg = ft._isFromFntDlg;
- // copy over the selected file attribute and status structures
- memcpy(&_fat, &ft._fat, sizeof(FATTRS));
- memcpy(&_status, &ft._status, sizeof(_status));
- }
-
- //=====================>>> vFont::= <<<===========================
- vFont& vFont::operator =(const vFont& ft)
- {
- if (this == &ft) // assigning to self
- {
- return *this;
- }
- // just like the copy constructor
- _family = ft._family;
- _pointSize = ft._pointSize;
- _style = ft._style;
- _weight = ft._weight;
- _underlined = ft._underlined;
- _angle = ft._angle;
- _isFromFntDlg = ft._isFromFntDlg;
-
- // copy over the selected file attribute structure
- memcpy(&_fat, &ft._fat, sizeof(FATTRS));
- memcpy(&_status, &ft._status, sizeof(_status));
-
- return *this;
- }
-
- //=====================>>> vFont::SetFontValues <<<===========================
- void vFont::SetFontValues(vFontID fam, int size, vFontID sty, vFontID wt,
- int und)
- {
- // delete the old font from all assigned dc's
- for (int i=0; i<MAXPS; i++)
- {
- if (_status[i].dc != 0)
- {
- GpiSetCharSet(_status[i].dc, LCID_DEFAULT); // restore default font
- GpiDeleteSetId(_status[i].dc, _status[i].fid); // destroy logical font
- }
- }
- _family = fam;
- _pointSize = size;
- _style = sty;
- _weight = wt;
- _underlined = und;
- _isFromFntDlg = 0;
- memset(&_fat, 0, sizeof(FATTRS)); // clear structure
- _fat.usRecordLength = sizeof(FATTRS);
- memset(&_status, 0, sizeof(_status)); // clear structure
- }
-
-
- //=====================>>> vFont::SetWinFontValues <<<========================
- // This is the entry point from the font dialog box and is the typical
- // way an app will set the desired font
- void vFont::SetWinFontValues(VCONST FONTDLG& fdlg)
- {
- // delete the old font from all assigned dc's
- for (int i=0; i<MAXPS; i++)
- {
- if (_status[i].dc != 0)
- {
- GpiSetCharSet(_status[i].dc, LCID_DEFAULT); // restore default font
- GpiDeleteSetId(_status[i].dc, _status[i].fid); // destroy logical font
- }
- }
- memset(&_status, 0, sizeof(_status)); // clear structure
-
- _isFromFntDlg = 1; // font selection is from dialog box
-
- // copy over the selected file attribute structure
- memcpy(&_fat, &fdlg.fAttrs, sizeof(FATTRS));
- /*
- _fat.usRecordLength = sizeof(FATTRS);
- _fat.fsSelection = fdlg.fAttrs.fsSelection;
- _fat.lMatch = fdlg.fAttrs.lMatch;
- strcpy(_fat.szFacename, fdlg.fAttrs.szFacename);
- _fat.idRegistry = fdlg.fAttrs.idRegistry;
- _fat.usCodePage = fdlg.fAttrs.usCodePage;
- _fat.lMaxBaselineExt = fdlg.fAttrs.lMaxBaselineExt;
- _fat.lAveCharWidth = fdlg.fAttrs.lAveCharWidth;
- _fat.fsType = fdlg.fAttrs.fsType;
- _fat.fsFontUse = fdlg.fAttrs.fsFontUse;
- */
-
- // now fill in the V font variables
- _pointSize = FIXEDINT(fdlg.fxPointSize);
-
- if (_fat.fsSelection & FATTR_SEL_UNDERSCORE)
- _underlined = 1;
- else
- _underlined = 0;
-
- // fsSelection will indicate Bold and Italic only for synthesized
- // (ie. bitmap) fonts and will not be set for regular Adobe outline fonts
- // For outline fonts must use FONTMETRICS to determine these properties
- // in vfont::loadfont
- if (_fat.fsFontUse & FATTR_FONTUSE_OUTLINE) // its an outline font
- {
- if (fdlg.usWeight >= FWEIGHT_BOLD)
- _weight = vfBold;
- else
- _weight = vfNormal;
-
- if (_fat.fsSelection & FATTR_SEL_ITALIC)
- _style = vfItalic;
- else
- _style = vfNormal;
- }
- else // an image font
- {
- if (_fat.fsSelection & FATTR_SEL_ITALIC)
- _style = vfItalic;
- else
- _style = vfNormal;
-
- if (_fat.fsSelection & FATTR_SEL_BOLD)
- _weight = vfBold;
- else
- _weight = vfNormal;
- }
-
- // Now, determine if it is a V family
- // Serif fonts
- if (strcmp(_fat.szFacename, "Times New Roman") == 0 ||
- strcmp(_fat.szFacename, "Tms Rmn") == 0)
- {
- _family = vfSerif;
- _weight = vfNormal;
- _style = vfNormal;
- }
- else if (strcmp(_fat.szFacename, "Times New Roman Italic") == 0 ||
- strcmp(_fat.szFacename, "Tms Rmn Italic") == 0)
- {
- _family = vfSerif;
- _weight = vfNormal;
- _style = vfItalic;
- }
- else if (strcmp(_fat.szFacename, "Times New Roman Bold") == 0 ||
- strcmp(_fat.szFacename, "Tms Rmn Bold") == 0)
- {
- _family = vfSerif;
- _weight = vfBold;
- _style = vfNormal;
- }
- else if (strcmp(_fat.szFacename, "Times New Roman Bold Italic") == 0 ||
- strcmp(_fat.szFacename, "Tms Rmn Bold Italic") == 0)
- {
- _family = vfSerif;
- _weight = vfBold;
- _style = vfItalic;
- }
- // Sans Serif fonts
- else if (strcmp(_fat.szFacename, "Helvetica") == 0 ||
- strcmp(_fat.szFacename, "Helv") == 0)
- {
- _family = vfSansSerif;
- _weight = vfNormal;
- _style = vfNormal;
- }
- else if (strcmp(_fat.szFacename, "Helvetica Bold") == 0 ||
- strcmp(_fat.szFacename, "Helv Bold") == 0)
- {
- _family = vfSansSerif;
- _weight = vfBold;
- _style = vfNormal;
- }
- else if (strcmp(_fat.szFacename, "Helvetica Italic") == 0 ||
- strcmp(_fat.szFacename, "Helv Italic") == 0)
- {
- _family = vfSansSerif;
- _weight = vfNormal;
- _style = vfItalic;
- }
- else if (strcmp(_fat.szFacename, "Helvetica Bold Italic") == 0 ||
- strcmp(_fat.szFacename, "Helv Bold Italic") == 0)
- {
- _family = vfSansSerif;
- _weight = vfBold;
- _style = vfItalic;
- }
- // fixed pitch fonts
- else if (strcmp(_fat.szFacename, "Courier") == 0 )
- {
- _family = vfFixed;
- _weight = vfNormal;
- _style = vfNormal;
- }
- else if (strcmp(_fat.szFacename, "Courier Bold") == 0 )
- {
- _family = vfFixed;
- _weight = vfBold;
- _style = vfNormal;
- }
- else if (strcmp(_fat.szFacename, "Courier Italic") == 0 )
- {
- _family = vfFixed;
- _weight = vfNormal;
- _style = vfItalic;
- }
- else if (strcmp(_fat.szFacename, "Courier Bold Italic") == 0 )
- {
- _family = vfFixed;
- _weight = vfBold;
- _style = vfItalic;
- }
- // decorative font
- else if (strcmp(_fat.szFacename, "Symbol Set") == 0 )
- {
- _family = vfDecorative;
- _weight = vfNormal;
- _style = vfNormal;
- }
- // default fixed pitch font
- else if (strcmp(_fat.szFacename, "System Monospaced") == 0 )
- {
- _family = vfDefaultFixed;
- }
- // default proportional pitch font
- else if (strcmp(_fat.szFacename, "System Proportional") == 0 )
- {
- _family = vfDefaultVariable;
- }
- // otherwise, it must be an 'other' font
- else
- {
- _family = vfOtherFont; // a Native OS/2 font
- }
-
- // Finally, check things that might make it NOT a V font.
- if (_fat.fsSelection & FATTR_SEL_STRIKEOUT ||
- _fat.fsSelection & FATTR_SEL_OUTLINE)
- {
- _family = vfOtherFont; // a Native OS/2 font
- }
- }
-
- //=======================>>> vFont::~vFont <<<=============================
- vFont::~vFont()
- {
- SysDebug(Destructor,"vFont::~vFont() destructor\n")
-
- // delete the font from all assigned dc's
- for (int i=0; i<MAXPS; i++)
- {
- if (_status[i].dc != 0)
- {
- GpiSetCharSet(_status[i].dc, LCID_DEFAULT); // restore default font
- GpiDeleteSetId(_status[i].dc, _status[i].fid); // destroy logical font
- }
- }
- }
-
- //=======================>>> vFont::LoadFont <<<=============================
- void vFont::LoadFont(HPS dc)
- {
- // if font already created, then just set to PS, otherwise need to create the
- // logical font first
- int i;
- for (i=0; i< MAXPS; i++)
- {
- if (dc == _status[i].dc)
- {
- GpiSetCharSet(dc, _status[i].fid);
- // get info on current font and load into font metrics
- GpiQueryFontMetrics(dc, sizeof(_fm), &_fm);
-
- // set the char box size if its an Adobe (outline) font
- if (_fm.fsDefn & FM_DEFN_OUTLINE)
- {
- GpiSetCharBox(dc, &_status[i].CharBoxSize);
- }
- return; // font loaded, we are done
- }
- }
- // else font not created yet
-
- // fill in the _fat structure and create the logical font
- ULONG chrSet = theApp->AppCP();
- switch (_family)
- {
- // make monospaced system default as per windows code
- case vfDefaultSystem:
- case vfDefaultFixed:
- _fat.fsFontUse = 0;
- _angle = 0;
- strncpy(_fat.szFacename, "System Monospaced", FACESIZE);
- break;
-
- case vfSerif: // Serif font
- _fat.fsFontUse = FATTR_FONTUSE_OUTLINE;
- if (_weight == vfNormal && _style == vfNormal)
- strncpy(_fat.szFacename, "Times New Roman", FACESIZE);
- else if (_weight == vfBold && _style == vfNormal)
- strncpy(_fat.szFacename, "Times New Roman Bold", FACESIZE);
- else if (_weight == vfNormal && _style == vfItalic)
- strncpy(_fat.szFacename, "Times New Roman Italic", FACESIZE);
- else
- strncpy(_fat.szFacename, "Times New Roman Bold Italic", FACESIZE);
- break;
-
- case vfSansSerif: // SansSerif Font
- _fat.fsFontUse = FATTR_FONTUSE_OUTLINE;
- if (_weight == vfNormal && _style == vfNormal)
- strncpy(_fat.szFacename, "Helvetica", FACESIZE);
- else if (_weight == vfBold && _style == vfNormal)
- strncpy(_fat.szFacename, "Helvetica Bold", FACESIZE);
- else if (_weight == vfNormal && _style == vfItalic)
- strncpy(_fat.szFacename, "Helvetica Italic", FACESIZE);
- else
- strncpy(_fat.szFacename, "Helvetica Bold Italic", FACESIZE);
- break;
-
- case vfFixed: // Courier font
-
- _fat.fsFontUse = 0;
- _angle = 0;
- strncpy(_fat.szFacename, "System Monospaced", FACESIZE);
- /*
- // Although Courier is a fixed space font, OS/2 may or may not
- // work that way. If you choose Courier at a font size of 10 or 12
- // you get the desired monospace font (a bitmap font).
- // For other point sizes, you get an "outline" Courier font that is proportional.
- // Just another saga is the disgusting mess that OS/2 calls a font system. Imagine
- // having both outline and bitmap fonts with the same name.... uuughhh!
- // Hence, we will use system monospace instead to avoid a debacle!
- _fat.fsFontUse = FATTR_FONTUSE_OUTLINE;
- if (_weight == vfNormal && _style == vfNormal)
- strncpy(_fat.szFacename, "Courier", FACESIZE);
- else if (_weight == vfBold && _style == vfNormal)
- strncpy(_fat.szFacename, "Courier Bold", FACESIZE);
- else if (_weight == vfNormal && _style == vfItalic)
- strncpy(_fat.szFacename, "Courier Italic", FACESIZE);
- else
- strncpy(_fat.szFacename, "Courier Bold Italic", FACESIZE);
- */
- break;
-
- case vfDecorative: // Decorative
- _fat.fsFontUse = FATTR_FONTUSE_OUTLINE;
- strncpy(_fat.szFacename, "Symbol Set", FACESIZE);
- chrSet = 65400;
- break;
-
- case vfOtherFont: // set by font picker dialog
- if (_isFromFntDlg == 1 )
- {
- // all okay
- break;
- }
- // otherwise fall through to default variable font
-
- case vfDefaultVariable: // default font
- default:
- _fat.fsFontUse = 0;
- _angle = 0;
- strncpy(_fat.szFacename, "System Proportional",FACESIZE);
- break;
- }
- // Now, set the rest of the font attributes
- _fat.usCodePage = chrSet;
-
- // synthesize attributes if bitmap font
- if (!(_fat.fsFontUse & FATTR_FONTUSE_OUTLINE))
- {
- if (_weight == vfNormal && _style == vfItalic)
- _fat.fsSelection = FATTR_SEL_ITALIC;
- else if (_weight == vfBold && _style == vfNormal)
- _fat.fsSelection = FATTR_SEL_BOLD;
- else if (_weight == vfBold && _style == vfItalic)
- _fat.fsSelection = FATTR_SEL_BOLD | FATTR_SEL_ITALIC;
-
- // compute required pointsize if not from font dialog box
- if (_isFromFntDlg == 0 )
- {
- // For bitmap (image) fonts we match the requested font point size
- // to the os/2 font with the closest font size for the system dpi!
- // But there's more to this nightmare. We must query the bitmap font
- // FONTMETRICS to get the exact value for MaxBaseLineExt and AveCharWidth.
- // in order to select the font, otherwise the selection fails
- // and we get the default font which is System Proportional!!!!!
- // They must have been on heavy drugs when they came
- // with this bizarre font API
- LoadBitmapFont(dc);
- }
- }
- // set underlining for all fonts
- if (_underlined )
- _fat.fsSelection |= FATTR_SEL_UNDERSCORE;
-
- // now create the logical font
- // First, find an unused index in the _status array and save dc
- for (i=0; i< MAXPS; i++)
- {
- if (_status[i].dc == 0)
- break;
- }
- _status[i].dc = dc;
- // Next, allocate an available LCID. This routine will find the
- // lowest numbered id not currently being used
- LONG Count = GpiQueryNumberSetIds(dc); // query the number of set ids
- if (Count==0)
- _status[i].fid = 1; // none allocated yet, so choice is easy
- else
- {
- // we need space for 3 arrays (LONG[Count], LONG[Count], STR8[Count])
- PLONG pLcids = (PLONG) malloc((ULONG)((2 * sizeof(LONG) + sizeof(STR8)) * Count ));
- PLONG pTypes = (PLONG)(pLcids + Count); // start of 2nd array
- PSTR8 pNames = (PSTR8)(pTypes + Count); // start of 3rd array
-
- GpiQuerySetIds(dc, Count, pTypes, pNames, pLcids); // get all allocated ids
-
- // search over the entire set of ids
- for (_status[i].fid=1; _status[i].fid<=LCID_MAX; _status[i].fid++)
- {
- // we check if any of the allocated ids are set to _status[i].fid
- int j;
- for (j=0; (j<Count) && (pLcids[j]!=_status[i].fid); j++);
- // if j==Count then none of the allocated ids matched _status[i].fid,
- // and thus _status[i].fid is available for assignment, otherwise keep looking
- if (j==Count)
- break;
- }
- free(pLcids);
- }
-
- // now create the logical font
- int rc = GpiCreateLogFont(dc, (PSTR8)NULL, _status[i].fid, &_fat);
- SysDebug3(Text,"vFont::LoadFont %s size=%u (GpiCreateLogFont=%u)\n",
- _fat.szFacename, _pointSize, rc);
-
- GpiSetCharSet(dc, _status[i].fid);
-
- // we set the character angle here
- // note that bitmap fonts do not work very well with angles
- // other than 0 degrees.
- LONG dx, dy;
- dx = (LONG)( (2^16) * cos(_angle*PI/180.) );
- dy = (LONG)( (2^16) * sin(_angle*PI/180.) );
- GRADIENTL grAngle={dx,dy};
- GpiSetCharAngle(dc, &grAngle);
-
- // get info on current font and load into font metrics
- GpiQueryFontMetrics(dc, sizeof(_fm), &_fm);
-
- // now set the character box (pointsize) if its an outline font
- if (_fm.fsDefn & FM_DEFN_OUTLINE)
- {
- // get the device resolution in pels/meter
- POINTL points[2];
- SIZEF CharBoxSize;
-
- // compute the point size in pels
- // get dc resolution pels/meter
- HDC hDevCxt = GpiQueryDevice(dc);
- DevQueryCaps(hDevCxt, CAPS_HORIZONTAL_RESOLUTION, 1L, &_XDeviceRes);
- DevQueryCaps(hDevCxt, CAPS_VERTICAL_RESOLUTION, 1L, &_YDeviceRes);
- // compute equivalent pointsize in pels
- // we add half DPM to get correct round-off behaviour
- points[0].x = 0;
- points[0].y = 0;
- points[1].x = (_pointSize * 10 * _XDeviceRes + DPM/2)/DPM;
- points[1].y = (_pointSize * 10 * _YDeviceRes + DPM/2)/DPM;
- // this is probably a unity transform but play it safe...
- GpiConvert(dc, CVTC_DEVICE, CVTC_WORLD, 2L, points);
- // transform to type fixed
- CharBoxSize.cx = MAKEFIXED((points[1].x - points[0].x), 0);
- CharBoxSize.cy = MAKEFIXED((points[1].y - points[0].y), 0);
- GpiSetCharBox(dc, &CharBoxSize);
- // save for future loads
- _status[i].CharBoxSize.cx = CharBoxSize.cx;
- _status[i].CharBoxSize.cy = CharBoxSize.cy;
-
- }
- }
-
-
- //====================>>> vFont::loadBitmapFont <<<==========================
- // finds the nearest bitmap font to the requested pointsize and
- // facename. This is for internal use only. Minimal error
- // checking is done.
- void vFont::LoadBitmapFont( HPS dc )
- {
- PFONTMETRICS pFM, pCurFM;
- LONG Count = 0L;
- int i;
-
- // Do any fonts with the requested facename exist
- Count = GpiQueryFonts (dc, QF_PUBLIC | QF_PRIVATE, _fat.szFacename,
- &Count, (LONG)sizeof(FONTMETRICS), 0);
-
- if (Count)
- {
- // If so allocate memory and retrieve their metrics
- DosAllocMem ((PPVOID)&pFM, sizeof(FONTMETRICS) * (USHORT)Count,
- OBJ_TILE | PAG_READ | PAG_WRITE | PAG_COMMIT);
-
- GpiQueryFonts (dc,QF_PUBLIC | QF_PRIVATE, _fat.szFacename,
- &Count, (LONG)sizeof(FONTMETRICS), pFM);
-
- // get the font resolution (dpi) of the display
- HDC hDevCxt = GpiQueryDevice(dc);
- LONG cxFontRes, cyFontRes;
- DevQueryCaps(hDevCxt, CAPS_VERTICAL_FONT_RES, 1L, &cyFontRes);
- DevQueryCaps(hDevCxt, CAPS_HORIZONTAL_FONT_RES, 1L, &cxFontRes);
-
- // Look through the list trying to find a match
- pCurFM = pFM;
- int BestDelta = 9999999; // set to something huge
-
- while (Count)
- {
- if (pCurFM->fsDefn & FM_DEFN_OUTLINE)
- {
- // this should not happen, since this is intended to be used
- // only for finding bitmap fonts
- Count--;
- continue;
- }
- // check if resolution is what we are looking for +/- some slop
- else if ( (pCurFM->sYDeviceRes == cyFontRes) &&
- (pCurFM->sXDeviceRes == cxFontRes) )
- {
- int Delta = abs((pCurFM->sNominalPointSize / 10) - _pointSize);
- if (Delta <= BestDelta)
- {
- BestDelta = Delta;
- pFM = pCurFM;
- }
- }
- Count--;
- if (Count)
- pCurFM++;
- // now set the font attributes to those of the best match
- _fat.lAveCharWidth = pFM->lAveCharWidth;
- _fat.lMaxBaselineExt = pFM->lMaxBaselineExt;
-
- SysDebug3(Text,"vFont::LoadBitmapFont %s CharWidth=%u (Delta=%u)\n",
- _fat.szFacename, pFM->lAveCharWidth, BestDelta);
- }
- DosFreeMem(pFM);
- }
- }
-