X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3417f6618c41a6b8a7adc29ad5a12ca8c0dad248..bf3ed077c1be511252e4f43961ac6ea51c454e90:/src/os2/fontutil.cpp diff --git a/src/os2/fontutil.cpp b/src/os2/fontutil.cpp index 7fb1ff865c..ad94caff32 100644 --- a/src/os2/fontutil.cpp +++ b/src/os2/fontutil.cpp @@ -6,12 +6,8 @@ // Created: 01.03.00 // RCS-ID: $Id$ // Copyright: (c) 1999 Vadim Zeitlin -// Licence: wxWindows license +// Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -#define DEBUG_PRINTF(NAME) { static int raz=0; \ - printf( #NAME " %i\n",raz); fflush(stdout); \ - raz++; \ - } // ============================================================================ // declarations @@ -21,13 +17,16 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "fontutil.h" -#endif - // 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" @@ -39,6 +38,7 @@ #include "wx/fontutil.h" #include "wx/fontmap.h" +#include "wx/encinfo.h" #include "wx/tokenzr.h" @@ -53,11 +53,9 @@ // convert to/from the string representation: format is // encodingid;facename[;charset] -bool wxNativeEncodingInfo::FromString( - const wxString& rsStr -) +bool wxNativeEncodingInfo::FromString( const wxString& rsStr ) { - wxStringTokenizer vTokenizer(rsStr, _T(";")); + wxStringTokenizer vTokenizer(rsStr, wxT(";")); wxString sEncid = vTokenizer.GetNextToken(); long lEnc; @@ -76,24 +74,24 @@ bool wxNativeEncodingInfo::FromString( } else { - if ( wxSscanf(sTmp, _T("%u"), &charset) != 1 ) + if ( wxSscanf(sTmp, wxT("%u"), &charset) != 1 ) { // should be a number! return FALSE; } } - return TRUE; + return true; } // end of wxNativeEncodingInfo::FromString wxString wxNativeEncodingInfo::ToString() const { wxString sStr; - sStr << (long)encoding << _T(';') << facename; + sStr << (long)encoding << wxT(';') << facename; if (charset != 850) { - sStr << _T(';') << charset; + sStr << wxT(';') << charset; } return sStr; } // end of wxNativeEncodingInfo::ToString @@ -102,12 +100,10 @@ wxString wxNativeEncodingInfo::ToString() const // helper functions // ---------------------------------------------------------------------------- -bool wxGetNativeFontEncoding( - wxFontEncoding vEncoding -, wxNativeEncodingInfo* pInfo -) +bool wxGetNativeFontEncoding( wxFontEncoding vEncoding, + wxNativeEncodingInfo* pInfo ) { - wxCHECK_MSG(pInfo, FALSE, _T("bad pointer in wxGetNativeFontEncoding") ); + wxCHECK_MSG(pInfo, FALSE, wxT("bad pointer in wxGetNativeFontEncoding") ); if (vEncoding == wxFONTENCODING_DEFAULT) { vEncoding = wxFont::GetDefaultEncoding(); @@ -167,27 +163,77 @@ bool wxGetNativeFontEncoding( pInfo->charset = 850; break; } - return TRUE; + return true; } // end of wxGetNativeFontEncoding -bool wxTestFontEncoding( - const wxNativeEncodingInfo& rInfo +wxFontEncoding wxGetFontEncFromCharSet( + int nCharSet ) { - FATTRS vLogFont; - HPS hPS; + 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 = rInfo.charset; + 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 - strncpy(vLogFont.szFacename, rInfo.facename.c_str(), sizeof(vLogFont.szFacename)); + wxStrlcpy((wxChar*)vLogFont.szFacename, rInfo.facename.c_str(), WXSIZEOF(vLogFont.szFacename)); if (!::GpiCreateLogFont( hPS ,NULL @@ -199,85 +245,299 @@ bool wxTestFontEncoding( return FALSE; } ::WinReleasePS(hPS); - return TRUE; + return true; } // end of wxTestFontEncoding // ---------------------------------------------------------------------------- // wxFont <-> LOGFONT conversion // ---------------------------------------------------------------------------- -void wxFillLogFont( - LOGFONT* pLogFont // OS2 GPI FATTRS +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 ) { - wxString sFace; - USHORT uWeight; - int nItalic; + 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; - 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"); + sFaceName = wxT("Tms Rmn"); break; case wxDECORATIVE: + sFaceName = wxT("WarpSans"); + break; + case wxROMAN: - sFace = _T("Times New Roman"); + sFaceName = wxT("Tms Rmn"); break; case wxTELETYPE: + sFaceName = wxT("Courier") ; + break; + case wxMODERN: - sFace = _T("Courier New"); + sFaceName = wxT("System VIO") ; break; case wxSWISS: - sFace = _T("WarpSans"); + sFaceName = wxT("Helv") ; break; case wxDEFAULT: default: - sFace = _T("Helv"); + sFaceName = wxT("System VIO") ; } switch (pFont->GetWeight()) { default: - wxFAIL_MSG(_T("unknown font weight")); - uWeight = FWEIGHT_DONT_CARE; + wxFAIL_MSG(wxT("unknown font weight")); + // fall through + usWeightClass = FWEIGHT_DONT_CARE; break; case wxNORMAL: - uWeight = FWEIGHT_NORMAL; + usWeightClass = FWEIGHT_NORMAL; break; case wxLIGHT: - uWeight = FWEIGHT_LIGHT; + usWeightClass = FWEIGHT_LIGHT; break; case wxBOLD: - uWeight = FWEIGHT_BOLD; - pLogFont->fsSelection |= FATTR_SEL_BOLD; + usWeightClass = FWEIGHT_BOLD; break; - case wxFONTWEIGHT_MAX: - uWeight = FWEIGHT_ULTRA_BOLD; - pLogFont->fsSelection |= FATTR_SEL_BOLD; + case wxFONTWEIGHT_MAX: + usWeightClass = FWEIGHT_ULTRA_BOLD; break; } - pFaceName->usWeightClass |= uWeight; + pFaceName->usWeightClass = usWeightClass; switch (pFont->GetStyle()) { case wxITALIC: case wxSLANT: - nItalic = FTYPE_ITALIC; - pLogFont->fsSelection |= FATTR_SEL_ITALIC; + fsSelection = FM_SEL_ITALIC; + pFaceName->flOptions = FTYPE_ITALIC; break; default: @@ -285,81 +545,110 @@ void wxFillLogFont( // fall through case wxNORMAL: - nItalic = 0; + fsSelection = 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 + wxStrlcpy(zFontFaceName, sFaceName.c_str(), WXSIZEOF(zFontFaceName)); + nPointSize = pFont->GetPointSize(); // - // Deal with encoding now + // Matching logic to find the right FM struct // - wxNativeEncodingInfo vInfo; - wxFontEncoding vEncoding = pFont->GetEncoding(); - - if (!wxGetNativeFontEncoding( vEncoding - ,&vInfo - )) + nIndex = 0; + for(i = 0, nIs = 0; i < nNumFonts; i++) { - if ( !wxTheFontMapper->GetAltForEncoding( vEncoding - ,&vInfo - )) + 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) { - // - // Unsupported encoding, replace with the default - // - vInfo.charset = 850; + 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; + } } - } - - if (!vInfo.facename.IsEmpty() ) - { - // - // The facename determined by the encoding overrides everything else - // - sFace = vInfo.facename; } // - // Transfer all the data to LOGFONT + // Fill in the FATTRS with the best match from FONTMETRICS // - 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 + 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 @@ -367,115 +656,17 @@ wxFont wxCreateFontFromLogFont( , 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; + wxNativeFontInfo vInfo; - // - // 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 - ); + vInfo.fa = *pLogFont; + vInfo.fm = *pFM; + vInfo.fn = *pFaceName; + return wxFont(vInfo); } // end of wxCreateFontFromLogFont int wxGpiStrcmp( - char* s0 -, char* s1 + wxChar* s0 +, wxChar* s1 ) { int l0; int l1; @@ -496,8 +687,8 @@ int wxGpiStrcmp( else if(s1 == NULL) return 32; - l0 = strlen(s0); - l1 = strlen(s1); + l0 = wxStrlen(s0); + l1 = wxStrlen(s1); l = l0; if(l0 != l1) { @@ -510,11 +701,10 @@ int wxGpiStrcmp( d = s0[i]-s1[i]; if(!d) continue; - d1 = toupper(s0[i]) - toupper(s1[i]); + d1 = wxToupper(s0[i]) - wxToupper(s1[i]); if(!d1) continue; rc += abs(d); } return rc; } -