xref: /aoo42x/main/vcl/os2/source/gdi/salgdi3.cxx (revision 9f62ea84)
1*9f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*9f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*9f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*9f62ea84SAndrew Rist  * distributed with this work for additional information
6*9f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*9f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*9f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
9*9f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*9f62ea84SAndrew Rist  *
11*9f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*9f62ea84SAndrew Rist  *
13*9f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*9f62ea84SAndrew Rist  * software distributed under the License is distributed on an
15*9f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
17*9f62ea84SAndrew Rist  * specific language governing permissions and limitations
18*9f62ea84SAndrew Rist  * under the License.
19*9f62ea84SAndrew Rist  *
20*9f62ea84SAndrew Rist  *************************************************************/
21*9f62ea84SAndrew Rist 
22*9f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #define INCL_GRE_STRINGS
25cdf0e10cSrcweir #define INCL_GPI
26cdf0e10cSrcweir #define INCL_DOS
27cdf0e10cSrcweir 
28cdf0e10cSrcweir #include <string.h>
29cdf0e10cSrcweir #include <stdlib.h>
30cdf0e10cSrcweir #include <math.h>
31cdf0e10cSrcweir #include <svpm.h>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #define _SV_SALGDI3_CXX
34cdf0e10cSrcweir #include <tools/svwin.h>
35cdf0e10cSrcweir #include <rtl/tencinfo.h>
36cdf0e10cSrcweir #ifndef _OSL_FILE_HXX
37cdf0e10cSrcweir #include <osl/file.hxx>
38cdf0e10cSrcweir #endif
39cdf0e10cSrcweir #ifndef _OSL_THREAD_HXX
40cdf0e10cSrcweir #include <osl/thread.hxx>
41cdf0e10cSrcweir #endif
42cdf0e10cSrcweir #ifndef _OSL_PROCESS_HXX
43cdf0e10cSrcweir #include <osl/process.h>
44cdf0e10cSrcweir #endif
45cdf0e10cSrcweir #include <vcl/svapp.hxx>
46cdf0e10cSrcweir #include <saldata.hxx>
47cdf0e10cSrcweir #include <salgdi.h>
48cdf0e10cSrcweir #include <vcl/font.hxx>
49cdf0e10cSrcweir #include <vcl/sallayout.hxx>
50cdf0e10cSrcweir #include <tools/poly.hxx>
51cdf0e10cSrcweir #include <tools/debug.hxx>
52cdf0e10cSrcweir #include <rtl/textcvt.h>
53cdf0e10cSrcweir #include <tools/debug.hxx>
54cdf0e10cSrcweir #include <saldata.hxx>
55cdf0e10cSrcweir #include <salgdi.h>
56cdf0e10cSrcweir #ifndef _SV_OUTFONT_HXX
57cdf0e10cSrcweir #include <vcl/outfont.hxx>
58cdf0e10cSrcweir #endif
59cdf0e10cSrcweir #include <sallayout.h>
60cdf0e10cSrcweir #include <tools/poly.hxx>
61cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
62cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygon.hxx>
63cdf0e10cSrcweir #include <basegfx/matrix/b2dhommatrix.hxx>
64cdf0e10cSrcweir 
65cdf0e10cSrcweir #ifndef __H_FT2LIB
66cdf0e10cSrcweir #include <wingdi.h>
67cdf0e10cSrcweir #include <ft2lib.h>
68cdf0e10cSrcweir #endif
69cdf0e10cSrcweir 
70cdf0e10cSrcweir #include "sft.hxx"
71cdf0e10cSrcweir 
72cdf0e10cSrcweir #ifdef GCP_KERN_HACK
73cdf0e10cSrcweir #include <algorithm>
74cdf0e10cSrcweir #endif
75cdf0e10cSrcweir 
76cdf0e10cSrcweir using namespace vcl;
77cdf0e10cSrcweir 
78cdf0e10cSrcweir // -----------
79cdf0e10cSrcweir // - Inlines -
80cdf0e10cSrcweir // -----------
81cdf0e10cSrcweir 
82cdf0e10cSrcweir 
83cdf0e10cSrcweir inline W32FIXED FixedFromDouble( double d )
84cdf0e10cSrcweir {
85cdf0e10cSrcweir     const long l = (long) ( d * 65536. );
86cdf0e10cSrcweir     return *(W32FIXED*) &l;
87cdf0e10cSrcweir }
88cdf0e10cSrcweir 
89cdf0e10cSrcweir // -----------------------------------------------------------------------
90cdf0e10cSrcweir 
91cdf0e10cSrcweir inline int IntTimes256FromFixed(W32FIXED f)
92cdf0e10cSrcweir {
93cdf0e10cSrcweir     int nFixedTimes256 = (f.value << 8) + ((f.fract+0x80) >> 8);
94cdf0e10cSrcweir     return nFixedTimes256;
95cdf0e10cSrcweir }
96cdf0e10cSrcweir 
97cdf0e10cSrcweir // -----------
98cdf0e10cSrcweir // - Defines -
99cdf0e10cSrcweir // -----------
100cdf0e10cSrcweir 
101cdf0e10cSrcweir // this is a special codepage code, used to identify OS/2 symbol font.
102cdf0e10cSrcweir #define SYMBOL_CHARSET					65400
103cdf0e10cSrcweir 
104cdf0e10cSrcweir // =======================================================================
105cdf0e10cSrcweir 
106cdf0e10cSrcweir UniString ImplSalGetUniString( const sal_Char* pStr, xub_StrLen nLen = STRING_LEN)
107cdf0e10cSrcweir {
108cdf0e10cSrcweir 	return UniString( pStr, nLen, gsl_getSystemTextEncoding(),
109cdf0e10cSrcweir 					  RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
110cdf0e10cSrcweir 					  RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
111cdf0e10cSrcweir 					  RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT );
112cdf0e10cSrcweir }
113cdf0e10cSrcweir 
114cdf0e10cSrcweir // =======================================================================
115cdf0e10cSrcweir 
116cdf0e10cSrcweir static USHORT ImplSalToCharSet( CharSet eCharSet )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir 	// !!! Fuer DBCS-Systeme muss dieser Code auskommentiert werden und 0
119cdf0e10cSrcweir 	// !!! zurueckgegeben werden, solange die DBCS-Charsets nicht
120cdf0e10cSrcweir 	// !!! durchgereicht werden
121cdf0e10cSrcweir 
122cdf0e10cSrcweir 	switch ( eCharSet )
123cdf0e10cSrcweir 	{
124cdf0e10cSrcweir 		case RTL_TEXTENCODING_IBM_437:
125cdf0e10cSrcweir 			return 437;
126cdf0e10cSrcweir 
127cdf0e10cSrcweir 		case RTL_TEXTENCODING_IBM_850:
128cdf0e10cSrcweir 			return 850;
129cdf0e10cSrcweir 
130cdf0e10cSrcweir 		case RTL_TEXTENCODING_IBM_860:
131cdf0e10cSrcweir 			return 860;
132cdf0e10cSrcweir 
133cdf0e10cSrcweir 		case RTL_TEXTENCODING_IBM_861:
134cdf0e10cSrcweir 			return 861;
135cdf0e10cSrcweir 
136cdf0e10cSrcweir 		case RTL_TEXTENCODING_IBM_863:
137cdf0e10cSrcweir 			return 863;
138cdf0e10cSrcweir 
139cdf0e10cSrcweir 		case RTL_TEXTENCODING_IBM_865:
140cdf0e10cSrcweir 			return 865;
141cdf0e10cSrcweir 		case RTL_TEXTENCODING_MS_1252:
142cdf0e10cSrcweir 			return 1004;
143cdf0e10cSrcweir 		case RTL_TEXTENCODING_SYMBOL:
144cdf0e10cSrcweir 			return 65400;
145cdf0e10cSrcweir 	}
146cdf0e10cSrcweir 
147cdf0e10cSrcweir 	return 0;
148cdf0e10cSrcweir }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir // -----------------------------------------------------------------------
151cdf0e10cSrcweir 
152cdf0e10cSrcweir static CharSet ImplCharSetToSal( USHORT usCodePage )
153cdf0e10cSrcweir {
154cdf0e10cSrcweir 	switch ( usCodePage )
155cdf0e10cSrcweir 	{
156cdf0e10cSrcweir 		case 437:
157cdf0e10cSrcweir 			return RTL_TEXTENCODING_IBM_437;
158cdf0e10cSrcweir 
159cdf0e10cSrcweir 		case 850:
160cdf0e10cSrcweir 			return RTL_TEXTENCODING_IBM_850;
161cdf0e10cSrcweir 
162cdf0e10cSrcweir 		case 860:
163cdf0e10cSrcweir 			return RTL_TEXTENCODING_IBM_860;
164cdf0e10cSrcweir 
165cdf0e10cSrcweir 		case 861:
166cdf0e10cSrcweir 			return RTL_TEXTENCODING_IBM_861;
167cdf0e10cSrcweir 
168cdf0e10cSrcweir 		case 863:
169cdf0e10cSrcweir 			return RTL_TEXTENCODING_IBM_863;
170cdf0e10cSrcweir 
171cdf0e10cSrcweir 		case 865:
172cdf0e10cSrcweir 			return RTL_TEXTENCODING_IBM_865;
173cdf0e10cSrcweir 		case 1004:
174cdf0e10cSrcweir 			return RTL_TEXTENCODING_MS_1252;
175cdf0e10cSrcweir 		case 65400:
176cdf0e10cSrcweir 			return RTL_TEXTENCODING_SYMBOL;
177cdf0e10cSrcweir 	}
178cdf0e10cSrcweir 
179cdf0e10cSrcweir 	return RTL_TEXTENCODING_DONTKNOW;
180cdf0e10cSrcweir }
181cdf0e10cSrcweir 
182cdf0e10cSrcweir // -----------------------------------------------------------------------
183cdf0e10cSrcweir 
184cdf0e10cSrcweir static FontFamily ImplFamilyToSal( BYTE bFamilyType )
185cdf0e10cSrcweir {
186cdf0e10cSrcweir     switch ( bFamilyType )
187cdf0e10cSrcweir     {
188cdf0e10cSrcweir         case 4:
189cdf0e10cSrcweir             return FAMILY_DECORATIVE;
190cdf0e10cSrcweir         case 3:
191cdf0e10cSrcweir             return FAMILY_SCRIPT;
192cdf0e10cSrcweir     }
193cdf0e10cSrcweir 
194cdf0e10cSrcweir     return FAMILY_DONTKNOW;
195cdf0e10cSrcweir }
196cdf0e10cSrcweir 
197cdf0e10cSrcweir // -----------------------------------------------------------------------
198cdf0e10cSrcweir 
199cdf0e10cSrcweir static FontWeight ImplWeightToSal( USHORT nWeight )
200cdf0e10cSrcweir {
201cdf0e10cSrcweir 	// Falls sich jemand an die alte Doku gehalten hat
202cdf0e10cSrcweir 	if ( nWeight > 999 )
203cdf0e10cSrcweir 		nWeight /= 1000;
204cdf0e10cSrcweir 
205cdf0e10cSrcweir 	switch ( nWeight )
206cdf0e10cSrcweir 	{
207cdf0e10cSrcweir 		case 1:
208cdf0e10cSrcweir 			return WEIGHT_THIN;
209cdf0e10cSrcweir 
210cdf0e10cSrcweir 		case 2:
211cdf0e10cSrcweir 			return WEIGHT_ULTRALIGHT;
212cdf0e10cSrcweir 
213cdf0e10cSrcweir 		case 3:
214cdf0e10cSrcweir 			return WEIGHT_LIGHT;
215cdf0e10cSrcweir 
216cdf0e10cSrcweir 		case 4:
217cdf0e10cSrcweir 			return WEIGHT_SEMILIGHT;
218cdf0e10cSrcweir 
219cdf0e10cSrcweir 		case 5:
220cdf0e10cSrcweir 			return WEIGHT_NORMAL;
221cdf0e10cSrcweir 
222cdf0e10cSrcweir 		case 6:
223cdf0e10cSrcweir 			return WEIGHT_SEMIBOLD;
224cdf0e10cSrcweir 
225cdf0e10cSrcweir 		case 7:
226cdf0e10cSrcweir 			return WEIGHT_BOLD;
227cdf0e10cSrcweir 
228cdf0e10cSrcweir 		case 8:
229cdf0e10cSrcweir 			return WEIGHT_ULTRABOLD;
230cdf0e10cSrcweir 
231cdf0e10cSrcweir 		case 9:
232cdf0e10cSrcweir 			return WEIGHT_BLACK;
233cdf0e10cSrcweir 	}
234cdf0e10cSrcweir 
235cdf0e10cSrcweir 	return WEIGHT_DONTKNOW;
236cdf0e10cSrcweir }
237cdf0e10cSrcweir 
238cdf0e10cSrcweir // -----------------------------------------------------------------------
239cdf0e10cSrcweir 
240cdf0e10cSrcweir static UniString ImpStyleNameToSal( const char* pFamilyName,
241cdf0e10cSrcweir 								   const char* pFaceName,
242cdf0e10cSrcweir 								   USHORT nLen )
243cdf0e10cSrcweir {
244cdf0e10cSrcweir 	if ( !nLen )
245cdf0e10cSrcweir 		nLen = strlen(pFamilyName);
246cdf0e10cSrcweir 
247cdf0e10cSrcweir 	// strip FamilyName from FaceName
248cdf0e10cSrcweir 	if ( strncmp( pFamilyName, pFaceName, nLen ) == 0 )
249cdf0e10cSrcweir 	{
250cdf0e10cSrcweir 		USHORT nFaceLen = (USHORT)strlen( pFaceName+nLen );
251cdf0e10cSrcweir 		// Ist Facename laenger, schneiden wir den FamilyName ab
252cdf0e10cSrcweir 		if ( nFaceLen > 1 )
253cdf0e10cSrcweir 			return UniString( pFaceName+(nLen+1), gsl_getSystemTextEncoding());
254cdf0e10cSrcweir 		else
255cdf0e10cSrcweir 			return UniString();
256cdf0e10cSrcweir 	}
257cdf0e10cSrcweir 	else
258cdf0e10cSrcweir 		return UniString( pFaceName, gsl_getSystemTextEncoding());
259cdf0e10cSrcweir }
260cdf0e10cSrcweir 
261cdf0e10cSrcweir // -----------------------------------------------------------------------
262cdf0e10cSrcweir 
263cdf0e10cSrcweir inline FontPitch ImplLogPitchToSal( BYTE fsType )
264cdf0e10cSrcweir {
265cdf0e10cSrcweir     if ( fsType & FM_TYPE_FIXED )
266cdf0e10cSrcweir         return PITCH_FIXED;
267cdf0e10cSrcweir     else
268cdf0e10cSrcweir         return PITCH_VARIABLE;
269cdf0e10cSrcweir }
270cdf0e10cSrcweir 
271cdf0e10cSrcweir // -----------------------------------------------------------------------
272cdf0e10cSrcweir 
273cdf0e10cSrcweir inline BYTE ImplPitchToWin( FontPitch ePitch )
274cdf0e10cSrcweir {
275cdf0e10cSrcweir     if ( ePitch == PITCH_FIXED )
276cdf0e10cSrcweir         return FM_TYPE_FIXED;
277cdf0e10cSrcweir     //else if ( ePitch == PITCH_VARIABLE )
278cdf0e10cSrcweir 
279cdf0e10cSrcweir 	return 0;
280cdf0e10cSrcweir }
281cdf0e10cSrcweir 
282cdf0e10cSrcweir // -----------------------------------------------------------------------
283cdf0e10cSrcweir 
284cdf0e10cSrcweir static ImplDevFontAttributes Os2Font2DevFontAttributes( const PFONTMETRICS pFontMetric)
285cdf0e10cSrcweir {
286cdf0e10cSrcweir     ImplDevFontAttributes aDFA;
287cdf0e10cSrcweir 
288cdf0e10cSrcweir     // get font face attributes
289cdf0e10cSrcweir     aDFA.meFamily       = ImplFamilyToSal( pFontMetric->panose.bFamilyType);
290cdf0e10cSrcweir     aDFA.meWidthType    = WIDTH_DONTKNOW;
291cdf0e10cSrcweir     aDFA.meWeight       = ImplWeightToSal( pFontMetric->usWeightClass);
292cdf0e10cSrcweir     aDFA.meItalic       = (pFontMetric->fsSelection & FM_SEL_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE;
293cdf0e10cSrcweir     aDFA.mePitch        = ImplLogPitchToSal( pFontMetric->fsType );
294cdf0e10cSrcweir     aDFA.mbSymbolFlag   = (pFontMetric->usCodePage == SYMBOL_CHARSET);
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 	// get the font face name
297cdf0e10cSrcweir 	// the maName field stores the font name without the style, so under OS/2
298cdf0e10cSrcweir 	// we must use the family name
299cdf0e10cSrcweir 	aDFA.maName = UniString( pFontMetric->szFamilyname, gsl_getSystemTextEncoding());
300cdf0e10cSrcweir 
301cdf0e10cSrcweir 	aDFA.maStyleName = ImpStyleNameToSal( pFontMetric->szFamilyname,
302cdf0e10cSrcweir  										  pFontMetric->szFacename,
303cdf0e10cSrcweir  										  strlen( pFontMetric->szFamilyname) );
304cdf0e10cSrcweir 
305cdf0e10cSrcweir     // get device specific font attributes
306cdf0e10cSrcweir     aDFA.mbOrientation  = (pFontMetric->fsDefn & FM_DEFN_OUTLINE) != 0;
307cdf0e10cSrcweir     aDFA.mbDevice       = (pFontMetric->fsDefn & FM_DEFN_GENERIC) ? FALSE : TRUE;
308cdf0e10cSrcweir 
309cdf0e10cSrcweir     aDFA.mbEmbeddable   = false;
310cdf0e10cSrcweir     aDFA.mbSubsettable  = false;
311cdf0e10cSrcweir     DWORD fontType = Ft2QueryFontType( 0, pFontMetric->szFamilyname);
312cdf0e10cSrcweir     if( fontType == FT2_FONTTYPE_TRUETYPE && !aDFA.mbDevice)
313cdf0e10cSrcweir 		aDFA.mbSubsettable = true;
314cdf0e10cSrcweir     // for now we can only embed Type1 fonts
315cdf0e10cSrcweir     if( fontType == FT2_FONTTYPE_TYPE1 )
316cdf0e10cSrcweir         aDFA.mbEmbeddable = true;
317cdf0e10cSrcweir 
318cdf0e10cSrcweir     // heuristics for font quality
319cdf0e10cSrcweir     // -   standard-type1 > opentypeTT > truetype > non-standard-type1 > raster
320cdf0e10cSrcweir     // -   subsetting > embedding > none
321cdf0e10cSrcweir     aDFA.mnQuality = 0;
322cdf0e10cSrcweir     if( fontType == FT2_FONTTYPE_TRUETYPE )
323cdf0e10cSrcweir         aDFA.mnQuality += 50;
324cdf0e10cSrcweir     if( aDFA.mbSubsettable )
325cdf0e10cSrcweir         aDFA.mnQuality += 200;
326cdf0e10cSrcweir     else if( aDFA.mbEmbeddable )
327cdf0e10cSrcweir         aDFA.mnQuality += 100;
328cdf0e10cSrcweir 
329cdf0e10cSrcweir     // #i38665# prefer Type1 versions of the standard postscript fonts
330cdf0e10cSrcweir     if( aDFA.mbEmbeddable )
331cdf0e10cSrcweir     {
332cdf0e10cSrcweir         if( aDFA.maName.EqualsAscii( "AvantGarde" )
333cdf0e10cSrcweir         ||  aDFA.maName.EqualsAscii( "Bookman" )
334cdf0e10cSrcweir         ||  aDFA.maName.EqualsAscii( "Courier" )
335cdf0e10cSrcweir         ||  aDFA.maName.EqualsAscii( "Helvetica" )
336cdf0e10cSrcweir         ||  aDFA.maName.EqualsAscii( "NewCenturySchlbk" )
337cdf0e10cSrcweir         ||  aDFA.maName.EqualsAscii( "Palatino" )
338cdf0e10cSrcweir         ||  aDFA.maName.EqualsAscii( "Symbol" )
339cdf0e10cSrcweir         ||  aDFA.maName.EqualsAscii( "Times" )
340cdf0e10cSrcweir         ||  aDFA.maName.EqualsAscii( "ZapfChancery" )
341cdf0e10cSrcweir         ||  aDFA.maName.EqualsAscii( "ZapfDingbats" ) )
342cdf0e10cSrcweir             aDFA.mnQuality += 500;
343cdf0e10cSrcweir     }
344cdf0e10cSrcweir 
345cdf0e10cSrcweir     aDFA.meEmbeddedBitmap = EMBEDDEDBITMAP_DONTKNOW;
346cdf0e10cSrcweir     aDFA.meAntiAlias = ANTIALIAS_DONTKNOW;
347cdf0e10cSrcweir 
348cdf0e10cSrcweir     // TODO: add alias names
349cdf0e10cSrcweir 
350cdf0e10cSrcweir     return aDFA;
351cdf0e10cSrcweir }
352cdf0e10cSrcweir 
353cdf0e10cSrcweir // =======================================================================
354cdf0e10cSrcweir 
355cdf0e10cSrcweir // -----------------------------------------------------------------------
356cdf0e10cSrcweir 
357cdf0e10cSrcweir // =======================================================================
358cdf0e10cSrcweir 
359cdf0e10cSrcweir ImplOs2FontData::ImplOs2FontData( PFONTMETRICS _pFontMetric,
360cdf0e10cSrcweir     int nHeight, BYTE nPitchAndFamily )
361cdf0e10cSrcweir :	ImplFontData( Os2Font2DevFontAttributes(_pFontMetric), 0 ),
362cdf0e10cSrcweir     pFontMetric( _pFontMetric ),
363cdf0e10cSrcweir 	meOs2CharSet( _pFontMetric->usCodePage),
364cdf0e10cSrcweir     mnPitchAndFamily( nPitchAndFamily ),
365cdf0e10cSrcweir     mpFontCharSets( NULL ),
366cdf0e10cSrcweir     mpUnicodeMap( NULL ),
367cdf0e10cSrcweir     mbDisableGlyphApi( false ),
368cdf0e10cSrcweir     mbHasKoreanRange( false ),
369cdf0e10cSrcweir     mbHasCJKSupport( false ),
370cdf0e10cSrcweir     mbAliasSymbolsLow( false ),
371cdf0e10cSrcweir     mbAliasSymbolsHigh( false ),
372cdf0e10cSrcweir     mnId( 0 )
373cdf0e10cSrcweir {
374cdf0e10cSrcweir     SetBitmapSize( 0, nHeight );
375cdf0e10cSrcweir }
376cdf0e10cSrcweir 
377cdf0e10cSrcweir // -----------------------------------------------------------------------
378cdf0e10cSrcweir 
379cdf0e10cSrcweir ImplOs2FontData::~ImplOs2FontData()
380cdf0e10cSrcweir {
381cdf0e10cSrcweir     delete[] mpFontCharSets;
382cdf0e10cSrcweir 
383cdf0e10cSrcweir     if( mpUnicodeMap )
384cdf0e10cSrcweir         mpUnicodeMap->DeReference();
385cdf0e10cSrcweir }
386cdf0e10cSrcweir 
387cdf0e10cSrcweir // -----------------------------------------------------------------------
388cdf0e10cSrcweir 
389cdf0e10cSrcweir sal_IntPtr ImplOs2FontData::GetFontId() const
390cdf0e10cSrcweir {
391cdf0e10cSrcweir     return mnId;
392cdf0e10cSrcweir }
393cdf0e10cSrcweir 
394cdf0e10cSrcweir // -----------------------------------------------------------------------
395cdf0e10cSrcweir 
396cdf0e10cSrcweir void ImplOs2FontData::UpdateFromHPS( HPS hPS ) const
397cdf0e10cSrcweir {
398cdf0e10cSrcweir     // short circuit if already initialized
399cdf0e10cSrcweir     if( mpUnicodeMap != NULL )
400cdf0e10cSrcweir         return;
401cdf0e10cSrcweir 
402cdf0e10cSrcweir     ReadCmapTable( hPS );
403cdf0e10cSrcweir     ReadOs2Table( hPS );
404cdf0e10cSrcweir 
405cdf0e10cSrcweir     // even if the font works some fonts have problems with the glyph API
406cdf0e10cSrcweir     // => the heuristic below tries to figure out which fonts have the problem
407cdf0e10cSrcweir 	DWORD	fontType = Ft2QueryFontType( 0, pFontMetric->szFacename);
408cdf0e10cSrcweir     if( fontType != FT2_FONTTYPE_TRUETYPE
409cdf0e10cSrcweir 		&& (pFontMetric->fsDefn & FM_DEFN_GENERIC) == 0)
410cdf0e10cSrcweir 		mbDisableGlyphApi = true;
411cdf0e10cSrcweir }
412cdf0e10cSrcweir 
413cdf0e10cSrcweir // -----------------------------------------------------------------------
414cdf0e10cSrcweir 
415cdf0e10cSrcweir #ifdef GNG_VERT_HACK
416cdf0e10cSrcweir bool ImplOs2FontData::HasGSUBstitutions( HPS hPS ) const
417cdf0e10cSrcweir {
418cdf0e10cSrcweir     if( !mbGsubRead )
419cdf0e10cSrcweir         ReadGsubTable( hPS );
420cdf0e10cSrcweir     return !maGsubTable.empty();
421cdf0e10cSrcweir }
422cdf0e10cSrcweir 
423cdf0e10cSrcweir // -----------------------------------------------------------------------
424cdf0e10cSrcweir 
425cdf0e10cSrcweir bool ImplOs2FontData::IsGSUBstituted( sal_Ucs cChar ) const
426cdf0e10cSrcweir {
427cdf0e10cSrcweir     return( maGsubTable.find( cChar ) != maGsubTable.end() );
428cdf0e10cSrcweir }
429cdf0e10cSrcweir #endif // GNG_VERT_HACK
430cdf0e10cSrcweir 
431cdf0e10cSrcweir // -----------------------------------------------------------------------
432cdf0e10cSrcweir 
433cdf0e10cSrcweir const ImplFontCharMap* ImplOs2FontData::GetImplFontCharMap() const
434cdf0e10cSrcweir {
435cdf0e10cSrcweir     return mpUnicodeMap;
436cdf0e10cSrcweir }
437cdf0e10cSrcweir 
438cdf0e10cSrcweir // -----------------------------------------------------------------------
439cdf0e10cSrcweir 
440cdf0e10cSrcweir static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
441cdf0e10cSrcweir static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8)+p[1]);}
442cdf0e10cSrcweir static signed GetSShort( const unsigned char* p ){ return((short)((p[0]<<8)+p[1]));}
443cdf0e10cSrcweir static inline DWORD CalcTag( const char p[4]) { return (p[0]+(p[1]<<8)+(p[2]<<16)+(p[3]<<24)); }
444cdf0e10cSrcweir 
445cdf0e10cSrcweir void ImplOs2FontData::ReadOs2Table( HPS hPS ) const
446cdf0e10cSrcweir {
447cdf0e10cSrcweir     const DWORD Os2Tag = CalcTag( "OS/2" );
448cdf0e10cSrcweir     DWORD nLength = Ft2GetFontData( hPS, Os2Tag, 0, NULL, 0 );
449cdf0e10cSrcweir     if( (nLength == FT2_ERROR) || !nLength )
450cdf0e10cSrcweir         return;
451cdf0e10cSrcweir     std::vector<unsigned char> aOS2map( nLength );
452cdf0e10cSrcweir     unsigned char* pOS2map = &aOS2map[0];
453cdf0e10cSrcweir     DWORD nRC = Ft2GetFontData( hPS, Os2Tag, 0, pOS2map, nLength );
454cdf0e10cSrcweir     sal_uInt32 nVersion = GetUShort( pOS2map );
455cdf0e10cSrcweir     if ( nVersion >= 0x0001 && nLength >= 58 )
456cdf0e10cSrcweir     {
457cdf0e10cSrcweir         // We need at least version 0x0001 (TrueType rev 1.66)
458cdf0e10cSrcweir         // to have access to the needed struct members.
459cdf0e10cSrcweir         sal_uInt32 ulUnicodeRange1 = GetUInt( pOS2map + 42 );
460cdf0e10cSrcweir         sal_uInt32 ulUnicodeRange2 = GetUInt( pOS2map + 46 );
461cdf0e10cSrcweir         sal_uInt32 ulUnicodeRange3 = GetUInt( pOS2map + 50 );
462cdf0e10cSrcweir         sal_uInt32 ulUnicodeRange4 = GetUInt( pOS2map + 54 );
463cdf0e10cSrcweir 
464cdf0e10cSrcweir         // Check for CJK capabilities of the current font
465cdf0e10cSrcweir         mbHasCJKSupport = (ulUnicodeRange2 & 0x2fff0000)
466cdf0e10cSrcweir                         | (ulUnicodeRange3 & 0x00000001);
467cdf0e10cSrcweir         mbHasKoreanRange= (ulUnicodeRange1 & 0x10000000)
468cdf0e10cSrcweir                         | (ulUnicodeRange2 & 0x01100000);
469cdf0e10cSrcweir     }
470cdf0e10cSrcweir }
471cdf0e10cSrcweir 
472cdf0e10cSrcweir 
473cdf0e10cSrcweir // -----------------------------------------------------------------------
474cdf0e10cSrcweir 
475cdf0e10cSrcweir #ifdef GNG_VERT_HACK
476cdf0e10cSrcweir void ImplOs2FontData::ReadGsubTable( HPS hPS ) const
477cdf0e10cSrcweir {
478cdf0e10cSrcweir     mbGsubRead = true;
479cdf0e10cSrcweir 
480cdf0e10cSrcweir     // check the existence of a GSUB table
481cdf0e10cSrcweir     const DWORD GsubTag = CalcTag( "GSUB" );
482cdf0e10cSrcweir     DWORD nRC = Ft2GetFontData( hPS, GsubTag, 0, NULL, 0 );
483cdf0e10cSrcweir     if( (nRC == FT2_ERROR) || !nRC )
484cdf0e10cSrcweir         return;
485cdf0e10cSrcweir 
486cdf0e10cSrcweir     // TODO: directly read the GSUB table instead of going through sft
487cdf0e10cSrcweir 
488cdf0e10cSrcweir     // get raw font file data
489cdf0e10cSrcweir     DWORD nFontSize = Ft2GetFontData( hPS, 0, 0, NULL, 0 );
490cdf0e10cSrcweir     if( nFontSize == FT2_ERROR )
491cdf0e10cSrcweir         return;
492cdf0e10cSrcweir     std::vector<char> aRawFont( nFontSize+1 );
493cdf0e10cSrcweir     aRawFont[ nFontSize ] = 0;
494cdf0e10cSrcweir     DWORD nFontSize2 = Ft2GetFontData( hPS, 0, 0, (void*)&aRawFont[0], nFontSize );
495cdf0e10cSrcweir     if( nFontSize != nFontSize2 )
496cdf0e10cSrcweir         return;
497cdf0e10cSrcweir 
498cdf0e10cSrcweir     // open font file
499cdf0e10cSrcweir     sal_uInt32 nFaceNum = 0;
500cdf0e10cSrcweir     if( !aRawFont[0] )  // TTC candidate
501cdf0e10cSrcweir         nFaceNum = ~0U;  // indicate "TTC font extracts only"
502cdf0e10cSrcweir 
503cdf0e10cSrcweir     TrueTypeFont* pTTFont = NULL;
504cdf0e10cSrcweir     ::OpenTTFontBuffer( &aRawFont[0], nFontSize, nFaceNum, &pTTFont );
505cdf0e10cSrcweir     if( !pTTFont )
506cdf0e10cSrcweir         return;
507cdf0e10cSrcweir 
508cdf0e10cSrcweir     // add vertically substituted characters to list
509cdf0e10cSrcweir     static const sal_Unicode aGSUBCandidates[] = {
510cdf0e10cSrcweir         0x0020, 0x0080, // ASCII
511cdf0e10cSrcweir         0x2000, 0x2600, // misc
512cdf0e10cSrcweir         0x3000, 0x3100, // CJK punctutation
513cdf0e10cSrcweir         0x3300, 0x3400, // squared words
514cdf0e10cSrcweir         0xFF00, 0xFFF0, // halfwidth|fullwidth forms
515cdf0e10cSrcweir     0 };
516cdf0e10cSrcweir 
517cdf0e10cSrcweir     for( const sal_Unicode* pPair = aGSUBCandidates; *pPair; pPair += 2 )
518cdf0e10cSrcweir         for( sal_Unicode cChar = pPair[0]; cChar < pPair[1]; ++cChar )
519cdf0e10cSrcweir             if( ::MapChar( pTTFont, cChar, 0 ) != ::MapChar( pTTFont, cChar, 1 ) )
520cdf0e10cSrcweir                 maGsubTable.insert( cChar ); // insert GSUBbed unicodes
521cdf0e10cSrcweir 
522cdf0e10cSrcweir     CloseTTFont( pTTFont );
523cdf0e10cSrcweir 
524cdf0e10cSrcweir #if 0
525cdf0e10cSrcweir     TrueTypeFont* pTTFont = NULL;
526cdf0e10cSrcweir     ::OpenTTFont( &aRawFont[0], nFontSize, nFaceNum, &pTTFont );
527cdf0e10cSrcweir     if( !pTTFont )
528cdf0e10cSrcweir         return;
529cdf0e10cSrcweir 
530cdf0e10cSrcweir     // add vertically substituted characters to list
531cdf0e10cSrcweir     static const sal_Unicode aGSUBCandidates[] = {
532cdf0e10cSrcweir         0x0020, 0x0080, // ASCII
533cdf0e10cSrcweir         0x2000, 0x2600, // misc
534cdf0e10cSrcweir         0x3000, 0x3100, // CJK punctutation
535cdf0e10cSrcweir         0x3300, 0x3400, // squared words
536cdf0e10cSrcweir         0xFF00, 0xFFF0, // halfwidth|fullwidth forms
537cdf0e10cSrcweir     0 };
538cdf0e10cSrcweir 
539cdf0e10cSrcweir     for( const sal_Unicode* pPair = aGSUBCandidates; *pPair; pPair += 2 )
540cdf0e10cSrcweir         for( sal_Unicode cChar = pPair[0]; cChar < pPair[1]; ++cChar )
541cdf0e10cSrcweir             if( ::MapChar( pTTFont, cChar, 0 ) != ::MapChar( pTTFont, cChar, 1 ) )
542cdf0e10cSrcweir                 maGsubTable.insert( cChar ); // insert GSUBbed unicodes
543cdf0e10cSrcweir 
544cdf0e10cSrcweir     CloseTTFont( pTTFont );
545cdf0e10cSrcweir #endif
546cdf0e10cSrcweir }
547cdf0e10cSrcweir #endif // GNG_VERT_HACK
548cdf0e10cSrcweir 
549cdf0e10cSrcweir // -----------------------------------------------------------------------
550cdf0e10cSrcweir 
551cdf0e10cSrcweir void ImplOs2FontData::ReadCmapTable( HPS hPS ) const
552cdf0e10cSrcweir {
553cdf0e10cSrcweir     CmapResult aResult;
554cdf0e10cSrcweir     aResult.mnPairCount = 0;
555cdf0e10cSrcweir     aResult.mbSymbolic  = (meOs2CharSet == SYMBOL_CHARSET);
556cdf0e10cSrcweir     aResult.mbRecoded   = true;
557cdf0e10cSrcweir 
558cdf0e10cSrcweir     // get the CMAP table from the font which is selected into the DC
559cdf0e10cSrcweir     const DWORD CmapTag = CalcTag( "cmap" );
560cdf0e10cSrcweir     DWORD nRC = Ft2GetFontData( hPS, CmapTag, 0, NULL, 0 );
561cdf0e10cSrcweir     // read the CMAP table if available
562cdf0e10cSrcweir     if( nRC != FT2_ERROR )
563cdf0e10cSrcweir     {
564cdf0e10cSrcweir         const int nLength = nRC;
565cdf0e10cSrcweir         std::vector<unsigned char> aCmap( nLength );
566cdf0e10cSrcweir         unsigned char* pCmap = &aCmap[0];
567cdf0e10cSrcweir         nRC = Ft2GetFontData( hPS, CmapTag, 0, pCmap, nLength );
568cdf0e10cSrcweir         // parse the CMAP table
569cdf0e10cSrcweir         if( nRC == nLength )
570cdf0e10cSrcweir             ParseCMAP( pCmap, nLength, aResult );
571cdf0e10cSrcweir     } else {
572cdf0e10cSrcweir 		// we need to define at least a simple charmap, otherwise this font
573cdf0e10cSrcweir 		// will be mapped to default charmap, and OOo doesn't accept the
574cdf0e10cSrcweir 		// system font to match the default charmap
575cdf0e10cSrcweir 		aResult.mnPairCount = 1;
576cdf0e10cSrcweir 		// ImplFontCharMap destructor will free this memory
577cdf0e10cSrcweir 		aResult.mpPairCodes = new sal_uInt32[ 2 * aResult.mnPairCount ];
578cdf0e10cSrcweir 		aResult.mpPairCodes[0] = 0x0020;
579cdf0e10cSrcweir 		aResult.mpPairCodes[1] = 0x00FF;
580cdf0e10cSrcweir 		aResult.mpStartGlyphs = NULL;
581cdf0e10cSrcweir 	}
582cdf0e10cSrcweir 
583cdf0e10cSrcweir     mbDisableGlyphApi |= aResult.mbRecoded;
584cdf0e10cSrcweir 
585cdf0e10cSrcweir     if( aResult.mnPairCount > 0 )
586cdf0e10cSrcweir         mpUnicodeMap = new ImplFontCharMap( aResult.mnPairCount,
587cdf0e10cSrcweir             aResult.mpPairCodes, aResult.mpStartGlyphs );
588cdf0e10cSrcweir     else
589cdf0e10cSrcweir         mpUnicodeMap = ImplFontCharMap::GetDefaultMap();
590cdf0e10cSrcweir 	mpUnicodeMap->AddReference();
591cdf0e10cSrcweir }
592cdf0e10cSrcweir 
593cdf0e10cSrcweir // =======================================================================
594cdf0e10cSrcweir 
595cdf0e10cSrcweir void Os2SalGraphics::SetTextColor( SalColor nSalColor )
596cdf0e10cSrcweir {
597cdf0e10cSrcweir 	CHARBUNDLE cb;
598cdf0e10cSrcweir 
599cdf0e10cSrcweir 	cb.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ),
600cdf0e10cSrcweir 						  SALCOLOR_GREEN( nSalColor ),
601cdf0e10cSrcweir 						  SALCOLOR_BLUE( nSalColor ) );
602cdf0e10cSrcweir 
603cdf0e10cSrcweir 	// set default color attributes
604cdf0e10cSrcweir 	Ft2SetAttrs( mhPS,
605cdf0e10cSrcweir 				 PRIM_CHAR,
606cdf0e10cSrcweir 				 CBB_COLOR,
607cdf0e10cSrcweir 				 0,
608cdf0e10cSrcweir 				 &cb );
609cdf0e10cSrcweir }
610cdf0e10cSrcweir 
611cdf0e10cSrcweir // -----------------------------------------------------------------------
612cdf0e10cSrcweir 
613cdf0e10cSrcweir USHORT Os2SalGraphics::ImplDoSetFont( ImplFontSelectData* i_pFont, float& o_rFontScale, int nFallbackLevel)
614cdf0e10cSrcweir {
615cdf0e10cSrcweir 
616cdf0e10cSrcweir #if OSL_DEBUG_LEVEL>10
617cdf0e10cSrcweir     debug_printf( "Os2SalGraphics::ImplDoSetFont\n");
618cdf0e10cSrcweir #endif
619cdf0e10cSrcweir 
620cdf0e10cSrcweir 	ImplOs2FontData* pFontData = (ImplOs2FontData*)i_pFont->mpFontData;
621cdf0e10cSrcweir 	PFONTMETRICS 	pFontMetric = NULL;
622cdf0e10cSrcweir 	FATTRS		  	aFAttrs;
623cdf0e10cSrcweir 	BOOL		  	bOutline = FALSE;
624cdf0e10cSrcweir 	APIRET			rc;
625cdf0e10cSrcweir 
626cdf0e10cSrcweir 	memset( &aFAttrs, 0, sizeof( FATTRS ) );
627cdf0e10cSrcweir 	aFAttrs.usRecordLength = sizeof( FATTRS );
628cdf0e10cSrcweir 
629cdf0e10cSrcweir 	aFAttrs.lMaxBaselineExt = i_pFont->mnHeight;
630cdf0e10cSrcweir 	aFAttrs.lAveCharWidth	= i_pFont->mnWidth;
631cdf0e10cSrcweir 
632cdf0e10cSrcweir 	// do we have a pointer to the FONTMETRICS of the selected font? -> use it!
633cdf0e10cSrcweir 	if ( pFontData )
634cdf0e10cSrcweir 	{
635cdf0e10cSrcweir 		pFontMetric = pFontData->GetFontMetrics();
636cdf0e10cSrcweir 
637cdf0e10cSrcweir 		bOutline = (pFontMetric->fsDefn & FM_DEFN_OUTLINE) != 0;
638cdf0e10cSrcweir 
639cdf0e10cSrcweir 		// use match&registry fields to get correct match
640cdf0e10cSrcweir 		aFAttrs.lMatch	     	= pFontMetric->lMatch;
641cdf0e10cSrcweir 		aFAttrs.idRegistry 		= pFontMetric->idRegistry;
642cdf0e10cSrcweir 		aFAttrs.usCodePage 		= pFontMetric->usCodePage;
643cdf0e10cSrcweir 
644cdf0e10cSrcweir 		if ( bOutline )
645cdf0e10cSrcweir 		{
646cdf0e10cSrcweir 			aFAttrs.fsFontUse |= FATTR_FONTUSE_OUTLINE;
647cdf0e10cSrcweir 			if ( i_pFont->mnOrientation )
648cdf0e10cSrcweir 				aFAttrs.fsFontUse |= FATTR_FONTUSE_TRANSFORMABLE;
649cdf0e10cSrcweir 		}
650cdf0e10cSrcweir 		else
651cdf0e10cSrcweir 		{
652cdf0e10cSrcweir 			aFAttrs.lMaxBaselineExt = pFontMetric->lMaxBaselineExt;
653cdf0e10cSrcweir 			aFAttrs.lAveCharWidth	= pFontMetric->lAveCharWidth;
654cdf0e10cSrcweir 		}
655cdf0e10cSrcweir 
656cdf0e10cSrcweir 	}
657cdf0e10cSrcweir 
658cdf0e10cSrcweir 	// use family name for outline fonts
659cdf0e10cSrcweir     if ( mbPrinter ) {
660cdf0e10cSrcweir 		// use font face name for printers because otherwise ft2lib will fail
661cdf0e10cSrcweir 		// to select the correct font for GPI (ticket#117)
662cdf0e10cSrcweir 		strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFacename, sizeof( aFAttrs.szFacename ) );
663cdf0e10cSrcweir 	} else if ( !pFontMetric) {
664cdf0e10cSrcweir 		// use OOo name if fontmetrics not available!
665cdf0e10cSrcweir 		ByteString aName( i_pFont->maName.GetToken( 0 ), gsl_getSystemTextEncoding());
666cdf0e10cSrcweir 		strncpy( (char*)(aFAttrs.szFacename), aName.GetBuffer(), sizeof( aFAttrs.szFacename ) );
667cdf0e10cSrcweir 	} else if ( bOutline) {
668cdf0e10cSrcweir 		// use fontmetric family name for outline fonts
669cdf0e10cSrcweir 		strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFamilyname, sizeof( aFAttrs.szFacename ) );
670cdf0e10cSrcweir 	} else {
671cdf0e10cSrcweir 		// use real font face name for bitmaps (WarpSans only)
672cdf0e10cSrcweir 		strncpy( (char*)(aFAttrs.szFacename), pFontMetric->szFacename, sizeof( aFAttrs.szFacename ) );
673cdf0e10cSrcweir 	}
674cdf0e10cSrcweir 
675cdf0e10cSrcweir 	if ( i_pFont->meItalic != ITALIC_NONE )
676cdf0e10cSrcweir 		aFAttrs.fsSelection |= FATTR_SEL_ITALIC;
677cdf0e10cSrcweir 	if ( i_pFont->meWeight > WEIGHT_MEDIUM )
678cdf0e10cSrcweir 		aFAttrs.fsSelection |= FATTR_SEL_BOLD;
679cdf0e10cSrcweir 
680cdf0e10cSrcweir #if OSL_DEBUG_LEVEL>1
681cdf0e10cSrcweir 	if (pFontMetric->szFacename[0] == 'A') {
682cdf0e10cSrcweir 		debug_printf( "Os2SalGraphics::SetFont hps %x lMatch '%d'\n", mhPS, pFontMetric->lMatch);
683cdf0e10cSrcweir 		debug_printf( "Os2SalGraphics::SetFont hps %x fontmetrics facename '%s'\n", mhPS, pFontMetric->szFacename);
684cdf0e10cSrcweir 		debug_printf( "Os2SalGraphics::SetFont hps %x fattrs facename '%s'\n", mhPS, aFAttrs.szFacename);
685cdf0e10cSrcweir 	}
686cdf0e10cSrcweir #endif
687cdf0e10cSrcweir 
688cdf0e10cSrcweir 	Ft2DeleteSetId( mhPS, nFallbackLevel + LCID_BASE);
689cdf0e10cSrcweir 	if ( (rc=Ft2CreateLogFont( mhPS, NULL, nFallbackLevel + LCID_BASE, &aFAttrs)) == GPI_ERROR ) {
690cdf0e10cSrcweir #if OSL_DEBUG_LEVEL>1
691cdf0e10cSrcweir 		ERRORID nLastError = WinGetLastError( GetSalData()->mhAB );
692cdf0e10cSrcweir     	debug_printf( "Os2SalGraphics::SetFont hps %x Ft2CreateLogFont failed err %x\n", mhPS, nLastError );
693cdf0e10cSrcweir #endif
694cdf0e10cSrcweir 		return SAL_SETFONT_REMOVEANDMATCHNEW;
695cdf0e10cSrcweir 	}
696cdf0e10cSrcweir 
697cdf0e10cSrcweir 	CHARBUNDLE aBundle;
698cdf0e10cSrcweir 
699cdf0e10cSrcweir 	ULONG nAttrsDefault = 0;
700cdf0e10cSrcweir 	ULONG nAttrs = CBB_SET;
701cdf0e10cSrcweir 	aBundle.usSet = nFallbackLevel + LCID_BASE;
702cdf0e10cSrcweir 
703cdf0e10cSrcweir 	if ( bOutline )
704cdf0e10cSrcweir 	{
705cdf0e10cSrcweir 		nAttrs |= CBB_BOX;
706cdf0e10cSrcweir 		aBundle.sizfxCell.cy = MAKEFIXED( i_pFont->mnHeight, 0 );
707cdf0e10cSrcweir 
708cdf0e10cSrcweir 		if ( !i_pFont->mnWidth )
709cdf0e10cSrcweir 		{
710cdf0e10cSrcweir 			LONG nXFontRes;
711cdf0e10cSrcweir 			LONG nYFontRes;
712cdf0e10cSrcweir 			LONG nHeight;
713cdf0e10cSrcweir 
714cdf0e10cSrcweir 			// Auf die Aufloesung achten, damit das Ergebnis auch auf
715cdf0e10cSrcweir 			// Drucken mit 180*360 DPI stimmt. Ausserdem muss gerundet
716cdf0e10cSrcweir 			// werden, da auf meinem OS2 beispielsweise als
717cdf0e10cSrcweir 			// Bildschirmaufloesung 3618*3622 PixelPerMeter zurueck-
718cdf0e10cSrcweir 			// gegeben wird
719cdf0e10cSrcweir 			GetResolution( nXFontRes, nYFontRes );
720cdf0e10cSrcweir 			nHeight = i_pFont->mnHeight;
721cdf0e10cSrcweir 			nHeight *= nXFontRes;
722cdf0e10cSrcweir 			nHeight += nYFontRes/2;
723cdf0e10cSrcweir 			nHeight /= nYFontRes;
724cdf0e10cSrcweir 			aBundle.sizfxCell.cx = MAKEFIXED( nHeight, 0 );
725cdf0e10cSrcweir 		}
726cdf0e10cSrcweir 		else
727cdf0e10cSrcweir 			aBundle.sizfxCell.cx = MAKEFIXED( i_pFont->mnWidth, 0 );
728cdf0e10cSrcweir 	}
729cdf0e10cSrcweir 
730cdf0e10cSrcweir 	// set orientation for outlinefonts
731cdf0e10cSrcweir 	if ( i_pFont->mnOrientation )
732cdf0e10cSrcweir 	{
733cdf0e10cSrcweir 		if ( bOutline )
734cdf0e10cSrcweir 		{
735cdf0e10cSrcweir 			nAttrs |= CBB_ANGLE;
736cdf0e10cSrcweir 			double alpha = (double)(i_pFont->mnOrientation);
737cdf0e10cSrcweir 			alpha *= 0.0017453292;	 // *PI / 1800
738cdf0e10cSrcweir 			mnOrientationY = (long) (1000.0 * sin( alpha ));
739cdf0e10cSrcweir 			mnOrientationX = (long) (1000.0 * cos( alpha ));
740cdf0e10cSrcweir 			aBundle.ptlAngle.x = mnOrientationX;
741cdf0e10cSrcweir 			aBundle.ptlAngle.y = mnOrientationY;
742cdf0e10cSrcweir 		}
743cdf0e10cSrcweir 		else
744cdf0e10cSrcweir 		{
745cdf0e10cSrcweir 			mnOrientationX = 1;
746cdf0e10cSrcweir 			mnOrientationY = 0;
747cdf0e10cSrcweir 			nAttrs |= CBB_ANGLE;
748cdf0e10cSrcweir 			aBundle.ptlAngle.x = 1;
749cdf0e10cSrcweir 			aBundle.ptlAngle.y = 0;
750cdf0e10cSrcweir 		}
751cdf0e10cSrcweir 	}
752cdf0e10cSrcweir 	else
753cdf0e10cSrcweir 	{
754cdf0e10cSrcweir 		mnOrientationX = 1;
755cdf0e10cSrcweir 		mnOrientationY = 0;
756cdf0e10cSrcweir 		nAttrs |= CBB_ANGLE;
757cdf0e10cSrcweir 		aBundle.ptlAngle.x = 1;
758cdf0e10cSrcweir 		aBundle.ptlAngle.y = 0;
759cdf0e10cSrcweir 	}
760cdf0e10cSrcweir 
761cdf0e10cSrcweir 	rc = Ft2SetAttrs( mhPS, PRIM_CHAR, nAttrs, nAttrsDefault, &aBundle );
762cdf0e10cSrcweir 
763cdf0e10cSrcweir #if OSL_DEBUG_LEVEL>1
764cdf0e10cSrcweir 	FONTMETRICS aOS2Metric = {0};
765cdf0e10cSrcweir 	Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric );
766cdf0e10cSrcweir #endif
767cdf0e10cSrcweir 
768cdf0e10cSrcweir 	return 0;
769cdf0e10cSrcweir }
770cdf0e10cSrcweir 
771cdf0e10cSrcweir 
772cdf0e10cSrcweir USHORT Os2SalGraphics::SetFont( ImplFontSelectData* pFont, int nFallbackLevel )
773cdf0e10cSrcweir {
774cdf0e10cSrcweir 
775cdf0e10cSrcweir     // return early if there is no new font
776cdf0e10cSrcweir     if( !pFont )
777cdf0e10cSrcweir     {
778cdf0e10cSrcweir #if 0
779cdf0e10cSrcweir         // deselect still active font
780cdf0e10cSrcweir         if( mhDefFont )
781cdf0e10cSrcweir             Ft2SetCharSet( mhPS, mhDefFont );
782cdf0e10cSrcweir         // release no longer referenced font handles
783cdf0e10cSrcweir         for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
784cdf0e10cSrcweir         {
785cdf0e10cSrcweir             if( mhFonts[i] )
786cdf0e10cSrcweir                 Ft2DeleteSetId( mhPS, mhFonts[i] );
787cdf0e10cSrcweir             mhFonts[ i ] = 0;
788cdf0e10cSrcweir         }
789cdf0e10cSrcweir #endif
790cdf0e10cSrcweir         mhDefFont = 0;
791cdf0e10cSrcweir         return 0;
792cdf0e10cSrcweir     }
793cdf0e10cSrcweir 
794cdf0e10cSrcweir #if OSL_DEBUG_LEVEL>10
795cdf0e10cSrcweir     debug_printf( "Os2SalGraphics::SetFont\n");
796cdf0e10cSrcweir #endif
797cdf0e10cSrcweir 
798cdf0e10cSrcweir     DBG_ASSERT( pFont->mpFontData, "WinSalGraphics mpFontData==NULL");
799cdf0e10cSrcweir     mpOs2FontEntry[ nFallbackLevel ] = reinterpret_cast<ImplOs2FontEntry*>( pFont->mpFontEntry );
800cdf0e10cSrcweir     mpOs2FontData[ nFallbackLevel ] = static_cast<const ImplOs2FontData*>( pFont->mpFontData );
801cdf0e10cSrcweir 
802cdf0e10cSrcweir 	ImplDoSetFont( pFont, mfFontScale, nFallbackLevel);
803cdf0e10cSrcweir 
804cdf0e10cSrcweir     if( !mhDefFont )
805cdf0e10cSrcweir     {
806cdf0e10cSrcweir         // keep default font
807cdf0e10cSrcweir         mhDefFont = nFallbackLevel + LCID_BASE;
808cdf0e10cSrcweir     }
809cdf0e10cSrcweir     else
810cdf0e10cSrcweir     {
811cdf0e10cSrcweir         // release no longer referenced font handles
812cdf0e10cSrcweir         for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
813cdf0e10cSrcweir         {
814cdf0e10cSrcweir             if( mhFonts[i] )
815cdf0e10cSrcweir             {
816cdf0e10cSrcweir #if 0
817cdf0e10cSrcweir                 Ft2DeleteSetId( mhPS, mhFonts[i] );
818cdf0e10cSrcweir #endif
819cdf0e10cSrcweir                 mhFonts[i] = 0;
820cdf0e10cSrcweir             }
821cdf0e10cSrcweir         }
822cdf0e10cSrcweir     }
823cdf0e10cSrcweir 
824cdf0e10cSrcweir     // store new font in correct layer
825cdf0e10cSrcweir     mhFonts[ nFallbackLevel ] = nFallbackLevel + LCID_BASE;
826cdf0e10cSrcweir 
827cdf0e10cSrcweir     // now the font is live => update font face
828cdf0e10cSrcweir     if( mpOs2FontData[ nFallbackLevel ] )
829cdf0e10cSrcweir         mpOs2FontData[ nFallbackLevel ]->UpdateFromHPS( mhPS );
830cdf0e10cSrcweir 
831cdf0e10cSrcweir     if( !nFallbackLevel )
832cdf0e10cSrcweir     {
833cdf0e10cSrcweir         mbFontKernInit = TRUE;
834cdf0e10cSrcweir         if ( mpFontKernPairs )
835cdf0e10cSrcweir         {
836cdf0e10cSrcweir             delete[] mpFontKernPairs;
837cdf0e10cSrcweir             mpFontKernPairs = NULL;
838cdf0e10cSrcweir         }
839cdf0e10cSrcweir         mnFontKernPairCount = 0;
840cdf0e10cSrcweir     }
841cdf0e10cSrcweir 
842cdf0e10cSrcweir     // some printers have higher internal resolution, so their
843cdf0e10cSrcweir     // text output would be different from what we calculated
844cdf0e10cSrcweir     // => suggest DrawTextArray to workaround this problem
845cdf0e10cSrcweir     if ( mbPrinter )
846cdf0e10cSrcweir         return SAL_SETFONT_USEDRAWTEXTARRAY;
847cdf0e10cSrcweir     else
848cdf0e10cSrcweir         return 0;
849cdf0e10cSrcweir }
850cdf0e10cSrcweir 
851cdf0e10cSrcweir // -----------------------------------------------------------------------
852cdf0e10cSrcweir 
853cdf0e10cSrcweir void Os2SalGraphics::GetFontMetric( ImplFontMetricData* pMetric )
854cdf0e10cSrcweir {
855cdf0e10cSrcweir 	FONTMETRICS aOS2Metric;
856cdf0e10cSrcweir 	Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric );
857cdf0e10cSrcweir 
858cdf0e10cSrcweir #if OSL_DEBUG_LEVEL>1
859cdf0e10cSrcweir 	debug_printf( "Os2SalGraphics::GetFontMetric hps %x\n", mhPS);
860cdf0e10cSrcweir 	if (aOS2Metric.szFacename[0] == 'A') {
861cdf0e10cSrcweir 		debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics facename '%s'\n", mhPS, aOS2Metric.szFacename);
862cdf0e10cSrcweir 		debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics lMatch '%d'\n", mhPS, aOS2Metric.lMatch);
863cdf0e10cSrcweir 	}
864cdf0e10cSrcweir #endif
865cdf0e10cSrcweir 
866cdf0e10cSrcweir 	pMetric->maName 			= UniString( aOS2Metric.szFamilyname, gsl_getSystemTextEncoding());
867cdf0e10cSrcweir 	pMetric->maStyleName		= ImpStyleNameToSal( aOS2Metric.szFamilyname,
868cdf0e10cSrcweir 													 aOS2Metric.szFacename,
869cdf0e10cSrcweir 													 strlen( aOS2Metric.szFamilyname ) );
870cdf0e10cSrcweir 
871cdf0e10cSrcweir     // device independent font attributes
872cdf0e10cSrcweir     pMetric->meFamily       = ImplFamilyToSal( aOS2Metric.panose.bFamilyType);
873cdf0e10cSrcweir     pMetric->mbSymbolFlag   = (aOS2Metric.usCodePage == SYMBOL_CHARSET);
874cdf0e10cSrcweir     pMetric->meWeight       = ImplWeightToSal( aOS2Metric.usWeightClass );
875cdf0e10cSrcweir     pMetric->mePitch        = ImplLogPitchToSal( aOS2Metric.fsType );
876cdf0e10cSrcweir     pMetric->meItalic       = (aOS2Metric.fsSelection & FM_SEL_ITALIC) ? ITALIC_NORMAL : ITALIC_NONE;
877cdf0e10cSrcweir     pMetric->mnSlant        = 0;
878cdf0e10cSrcweir 
879cdf0e10cSrcweir     // device dependend font attributes
880cdf0e10cSrcweir     pMetric->mbDevice       = (aOS2Metric.fsDefn & FM_DEFN_GENERIC) ? FALSE : TRUE;
881cdf0e10cSrcweir     pMetric->mbScalableFont = (aOS2Metric.fsDefn & FM_DEFN_OUTLINE) ? true : false;
882cdf0e10cSrcweir     if( pMetric->mbScalableFont )
883cdf0e10cSrcweir     {
884cdf0e10cSrcweir         // check if there are kern pairs
885cdf0e10cSrcweir         // TODO: does this work with GPOS kerning?
886cdf0e10cSrcweir         pMetric->mbKernableFont = (aOS2Metric.sKerningPairs > 0);
887cdf0e10cSrcweir     }
888cdf0e10cSrcweir     else
889cdf0e10cSrcweir     {
890cdf0e10cSrcweir         // bitmap fonts cannot be rotated directly
891cdf0e10cSrcweir         pMetric->mnOrientation  = 0;
892cdf0e10cSrcweir         // bitmap fonts have no kerning
893cdf0e10cSrcweir         pMetric->mbKernableFont = false;
894cdf0e10cSrcweir     }
895cdf0e10cSrcweir 
896cdf0e10cSrcweir     // transformation dependend font metrics
897cdf0e10cSrcweir 	if ( aOS2Metric.fsDefn & FM_DEFN_OUTLINE )
898cdf0e10cSrcweir 	{
899cdf0e10cSrcweir 		pMetric->mnWidth	   = aOS2Metric.lEmInc;
900cdf0e10cSrcweir 	}
901cdf0e10cSrcweir 	else
902cdf0e10cSrcweir 	{
903cdf0e10cSrcweir 		pMetric->mnWidth	   = aOS2Metric.lAveCharWidth;
904cdf0e10cSrcweir 		pMetric->mnOrientation = 0;
905cdf0e10cSrcweir 	}
906cdf0e10cSrcweir 	pMetric->mnIntLeading		= aOS2Metric.lInternalLeading;
907cdf0e10cSrcweir 	pMetric->mnExtLeading		= aOS2Metric.lExternalLeading;
908cdf0e10cSrcweir 	pMetric->mnAscent			= aOS2Metric.lMaxAscender;
909cdf0e10cSrcweir 	pMetric->mnDescent			= aOS2Metric.lMaxDescender;
910cdf0e10cSrcweir 
911cdf0e10cSrcweir     // #107888# improved metric compatibility for Asian fonts...
912cdf0e10cSrcweir     // TODO: assess workaround below for CWS >= extleading
913cdf0e10cSrcweir     // TODO: evaluate use of aWinMetric.sTypo* members for CJK
914cdf0e10cSrcweir     if( mpOs2FontData[0] && mpOs2FontData[0]->SupportsCJK() )
915cdf0e10cSrcweir     {
916cdf0e10cSrcweir         pMetric->mnIntLeading += pMetric->mnExtLeading;
917cdf0e10cSrcweir 
918cdf0e10cSrcweir         // #109280# The line height for Asian fonts is too small.
919cdf0e10cSrcweir         // Therefore we add half of the external leading to the
920cdf0e10cSrcweir         // ascent, the other half is added to the descent.
921cdf0e10cSrcweir         const long nHalfTmpExtLeading = pMetric->mnExtLeading / 2;
922cdf0e10cSrcweir         const long nOtherHalfTmpExtLeading = pMetric->mnExtLeading - nHalfTmpExtLeading;
923cdf0e10cSrcweir 
924cdf0e10cSrcweir         // #110641# external leading for Asian fonts.
925cdf0e10cSrcweir         // The factor 0.3 has been confirmed with experiments.
926cdf0e10cSrcweir         long nCJKExtLeading = static_cast<long>(0.30 * (pMetric->mnAscent + pMetric->mnDescent));
927cdf0e10cSrcweir         nCJKExtLeading -= pMetric->mnExtLeading;
928cdf0e10cSrcweir         pMetric->mnExtLeading = (nCJKExtLeading > 0) ? nCJKExtLeading : 0;
929cdf0e10cSrcweir 
930cdf0e10cSrcweir         pMetric->mnAscent   += nHalfTmpExtLeading;
931cdf0e10cSrcweir         pMetric->mnDescent  += nOtherHalfTmpExtLeading;
932cdf0e10cSrcweir 
933cdf0e10cSrcweir         // #109280# HACK korean only: increase descent for wavelines and impr
934cdf0e10cSrcweir 		// YD win9x only
935cdf0e10cSrcweir     }
936cdf0e10cSrcweir 
937cdf0e10cSrcweir }
938cdf0e10cSrcweir 
939cdf0e10cSrcweir // -----------------------------------------------------------------------
940cdf0e10cSrcweir 
941cdf0e10cSrcweir ULONG Os2SalGraphics::GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs )
942cdf0e10cSrcweir {
943cdf0e10cSrcweir 	DBG_ASSERT( sizeof( KERNINGPAIRS ) == sizeof( ImplKernPairData ),
944cdf0e10cSrcweir 				"Os2SalGraphics::GetKernPairs(): KERNINGPAIRS != ImplKernPairData" );
945cdf0e10cSrcweir 
946cdf0e10cSrcweir     if ( mbFontKernInit )
947cdf0e10cSrcweir     {
948cdf0e10cSrcweir         if( mpFontKernPairs )
949cdf0e10cSrcweir         {
950cdf0e10cSrcweir             delete[] mpFontKernPairs;
951cdf0e10cSrcweir             mpFontKernPairs = NULL;
952cdf0e10cSrcweir         }
953cdf0e10cSrcweir         mnFontKernPairCount = 0;
954cdf0e10cSrcweir 
955cdf0e10cSrcweir         {
956cdf0e10cSrcweir             KERNINGPAIRS* pPairs = NULL;
957cdf0e10cSrcweir 			FONTMETRICS aOS2Metric;
958cdf0e10cSrcweir 			Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric );
959cdf0e10cSrcweir             int nCount = aOS2Metric.sKerningPairs;
960cdf0e10cSrcweir             if( nCount )
961cdf0e10cSrcweir             {
962cdf0e10cSrcweir #ifdef GCP_KERN_HACK
963cdf0e10cSrcweir                 pPairs = new KERNINGPAIRS[ nCount+1 ];
964cdf0e10cSrcweir                 mpFontKernPairs = pPairs;
965cdf0e10cSrcweir                 mnFontKernPairCount = nCount;
966cdf0e10cSrcweir 				Ft2QueryKerningPairs( mhPS, nCount, (KERNINGPAIRS*)pPairs );
967cdf0e10cSrcweir #else // GCP_KERN_HACK
968cdf0e10cSrcweir 				pPairs = (KERNINGPAIRS*)pKernPairs;
969cdf0e10cSrcweir 				nCount = (nCount < nPairs) ? nCount : nPairs;
970cdf0e10cSrcweir 				Ft2QueryKerningPairs( mhPS, nCount, (KERNINGPAIRS*)pPairs );
971cdf0e10cSrcweir                 return nCount;
972cdf0e10cSrcweir #endif // GCP_KERN_HACK
973cdf0e10cSrcweir             }
974cdf0e10cSrcweir         }
975cdf0e10cSrcweir 
976cdf0e10cSrcweir         mbFontKernInit = FALSE;
977cdf0e10cSrcweir 
978cdf0e10cSrcweir         std::sort( mpFontKernPairs, mpFontKernPairs + mnFontKernPairCount, ImplCmpKernData );
979cdf0e10cSrcweir     }
980cdf0e10cSrcweir 
981cdf0e10cSrcweir     if( !pKernPairs )
982cdf0e10cSrcweir         return mnFontKernPairCount;
983cdf0e10cSrcweir     else if( mpFontKernPairs )
984cdf0e10cSrcweir     {
985cdf0e10cSrcweir         if ( nPairs < mnFontKernPairCount )
986cdf0e10cSrcweir             nPairs = mnFontKernPairCount;
987cdf0e10cSrcweir         memcpy( pKernPairs, mpFontKernPairs,
988cdf0e10cSrcweir                 nPairs*sizeof( ImplKernPairData ) );
989cdf0e10cSrcweir         return nPairs;
990cdf0e10cSrcweir     }
991cdf0e10cSrcweir 
992cdf0e10cSrcweir     return 0;
993cdf0e10cSrcweir }
994cdf0e10cSrcweir 
995cdf0e10cSrcweir 
996cdf0e10cSrcweir // -----------------------------------------------------------------------
997cdf0e10cSrcweir 
998cdf0e10cSrcweir static const ImplFontCharMap* pOs2DefaultImplFontCharMap = NULL;
999cdf0e10cSrcweir static const sal_uInt32 pOs2DefaultRangeCodes[] = {0x0020,0x00FF};
1000cdf0e10cSrcweir 
1001cdf0e10cSrcweir const ImplFontCharMap* Os2SalGraphics::GetImplFontCharMap() const
1002cdf0e10cSrcweir {
1003cdf0e10cSrcweir     if( !mpOs2FontData[0] )
1004cdf0e10cSrcweir         return ImplFontCharMap::GetDefaultMap();
1005cdf0e10cSrcweir     return mpOs2FontData[0]->GetImplFontCharMap();
1006cdf0e10cSrcweir }
1007cdf0e10cSrcweir 
1008cdf0e10cSrcweir // -----------------------------------------------------------------------
1009cdf0e10cSrcweir 
1010cdf0e10cSrcweir bool Os2SalGraphics::AddTempDevFont( ImplDevFontList* pFontList,
1011cdf0e10cSrcweir     const String& rFontFileURL, const String& rFontName )
1012cdf0e10cSrcweir {
1013cdf0e10cSrcweir #if OSL_DEBUG_LEVEL>0
1014cdf0e10cSrcweir     debug_printf("Os2SalGraphics::AddTempDevFont\n");
1015cdf0e10cSrcweir #endif
1016cdf0e10cSrcweir     return false;
1017cdf0e10cSrcweir }
1018cdf0e10cSrcweir 
1019cdf0e10cSrcweir // -----------------------------------------------------------------------
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir void Os2SalGraphics::GetDevFontList( ImplDevFontList* pList )
1022cdf0e10cSrcweir {
1023cdf0e10cSrcweir 	PFONTMETRICS	pFontMetrics;
1024cdf0e10cSrcweir 	ULONG			nFontMetricCount;
1025cdf0e10cSrcweir 	SalData*		pSalData;
1026cdf0e10cSrcweir 
1027cdf0e10cSrcweir #if OSL_DEBUG_LEVEL>0
1028cdf0e10cSrcweir 	debug_printf("Os2SalGraphics::GetDevFontList\n");
1029cdf0e10cSrcweir #endif
1030cdf0e10cSrcweir 
1031cdf0e10cSrcweir 	// install OpenSymbol
1032cdf0e10cSrcweir 	HMODULE hMod;
1033cdf0e10cSrcweir 	ULONG	ObjNum, Offset, rc;
1034cdf0e10cSrcweir 	CHAR	Buff[2*_MAX_PATH];
1035cdf0e10cSrcweir 	char 	drive[_MAX_DRIVE], dir[_MAX_DIR];
1036cdf0e10cSrcweir 	char 	fname[_MAX_FNAME], ext[_MAX_EXT];
1037cdf0e10cSrcweir 	// get module handle (and name)
1038cdf0e10cSrcweir 	rc = DosQueryModFromEIP( &hMod, &ObjNum, sizeof( Buff), Buff,
1039cdf0e10cSrcweir 							&Offset, (ULONG)ImplSalGetUniString);
1040cdf0e10cSrcweir 	DosQueryModuleName(hMod, sizeof(Buff), Buff);
1041cdf0e10cSrcweir 	// replace module path with font path
1042cdf0e10cSrcweir 	char* slash = strrchr( Buff, '\\');
1043cdf0e10cSrcweir 	*slash = '\0';
1044cdf0e10cSrcweir 	slash = strrchr( Buff, '\\');
1045cdf0e10cSrcweir 	*slash = '\0';
1046cdf0e10cSrcweir 	strcat( Buff, "\\SHARE\\FONTS\\TRUETYPE\\OPENS___.TTF");
1047cdf0e10cSrcweir 	rc = GpiLoadPublicFonts( GetSalData()->mhAB, Buff);
1048cdf0e10cSrcweir 
1049cdf0e10cSrcweir 	if ( !mbPrinter )
1050cdf0e10cSrcweir 	{
1051cdf0e10cSrcweir 		// Bei Bildschirm-Devices cachen wir die Liste global, da
1052cdf0e10cSrcweir 		// dies im unabhaengigen Teil auch so gemacht wird und wir
1053cdf0e10cSrcweir 		// ansonsten auf geloeschten Systemdaten arbeiten koennten
1054cdf0e10cSrcweir 		pSalData = GetSalData();
1055cdf0e10cSrcweir 		nFontMetricCount	= pSalData->mnFontMetricCount;
1056cdf0e10cSrcweir 		pFontMetrics		= pSalData->mpFontMetrics;
1057cdf0e10cSrcweir 		// Bei Bildschirm-Devices holen wir uns die Fontliste jedesmal neu
1058cdf0e10cSrcweir 		if ( pFontMetrics )
1059cdf0e10cSrcweir 		{
1060cdf0e10cSrcweir 			delete pFontMetrics;
1061cdf0e10cSrcweir 			pFontMetrics		= NULL;
1062cdf0e10cSrcweir 			nFontMetricCount	= 0;
1063cdf0e10cSrcweir 		}
1064cdf0e10cSrcweir 	}
1065cdf0e10cSrcweir 	else
1066cdf0e10cSrcweir 	{
1067cdf0e10cSrcweir 		nFontMetricCount	= mnFontMetricCount;
1068cdf0e10cSrcweir 		pFontMetrics		= mpFontMetrics;
1069cdf0e10cSrcweir 	}
1070cdf0e10cSrcweir 
1071cdf0e10cSrcweir 	// do we have to create the cached font list first?
1072cdf0e10cSrcweir 	if ( !pFontMetrics )
1073cdf0e10cSrcweir 	{
1074cdf0e10cSrcweir 		// query the number of fonts available
1075cdf0e10cSrcweir 		LONG nTemp = 0;
1076cdf0e10cSrcweir 		nFontMetricCount = Ft2QueryFonts( mhPS,
1077cdf0e10cSrcweir 										  QF_PUBLIC | QF_PRIVATE,
1078cdf0e10cSrcweir 										  NULL, &nTemp,
1079cdf0e10cSrcweir 										  sizeof( FONTMETRICS ), NULL );
1080cdf0e10cSrcweir 
1081cdf0e10cSrcweir 		// procede only if at least one is available!
1082cdf0e10cSrcweir 		if ( nFontMetricCount )
1083cdf0e10cSrcweir 		{
1084cdf0e10cSrcweir 			// allocate memory for font list
1085cdf0e10cSrcweir 			pFontMetrics = new FONTMETRICS[nFontMetricCount];
1086cdf0e10cSrcweir 
1087cdf0e10cSrcweir 			// query font list
1088cdf0e10cSrcweir 			Ft2QueryFonts( mhPS,
1089cdf0e10cSrcweir 						   QF_PUBLIC | QF_PRIVATE,
1090cdf0e10cSrcweir 						   NULL,
1091cdf0e10cSrcweir 						   (PLONG)&nFontMetricCount,
1092cdf0e10cSrcweir 						   (LONG) sizeof( FONTMETRICS ),
1093cdf0e10cSrcweir 						   pFontMetrics );
1094cdf0e10cSrcweir 		}
1095cdf0e10cSrcweir 
1096cdf0e10cSrcweir 		if ( !mbPrinter )
1097cdf0e10cSrcweir 		{
1098cdf0e10cSrcweir 			pSalData->mnFontMetricCount 		= nFontMetricCount;
1099cdf0e10cSrcweir 			pSalData->mpFontMetrics 			= pFontMetrics;
1100cdf0e10cSrcweir 		}
1101cdf0e10cSrcweir 		else
1102cdf0e10cSrcweir 		{
1103cdf0e10cSrcweir 			mnFontMetricCount	= nFontMetricCount;
1104cdf0e10cSrcweir 			mpFontMetrics		= pFontMetrics;
1105cdf0e10cSrcweir 		}
1106cdf0e10cSrcweir 	}
1107cdf0e10cSrcweir 
1108cdf0e10cSrcweir 	// copy data from the font list
1109cdf0e10cSrcweir 	for( ULONG i = 0; i < nFontMetricCount; i++ )
1110cdf0e10cSrcweir 	{
1111cdf0e10cSrcweir 		PFONTMETRICS pFontMetric = &pFontMetrics[i];
1112cdf0e10cSrcweir 
1113cdf0e10cSrcweir 		// skip font starting with '@', this is an alias internally
1114cdf0e10cSrcweir 		// used by truetype engine.
1115cdf0e10cSrcweir 		if (pFontMetric->szFacename[0] == '@')
1116cdf0e10cSrcweir 			continue;
1117cdf0e10cSrcweir 
1118cdf0e10cSrcweir 		// skip bitmap fonts (but keep WarpSans)
1119cdf0e10cSrcweir 		if ( (pFontMetric->fsDefn & FM_DEFN_OUTLINE) == 0
1120cdf0e10cSrcweir 			&& strncmp( pFontMetric->szFacename, "WarpSans", 8) )
1121cdf0e10cSrcweir 			// Font nicht aufnehmen
1122cdf0e10cSrcweir 			continue;
1123cdf0e10cSrcweir 
1124cdf0e10cSrcweir 		// replace '-' in facename with ' ' (for ft2lib)
1125cdf0e10cSrcweir 		char* dash = pFontMetric->szFacename;
1126cdf0e10cSrcweir 		while( (dash=strchr( dash, '-')))
1127cdf0e10cSrcweir 			*dash++ = ' ';
1128cdf0e10cSrcweir 
1129cdf0e10cSrcweir 		// create new font list element
1130cdf0e10cSrcweir 		ImplOs2FontData* pData 		= new ImplOs2FontData( pFontMetric, 0, 0 );
1131cdf0e10cSrcweir 
1132cdf0e10cSrcweir 		// add font list element to font list
1133cdf0e10cSrcweir 		pList->Add( pData );
1134cdf0e10cSrcweir 
1135cdf0e10cSrcweir 	}
1136cdf0e10cSrcweir }
1137cdf0e10cSrcweir 
1138cdf0e10cSrcweir // ----------------------------------------------------------------------------
1139cdf0e10cSrcweir 
1140cdf0e10cSrcweir void Os2SalGraphics::GetDevFontSubstList( OutputDevice* pOutDev )
1141cdf0e10cSrcweir {
1142cdf0e10cSrcweir }
1143cdf0e10cSrcweir 
1144cdf0e10cSrcweir // -----------------------------------------------------------------------
1145cdf0e10cSrcweir 
1146cdf0e10cSrcweir BOOL Os2SalGraphics::GetGlyphBoundRect( long nIndex, Rectangle& rRect )
1147cdf0e10cSrcweir {
1148cdf0e10cSrcweir     // use unity matrix
1149cdf0e10cSrcweir     MAT2 aMat;
1150cdf0e10cSrcweir     aMat.eM11 = aMat.eM22 = FixedFromDouble( 1.0 );
1151cdf0e10cSrcweir     aMat.eM12 = aMat.eM21 = FixedFromDouble( 0.0 );
1152cdf0e10cSrcweir 
1153cdf0e10cSrcweir     UINT nGGOFlags = GGO_METRICS;
1154cdf0e10cSrcweir     if( !(nIndex & GF_ISCHAR) )
1155cdf0e10cSrcweir         nGGOFlags |= GGO_GLYPH_INDEX;
1156cdf0e10cSrcweir     nIndex &= GF_IDXMASK;
1157cdf0e10cSrcweir 
1158cdf0e10cSrcweir     GLYPHMETRICS aGM;
1159cdf0e10cSrcweir     DWORD nSize = FT2_ERROR;
1160cdf0e10cSrcweir     nSize = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, &aGM, 0, NULL, &aMat );
1161cdf0e10cSrcweir     if( nSize == FT2_ERROR )
1162cdf0e10cSrcweir         return false;
1163cdf0e10cSrcweir 
1164cdf0e10cSrcweir     rRect = Rectangle( Point( +aGM.gmptGlyphOrigin.x, -aGM.gmptGlyphOrigin.y ),
1165cdf0e10cSrcweir         Size( aGM.gmBlackBoxX, aGM.gmBlackBoxY ) );
1166cdf0e10cSrcweir     rRect.Left()    = static_cast<int>( mfFontScale * rRect.Left() );
1167cdf0e10cSrcweir     rRect.Right()   = static_cast<int>( mfFontScale * rRect.Right() );
1168cdf0e10cSrcweir     rRect.Top()     = static_cast<int>( mfFontScale * rRect.Top() );
1169cdf0e10cSrcweir     rRect.Bottom()  = static_cast<int>( mfFontScale * rRect.Bottom() );
1170cdf0e10cSrcweir     return true;
1171cdf0e10cSrcweir }
1172cdf0e10cSrcweir 
1173cdf0e10cSrcweir // -----------------------------------------------------------------------
1174cdf0e10cSrcweir 
1175cdf0e10cSrcweir BOOL Os2SalGraphics::GetGlyphOutline( long nIndex, ::basegfx::B2DPolyPolygon& rB2DPolyPoly )
1176cdf0e10cSrcweir {
1177cdf0e10cSrcweir #if OSL_DEBUG_LEVEL>0
1178cdf0e10cSrcweir 	debug_printf("Os2SalGraphics::GetGlyphOutline\n");
1179cdf0e10cSrcweir #endif
1180cdf0e10cSrcweir     rB2DPolyPoly.clear();
1181cdf0e10cSrcweir 
1182cdf0e10cSrcweir     BOOL bRet = FALSE;
1183cdf0e10cSrcweir 
1184cdf0e10cSrcweir     // use unity matrix
1185cdf0e10cSrcweir     MAT2 aMat;
1186cdf0e10cSrcweir     aMat.eM11 = aMat.eM22 = FixedFromDouble( 1.0 );
1187cdf0e10cSrcweir     aMat.eM12 = aMat.eM21 = FixedFromDouble( 0.0 );
1188cdf0e10cSrcweir 
1189cdf0e10cSrcweir     UINT nGGOFlags = GGO_NATIVE;
1190cdf0e10cSrcweir     if( !(nIndex & GF_ISCHAR) )
1191cdf0e10cSrcweir         nGGOFlags |= GGO_GLYPH_INDEX;
1192cdf0e10cSrcweir     nIndex &= GF_IDXMASK;
1193cdf0e10cSrcweir 
1194cdf0e10cSrcweir     GLYPHMETRICS aGlyphMetrics;
1195cdf0e10cSrcweir     DWORD nSize1 = FT2_ERROR;
1196cdf0e10cSrcweir     nSize1 = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags, &aGlyphMetrics, 0, NULL, &aMat );
1197cdf0e10cSrcweir 
1198cdf0e10cSrcweir     if( !nSize1 )       // blank glyphs are ok
1199cdf0e10cSrcweir         bRet = TRUE;
1200cdf0e10cSrcweir     else if( nSize1 != FT2_ERROR )
1201cdf0e10cSrcweir     {
1202cdf0e10cSrcweir         BYTE*   pData = new BYTE[ nSize1 ];
1203cdf0e10cSrcweir         ULONG   nTotalCount = 0;
1204cdf0e10cSrcweir         DWORD   nSize2;
1205cdf0e10cSrcweir         nSize2 = Ft2GetGlyphOutline( mhPS, nIndex, nGGOFlags,
1206cdf0e10cSrcweir                 &aGlyphMetrics, nSize1, pData, &aMat );
1207cdf0e10cSrcweir 
1208cdf0e10cSrcweir         if( nSize1 == nSize2 )
1209cdf0e10cSrcweir         {
1210cdf0e10cSrcweir             bRet = TRUE;
1211cdf0e10cSrcweir 
1212cdf0e10cSrcweir             int     nPtSize = 512;
1213cdf0e10cSrcweir             Point*  pPoints = new Point[ nPtSize ];
1214cdf0e10cSrcweir             BYTE*   pFlags = new BYTE[ nPtSize ];
1215cdf0e10cSrcweir 
1216cdf0e10cSrcweir             TTPOLYGONHEADER* pHeader = (TTPOLYGONHEADER*)pData;
1217cdf0e10cSrcweir             while( (BYTE*)pHeader < pData+nSize2 )
1218cdf0e10cSrcweir             {
1219cdf0e10cSrcweir                 // only outline data is interesting
1220cdf0e10cSrcweir                 if( pHeader->dwType != TT_POLYGON_TYPE )
1221cdf0e10cSrcweir                     break;
1222cdf0e10cSrcweir 
1223cdf0e10cSrcweir                 // get start point; next start points are end points
1224cdf0e10cSrcweir                 // of previous segment
1225cdf0e10cSrcweir                 int nPnt = 0;
1226cdf0e10cSrcweir 
1227cdf0e10cSrcweir                 long nX = IntTimes256FromFixed( pHeader->pfxStart.x );
1228cdf0e10cSrcweir                 long nY = IntTimes256FromFixed( pHeader->pfxStart.y );
1229cdf0e10cSrcweir                 pPoints[ nPnt ] = Point( nX, nY );
1230cdf0e10cSrcweir                 pFlags[ nPnt++ ] = POLY_NORMAL;
1231cdf0e10cSrcweir 
1232cdf0e10cSrcweir                 bool bHasOfflinePoints = false;
1233cdf0e10cSrcweir                 TTPOLYCURVE* pCurve = (TTPOLYCURVE*)( pHeader + 1 );
1234cdf0e10cSrcweir                 pHeader = (TTPOLYGONHEADER*)( (BYTE*)pHeader + pHeader->cb );
1235cdf0e10cSrcweir                 while( (BYTE*)pCurve < (BYTE*)pHeader )
1236cdf0e10cSrcweir                 {
1237cdf0e10cSrcweir                     int nNeededSize = nPnt + 16 + 3 * pCurve->cpfx;
1238cdf0e10cSrcweir                     if( nPtSize < nNeededSize )
1239cdf0e10cSrcweir                     {
1240cdf0e10cSrcweir                         Point* pOldPoints = pPoints;
1241cdf0e10cSrcweir                         BYTE* pOldFlags = pFlags;
1242cdf0e10cSrcweir                         nPtSize = 2 * nNeededSize;
1243cdf0e10cSrcweir                         pPoints = new Point[ nPtSize ];
1244cdf0e10cSrcweir                         pFlags = new BYTE[ nPtSize ];
1245cdf0e10cSrcweir                         for( int i = 0; i < nPnt; ++i )
1246cdf0e10cSrcweir                         {
1247cdf0e10cSrcweir                             pPoints[ i ] = pOldPoints[ i ];
1248cdf0e10cSrcweir                             pFlags[ i ] = pOldFlags[ i ];
1249cdf0e10cSrcweir                         }
1250cdf0e10cSrcweir                         delete[] pOldPoints;
1251cdf0e10cSrcweir                         delete[] pOldFlags;
1252cdf0e10cSrcweir                     }
1253cdf0e10cSrcweir 
1254cdf0e10cSrcweir                     int i = 0;
1255cdf0e10cSrcweir                     if( TT_PRIM_LINE == pCurve->wType )
1256cdf0e10cSrcweir                     {
1257cdf0e10cSrcweir                         while( i < pCurve->cpfx )
1258cdf0e10cSrcweir                         {
1259cdf0e10cSrcweir                             nX = IntTimes256FromFixed( pCurve->apfx[ i ].x );
1260cdf0e10cSrcweir                             nY = IntTimes256FromFixed( pCurve->apfx[ i ].y );
1261cdf0e10cSrcweir                             ++i;
1262cdf0e10cSrcweir                             pPoints[ nPnt ] = Point( nX, nY );
1263cdf0e10cSrcweir                             pFlags[ nPnt ] = POLY_NORMAL;
1264cdf0e10cSrcweir                             ++nPnt;
1265cdf0e10cSrcweir                         }
1266cdf0e10cSrcweir                     }
1267cdf0e10cSrcweir                     else if( TT_PRIM_QSPLINE == pCurve->wType )
1268cdf0e10cSrcweir                     {
1269cdf0e10cSrcweir                         bHasOfflinePoints = true;
1270cdf0e10cSrcweir                         while( i < pCurve->cpfx )
1271cdf0e10cSrcweir                         {
1272cdf0e10cSrcweir                             // get control point of quadratic bezier spline
1273cdf0e10cSrcweir                             nX = IntTimes256FromFixed( pCurve->apfx[ i ].x );
1274cdf0e10cSrcweir                             nY = IntTimes256FromFixed( pCurve->apfx[ i ].y );
1275cdf0e10cSrcweir                             ++i;
1276cdf0e10cSrcweir                             Point aControlP( nX, nY );
1277cdf0e10cSrcweir 
1278cdf0e10cSrcweir                             // calculate first cubic control point
1279cdf0e10cSrcweir                             // P0 = 1/3 * (PBeg + 2 * PQControl)
1280cdf0e10cSrcweir                             nX = pPoints[ nPnt-1 ].X() + 2 * aControlP.X();
1281cdf0e10cSrcweir                             nY = pPoints[ nPnt-1 ].Y() + 2 * aControlP.Y();
1282cdf0e10cSrcweir                             pPoints[ nPnt+0 ] = Point( (2*nX+3)/6, (2*nY+3)/6 );
1283cdf0e10cSrcweir                             pFlags[ nPnt+0 ] = POLY_CONTROL;
1284cdf0e10cSrcweir 
1285cdf0e10cSrcweir                             // calculate endpoint of segment
1286cdf0e10cSrcweir                             nX = IntTimes256FromFixed( pCurve->apfx[ i ].x );
1287cdf0e10cSrcweir                             nY = IntTimes256FromFixed( pCurve->apfx[ i ].y );
1288cdf0e10cSrcweir 
1289cdf0e10cSrcweir                             if ( i+1 >= pCurve->cpfx )
1290cdf0e10cSrcweir                             {
1291cdf0e10cSrcweir                                 // endpoint is either last point in segment => advance
1292cdf0e10cSrcweir                                 ++i;
1293cdf0e10cSrcweir                             }
1294cdf0e10cSrcweir                             else
1295cdf0e10cSrcweir                             {
1296cdf0e10cSrcweir                                 // or endpoint is the middle of two control points
1297cdf0e10cSrcweir                                 nX += IntTimes256FromFixed( pCurve->apfx[ i-1 ].x );
1298cdf0e10cSrcweir                                 nY += IntTimes256FromFixed( pCurve->apfx[ i-1 ].y );
1299cdf0e10cSrcweir                                 nX = (nX + 1) / 2;
1300cdf0e10cSrcweir                                 nY = (nY + 1) / 2;
1301cdf0e10cSrcweir                                 // no need to advance, because the current point
1302cdf0e10cSrcweir                                 // is the control point in next bezier spline
1303cdf0e10cSrcweir                             }
1304cdf0e10cSrcweir 
1305cdf0e10cSrcweir                             pPoints[ nPnt+2 ] = Point( nX, nY );
1306cdf0e10cSrcweir                             pFlags[ nPnt+2 ] = POLY_NORMAL;
1307cdf0e10cSrcweir 
1308cdf0e10cSrcweir                             // calculate second cubic control point
1309cdf0e10cSrcweir                             // P1 = 1/3 * (PEnd + 2 * PQControl)
1310cdf0e10cSrcweir                             nX = pPoints[ nPnt+2 ].X() + 2 * aControlP.X();
1311cdf0e10cSrcweir                             nY = pPoints[ nPnt+2 ].Y() + 2 * aControlP.Y();
1312cdf0e10cSrcweir                             pPoints[ nPnt+1 ] = Point( (2*nX+3)/6, (2*nY+3)/6 );
1313cdf0e10cSrcweir                             pFlags[ nPnt+1 ] = POLY_CONTROL;
1314cdf0e10cSrcweir 
1315cdf0e10cSrcweir                             nPnt += 3;
1316cdf0e10cSrcweir                         }
1317cdf0e10cSrcweir                     }
1318cdf0e10cSrcweir 
1319cdf0e10cSrcweir                     // next curve segment
1320cdf0e10cSrcweir                     pCurve = (TTPOLYCURVE*)&pCurve->apfx[ i ];
1321cdf0e10cSrcweir                 }
1322cdf0e10cSrcweir 
1323cdf0e10cSrcweir                 // end point is start point for closed contour
1324cdf0e10cSrcweir                 // disabled, because Polygon class closes the contour itself
1325cdf0e10cSrcweir                 // pPoints[nPnt++] = pPoints[0];
1326cdf0e10cSrcweir 				// #i35928#
1327cdf0e10cSrcweir 				// Added again, but add only when not yet closed
1328cdf0e10cSrcweir 				if(pPoints[nPnt - 1] != pPoints[0])
1329cdf0e10cSrcweir 				{
1330cdf0e10cSrcweir                     if( bHasOfflinePoints )
1331cdf0e10cSrcweir                         pFlags[nPnt] = pFlags[0];
1332cdf0e10cSrcweir 
1333cdf0e10cSrcweir 					pPoints[nPnt++] = pPoints[0];
1334cdf0e10cSrcweir 				}
1335cdf0e10cSrcweir 
1336cdf0e10cSrcweir                 // convert y-coordinates W32 -> VCL
1337cdf0e10cSrcweir                 for( int i = 0; i < nPnt; ++i )
1338cdf0e10cSrcweir                     pPoints[i].Y() = -pPoints[i].Y();
1339cdf0e10cSrcweir 
1340cdf0e10cSrcweir                 // insert into polypolygon
1341cdf0e10cSrcweir                 Polygon aPoly( nPnt, pPoints, (bHasOfflinePoints ? pFlags : NULL) );
1342cdf0e10cSrcweir                 // convert to B2DPolyPolygon
1343cdf0e10cSrcweir                 // TODO: get rid of the intermediate PolyPolygon
1344cdf0e10cSrcweir                 rB2DPolyPoly.append( aPoly.getB2DPolygon() );
1345cdf0e10cSrcweir             }
1346cdf0e10cSrcweir 
1347cdf0e10cSrcweir             delete[] pPoints;
1348cdf0e10cSrcweir             delete[] pFlags;
1349cdf0e10cSrcweir         }
1350cdf0e10cSrcweir 
1351cdf0e10cSrcweir         delete[] pData;
1352cdf0e10cSrcweir     }
1353cdf0e10cSrcweir 
1354cdf0e10cSrcweir     // rescaling needed for the PolyPolygon conversion
1355cdf0e10cSrcweir     if( rB2DPolyPoly.count() )
1356cdf0e10cSrcweir     {
1357cdf0e10cSrcweir 		const double fFactor((1.0/256) * mfFontScale);
1358cdf0e10cSrcweir 		rB2DPolyPoly.transform(basegfx::tools::createScaleB2DHomMatrix(fFactor, fFactor));
1359cdf0e10cSrcweir     }
1360cdf0e10cSrcweir 
1361cdf0e10cSrcweir     return bRet;
1362cdf0e10cSrcweir }
1363cdf0e10cSrcweir 
1364cdf0e10cSrcweir // -----------------------------------------------------------------------
1365cdf0e10cSrcweir 
1366cdf0e10cSrcweir // TODO:  Replace this class with boost::scoped_array
1367cdf0e10cSrcweir class ScopedCharArray
1368cdf0e10cSrcweir {
1369cdf0e10cSrcweir public:
1370cdf0e10cSrcweir 	inline explicit ScopedCharArray(char * pArray): m_pArray(pArray) {}
1371cdf0e10cSrcweir 
1372cdf0e10cSrcweir 	inline ~ScopedCharArray() { delete[] m_pArray; }
1373cdf0e10cSrcweir 
1374cdf0e10cSrcweir 	inline char * get() const { return m_pArray; }
1375cdf0e10cSrcweir 
1376cdf0e10cSrcweir private:
1377cdf0e10cSrcweir 	char * m_pArray;
1378cdf0e10cSrcweir };
1379cdf0e10cSrcweir 
1380cdf0e10cSrcweir class ScopedFont
1381cdf0e10cSrcweir {
1382cdf0e10cSrcweir public:
1383cdf0e10cSrcweir 	explicit ScopedFont(Os2SalGraphics & rData);
1384cdf0e10cSrcweir 
1385cdf0e10cSrcweir 	~ScopedFont();
1386cdf0e10cSrcweir 
1387cdf0e10cSrcweir private:
1388cdf0e10cSrcweir 	Os2SalGraphics & m_rData;
1389cdf0e10cSrcweir 	ULONG m_hOrigFont;
1390cdf0e10cSrcweir };
1391cdf0e10cSrcweir 
1392cdf0e10cSrcweir ScopedFont::ScopedFont(Os2SalGraphics & rData): m_rData(rData)
1393cdf0e10cSrcweir {
1394cdf0e10cSrcweir #if 0
1395cdf0e10cSrcweir 	m_hOrigFont = m_rData.mhFonts[0];
1396cdf0e10cSrcweir 	m_rData.mhFonts[0] = 0; // avoid deletion of current font
1397cdf0e10cSrcweir #endif
1398cdf0e10cSrcweir }
1399cdf0e10cSrcweir 
1400cdf0e10cSrcweir ScopedFont::~ScopedFont()
1401cdf0e10cSrcweir {
1402cdf0e10cSrcweir #if 0
1403cdf0e10cSrcweir 	if( m_hOrigFont )
1404cdf0e10cSrcweir 	{
1405cdf0e10cSrcweir 		// restore original font, destroy temporary font
1406cdf0e10cSrcweir 		HFONT hTempFont = m_rData.mhFonts[0];
1407cdf0e10cSrcweir 		m_rData.mhFonts[0] = m_hOrigFont;
1408cdf0e10cSrcweir 		SelectObject( m_rData.mhDC, m_hOrigFont );
1409cdf0e10cSrcweir 		DeleteObject( hTempFont );
1410cdf0e10cSrcweir 	}
1411cdf0e10cSrcweir #endif
1412cdf0e10cSrcweir }
1413cdf0e10cSrcweir 
1414cdf0e10cSrcweir class ScopedTrueTypeFont
1415cdf0e10cSrcweir {
1416cdf0e10cSrcweir public:
1417cdf0e10cSrcweir 	inline ScopedTrueTypeFont(): m_pFont(0) {}
1418cdf0e10cSrcweir 
1419cdf0e10cSrcweir 	~ScopedTrueTypeFont();
1420cdf0e10cSrcweir 
1421cdf0e10cSrcweir 	int open(void * pBuffer, sal_uInt32 nLen, sal_uInt32 nFaceNum);
1422cdf0e10cSrcweir 
1423cdf0e10cSrcweir 	inline TrueTypeFont * get() const { return m_pFont; }
1424cdf0e10cSrcweir 
1425cdf0e10cSrcweir private:
1426cdf0e10cSrcweir 	TrueTypeFont * m_pFont;
1427cdf0e10cSrcweir };
1428cdf0e10cSrcweir 
1429cdf0e10cSrcweir ScopedTrueTypeFont::~ScopedTrueTypeFont()
1430cdf0e10cSrcweir {
1431cdf0e10cSrcweir 	if (m_pFont != 0)
1432cdf0e10cSrcweir 		CloseTTFont(m_pFont);
1433cdf0e10cSrcweir }
1434cdf0e10cSrcweir 
1435cdf0e10cSrcweir int ScopedTrueTypeFont::open(void * pBuffer, sal_uInt32 nLen,
1436cdf0e10cSrcweir 							 sal_uInt32 nFaceNum)
1437cdf0e10cSrcweir {
1438cdf0e10cSrcweir 	OSL_ENSURE(m_pFont == 0, "already open");
1439cdf0e10cSrcweir     return OpenTTFontBuffer(pBuffer, nLen, nFaceNum, &m_pFont);
1440cdf0e10cSrcweir }
1441cdf0e10cSrcweir 
1442cdf0e10cSrcweir BOOL Os2SalGraphics::CreateFontSubset( const rtl::OUString& rToFile,
1443cdf0e10cSrcweir 	const ImplFontData* pFont, long* pGlyphIDs, sal_uInt8* pEncoding,
1444cdf0e10cSrcweir 	sal_Int32* pGlyphWidths, int nGlyphCount, FontSubsetInfo& rInfo )
1445cdf0e10cSrcweir {
1446cdf0e10cSrcweir 	// create matching ImplFontSelectData
1447cdf0e10cSrcweir 	// we need just enough to get to the font file data
1448cdf0e10cSrcweir 	// use height=1000 for easier debugging (to match psprint's font units)
1449cdf0e10cSrcweir 	ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false );
1450cdf0e10cSrcweir 
1451cdf0e10cSrcweir 	// TODO: much better solution: move SetFont and restoration of old font to caller
1452cdf0e10cSrcweir 	ScopedFont aOldFont(*this);
1453cdf0e10cSrcweir 	SetFont( &aIFSD, 0 );
1454cdf0e10cSrcweir 
1455cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 100
1456cdf0e10cSrcweir 	// get font metrics
1457cdf0e10cSrcweir 	TEXTMETRICA aWinMetric;
1458cdf0e10cSrcweir 	if( !::GetTextMetricsA( mhDC, &aWinMetric ) )
1459cdf0e10cSrcweir 		return FALSE;
1460cdf0e10cSrcweir 
1461cdf0e10cSrcweir 	DBG_ASSERT( !(aWinMetric.tmPitchAndFamily & TMPF_DEVICE), "cannot subset device font" );
1462cdf0e10cSrcweir 	DBG_ASSERT( aWinMetric.tmPitchAndFamily & TMPF_TRUETYPE, "can only subset TT font" );
1463cdf0e10cSrcweir #endif
1464cdf0e10cSrcweir 
1465cdf0e10cSrcweir 	// get raw font file data
1466cdf0e10cSrcweir 	DWORD nFontSize1 = Ft2GetFontData( mhPS, 0, 0, NULL, 0 );
1467cdf0e10cSrcweir 	if( nFontSize1 == FT2_ERROR )
1468cdf0e10cSrcweir 		return FALSE;
1469cdf0e10cSrcweir 	ScopedCharArray xRawFontData(new char[ nFontSize1 ]);
1470cdf0e10cSrcweir 	DWORD nFontSize2 = Ft2GetFontData( mhPS, 0, 0, (void*)xRawFontData.get(), nFontSize1 );
1471cdf0e10cSrcweir 	if( nFontSize1 != nFontSize2 )
1472cdf0e10cSrcweir 		return FALSE;
1473cdf0e10cSrcweir 
1474cdf0e10cSrcweir 	// open font file
1475cdf0e10cSrcweir 	sal_uInt32 nFaceNum = 0;
1476cdf0e10cSrcweir 	if( !*xRawFontData.get() )	// TTC candidate
1477cdf0e10cSrcweir 		nFaceNum = ~0U;	 // indicate "TTC font extracts only"
1478cdf0e10cSrcweir 
1479cdf0e10cSrcweir 	ScopedTrueTypeFont aSftTTF;
1480cdf0e10cSrcweir 	int nRC = aSftTTF.open( xRawFontData.get(), nFontSize1, nFaceNum );
1481cdf0e10cSrcweir 	if( nRC != SF_OK )
1482cdf0e10cSrcweir 		return FALSE;
1483cdf0e10cSrcweir 
1484cdf0e10cSrcweir 	TTGlobalFontInfo aTTInfo;
1485cdf0e10cSrcweir 	::GetTTGlobalFontInfo( aSftTTF.get(), &aTTInfo );
1486cdf0e10cSrcweir 	rInfo.m_nFontType	= SAL_FONTSUBSETINFO_TYPE_TRUETYPE;
1487cdf0e10cSrcweir 	rInfo.m_aPSName		= ImplSalGetUniString( aTTInfo.psname );
1488cdf0e10cSrcweir 	rInfo.m_nAscent		= +aTTInfo.winAscent;
1489cdf0e10cSrcweir 	rInfo.m_nDescent	= -aTTInfo.winDescent;
1490cdf0e10cSrcweir 	rInfo.m_aFontBBox	= Rectangle( Point( aTTInfo.xMin, aTTInfo.yMin ),
1491cdf0e10cSrcweir 									Point( aTTInfo.xMax, aTTInfo.yMax ) );
1492cdf0e10cSrcweir 	rInfo.m_nCapHeight	= aTTInfo.yMax; // Well ...
1493cdf0e10cSrcweir 
1494cdf0e10cSrcweir 	// subset glyphs and get their properties
1495cdf0e10cSrcweir 	// take care that subset fonts require the NotDef glyph in pos 0
1496cdf0e10cSrcweir 	int nOrigCount = nGlyphCount;
1497cdf0e10cSrcweir 	USHORT	  aShortIDs[ 256 ];
1498cdf0e10cSrcweir 	sal_uInt8 aTempEncs[ 256 ];
1499cdf0e10cSrcweir 
1500cdf0e10cSrcweir 	int nNotDef=-1, i;
1501cdf0e10cSrcweir 	for( i = 0; i < nGlyphCount; ++i )
1502cdf0e10cSrcweir 	{
1503cdf0e10cSrcweir 		aTempEncs[i] = pEncoding[i];
1504cdf0e10cSrcweir 		sal_uInt32 nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK;
1505cdf0e10cSrcweir 		if( pGlyphIDs[i] & GF_ISCHAR )
1506cdf0e10cSrcweir 		{
1507cdf0e10cSrcweir 			bool bVertical = (pGlyphIDs[i] & GF_ROTMASK) != 0;
1508cdf0e10cSrcweir 			nGlyphIdx = ::MapChar( aSftTTF.get(), sal::static_int_cast<sal_uInt16>(nGlyphIdx), bVertical );
1509cdf0e10cSrcweir 			if( nGlyphIdx == 0 && pFont->IsSymbolFont() )
1510cdf0e10cSrcweir 			{
1511cdf0e10cSrcweir 				// #i12824# emulate symbol aliasing U+FXXX <-> U+0XXX
1512cdf0e10cSrcweir 				nGlyphIdx = pGlyphIDs[i] & GF_IDXMASK;
1513cdf0e10cSrcweir 				nGlyphIdx = (nGlyphIdx & 0xF000) ? (nGlyphIdx & 0x00FF) : (nGlyphIdx | 0xF000 );
1514cdf0e10cSrcweir 				nGlyphIdx = ::MapChar( aSftTTF.get(), sal::static_int_cast<sal_uInt16>(nGlyphIdx), bVertical );
1515cdf0e10cSrcweir 			}
1516cdf0e10cSrcweir 		}
1517cdf0e10cSrcweir 		aShortIDs[i] = static_cast<USHORT>( nGlyphIdx );
1518cdf0e10cSrcweir 		if( !nGlyphIdx )
1519cdf0e10cSrcweir 			if( nNotDef < 0 )
1520cdf0e10cSrcweir 				nNotDef = i; // first NotDef glyph found
1521cdf0e10cSrcweir 	}
1522cdf0e10cSrcweir 
1523cdf0e10cSrcweir 	if( nNotDef != 0 )
1524cdf0e10cSrcweir 	{
1525cdf0e10cSrcweir 		// add fake NotDef glyph if needed
1526cdf0e10cSrcweir 		if( nNotDef < 0 )
1527cdf0e10cSrcweir 			nNotDef = nGlyphCount++;
1528cdf0e10cSrcweir 
1529cdf0e10cSrcweir 		// NotDef glyph must be in pos 0 => swap glyphids
1530cdf0e10cSrcweir 		aShortIDs[ nNotDef ] = aShortIDs[0];
1531cdf0e10cSrcweir 		aTempEncs[ nNotDef ] = aTempEncs[0];
1532cdf0e10cSrcweir 		aShortIDs[0] = 0;
1533cdf0e10cSrcweir 		aTempEncs[0] = 0;
1534cdf0e10cSrcweir 	}
1535cdf0e10cSrcweir 	DBG_ASSERT( nGlyphCount < 257, "too many glyphs for subsetting" );
1536cdf0e10cSrcweir 
1537cdf0e10cSrcweir 	// fill pWidth array
1538cdf0e10cSrcweir 	TTSimpleGlyphMetrics* pMetrics =
1539cdf0e10cSrcweir 		::GetTTSimpleGlyphMetrics( aSftTTF.get(), aShortIDs, nGlyphCount, aIFSD.mbVertical );
1540cdf0e10cSrcweir 	if( !pMetrics )
1541cdf0e10cSrcweir 		return FALSE;
1542cdf0e10cSrcweir 	sal_uInt16 nNotDefAdv	= pMetrics[0].adv;
1543cdf0e10cSrcweir 	pMetrics[0].adv			= pMetrics[nNotDef].adv;
1544cdf0e10cSrcweir 	pMetrics[nNotDef].adv	= nNotDefAdv;
1545cdf0e10cSrcweir 	for( i = 0; i < nOrigCount; ++i )
1546cdf0e10cSrcweir 		pGlyphWidths[i] = pMetrics[i].adv;
1547cdf0e10cSrcweir 	free( pMetrics );
1548cdf0e10cSrcweir 
1549cdf0e10cSrcweir 	// write subset into destination file
1550cdf0e10cSrcweir 	rtl::OUString aSysPath;
1551cdf0e10cSrcweir 	if( osl_File_E_None != osl_getSystemPathFromFileURL( rToFile.pData, &aSysPath.pData ) )
1552cdf0e10cSrcweir 		return FALSE;
1553cdf0e10cSrcweir 	rtl_TextEncoding aThreadEncoding = osl_getThreadTextEncoding();
1554cdf0e10cSrcweir 	ByteString aToFile( rtl::OUStringToOString( aSysPath, aThreadEncoding ) );
1555cdf0e10cSrcweir 	nRC = ::CreateTTFromTTGlyphs( aSftTTF.get(), aToFile.GetBuffer(), aShortIDs,
1556cdf0e10cSrcweir 			aTempEncs, nGlyphCount, 0, NULL, 0 );
1557cdf0e10cSrcweir 	return nRC == SF_OK;
1558cdf0e10cSrcweir }
1559cdf0e10cSrcweir 
1560cdf0e10cSrcweir //--------------------------------------------------------------------------
1561cdf0e10cSrcweir 
1562cdf0e10cSrcweir const void* Os2SalGraphics::GetEmbedFontData( const ImplFontData* pFont,
1563cdf0e10cSrcweir 	const sal_Ucs* pUnicodes, sal_Int32* pCharWidths,
1564cdf0e10cSrcweir 	FontSubsetInfo& rInfo, long* pDataLen )
1565cdf0e10cSrcweir {
1566cdf0e10cSrcweir 	// create matching ImplFontSelectData
1567cdf0e10cSrcweir 	// we need just enough to get to the font file data
1568cdf0e10cSrcweir 	ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false );
1569cdf0e10cSrcweir 
1570cdf0e10cSrcweir 	// TODO: much better solution: move SetFont and restoration of old font to caller
1571cdf0e10cSrcweir 	ScopedFont aOldFont(*this);
1572cdf0e10cSrcweir 	SetFont( &aIFSD, 0 );
1573cdf0e10cSrcweir 
1574cdf0e10cSrcweir 	// get the raw font file data
1575cdf0e10cSrcweir 	DWORD nFontSize1 = Ft2GetFontData( mhPS, 0, 0, NULL, 0 );
1576cdf0e10cSrcweir 	if( nFontSize1 == FT2_ERROR || nFontSize1 <= 0 )
1577cdf0e10cSrcweir 	return NULL;
1578cdf0e10cSrcweir 	*pDataLen = nFontSize1;
1579cdf0e10cSrcweir 	void* pData = reinterpret_cast<void*>(new char[ nFontSize1 ]);
1580cdf0e10cSrcweir 	DWORD nFontSize2 = Ft2GetFontData( mhPS, 0, 0, pData, nFontSize1 );
1581cdf0e10cSrcweir 	if( nFontSize1 != nFontSize2 )
1582cdf0e10cSrcweir 		*pDataLen = 0;
1583cdf0e10cSrcweir 
1584cdf0e10cSrcweir 	// get important font properties
1585cdf0e10cSrcweir 	FONTMETRICS aOS2Metric;
1586cdf0e10cSrcweir 	if (Ft2QueryFontMetrics( mhPS, sizeof( aOS2Metric ), &aOS2Metric ) == GPI_ERROR)
1587cdf0e10cSrcweir 			*pDataLen = 0;
1588cdf0e10cSrcweir 	rInfo.m_nFontType	= SAL_FONTSUBSETINFO_TYPE_TYPE1;
1589cdf0e10cSrcweir 	rInfo.m_aPSName		= ImplSalGetUniString( aOS2Metric.szFacename );
1590cdf0e10cSrcweir 	rInfo.m_nAscent		= +aOS2Metric.lMaxAscender;
1591cdf0e10cSrcweir 	rInfo.m_nDescent	= -aOS2Metric.lMaxDescender;
1592cdf0e10cSrcweir 	rInfo.m_aFontBBox	= Rectangle( Point( 0, -aOS2Metric.lMaxDescender ),
1593cdf0e10cSrcweir 			  Point( aOS2Metric.lMaxCharInc, aOS2Metric.lMaxAscender+aOS2Metric.lExternalLeading ) );
1594cdf0e10cSrcweir 	rInfo.m_nCapHeight	= aOS2Metric.lMaxAscender; // Well ...
1595cdf0e10cSrcweir 
1596cdf0e10cSrcweir 	// get individual character widths
1597cdf0e10cSrcweir 	for( int i = 0; i < 256; ++i )
1598cdf0e10cSrcweir 	{
1599cdf0e10cSrcweir 		LONG nCharWidth = 0;
1600cdf0e10cSrcweir 		const sal_Ucs cChar = pUnicodes[i];
1601cdf0e10cSrcweir 		if( !Ft2QueryStringWidthW( mhPS, (LPWSTR)&cChar, 1, &nCharWidth ) )
1602cdf0e10cSrcweir 			*pDataLen = 0;
1603cdf0e10cSrcweir 		pCharWidths[i] = nCharWidth;
1604cdf0e10cSrcweir 	}
1605cdf0e10cSrcweir 
1606cdf0e10cSrcweir 	if( !*pDataLen )
1607cdf0e10cSrcweir 	{
1608cdf0e10cSrcweir 		FreeEmbedFontData( pData, nFontSize1 );
1609cdf0e10cSrcweir 		pData = NULL;
1610cdf0e10cSrcweir 	}
1611cdf0e10cSrcweir 
1612cdf0e10cSrcweir 	return pData;
1613cdf0e10cSrcweir }
1614cdf0e10cSrcweir 
1615cdf0e10cSrcweir //--------------------------------------------------------------------------
1616cdf0e10cSrcweir 
1617cdf0e10cSrcweir void Os2SalGraphics::FreeEmbedFontData( const void* pData, long /*nLen*/ )
1618cdf0e10cSrcweir {
1619cdf0e10cSrcweir 	delete[] reinterpret_cast<char*>(const_cast<void*>(pData));
1620cdf0e10cSrcweir }
1621cdf0e10cSrcweir 
1622cdf0e10cSrcweir const Ucs2SIntMap* Os2SalGraphics::GetFontEncodingVector( const ImplFontData* pFont, const Ucs2OStrMap** pNonEncoded )
1623cdf0e10cSrcweir {
1624cdf0e10cSrcweir 	// TODO: even for builtin fonts we get here... why?
1625cdf0e10cSrcweir 	if( !pFont->IsEmbeddable() )
1626cdf0e10cSrcweir 		return NULL;
1627cdf0e10cSrcweir 
1628cdf0e10cSrcweir 	// fill the encoding vector
1629cdf0e10cSrcweir 	Ucs2SIntMap& rMap = *new Ucs2SIntMap;
1630cdf0e10cSrcweir #if 0
1631cdf0e10cSrcweir 	// TODO: get correct encoding vector
1632cdf0e10cSrcweir 	ImplWinFontData* pWinFontData = reinterpret_cast<ImplWinFontData*>(pFont);
1633cdf0e10cSrcweir 
1634cdf0e10cSrcweir 	GLYPHSET aGlyphSet;
1635cdf0e10cSrcweir 	aGlyphSet.cbThis = sizeof(aGlyphSet);
1636cdf0e10cSrcweir 	DWORD aW = ::GetFontUnicodeRanges( mhDC, &aGlyphSet);
1637cdf0e10cSrcweir #else
1638cdf0e10cSrcweir 	for( sal_Unicode i = 32; i < 256; ++i )
1639cdf0e10cSrcweir 		rMap[i] = i;
1640cdf0e10cSrcweir 	if( pNonEncoded )
1641cdf0e10cSrcweir 		*pNonEncoded = NULL;
1642cdf0e10cSrcweir #endif
1643cdf0e10cSrcweir 
1644cdf0e10cSrcweir 	return &rMap;
1645cdf0e10cSrcweir }
1646cdf0e10cSrcweir 
1647cdf0e10cSrcweir //--------------------------------------------------------------------------
1648cdf0e10cSrcweir 
1649cdf0e10cSrcweir void Os2SalGraphics::GetGlyphWidths( const ImplFontData* pFont,
1650cdf0e10cSrcweir                                      bool bVertical,
1651cdf0e10cSrcweir                                      Int32Vector& rWidths,
1652cdf0e10cSrcweir                                      Ucs2UIntMap& rUnicodeEnc )
1653cdf0e10cSrcweir {
1654cdf0e10cSrcweir     // create matching ImplFontSelectData
1655cdf0e10cSrcweir     // we need just enough to get to the font file data
1656cdf0e10cSrcweir     ImplFontSelectData aIFSD( *pFont, Size(0,1000), 1000.0, 0, false );
1657cdf0e10cSrcweir 
1658cdf0e10cSrcweir     // TODO: much better solution: move SetFont and restoration of old font to caller
1659cdf0e10cSrcweir     ScopedFont aOldFont(*this);
1660cdf0e10cSrcweir 
1661cdf0e10cSrcweir     float fScale = 0.0;
1662cdf0e10cSrcweir     ImplDoSetFont( &aIFSD, fScale, 0);
1663cdf0e10cSrcweir 
1664cdf0e10cSrcweir     if( pFont->IsSubsettable() )
1665cdf0e10cSrcweir     {
1666cdf0e10cSrcweir         // get raw font file data
1667cdf0e10cSrcweir         DWORD nFontSize1 = ::Ft2GetFontData( mhPS, 0, 0, NULL, 0 );
1668cdf0e10cSrcweir         if( nFontSize1 == FT2_ERROR )
1669cdf0e10cSrcweir             return;
1670cdf0e10cSrcweir         ScopedCharArray xRawFontData(new char[ nFontSize1 ]);
1671cdf0e10cSrcweir         DWORD nFontSize2 = ::Ft2GetFontData( mhPS, 0, 0, (void*)xRawFontData.get(), nFontSize1 );
1672cdf0e10cSrcweir         if( nFontSize1 != nFontSize2 )
1673cdf0e10cSrcweir             return;
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir         // open font file
1676cdf0e10cSrcweir         sal_uInt32 nFaceNum = 0;
1677cdf0e10cSrcweir         if( !*xRawFontData.get() )  // TTC candidate
1678cdf0e10cSrcweir             nFaceNum = ~0U;  // indicate "TTC font extracts only"
1679cdf0e10cSrcweir 
1680cdf0e10cSrcweir         ScopedTrueTypeFont aSftTTF;
1681cdf0e10cSrcweir         int nRC = aSftTTF.open( xRawFontData.get(), nFontSize1, nFaceNum );
1682cdf0e10cSrcweir         if( nRC != SF_OK )
1683cdf0e10cSrcweir             return;
1684cdf0e10cSrcweir 
1685cdf0e10cSrcweir         int nGlyphs = GetTTGlyphCount( aSftTTF.get() );
1686cdf0e10cSrcweir         if( nGlyphs > 0 )
1687cdf0e10cSrcweir         {
1688cdf0e10cSrcweir             rWidths.resize(nGlyphs);
1689cdf0e10cSrcweir             std::vector<sal_uInt16> aGlyphIds(nGlyphs);
1690cdf0e10cSrcweir             for( int i = 0; i < nGlyphs; i++ )
1691cdf0e10cSrcweir                 aGlyphIds[i] = sal_uInt16(i);
1692cdf0e10cSrcweir             TTSimpleGlyphMetrics* pMetrics = ::GetTTSimpleGlyphMetrics( aSftTTF.get(),
1693cdf0e10cSrcweir                                                                         &aGlyphIds[0],
1694cdf0e10cSrcweir                                                                         nGlyphs,
1695cdf0e10cSrcweir                                                                         bVertical ? 1 : 0 );
1696cdf0e10cSrcweir             if( pMetrics )
1697cdf0e10cSrcweir             {
1698cdf0e10cSrcweir                 for( int i = 0; i< nGlyphs; i++ )
1699cdf0e10cSrcweir                     rWidths[i] = pMetrics[i].adv;
1700cdf0e10cSrcweir                 free( pMetrics );
1701cdf0e10cSrcweir                 rUnicodeEnc.clear();
1702cdf0e10cSrcweir             }
1703cdf0e10cSrcweir             const ImplOs2FontData* pWinFont = static_cast<const ImplOs2FontData*>(pFont);
1704cdf0e10cSrcweir             const ImplFontCharMap* pMap = pWinFont->GetImplFontCharMap();
1705cdf0e10cSrcweir 			DBG_ASSERT( pMap && pMap->GetCharCount(), "no map" );
1706cdf0e10cSrcweir 
1707cdf0e10cSrcweir 			int nCharCount = pMap->GetCharCount();
1708cdf0e10cSrcweir             sal_uInt32 nChar = pMap->GetFirstChar();
1709cdf0e10cSrcweir 			for( int i = 0; i < nCharCount; i++ )
1710cdf0e10cSrcweir             {
1711cdf0e10cSrcweir                 if( nChar < 0x00010000 )
1712cdf0e10cSrcweir                 {
1713cdf0e10cSrcweir                     sal_uInt16 nGlyph = ::MapChar( aSftTTF.get(),
1714cdf0e10cSrcweir                                                    static_cast<sal_uInt16>(nChar),
1715cdf0e10cSrcweir                                                    bVertical ? 1 : 0 );
1716cdf0e10cSrcweir                     if( nGlyph )
1717cdf0e10cSrcweir                         rUnicodeEnc[ static_cast<sal_Unicode>(nChar) ] = nGlyph;
1718cdf0e10cSrcweir                 }
1719cdf0e10cSrcweir 				nChar = pMap->GetNextChar( nChar );
1720cdf0e10cSrcweir             }
1721cdf0e10cSrcweir         }
1722cdf0e10cSrcweir     }
1723cdf0e10cSrcweir     else if( pFont->IsEmbeddable() )
1724cdf0e10cSrcweir     {
1725cdf0e10cSrcweir         // get individual character widths
1726cdf0e10cSrcweir         rWidths.clear();
1727cdf0e10cSrcweir         rUnicodeEnc.clear();
1728cdf0e10cSrcweir         rWidths.reserve( 224 );
1729cdf0e10cSrcweir         for( sal_Unicode i = 32; i < 256; ++i )
1730cdf0e10cSrcweir         {
1731cdf0e10cSrcweir             int nCharWidth = 0;
1732cdf0e10cSrcweir             if( Ft2QueryStringWidthW( mhPS, (LPWSTR)&i, 1, (LONG*)&nCharWidth ) )
1733cdf0e10cSrcweir             {
1734cdf0e10cSrcweir                 rUnicodeEnc[ i ] = rWidths.size();
1735cdf0e10cSrcweir                 rWidths.push_back( nCharWidth );
1736cdf0e10cSrcweir             }
1737cdf0e10cSrcweir         }
1738cdf0e10cSrcweir     }
1739cdf0e10cSrcweir }
1740cdf0e10cSrcweir 
1741cdf0e10cSrcweir //--------------------------------------------------------------------------
1742cdf0e10cSrcweir 
1743cdf0e10cSrcweir void Os2SalGraphics::DrawServerFontLayout( const ServerFontLayout& )
1744cdf0e10cSrcweir {}
1745cdf0e10cSrcweir 
1746cdf0e10cSrcweir //--------------------------------------------------------------------------
1747cdf0e10cSrcweir 
1748cdf0e10cSrcweir SystemFontData Os2SalGraphics::GetSysFontData( int nFallbacklevel ) const
1749cdf0e10cSrcweir {
1750cdf0e10cSrcweir     SystemFontData aSysFontData;
1751cdf0e10cSrcweir 
1752cdf0e10cSrcweir     if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1;
1753cdf0e10cSrcweir     if (nFallbacklevel < 0 ) nFallbacklevel = 0;
1754cdf0e10cSrcweir 
1755cdf0e10cSrcweir     aSysFontData.nSize = sizeof( SystemFontData );
1756cdf0e10cSrcweir     aSysFontData.hFont = mhFonts[nFallbacklevel];
1757cdf0e10cSrcweir     aSysFontData.bFakeBold = false;
1758cdf0e10cSrcweir     aSysFontData.bFakeItalic = false;
1759cdf0e10cSrcweir     aSysFontData.bAntialias = true;
1760cdf0e10cSrcweir     aSysFontData.bVerticalCharacterType = false;
1761cdf0e10cSrcweir 
1762cdf0e10cSrcweir     return aSysFontData;
1763cdf0e10cSrcweir }
1764cdf0e10cSrcweir 
1765cdf0e10cSrcweir //--------------------------------------------------------------------------
1766