1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salgdi3.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #define INCL_GRE_STRINGS
40 #define _SV_SALGDI3_CXX
41 #include <tools/svwin.h>
42 #include <rtl/tencinfo.h>
44 #include <osl/file.hxx>
46 #ifndef _OSL_THREAD_HXX
47 #include <osl/thread.hxx>
49 #ifndef _OSL_PROCESS_HXX
50 #include <osl/process.h>
52 #include <vcl/svapp.hxx>
53 #include <saldata.hxx>
55 #include <vcl/font.hxx>
56 #include <vcl/sallayout.hxx>
57 #include <tools/poly.hxx>
58 #include <tools/debug.hxx>
59 #include <rtl/textcvt.h>
60 #include <tools/debug.hxx>
61 #include <saldata.hxx>
63 #ifndef _SV_OUTFONT_HXX
64 #include <vcl/outfont.hxx>
66 #include <sallayout.h>
67 #include <tools/poly.hxx>
68 #include <basegfx/polygon/b2dpolygon.hxx>
69 #include <basegfx/polygon/b2dpolypolygon.hxx>
70 #include <basegfx/matrix/b2dhommatrix.hxx>
90 inline W32FIXED
FixedFromDouble( double d
)
92 const long l
= (long) ( d
* 65536. );
93 return *(W32FIXED
*) &l
;
96 // -----------------------------------------------------------------------
98 inline int IntTimes256FromFixed(W32FIXED f
)
100 int nFixedTimes256
= (f
.value
<< 8) + ((f
.fract
+0x80) >> 8);
101 return nFixedTimes256
;
108 // this is a special codepage code, used to identify OS/2 symbol font.
109 #define SYMBOL_CHARSET 65400
111 // =======================================================================
113 UniString
ImplSalGetUniString( const sal_Char
* pStr
, xub_StrLen nLen
= STRING_LEN
)
115 return UniString( pStr
, nLen
, gsl_getSystemTextEncoding(),
116 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT
|
117 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT
|
118 RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT
);
121 // =======================================================================
123 static USHORT
ImplSalToCharSet( CharSet eCharSet
)
125 // !!! Fuer DBCS-Systeme muss dieser Code auskommentiert werden und 0
126 // !!! zurueckgegeben werden, solange die DBCS-Charsets nicht
127 // !!! durchgereicht werden
131 case RTL_TEXTENCODING_IBM_437
:
134 case RTL_TEXTENCODING_IBM_850
:
137 case RTL_TEXTENCODING_IBM_860
:
140 case RTL_TEXTENCODING_IBM_861
:
143 case RTL_TEXTENCODING_IBM_863
:
146 case RTL_TEXTENCODING_IBM_865
:
148 case RTL_TEXTENCODING_MS_1252
:
150 case RTL_TEXTENCODING_SYMBOL
:
157 // -----------------------------------------------------------------------
159 static CharSet
ImplCharSetToSal( USHORT usCodePage
)
161 switch ( usCodePage
)
164 return RTL_TEXTENCODING_IBM_437
;
167 return RTL_TEXTENCODING_IBM_850
;
170 return RTL_TEXTENCODING_IBM_860
;
173 return RTL_TEXTENCODING_IBM_861
;
176 return RTL_TEXTENCODING_IBM_863
;
179 return RTL_TEXTENCODING_IBM_865
;
181 return RTL_TEXTENCODING_MS_1252
;
183 return RTL_TEXTENCODING_SYMBOL
;
186 return RTL_TEXTENCODING_DONTKNOW
;
189 // -----------------------------------------------------------------------
191 static FontFamily
ImplFamilyToSal( BYTE bFamilyType
)
193 switch ( bFamilyType
)
196 return FAMILY_DECORATIVE
;
198 return FAMILY_SCRIPT
;
201 return FAMILY_DONTKNOW
;
204 // -----------------------------------------------------------------------
206 static FontWeight
ImplWeightToSal( USHORT nWeight
)
208 // Falls sich jemand an die alte Doku gehalten hat
218 return WEIGHT_ULTRALIGHT
;
224 return WEIGHT_SEMILIGHT
;
227 return WEIGHT_NORMAL
;
230 return WEIGHT_SEMIBOLD
;
236 return WEIGHT_ULTRABOLD
;
242 return WEIGHT_DONTKNOW
;
245 // -----------------------------------------------------------------------
247 static UniString
ImpStyleNameToSal( const char* pFamilyName
,
248 const char* pFaceName
,
252 nLen
= strlen(pFamilyName
);
254 // strip FamilyName from FaceName
255 if ( strncmp( pFamilyName
, pFaceName
, nLen
) == 0 )
257 USHORT nFaceLen
= (USHORT
)strlen( pFaceName
+nLen
);
258 // Ist Facename laenger, schneiden wir den FamilyName ab
260 return UniString( pFaceName
+(nLen
+1), gsl_getSystemTextEncoding());
265 return UniString( pFaceName
, gsl_getSystemTextEncoding());
268 // -----------------------------------------------------------------------
270 inline FontPitch
ImplLogPitchToSal( BYTE fsType
)
272 if ( fsType
& FM_TYPE_FIXED
)
275 return PITCH_VARIABLE
;
278 // -----------------------------------------------------------------------
280 inline BYTE
ImplPitchToWin( FontPitch ePitch
)
282 if ( ePitch
== PITCH_FIXED
)
283 return FM_TYPE_FIXED
;
284 //else if ( ePitch == PITCH_VARIABLE )
289 // -----------------------------------------------------------------------
291 static ImplDevFontAttributes
Os2Font2DevFontAttributes( const PFONTMETRICS pFontMetric
)
293 ImplDevFontAttributes aDFA
;
295 // get font face attributes
296 aDFA
.meFamily
= ImplFamilyToSal( pFontMetric
->panose
.bFamilyType
);
297 aDFA
.meWidthType
= WIDTH_DONTKNOW
;
298 aDFA
.meWeight
= ImplWeightToSal( pFontMetric
->usWeightClass
);
299 aDFA
.meItalic
= (pFontMetric
->fsSelection
& FM_SEL_ITALIC
) ? ITALIC_NORMAL
: ITALIC_NONE
;
300 aDFA
.mePitch
= ImplLogPitchToSal( pFontMetric
->fsType
);
301 aDFA
.mbSymbolFlag
= (pFontMetric
->usCodePage
== SYMBOL_CHARSET
);
303 // get the font face name
304 // the maName field stores the font name without the style, so under OS/2
305 // we must use the family name
306 aDFA
.maName
= UniString( pFontMetric
->szFamilyname
, gsl_getSystemTextEncoding());
308 aDFA
.maStyleName
= ImpStyleNameToSal( pFontMetric
->szFamilyname
,
309 pFontMetric
->szFacename
,
310 strlen( pFontMetric
->szFamilyname
) );
312 // get device specific font attributes
313 aDFA
.mbOrientation
= (pFontMetric
->fsDefn
& FM_DEFN_OUTLINE
) != 0;
314 aDFA
.mbDevice
= (pFontMetric
->fsDefn
& FM_DEFN_GENERIC
) ? FALSE
: TRUE
;
316 aDFA
.mbEmbeddable
= false;
317 aDFA
.mbSubsettable
= false;
318 DWORD fontType
= Ft2QueryFontType( 0, pFontMetric
->szFamilyname
);
319 if( fontType
== FT2_FONTTYPE_TRUETYPE
&& !aDFA
.mbDevice
)
320 aDFA
.mbSubsettable
= true;
321 // for now we can only embed Type1 fonts
322 if( fontType
== FT2_FONTTYPE_TYPE1
)
323 aDFA
.mbEmbeddable
= true;
325 // heuristics for font quality
326 // - standard-type1 > opentypeTT > truetype > non-standard-type1 > raster
327 // - subsetting > embedding > none
329 if( fontType
== FT2_FONTTYPE_TRUETYPE
)
330 aDFA
.mnQuality
+= 50;
331 if( aDFA
.mbSubsettable
)
332 aDFA
.mnQuality
+= 200;
333 else if( aDFA
.mbEmbeddable
)
334 aDFA
.mnQuality
+= 100;
336 // #i38665# prefer Type1 versions of the standard postscript fonts
337 if( aDFA
.mbEmbeddable
)
339 if( aDFA
.maName
.EqualsAscii( "AvantGarde" )
340 || aDFA
.maName
.EqualsAscii( "Bookman" )
341 || aDFA
.maName
.EqualsAscii( "Courier" )
342 || aDFA
.maName
.EqualsAscii( "Helvetica" )
343 || aDFA
.maName
.EqualsAscii( "NewCenturySchlbk" )
344 || aDFA
.maName
.EqualsAscii( "Palatino" )
345 || aDFA
.maName
.EqualsAscii( "Symbol" )
346 || aDFA
.maName
.EqualsAscii( "Times" )
347 || aDFA
.maName
.EqualsAscii( "ZapfChancery" )
348 || aDFA
.maName
.EqualsAscii( "ZapfDingbats" ) )
349 aDFA
.mnQuality
+= 500;
352 aDFA
.meEmbeddedBitmap
= EMBEDDEDBITMAP_DONTKNOW
;
353 aDFA
.meAntiAlias
= ANTIALIAS_DONTKNOW
;
355 // TODO: add alias names
360 // =======================================================================
362 // -----------------------------------------------------------------------
364 // =======================================================================
366 ImplOs2FontData::ImplOs2FontData( PFONTMETRICS _pFontMetric
,
367 int nHeight
, BYTE nPitchAndFamily
)
368 : ImplFontData( Os2Font2DevFontAttributes(_pFontMetric
), 0 ),
369 pFontMetric( _pFontMetric
),
370 meOs2CharSet( _pFontMetric
->usCodePage
),
371 mnPitchAndFamily( nPitchAndFamily
),
372 mpFontCharSets( NULL
),
373 mpUnicodeMap( NULL
),
374 mbDisableGlyphApi( false ),
375 mbHasKoreanRange( false ),
376 mbHasCJKSupport( false ),
377 mbAliasSymbolsLow( false ),
378 mbAliasSymbolsHigh( false ),
381 SetBitmapSize( 0, nHeight
);
384 // -----------------------------------------------------------------------
386 ImplOs2FontData::~ImplOs2FontData()
388 delete[] mpFontCharSets
;
391 mpUnicodeMap
->DeReference();
394 // -----------------------------------------------------------------------
396 sal_IntPtr
ImplOs2FontData::GetFontId() const
401 // -----------------------------------------------------------------------
403 void ImplOs2FontData::UpdateFromHPS( HPS hPS
) const
405 // short circuit if already initialized
406 if( mpUnicodeMap
!= NULL
)
409 ReadCmapTable( hPS
);
412 // even if the font works some fonts have problems with the glyph API
413 // => the heuristic below tries to figure out which fonts have the problem
414 DWORD fontType
= Ft2QueryFontType( 0, pFontMetric
->szFacename
);
415 if( fontType
!= FT2_FONTTYPE_TRUETYPE
416 && (pFontMetric
->fsDefn
& FM_DEFN_GENERIC
) == 0)
417 mbDisableGlyphApi
= true;
420 // -----------------------------------------------------------------------
423 bool ImplOs2FontData::HasGSUBstitutions( HPS hPS
) const
426 ReadGsubTable( hPS
);
427 return !maGsubTable
.empty();
430 // -----------------------------------------------------------------------
432 bool ImplOs2FontData::IsGSUBstituted( sal_Ucs cChar
) const
434 return( maGsubTable
.find( cChar
) != maGsubTable
.end() );
436 #endif // GNG_VERT_HACK
438 // -----------------------------------------------------------------------
440 ImplFontCharMap
* ImplOs2FontData::GetImplFontCharMap() const
442 mpUnicodeMap
->AddReference();
446 // -----------------------------------------------------------------------
448 static unsigned GetUInt( const unsigned char* p
) { return((p
[0]<<24)+(p
[1]<<16)+(p
[2]<<8)+p
[3]);}
449 static unsigned GetUShort( const unsigned char* p
){ return((p
[0]<<8)+p
[1]);}
450 static signed GetSShort( const unsigned char* p
){ return((short)((p
[0]<<8)+p
[1]));}
451 static inline DWORD
CalcTag( const char p
[4]) { return (p
[0]+(p
[1]<<8)+(p
[2]<<16)+(p
[3]<<24)); }
453 void ImplOs2FontData::ReadOs2Table( HPS hPS
) const
455 const DWORD Os2Tag
= CalcTag( "OS/2" );
456 DWORD nLength
= Ft2GetFontData( hPS
, Os2Tag
, 0, NULL
, 0 );
457 if( (nLength
== FT2_ERROR
) || !nLength
)
459 std::vector
<unsigned char> aOS2map( nLength
);
460 unsigned char* pOS2map
= &aOS2map
[0];
461 DWORD nRC
= Ft2GetFontData( hPS
, Os2Tag
, 0, pOS2map
, nLength
);
462 sal_uInt32 nVersion
= GetUShort( pOS2map
);
463 if ( nVersion
>= 0x0001 && nLength
>= 58 )
465 // We need at least version 0x0001 (TrueType rev 1.66)
466 // to have access to the needed struct members.
467 sal_uInt32 ulUnicodeRange1
= GetUInt( pOS2map
+ 42 );
468 sal_uInt32 ulUnicodeRange2
= GetUInt( pOS2map
+ 46 );
469 sal_uInt32 ulUnicodeRange3
= GetUInt( pOS2map
+ 50 );
470 sal_uInt32 ulUnicodeRange4
= GetUInt( pOS2map
+ 54 );
472 // Check for CJK capabilities of the current font
473 mbHasCJKSupport
= (ulUnicodeRange2
& 0x2fff0000)
474 | (ulUnicodeRange3
& 0x00000001);
475 mbHasKoreanRange
= (ulUnicodeRange1
& 0x10000000)
476 | (ulUnicodeRange2
& 0x01100000);
481 // -----------------------------------------------------------------------
484 void ImplOs2FontData::ReadGsubTable( HPS hPS
) const
488 // check the existence of a GSUB table
489 const DWORD GsubTag
= CalcTag( "GSUB" );
490 DWORD nRC
= Ft2GetFontData( hPS
, GsubTag
, 0, NULL
, 0 );
491 if( (nRC
== FT2_ERROR
) || !nRC
)
494 // TODO: directly read the GSUB table instead of going through sft
496 // get raw font file data
497 DWORD nFontSize
= Ft2GetFontData( hPS
, 0, 0, NULL
, 0 );
498 if( nFontSize
== FT2_ERROR
)
500 std::vector
<char> aRawFont( nFontSize
+1 );
501 aRawFont
[ nFontSize
] = 0;
502 DWORD nFontSize2
= Ft2GetFontData( hPS
, 0, 0, (void*)&aRawFont
[0], nFontSize
);
503 if( nFontSize
!= nFontSize2
)
507 sal_uInt32 nFaceNum
= 0;
508 if( !aRawFont
[0] ) // TTC candidate
509 nFaceNum
= ~0U; // indicate "TTC font extracts only"
511 TrueTypeFont
* pTTFont
= NULL
;
512 ::OpenTTFontBuffer( &aRawFont
[0], nFontSize
, nFaceNum
, &pTTFont
);
516 // add vertically substituted characters to list
517 static const sal_Unicode aGSUBCandidates
[] = {
518 0x0020, 0x0080, // ASCII
519 0x2000, 0x2600, // misc
520 0x3000, 0x3100, // CJK punctutation
521 0x3300, 0x3400, // squared words
522 0xFF00, 0xFFF0, // halfwidth|fullwidth forms
525 for( const sal_Unicode
* pPair
= aGSUBCandidates
; *pPair
; pPair
+= 2 )
526 for( sal_Unicode cChar
= pPair
[0]; cChar
< pPair
[1]; ++cChar
)
527 if( ::MapChar( pTTFont
, cChar
, 0 ) != ::MapChar( pTTFont
, cChar
, 1 ) )
528 maGsubTable
.insert( cChar
); // insert GSUBbed unicodes
530 CloseTTFont( pTTFont
);
533 TrueTypeFont
* pTTFont
= NULL
;
534 ::OpenTTFont( &aRawFont
[0], nFontSize
, nFaceNum
, &pTTFont
);
538 // add vertically substituted characters to list
539 static const sal_Unicode aGSUBCandidates
[] = {
540 0x0020, 0x0080, // ASCII
541 0x2000, 0x2600, // misc
542 0x3000, 0x3100, // CJK punctutation
543 0x3300, 0x3400, // squared words
544 0xFF00, 0xFFF0, // halfwidth|fullwidth forms
547 for( const sal_Unicode
* pPair
= aGSUBCandidates
; *pPair
; pPair
+= 2 )
548 for( sal_Unicode cChar
= pPair
[0]; cChar
< pPair
[1]; ++cChar
)
549 if( ::MapChar( pTTFont
, cChar
, 0 ) != ::MapChar( pTTFont
, cChar
, 1 ) )
550 maGsubTable
.insert( cChar
); // insert GSUBbed unicodes
552 CloseTTFont( pTTFont
);
555 #endif // GNG_VERT_HACK
557 // -----------------------------------------------------------------------
559 void ImplOs2FontData::ReadCmapTable( HPS hPS
) const
562 aResult
.mnPairCount
= 0;
563 aResult
.mbSymbolic
= (meOs2CharSet
== SYMBOL_CHARSET
);
564 aResult
.mbRecoded
= true;
566 // get the CMAP table from the font which is selected into the DC
567 const DWORD CmapTag
= CalcTag( "cmap" );
568 DWORD nRC
= Ft2GetFontData( hPS
, CmapTag
, 0, NULL
, 0 );
569 // read the CMAP table if available
570 if( nRC
!= FT2_ERROR
)
572 const int nLength
= nRC
;
573 std::vector
<unsigned char> aCmap( nLength
);
574 unsigned char* pCmap
= &aCmap
[0];
575 nRC
= Ft2GetFontData( hPS
, CmapTag
, 0, pCmap
, nLength
);
576 // parse the CMAP table
578 ParseCMAP( pCmap
, nLength
, aResult
);
580 // we need to define at least a simple charmap, otherwise this font
581 // will be mapped to default charmap, and OOo doesn't accept the
582 // system font to match the default charmap
583 aResult
.mnPairCount
= 1;
584 // ImplFontCharMap destructor will free this memory
585 aResult
.mpPairCodes
= new sal_uInt32
[ 2 * aResult
.mnPairCount
];
586 aResult
.mpPairCodes
[0] = 0x0020;
587 aResult
.mpPairCodes
[1] = 0x00FF;
588 aResult
.mpStartGlyphs
= NULL
;
591 mbDisableGlyphApi
|= aResult
.mbRecoded
;
593 if( aResult
.mnPairCount
> 0 )
594 mpUnicodeMap
= new ImplFontCharMap( aResult
.mnPairCount
,
595 aResult
.mpPairCodes
, aResult
.mpStartGlyphs
);
597 mpUnicodeMap
= ImplFontCharMap::GetDefaultMap();
600 // =======================================================================
602 void Os2SalGraphics::SetTextColor( SalColor nSalColor
)
606 cb
.lColor
= RGBCOLOR( SALCOLOR_RED( nSalColor
),
607 SALCOLOR_GREEN( nSalColor
),
608 SALCOLOR_BLUE( nSalColor
) );
610 // set default color attributes
618 // -----------------------------------------------------------------------
620 USHORT
Os2SalGraphics::ImplDoSetFont( ImplFontSelectData
* i_pFont
, float& o_rFontScale
, int nFallbackLevel
)
623 #if OSL_DEBUG_LEVEL>10
624 debug_printf( "Os2SalGraphics::ImplDoSetFont\n");
627 ImplOs2FontData
* pFontData
= (ImplOs2FontData
*)i_pFont
->mpFontData
;
628 PFONTMETRICS pFontMetric
= NULL
;
630 BOOL bOutline
= FALSE
;
633 memset( &aFAttrs
, 0, sizeof( FATTRS
) );
634 aFAttrs
.usRecordLength
= sizeof( FATTRS
);
636 aFAttrs
.lMaxBaselineExt
= i_pFont
->mnHeight
;
637 aFAttrs
.lAveCharWidth
= i_pFont
->mnWidth
;
639 // do we have a pointer to the FONTMETRICS of the selected font? -> use it!
642 pFontMetric
= pFontData
->GetFontMetrics();
644 bOutline
= (pFontMetric
->fsDefn
& FM_DEFN_OUTLINE
) != 0;
646 // use match®istry fields to get correct match
647 aFAttrs
.lMatch
= pFontMetric
->lMatch
;
648 aFAttrs
.idRegistry
= pFontMetric
->idRegistry
;
649 aFAttrs
.usCodePage
= pFontMetric
->usCodePage
;
653 aFAttrs
.fsFontUse
|= FATTR_FONTUSE_OUTLINE
;
654 if ( i_pFont
->mnOrientation
)
655 aFAttrs
.fsFontUse
|= FATTR_FONTUSE_TRANSFORMABLE
;
659 aFAttrs
.lMaxBaselineExt
= pFontMetric
->lMaxBaselineExt
;
660 aFAttrs
.lAveCharWidth
= pFontMetric
->lAveCharWidth
;
665 // use family name for outline fonts
667 // use font face name for printers because otherwise ft2lib will fail
668 // to select the correct font for GPI (ticket#117)
669 strncpy( (char*)(aFAttrs
.szFacename
), pFontMetric
->szFacename
, sizeof( aFAttrs
.szFacename
) );
670 } else if ( !pFontMetric
) {
671 // use OOo name if fontmetrics not available!
672 ByteString
aName( i_pFont
->maName
.GetToken( 0 ), gsl_getSystemTextEncoding());
673 strncpy( (char*)(aFAttrs
.szFacename
), aName
.GetBuffer(), sizeof( aFAttrs
.szFacename
) );
674 } else if ( bOutline
) {
675 // use fontmetric family name for outline fonts
676 strncpy( (char*)(aFAttrs
.szFacename
), pFontMetric
->szFamilyname
, sizeof( aFAttrs
.szFacename
) );
678 // use real font face name for bitmaps (WarpSans only)
679 strncpy( (char*)(aFAttrs
.szFacename
), pFontMetric
->szFacename
, sizeof( aFAttrs
.szFacename
) );
682 if ( i_pFont
->meItalic
!= ITALIC_NONE
)
683 aFAttrs
.fsSelection
|= FATTR_SEL_ITALIC
;
684 if ( i_pFont
->meWeight
> WEIGHT_MEDIUM
)
685 aFAttrs
.fsSelection
|= FATTR_SEL_BOLD
;
687 #if OSL_DEBUG_LEVEL>1
688 if (pFontMetric
->szFacename
[0] == 'A') {
689 debug_printf( "Os2SalGraphics::SetFont hps %x lMatch '%d'\n", mhPS
, pFontMetric
->lMatch
);
690 debug_printf( "Os2SalGraphics::SetFont hps %x fontmetrics facename '%s'\n", mhPS
, pFontMetric
->szFacename
);
691 debug_printf( "Os2SalGraphics::SetFont hps %x fattrs facename '%s'\n", mhPS
, aFAttrs
.szFacename
);
695 Ft2DeleteSetId( mhPS
, nFallbackLevel
+ LCID_BASE
);
696 if ( (rc
=Ft2CreateLogFont( mhPS
, NULL
, nFallbackLevel
+ LCID_BASE
, &aFAttrs
)) == GPI_ERROR
) {
697 #if OSL_DEBUG_LEVEL>1
698 ERRORID nLastError
= WinGetLastError( GetSalData()->mhAB
);
699 debug_printf( "Os2SalGraphics::SetFont hps %x Ft2CreateLogFont failed err %x\n", mhPS
, nLastError
);
701 return SAL_SETFONT_REMOVEANDMATCHNEW
;
706 ULONG nAttrsDefault
= 0;
707 ULONG nAttrs
= CBB_SET
;
708 aBundle
.usSet
= nFallbackLevel
+ LCID_BASE
;
713 aBundle
.sizfxCell
.cy
= MAKEFIXED( i_pFont
->mnHeight
, 0 );
715 if ( !i_pFont
->mnWidth
)
721 // Auf die Aufloesung achten, damit das Ergebnis auch auf
722 // Drucken mit 180*360 DPI stimmt. Ausserdem muss gerundet
723 // werden, da auf meinem OS2 beispielsweise als
724 // Bildschirmaufloesung 3618*3622 PixelPerMeter zurueck-
726 GetResolution( nXFontRes
, nYFontRes
);
727 nHeight
= i_pFont
->mnHeight
;
728 nHeight
*= nXFontRes
;
729 nHeight
+= nYFontRes
/2;
730 nHeight
/= nYFontRes
;
731 aBundle
.sizfxCell
.cx
= MAKEFIXED( nHeight
, 0 );
734 aBundle
.sizfxCell
.cx
= MAKEFIXED( i_pFont
->mnWidth
, 0 );
737 // set orientation for outlinefonts
738 if ( i_pFont
->mnOrientation
)
743 double alpha
= (double)(i_pFont
->mnOrientation
);
744 alpha
*= 0.0017453292; // *PI / 1800
745 mnOrientationY
= (long) (1000.0 * sin( alpha
));
746 mnOrientationX
= (long) (1000.0 * cos( alpha
));
747 aBundle
.ptlAngle
.x
= mnOrientationX
;
748 aBundle
.ptlAngle
.y
= mnOrientationY
;
755 aBundle
.ptlAngle
.x
= 1;
756 aBundle
.ptlAngle
.y
= 0;
764 aBundle
.ptlAngle
.x
= 1;
765 aBundle
.ptlAngle
.y
= 0;
768 rc
= Ft2SetAttrs( mhPS
, PRIM_CHAR
, nAttrs
, nAttrsDefault
, &aBundle
);
770 #if OSL_DEBUG_LEVEL>1
771 FONTMETRICS aOS2Metric
= {0};
772 Ft2QueryFontMetrics( mhPS
, sizeof( aOS2Metric
), &aOS2Metric
);
779 USHORT
Os2SalGraphics::SetFont( ImplFontSelectData
* pFont
, int nFallbackLevel
)
782 // return early if there is no new font
786 // deselect still active font
788 Ft2SetCharSet( mhPS
, mhDefFont
);
789 // release no longer referenced font handles
790 for( int i
= nFallbackLevel
; i
< MAX_FALLBACK
; ++i
)
793 Ft2DeleteSetId( mhPS
, mhFonts
[i
] );
801 #if OSL_DEBUG_LEVEL>10
802 debug_printf( "Os2SalGraphics::SetFont\n");
805 DBG_ASSERT( pFont
->mpFontData
, "WinSalGraphics mpFontData==NULL");
806 mpOs2FontEntry
[ nFallbackLevel
] = reinterpret_cast<ImplOs2FontEntry
*>( pFont
->mpFontEntry
);
807 mpOs2FontData
[ nFallbackLevel
] = static_cast<const ImplOs2FontData
*>( pFont
->mpFontData
);
809 ImplDoSetFont( pFont
, mfFontScale
, nFallbackLevel
);
814 mhDefFont
= nFallbackLevel
+ LCID_BASE
;
818 // release no longer referenced font handles
819 for( int i
= nFallbackLevel
; i
< MAX_FALLBACK
; ++i
)
824 Ft2DeleteSetId( mhPS
, mhFonts
[i
] );
831 // store new font in correct layer
832 mhFonts
[ nFallbackLevel
] = nFallbackLevel
+ LCID_BASE
;
834 // now the font is live => update font face
835 if( mpOs2FontData
[ nFallbackLevel
] )
836 mpOs2FontData
[ nFallbackLevel
]->UpdateFromHPS( mhPS
);
838 if( !nFallbackLevel
)
840 mbFontKernInit
= TRUE
;
841 if ( mpFontKernPairs
)
843 delete[] mpFontKernPairs
;
844 mpFontKernPairs
= NULL
;
846 mnFontKernPairCount
= 0;
849 // some printers have higher internal resolution, so their
850 // text output would be different from what we calculated
851 // => suggest DrawTextArray to workaround this problem
853 return SAL_SETFONT_USEDRAWTEXTARRAY
;
858 // -----------------------------------------------------------------------
860 void Os2SalGraphics::GetFontMetric( ImplFontMetricData
* pMetric
)
862 FONTMETRICS aOS2Metric
;
863 Ft2QueryFontMetrics( mhPS
, sizeof( aOS2Metric
), &aOS2Metric
);
865 #if OSL_DEBUG_LEVEL>1
866 debug_printf( "Os2SalGraphics::GetFontMetric hps %x\n", mhPS
);
867 if (aOS2Metric
.szFacename
[0] == 'A') {
868 debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics facename '%s'\n", mhPS
, aOS2Metric
.szFacename
);
869 debug_printf( "Os2SalGraphics::GetFontMetric hps %x fontmetrics lMatch '%d'\n", mhPS
, aOS2Metric
.lMatch
);
873 pMetric
->maName
= UniString( aOS2Metric
.szFamilyname
, gsl_getSystemTextEncoding());
874 pMetric
->maStyleName
= ImpStyleNameToSal( aOS2Metric
.szFamilyname
,
875 aOS2Metric
.szFacename
,
876 strlen( aOS2Metric
.szFamilyname
) );
878 // device independent font attributes
879 pMetric
->meFamily
= ImplFamilyToSal( aOS2Metric
.panose
.bFamilyType
);
880 pMetric
->mbSymbolFlag
= (aOS2Metric
.usCodePage
== SYMBOL_CHARSET
);
881 pMetric
->meWeight
= ImplWeightToSal( aOS2Metric
.usWeightClass
);
882 pMetric
->mePitch
= ImplLogPitchToSal( aOS2Metric
.fsType
);
883 pMetric
->meItalic
= (aOS2Metric
.fsSelection
& FM_SEL_ITALIC
) ? ITALIC_NORMAL
: ITALIC_NONE
;
884 pMetric
->mnSlant
= 0;
886 // device dependend font attributes
887 pMetric
->mbDevice
= (aOS2Metric
.fsDefn
& FM_DEFN_GENERIC
) ? FALSE
: TRUE
;
888 pMetric
->mbScalableFont
= (aOS2Metric
.fsDefn
& FM_DEFN_OUTLINE
) ? true : false;
889 if( pMetric
->mbScalableFont
)
891 // check if there are kern pairs
892 // TODO: does this work with GPOS kerning?
893 pMetric
->mbKernableFont
= (aOS2Metric
.sKerningPairs
> 0);
897 // bitmap fonts cannot be rotated directly
898 pMetric
->mnOrientation
= 0;
899 // bitmap fonts have no kerning
900 pMetric
->mbKernableFont
= false;
903 // transformation dependend font metrics
904 if ( aOS2Metric
.fsDefn
& FM_DEFN_OUTLINE
)
906 pMetric
->mnWidth
= aOS2Metric
.lEmInc
;
910 pMetric
->mnWidth
= aOS2Metric
.lAveCharWidth
;
911 pMetric
->mnOrientation
= 0;
913 pMetric
->mnIntLeading
= aOS2Metric
.lInternalLeading
;
914 pMetric
->mnExtLeading
= aOS2Metric
.lExternalLeading
;
915 pMetric
->mnAscent
= aOS2Metric
.lMaxAscender
;
916 pMetric
->mnDescent
= aOS2Metric
.lMaxDescender
;
918 // #107888# improved metric compatibility for Asian fonts...
919 // TODO: assess workaround below for CWS >= extleading
920 // TODO: evaluate use of aWinMetric.sTypo* members for CJK
921 if( mpOs2FontData
[0] && mpOs2FontData
[0]->SupportsCJK() )
923 pMetric
->mnIntLeading
+= pMetric
->mnExtLeading
;
925 // #109280# The line height for Asian fonts is too small.
926 // Therefore we add half of the external leading to the
927 // ascent, the other half is added to the descent.
928 const long nHalfTmpExtLeading
= pMetric
->mnExtLeading
/ 2;
929 const long nOtherHalfTmpExtLeading
= pMetric
->mnExtLeading
- nHalfTmpExtLeading
;
931 // #110641# external leading for Asian fonts.
932 // The factor 0.3 has been confirmed with experiments.
933 long nCJKExtLeading
= static_cast<long>(0.30 * (pMetric
->mnAscent
+ pMetric
->mnDescent
));
934 nCJKExtLeading
-= pMetric
->mnExtLeading
;
935 pMetric
->mnExtLeading
= (nCJKExtLeading
> 0) ? nCJKExtLeading
: 0;
937 pMetric
->mnAscent
+= nHalfTmpExtLeading
;
938 pMetric
->mnDescent
+= nOtherHalfTmpExtLeading
;
940 // #109280# HACK korean only: increase descent for wavelines and impr
946 // -----------------------------------------------------------------------
948 ULONG
Os2SalGraphics::GetKernPairs( ULONG nPairs
, ImplKernPairData
* pKernPairs
)
950 DBG_ASSERT( sizeof( KERNINGPAIRS
) == sizeof( ImplKernPairData
),
951 "Os2SalGraphics::GetKernPairs(): KERNINGPAIRS != ImplKernPairData" );
953 if ( mbFontKernInit
)
955 if( mpFontKernPairs
)
957 delete[] mpFontKernPairs
;
958 mpFontKernPairs
= NULL
;
960 mnFontKernPairCount
= 0;
963 KERNINGPAIRS
* pPairs
= NULL
;
964 FONTMETRICS aOS2Metric
;
965 Ft2QueryFontMetrics( mhPS
, sizeof( aOS2Metric
), &aOS2Metric
);
966 int nCount
= aOS2Metric
.sKerningPairs
;
970 pPairs
= new KERNINGPAIRS
[ nCount
+1 ];
971 mpFontKernPairs
= pPairs
;
972 mnFontKernPairCount
= nCount
;
973 Ft2QueryKerningPairs( mhPS
, nCount
, (KERNINGPAIRS
*)pPairs
);
974 #else // GCP_KERN_HACK
975 pPairs
= (KERNINGPAIRS
*)pKernPairs
;
976 nCount
= (nCount
< nPairs
) ? nCount
: nPairs
;
977 Ft2QueryKerningPairs( mhPS
, nCount
, (KERNINGPAIRS
*)pPairs
);
979 #endif // GCP_KERN_HACK
983 mbFontKernInit
= FALSE
;
985 std::sort( mpFontKernPairs
, mpFontKernPairs
+ mnFontKernPairCount
, ImplCmpKernData
);
989 return mnFontKernPairCount
;
990 else if( mpFontKernPairs
)
992 if ( nPairs
< mnFontKernPairCount
)
993 nPairs
= mnFontKernPairCount
;
994 memcpy( pKernPairs
, mpFontKernPairs
,
995 nPairs
*sizeof( ImplKernPairData
) );
1003 // -----------------------------------------------------------------------
1005 static ImplFontCharMap
* pOs2DefaultImplFontCharMap
= NULL
;
1006 static const sal_uInt32 pOs2DefaultRangeCodes
[] = {0x0020,0x00FF};
1008 ImplFontCharMap
* Os2SalGraphics::GetImplFontCharMap() const
1010 if( !mpOs2FontData
[0] )
1011 return ImplFontCharMap::GetDefaultMap();
1012 return mpOs2FontData
[0]->GetImplFontCharMap();
1015 // -----------------------------------------------------------------------
1017 bool Os2SalGraphics::AddTempDevFont( ImplDevFontList
* pFontList
,
1018 const String
& rFontFileURL
, const String
& rFontName
)
1020 #if OSL_DEBUG_LEVEL>0
1021 debug_printf("Os2SalGraphics::AddTempDevFont\n");
1026 // -----------------------------------------------------------------------
1028 void Os2SalGraphics::GetDevFontList( ImplDevFontList
* pList
)
1030 PFONTMETRICS pFontMetrics
;
1031 ULONG nFontMetricCount
;
1034 #if OSL_DEBUG_LEVEL>0
1035 debug_printf("Os2SalGraphics::GetDevFontList\n");
1038 // install OpenSymbol
1040 ULONG ObjNum
, Offset
, rc
;
1041 CHAR Buff
[2*_MAX_PATH
];
1042 char drive
[_MAX_DRIVE
], dir
[_MAX_DIR
];
1043 char fname
[_MAX_FNAME
], ext
[_MAX_EXT
];
1044 // get module handle (and name)
1045 rc
= DosQueryModFromEIP( &hMod
, &ObjNum
, sizeof( Buff
), Buff
,
1046 &Offset
, (ULONG
)ImplSalGetUniString
);
1047 DosQueryModuleName(hMod
, sizeof(Buff
), Buff
);
1048 // replace module path with font path
1049 char* slash
= strrchr( Buff
, '\\');
1051 slash
= strrchr( Buff
, '\\');
1053 strcat( Buff
, "\\SHARE\\FONTS\\TRUETYPE\\OPENS___.TTF");
1054 rc
= GpiLoadPublicFonts( GetSalData()->mhAB
, Buff
);
1058 // Bei Bildschirm-Devices cachen wir die Liste global, da
1059 // dies im unabhaengigen Teil auch so gemacht wird und wir
1060 // ansonsten auf geloeschten Systemdaten arbeiten koennten
1061 pSalData
= GetSalData();
1062 nFontMetricCount
= pSalData
->mnFontMetricCount
;
1063 pFontMetrics
= pSalData
->mpFontMetrics
;
1064 // Bei Bildschirm-Devices holen wir uns die Fontliste jedesmal neu
1067 delete pFontMetrics
;
1068 pFontMetrics
= NULL
;
1069 nFontMetricCount
= 0;
1074 nFontMetricCount
= mnFontMetricCount
;
1075 pFontMetrics
= mpFontMetrics
;
1078 // do we have to create the cached font list first?
1079 if ( !pFontMetrics
)
1081 // query the number of fonts available
1083 nFontMetricCount
= Ft2QueryFonts( mhPS
,
1084 QF_PUBLIC
| QF_PRIVATE
,
1086 sizeof( FONTMETRICS
), NULL
);
1088 // procede only if at least one is available!
1089 if ( nFontMetricCount
)
1091 // allocate memory for font list
1092 pFontMetrics
= new FONTMETRICS
[nFontMetricCount
];
1095 Ft2QueryFonts( mhPS
,
1096 QF_PUBLIC
| QF_PRIVATE
,
1098 (PLONG
)&nFontMetricCount
,
1099 (LONG
) sizeof( FONTMETRICS
),
1105 pSalData
->mnFontMetricCount
= nFontMetricCount
;
1106 pSalData
->mpFontMetrics
= pFontMetrics
;
1110 mnFontMetricCount
= nFontMetricCount
;
1111 mpFontMetrics
= pFontMetrics
;
1115 // copy data from the font list
1116 for( ULONG i
= 0; i
< nFontMetricCount
; i
++ )
1118 PFONTMETRICS pFontMetric
= &pFontMetrics
[i
];
1120 // skip font starting with '@', this is an alias internally
1121 // used by truetype engine.
1122 if (pFontMetric
->szFacename
[0] == '@')
1125 // skip bitmap fonts (but keep WarpSans)
1126 if ( (pFontMetric
->fsDefn
& FM_DEFN_OUTLINE
) == 0
1127 && strncmp( pFontMetric
->szFacename
, "WarpSans", 8) )
1128 // Font nicht aufnehmen
1131 // replace '-' in facename with ' ' (for ft2lib)
1132 char* dash
= pFontMetric
->szFacename
;
1133 while( (dash
=strchr( dash
, '-')))
1136 // create new font list element
1137 ImplOs2FontData
* pData
= new ImplOs2FontData( pFontMetric
, 0, 0 );
1139 // add font list element to font list
1140 pList
->Add( pData
);
1145 // ----------------------------------------------------------------------------
1147 void Os2SalGraphics::GetDevFontSubstList( OutputDevice
* pOutDev
)
1151 // -----------------------------------------------------------------------
1153 BOOL
Os2SalGraphics::GetGlyphBoundRect( long nIndex
, Rectangle
& rRect
)
1157 aMat
.eM11
= aMat
.eM22
= FixedFromDouble( 1.0 );
1158 aMat
.eM12
= aMat
.eM21
= FixedFromDouble( 0.0 );
1160 UINT nGGOFlags
= GGO_METRICS
;
1161 if( !(nIndex
& GF_ISCHAR
) )
1162 nGGOFlags
|= GGO_GLYPH_INDEX
;
1163 nIndex
&= GF_IDXMASK
;
1166 DWORD nSize
= FT2_ERROR
;
1167 nSize
= Ft2GetGlyphOutline( mhPS
, nIndex
, nGGOFlags
, &aGM
, 0, NULL
, &aMat
);
1168 if( nSize
== FT2_ERROR
)
1171 rRect
= Rectangle( Point( +aGM
.gmptGlyphOrigin
.x
, -aGM
.gmptGlyphOrigin
.y
),
1172 Size( aGM
.gmBlackBoxX
, aGM
.gmBlackBoxY
) );
1173 rRect
.Left() = static_cast<int>( mfFontScale
* rRect
.Left() );
1174 rRect
.Right() = static_cast<int>( mfFontScale
* rRect
.Right() );
1175 rRect
.Top() = static_cast<int>( mfFontScale
* rRect
.Top() );
1176 rRect
.Bottom() = static_cast<int>( mfFontScale
* rRect
.Bottom() );
1180 // -----------------------------------------------------------------------
1182 BOOL
Os2SalGraphics::GetGlyphOutline( long nIndex
, ::basegfx::B2DPolyPolygon
& rB2DPolyPoly
)
1184 #if OSL_DEBUG_LEVEL>0
1185 debug_printf("Os2SalGraphics::GetGlyphOutline\n");
1187 rB2DPolyPoly
.clear();
1193 aMat
.eM11
= aMat
.eM22
= FixedFromDouble( 1.0 );
1194 aMat
.eM12
= aMat
.eM21
= FixedFromDouble( 0.0 );
1196 UINT nGGOFlags
= GGO_NATIVE
;
1197 if( !(nIndex
& GF_ISCHAR
) )
1198 nGGOFlags
|= GGO_GLYPH_INDEX
;
1199 nIndex
&= GF_IDXMASK
;
1201 GLYPHMETRICS aGlyphMetrics
;
1202 DWORD nSize1
= FT2_ERROR
;
1203 nSize1
= Ft2GetGlyphOutline( mhPS
, nIndex
, nGGOFlags
, &aGlyphMetrics
, 0, NULL
, &aMat
);
1205 if( !nSize1
) // blank glyphs are ok
1207 else if( nSize1
!= FT2_ERROR
)
1209 BYTE
* pData
= new BYTE
[ nSize1
];
1210 ULONG nTotalCount
= 0;
1212 nSize2
= Ft2GetGlyphOutline( mhPS
, nIndex
, nGGOFlags
,
1213 &aGlyphMetrics
, nSize1
, pData
, &aMat
);
1215 if( nSize1
== nSize2
)
1220 Point
* pPoints
= new Point
[ nPtSize
];
1221 BYTE
* pFlags
= new BYTE
[ nPtSize
];
1223 TTPOLYGONHEADER
* pHeader
= (TTPOLYGONHEADER
*)pData
;
1224 while( (BYTE
*)pHeader
< pData
+nSize2
)
1226 // only outline data is interesting
1227 if( pHeader
->dwType
!= TT_POLYGON_TYPE
)
1230 // get start point; next start points are end points
1231 // of previous segment
1234 long nX
= IntTimes256FromFixed( pHeader
->pfxStart
.x
);
1235 long nY
= IntTimes256FromFixed( pHeader
->pfxStart
.y
);
1236 pPoints
[ nPnt
] = Point( nX
, nY
);
1237 pFlags
[ nPnt
++ ] = POLY_NORMAL
;
1239 bool bHasOfflinePoints
= false;
1240 TTPOLYCURVE
* pCurve
= (TTPOLYCURVE
*)( pHeader
+ 1 );
1241 pHeader
= (TTPOLYGONHEADER
*)( (BYTE
*)pHeader
+ pHeader
->cb
);
1242 while( (BYTE
*)pCurve
< (BYTE
*)pHeader
)
1244 int nNeededSize
= nPnt
+ 16 + 3 * pCurve
->cpfx
;
1245 if( nPtSize
< nNeededSize
)
1247 Point
* pOldPoints
= pPoints
;
1248 BYTE
* pOldFlags
= pFlags
;
1249 nPtSize
= 2 * nNeededSize
;
1250 pPoints
= new Point
[ nPtSize
];
1251 pFlags
= new BYTE
[ nPtSize
];
1252 for( int i
= 0; i
< nPnt
; ++i
)
1254 pPoints
[ i
] = pOldPoints
[ i
];
1255 pFlags
[ i
] = pOldFlags
[ i
];
1257 delete[] pOldPoints
;
1262 if( TT_PRIM_LINE
== pCurve
->wType
)
1264 while( i
< pCurve
->cpfx
)
1266 nX
= IntTimes256FromFixed( pCurve
->apfx
[ i
].x
);
1267 nY
= IntTimes256FromFixed( pCurve
->apfx
[ i
].y
);
1269 pPoints
[ nPnt
] = Point( nX
, nY
);
1270 pFlags
[ nPnt
] = POLY_NORMAL
;
1274 else if( TT_PRIM_QSPLINE
== pCurve
->wType
)
1276 bHasOfflinePoints
= true;
1277 while( i
< pCurve
->cpfx
)
1279 // get control point of quadratic bezier spline
1280 nX
= IntTimes256FromFixed( pCurve
->apfx
[ i
].x
);
1281 nY
= IntTimes256FromFixed( pCurve
->apfx
[ i
].y
);
1283 Point
aControlP( nX
, nY
);
1285 // calculate first cubic control point
1286 // P0 = 1/3 * (PBeg + 2 * PQControl)
1287 nX
= pPoints
[ nPnt
-1 ].X() + 2 * aControlP
.X();
1288 nY
= pPoints
[ nPnt
-1 ].Y() + 2 * aControlP
.Y();
1289 pPoints
[ nPnt
+0 ] = Point( (2*nX
+3)/6, (2*nY
+3)/6 );
1290 pFlags
[ nPnt
+0 ] = POLY_CONTROL
;
1292 // calculate endpoint of segment
1293 nX
= IntTimes256FromFixed( pCurve
->apfx
[ i
].x
);
1294 nY
= IntTimes256FromFixed( pCurve
->apfx
[ i
].y
);
1296 if ( i
+1 >= pCurve
->cpfx
)
1298 // endpoint is either last point in segment => advance
1303 // or endpoint is the middle of two control points
1304 nX
+= IntTimes256FromFixed( pCurve
->apfx
[ i
-1 ].x
);
1305 nY
+= IntTimes256FromFixed( pCurve
->apfx
[ i
-1 ].y
);
1308 // no need to advance, because the current point
1309 // is the control point in next bezier spline
1312 pPoints
[ nPnt
+2 ] = Point( nX
, nY
);
1313 pFlags
[ nPnt
+2 ] = POLY_NORMAL
;
1315 // calculate second cubic control point
1316 // P1 = 1/3 * (PEnd + 2 * PQControl)
1317 nX
= pPoints
[ nPnt
+2 ].X() + 2 * aControlP
.X();
1318 nY
= pPoints
[ nPnt
+2 ].Y() + 2 * aControlP
.Y();
1319 pPoints
[ nPnt
+1 ] = Point( (2*nX
+3)/6, (2*nY
+3)/6 );
1320 pFlags
[ nPnt
+1 ] = POLY_CONTROL
;
1326 // next curve segment
1327 pCurve
= (TTPOLYCURVE
*)&pCurve
->apfx
[ i
];
1330 // end point is start point for closed contour
1331 // disabled, because Polygon class closes the contour itself
1332 // pPoints[nPnt++] = pPoints[0];
1334 // Added again, but add only when not yet closed
1335 if(pPoints
[nPnt
- 1] != pPoints
[0])
1337 if( bHasOfflinePoints
)
1338 pFlags
[nPnt
] = pFlags
[0];
1340 pPoints
[nPnt
++] = pPoints
[0];
1343 // convert y-coordinates W32 -> VCL
1344 for( int i
= 0; i
< nPnt
; ++i
)
1345 pPoints
[i
].Y() = -pPoints
[i
].Y();
1347 // insert into polypolygon
1348 Polygon
aPoly( nPnt
, pPoints
, (bHasOfflinePoints
? pFlags
: NULL
) );
1349 // convert to B2DPolyPolygon
1350 // TODO: get rid of the intermediate PolyPolygon
1351 rB2DPolyPoly
.append( aPoly
.getB2DPolygon() );
1361 // rescaling needed for the PolyPolygon conversion
1362 if( rB2DPolyPoly
.count() )
1364 ::basegfx::B2DHomMatrix aMatrix
;
1365 aMatrix
.scale( 1.0/256, 1.0/256 );
1366 aMatrix
.scale( mfFontScale
, mfFontScale
);
1367 rB2DPolyPoly
.transform( aMatrix
);
1373 // -----------------------------------------------------------------------
1375 // TODO: Replace this class with boost::scoped_array
1376 class ScopedCharArray
1379 inline explicit ScopedCharArray(char * pArray
): m_pArray(pArray
) {}
1381 inline ~ScopedCharArray() { delete[] m_pArray
; }
1383 inline char * get() const { return m_pArray
; }
1392 explicit ScopedFont(Os2SalGraphics
& rData
);
1397 Os2SalGraphics
& m_rData
;
1401 ScopedFont::ScopedFont(Os2SalGraphics
& rData
): m_rData(rData
)
1404 m_hOrigFont
= m_rData
.mhFonts
[0];
1405 m_rData
.mhFonts
[0] = 0; // avoid deletion of current font
1409 ScopedFont::~ScopedFont()
1414 // restore original font, destroy temporary font
1415 HFONT hTempFont
= m_rData
.mhFonts
[0];
1416 m_rData
.mhFonts
[0] = m_hOrigFont
;
1417 SelectObject( m_rData
.mhDC
, m_hOrigFont
);
1418 DeleteObject( hTempFont
);
1423 class ScopedTrueTypeFont
1426 inline ScopedTrueTypeFont(): m_pFont(0) {}
1428 ~ScopedTrueTypeFont();
1430 int open(void * pBuffer
, sal_uInt32 nLen
, sal_uInt32 nFaceNum
);
1432 inline TrueTypeFont
* get() const { return m_pFont
; }
1435 TrueTypeFont
* m_pFont
;
1438 ScopedTrueTypeFont::~ScopedTrueTypeFont()
1441 CloseTTFont(m_pFont
);
1444 int ScopedTrueTypeFont::open(void * pBuffer
, sal_uInt32 nLen
,
1445 sal_uInt32 nFaceNum
)
1447 OSL_ENSURE(m_pFont
== 0, "already open");
1448 return OpenTTFontBuffer(pBuffer
, nLen
, nFaceNum
, &m_pFont
);
1451 BOOL
Os2SalGraphics::CreateFontSubset( const rtl::OUString
& rToFile
,
1452 const ImplFontData
* pFont
, long* pGlyphIDs
, sal_uInt8
* pEncoding
,
1453 sal_Int32
* pGlyphWidths
, int nGlyphCount
, FontSubsetInfo
& rInfo
)
1455 // create matching ImplFontSelectData
1456 // we need just enough to get to the font file data
1457 // use height=1000 for easier debugging (to match psprint's font units)
1458 ImplFontSelectData
aIFSD( *pFont
, Size(0,1000), 1000.0, 0, false );
1460 // TODO: much better solution: move SetFont and restoration of old font to caller
1461 ScopedFont
aOldFont(*this);
1462 SetFont( &aIFSD
, 0 );
1464 #if OSL_DEBUG_LEVEL > 100
1466 TEXTMETRICA aWinMetric
;
1467 if( !::GetTextMetricsA( mhDC
, &aWinMetric
) )
1470 DBG_ASSERT( !(aWinMetric
.tmPitchAndFamily
& TMPF_DEVICE
), "cannot subset device font" );
1471 DBG_ASSERT( aWinMetric
.tmPitchAndFamily
& TMPF_TRUETYPE
, "can only subset TT font" );
1474 // get raw font file data
1475 DWORD nFontSize1
= Ft2GetFontData( mhPS
, 0, 0, NULL
, 0 );
1476 if( nFontSize1
== FT2_ERROR
)
1478 ScopedCharArray
xRawFontData(new char[ nFontSize1
]);
1479 DWORD nFontSize2
= Ft2GetFontData( mhPS
, 0, 0, (void*)xRawFontData
.get(), nFontSize1
);
1480 if( nFontSize1
!= nFontSize2
)
1484 sal_uInt32 nFaceNum
= 0;
1485 if( !*xRawFontData
.get() ) // TTC candidate
1486 nFaceNum
= ~0U; // indicate "TTC font extracts only"
1488 ScopedTrueTypeFont aSftTTF
;
1489 int nRC
= aSftTTF
.open( xRawFontData
.get(), nFontSize1
, nFaceNum
);
1493 TTGlobalFontInfo aTTInfo
;
1494 ::GetTTGlobalFontInfo( aSftTTF
.get(), &aTTInfo
);
1495 rInfo
.m_nFontType
= SAL_FONTSUBSETINFO_TYPE_TRUETYPE
;
1496 rInfo
.m_aPSName
= ImplSalGetUniString( aTTInfo
.psname
);
1497 rInfo
.m_nAscent
= +aTTInfo
.winAscent
;
1498 rInfo
.m_nDescent
= -aTTInfo
.winDescent
;
1499 rInfo
.m_aFontBBox
= Rectangle( Point( aTTInfo
.xMin
, aTTInfo
.yMin
),
1500 Point( aTTInfo
.xMax
, aTTInfo
.yMax
) );
1501 rInfo
.m_nCapHeight
= aTTInfo
.yMax
; // Well ...
1503 // subset glyphs and get their properties
1504 // take care that subset fonts require the NotDef glyph in pos 0
1505 int nOrigCount
= nGlyphCount
;
1506 USHORT aShortIDs
[ 256 ];
1507 sal_uInt8 aTempEncs
[ 256 ];
1510 for( i
= 0; i
< nGlyphCount
; ++i
)
1512 aTempEncs
[i
] = pEncoding
[i
];
1513 sal_uInt32 nGlyphIdx
= pGlyphIDs
[i
] & GF_IDXMASK
;
1514 if( pGlyphIDs
[i
] & GF_ISCHAR
)
1516 bool bVertical
= (pGlyphIDs
[i
] & GF_ROTMASK
) != 0;
1517 nGlyphIdx
= ::MapChar( aSftTTF
.get(), sal::static_int_cast
<sal_uInt16
>(nGlyphIdx
), bVertical
);
1518 if( nGlyphIdx
== 0 && pFont
->IsSymbolFont() )
1520 // #i12824# emulate symbol aliasing U+FXXX <-> U+0XXX
1521 nGlyphIdx
= pGlyphIDs
[i
] & GF_IDXMASK
;
1522 nGlyphIdx
= (nGlyphIdx
& 0xF000) ? (nGlyphIdx
& 0x00FF) : (nGlyphIdx
| 0xF000 );
1523 nGlyphIdx
= ::MapChar( aSftTTF
.get(), sal::static_int_cast
<sal_uInt16
>(nGlyphIdx
), bVertical
);
1526 aShortIDs
[i
] = static_cast<USHORT
>( nGlyphIdx
);
1529 nNotDef
= i
; // first NotDef glyph found
1534 // add fake NotDef glyph if needed
1536 nNotDef
= nGlyphCount
++;
1538 // NotDef glyph must be in pos 0 => swap glyphids
1539 aShortIDs
[ nNotDef
] = aShortIDs
[0];
1540 aTempEncs
[ nNotDef
] = aTempEncs
[0];
1544 DBG_ASSERT( nGlyphCount
< 257, "too many glyphs for subsetting" );
1546 // fill pWidth array
1547 TTSimpleGlyphMetrics
* pMetrics
=
1548 ::GetTTSimpleGlyphMetrics( aSftTTF
.get(), aShortIDs
, nGlyphCount
, aIFSD
.mbVertical
);
1551 sal_uInt16 nNotDefAdv
= pMetrics
[0].adv
;
1552 pMetrics
[0].adv
= pMetrics
[nNotDef
].adv
;
1553 pMetrics
[nNotDef
].adv
= nNotDefAdv
;
1554 for( i
= 0; i
< nOrigCount
; ++i
)
1555 pGlyphWidths
[i
] = pMetrics
[i
].adv
;
1558 // write subset into destination file
1559 rtl::OUString aSysPath
;
1560 if( osl_File_E_None
!= osl_getSystemPathFromFileURL( rToFile
.pData
, &aSysPath
.pData
) )
1562 rtl_TextEncoding aThreadEncoding
= osl_getThreadTextEncoding();
1563 ByteString
aToFile( rtl::OUStringToOString( aSysPath
, aThreadEncoding
) );
1564 nRC
= ::CreateTTFromTTGlyphs( aSftTTF
.get(), aToFile
.GetBuffer(), aShortIDs
,
1565 aTempEncs
, nGlyphCount
, 0, NULL
, 0 );
1566 return nRC
== SF_OK
;
1569 //--------------------------------------------------------------------------
1571 const void* Os2SalGraphics::GetEmbedFontData( const ImplFontData
* pFont
,
1572 const sal_Ucs
* pUnicodes
, sal_Int32
* pCharWidths
,
1573 FontSubsetInfo
& rInfo
, long* pDataLen
)
1575 // create matching ImplFontSelectData
1576 // we need just enough to get to the font file data
1577 ImplFontSelectData
aIFSD( *pFont
, Size(0,1000), 1000.0, 0, false );
1579 // TODO: much better solution: move SetFont and restoration of old font to caller
1580 ScopedFont
aOldFont(*this);
1581 SetFont( &aIFSD
, 0 );
1583 // get the raw font file data
1584 DWORD nFontSize1
= Ft2GetFontData( mhPS
, 0, 0, NULL
, 0 );
1585 if( nFontSize1
== FT2_ERROR
|| nFontSize1
<= 0 )
1587 *pDataLen
= nFontSize1
;
1588 void* pData
= reinterpret_cast<void*>(new char[ nFontSize1
]);
1589 DWORD nFontSize2
= Ft2GetFontData( mhPS
, 0, 0, pData
, nFontSize1
);
1590 if( nFontSize1
!= nFontSize2
)
1593 // get important font properties
1594 FONTMETRICS aOS2Metric
;
1595 if (Ft2QueryFontMetrics( mhPS
, sizeof( aOS2Metric
), &aOS2Metric
) == GPI_ERROR
)
1597 rInfo
.m_nFontType
= SAL_FONTSUBSETINFO_TYPE_TYPE1
;
1598 rInfo
.m_aPSName
= ImplSalGetUniString( aOS2Metric
.szFacename
);
1599 rInfo
.m_nAscent
= +aOS2Metric
.lMaxAscender
;
1600 rInfo
.m_nDescent
= -aOS2Metric
.lMaxDescender
;
1601 rInfo
.m_aFontBBox
= Rectangle( Point( 0, -aOS2Metric
.lMaxDescender
),
1602 Point( aOS2Metric
.lMaxCharInc
, aOS2Metric
.lMaxAscender
+aOS2Metric
.lExternalLeading
) );
1603 rInfo
.m_nCapHeight
= aOS2Metric
.lMaxAscender
; // Well ...
1605 // get individual character widths
1606 for( int i
= 0; i
< 256; ++i
)
1608 LONG nCharWidth
= 0;
1609 const sal_Ucs cChar
= pUnicodes
[i
];
1610 if( !Ft2QueryStringWidthW( mhPS
, (LPWSTR
)&cChar
, 1, &nCharWidth
) )
1612 pCharWidths
[i
] = nCharWidth
;
1617 FreeEmbedFontData( pData
, nFontSize1
);
1624 //--------------------------------------------------------------------------
1626 void Os2SalGraphics::FreeEmbedFontData( const void* pData
, long /*nLen*/ )
1628 delete[] reinterpret_cast<char*>(const_cast<void*>(pData
));
1631 const Ucs2SIntMap
* Os2SalGraphics::GetFontEncodingVector( const ImplFontData
* pFont
, const Ucs2OStrMap
** pNonEncoded
)
1633 // TODO: even for builtin fonts we get here... why?
1634 if( !pFont
->IsEmbeddable() )
1637 // fill the encoding vector
1638 Ucs2SIntMap
& rMap
= *new Ucs2SIntMap
;
1640 // TODO: get correct encoding vector
1641 ImplWinFontData
* pWinFontData
= reinterpret_cast<ImplWinFontData
*>(pFont
);
1644 aGlyphSet
.cbThis
= sizeof(aGlyphSet
);
1645 DWORD aW
= ::GetFontUnicodeRanges( mhDC
, &aGlyphSet
);
1647 for( sal_Unicode i
= 32; i
< 256; ++i
)
1650 *pNonEncoded
= NULL
;
1656 //--------------------------------------------------------------------------
1658 void Os2SalGraphics::GetGlyphWidths( const ImplFontData
* pFont
,
1660 Int32Vector
& rWidths
,
1661 Ucs2UIntMap
& rUnicodeEnc
)
1663 // create matching ImplFontSelectData
1664 // we need just enough to get to the font file data
1665 ImplFontSelectData
aIFSD( *pFont
, Size(0,1000), 1000.0, 0, false );
1667 // TODO: much better solution: move SetFont and restoration of old font to caller
1668 ScopedFont
aOldFont(*this);
1671 ImplDoSetFont( &aIFSD
, fScale
, 0);
1673 if( pFont
->IsSubsettable() )
1675 // get raw font file data
1676 DWORD nFontSize1
= ::Ft2GetFontData( mhPS
, 0, 0, NULL
, 0 );
1677 if( nFontSize1
== FT2_ERROR
)
1679 ScopedCharArray
xRawFontData(new char[ nFontSize1
]);
1680 DWORD nFontSize2
= ::Ft2GetFontData( mhPS
, 0, 0, (void*)xRawFontData
.get(), nFontSize1
);
1681 if( nFontSize1
!= nFontSize2
)
1685 sal_uInt32 nFaceNum
= 0;
1686 if( !*xRawFontData
.get() ) // TTC candidate
1687 nFaceNum
= ~0U; // indicate "TTC font extracts only"
1689 ScopedTrueTypeFont aSftTTF
;
1690 int nRC
= aSftTTF
.open( xRawFontData
.get(), nFontSize1
, nFaceNum
);
1694 int nGlyphs
= GetTTGlyphCount( aSftTTF
.get() );
1697 rWidths
.resize(nGlyphs
);
1698 std::vector
<sal_uInt16
> aGlyphIds(nGlyphs
);
1699 for( int i
= 0; i
< nGlyphs
; i
++ )
1700 aGlyphIds
[i
] = sal_uInt16(i
);
1701 TTSimpleGlyphMetrics
* pMetrics
= ::GetTTSimpleGlyphMetrics( aSftTTF
.get(),
1704 bVertical
? 1 : 0 );
1707 for( int i
= 0; i
< nGlyphs
; i
++ )
1708 rWidths
[i
] = pMetrics
[i
].adv
;
1710 rUnicodeEnc
.clear();
1712 const ImplOs2FontData
* pWinFont
= static_cast<const ImplOs2FontData
*>(pFont
);
1713 ImplFontCharMap
* pMap
= pWinFont
->GetImplFontCharMap();
1714 DBG_ASSERT( pMap
&& pMap
->GetCharCount(), "no map" );
1716 int nCharCount
= pMap
->GetCharCount();
1717 sal_uInt32 nChar
= pMap
->GetFirstChar();
1718 for( int i
= 0; i
< nCharCount
; i
++ )
1720 if( nChar
< 0x00010000 )
1722 sal_uInt16 nGlyph
= ::MapChar( aSftTTF
.get(),
1723 static_cast<sal_uInt16
>(nChar
),
1724 bVertical
? 1 : 0 );
1726 rUnicodeEnc
[ static_cast<sal_Unicode
>(nChar
) ] = nGlyph
;
1728 nChar
= pMap
->GetNextChar( nChar
);
1732 else if( pFont
->IsEmbeddable() )
1734 // get individual character widths
1736 rUnicodeEnc
.clear();
1737 rWidths
.reserve( 224 );
1738 for( sal_Unicode i
= 32; i
< 256; ++i
)
1741 if( Ft2QueryStringWidthW( mhPS
, (LPWSTR
)&i
, 1, (LONG
*)&nCharWidth
) )
1743 rUnicodeEnc
[ i
] = rWidths
.size();
1744 rWidths
.push_back( nCharWidth
);
1750 //--------------------------------------------------------------------------
1752 void Os2SalGraphics::DrawServerFontLayout( const ServerFontLayout
& )
1755 //--------------------------------------------------------------------------
1757 SystemFontData
Os2SalGraphics::GetSysFontData( int nFallbacklevel
) const
1759 SystemFontData aSysFontData
;
1761 if (nFallbacklevel
>= MAX_FALLBACK
) nFallbacklevel
= MAX_FALLBACK
- 1;
1762 if (nFallbacklevel
< 0 ) nFallbacklevel
= 0;
1764 aSysFontData
.nSize
= sizeof( SystemFontData
);
1765 aSysFontData
.hFont
= mhFonts
[nFallbacklevel
];
1766 aSysFontData
.bFakeBold
= false;
1767 aSysFontData
.bFakeItalic
= false;
1768 aSysFontData
.bAntialias
= true;
1769 aSysFontData
.bVerticalCharacterType
= false;
1771 return aSysFontData
;
1774 //--------------------------------------------------------------------------