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 >
Wrap
C/C++ Source or Header
|
1999-02-19
|
20KB
|
592 lines
//===============================================================
// 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);
}
}