git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8906 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
520 lines
14 KiB
C++
520 lines
14 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: msw/fontutil.cpp
|
|
// Purpose: font-related helper functions for wxMSW
|
|
// Author: Modified by David Webster for OS/2
|
|
// Modified by:
|
|
// Created: 01.03.00
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
|
|
// Licence: wxWindows license
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define DEBUG_PRINTF(NAME) { static int raz=0; \
|
|
printf( #NAME " %i\n",raz); fflush(stdout); \
|
|
raz++; \
|
|
}
|
|
|
|
// ============================================================================
|
|
// declarations
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation "fontutil.h"
|
|
#endif
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/string.h"
|
|
#include "wx/log.h"
|
|
#include "wx/intl.h"
|
|
#endif //WX_PRECOMP
|
|
|
|
#include "wx/os2/private.h"
|
|
|
|
#include "wx/fontutil.h"
|
|
#include "wx/fontmap.h"
|
|
|
|
#include "wx/tokenzr.h"
|
|
|
|
// ============================================================================
|
|
// implementation
|
|
// ============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxNativeEncodingInfo
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// convert to/from the string representation: format is
|
|
// encodingid;facename[;charset]
|
|
|
|
bool wxNativeEncodingInfo::FromString(
|
|
const wxString& rsStr
|
|
)
|
|
{
|
|
wxStringTokenizer vTokenizer(rsStr, _T(";"));
|
|
wxString sEncid = vTokenizer.GetNextToken();
|
|
long lEnc;
|
|
|
|
if (!sEncid.ToLong(&lEnc))
|
|
return FALSE;
|
|
encoding = (wxFontEncoding)lEnc;
|
|
facename = vTokenizer.GetNextToken();
|
|
if (!facename)
|
|
return FALSE;
|
|
|
|
wxString sTmp = vTokenizer.GetNextToken();
|
|
|
|
if (!sTmp)
|
|
{
|
|
charset = 850;
|
|
}
|
|
else
|
|
{
|
|
if ( wxSscanf(sTmp, _T("%u"), &charset) != 1 )
|
|
{
|
|
// should be a number!
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
} // end of wxNativeEncodingInfo::FromString
|
|
|
|
wxString wxNativeEncodingInfo::ToString() const
|
|
{
|
|
wxString sStr;
|
|
|
|
sStr << (long)encoding << _T(';') << facename;
|
|
|
|
if (charset != 850)
|
|
{
|
|
sStr << _T(';') << charset;
|
|
}
|
|
return sStr;
|
|
} // end of wxNativeEncodingInfo::ToString
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// helper functions
|
|
// ----------------------------------------------------------------------------
|
|
|
|
bool wxGetNativeFontEncoding(
|
|
wxFontEncoding vEncoding
|
|
, wxNativeEncodingInfo* pInfo
|
|
)
|
|
{
|
|
wxCHECK_MSG(pInfo, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
|
|
if (vEncoding == wxFONTENCODING_DEFAULT)
|
|
{
|
|
vEncoding = wxFont::GetDefaultEncoding();
|
|
}
|
|
switch (vEncoding)
|
|
{
|
|
case wxFONTENCODING_ISO8859_1:
|
|
case wxFONTENCODING_ISO8859_15:
|
|
case wxFONTENCODING_CP1250:
|
|
pInfo->charset = 1250;
|
|
break;
|
|
|
|
case wxFONTENCODING_ISO8859_2:
|
|
case wxFONTENCODING_CP1252:
|
|
pInfo->charset = 1252;
|
|
break;
|
|
|
|
case wxFONTENCODING_ISO8859_4:
|
|
case wxFONTENCODING_ISO8859_10:
|
|
pInfo->charset = 921; // what is baltic?
|
|
break;
|
|
|
|
case wxFONTENCODING_ISO8859_5:
|
|
case wxFONTENCODING_CP1251:
|
|
pInfo->charset = 1251;
|
|
break;
|
|
|
|
case wxFONTENCODING_ISO8859_6:
|
|
pInfo->charset = 864;
|
|
break;
|
|
|
|
case wxFONTENCODING_ISO8859_7:
|
|
pInfo->charset = 869;
|
|
break;
|
|
|
|
case wxFONTENCODING_ISO8859_8:
|
|
pInfo->charset = 862;
|
|
break;
|
|
|
|
case wxFONTENCODING_ISO8859_9:
|
|
pInfo->charset = 857;
|
|
break;
|
|
|
|
case wxFONTENCODING_ISO8859_11:
|
|
pInfo->charset = 874; // what is thai
|
|
break;
|
|
|
|
case wxFONTENCODING_CP437:
|
|
pInfo->charset = 437;
|
|
break;
|
|
|
|
default:
|
|
wxFAIL_MSG(wxT("unsupported encoding"));
|
|
// fall through
|
|
|
|
case wxFONTENCODING_SYSTEM:
|
|
pInfo->charset = 850;
|
|
break;
|
|
}
|
|
return TRUE;
|
|
} // end of wxGetNativeFontEncoding
|
|
|
|
bool wxTestFontEncoding(
|
|
const wxNativeEncodingInfo& rInfo
|
|
)
|
|
{
|
|
FATTRS vLogFont;
|
|
HPS hPS;
|
|
|
|
hPS = ::WinGetPS(HWND_DESKTOP);
|
|
|
|
memset(&vLogFont, '\0', sizeof(FATTRS)); // all default values
|
|
vLogFont.usRecordLength = sizeof(FATTRS);
|
|
vLogFont.usCodePage = rInfo.charset;
|
|
vLogFont.lMaxBaselineExt = 0L; // Outline fonts should use 0
|
|
vLogFont.lAveCharWidth = 0L; // Outline fonts should use 0
|
|
vLogFont.fsFontUse = FATTR_FONTUSE_OUTLINE | // only outline fonts allowed
|
|
FATTR_FONTUSE_TRANSFORMABLE; // may be transformed
|
|
|
|
strncpy(vLogFont.szFacename, rInfo.facename.c_str(), sizeof(vLogFont.szFacename));
|
|
|
|
if (!::GpiCreateLogFont( hPS
|
|
,NULL
|
|
,1L
|
|
,&vLogFont
|
|
))
|
|
{
|
|
::WinReleasePS(hPS);
|
|
return FALSE;
|
|
}
|
|
::WinReleasePS(hPS);
|
|
return TRUE;
|
|
} // end of wxTestFontEncoding
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxFont <-> LOGFONT conversion
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void wxFillLogFont(
|
|
LOGFONT* pLogFont // OS2 GPI FATTRS
|
|
, PFACENAMEDESC pFaceName
|
|
, const wxFont* pFont
|
|
)
|
|
{
|
|
wxString sFace;
|
|
USHORT uWeight;
|
|
int nItalic;
|
|
|
|
pLogFont->fsSelection = 0;
|
|
pLogFont->fsSelection = FATTR_SEL_OUTLINE; // we will alway use only outlines
|
|
pFaceName->usWeightClass = 0;
|
|
pFaceName->flOptions = 0;
|
|
switch (pFont->GetFamily())
|
|
{
|
|
case wxSCRIPT:
|
|
sFace = _T("Script");
|
|
break;
|
|
|
|
case wxDECORATIVE:
|
|
case wxROMAN:
|
|
sFace = _T("Times New Roman");
|
|
break;
|
|
|
|
case wxTELETYPE:
|
|
case wxMODERN:
|
|
sFace = _T("Courier New");
|
|
break;
|
|
|
|
case wxSWISS:
|
|
sFace = _T("WarpSans");
|
|
break;
|
|
|
|
case wxDEFAULT:
|
|
default:
|
|
sFace = _T("Helv");
|
|
}
|
|
|
|
switch (pFont->GetWeight())
|
|
{
|
|
default:
|
|
wxFAIL_MSG(_T("unknown font weight"));
|
|
uWeight = FWEIGHT_DONT_CARE;
|
|
break;
|
|
|
|
case wxNORMAL:
|
|
uWeight = FWEIGHT_NORMAL;
|
|
break;
|
|
|
|
case wxLIGHT:
|
|
uWeight = FWEIGHT_LIGHT;
|
|
break;
|
|
|
|
case wxBOLD:
|
|
uWeight = FWEIGHT_BOLD;
|
|
pLogFont->fsSelection |= FATTR_SEL_BOLD;
|
|
break;
|
|
|
|
case wxFONTWEIGHT_MAX:
|
|
uWeight = FWEIGHT_ULTRA_BOLD;
|
|
pLogFont->fsSelection |= FATTR_SEL_BOLD;
|
|
break;
|
|
}
|
|
pFaceName->usWeightClass |= uWeight;
|
|
|
|
switch (pFont->GetStyle())
|
|
{
|
|
case wxITALIC:
|
|
case wxSLANT:
|
|
nItalic = FTYPE_ITALIC;
|
|
pLogFont->fsSelection |= FATTR_SEL_ITALIC;
|
|
break;
|
|
|
|
default:
|
|
wxFAIL_MSG(wxT("unknown font slant"));
|
|
// fall through
|
|
|
|
case wxNORMAL:
|
|
nItalic = 0;
|
|
break;
|
|
}
|
|
pFaceName->flOptions |= nItalic;
|
|
if(pFont->GetUnderlined())
|
|
pLogFont->fsSelection |= FATTR_SEL_UNDERSCORE;
|
|
|
|
//
|
|
// In PM a font's height is expressed in points. A point equals
|
|
// approximately 1/72 of an inch. We'll assume for now that,
|
|
// like Windows, that fonts are 96 dpi.
|
|
//
|
|
DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L};
|
|
HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE);
|
|
LONG lStart = CAPS_FAMILY;
|
|
LONG lCount = CAPS_VERTICAL_RESOLUTION;
|
|
LONG alArray[CAPS_VERTICAL_RESOLUTION];
|
|
LONG lRes;
|
|
int nPpInch;
|
|
|
|
|
|
::DevQueryCaps(hDC, lStart, lCount, alArray);
|
|
lRes = alArray[CAPS_VERTICAL_RESOLUTION-1];
|
|
if (lRes > 0)
|
|
nPpInch = (int)(lRes/39.6); // lres is in pixels per meter
|
|
else
|
|
nPpInch = 96;
|
|
|
|
int nHeight = (pFont->GetPointSize() * nPpInch/72);
|
|
wxString sFacename = pFont->GetFaceName();
|
|
|
|
if (!!sFacename)
|
|
{
|
|
sFace = sFacename;
|
|
}
|
|
//else: ff_face is a reasonable default facename for this font family
|
|
|
|
//
|
|
// Deal with encoding now
|
|
//
|
|
wxNativeEncodingInfo vInfo;
|
|
wxFontEncoding vEncoding = pFont->GetEncoding();
|
|
|
|
if (!wxGetNativeFontEncoding( vEncoding
|
|
,&vInfo
|
|
))
|
|
{
|
|
if ( !wxTheFontMapper->GetAltForEncoding( vEncoding
|
|
,&vInfo
|
|
))
|
|
{
|
|
//
|
|
// Unsupported encoding, replace with the default
|
|
//
|
|
vInfo.charset = 850;
|
|
}
|
|
}
|
|
|
|
if (!vInfo.facename.IsEmpty() )
|
|
{
|
|
//
|
|
// The facename determined by the encoding overrides everything else
|
|
//
|
|
sFace = vInfo.facename;
|
|
}
|
|
|
|
//
|
|
// Transfer all the data to LOGFONT
|
|
//
|
|
pLogFont->usRecordLength = sizeof(FATTRS);
|
|
wxStrcpy(pLogFont->szFacename, sFace.c_str());
|
|
pLogFont->usCodePage = vInfo.charset;
|
|
pLogFont->fsFontUse |= FATTR_FONTUSE_OUTLINE |
|
|
FATTR_FONTUSE_TRANSFORMABLE;
|
|
} // end of wxFillLogFont
|
|
|
|
wxFont wxCreateFontFromLogFont(
|
|
const LOGFONT* pLogFont
|
|
, const PFONTMETRICS pFM
|
|
, PFACENAMEDESC pFaceName
|
|
)
|
|
{
|
|
//
|
|
// Extract family from facename
|
|
//
|
|
int nFontFamily;
|
|
|
|
if (strcmp(pLogFont->szFacename, "Times New Roman") == 0)
|
|
nFontFamily = wxROMAN;
|
|
else if (strcmp(pLogFont->szFacename, "WarpSans") == 0)
|
|
nFontFamily = wxSWISS;
|
|
else if (strcmp(pLogFont->szFacename, "Script") == 0)
|
|
nFontFamily = wxSCRIPT;
|
|
else if (strcmp(pLogFont->szFacename, "Courier New") == 0)
|
|
nFontFamily = wxMODERN;
|
|
else
|
|
nFontFamily = wxSWISS;
|
|
|
|
//
|
|
// Weight and Style
|
|
//
|
|
int nFontWeight = wxNORMAL;
|
|
|
|
switch (pFaceName->usWeightClass)
|
|
{
|
|
case FWEIGHT_LIGHT:
|
|
nFontWeight = wxLIGHT;
|
|
break;
|
|
|
|
default:
|
|
case FWEIGHT_NORMAL:
|
|
nFontWeight = wxNORMAL;
|
|
break;
|
|
|
|
case FWEIGHT_BOLD:
|
|
nFontWeight = wxBOLD;
|
|
break;
|
|
}
|
|
|
|
int nFontStyle;
|
|
|
|
if(pLogFont->fsSelection & FATTR_SEL_ITALIC)
|
|
nFontStyle = wxITALIC;
|
|
else
|
|
nFontStyle = wxNORMAL;
|
|
|
|
bool bFontUnderline = (pLogFont->fsSelection & FATTR_SEL_UNDERSCORE);
|
|
wxString sFontFace = pLogFont->szFacename;
|
|
int nFontPoints = pFM->lEmHeight;
|
|
wxFontEncoding vFontEncoding;
|
|
|
|
switch (pLogFont->usCodePage)
|
|
{
|
|
default:
|
|
wxFAIL_MSG(wxT("unsupported charset"));
|
|
// fall through
|
|
|
|
case 850:
|
|
vFontEncoding = wxFONTENCODING_CP1252;
|
|
break;
|
|
|
|
case 1250:
|
|
vFontEncoding = wxFONTENCODING_CP1250;
|
|
break;
|
|
|
|
case 921:
|
|
vFontEncoding = wxFONTENCODING_CP1257;
|
|
break;
|
|
|
|
case 866:
|
|
vFontEncoding = wxFONTENCODING_CP1251;
|
|
break;
|
|
|
|
case 864:
|
|
vFontEncoding = wxFONTENCODING_CP1256;
|
|
break;
|
|
|
|
case 869:
|
|
vFontEncoding = wxFONTENCODING_CP1253;
|
|
break;
|
|
|
|
case 862:
|
|
vFontEncoding = wxFONTENCODING_CP1255;
|
|
break;
|
|
|
|
case 857:
|
|
vFontEncoding = wxFONTENCODING_CP1254;
|
|
break;
|
|
|
|
case 874:
|
|
vFontEncoding = wxFONTENCODING_CP437;
|
|
break;
|
|
|
|
case 437:
|
|
vFontEncoding = wxFONTENCODING_CP437;
|
|
break;
|
|
}
|
|
|
|
return wxFont( nFontPoints
|
|
,nFontFamily
|
|
,nFontStyle
|
|
,nFontWeight
|
|
,bFontUnderline
|
|
,sFontFace
|
|
,vFontEncoding
|
|
);
|
|
} // end of wxCreateFontFromLogFont
|
|
|
|
int wxGpiStrcmp(
|
|
char* s0
|
|
, char* s1
|
|
)
|
|
{ int l0;
|
|
int l1;
|
|
int l;
|
|
int d;
|
|
int d1;
|
|
int i;
|
|
int rc;
|
|
|
|
rc = 0;
|
|
if(s0 == NULL)
|
|
{
|
|
if(s1 == NULL)
|
|
return 0;
|
|
else
|
|
return 32;
|
|
}
|
|
else if(s1 == NULL)
|
|
return 32;
|
|
|
|
l0 = strlen(s0);
|
|
l1 = strlen(s1);
|
|
l = l0;
|
|
if(l0 != l1)
|
|
{
|
|
rc++;
|
|
if(l1 < l0)
|
|
l = l1;
|
|
}
|
|
for(i=0;i<l;i++)
|
|
{
|
|
d = s0[i]-s1[i];
|
|
if(!d)
|
|
continue;
|
|
d1 = toupper(s0[i]) - toupper(s1[i]);
|
|
if(!d1)
|
|
continue;
|
|
rc += abs(d);
|
|
}
|
|
return rc;
|
|
}
|
|
|