/////////////////////////////////////////////////////////////////////////////// // 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: fontutil.cpp 51287 2008-01-19 14:10:36Z SN $ // Copyright: (c) 1999 Vadim Zeitlin // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// // ============================================================================ // declarations // ============================================================================ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #define DEBUG_PRINTF(NAME) \ { \ static int raz=0; \ printf( #NAME " %i\n",raz); fflush(stdout); \ raz++; \ } #ifndef WX_PRECOMP #include "wx/app.h" #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/encinfo.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 wxFontEncoding wxGetFontEncFromCharSet( int nCharSet ) { wxFontEncoding eFontEncoding; switch (nCharSet) { default: case 1250: eFontEncoding = wxFONTENCODING_CP1250; break; case 1252: eFontEncoding = wxFONTENCODING_CP1252; break; case 921: eFontEncoding = wxFONTENCODING_ISO8859_4; break; case 1251: eFontEncoding = wxFONTENCODING_CP1251; break; case 864: eFontEncoding = wxFONTENCODING_ISO8859_6; break; case 869: eFontEncoding = wxFONTENCODING_ISO8859_7; break; case 862: eFontEncoding = wxFONTENCODING_ISO8859_8; break; case 857: eFontEncoding = wxFONTENCODING_ISO8859_9; break; case 874: eFontEncoding = wxFONTENCODING_ISO8859_11; break; case 437: eFontEncoding = wxFONTENCODING_CP437; break; } return eFontEncoding; } // 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 = (USHORT)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 wxStrncpy((wxChar*)vLogFont.szFacename, rInfo.facename.c_str(), WXSIZEOF(vLogFont.szFacename)); if (!::GpiCreateLogFont( hPS ,NULL ,1L ,&vLogFont )) { ::WinReleasePS(hPS); return FALSE; } ::WinReleasePS(hPS); return true; } // end of wxTestFontEncoding // ---------------------------------------------------------------------------- // wxFont <-> LOGFONT conversion // ---------------------------------------------------------------------------- void wxConvertVectorFontSize( FIXED fxPointSize , PFATTRS pFattrs ) { HPS hPS; HDC hDC; LONG lXFontResolution; LONG lYFontResolution; SIZEF vSizef; hPS = WinGetScreenPS(HWND_DESKTOP); // Screen presentation space // // Query device context for the screen and then query // the resolution of the device for the device context. // hDC = GpiQueryDevice(hPS); DevQueryCaps( hDC, CAPS_HORIZONTAL_FONT_RES, (LONG)1, &lXFontResolution); DevQueryCaps( hDC, CAPS_VERTICAL_FONT_RES, (LONG)1, &lYFontResolution); // // Calculate the size of the character box, based on the // point size selected and the resolution of the device. // The size parameters are of type FIXED, NOT int. // NOTE: 1 point == 1/72 of an inch. // // multiply first to avoid getting vSizef.cx,cy = 0 since fxPointSize // is normally < 72 and FontResolution is typically ca. 100 vSizef.cx = (FIXED)( (fxPointSize * lXFontResolution) / 72 ); vSizef.cy = (FIXED)( (fxPointSize * lYFontResolution) / 72 ); if (pFattrs) { pFattrs->lMaxBaselineExt = MAKELONG( HIUSHORT( vSizef.cy ), 0 ); pFattrs->lAveCharWidth = MAKELONG( HIUSHORT( vSizef.cx ), 0 ); } WinReleasePS(hPS); } // end of wxConvertVectorPointSize void wxFillLogFont( LOGFONT* pFattrs, // OS2 GPI FATTRS PFACENAMEDESC pFaceName, HPS* phPS, bool* pbInternalPS, long* pflId, wxString& sFaceName, wxFont* pFont ) { LONG lNumFonts = 0L; // For system font count ERRORID vError; // For logging API errors LONG lTemp = 0L; bool bInternalPS = false; // if we have to create one PFONTMETRICS pFM = NULL; // // Initial house cleaning to free data buffers and ensure we have a // functional PS to work with // if (!*phPS) { *phPS = ::WinGetPS(HWND_DESKTOP); bInternalPS = true; } // // Determine the number of fonts. // if((lNumFonts = ::GpiQueryFonts( *phPS ,QF_PUBLIC | QF_PRIVATE ,NULL ,&lTemp ,(LONG) sizeof(FONTMETRICS) ,NULL )) < 0L) { ERRORID vError; wxString sError; vError = ::WinGetLastError(wxGetInstance()); sError = wxPMErrorToStr(vError); return; } // // Allocate space for the font metrics. // pFM = new FONTMETRICS[lNumFonts + 1]; // // Retrieve the font metrics. // lTemp = lNumFonts; lTemp = ::GpiQueryFonts( *phPS ,QF_PUBLIC ,NULL ,&lTemp ,(LONG) sizeof(FONTMETRICS) ,pFM ); pFont->SetFM( pFM ,(int)lNumFonts ); // // Initialize FATTR and FACENAMEDESC // pFattrs->usRecordLength = sizeof(FATTRS); pFattrs->fsFontUse = FATTR_FONTUSE_OUTLINE; // only outline fonts allowed pFattrs->fsType = 0; pFattrs->lMaxBaselineExt = pFattrs->lAveCharWidth = 0; pFattrs->idRegistry = 0; pFattrs->lMatch = 0; pFaceName->usSize = sizeof(FACENAMEDESC); pFaceName->usWeightClass = FWEIGHT_DONT_CARE; pFaceName->usWidthClass = FWIDTH_DONT_CARE; pFaceName->usReserved = 0; pFaceName->flOptions = 0; // // This does the actual selection of fonts // wxOS2SelectMatchingFontByName( pFattrs ,pFaceName ,pFM ,(int)lNumFonts ,pFont ); // // We should now have the correct FATTRS set with the selected // font, so now we need to generate an ID // long lNumLids = ::GpiQueryNumberSetIds(*phPS); if(lNumLids ) { long alTypes[255]; STR8 azNames[255]; long alIds[255]; memset(alIds, 0, sizeof(long) * 255); if(!::GpiQuerySetIds( *phPS ,lNumLids ,alTypes ,azNames ,alIds )) { if (bInternalPS) ::WinReleasePS(*phPS); return; } if (*pflId == 0L) *pflId = 1L; for(unsigned long LCNum = 0; LCNum < (unsigned long)lNumLids; LCNum++) if(alIds[LCNum] == *pflId) ++*pflId; if(*pflId > 254) // wow, no id available! { if (bInternalPS) ::WinReleasePS(*phPS); return; } } else *pflId = 1L; // // Release and delete the current font // ::GpiSetCharSet(*phPS, LCID_DEFAULT);/* release the font before deleting */ ::GpiDeleteSetId(*phPS, 1L); /* delete the logical font */ // // Now build a facestring // char zFacename[128]; strcpy(zFacename, pFattrs->szFacename); if(::GpiQueryFaceString( *phPS ,zFacename ,pFaceName ,FACESIZE ,pFattrs->szFacename ) == GPI_ERROR) { vError = ::WinGetLastError(vHabmain); } sFaceName = (wxChar*)zFacename; *pbInternalPS = bInternalPS; // // That's it, we now have everything we need to actually create the font // } // end of wxFillLogFont void wxOS2SelectMatchingFontByName( PFATTRS pFattrs , PFACENAMEDESC pFaceName , PFONTMETRICS pFM , int nNumFonts , const wxFont* pFont ) { int i; int nPointSize; int nIs; int nMinDiff0; int anDiff[16]; int anMinDiff[16]; int nIndex = 0; wxChar zFontFaceName[FACESIZE]; wxString sFaceName; USHORT usWeightClass; int fsSelection = 0; nMinDiff0 = 0xf000; for(i = 0;i < 16; i++) anMinDiff[i] = nMinDiff0; switch (pFont->GetFamily()) { case wxSCRIPT: sFaceName = wxT("Tms Rmn"); break; case wxDECORATIVE: sFaceName = wxT("WarpSans"); break; case wxROMAN: sFaceName = wxT("Tms Rmn"); break; case wxTELETYPE: sFaceName = wxT("Courier") ; break; case wxMODERN: sFaceName = wxT("System VIO") ; break; case wxSWISS: sFaceName = wxT("Helv") ; break; case wxDEFAULT: default: sFaceName = wxT("System VIO") ; } switch (pFont->GetWeight()) { default: wxFAIL_MSG(_T("unknown font weight")); // fall through usWeightClass = FWEIGHT_DONT_CARE; break; case wxNORMAL: usWeightClass = FWEIGHT_NORMAL; break; case wxLIGHT: usWeightClass = FWEIGHT_LIGHT; break; case wxBOLD: usWeightClass = FWEIGHT_BOLD; break; case wxFONTWEIGHT_MAX: usWeightClass = FWEIGHT_ULTRA_BOLD; break; } pFaceName->usWeightClass = usWeightClass; switch (pFont->GetStyle()) { case wxITALIC: case wxSLANT: fsSelection = FM_SEL_ITALIC; pFaceName->flOptions = FTYPE_ITALIC; break; default: wxFAIL_MSG(wxT("unknown font slant")); // fall through case wxNORMAL: fsSelection = 0; break; } wxStrncpy(zFontFaceName, sFaceName.c_str(), WXSIZEOF(zFontFaceName)); nPointSize = pFont->GetPointSize(); // // Matching logic to find the right FM struct // nIndex = 0; for(i = 0, nIs = 0; i < nNumFonts; i++) { int nEmHeight = 0; int nXHeight = 0; anDiff[0] = wxGpiStrcmp((wxChar*)pFM[i].szFacename, zFontFaceName); anDiff[1] = abs(pFM[i].lEmHeight - nPointSize); anDiff[2] = abs(pFM[i].usWeightClass - usWeightClass); anDiff[3] = abs((pFM[i].fsSelection & 0x2f) - fsSelection); if(anDiff[0] == 0) { nEmHeight = (int)pFM[i].lEmHeight; nXHeight =(int)pFM[i].lXHeight; if( (nIs & 0x01) == 0) { nIs = 1; nIndex = i; anMinDiff[1] = anDiff[1]; anMinDiff[2] = anDiff[2]; anMinDiff[3] = anDiff[3]; } else if(anDiff[3] < anMinDiff[3]) { nIndex = i; anMinDiff[3] = anDiff[3]; } else if(anDiff[2] < anMinDiff[2]) { nIndex = i; anMinDiff[2] = anDiff[2]; } else if(anDiff[1] < anMinDiff[1]) { nIndex = i; anMinDiff[1] = anDiff[1]; } anMinDiff[0] = 0; } else if(anDiff[0] < anMinDiff[0]) { nIs = 2; nIndex = i; anMinDiff[3] = anDiff[3]; anMinDiff[2] = anDiff[2]; anMinDiff[1] = anDiff[1]; anMinDiff[0] = anDiff[0]; } else if(anDiff[0] == anMinDiff[0]) { if(anDiff[3] < anMinDiff[3]) { nIndex = i; anMinDiff[3] = anDiff[3]; nIs = 2; } else if(anDiff[2] < anMinDiff[2]) { nIndex = i; anMinDiff[2] = anDiff[2]; nIs = 2; } else if(anDiff[1] < anMinDiff[1]) { nIndex = i; anMinDiff[1] = anDiff[1]; nIs = 2; } } } // // Fill in the FATTRS with the best match from FONTMETRICS // pFattrs->usRecordLength = sizeof(FATTRS); // Sets size of structure pFattrs->lMatch = pFM[nIndex].lMatch; // Force match pFattrs->idRegistry = 0; pFattrs->usCodePage = 0; pFattrs->fsFontUse = 0; pFattrs->fsType = 0; pFattrs->lMaxBaselineExt = 0; pFattrs->lAveCharWidth = 0; wxStrcpy((wxChar*)pFattrs->szFacename, (wxChar*)pFM[nIndex].szFacename); if (pFont->GetWeight() == wxNORMAL) pFattrs->fsSelection = 0; else pFattrs->fsSelection = FATTR_SEL_BOLD; if (pFont->GetStyle() == wxITALIC || pFont->GetStyle() == wxSLANT) pFattrs->fsSelection |= FATTR_SEL_ITALIC; if (pFont->GetUnderlined()) pFattrs->fsSelection |= FATTR_SEL_UNDERSCORE; } // end of wxOS2SelectMatchingFontByName wxFont wxCreateFontFromLogFont( const LOGFONT* pLogFont , const PFONTMETRICS pFM , PFACENAMEDESC pFaceName ) { wxNativeFontInfo vInfo; vInfo.fa = *pLogFont; vInfo.fm = *pFM; vInfo.fn = *pFaceName; return wxFont(vInfo); } // end of wxCreateFontFromLogFont int wxGpiStrcmp( wxChar* s0 , wxChar* 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 = wxStrlen(s0); l1 = wxStrlen(s1); l = l0; if(l0 != l1) { rc++; if(l1 < l0) l = l1; } for(i=0;i