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