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