summaryrefslogtreecommitdiff
path: root/vcl/win/source/gdi/salgdi3.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/win/source/gdi/salgdi3.cxx')
-rw-r--r--vcl/win/source/gdi/salgdi3.cxx1531
1 files changed, 1531 insertions, 0 deletions
diff --git a/vcl/win/source/gdi/salgdi3.cxx b/vcl/win/source/gdi/salgdi3.cxx
new file mode 100644
index 000000000000..aa6b4c347090
--- /dev/null
+++ b/vcl/win/source/gdi/salgdi3.cxx
@@ -0,0 +1,1531 @@
+/*************************************************************************
+ *
+ * $RCSfile: salgdi3.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:49 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <string.h>
+
+#ifndef _SVWIN_H
+#include <tools/svwin.h>
+#endif
+
+#define _SV_SALGDI3_CXX
+
+#ifndef _RTL_TENCINFO_H
+#include <rtl/tencinfo.h>
+#endif
+
+#ifndef _SV_WINCOMP_HXX
+#include <wincomp.hxx>
+#endif
+#ifndef _SV_SALDATA_HXX
+#include <saldata.hxx>
+#endif
+#ifndef _SV_SALGDI_HXX
+#include <salgdi.hxx>
+#endif
+#ifndef _SV_OUTFONT_HXX
+#include <outfont.hxx>
+#endif
+#ifndef _SV_FONT_HXX
+#include <font.hxx>
+#endif
+
+#ifndef _DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+
+// -----------
+// - Defines -
+// -----------
+
+#ifdef WIN
+#define GDI_ERROR (0xFFFFFFFFUL)
+#endif
+
+#define GLYPH_INC (512UL)
+#define MAX_POLYCOUNT (2048UL)
+#define CHECKPOINTS( _def_nPnt ) \
+ if( (_def_nPnt) >= nPtSize ) \
+ nPtSize = ImplIncreaseArrays( nPtSize, &pPoints, &pFlags, GLYPH_INC )
+
+// -----------
+// - Inlines -
+// -----------
+
+inline FIXED FixedFromDouble( double d )
+{
+ const long l = (long) ( d * 65536. );
+ return *(FIXED*) &l;
+}
+
+// -----------------------------------------------------------------------
+
+inline int IntFromFixed(FIXED f)
+{
+ return( ( f.fract >= 0x8000 ) ? ( f.value + 1 ) : f.value );
+}
+
+// -----------------------------------------------------------------------
+
+inline FIXED fxDiv2( FIXED fxVal1, FIXED fxVal2 )
+{
+ const long l = (*((long far *)&(fxVal1)) + *((long far *)&(fxVal2))) >> 1;
+ return *(FIXED*) &l;
+}
+
+// =======================================================================
+
+#define SAL_DRAWTEXT_STACKBUF 128
+
+// =======================================================================
+
+// Diese Variablen koennen static sein, da systemweite Einstellungen
+// gemerkt werden
+static BOOL bImplSalCourierScalable = FALSE;
+static BOOL bImplSalCourierNew = FALSE;
+
+// =======================================================================
+
+struct ImplEnumInfo
+{
+ HDC mhDC;
+ ImplDevFontList* mpList;
+ XubString* mpName;
+ LOGFONTA* mpLogFontA;
+ LOGFONTW* mpLogFontW;
+ BOOL mbCourier;
+ BOOL mbImplSalCourierScalable;
+ BOOL mbImplSalCourierNew;
+ BOOL mbPrinter;
+};
+
+// =======================================================================
+
+static CharSet ImplCharSetToSal( BYTE nCharSet )
+{
+ if ( nCharSet == OEM_CHARSET )
+ {
+ UINT nCP = (USHORT)GetOEMCP();
+ return rtl_getTextEncodingFromPCCodePage( nCP );
+ }
+ else
+ return rtl_getTextEncodingFromWindowsCharset( nCharSet );
+}
+
+// -----------------------------------------------------------------------
+
+static BYTE ImplCharSetToWin( CharSet eCharSet )
+{
+ return rtl_getBestWindowsCharsetFromTextEncoding( eCharSet );
+}
+
+// -----------------------------------------------------------------------
+
+static FontFamily ImplFamilyToSal( BYTE nFamily )
+{
+ switch ( nFamily & 0xF0 )
+ {
+ case FF_DECORATIVE:
+ return FAMILY_DECORATIVE;
+
+ case FF_MODERN:
+ return FAMILY_MODERN;
+
+ case FF_ROMAN:
+ return FAMILY_ROMAN;
+
+ case FF_SCRIPT:
+ return FAMILY_SCRIPT;
+
+ case FF_SWISS:
+ return FAMILY_SWISS;
+ }
+
+ return FAMILY_DONTKNOW;
+}
+
+// -----------------------------------------------------------------------
+
+static BYTE ImplFamilyToWin( FontFamily eFamily )
+{
+ switch ( eFamily )
+ {
+ case FAMILY_DECORATIVE:
+ return FF_DECORATIVE;
+
+ case FAMILY_MODERN:
+ return FF_MODERN;
+
+ case FAMILY_ROMAN:
+ return FF_ROMAN;
+
+ case FAMILY_SCRIPT:
+ return FF_SCRIPT;
+
+ case FAMILY_SWISS:
+ return FF_SWISS;
+
+ case FAMILY_SYSTEM:
+ return FF_SWISS;
+ }
+
+ return FF_DONTCARE;
+}
+
+// -----------------------------------------------------------------------
+
+static FontWeight ImplWeightToSal( WinWeight nWeight )
+{
+ if ( nWeight <= FW_THIN )
+ return WEIGHT_THIN;
+ else if ( nWeight <= FW_ULTRALIGHT )
+ return WEIGHT_ULTRALIGHT;
+ else if ( nWeight <= FW_LIGHT )
+ return WEIGHT_LIGHT;
+ else if ( nWeight < FW_MEDIUM )
+ return WEIGHT_NORMAL;
+ else if ( nWeight == FW_MEDIUM )
+ return WEIGHT_MEDIUM;
+ else if ( nWeight <= FW_SEMIBOLD )
+ return WEIGHT_SEMIBOLD;
+ else if ( nWeight <= FW_BOLD )
+ return WEIGHT_BOLD;
+ else if ( nWeight <= FW_ULTRABOLD )
+ return WEIGHT_ULTRABOLD;
+ else
+ return WEIGHT_BLACK;
+}
+
+// -----------------------------------------------------------------------
+
+static WinWeight ImplWeightToWin( FontWeight eWeight )
+{
+ switch ( eWeight )
+ {
+ case WEIGHT_THIN:
+ return FW_THIN;
+
+ case WEIGHT_ULTRALIGHT:
+ return FW_ULTRALIGHT;
+
+ case WEIGHT_LIGHT:
+ return FW_LIGHT;
+
+ case WEIGHT_SEMILIGHT:
+ case WEIGHT_NORMAL:
+ return FW_NORMAL;
+
+ case WEIGHT_MEDIUM:
+ return FW_MEDIUM;
+
+ case WEIGHT_SEMIBOLD:
+ return FW_SEMIBOLD;
+
+ case WEIGHT_BOLD:
+ return FW_BOLD;
+
+ case WEIGHT_ULTRABOLD:
+ return FW_ULTRABOLD;
+
+ case WEIGHT_BLACK:
+ return FW_BLACK;
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+inline FontPitch ImplLogPitchToSal( BYTE nPitch )
+{
+ if ( nPitch & FIXED_PITCH )
+ return PITCH_FIXED;
+ else
+ return PITCH_VARIABLE;
+}
+
+// -----------------------------------------------------------------------
+
+inline FontPitch ImplMetricPitchToSal( BYTE nPitch )
+{
+ // Sausaecke bei MS !! siehe NT Hilfe
+ if ( !(nPitch & TMPF_FIXED_PITCH) )
+ return PITCH_FIXED;
+ else
+ return PITCH_VARIABLE;
+}
+
+// -----------------------------------------------------------------------
+
+inline BYTE ImplPitchToWin( FontPitch ePitch )
+{
+ if ( ePitch == PITCH_FIXED )
+ return FIXED_PITCH;
+ else if ( ePitch == PITCH_VARIABLE )
+ return VARIABLE_PITCH;
+ else
+ return DEFAULT_PITCH;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplLogMetricToDevFontDataA( const LOGFONTA* pLogFont,
+ const NEWTEXTMETRICA* pMetric,
+ DWORD nFontType,
+ ImplFontData* pData )
+{
+ if ( !(nFontType & RASTER_FONTTYPE) )
+ {
+ pData->mnWidth = 0;
+ pData->mnHeight = 0;
+ }
+ else
+ {
+ pData->mnWidth = 0;
+ pData->mnHeight = pMetric->tmHeight-pMetric->tmInternalLeading;
+ }
+ pData->meFamily = ImplFamilyToSal( pLogFont->lfPitchAndFamily );
+ pData->meCharSet = ImplCharSetToSal( pLogFont->lfCharSet );
+ pData->meWidthType = WIDTH_DONTKNOW;
+ pData->meWeight = ImplWeightToSal( pLogFont->lfWeight );
+ pData->meItalic = (pLogFont->lfItalic) ? ITALIC_NORMAL : ITALIC_NONE;
+ pData->mePitch = ImplLogPitchToSal( pLogFont->lfPitchAndFamily );
+ if ( pMetric->tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE) )
+ pData->meType = TYPE_SCALABLE;
+ else
+ pData->meType = TYPE_RASTER;
+ pData->mbOrientation = (nFontType & RASTER_FONTTYPE) == 0;
+ pData->mbDevice = (pMetric->tmPitchAndFamily & TMPF_DEVICE) != 0;
+ pData->mnQuality = 0;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplLogMetricToDevFontDataW( const LOGFONTW* pLogFont,
+ const NEWTEXTMETRICW* pMetric,
+ DWORD nFontType,
+ ImplFontData* pData )
+{
+ if ( !(nFontType & RASTER_FONTTYPE) )
+ {
+ pData->mnWidth = 0;
+ pData->mnHeight = 0;
+ }
+ else
+ {
+ pData->mnWidth = 0;
+ pData->mnHeight = pMetric->tmHeight-pMetric->tmInternalLeading;
+ }
+ pData->meFamily = ImplFamilyToSal( pLogFont->lfPitchAndFamily );
+ pData->meCharSet = ImplCharSetToSal( pLogFont->lfCharSet );
+ pData->meWidthType = WIDTH_DONTKNOW;
+ pData->meWeight = ImplWeightToSal( pLogFont->lfWeight );
+ pData->meItalic = (pLogFont->lfItalic) ? ITALIC_NORMAL : ITALIC_NONE;
+ pData->mePitch = ImplLogPitchToSal( pLogFont->lfPitchAndFamily );
+ if ( pMetric->tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE) )
+ pData->meType = TYPE_SCALABLE;
+ else
+ pData->meType = TYPE_RASTER;
+ pData->mbOrientation = (nFontType & RASTER_FONTTYPE) == 0;
+ pData->mbDevice = (pMetric->tmPitchAndFamily & TMPF_DEVICE) != 0;
+ pData->mnQuality = 0;
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalLogFontToFontA( const LOGFONTA& rLogFont, Font& rFont )
+{
+ XubString aFontName( ImplSalGetUniString( rLogFont.lfFaceName ) );
+ if ( aFontName.Len() )
+ {
+ rFont.SetName( aFontName );
+ long nFontHeight = rLogFont.lfHeight;
+ if ( nFontHeight < 0 )
+ nFontHeight = -nFontHeight;
+ HDC hDC = GetDC( 0 );
+ long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY );
+ ReleaseDC( 0, hDC );
+ nFontHeight *= 72;
+ nFontHeight += nDPIY/2;
+ nFontHeight /= nDPIY;
+ rFont.SetSize( Size( 0, nFontHeight ) );
+ rFont.SetOrientation( (short)rLogFont.lfEscapement );
+ rFont.SetCharSet( ImplCharSetToSal( rLogFont.lfCharSet ) );
+ rFont.SetFamily( ImplFamilyToSal( rLogFont.lfPitchAndFamily ) );
+ rFont.SetPitch( ImplLogPitchToSal( rLogFont.lfPitchAndFamily ) );
+ rFont.SetWeight( ImplWeightToSal( rLogFont.lfWeight ) );
+ if ( rLogFont.lfItalic )
+ rFont.SetItalic( ITALIC_NORMAL );
+ else
+ rFont.SetItalic( ITALIC_NONE );
+ if ( rLogFont.lfUnderline )
+ rFont.SetUnderline( UNDERLINE_SINGLE );
+ else
+ rFont.SetUnderline( UNDERLINE_NONE );
+ if ( rLogFont.lfStrikeOut )
+ rFont.SetStrikeout( STRIKEOUT_SINGLE );
+ else
+ rFont.SetStrikeout( STRIKEOUT_NONE );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void ImplSalLogFontToFontW( const LOGFONTW& rLogFont, Font& rFont )
+{
+ XubString aFontName( rLogFont.lfFaceName );
+ if ( aFontName.Len() )
+ {
+ rFont.SetName( aFontName );
+ long nFontHeight = rLogFont.lfHeight;
+ if ( nFontHeight < 0 )
+ nFontHeight = -nFontHeight;
+ HDC hDC = GetDC( 0 );
+ long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY );
+ ReleaseDC( 0, hDC );
+ nFontHeight *= 72;
+ nFontHeight += nDPIY/2;
+ nFontHeight /= nDPIY;
+ rFont.SetSize( Size( 0, nFontHeight ) );
+ rFont.SetOrientation( (short)rLogFont.lfEscapement );
+ rFont.SetCharSet( ImplCharSetToSal( rLogFont.lfCharSet ) );
+ rFont.SetFamily( ImplFamilyToSal( rLogFont.lfPitchAndFamily ) );
+ rFont.SetPitch( ImplLogPitchToSal( rLogFont.lfPitchAndFamily ) );
+ rFont.SetWeight( ImplWeightToSal( rLogFont.lfWeight ) );
+ if ( rLogFont.lfItalic )
+ rFont.SetItalic( ITALIC_NORMAL );
+ else
+ rFont.SetItalic( ITALIC_NONE );
+ if ( rLogFont.lfUnderline )
+ rFont.SetUnderline( UNDERLINE_SINGLE );
+ else
+ rFont.SetUnderline( UNDERLINE_NONE );
+ if ( rLogFont.lfStrikeOut )
+ rFont.SetStrikeout( STRIKEOUT_SINGLE );
+ else
+ rFont.SetStrikeout( STRIKEOUT_NONE );
+ }
+}
+
+// =======================================================================
+
+void SalGraphics::SetTextColor( SalColor nSalColor )
+{
+ COLORREF aCol = PALETTERGB( SALCOLOR_RED( nSalColor ),
+ SALCOLOR_GREEN( nSalColor ),
+ SALCOLOR_BLUE( nSalColor ) );
+
+ if( !maGraphicsData.mbPrinter &&
+ GetSalData()->mhDitherPal &&
+ ImplIsSysColorEntry( nSalColor ) )
+ {
+ aCol = PALRGB_TO_RGB( aCol );
+ }
+
+ ::SetTextColor( maGraphicsData.mhDC, aCol );
+}
+
+// -----------------------------------------------------------------------
+
+USHORT SalGraphics::SetFont( ImplFontSelectData* pFont )
+{
+ HFONT hNewFont;
+ if ( aSalShlData.mbWNT )
+ {
+ LOGFONTW aLogFont;
+ UniString aName;
+ if ( pFont->mpFontData )
+ aName = pFont->mpFontData->maName;
+ else
+ aName = pFont->maName.GetToken( 0 );
+
+ UINT nNameLen = aName.Len();
+ if ( nNameLen > (sizeof( aLogFont.lfFaceName )/sizeof( wchar_t ))-1 )
+ nNameLen = (sizeof( aLogFont.lfFaceName )/sizeof( wchar_t ))-1;
+ memcpy( aLogFont.lfFaceName, aName.GetBuffer(), nNameLen*sizeof( wchar_t ) );
+ aLogFont.lfFaceName[nNameLen] = 0;
+ if ( pFont->mpFontData &&
+ ((pFont->meCharSet == RTL_TEXTENCODING_DONTKNOW) ||
+ ((WIN_BYTE)(pFont->mpFontData->mpSysData) == OEM_CHARSET)) )
+ aLogFont.lfCharSet = (WIN_BYTE)(pFont->mpFontData->mpSysData);
+ else
+ aLogFont.lfCharSet = ImplCharSetToWin( pFont->meCharSet );
+ aLogFont.lfPitchAndFamily = ImplPitchToWin( pFont->mePitch );
+ aLogFont.lfPitchAndFamily |= ImplFamilyToWin( pFont->meFamily );
+ aLogFont.lfWeight = ImplWeightToWin( pFont->meWeight );
+ aLogFont.lfHeight = (int)-pFont->mnHeight;
+ aLogFont.lfWidth = (int)pFont->mnWidth;
+ aLogFont.lfUnderline = 0;
+ aLogFont.lfStrikeOut = 0;
+ aLogFont.lfItalic = (pFont->meItalic) != ITALIC_NONE;
+ aLogFont.lfEscapement = pFont->mnOrientation;
+ aLogFont.lfOrientation = 0;
+ aLogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ aLogFont.lfQuality = DEFAULT_QUALITY;
+ if ( pFont->mnOrientation )
+ {
+ aLogFont.lfOutPrecision = OUT_TT_PRECIS;
+ aLogFont.lfClipPrecision |= CLIP_LH_ANGLES;
+ }
+ else
+ aLogFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
+
+ // Auf dem Bildschirm nehmen wir Courier New, wenn Courier nicht
+ // skalierbar ist und wenn der Font skaliert oder rotiert werden
+ // muss
+ if ( maGraphicsData.mbScreen &&
+ (pFont->mnWidth || pFont->mnOrientation ||
+ !pFont->mpFontData || (pFont->mpFontData->mnHeight != pFont->mnHeight)) &&
+ !bImplSalCourierScalable && bImplSalCourierNew &&
+ (ImplSalWICompareAscii( aLogFont.lfFaceName, "Courier" ) == 0) )
+ lstrcpyW( aLogFont.lfFaceName, L"Courier New" );
+
+ hNewFont = CreateFontIndirectW( &aLogFont );
+ }
+ else
+ {
+ if ( !maGraphicsData.mpLogFont )
+ maGraphicsData.mpLogFont = new LOGFONTA;
+
+ ByteString aName;
+ if ( pFont->mpFontData )
+ aName = ImplSalGetWinAnsiString( pFont->mpFontData->maName );
+ else
+ aName = ImplSalGetWinAnsiString( pFont->maName.GetToken( 0 ) );
+ UINT nNameLen = aName.Len();
+ if ( nNameLen > sizeof( maGraphicsData.mpLogFont->lfFaceName )-1 )
+ nNameLen = sizeof( maGraphicsData.mpLogFont->lfFaceName )-1;
+ memcpy( maGraphicsData.mpLogFont->lfFaceName, aName.GetBuffer(), nNameLen );
+ maGraphicsData.mpLogFont->lfFaceName[nNameLen] = 0;
+ if ( pFont->mpFontData &&
+ ((pFont->meCharSet == RTL_TEXTENCODING_DONTKNOW) ||
+ ((WIN_BYTE)(pFont->mpFontData->mpSysData) == OEM_CHARSET)) )
+ maGraphicsData.mpLogFont->lfCharSet = (WIN_BYTE)(pFont->mpFontData->mpSysData);
+ else
+ maGraphicsData.mpLogFont->lfCharSet = ImplCharSetToWin( pFont->meCharSet );
+ maGraphicsData.mpLogFont->lfPitchAndFamily = ImplPitchToWin( pFont->mePitch );
+ maGraphicsData.mpLogFont->lfPitchAndFamily |= ImplFamilyToWin( pFont->meFamily );
+ maGraphicsData.mpLogFont->lfWeight = ImplWeightToWin( pFont->meWeight );
+ maGraphicsData.mpLogFont->lfHeight = (int)-pFont->mnHeight;
+ maGraphicsData.mpLogFont->lfWidth = (int)pFont->mnWidth;
+ maGraphicsData.mpLogFont->lfUnderline = 0;
+ maGraphicsData.mpLogFont->lfStrikeOut = 0;
+ maGraphicsData.mpLogFont->lfItalic = (pFont->meItalic) != ITALIC_NONE;
+ maGraphicsData.mpLogFont->lfEscapement = pFont->mnOrientation;
+ maGraphicsData.mpLogFont->lfOrientation = 0;
+ maGraphicsData.mpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ maGraphicsData.mpLogFont->lfQuality = DEFAULT_QUALITY;
+ if ( pFont->mnOrientation )
+ {
+ maGraphicsData.mpLogFont->lfOutPrecision = OUT_TT_PRECIS;
+ maGraphicsData.mpLogFont->lfClipPrecision |= CLIP_LH_ANGLES;
+ }
+ else
+ maGraphicsData.mpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
+
+ // Auf dem Bildschirm nehmen wir Courier New, wenn Courier nicht
+ // skalierbar ist und wenn der Font skaliert oder rotiert werden
+ // muss
+ if ( maGraphicsData.mbScreen &&
+ (pFont->mnWidth || pFont->mnOrientation ||
+ !pFont->mpFontData || (pFont->mpFontData->mnHeight != pFont->mnHeight)) &&
+ !bImplSalCourierScalable && bImplSalCourierNew &&
+ (stricmp( maGraphicsData.mpLogFont->lfFaceName, "Courier" ) == 0) )
+ strcpy( maGraphicsData.mpLogFont->lfFaceName, "Courier New" );
+
+ hNewFont = CreateFontIndirectA( maGraphicsData.mpLogFont );
+ }
+
+ HFONT hOldFont = SelectFont( maGraphicsData.mhDC, hNewFont );
+
+ // destory or save old font
+ if ( maGraphicsData.mhFont )
+ DeleteFont( maGraphicsData.mhFont );
+ else
+ maGraphicsData.mhDefFont = hOldFont;
+
+ // set new data
+ maGraphicsData.mhFont = hNewFont;
+ maGraphicsData.mbCalcOverhang = TRUE;
+
+ maGraphicsData.mnFontCharSetCount = 0;
+ maGraphicsData.mbFontKernInit = TRUE;
+ if ( maGraphicsData.mpFontKernPairs )
+ {
+ delete maGraphicsData.mpFontKernPairs;
+ maGraphicsData.mpFontKernPairs = 0;
+ }
+ maGraphicsData.mnFontKernPairCount = 0;
+
+ // Auf dem Printer immer mit DrawTextArray arbeiten, da dort die
+ // Zeichenbreiten genauer als Pixel sein koennen
+ if ( maGraphicsData.mbPrinter )
+ return SAL_SETFONT_USEDRAWTEXTARRAY;
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+long SalGraphics::GetCharWidth( sal_Unicode nChar1, sal_Unicode nChar2, long* pWidthAry )
+{
+ SIZE aExtent;
+ SIZE aExtent2;
+ sal_Unicode nCharCount = nChar2-nChar1+1;
+ sal_Unicode i;
+ int* pWinWidthAry = (int*)pWidthAry;
+ DBG_ASSERT( sizeof( int ) == sizeof( long ), "SalGraphics::GetCharWidth(): int != long" );
+
+ // Da nicht bei allen Treibern diese Funktion funktioniert
+ if ( !GetCharWidthW( maGraphicsData.mhDC, nChar1, nChar2, pWinWidthAry ) )
+ {
+ for ( i = 0; i < nCharCount; i++ )
+ {
+ WCHAR c =i+nChar1;
+ if ( !GetTextExtentPointW( maGraphicsData.mhDC, &c, 1, &aExtent ) )
+ pWinWidthAry[i] = 0;
+ else
+ pWinWidthAry[i] = aExtent.cx;
+ }
+ }
+
+ // Ueberhang abziehen
+ if ( maGraphicsData.mbCalcOverhang )
+ {
+ WCHAR aAA[2] = { 'A', 'A' };
+ if ( GetTextExtentPointW( maGraphicsData.mhDC, aAA, 2, &aExtent ) &&
+ GetTextExtentPointW( maGraphicsData.mhDC, aAA, 1, &aExtent2 ) )
+ {
+ maGraphicsData.mbCalcOverhang = FALSE;
+ maGraphicsData.mnFontOverhang = (aExtent2.cx*2)-aExtent.cx;
+ }
+
+ int nOverhang = maGraphicsData.mnFontOverhang;
+ if ( nOverhang )
+ {
+ for ( i = 0; i < nCharCount; i++ )
+ pWinWidthAry[i] -= nOverhang;
+ }
+ }
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+void SalGraphics::GetFontMetric( ImplFontMetricData* pMetric )
+{
+ if ( aSalShlData.mbWNT )
+ {
+ wchar_t aFaceName[LF_FACESIZE+60];
+ GetTextFaceW( maGraphicsData.mhDC, sizeof( aFaceName ), aFaceName );
+ pMetric->maName = aFaceName;
+
+ TEXTMETRICW aWinMetric;
+ GetTextMetricsW( maGraphicsData.mhDC, &aWinMetric );
+
+ pMetric->mnWidth = aWinMetric.tmAveCharWidth;
+ pMetric->meFamily = ImplFamilyToSal( aWinMetric.tmPitchAndFamily );;
+ pMetric->meCharSet = ImplCharSetToSal( aWinMetric.tmCharSet );
+ pMetric->meWeight = ImplWeightToSal( aWinMetric.tmWeight );
+ pMetric->mePitch = ImplMetricPitchToSal( aWinMetric.tmPitchAndFamily );
+ if ( aWinMetric.tmItalic )
+ pMetric->meItalic = ITALIC_NORMAL;
+ else
+ pMetric->meItalic = ITALIC_NONE;
+ if ( aWinMetric.tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE) )
+ pMetric->meType = TYPE_SCALABLE;
+ else
+ {
+ pMetric->meType = TYPE_RASTER;
+ pMetric->mnOrientation = 0;
+ }
+ pMetric->mbDevice = (aWinMetric.tmPitchAndFamily & TMPF_DEVICE) != 0;
+ pMetric->mnAscent = aWinMetric.tmAscent;
+ pMetric->mnDescent = aWinMetric.tmDescent;
+ pMetric->mnLeading = aWinMetric.tmInternalLeading;
+ pMetric->mnSlant = 0;
+ pMetric->mnFirstChar = 0;
+ pMetric->mnLastChar = 0xFF;
+ }
+ else
+ {
+ char aFaceName[LF_FACESIZE+60];
+ GetTextFaceA( maGraphicsData.mhDC, sizeof( aFaceName ), aFaceName );
+ pMetric->maName = ImplSalGetUniString( aFaceName );
+
+ TEXTMETRICA aWinMetric;
+ GetTextMetricsA( maGraphicsData.mhDC, &aWinMetric );
+
+ pMetric->mnWidth = aWinMetric.tmAveCharWidth;
+ pMetric->meFamily = ImplFamilyToSal( aWinMetric.tmPitchAndFamily );;
+ pMetric->meCharSet = ImplCharSetToSal( aWinMetric.tmCharSet );
+ pMetric->meWeight = ImplWeightToSal( aWinMetric.tmWeight );
+ pMetric->mePitch = ImplMetricPitchToSal( aWinMetric.tmPitchAndFamily );
+ if ( aWinMetric.tmItalic )
+ pMetric->meItalic = ITALIC_NORMAL;
+ else
+ pMetric->meItalic = ITALIC_NONE;
+ if ( aWinMetric.tmPitchAndFamily & (TMPF_VECTOR | TMPF_TRUETYPE) )
+ pMetric->meType = TYPE_SCALABLE;
+ else
+ {
+ pMetric->meType = TYPE_RASTER;
+ pMetric->mnOrientation = 0;
+ }
+ pMetric->mbDevice = (aWinMetric.tmPitchAndFamily & TMPF_DEVICE) != 0;
+ pMetric->mnAscent = aWinMetric.tmAscent;
+ pMetric->mnDescent = aWinMetric.tmDescent;
+ pMetric->mnLeading = aWinMetric.tmInternalLeading;
+ pMetric->mnSlant = 0;
+ pMetric->mnFirstChar = 0;
+ pMetric->mnLastChar = 0xFF;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+int CALLBACK SalEnumCharSetsProcExA( const ENUMLOGFONTEXA* pLogFont,
+ const NEWTEXTMETRICEXA* pMetric,
+ DWORD nFontType, LPARAM lParam )
+{
+ SalGraphicsData* pData = (SalGraphicsData*)lParam;
+ // Charset already in the list?
+ for ( BYTE i = 0; i < pData->mnFontCharSetCount; i++ )
+ {
+ if ( pData->mpFontCharSets[i] == pLogFont->elfLogFont.lfCharSet )
+ return 1;
+ }
+ pData->mpFontCharSets[pData->mnFontCharSetCount] = pLogFont->elfLogFont.lfCharSet;
+ pData->mnFontCharSetCount++;
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplGetAllFontCharSets( SalGraphicsData* pData )
+{
+ if ( !pData->mpFontCharSets )
+ pData->mpFontCharSets = new BYTE[256];
+
+ LOGFONTA aLogFont;
+ memset( &aLogFont, 0, sizeof( aLogFont ) );
+ aLogFont.lfCharSet = DEFAULT_CHARSET;
+ GetTextFace( pData->mhDC, sizeof( aLogFont.lfFaceName ), aLogFont.lfFaceName );
+ EnumFontFamiliesExA( pData->mhDC, &aLogFont, (FONTENUMPROCA)SalEnumCharSetsProcExA,
+ (LPARAM)(void*)pData, 0 );
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplAddKerningPairs( SalGraphicsData* pData )
+{
+ ULONG nPairs = ::GetKerningPairsA( pData->mhDC, 0, NULL );
+ if ( !nPairs )
+ return;
+
+ CHARSETINFO aInfo;
+ if ( !TranslateCharsetInfo( (DWORD*)(ULONG)GetTextCharset( pData->mhDC ), &aInfo, TCI_SRCCHARSET ) )
+ return;
+
+ if ( !pData->mpFontKernPairs )
+ pData->mpFontKernPairs = new KERNINGPAIR[nPairs];
+ else
+ {
+ KERNINGPAIR* pOldPairs = pData->mpFontKernPairs;
+ pData->mpFontKernPairs = new KERNINGPAIR[nPairs+pData->mnFontKernPairCount];
+ memcpy( pData->mpFontKernPairs, pOldPairs,
+ pData->mnFontKernPairCount*sizeof( KERNINGPAIR ) );
+ delete pOldPairs;
+ }
+
+ UINT nCP = aInfo.ciACP;
+ ULONG nOldPairs = pData->mnFontKernPairCount;
+ KERNINGPAIR* pTempPair = pData->mpFontKernPairs+pData->mnFontKernPairCount;
+ nPairs = ::GetKerningPairsA( pData->mhDC, nPairs, pTempPair );
+ for ( ULONG i = 0; i < nPairs; i++ )
+ {
+ unsigned char aBuf[2];
+ wchar_t nChar;
+ int nLen;
+ BOOL bAdd = TRUE;
+
+ // None-ASCII?, then we must convert the char
+ if ( (pTempPair->wFirst > 125) || (pTempPair->wFirst == 92) )
+ {
+ if ( pTempPair->wFirst < 256 )
+ {
+ aBuf[0] = (unsigned char)pTempPair->wFirst;
+ nLen = 1;
+ }
+ else
+ {
+ aBuf[0] = (unsigned char)(pTempPair->wFirst >> 8);
+ aBuf[1] = (unsigned char)(pTempPair->wFirst & 0xFF);
+ nLen = 2;
+ }
+ if ( MultiByteToWideChar( nCP, MB_PRECOMPOSED | MB_USEGLYPHCHARS,
+ (const char*)aBuf, nLen, &nChar, 1 ) )
+ pTempPair->wFirst = nChar;
+ else
+ bAdd = FALSE;
+ }
+ if ( (pTempPair->wSecond > 125) || (pTempPair->wSecond == 92) )
+ {
+ if ( pTempPair->wSecond < 256 )
+ {
+ aBuf[0] = (unsigned char)pTempPair->wSecond;
+ nLen = 1;
+ }
+ else
+ {
+ aBuf[0] = (unsigned char)(pTempPair->wSecond >> 8);
+ aBuf[1] = (unsigned char)(pTempPair->wSecond & 0xFF);
+ nLen = 2;
+ }
+ if ( MultiByteToWideChar( nCP, MB_PRECOMPOSED | MB_USEGLYPHCHARS,
+ (const char*)aBuf, nLen, &nChar, 1 ) )
+ pTempPair->wSecond = nChar;
+ else
+ bAdd = FALSE;
+ }
+
+ KERNINGPAIR* pTempPair2 = pData->mpFontKernPairs;
+ for ( ULONG j = 0; j < nOldPairs; j++ )
+ {
+ if ( (pTempPair2->wFirst == pTempPair->wFirst) &&
+ (pTempPair2->wSecond == pTempPair->wSecond) )
+ {
+ bAdd = FALSE;
+ break;
+ }
+ pTempPair2++;
+ }
+
+ if ( bAdd )
+ {
+ KERNINGPAIR* pDestPair = pData->mpFontKernPairs+pData->mnFontKernPairCount;
+ if ( pDestPair != pTempPair )
+ memcpy( pDestPair, pTempPair, sizeof( KERNINGPAIR ) );
+ pData->mnFontKernPairCount++;
+ }
+
+ pTempPair++;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+ULONG SalGraphics::GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs )
+{
+ DBG_ASSERT( sizeof( KERNINGPAIR ) == sizeof( ImplKernPairData ),
+ "SalGraphics::GetKernPairs(): KERNINGPAIR != ImplKernPairData" );
+
+ if ( aSalShlData.mbWNT )
+ {
+ if ( !pKernPairs )
+ return ::GetKerningPairsW( maGraphicsData.mhDC, 0, NULL );
+ else
+ return ::GetKerningPairsW( maGraphicsData.mhDC, nPairs, (KERNINGPAIR*)pKernPairs );
+ }
+ else
+ {
+ if ( maGraphicsData.mbFontKernInit )
+ {
+ if ( maGraphicsData.mpFontKernPairs )
+ {
+ delete maGraphicsData.mpFontKernPairs;
+ maGraphicsData.mpFontKernPairs = 0;
+ }
+ maGraphicsData.mnFontKernPairCount = 0;
+
+ if ( !maGraphicsData.mnFontCharSetCount )
+ ImplGetAllFontCharSets( &maGraphicsData );
+
+ if ( maGraphicsData.mnFontCharSetCount <= 1 )
+ ImplAddKerningPairs( &maGraphicsData );
+ else
+ {
+ // Query All Kerning Pairs from all possible CharSets
+ for ( BYTE i = 0; i < maGraphicsData.mnFontCharSetCount; i++ )
+ {
+ maGraphicsData.mpLogFont->lfCharSet = maGraphicsData.mpFontCharSets[i];
+ HFONT hNewFont = CreateFontIndirectA( maGraphicsData.mpLogFont );
+ HFONT hOldFont = SelectFont( maGraphicsData.mhDC, hNewFont );
+ ImplAddKerningPairs( &maGraphicsData );
+ SelectFont( maGraphicsData.mhDC, hOldFont );
+ DeleteFont( hNewFont );
+ }
+ }
+
+ maGraphicsData.mbFontKernInit = FALSE;
+ }
+
+ if ( !pKernPairs )
+ return maGraphicsData.mnFontKernPairCount;
+ else
+ {
+ if ( nPairs > maGraphicsData.mnFontKernPairCount )
+ nPairs = maGraphicsData.mnFontKernPairCount;
+ memcpy( pKernPairs, maGraphicsData.mpFontKernPairs,
+ nPairs*sizeof( ImplKernPairData ) );
+ return nPairs;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+int CALLBACK SalEnumFontsProcExA( const ENUMLOGFONTEXA* pLogFont,
+ const NEWTEXTMETRICEXA* pMetric,
+ DWORD nFontType, LPARAM lParam )
+{
+ ImplEnumInfo* pInfo = (ImplEnumInfo*)(void*)lParam;
+ if ( !pInfo->mpName )
+ {
+ // Ignore vertical fonts
+ if ( pLogFont->elfLogFont.lfFaceName[0] != '@' )
+ {
+ if ( !pInfo->mbImplSalCourierNew )
+ pInfo->mbImplSalCourierNew = stricmp( pLogFont->elfLogFont.lfFaceName, "Courier New" ) == 0;
+ if ( !pInfo->mbImplSalCourierScalable )
+ pInfo->mbCourier = stricmp( pLogFont->elfLogFont.lfFaceName, "Courier" ) == 0;
+ else
+ pInfo->mbCourier = FALSE;
+ XubString aName( ImplSalGetUniString( pLogFont->elfLogFont.lfFaceName ) );
+ pInfo->mpName = &aName;
+ strcpy( pInfo->mpLogFontA->lfFaceName, pLogFont->elfLogFont.lfFaceName );
+ pInfo->mpLogFontA->lfCharSet = pLogFont->elfLogFont.lfCharSet;
+ EnumFontFamiliesExA( pInfo->mhDC, pInfo->mpLogFontA, (FONTENUMPROCA)SalEnumFontsProcExA,
+ (LPARAM)(void*)pInfo, 0 );
+ pInfo->mpLogFontA->lfFaceName[0] = '\0';
+ pInfo->mpLogFontA->lfCharSet = DEFAULT_CHARSET;
+ pInfo->mpName = NULL;
+ pInfo->mbCourier = FALSE;
+ }
+ }
+ else
+ {
+ ImplFontData* pData = new ImplFontData;
+ pData->maName = *(pInfo->mpName);
+
+ ImplLogMetricToDevFontDataA( &(pLogFont->elfLogFont), &(pMetric->ntmTm), nFontType, pData );
+ // StyleName nur bei TrueType uebernehmen, da sonst bei 3.1 Mist drinsteht
+ if ( pMetric->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE )
+ pData->maStyleName = ImplSalGetUniString( (const char*)pLogFont->elfStyle );
+ pData->mpSysData = (void*)(pLogFont->elfLogFont.lfCharSet);
+ BOOL bAdd = TRUE;
+
+ // Wenn es sich um einen nicht skalierbaren Bildschirm-Font
+ // handelt, dann auf dem Drucker ignorieren
+ if ( pData->meType != TYPE_SCALABLE )
+ {
+ if ( pInfo->mbPrinter )
+ bAdd = pData->mbDevice;
+ }
+ else
+ {
+ // Feststellen, ob Courier skalierbar ist
+ if ( pInfo->mbCourier )
+ pInfo->mbImplSalCourierScalable = TRUE;
+ }
+
+ if ( bAdd )
+ pInfo->mpList->Add( pData );
+ else
+ delete pData;
+ }
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+int CALLBACK SalEnumFontsProcExW( const ENUMLOGFONTEXW* pLogFont,
+ const NEWTEXTMETRICEXW* pMetric,
+ DWORD nFontType, LPARAM lParam )
+{
+ ImplEnumInfo* pInfo = (ImplEnumInfo*)(void*)lParam;
+ if ( !pInfo->mpName )
+ {
+ // Ignore vertical fonts
+ if ( pLogFont->elfLogFont.lfFaceName[0] != '@' )
+ {
+ if ( !pInfo->mbImplSalCourierNew )
+ pInfo->mbImplSalCourierNew = ImplSalWICompareAscii( pLogFont->elfLogFont.lfFaceName, "Courier New" ) == 0;
+ if ( !pInfo->mbImplSalCourierScalable )
+ pInfo->mbCourier = ImplSalWICompareAscii( pLogFont->elfLogFont.lfFaceName, "Courier" ) == 0;
+ else
+ pInfo->mbCourier = FALSE;
+ XubString aName( pLogFont->elfLogFont.lfFaceName );
+ pInfo->mpName = &aName;
+ memcpy( pInfo->mpLogFontW->lfFaceName, pLogFont->elfLogFont.lfFaceName, (aName.Len()+1)*sizeof( wchar_t ) );
+ pInfo->mpLogFontW->lfCharSet = pLogFont->elfLogFont.lfCharSet;
+ EnumFontFamiliesExW( pInfo->mhDC, pInfo->mpLogFontW, (FONTENUMPROCW)SalEnumFontsProcExW,
+ (LPARAM)(void*)pInfo, 0 );
+ pInfo->mpLogFontW->lfFaceName[0] = '\0';
+ pInfo->mpLogFontW->lfCharSet = DEFAULT_CHARSET;
+ pInfo->mpName = NULL;
+ pInfo->mbCourier = FALSE;
+ }
+ }
+ else
+ {
+ ImplFontData* pData = new ImplFontData;
+ pData->maName = *(pInfo->mpName);
+
+ ImplLogMetricToDevFontDataW( &(pLogFont->elfLogFont), &(pMetric->ntmTm), nFontType, pData );
+ // StyleName nur bei TrueType uebernehmen, da sonst bei 3.1 Mist drinsteht
+ if ( pMetric->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE )
+ pData->maStyleName = pLogFont->elfStyle;
+ pData->mpSysData = (void*)(pLogFont->elfLogFont.lfCharSet);
+ BOOL bAdd = TRUE;
+
+ // Wenn es sich um einen nicht skalierbaren Bildschirm-Font
+ // handelt, dann auf dem Drucker ignorieren
+ if ( pData->meType != TYPE_SCALABLE )
+ {
+ if ( pInfo->mbPrinter )
+ bAdd = pData->mbDevice;
+ }
+ else
+ {
+ // Feststellen, ob Courier skalierbar ist
+ if ( pInfo->mbCourier )
+ pInfo->mbImplSalCourierScalable = TRUE;
+ }
+
+ if ( bAdd )
+ pInfo->mpList->Add( pData );
+ else
+ delete pData;
+ }
+
+ return 1;
+}
+
+// -----------------------------------------------------------------------
+
+void SalGraphics::GetDevFontList( ImplDevFontList* pList )
+{
+ ImplEnumInfo aInfo;
+ aInfo.mhDC = maGraphicsData.mhDC;
+ aInfo.mpList = pList;
+ aInfo.mpName = NULL;
+ aInfo.mpLogFontA = NULL;
+ aInfo.mpLogFontW = NULL;
+ aInfo.mbCourier = FALSE;
+ if ( !maGraphicsData.mbPrinter )
+ {
+ aInfo.mbImplSalCourierScalable = FALSE;
+ aInfo.mbImplSalCourierNew = FALSE;
+ aInfo.mbPrinter = FALSE;
+ }
+ else
+ {
+ aInfo.mbImplSalCourierScalable = TRUE;
+ aInfo.mbImplSalCourierNew = TRUE;
+ aInfo.mbPrinter = TRUE;
+ }
+
+ if ( aSalShlData.mbWNT )
+ {
+ LOGFONTW aLogFont;
+ memset( &aLogFont, 0, sizeof( aLogFont ) );
+ aLogFont.lfCharSet = DEFAULT_CHARSET;
+ aInfo.mpLogFontW = &aLogFont;
+ EnumFontFamiliesExW( maGraphicsData.mhDC, &aLogFont, (FONTENUMPROCW)SalEnumFontsProcExW,
+ (LPARAM)(void*)&aInfo, 0 );
+ }
+ else
+ {
+ LOGFONTA aLogFont;
+ memset( &aLogFont, 0, sizeof( aLogFont ) );
+ aLogFont.lfCharSet = DEFAULT_CHARSET;
+ aInfo.mpLogFontA = &aLogFont;
+ EnumFontFamiliesExA( maGraphicsData.mhDC, &aLogFont, (FONTENUMPROCA)SalEnumFontsProcExA,
+ (LPARAM)(void*)&aInfo, 0 );
+ }
+
+ // Feststellen, was es fuer Courier-Schriften auf dem Bildschirm gibt,
+ // um in SetFont() evt. Courier auf Courier New zu mappen
+ if ( !maGraphicsData.mbPrinter )
+ {
+ bImplSalCourierScalable = aInfo.mbImplSalCourierScalable;
+ bImplSalCourierNew = aInfo.mbImplSalCourierNew;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void SalGraphics::DrawText( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen )
+{
+ DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "SalGraphics::DrawText(): WCHAR != sal_Unicode" );
+
+ ::ExtTextOutW( maGraphicsData.mhDC, (int)nX, (int)nY,
+ 0, NULL, pStr, nLen, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void SalGraphics::DrawTextArray( long nX, long nY,
+ const xub_Unicode* pStr, xub_StrLen nLen,
+ const long* pDXAry )
+{
+ DBG_ASSERT( sizeof( WCHAR ) == sizeof( xub_Unicode ), "SalGraphics::DrawText(): WCHAR != sal_Unicode" );
+
+ if ( nLen < 2 )
+ ::ExtTextOutW( maGraphicsData.mhDC, (int)nX, (int)nY, 0, NULL, pStr, nLen, NULL );
+ else
+ {
+ int aStackAry[SAL_DRAWTEXT_STACKBUF];
+ int* pWinDXAry;
+
+ if ( nLen <= SAL_DRAWTEXT_STACKBUF )
+ pWinDXAry = aStackAry;
+ else
+ pWinDXAry = new int[nLen];
+
+ pWinDXAry[0] = (int)pDXAry[0];
+ for ( xub_StrLen i = 1; i < nLen-1; i++ )
+ pWinDXAry[i] = (int)pDXAry[i]-pDXAry[i-1];
+
+ // Breite vom letzten Zeichen ermitteln, da wir dieses auch
+ // beim Windows-XArray in der richtigen Breite reingeben
+ // muessen, um nicht auf Probleme bei einigen
+ // Grafikkarten oder Druckertreibern zu stossen
+ SIZE aExtent;
+ if ( GetTextExtentPointW( maGraphicsData.mhDC, pStr+nLen-1, 1, &aExtent ) )
+ pWinDXAry[nLen-1] = aExtent.cx;
+ else
+ pWinDXAry[nLen-1] = 4095;
+
+ // Text ausgeben
+ ::ExtTextOutW( maGraphicsData.mhDC, (int)nX, (int)nY, 0, NULL, pStr, nLen, pWinDXAry );
+
+ if ( pWinDXAry != aStackAry )
+ delete pWinDXAry;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static ULONG ImplIncreaseArrays( ULONG nSize, SalPoint** ppPoints, BYTE** ppFlags, ULONG nIncSize )
+{
+ const ULONG nOldSize = nSize;
+ SalPoint* pNewPoints = new SalPoint[ nSize += nIncSize ];
+ BYTE* pNewFlags = new BYTE[ nSize ];
+
+ if( *ppPoints )
+ {
+ memcpy( pNewPoints, *ppPoints, nOldSize * sizeof( SalPoint ) );
+ memset( pNewPoints + nOldSize, 0, nIncSize * sizeof( SalPoint ) );
+ delete[] *ppPoints;
+ }
+ else
+ memset( pNewPoints, 0, nSize * sizeof( SalPoint ) );
+
+ if( *ppFlags )
+ {
+ memcpy( pNewFlags, *ppFlags, nOldSize );
+ memset( pNewFlags + nOldSize, 0, nIncSize );
+ delete[] *ppFlags;
+ }
+ else
+ memset( pNewFlags, 0, nSize );
+
+ *ppPoints = pNewPoints;
+ *ppFlags = pNewFlags;
+
+ return nSize;
+}
+
+// -----------------------------------------------------------------------
+
+static void ImplGetFamilyAndAscents( HDC hDC, BYTE& rPitch, long& rAscent )
+{
+ rPitch = 0;
+ rAscent = 0;
+
+ if ( aSalShlData.mbWNT )
+ {
+ TEXTMETRICW aTextMetricW;
+ if ( GetTextMetricsW( hDC, &aTextMetricW ) )
+ {
+ rPitch = aTextMetricW.tmPitchAndFamily;
+ rAscent = aTextMetricW.tmAscent;
+ }
+ }
+ else
+ {
+ TEXTMETRICA aTextMetricA;
+ if ( GetTextMetricsA( hDC, &aTextMetricA ) )
+ {
+ rPitch = aTextMetricA.tmPitchAndFamily;
+ rAscent = aTextMetricA.tmAscent;
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+static BOOL ImplGetGlyphChar( SalGraphicsData* pData, sal_Unicode c,
+ WORD& rByteChar, HFONT& rOldFont )
+{
+ rOldFont = 0;
+
+ if ( !pData->mnFontCharSetCount )
+ ImplGetAllFontCharSets( pData );
+
+ // Try at first the current charset
+ CHARSETINFO aInfo;
+ char aDestBuf[2];
+ int nLen = 0;
+ WIN_BOOL bDefault;
+ if ( TranslateCharsetInfo( (DWORD*)(ULONG)GetTextCharset( pData->mhDC ), &aInfo, TCI_SRCCHARSET ) )
+ {
+ bDefault = FALSE;
+ nLen = WideCharToMultiByte( aInfo.ciACP,
+ WC_COMPOSITECHECK | WC_DISCARDNS | WC_DEFAULTCHAR,
+ &c, 1,
+ aDestBuf, sizeof( aDestBuf ),
+ NULL, &bDefault );
+ }
+
+ // Try all possible charsets
+ if ( (nLen != 1) || bDefault )
+ {
+ // Query All Kerning Pairs from all possible CharSets
+ for ( BYTE i = 0; i < pData->mnFontCharSetCount; i++ )
+ {
+ if ( TranslateCharsetInfo( (DWORD*)(ULONG)pData->mpFontCharSets[i], &aInfo, TCI_SRCCHARSET ) )
+ {
+ bDefault = FALSE;
+ nLen = WideCharToMultiByte( aInfo.ciACP,
+ WC_COMPOSITECHECK | WC_DISCARDNS | WC_DEFAULTCHAR,
+ &c, 1,
+ aDestBuf, sizeof( aDestBuf ),
+ NULL, &bDefault );
+ if ( (nLen == 1) && !bDefault )
+ {
+ pData->mpLogFont->lfCharSet = pData->mpFontCharSets[i];
+ HFONT hNewFont = CreateFontIndirectA( pData->mpLogFont );
+ rOldFont = SelectFont( pData->mhDC, hNewFont );
+ break;
+ }
+ }
+ }
+ }
+
+ // GetGlyphOutline() only works for characters < 256. For all characters
+ // greater than 256 we use the default mechanismn in VCL to scan
+ // the printed Glyph
+ if ( (nLen == 1) && !bDefault )
+ {
+ rByteChar = (unsigned char)aDestBuf[0];
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// -----------------------------------------------------------------------
+
+BOOL SalGraphics::GetGlyphBoundRect( xub_Unicode cChar, long* pX, long* pY,
+ long* pWidth, long* pHeight )
+{
+ HDC hDC = maGraphicsData.mhDC;
+ BYTE nPitchAndFamily;
+ long nAscent;
+
+ ImplGetFamilyAndAscents( hDC, nPitchAndFamily, nAscent );
+ if ( !(nPitchAndFamily & TMPF_TRUETYPE) )
+ return FALSE;
+
+ GLYPHMETRICS aGlyphMetrics;
+ MAT2 aMat;
+ DWORD nSize;
+ BOOL bOK;
+ HFONT hOldFont = 0;
+
+ // Einheitsmatrix erzeugen
+ aMat.eM11 = FixedFromDouble(1.);
+ aMat.eM12 = FixedFromDouble(0.);
+ aMat.eM21 = FixedFromDouble(0.);
+ aMat.eM22 = FixedFromDouble(1.);
+ if ( aSalShlData.mbWNT )
+ nSize = ::GetGlyphOutlineW( hDC, cChar, GGO_METRICS, &aGlyphMetrics, 0, NULL, &aMat );
+ else
+ {
+ WORD nChar;
+ if ( ImplGetGlyphChar( &maGraphicsData, cChar, nChar, hOldFont ) )
+ nSize = ::GetGlyphOutlineA( hDC, nChar, GGO_METRICS, &aGlyphMetrics, 0, NULL, &aMat );
+ else
+ nSize = 0;
+ }
+ bOK = (nSize != GDI_ERROR) && nSize;
+ if ( bOK )
+ {
+ *pX = aGlyphMetrics.gmptGlyphOrigin.x;
+ *pY = nAscent - aGlyphMetrics.gmptGlyphOrigin.y;
+ *pWidth = aGlyphMetrics.gmBlackBoxX;
+ *pHeight = aGlyphMetrics.gmBlackBoxY;
+ }
+
+ if ( hOldFont )
+ {
+ HFONT hNewFont = SelectFont( maGraphicsData.mhDC, hOldFont );
+ DeleteFont( hNewFont );
+ }
+
+ return bOK;
+}
+
+// -----------------------------------------------------------------------
+
+ULONG SalGraphics::GetGlyphOutline( xub_Unicode cChar, USHORT** ppPolySizes,
+ SalPoint** ppPoints, BYTE** ppFlags )
+{
+ HDC hDC = maGraphicsData.mhDC;
+ BYTE nPitchAndFamily;
+ long nAscent;
+
+ ImplGetFamilyAndAscents( hDC, nPitchAndFamily, nAscent );
+ if ( !(nPitchAndFamily & TMPF_TRUETYPE) )
+ return 0;
+
+ GLYPHMETRICS aGlyphMetrics;
+ MAT2 aMat;
+ DWORD nSize;
+ USHORT nChar = cChar;
+ HFONT hOldFont = 0;
+ ULONG nPolyCount = 0;
+
+ // Einheitsmatrix erzeugen
+ aMat.eM11 = FixedFromDouble(1.);
+ aMat.eM12 = FixedFromDouble(0.);
+ aMat.eM21 = FixedFromDouble(0.);
+ aMat.eM22 = FixedFromDouble(1.);
+
+ if ( aSalShlData.mbWNT )
+ nSize = ::GetGlyphOutlineW( hDC, nChar, GGO_NATIVE, &aGlyphMetrics, 0, NULL, &aMat );
+ else
+ {
+ if ( ImplGetGlyphChar( &maGraphicsData, cChar, nChar, hOldFont ) )
+ nSize = ::GetGlyphOutlineA( hDC, nChar, GGO_NATIVE, &aGlyphMetrics, 0, NULL, &aMat );
+ else
+ nSize = 0;
+ }
+
+ if ( (nSize != GDI_ERROR) && nSize )
+ {
+ BYTE* pData = new BYTE[ nSize ];
+ ULONG nTotalCount = 0;
+ DWORD nSize2;
+ if ( aSalShlData.mbWNT )
+ nSize2 = ::GetGlyphOutlineW( hDC, nChar, GGO_NATIVE, &aGlyphMetrics, nSize, pData, &aMat );
+ else
+ nSize2 = ::GetGlyphOutlineA( hDC, nChar, GGO_NATIVE, &aGlyphMetrics, nSize, pData, &aMat );
+ if ( nSize == nSize2 )
+ {
+ ULONG nPtSize = GLYPH_INC;
+ SalPoint* pPoints = new SalPoint[ GLYPH_INC ];
+ SalPoint* pTotalPoints = NULL;
+ BYTE* pFlags = new BYTE[ GLYPH_INC ];
+ BYTE* pTotalFlags = NULL;
+ TTPOLYGONHEADER* pHeader = (TTPOLYGONHEADER*)pData;
+ TTPOLYCURVE* pCurve;
+ *ppPolySizes = new USHORT[ MAX_POLYCOUNT ];
+ memset( *ppPolySizes, 0, MAX_POLYCOUNT * sizeof( USHORT ) );
+
+ while ( ((BYTE*)pHeader < pData+nSize) && (nPolyCount < (MAX_POLYCOUNT - 1)) )
+ {
+ if ( pHeader->dwType == TT_POLYGON_TYPE )
+ {
+ USHORT nPnt = 0;
+ USHORT i;
+
+ memset( pPoints, 0, nPtSize * sizeof( SalPoint ) );
+ memset( pFlags, 0, nPtSize );
+
+ // ersten Startpunkt holen; die folgenden Startpunkte sind
+ // die Endpunkte der vorhergehenden Kurven
+ pPoints[ nPnt ].mnX = IntFromFixed( pHeader->pfxStart.x );
+ pPoints[ nPnt++ ].mnY = IntFromFixed( pHeader->pfxStart.y );
+
+ pCurve = (TTPOLYCURVE*) ( pHeader + 1 );
+
+ while ( (BYTE*)pCurve < (BYTE*)pHeader+pHeader->cb )
+ {
+ if ( TT_PRIM_LINE == pCurve->wType )
+ {
+ for( i = 0; i < pCurve->cpfx; i++ )
+ {
+ CHECKPOINTS( nPnt );
+ pPoints[ nPnt ].mnX = IntFromFixed( pCurve->apfx[ i ].x );
+ pPoints[ nPnt++ ].mnY = IntFromFixed( pCurve->apfx[ i ].y );
+ }
+ }
+ else if ( pCurve->wType == TT_PRIM_QSPLINE )
+ {
+ for ( i = 0; i < pCurve->cpfx; )
+ {
+ // Punkt B, der Kontrollpunkt der Kurve
+ CHECKPOINTS( nPnt );
+ pPoints[ nPnt ].mnX = IntFromFixed( pCurve->apfx[ i ].x );
+ pPoints[ nPnt ].mnY = IntFromFixed( pCurve->apfx[ i++ ].y );
+
+ // Punkt verdoppeln fuer Bezier-Wandlung
+ CHECKPOINTS( nPnt + 1UL );
+ pPoints[ nPnt + 1 ] = pPoints[ nPnt ];
+ nPnt += 2;
+
+ // Endpunkt der Kurve bestimmen
+ if ( i == (pCurve->cpfx - 1) )
+ {
+ // entweder letzter Punkt
+ CHECKPOINTS( nPnt );
+ pPoints[ nPnt ].mnX = IntFromFixed( pCurve->apfx[ i ].x );
+ pPoints[ nPnt++].mnY = IntFromFixed( pCurve->apfx[ i++ ].y );
+ }
+ else
+ {
+ // oder die Mitte zwischen den Kontrollpunkten
+ // dieser und der naechsten Kurce
+ CHECKPOINTS( nPnt );
+ pPoints[ nPnt ].mnX = IntFromFixed( fxDiv2( pCurve->apfx[ i - 1 ].x,
+ pCurve->apfx[ i ].x ) );
+ pPoints[ nPnt++ ].mnY = IntFromFixed( fxDiv2( pCurve->apfx[ i - 1 ].y,
+ pCurve->apfx[ i ].y ) );
+ }
+
+ // Umrechnung in Bezier ( PQ = TrueType-Controlpunkt):
+ // P1 = 1/3 * (P0 + 2 * PQ) / P2 = 1/3 * (P3 + 2 * PQ)
+ pPoints[ nPnt - 3 ].mnX = ( pPoints[ nPnt - 4 ].mnX +
+ ( pPoints[ nPnt - 3 ].mnX << 1 ) ) / 3;
+ pPoints[ nPnt - 3 ].mnY = ( pPoints[ nPnt - 4 ].mnY +
+ ( pPoints[ nPnt - 3 ].mnY << 1 ) ) / 3;
+
+ pPoints[ nPnt - 2 ].mnX = ( pPoints[ nPnt - 1 ].mnX +
+ ( pPoints[ nPnt - 2 ].mnX << 1 ) ) / 3;
+ pPoints[ nPnt - 2 ].mnY = ( pPoints[ nPnt - 1 ].mnY +
+ ( pPoints[ nPnt - 2 ].mnY << 1 ) ) / 3;
+
+ pFlags[ nPnt - 3 ] = pFlags[ nPnt - 2 ] = 2;
+ }
+ }
+
+ // weiter mit naechstem Kurvensegment
+ pCurve = (TTPOLYCURVE*) &pCurve->apfx[ i ];
+ }
+
+ CHECKPOINTS( nPnt );
+ pPoints[nPnt++] = pPoints[0];
+
+ if ( nPnt )
+ {
+ (*ppPolySizes)[ nPolyCount++ ] = nPnt;
+ ImplIncreaseArrays( nTotalCount, &pTotalPoints, &pTotalFlags, nPnt );
+
+ // Polygon senkrecht kippen: TrueType-Y-Koordinaten verlaufen von unten nach oben
+ for ( i = 0; i < nPnt; i++ )
+ {
+ pTotalPoints[ nTotalCount ].mnX = pPoints[i].mnX;
+ pTotalPoints[ nTotalCount ].mnY = nAscent - pPoints[i].mnY;
+ pTotalFlags[ nTotalCount++ ] = pFlags[i];
+ }
+ }
+
+ // naechstes Polygon
+ pHeader = (TTPOLYGONHEADER*) ( (BYTE*) pHeader + pHeader->cb );
+ }
+ }
+
+ delete[] pPoints;
+ delete[] pFlags;
+
+ if ( !nPolyCount )
+ {
+ delete[] pTotalPoints;
+ *ppPoints = NULL;
+ delete[] pTotalFlags;
+ *ppFlags = NULL;
+ delete[] *ppPolySizes;
+ *ppPolySizes = NULL;
+ }
+ else
+ {
+ *ppPoints = pTotalPoints;
+ *ppFlags = pTotalFlags;
+ }
+ }
+
+ delete [] pData;
+ }
+
+ if ( hOldFont )
+ {
+ HFONT hNewFont = SelectFont( maGraphicsData.mhDC, hOldFont );
+ DeleteFont( hNewFont );
+ }
+
+ return nPolyCount;
+}