]> git.saurik.com Git - wxWidgets.git/blob - src/os2/fontutil.cpp
Demo cleanup and path issues.
[wxWidgets.git] / src / os2 / fontutil.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/fontutil.cpp
3 // Purpose: font-related helper functions for wxMSW
4 // Author: Modified by David Webster for OS/2
5 // Modified by:
6 // Created: 01.03.00
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11 #define DEBUG_PRINTF(NAME) { static int raz=0; \
12 printf( #NAME " %i\n",raz); fflush(stdout); \
13 raz++; \
14 }
15
16 // ============================================================================
17 // declarations
18 // ============================================================================
19
20 // ----------------------------------------------------------------------------
21 // headers
22 // ----------------------------------------------------------------------------
23
24 #ifdef __GNUG__
25 #pragma implementation "fontutil.h"
26 #endif
27
28 // For compilers that support precompilation, includes "wx.h".
29 #include "wx/wxprec.h"
30
31 #ifndef WX_PRECOMP
32 #include "wx/app.h"
33 #include "wx/string.h"
34 #include "wx/log.h"
35 #include "wx/intl.h"
36 #endif //WX_PRECOMP
37
38 #include "wx/os2/private.h"
39
40 #include "wx/fontutil.h"
41 #include "wx/fontmap.h"
42
43 #include "wx/tokenzr.h"
44
45 // ============================================================================
46 // implementation
47 // ============================================================================
48
49 // ----------------------------------------------------------------------------
50 // wxNativeEncodingInfo
51 // ----------------------------------------------------------------------------
52
53 // convert to/from the string representation: format is
54 // encodingid;facename[;charset]
55
56 bool wxNativeEncodingInfo::FromString(
57 const wxString& rsStr
58 )
59 {
60 wxStringTokenizer vTokenizer(rsStr, _T(";"));
61 wxString sEncid = vTokenizer.GetNextToken();
62 long lEnc;
63
64 if (!sEncid.ToLong(&lEnc))
65 return FALSE;
66 encoding = (wxFontEncoding)lEnc;
67 facename = vTokenizer.GetNextToken();
68 if (!facename)
69 return FALSE;
70
71 wxString sTmp = vTokenizer.GetNextToken();
72
73 if (!sTmp)
74 {
75 charset = 850;
76 }
77 else
78 {
79 if ( wxSscanf(sTmp, _T("%u"), &charset) != 1 )
80 {
81 // should be a number!
82 return FALSE;
83 }
84 }
85 return TRUE;
86 } // end of wxNativeEncodingInfo::FromString
87
88 wxString wxNativeEncodingInfo::ToString() const
89 {
90 wxString sStr;
91
92 sStr << (long)encoding << _T(';') << facename;
93
94 if (charset != 850)
95 {
96 sStr << _T(';') << charset;
97 }
98 return sStr;
99 } // end of wxNativeEncodingInfo::ToString
100
101 // ----------------------------------------------------------------------------
102 // helper functions
103 // ----------------------------------------------------------------------------
104
105 bool wxGetNativeFontEncoding(
106 wxFontEncoding vEncoding
107 , wxNativeEncodingInfo* pInfo
108 )
109 {
110 wxCHECK_MSG(pInfo, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
111 if (vEncoding == wxFONTENCODING_DEFAULT)
112 {
113 vEncoding = wxFont::GetDefaultEncoding();
114 }
115 switch (vEncoding)
116 {
117 case wxFONTENCODING_ISO8859_1:
118 case wxFONTENCODING_ISO8859_15:
119 case wxFONTENCODING_CP1250:
120 pInfo->charset = 1250;
121 break;
122
123 case wxFONTENCODING_ISO8859_2:
124 case wxFONTENCODING_CP1252:
125 pInfo->charset = 1252;
126 break;
127
128 case wxFONTENCODING_ISO8859_4:
129 case wxFONTENCODING_ISO8859_10:
130 pInfo->charset = 921; // what is baltic?
131 break;
132
133 case wxFONTENCODING_ISO8859_5:
134 case wxFONTENCODING_CP1251:
135 pInfo->charset = 1251;
136 break;
137
138 case wxFONTENCODING_ISO8859_6:
139 pInfo->charset = 864;
140 break;
141
142 case wxFONTENCODING_ISO8859_7:
143 pInfo->charset = 869;
144 break;
145
146 case wxFONTENCODING_ISO8859_8:
147 pInfo->charset = 862;
148 break;
149
150 case wxFONTENCODING_ISO8859_9:
151 pInfo->charset = 857;
152 break;
153
154 case wxFONTENCODING_ISO8859_11:
155 pInfo->charset = 874; // what is thai
156 break;
157
158 case wxFONTENCODING_CP437:
159 pInfo->charset = 437;
160 break;
161
162 default:
163 wxFAIL_MSG(wxT("unsupported encoding"));
164 // fall through
165
166 case wxFONTENCODING_SYSTEM:
167 pInfo->charset = 850;
168 break;
169 }
170 return TRUE;
171 } // end of wxGetNativeFontEncoding
172
173 wxFontEncoding wxGetFontEncFromCharSet(
174 int nCharSet
175 )
176 {
177 wxFontEncoding eFontEncoding;
178
179 switch (nCharSet)
180 {
181 default:
182 case 1250:
183 eFontEncoding = wxFONTENCODING_CP1250;
184 break;
185
186 case 1252:
187 eFontEncoding = wxFONTENCODING_CP1252;
188 break;
189
190 case 921:
191 eFontEncoding = wxFONTENCODING_ISO8859_4;
192 break;
193
194 case 1251:
195 eFontEncoding = wxFONTENCODING_CP1251;
196 break;
197
198 case 864:
199 eFontEncoding = wxFONTENCODING_ISO8859_6;
200 break;
201
202 case 869:
203 eFontEncoding = wxFONTENCODING_ISO8859_7;
204 break;
205
206 case 862:
207 eFontEncoding = wxFONTENCODING_ISO8859_8;
208 break;
209
210 case 857:
211 eFontEncoding = wxFONTENCODING_ISO8859_9;
212 break;
213
214 case 874:
215 eFontEncoding = wxFONTENCODING_ISO8859_11;
216 break;
217
218 case 437:
219 eFontEncoding = wxFONTENCODING_CP437;
220 break;
221 }
222 return eFontEncoding;
223 } // end of wxGetNativeFontEncoding
224
225 bool wxTestFontEncoding(
226 const wxNativeEncodingInfo& rInfo
227 )
228 {
229 FATTRS vLogFont;
230 HPS hPS;
231
232 hPS = ::WinGetPS(HWND_DESKTOP);
233
234 memset(&vLogFont, '\0', sizeof(FATTRS)); // all default values
235 vLogFont.usRecordLength = sizeof(FATTRS);
236 vLogFont.usCodePage = rInfo.charset;
237 vLogFont.lMaxBaselineExt = 0L; // Outline fonts should use 0
238 vLogFont.lAveCharWidth = 0L; // Outline fonts should use 0
239 vLogFont.fsFontUse = FATTR_FONTUSE_OUTLINE | // only outline fonts allowed
240 FATTR_FONTUSE_TRANSFORMABLE; // may be transformed
241
242 strncpy(vLogFont.szFacename, rInfo.facename.c_str(), sizeof(vLogFont.szFacename));
243
244 if (!::GpiCreateLogFont( hPS
245 ,NULL
246 ,1L
247 ,&vLogFont
248 ))
249 {
250 ::WinReleasePS(hPS);
251 return FALSE;
252 }
253 ::WinReleasePS(hPS);
254 return TRUE;
255 } // end of wxTestFontEncoding
256
257 // ----------------------------------------------------------------------------
258 // wxFont <-> LOGFONT conversion
259 // ----------------------------------------------------------------------------
260
261 void wxFillLogFont(
262 LOGFONT* pFattrs // OS2 GPI FATTRS
263 , PFACENAMEDESC pFaceName
264 , HPS* phPS
265 , bool* pbInternalPS
266 , long* pflId
267 , wxString& sFaceName
268 , wxFont* pFont
269 )
270 {
271 LONG lNumFonts = 0L; // For system font count
272 ERRORID vError; // For logging API errors
273 LONG lTemp = 0L;
274 bool bInternalPS = FALSE; // if we have to create one
275 PFONTMETRICS pFM = NULL;
276
277 //
278 // Initial house cleaning to free data buffers and ensure we have a
279 // functional PS to work with
280 //
281 if (!*phPS)
282 {
283 *phPS = ::WinGetPS(HWND_DESKTOP);
284 bInternalPS = TRUE;
285 }
286
287 //
288 // Determine the number of fonts.
289 //
290 if((lNumFonts = ::GpiQueryFonts( *phPS
291 ,QF_PUBLIC
292 ,NULL
293 ,&lTemp
294 ,(LONG) sizeof(FONTMETRICS)
295 ,NULL
296 )) < 0L)
297 {
298 ERRORID vError;
299 wxString sError;
300
301 vError = ::WinGetLastError(wxGetInstance());
302 sError = wxPMErrorToStr(vError);
303 return;
304 }
305
306 //
307 // Allocate space for the font metrics.
308 //
309 pFM = new FONTMETRICS[lNumFonts + 1];
310
311 //
312 // Retrieve the font metrics.
313 //
314 lTemp = lNumFonts;
315 lTemp = ::GpiQueryFonts( *phPS
316 ,QF_PUBLIC
317 ,NULL
318 ,&lTemp
319 ,(LONG) sizeof(FONTMETRICS)
320 ,pFM
321 );
322 pFont->SetFM( pFM
323 ,(int)lNumFonts
324 );
325
326 wxString sVals;
327
328 for (int i = 0; i < lNumFonts; i++)
329 {
330 sVals << "Face: " << pFM[i].szFacename
331 << "Family: " << pFM[i].szFamilyname
332 << " PointSize: " << pFM[i].lEmHeight
333 << " Height: " << pFM[i].lXHeight
334 ;
335 sVals = "";
336 }
337
338 //
339 // Initialize FATTR and FACENAMEDESC
340 //
341 pFattrs->usRecordLength = sizeof(FATTRS);
342 pFattrs->fsFontUse = FATTR_FONTUSE_OUTLINE | // only outline fonts allowed
343 FATTR_FONTUSE_TRANSFORMABLE; // may be transformed
344 pFattrs->fsType = 0;
345 pFattrs->lMaxBaselineExt = pFattrs->lAveCharWidth = 0;
346 pFattrs->idRegistry = 0;
347 pFattrs->lMatch = 0;
348
349 pFaceName->usSize = sizeof(FACENAMEDESC);
350 pFaceName->usWidthClass = FWIDTH_NORMAL;
351 pFaceName->usReserved = 0;
352 pFaceName->flOptions = 0;
353
354 //
355 // This does the actual selection of fonts
356 //
357 wxOS2SelectMatchingFontByName( pFattrs
358 ,pFaceName
359 ,pFM
360 ,(int)lNumFonts
361 ,pFont
362 );
363 //
364 // We should now have the correct FATTRS set with the selected
365 // font, so now we need to generate an ID
366 //
367 long lNumLids = ::GpiQueryNumberSetIds(*phPS);
368 long lGpiError;
369
370 if(lNumLids )
371 {
372 long alTypes[255];
373 STR8 azNames[255];
374 long alIds[255];
375
376 if(!::GpiQuerySetIds( *phPS
377 ,lNumLids
378 ,alTypes
379 ,azNames
380 ,alIds
381 ))
382 {
383 if (bInternalPS)
384 ::WinReleasePS(*phPS);
385 return;
386 }
387
388 for(unsigned long LCNum = 0; LCNum < lNumLids; LCNum++)
389 if(alIds[LCNum] == *pflId)
390 ++*pflId;
391 if(*pflId > 254) // wow, no id available!
392 {
393 if (bInternalPS)
394 ::WinReleasePS(*phPS);
395 return;
396 }
397 }
398 else
399 *pflId = 1L;
400 //
401 // Release and delete the current font
402 //
403 ::GpiSetCharSet(*phPS, LCID_DEFAULT);/* release the font before deleting */
404 ::GpiDeleteSetId(*phPS, 1L); /* delete the logical font */
405
406 //
407 // Now build a facestring
408 //
409 char zFacename[128];
410
411 strcpy(zFacename, pFattrs->szFacename);
412
413 if(::GpiQueryFaceString( *phPS
414 ,zFacename
415 ,pFaceName
416 ,FACESIZE
417 ,pFattrs->szFacename
418 ) == GPI_ERROR)
419 {
420 vError = ::WinGetLastError(vHabmain);
421 }
422 sFaceName = zFacename;
423 *pbInternalPS = bInternalPS;
424
425 //
426 // That's it, we now have everything we need to actually create the font
427 //
428 } // end of wxFillLogFont
429
430 void wxOS2SelectMatchingFontByName(
431 PFATTRS pFattrs
432 , PFACENAMEDESC pFaceName
433 , PFONTMETRICS pFM
434 , int nNumFonts
435 , const wxFont* pFont
436 )
437 {
438 int i;
439 int nDiff0;
440 int nPointSize;
441 int nDiff;
442 int nIs;
443 int nIndex;
444 int nMinDiff;
445 int nMinDiff0;
446 int nApirc;
447 int anDiff[16];
448 int anMinDiff[16];
449 STR8 zFn;
450 char zFontFaceName[FACESIZE];
451 wxString sFaceName;
452 USHORT usWeightClass;
453 int fsSelection = 0;
454
455 nMinDiff0 = 0xf000;
456 for(i = 0;i < 16; i++)
457 anMinDiff[i] = nMinDiff0;
458
459 switch (pFont->GetFamily())
460 {
461 case wxSCRIPT:
462 sFaceName = wxT("Script");
463 break;
464
465 case wxDECORATIVE:
466 case wxROMAN:
467 sFaceName = wxT("Times New Roman");
468 break;
469
470 case wxTELETYPE:
471 case wxMODERN:
472 sFaceName = wxT("Courier") ;
473 break;
474
475 case wxSWISS:
476 sFaceName = wxT("WarpSans") ;
477 break;
478
479 case wxDEFAULT:
480 default:
481 sFaceName = wxT("Helv") ;
482 }
483
484 switch (pFont->GetWeight())
485 {
486 default:
487 wxFAIL_MSG(_T("unknown font weight"));
488 // fall through
489 usWeightClass = FWEIGHT_DONT_CARE;
490 break;
491
492 case wxNORMAL:
493 usWeightClass = FWEIGHT_NORMAL;
494 break;
495
496 case wxLIGHT:
497 usWeightClass = FWEIGHT_LIGHT;
498 break;
499
500 case wxBOLD:
501 usWeightClass = FWEIGHT_BOLD;
502 break;
503
504 case wxFONTWEIGHT_MAX:
505 usWeightClass = FWEIGHT_ULTRA_BOLD;
506 break;
507 }
508 pFaceName->usWeightClass = usWeightClass;
509
510 switch (pFont->GetStyle())
511 {
512 case wxITALIC:
513 case wxSLANT:
514 fsSelection = FM_SEL_ITALIC;
515 pFaceName->flOptions = FTYPE_ITALIC;
516 break;
517
518 default:
519 wxFAIL_MSG(wxT("unknown font slant"));
520 // fall through
521
522 case wxNORMAL:
523 fsSelection = 0;
524 break;
525 }
526
527 wxStrncpy(zFontFaceName, sFaceName.c_str(), WXSIZEOF(zFontFaceName));
528 nPointSize = pFont->GetPointSize();
529
530 //
531 // Matching logic to find the right FM struct
532 //
533 nIndex = 0;
534 for(i = 0, nIs = 0; i < nNumFonts; i++)
535 {
536 int nEmHeight = 0;
537 int nXHeight = 0;
538
539 anDiff[0] = wxGpiStrcmp(pFM[i].szFamilyname, zFontFaceName);
540 anDiff[1] = abs(pFM[i].lEmHeight - nPointSize);
541 anDiff[2] = abs(pFM[i].usWeightClass - usWeightClass);
542 anDiff[3] = abs((pFM[i].fsSelection & 0x2f) - fsSelection);
543 if(anDiff[0] == 0)
544 {
545 nEmHeight = (int)pFM[i].lEmHeight;
546 nXHeight =(int)pFM[i].lXHeight;
547 if( (nIs & 0x01) == 0)
548 {
549 nIs = 1;
550 nIndex = i;
551 anMinDiff[1] = anDiff[1];
552 anMinDiff[2] = anDiff[2];
553 anMinDiff[3] = anDiff[3];
554 }
555 else if(anDiff[3] < anMinDiff[3])
556 {
557 nIndex = i;
558 anMinDiff[3] = anDiff[3];
559 }
560 else if(anDiff[2] < anMinDiff[2])
561 {
562 nIndex = i;
563 anMinDiff[2] = anDiff[2];
564 }
565 else if(anDiff[1] < anMinDiff[1])
566 {
567 nIndex = i;
568 anMinDiff[1] = anDiff[1];
569 }
570 anMinDiff[0] = 0;
571 }
572 else if(anDiff[0] < anMinDiff[0])
573 {
574 nIs = 2;
575 nIndex = i;
576 anMinDiff[3] = anDiff[3];
577 anMinDiff[2] = anDiff[2];
578 anMinDiff[1] = anDiff[1];
579 anMinDiff[0] = anDiff[0];
580 }
581 else if(anDiff[0] == anMinDiff[0])
582 {
583 if(anDiff[3] < anMinDiff[3])
584 {
585 nIndex = i;
586 anMinDiff[3] = anDiff[3];
587 nIs = 2;
588 }
589 else if(anDiff[2] < anMinDiff[2])
590 {
591 nIndex = i;
592 anMinDiff[2] = anDiff[2];
593 nIs = 2;
594 }
595 else if(anDiff[1] < anMinDiff[1])
596 {
597 nIndex = i;
598 anMinDiff[1] = anDiff[1];
599 nIs = 2;
600 }
601 }
602 }
603
604 //
605 // Fill in the FATTRS with the best match from FONTMETRICS
606 //
607 pFattrs->usRecordLength = sizeof(FATTRS); // sets size of structure
608 pFattrs->fsSelection = pFM[nIndex].fsSelection; // uses default selection
609 pFattrs->lMatch = pFM[nIndex].lMatch; // force match
610 pFattrs->idRegistry = pFM[nIndex].idRegistry; // uses default registry
611 pFattrs->usCodePage = pFM[nIndex].usCodePage; // code-page
612 if(pFM[nIndex].lMatch)
613 {
614 pFattrs->lMaxBaselineExt = pFM[nIndex].lMaxBaselineExt; // requested font height
615 pFattrs->lAveCharWidth = pFM[nIndex].lAveCharWidth ; // requested font width
616 }
617 else
618 {
619 pFattrs->lMaxBaselineExt = 0;
620 pFattrs->lAveCharWidth = 0;
621 }
622 pFattrs->fsType = 0;// pfm->fsType; /* uses default type */
623 pFattrs->fsFontUse = 0;
624
625 wxStrcpy(pFattrs->szFacename, pFM[nIndex].szFacename);
626 // Debug
627 strcpy(zFontFaceName, pFM[nIndex].szFacename);
628 strcpy(zFontFaceName, pFattrs->szFacename);
629
630 if(usWeightClass >= FWEIGHT_BOLD)
631 pFattrs->fsSelection |= FATTR_SEL_BOLD;
632 if(pFont->GetUnderlined())
633 pFattrs->fsSelection |= FATTR_SEL_UNDERSCORE;
634 if(fsSelection & FM_SEL_ITALIC)
635 pFattrs->fsSelection |= FATTR_SEL_ITALIC;
636 } // end of wxOS2SelectMatchingFontByName
637
638 wxFont wxCreateFontFromLogFont(
639 const LOGFONT* pLogFont
640 , const PFONTMETRICS pFM
641 , PFACENAMEDESC pFaceName
642 )
643 {
644 //
645 // Extract family from facename
646 //
647 int nFontFamily;
648
649 if (strcmp(pLogFont->szFacename, "Times New Roman") == 0)
650 nFontFamily = wxROMAN;
651 else if (strcmp(pLogFont->szFacename, "WarpSans") == 0)
652 nFontFamily = wxSWISS;
653 else if (strcmp(pLogFont->szFacename, "Script") == 0)
654 nFontFamily = wxSCRIPT;
655 else if (strcmp(pLogFont->szFacename, "Courier New") == 0)
656 nFontFamily = wxMODERN;
657 else
658 nFontFamily = wxSWISS;
659
660 //
661 // Weight and Style
662 //
663 int nFontWeight = wxNORMAL;
664
665 switch (pFaceName->usWeightClass)
666 {
667 case FWEIGHT_LIGHT:
668 nFontWeight = wxLIGHT;
669 break;
670
671 default:
672 case FWEIGHT_NORMAL:
673 nFontWeight = wxNORMAL;
674 break;
675
676 case FWEIGHT_BOLD:
677 nFontWeight = wxBOLD;
678 break;
679 }
680
681 int nFontStyle;
682
683 if(pLogFont->fsSelection & FATTR_SEL_ITALIC)
684 nFontStyle = wxITALIC;
685 else
686 nFontStyle = wxNORMAL;
687
688 bool bFontUnderline = (pLogFont->fsSelection & FATTR_SEL_UNDERSCORE);
689 wxString sFontFace = pLogFont->szFacename;
690 int nFontPoints = pFM->lEmHeight;
691 wxFontEncoding vFontEncoding;
692
693 switch (pLogFont->usCodePage)
694 {
695 default:
696 wxFAIL_MSG(wxT("unsupported charset"));
697 // fall through
698
699 case 850:
700 vFontEncoding = wxFONTENCODING_CP1252;
701 break;
702
703 case 1250:
704 vFontEncoding = wxFONTENCODING_CP1250;
705 break;
706
707 case 921:
708 vFontEncoding = wxFONTENCODING_CP1257;
709 break;
710
711 case 866:
712 vFontEncoding = wxFONTENCODING_CP1251;
713 break;
714
715 case 864:
716 vFontEncoding = wxFONTENCODING_CP1256;
717 break;
718
719 case 869:
720 vFontEncoding = wxFONTENCODING_CP1253;
721 break;
722
723 case 862:
724 vFontEncoding = wxFONTENCODING_CP1255;
725 break;
726
727 case 857:
728 vFontEncoding = wxFONTENCODING_CP1254;
729 break;
730
731 case 874:
732 vFontEncoding = wxFONTENCODING_CP437;
733 break;
734
735 case 437:
736 vFontEncoding = wxFONTENCODING_CP437;
737 break;
738 }
739
740 return wxFont( nFontPoints
741 ,nFontFamily
742 ,nFontStyle
743 ,nFontWeight
744 ,bFontUnderline
745 ,sFontFace
746 ,vFontEncoding
747 );
748 } // end of wxCreateFontFromLogFont
749
750 int wxGpiStrcmp(
751 char* s0
752 , char* s1
753 )
754 { int l0;
755 int l1;
756 int l;
757 int d;
758 int d1;
759 int i;
760 int rc;
761
762 rc = 0;
763 if(s0 == NULL)
764 {
765 if(s1 == NULL)
766 return 0;
767 else
768 return 32;
769 }
770 else if(s1 == NULL)
771 return 32;
772
773 l0 = strlen(s0);
774 l1 = strlen(s1);
775 l = l0;
776 if(l0 != l1)
777 {
778 rc++;
779 if(l1 < l0)
780 l = l1;
781 }
782 for(i=0;i<l;i++)
783 {
784 d = s0[i]-s1[i];
785 if(!d)
786 continue;
787 d1 = toupper(s0[i]) - toupper(s1[i]);
788 if(!d1)
789 continue;
790 rc += abs(d);
791 }
792 return rc;
793 }
794