| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svtools.hxx" |
| |
| |
| #include "winmtf.hxx" |
| #include <vcl/metaact.hxx> |
| #include <vcl/metric.hxx> |
| #include <rtl/tencinfo.h> |
| #include <vcl/svapp.hxx> |
| #include <vcl/virdev.hxx> |
| #include <vos/mutex.hxx> |
| |
| // ------------------------------------------------------------------------ |
| |
| #define WIN_MTF_MAX_CLIP_DEPTH 16 |
| |
| void WinMtfClipPath::ImpUpdateType() |
| { |
| if ( !aPolyPoly.Count() ) |
| eType = EMPTY; |
| else if ( aPolyPoly.IsRect() ) |
| eType = RECTANGLE; |
| else |
| eType = COMPLEX; |
| |
| bNeedsUpdate = sal_True; |
| } |
| |
| void WinMtfClipPath::IntersectClipRect( const Rectangle& rRect ) |
| { |
| if ( !aPolyPoly.Count() ) |
| aPolyPoly = Polygon( rRect ); |
| else if ( nDepth < WIN_MTF_MAX_CLIP_DEPTH ) |
| { |
| Polygon aPolygon( rRect ); |
| PolyPolygon aIntersection; |
| PolyPolygon aPolyPolyRect( aPolygon ); |
| aPolyPoly.GetIntersection( aPolyPolyRect, aIntersection ); |
| aPolyPoly = aIntersection; |
| nDepth++; |
| } |
| ImpUpdateType(); |
| } |
| |
| void WinMtfClipPath::ExcludeClipRect( const Rectangle& rRect ) |
| { |
| if ( aPolyPoly.Count() && ( nDepth < WIN_MTF_MAX_CLIP_DEPTH ) ) |
| { |
| Polygon aPolygon( rRect ); |
| PolyPolygon aPolyPolyRect( aPolygon ); |
| PolyPolygon aDifference; |
| aPolyPoly.GetDifference( aPolyPolyRect, aDifference ); |
| aPolyPoly = aDifference; |
| nDepth++; |
| } |
| ImpUpdateType(); |
| } |
| |
| void WinMtfClipPath::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode ) |
| { |
| PolyPolygon aSimplePoly; |
| if ( rPolyPolygon.Count() && rPolyPolygon[ 0 ].HasFlags() ) |
| rPolyPolygon.AdaptiveSubdivide( aSimplePoly, 100 ); |
| if ( !aSimplePoly.Count() ) |
| aPolyPoly = aSimplePoly; |
| else if ( nDepth < WIN_MTF_MAX_CLIP_DEPTH ) |
| { |
| nDepth++; |
| |
| PolyPolygon aNewClipPath; |
| |
| // #115345# Watch out for empty aPolyPoly here - conceptually, |
| // an empty clip path is a rectangle of infinite size, but it |
| // is represented by an empty aPolyPoly. When intersecting |
| // rPolyPolygon with this _empty_ aPolyPoly, set algebra |
| // guarantees wrong results. |
| switch ( nClippingMode ) |
| { |
| case RGN_OR : |
| // #115345# clip stays empty, when ORing an arbitrary |
| // rPolyPolygon. Thus, we can save us the unnecessary |
| // clipper call. |
| if( aPolyPoly.Count() ) |
| aPolyPoly.GetUnion( aSimplePoly, aNewClipPath ); |
| break; |
| case RGN_XOR : |
| // TODO: |
| // #115345# Cannot handle this case, for the time being |
| aPolyPoly.GetXOR( aSimplePoly, aNewClipPath ); |
| break; |
| case RGN_DIFF : |
| // TODO: |
| // #115345# Cannot handle this case, for the time being |
| aPolyPoly.GetDifference( aSimplePoly, aNewClipPath ); |
| break; |
| case RGN_AND : |
| // #115345# Clip becomes rPolyPolygon, when ANDing |
| // with an arbitrary rPolyPolygon |
| if( aPolyPoly.Count() ) |
| aPolyPoly.GetIntersection( aSimplePoly, aNewClipPath ); |
| else |
| aNewClipPath = aSimplePoly; |
| break; |
| case RGN_COPY : |
| aNewClipPath = aSimplePoly; |
| break; |
| } |
| aPolyPoly = aNewClipPath; |
| } |
| ImpUpdateType(); |
| } |
| |
| void WinMtfClipPath::MoveClipRegion( const Size& rSize ) |
| { |
| aPolyPoly.Move( rSize.Width(), rSize.Height() ); |
| bNeedsUpdate = sal_True; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void WinMtfPathObj::AddPoint( const Point& rPoint ) |
| { |
| if ( bClosed ) |
| Insert( Polygon(), POLYPOLY_APPEND ); |
| Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ]; |
| rPoly.Insert( rPoly.GetSize(), rPoint, POLY_NORMAL ); |
| bClosed = sal_False; |
| } |
| |
| void WinMtfPathObj::AddPolyLine( const Polygon& rPolyLine ) |
| { |
| if ( bClosed ) |
| Insert( Polygon(), POLYPOLY_APPEND ); |
| Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ]; |
| rPoly.Insert( rPoly.GetSize(), rPolyLine ); |
| bClosed = sal_False; |
| } |
| |
| void WinMtfPathObj::AddPolygon( const Polygon& rPoly ) |
| { |
| Insert( rPoly, POLYPOLY_APPEND ); |
| bClosed = sal_True; |
| } |
| |
| void WinMtfPathObj::AddPolyPolygon( const PolyPolygon& rPolyPoly ) |
| { |
| sal_uInt16 i, nCount = rPolyPoly.Count(); |
| for ( i = 0; i < nCount; i++ ) |
| Insert( rPolyPoly[ i ], POLYPOLY_APPEND ); |
| bClosed = sal_True; |
| } |
| |
| void WinMtfPathObj::ClosePath() |
| { |
| if ( Count() ) |
| { |
| Polygon& rPoly = ((PolyPolygon&)*this)[ Count() - 1 ]; |
| if ( rPoly.GetSize() > 2 ) |
| { |
| Point aFirst( rPoly[ 0 ] ); |
| if ( aFirst != rPoly[ rPoly.GetSize() - 1 ] ) |
| rPoly.Insert( rPoly.GetSize(), aFirst, POLY_NORMAL ); |
| } |
| } |
| bClosed = sal_True; |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| WinMtfFontStyle::WinMtfFontStyle( LOGFONTW& rFont ) |
| { |
| CharSet eCharSet; |
| if ( ( rFont.lfCharSet == OEM_CHARSET ) || ( rFont.lfCharSet == DEFAULT_CHARSET ) ) |
| eCharSet = gsl_getSystemTextEncoding(); |
| else |
| eCharSet = rtl_getTextEncodingFromWindowsCharset( rFont.lfCharSet ); |
| if ( eCharSet == RTL_TEXTENCODING_DONTKNOW ) |
| eCharSet = gsl_getSystemTextEncoding(); |
| aFont.SetCharSet( eCharSet ); |
| aFont.SetName( rFont.alfFaceName ); |
| FontFamily eFamily; |
| switch ( rFont.lfPitchAndFamily & 0xf0 ) |
| { |
| case FF_ROMAN: |
| eFamily = FAMILY_ROMAN; |
| break; |
| |
| case FF_SWISS: |
| eFamily = FAMILY_SWISS; |
| break; |
| |
| case FF_MODERN: |
| eFamily = FAMILY_MODERN; |
| break; |
| |
| case FF_SCRIPT: |
| eFamily = FAMILY_SCRIPT; |
| break; |
| |
| case FF_DECORATIVE: |
| eFamily = FAMILY_DECORATIVE; |
| break; |
| |
| default: |
| eFamily = FAMILY_DONTKNOW; |
| break; |
| } |
| aFont.SetFamily( eFamily ); |
| |
| FontPitch ePitch; |
| switch ( rFont.lfPitchAndFamily & 0x0f ) |
| { |
| case FIXED_PITCH: |
| ePitch = PITCH_FIXED; |
| break; |
| |
| case DEFAULT_PITCH: |
| case VARIABLE_PITCH: |
| default: |
| ePitch = PITCH_VARIABLE; |
| break; |
| } |
| aFont.SetPitch( ePitch ); |
| |
| FontWeight eWeight; |
| if( rFont.lfWeight <= FW_THIN ) |
| eWeight = WEIGHT_THIN; |
| else if( rFont.lfWeight <= FW_ULTRALIGHT ) |
| eWeight = WEIGHT_ULTRALIGHT; |
| else if( rFont.lfWeight <= FW_LIGHT ) |
| eWeight = WEIGHT_LIGHT; |
| else if( rFont.lfWeight < FW_MEDIUM ) |
| eWeight = WEIGHT_NORMAL; |
| else if( rFont.lfWeight == FW_MEDIUM ) |
| eWeight = WEIGHT_MEDIUM; |
| else if( rFont.lfWeight <= FW_SEMIBOLD ) |
| eWeight = WEIGHT_SEMIBOLD; |
| else if( rFont.lfWeight <= FW_BOLD ) |
| eWeight = WEIGHT_BOLD; |
| else if( rFont.lfWeight <= FW_ULTRABOLD ) |
| eWeight = WEIGHT_ULTRABOLD; |
| else |
| eWeight = WEIGHT_BLACK; |
| aFont.SetWeight( eWeight ); |
| |
| if( rFont.lfItalic ) |
| aFont.SetItalic( ITALIC_NORMAL ); |
| |
| if( rFont.lfUnderline ) |
| aFont.SetUnderline( UNDERLINE_SINGLE ); |
| |
| if( rFont.lfStrikeOut ) |
| aFont.SetStrikeout( STRIKEOUT_SINGLE ); |
| |
| if ( rFont.lfOrientation ) |
| aFont.SetOrientation( (short)rFont.lfOrientation ); |
| else |
| aFont.SetOrientation( (short)rFont.lfEscapement ); |
| |
| Size aFontSize( Size( rFont.lfWidth, rFont.lfHeight ) ); |
| if ( rFont.lfHeight > 0 ) |
| { |
| // #117968# VirtualDevice is not thread safe, but filter is used in multithreading |
| vos::OGuard aGuard( Application::GetSolarMutex() ); |
| VirtualDevice aVDev; |
| |
| // converting the cell height into a font height |
| aFont.SetSize( aFontSize ); |
| aVDev.SetFont( aFont ); |
| FontMetric aMetric( aVDev.GetFontMetric() ); |
| long nHeight = aMetric.GetAscent() + aMetric.GetDescent(); |
| if ( nHeight ) |
| { |
| double fHeight = ((double)aFontSize.Height() * rFont.lfHeight ) / nHeight; |
| aFontSize.Height() = (sal_Int32)( fHeight + 0.5 ); |
| } |
| } |
| else if ( aFontSize.Height() < 0 ) |
| aFontSize.Height() *= -1; |
| |
| if ( !rFont.lfWidth ) |
| { |
| // #117968# VirtualDevice is not thread safe, but filter is used in multithreading |
| vos::OGuard aGuard( Application::GetSolarMutex() ); |
| VirtualDevice aVDev; |
| |
| aFont.SetSize( aFontSize ); |
| aVDev.SetFont( aFont ); |
| FontMetric aMetric( aVDev.GetFontMetric() ); |
| aFontSize.Width() = aMetric.GetWidth(); |
| } |
| |
| aFont.SetSize( aFontSize ); |
| }; |
| |
| // ------------------------------------------------------------------------ |
| |
| #ifdef WIN_MTF_ASSERT |
| void WinMtfAssertHandler( const sal_Char* pAction, sal_uInt32 nFlags ) |
| { |
| static sal_Bool bOnlyOnce; |
| static sal_Int32 nAssertCount; |
| |
| if ( nFlags & WIN_MTF_ASSERT_INIT ) |
| nAssertCount = 0; |
| if ( nFlags & WIN_MTF_ASSERT_ONCE ) |
| bOnlyOnce = sal_True; |
| if ( nFlags & WIN_MTF_ASSERT_MIFE ) |
| { |
| if ( ( nAssertCount == 0 ) || ( bOnlyOnce == sal_False ) ) |
| { |
| ByteString aText( "WMF/EMF Import: " ); |
| if ( pAction ) |
| { |
| ByteString aAction( pAction ); |
| aText.Append( aAction ); |
| } |
| aText.Append( " needs to be implemented (SJ)" ); |
| DBG_ASSERT( 0, aText.GetBuffer() ); |
| } |
| nAssertCount++; |
| } |
| } |
| #endif |
| |
| // ------------------------------------------------------------------------ |
| |
| WinMtf::WinMtf( WinMtfOutput* pWinMtfOutput, SvStream& rStreamWMF, FilterConfigItem* pConfigItem ) : |
| pOut ( pWinMtfOutput ), |
| pWMF ( &rStreamWMF ), |
| pFilterConfigItem ( pConfigItem ) |
| { |
| #ifdef WIN_MTF_ASSERT |
| // we want to assert not implemented features, but we do this |
| // only once, so that nobody is handicaped by getting too much assertions |
| // I hope this will bring more testdocuments, without support of these |
| // testdocuments the implementation of missing features won't be possible. (SJ) |
| WinMtfAssertHandler( NULL, WIN_MTF_ASSERT_INIT | WIN_MTF_ASSERT_ONCE ); |
| #endif |
| |
| SvLockBytes *pLB = pWMF->GetLockBytes(); |
| if ( pLB ) |
| pLB->SetSynchronMode( sal_True ); |
| |
| nStartPos = pWMF->Tell(); |
| |
| pOut->SetDevOrg( Point() ); |
| if ( pFilterConfigItem ) |
| { |
| xStatusIndicator = pFilterConfigItem->GetStatusIndicator(); |
| if ( xStatusIndicator.is() ) |
| { |
| rtl::OUString aMsg; |
| xStatusIndicator->start( aMsg, 100 ); |
| } |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| WinMtf::~WinMtf() |
| { |
| delete pOut; |
| |
| if ( xStatusIndicator.is() ) |
| xStatusIndicator->end(); |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| void WinMtf::Callback( sal_uInt16 nPercent ) |
| { |
| if ( xStatusIndicator.is() ) |
| xStatusIndicator->setValue( nPercent ); |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| Color WinMtf::ReadColor() |
| { |
| sal_uInt32 nColor; |
| *pWMF >> nColor; |
| return Color( (sal_uInt8)nColor, (sal_uInt8)( nColor >> 8 ), (sal_uInt8)( nColor >> 16 ) ); |
| }; |
| |
| //----------------------------------------------------------------------------------- |
| //----------------------------------------------------------------------------------- |
| //----------------------------------------------------------------------------------- |
| |
| Point WinMtfOutput::ImplMap( const Point& rPt ) |
| { |
| if ( mnWinExtX && mnWinExtY ) |
| { |
| double fX2, fX = rPt.X(); |
| double fY2, fY = rPt.Y(); |
| |
| fX2 = fX * maXForm.eM11 + fY * maXForm.eM21 + maXForm.eDx; |
| fY2 = fX * maXForm.eM12 + fY * maXForm.eM22 + maXForm.eDy; |
| |
| if ( mnGfxMode == GM_COMPATIBLE ) |
| { |
| switch( mnMapMode ) |
| { |
| case MM_LOENGLISH : |
| { |
| fX2 -= mnWinOrgX; |
| fY2 = mnWinOrgY-fY2; |
| fX2 *= 25.40; |
| fY2 *= 25.40; |
| fX2 += mnDevOrgX; |
| fY2 += mnDevOrgY; |
| } |
| break; |
| case MM_HIENGLISH : |
| { |
| fX2 -= mnWinOrgX; |
| fY2 = mnWinOrgY-fY2; |
| fX2 *= 2.540; |
| fY2 *= 2.540; |
| fX2 += mnDevOrgX; |
| fY2 += mnDevOrgY; |
| } |
| break; |
| case MM_LOMETRIC : |
| { |
| fX2 -= mnWinOrgX; |
| fY2 = mnWinOrgY-fY2; |
| fX2 *= 10; |
| fY2 *= 10; |
| fX2 += mnDevOrgX; |
| fY2 += mnDevOrgY; |
| } |
| break; |
| case MM_HIMETRIC : |
| { |
| fX2 -= mnWinOrgX; |
| fY2 = mnWinOrgY-fY2; |
| fX2 += mnDevOrgX; |
| fY2 += mnDevOrgY; |
| } |
| break; |
| default : |
| { |
| fX2 -= mnWinOrgX; |
| fY2 -= mnWinOrgY; |
| fX2 /= mnWinExtX; |
| fY2 /= mnWinExtY; |
| fX2 *= mnDevWidth; |
| fY2 *= mnDevHeight; |
| fX2 += mnDevOrgX; |
| fY2 += mnDevOrgY; // fX2, fY2 now in device units |
| fX2 *= (double)mnMillX * 100.0 / (double)mnPixX; |
| fY2 *= (double)mnMillY * 100.0 / (double)mnPixY; |
| } |
| break; |
| } |
| fX2 -= mrclFrame.Left(); |
| fY2 -= mrclFrame.Top(); |
| } |
| return Point( FRound( fX2 ), FRound( fY2 ) ); |
| } |
| else |
| return Point(); |
| }; |
| |
| // ------------------------------------------------------------------------ |
| |
| Size WinMtfOutput::ImplMap( const Size& rSz ) |
| { |
| if ( mnWinExtX && mnWinExtY ) |
| { |
| // #121382# apply the whole WorldTransform, else a rotation will be misinterpreted |
| double fWidth = rSz.Width() * maXForm.eM11 + rSz.Height() * maXForm.eM21; |
| double fHeight = rSz.Width() * maXForm.eM12 + rSz.Height() * maXForm.eM22; |
| |
| if ( mnGfxMode == GM_COMPATIBLE ) |
| { |
| switch( mnMapMode ) |
| { |
| case MM_LOENGLISH : |
| { |
| fWidth *= 25.40; |
| fHeight*=-25.40; |
| } |
| break; |
| case MM_HIENGLISH : |
| { |
| fWidth *= 2.540; |
| fHeight*=-2.540; |
| } |
| break; |
| case MM_LOMETRIC : |
| { |
| fWidth *= 10; |
| fHeight*=-10; |
| } |
| break; |
| case MM_HIMETRIC : |
| { |
| fHeight *= -1; |
| } |
| break; |
| default : |
| { |
| fWidth /= mnWinExtX; |
| fHeight /= mnWinExtY; |
| fWidth *= mnDevWidth; |
| fHeight *= mnDevHeight; |
| fWidth *= (double)mnMillX * 100 / (double)mnPixX; |
| fHeight *= (double)mnMillY * 100 / (double)mnPixY; |
| } |
| break; |
| } |
| } |
| return Size( FRound( fWidth ), FRound( fHeight ) ); |
| } |
| else |
| return Size(); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| Rectangle WinMtfOutput::ImplMap( const Rectangle& rRect ) |
| { |
| return Rectangle( ImplMap( rRect.TopLeft() ), ImplMap( rRect.GetSize() ) ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::ImplMap( Font& rFont ) |
| { |
| // !!! HACK: Wir setzen die Breite jetzt immer auf Null, |
| // da OS die Breite unterschiedlich interpretieren; |
| // muss spaeter in SV portabel gemacht werden ( KA 08.02.96 ) |
| Size aFontSize = ImplMap ( rFont.GetSize() ); |
| |
| if( aFontSize.Height() < 0 ) |
| aFontSize.Height() *= -1; |
| |
| rFont.SetSize( aFontSize ); |
| |
| if( ( mnWinExtX * mnWinExtY ) < 0 ) |
| rFont.SetOrientation( 3600 - rFont.GetOrientation() ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| Polygon& WinMtfOutput::ImplMap( Polygon& rPolygon ) |
| { |
| sal_uInt16 nPoints = rPolygon.GetSize(); |
| for ( sal_uInt16 i = 0; i < nPoints; i++ ) |
| { |
| rPolygon[ i ] = ImplMap( rPolygon[ i ] ); |
| } |
| return rPolygon; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| PolyPolygon& WinMtfOutput::ImplMap( PolyPolygon& rPolyPolygon ) |
| { |
| sal_uInt16 nPolys = rPolyPolygon.Count(); |
| for ( sal_uInt16 i = 0; i < nPolys; ImplMap( rPolyPolygon[ i++ ] ) ) ; |
| return rPolyPolygon; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SelectObject( sal_Int32 nIndex ) |
| { |
| GDIObj* pGDIObj = NULL; |
| |
| if ( nIndex & ENHMETA_STOCK_OBJECT ) |
| pGDIObj = new GDIObj(); |
| else |
| { |
| nIndex &= 0xffff; // zur Sicherheit: mehr als 65535 nicht zulassen |
| |
| if ( (sal_uInt32)nIndex < vGDIObj.size() ) |
| pGDIObj = vGDIObj[ nIndex ]; |
| } |
| |
| if( pGDIObj == NULL ) |
| return; |
| |
| if ( nIndex & ENHMETA_STOCK_OBJECT ) |
| { |
| sal_uInt16 nStockId = (sal_uInt8)nIndex; |
| switch( nStockId ) |
| { |
| case WHITE_BRUSH : |
| { |
| pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_WHITE ) ) ); |
| } |
| break; |
| case LTGRAY_BRUSH : |
| { |
| pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_LIGHTGRAY ) ) ); |
| } |
| break; |
| case GRAY_BRUSH : |
| case DKGRAY_BRUSH : |
| { |
| pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_GRAY ) ) ); |
| } |
| break; |
| case BLACK_BRUSH : |
| { |
| pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_BLACK ) ) ); |
| } |
| break; |
| case NULL_BRUSH : |
| { |
| pGDIObj->Set( GDI_BRUSH, new WinMtfFillStyle( Color( COL_TRANSPARENT ), sal_True ) ); |
| } |
| break; |
| case WHITE_PEN : |
| { |
| pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_WHITE ) ) ); |
| } |
| break; |
| case BLACK_PEN : |
| { |
| pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_BLACK ) ) ); |
| } |
| break; |
| case NULL_PEN : |
| { |
| pGDIObj->Set( GDI_PEN, new WinMtfLineStyle( Color( COL_TRANSPARENT ), sal_True ) ); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| if ( pGDIObj->pStyle ) |
| { |
| switch( pGDIObj->eType ) |
| { |
| case GDI_PEN : |
| maLineStyle = (WinMtfLineStyle*)pGDIObj->pStyle; |
| break; |
| case GDI_BRUSH : |
| { |
| maFillStyle = (WinMtfFillStyle*)pGDIObj->pStyle; |
| mbFillStyleSelected = sal_True; |
| } |
| break; |
| case GDI_FONT : |
| maFont = ((WinMtfFontStyle*)pGDIObj->pStyle)->aFont; |
| break; |
| default: |
| break; // -Wall many options not handled. |
| } |
| } |
| if ( nIndex & ENHMETA_STOCK_OBJECT ) |
| delete pGDIObj; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetFont( const Font& rFont ) |
| { |
| maFont = rFont; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| const Font& WinMtfOutput::GetFont() const |
| { |
| return maFont; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetTextLayoutMode( const sal_uInt32 nTextLayoutMode ) |
| { |
| mnTextLayoutMode = nTextLayoutMode; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| sal_uInt32 WinMtfOutput::GetTextLayoutMode() const |
| { |
| return mnTextLayoutMode; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetBkMode( sal_uInt32 nMode ) |
| { |
| mnBkMode = nMode; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetBkColor( const Color& rColor ) |
| { |
| maBkColor = rColor; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetTextColor( const Color& rColor ) |
| { |
| maTextColor = rColor; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetTextAlign( sal_uInt32 nAlign ) |
| { |
| mnTextAlign = nAlign; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::ImplResizeObjectArry( sal_uInt32 nNewEntrys ) |
| { |
| sal_uInt32 i = vGDIObj.size(); |
| vGDIObj.resize( nNewEntrys ); |
| for ( ; i < nNewEntrys ; i++ ) |
| vGDIObj[ i ] = NULL; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::ImplDrawClippedPolyPolygon( const PolyPolygon& rPolyPoly ) |
| { |
| if ( rPolyPoly.Count() ) |
| { |
| ImplSetNonPersistentLineColorTransparenz(); |
| if ( rPolyPoly.Count() == 1 ) |
| { |
| if ( rPolyPoly.IsRect() ) |
| mpGDIMetaFile->AddAction( new MetaRectAction( rPolyPoly.GetBoundRect() ) ); |
| else |
| { |
| Polygon aPoly( rPolyPoly[ 0 ] ); |
| sal_uInt16 nCount = aPoly.GetSize(); |
| if ( nCount ) |
| { |
| if ( aPoly[ nCount - 1 ] != aPoly[ 0 ] ) |
| { |
| Point aPoint( aPoly[ 0 ] ); |
| aPoly.Insert( nCount, aPoint ); |
| } |
| mpGDIMetaFile->AddAction( new MetaPolygonAction( aPoly ) ); |
| } |
| } |
| } |
| else |
| mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPoly ) ); |
| } |
| } |
| |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::CreateObject( GDIObjectType eType, void* pStyle ) |
| { |
| if ( pStyle ) |
| { |
| if ( eType == GDI_FONT ) |
| { |
| ImplMap( ((WinMtfFontStyle*)pStyle)->aFont ); |
| if (!((WinMtfFontStyle*)pStyle)->aFont.GetHeight() ) |
| ((WinMtfFontStyle*)pStyle)->aFont.SetHeight( 423 ); // defaulting to 12pt |
| } |
| else if ( eType == GDI_PEN ) |
| { |
| Size aSize( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetWidth(), 0 ); |
| ((WinMtfLineStyle*)pStyle)->aLineInfo.SetWidth( ImplMap( aSize ).Width() ); |
| if ( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetStyle() == LINE_DASH ) |
| { |
| aSize.Width() += 1; |
| long nDotLen = ImplMap( aSize ).Width(); |
| ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDistance( nDotLen ); |
| ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDotLen( nDotLen ); |
| ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDashLen( nDotLen * 4 ); |
| } |
| } |
| } |
| sal_uInt32 nIndex; |
| for ( nIndex = 0; nIndex < vGDIObj.size(); nIndex++ ) |
| { |
| if ( vGDIObj[ nIndex ] == NULL ) |
| break; |
| } |
| if ( nIndex == vGDIObj.size() ) |
| ImplResizeObjectArry( vGDIObj.size() + 16 ); |
| |
| vGDIObj[ nIndex ] = new GDIObj( eType, pStyle ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::CreateObject( sal_Int32 nIndex, GDIObjectType eType, void* pStyle ) |
| { |
| if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 ) |
| { |
| nIndex &= 0xffff; // zur Sicherheit: mehr als 65535 nicht zulassen |
| if ( pStyle ) |
| { |
| if ( eType == GDI_FONT ) |
| ImplMap( ((WinMtfFontStyle*)pStyle)->aFont ); |
| else if ( eType == GDI_PEN ) |
| { |
| Size aSize( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetWidth(), 0 ); |
| ((WinMtfLineStyle*)pStyle)->aLineInfo.SetWidth( ImplMap( aSize ).Width() ); |
| if ( ((WinMtfLineStyle*)pStyle)->aLineInfo.GetStyle() == LINE_DASH ) |
| { |
| aSize.Width() += 1; |
| long nDotLen = ImplMap( aSize ).Width(); |
| ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDistance( nDotLen ); |
| ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDotLen( nDotLen ); |
| ((WinMtfLineStyle*)pStyle)->aLineInfo.SetDashLen( nDotLen * 4 ); |
| } |
| } |
| } |
| if ( (sal_uInt32)nIndex >= vGDIObj.size() ) |
| ImplResizeObjectArry( nIndex + 16 ); |
| |
| if ( vGDIObj[ nIndex ] != NULL ) |
| delete vGDIObj[ nIndex ]; |
| |
| vGDIObj[ nIndex ] = new GDIObj( eType, pStyle ); |
| } |
| else |
| { |
| switch ( eType ) |
| { |
| case GDI_PEN : |
| delete (WinMtfLineStyle*)pStyle; |
| break; |
| case GDI_BRUSH : |
| delete (WinMtfFillStyle*)pStyle; |
| break; |
| case GDI_FONT : |
| delete (WinMtfFontStyle*)pStyle; |
| break; |
| |
| default: |
| DBG_ERROR( "unsupported style not deleted" ); |
| break; |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DeleteObject( sal_Int32 nIndex ) |
| { |
| if ( ( nIndex & ENHMETA_STOCK_OBJECT ) == 0 ) |
| { |
| if ( (sal_uInt32)nIndex < vGDIObj.size() ) |
| { |
| delete vGDIObj[ nIndex ]; |
| vGDIObj[ nIndex ] = NULL; |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::IntersectClipRect( const Rectangle& rRect ) |
| { |
| aClipPath.IntersectClipRect( ImplMap( rRect ) ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::ExcludeClipRect( const Rectangle& rRect ) |
| { |
| aClipPath.ExcludeClipRect( ImplMap( rRect ) ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::MoveClipRegion( const Size& rSize ) |
| { |
| aClipPath.MoveClipRegion( ImplMap( rSize ) ); |
| } |
| |
| void WinMtfOutput::SetClipPath( const PolyPolygon& rPolyPolygon, sal_Int32 nClippingMode, sal_Bool bIsMapped ) |
| { |
| if ( bIsMapped ) |
| aClipPath.SetClipPath( rPolyPolygon, nClippingMode ); |
| else |
| { |
| PolyPolygon aPP( rPolyPolygon ); |
| aClipPath.SetClipPath( ImplMap( aPP ), nClippingMode ); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| //----------------------------------------------------------------------------------- |
| //----------------------------------------------------------------------------------- |
| |
| WinMtfOutput::WinMtfOutput( GDIMetaFile& rGDIMetaFile ) : |
| mnLatestTextAlign ( 0 ), |
| mnTextAlign ( TA_LEFT | TA_TOP | TA_NOUPDATECP ), |
| maLatestBkColor ( 0x12345678 ), |
| maBkColor ( COL_WHITE ), |
| mnLatestTextLayoutMode( TEXT_LAYOUT_DEFAULT ), |
| mnTextLayoutMode ( TEXT_LAYOUT_DEFAULT ), |
| mnLatestBkMode ( 0 ), |
| mnBkMode ( OPAQUE ), |
| meLatestRasterOp ( ROP_INVERT ), |
| meRasterOp ( ROP_OVERPAINT ), |
| maActPos ( Point() ), |
| mbNopMode ( sal_False ), |
| mbFillStyleSelected ( sal_False ), |
| mnGfxMode ( GM_COMPATIBLE ), |
| mnMapMode ( MM_TEXT ), |
| mnDevOrgX ( 0 ), |
| mnDevOrgY ( 0 ), |
| mnDevWidth ( 1 ), |
| mnDevHeight ( 1 ), |
| mnWinOrgX ( 0 ), |
| mnWinOrgY ( 0 ), |
| mnWinExtX ( 1 ), |
| mnWinExtY ( 1 ), |
| mnPixX ( 100 ), |
| mnPixY ( 100 ), |
| mnMillX ( 1 ), |
| mnMillY ( 1 ), |
| mpGDIMetaFile ( &rGDIMetaFile ) |
| { |
| mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); // The original clipregion has to be on top |
| // of the stack so it can always be restored |
| // this is necessary to be able to support |
| // SetClipRgn( NULL ) and similar ClipRgn actions (SJ) |
| |
| maFont.SetName( String( RTL_CONSTASCII_USTRINGPARAM( "Arial" )) ); // sj: #i57205#, we do have some scaling problems if using |
| maFont.SetCharSet( gsl_getSystemTextEncoding() ); // the default font then most times a x11 font is used, we |
| maFont.SetHeight( 423 ); // will prevent this defining a font |
| |
| maLatestLineStyle.aLineColor = Color( 0x12, 0x34, 0x56 ); |
| maLatestFillStyle.aFillColor = Color( 0x12, 0x34, 0x56 ); |
| |
| mnRop = R2_BLACK + 1; |
| SetRasterOp( R2_BLACK ); |
| }; |
| |
| //----------------------------------------------------------------------------------- |
| |
| WinMtfOutput::~WinMtfOutput() |
| { |
| mpGDIMetaFile->AddAction( new MetaPopAction() ); |
| mpGDIMetaFile->SetPrefMapMode( MAP_100TH_MM ); |
| if ( mrclFrame.IsEmpty() ) |
| mpGDIMetaFile->SetPrefSize( Size( mnDevWidth, mnDevHeight ) ); |
| else |
| mpGDIMetaFile->SetPrefSize( mrclFrame.GetSize() ); |
| |
| for ( sal_uInt32 i = 0; i < vGDIObj.size(); i++ ) |
| delete vGDIObj[ i ]; |
| }; |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::UpdateClipRegion() |
| { |
| if ( aClipPath.bNeedsUpdate ) |
| { |
| aClipPath.bNeedsUpdate = sal_False; |
| |
| mpGDIMetaFile->AddAction( new MetaPopAction() ); // taking the orignal clipregion |
| mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_CLIPREGION ) ); // |
| |
| switch ( aClipPath.GetType() ) |
| { |
| case RECTANGLE : |
| case COMPLEX : |
| { |
| // we will not generate a RegionClipRegion Action, because this action |
| // cannot be saved to the wmf format - saving to wmf always happens |
| // if the placeholder graphic for ole objects is generated. (SJ) |
| |
| // Region aClipRegion( aClipPath.GetClipPath() ); |
| // mpGDIMetaFile->AddAction( new MetaISectRegionClipRegionAction( aClipRegion ) ); |
| |
| Rectangle aClipRect( aClipPath.GetClipPath().GetBoundRect() ); |
| mpGDIMetaFile->AddAction( new MetaISectRectClipRegionAction( aClipRect ) ); |
| } |
| break; |
| case EMPTY: |
| break; // -Wall not handled. |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::ImplSetNonPersistentLineColorTransparenz() |
| { |
| Color aColor( COL_TRANSPARENT); |
| WinMtfLineStyle aTransparentLine( aColor, sal_True ); |
| if ( ! ( maLatestLineStyle == aTransparentLine ) ) |
| { |
| maLatestLineStyle = aTransparentLine; |
| mpGDIMetaFile->AddAction( new MetaLineColorAction( aTransparentLine.aLineColor, !aTransparentLine.bTransparent ) ); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::UpdateLineStyle() |
| { |
| if (!( maLatestLineStyle == maLineStyle ) ) |
| { |
| maLatestLineStyle = maLineStyle; |
| mpGDIMetaFile->AddAction( new MetaLineColorAction( maLineStyle.aLineColor, !maLineStyle.bTransparent ) ); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::UpdateFillStyle() |
| { |
| if ( !mbFillStyleSelected ) // SJ: #i57205# taking care of bkcolor if no brush is selected |
| maFillStyle = WinMtfFillStyle( maBkColor, mnBkMode == TRANSPARENT ); |
| if (!( maLatestFillStyle == maFillStyle ) ) |
| { |
| maLatestFillStyle = maFillStyle; |
| mpGDIMetaFile->AddAction( new MetaFillColorAction( maFillStyle.aFillColor, !maFillStyle.bTransparent ) ); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| sal_uInt32 WinMtfOutput::SetRasterOp( sal_uInt32 nRasterOp ) |
| { |
| sal_uInt32 nRetROP = mnRop; |
| if ( nRasterOp != mnRop ) |
| { |
| mnRop = nRasterOp; |
| static WinMtfFillStyle aNopFillStyle; |
| static WinMtfLineStyle aNopLineStyle; |
| |
| if ( mbNopMode && ( nRasterOp != R2_NOP ) ) |
| { // beim uebergang von R2_NOP auf anderen Modus |
| // gesetzten Pen und Brush aktivieren |
| maFillStyle = aNopFillStyle; |
| maLineStyle = aNopLineStyle; |
| mbNopMode = sal_False; |
| } |
| switch( nRasterOp ) |
| { |
| case R2_NOT: |
| meRasterOp = ROP_INVERT; |
| break; |
| |
| case R2_XORPEN: |
| meRasterOp = ROP_XOR; |
| break; |
| |
| case R2_NOP: |
| { |
| meRasterOp = ROP_OVERPAINT; |
| if( mbNopMode == sal_False ) |
| { |
| aNopFillStyle = maFillStyle; |
| aNopLineStyle = maLineStyle; |
| maFillStyle = WinMtfFillStyle( Color( COL_TRANSPARENT ), sal_True ); |
| maLineStyle = WinMtfLineStyle( Color( COL_TRANSPARENT ), sal_True ); |
| mbNopMode = sal_True; |
| } |
| } |
| break; |
| |
| default: |
| meRasterOp = ROP_OVERPAINT; |
| break; |
| } |
| } |
| if ( nRetROP != nRasterOp ) |
| mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) ); |
| return nRetROP; |
| }; |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::StrokeAndFillPath( sal_Bool bStroke, sal_Bool bFill ) |
| { |
| if ( aPathObj.Count() ) |
| { |
| UpdateClipRegion(); |
| UpdateLineStyle(); |
| UpdateFillStyle(); |
| if ( bFill ) |
| { |
| if ( !bStroke ) |
| { |
| mpGDIMetaFile->AddAction( new MetaPushAction( PUSH_LINECOLOR ) ); |
| mpGDIMetaFile->AddAction( new MetaLineColorAction( Color(), sal_False ) ); |
| } |
| if ( aPathObj.Count() == 1 ) |
| mpGDIMetaFile->AddAction( new MetaPolygonAction( aPathObj.GetObject( 0 ) ) ); |
| else |
| mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( aPathObj ) ); |
| |
| if ( !bStroke ) |
| mpGDIMetaFile->AddAction( new MetaPopAction() ); |
| } |
| else |
| { |
| sal_uInt16 i, nCount = aPathObj.Count(); |
| for ( i = 0; i < nCount; i++ ) |
| mpGDIMetaFile->AddAction( new MetaPolyLineAction( aPathObj[ i ], maLineStyle.aLineInfo ) ); |
| } |
| ClearPath(); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawPixel( const Point& rSource, const Color& rColor ) |
| { |
| mpGDIMetaFile->AddAction( new MetaPixelAction( ImplMap( rSource), rColor ) ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::MoveTo( const Point& rPoint, sal_Bool bRecordPath ) |
| { |
| Point aDest( ImplMap( rPoint ) ); |
| if ( bRecordPath ) |
| aPathObj.AddPoint( aDest ); |
| maActPos = aDest; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::LineTo( const Point& rPoint, sal_Bool bRecordPath ) |
| { |
| UpdateClipRegion(); |
| |
| Point aDest( ImplMap( rPoint ) ); |
| if ( bRecordPath ) |
| aPathObj.AddPoint( aDest ); |
| else |
| { |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaLineAction( maActPos, aDest, maLineStyle.aLineInfo ) ); |
| } |
| maActPos = aDest; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawLine( const Point& rSource, const Point& rDest ) |
| { |
| UpdateClipRegion(); |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaLineAction( ImplMap( rSource), ImplMap( rDest ), maLineStyle.aLineInfo ) ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawRect( const Rectangle& rRect, sal_Bool bEdge ) |
| { |
| UpdateClipRegion(); |
| UpdateFillStyle(); |
| |
| if ( aClipPath.GetType() == COMPLEX ) |
| { |
| Polygon aPoly( ImplMap( rRect ) ); |
| PolyPolygon aPolyPolyRect( aPoly ); |
| PolyPolygon aDest; |
| aClipPath.GetClipPath().GetIntersection( aPolyPolyRect, aDest ); |
| ImplDrawClippedPolyPolygon( aDest ); |
| } |
| else |
| { |
| if ( bEdge ) |
| { |
| if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) ) |
| { |
| ImplSetNonPersistentLineColorTransparenz(); |
| mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) ); |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( ImplMap( rRect ) ),maLineStyle.aLineInfo ) ); |
| } |
| else |
| { |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) ); |
| } |
| } |
| else |
| { |
| ImplSetNonPersistentLineColorTransparenz(); |
| mpGDIMetaFile->AddAction( new MetaRectAction( ImplMap( rRect ) ) ); |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawRoundRect( const Rectangle& rRect, const Size& rSize ) |
| { |
| UpdateClipRegion(); |
| UpdateLineStyle(); |
| UpdateFillStyle(); |
| mpGDIMetaFile->AddAction( new MetaRoundRectAction( ImplMap( rRect ), labs( ImplMap( rSize ).Width() ), labs( ImplMap( rSize ).Height() ) ) ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawEllipse( const Rectangle& rRect ) |
| { |
| UpdateClipRegion(); |
| UpdateFillStyle(); |
| |
| if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) ) |
| { |
| Point aCenter( ImplMap( rRect.Center() ) ); |
| Size aRad( ImplMap( Size( rRect.GetWidth() / 2, rRect.GetHeight() / 2 ) ) ); |
| |
| ImplSetNonPersistentLineColorTransparenz(); |
| mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) ); |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) ); |
| } |
| else |
| { |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaEllipseAction( ImplMap( rRect ) ) ); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawArc( const Rectangle& rRect, const Point& rStart, const Point& rEnd, sal_Bool bTo ) |
| { |
| UpdateClipRegion(); |
| UpdateLineStyle(); |
| UpdateFillStyle(); |
| |
| Rectangle aRect( ImplMap( rRect ) ); |
| Point aStart( ImplMap( rStart ) ); |
| Point aEnd( ImplMap( rEnd ) ); |
| |
| if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) ) |
| { |
| if ( aStart == aEnd ) |
| { // SJ: #i53768# if start & end is identical, then we have to draw a full ellipse |
| Point aCenter( aRect.Center() ); |
| Size aRad( aRect.GetWidth() / 2, aRect.GetHeight() / 2 ); |
| |
| mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aCenter, aRad.Width(), aRad.Height() ), maLineStyle.aLineInfo ) ); |
| } |
| else |
| mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_ARC ), maLineStyle.aLineInfo ) ); |
| } |
| else |
| mpGDIMetaFile->AddAction( new MetaArcAction( aRect, aStart, aEnd ) ); |
| |
| if ( bTo ) |
| maActPos = aEnd; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawPie( const Rectangle& rRect, const Point& rStart, const Point& rEnd ) |
| { |
| UpdateClipRegion(); |
| UpdateFillStyle(); |
| |
| Rectangle aRect( ImplMap( rRect ) ); |
| Point aStart( ImplMap( rStart ) ); |
| Point aEnd( ImplMap( rEnd ) ); |
| |
| if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) ) |
| { |
| ImplSetNonPersistentLineColorTransparenz(); |
| mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) ); |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_PIE ), maLineStyle.aLineInfo ) ); |
| } |
| else |
| { |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaPieAction( aRect, aStart, aEnd ) ); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawChord( const Rectangle& rRect, const Point& rStart, const Point& rEnd ) |
| { |
| UpdateClipRegion(); |
| UpdateFillStyle(); |
| |
| Rectangle aRect( ImplMap( rRect ) ); |
| Point aStart( ImplMap( rStart ) ); |
| Point aEnd( ImplMap( rEnd ) ); |
| |
| if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) ) |
| { |
| ImplSetNonPersistentLineColorTransparenz(); |
| mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) ); |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaPolyLineAction( Polygon( aRect, aStart, aEnd, POLY_CHORD ), maLineStyle.aLineInfo ) ); |
| } |
| else |
| { |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaChordAction( aRect, aStart, aEnd ) ); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawPolygon( Polygon& rPolygon, sal_Bool bRecordPath ) |
| { |
| UpdateClipRegion(); |
| ImplMap( rPolygon ); |
| if ( bRecordPath ) |
| aPathObj.AddPolygon( rPolygon ); |
| else |
| { |
| UpdateFillStyle(); |
| |
| if ( aClipPath.GetType() == COMPLEX ) |
| { |
| PolyPolygon aPolyPoly( rPolygon ); |
| PolyPolygon aDest; |
| aClipPath.GetClipPath().GetIntersection( aPolyPoly, aDest ); |
| ImplDrawClippedPolyPolygon( aDest ); |
| } |
| else |
| { |
| if ( maLineStyle.aLineInfo.GetWidth() || ( maLineStyle.aLineInfo.GetStyle() == LINE_DASH ) ) |
| { |
| sal_uInt16 nCount = rPolygon.GetSize(); |
| if ( nCount ) |
| { |
| if ( rPolygon[ nCount - 1 ] != rPolygon[ 0 ] ) |
| { |
| Point aPoint( rPolygon[ 0 ] ); |
| rPolygon.Insert( nCount, aPoint ); |
| } |
| } |
| ImplSetNonPersistentLineColorTransparenz(); |
| mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) ); |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) ); |
| } |
| else |
| { |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaPolygonAction( rPolygon ) ); |
| } |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawPolyPolygon( PolyPolygon& rPolyPolygon, sal_Bool bRecordPath ) |
| { |
| UpdateClipRegion(); |
| |
| ImplMap( rPolyPolygon ); |
| |
| if ( bRecordPath ) |
| aPathObj.AddPolyPolygon( rPolyPolygon ); |
| else |
| { |
| UpdateFillStyle(); |
| |
| if ( aClipPath.GetType() == COMPLEX ) |
| { |
| PolyPolygon aDest; |
| aClipPath.GetClipPath().GetIntersection( rPolyPolygon, aDest ); |
| ImplDrawClippedPolyPolygon( aDest ); |
| } |
| else |
| { |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaPolyPolygonAction( rPolyPolygon ) ); |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawPolyLine( Polygon& rPolygon, sal_Bool bTo, sal_Bool bRecordPath ) |
| { |
| UpdateClipRegion(); |
| |
| ImplMap( rPolygon ); |
| if ( bTo ) |
| { |
| rPolygon[ 0 ] = maActPos; |
| maActPos = rPolygon[ rPolygon.GetSize() - 1 ]; |
| } |
| if ( bRecordPath ) |
| aPathObj.AddPolyLine( rPolygon ); |
| else |
| { |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) ); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawPolyBezier( Polygon& rPolygon, sal_Bool bTo, sal_Bool bRecordPath ) |
| { |
| UpdateClipRegion(); |
| |
| sal_uInt16 nPoints = rPolygon.GetSize(); |
| if ( ( nPoints >= 4 ) && ( ( ( nPoints - 4 ) % 3 ) == 0 ) ) |
| { |
| ImplMap( rPolygon ); |
| if ( bTo ) |
| { |
| rPolygon[ 0 ] = maActPos; |
| maActPos = rPolygon[ nPoints - 1 ]; |
| } |
| sal_uInt16 i; |
| for ( i = 0; ( i + 2 ) < nPoints; ) |
| { |
| rPolygon.SetFlags( i++, POLY_NORMAL ); |
| rPolygon.SetFlags( i++, POLY_CONTROL ); |
| rPolygon.SetFlags( i++, POLY_CONTROL ); |
| } |
| if ( bRecordPath ) |
| aPathObj.AddPolyLine( rPolygon ); |
| else |
| { |
| UpdateLineStyle(); |
| mpGDIMetaFile->AddAction( new MetaPolyLineAction( rPolygon, maLineStyle.aLineInfo ) ); |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::DrawText( Point& rPosition, String& rText, sal_Int32* pDXArry, sal_Bool bRecordPath, sal_Int32 nGfxMode ) |
| { |
| UpdateClipRegion(); |
| rPosition = ImplMap( rPosition ); |
| sal_Int32 nOldGfxMode = GetGfxMode(); |
| SetGfxMode( GM_COMPATIBLE ); |
| |
| if ( pDXArry ) |
| { |
| sal_Int32 i, nSum, nLen = rText.Len(); |
| |
| for( i = 0, nSum = 0; i < nLen; i++ ) |
| { |
| // #121382# Map DXArray using WorldTransform |
| const Size aSize(ImplMap(Size( pDXArry[i], 0))); |
| const basegfx::B2DVector aVector(aSize.Width(), aSize.Height()); |
| const sal_Int32 nTemp(basegfx::fround(aVector.getLength())); |
| nSum += nTemp; |
| pDXArry[ i ] = nSum; |
| } |
| } |
| if ( mnLatestTextLayoutMode != mnTextLayoutMode ) |
| { |
| mnLatestTextLayoutMode = mnTextLayoutMode; |
| mpGDIMetaFile->AddAction( new MetaLayoutModeAction( mnTextLayoutMode ) ); |
| } |
| SetGfxMode( nGfxMode ); |
| sal_Bool bChangeFont = sal_False; |
| if ( mnLatestTextAlign != mnTextAlign ) |
| { |
| bChangeFont = sal_True; |
| mnLatestTextAlign = mnTextAlign; |
| TextAlign eTextAlign; |
| if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE ) |
| eTextAlign = ALIGN_BASELINE; |
| else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM ) |
| eTextAlign = ALIGN_BOTTOM; |
| else |
| eTextAlign = ALIGN_TOP; |
| mpGDIMetaFile->AddAction( new MetaTextAlignAction( eTextAlign ) ); |
| } |
| if ( maLatestTextColor != maTextColor ) |
| { |
| bChangeFont = sal_True; |
| maLatestTextColor = maTextColor; |
| mpGDIMetaFile->AddAction( new MetaTextColorAction( maTextColor ) ); |
| } |
| sal_Bool bChangeFillColor = sal_False; |
| if ( maLatestBkColor != maBkColor ) |
| { |
| bChangeFillColor = sal_True; |
| maLatestBkColor = maBkColor; |
| } |
| if ( mnLatestBkMode != mnBkMode ) |
| { |
| bChangeFillColor = sal_True; |
| mnLatestBkMode = mnBkMode; |
| } |
| if ( bChangeFillColor ) |
| { |
| bChangeFont = sal_True; |
| mpGDIMetaFile->AddAction( new MetaTextFillColorAction( maFont.GetFillColor(), !maFont.IsTransparent() ) ); |
| } |
| Font aTmp( maFont ); |
| aTmp.SetColor( maTextColor ); |
| aTmp.SetFillColor( maBkColor ); |
| |
| if( mnBkMode == TRANSPARENT ) |
| aTmp.SetTransparent( sal_True ); |
| else |
| aTmp.SetTransparent( sal_False ); |
| |
| if ( ( mnTextAlign & TA_BASELINE) == TA_BASELINE ) |
| aTmp.SetAlign( ALIGN_BASELINE ); |
| else if( ( mnTextAlign & TA_BOTTOM) == TA_BOTTOM ) |
| aTmp.SetAlign( ALIGN_BOTTOM ); |
| else |
| aTmp.SetAlign( ALIGN_TOP ); |
| |
| if ( nGfxMode == GM_ADVANCED ) |
| { |
| // check whether there is a font rotation applied via transformation |
| Point aP1( ImplMap( Point() ) ); |
| Point aP2( ImplMap( Point( 0, 100 ) ) ); |
| aP2.X() -= aP1.X(); |
| aP2.Y() -= aP1.Y(); |
| double fX = aP2.X(); |
| double fY = aP2.Y(); |
| if ( fX ) |
| { |
| double fOrientation = acos( fX / sqrt( fX * fX + fY * fY ) ) * 57.29577951308; |
| if ( fY > 0 ) |
| fOrientation = 360 - fOrientation; |
| fOrientation += 90; |
| fOrientation *= 10; |
| fOrientation += aTmp.GetOrientation(); |
| aTmp.SetOrientation( sal_Int16( fOrientation ) ); |
| } |
| } |
| |
| if( mnTextAlign & ( TA_UPDATECP | TA_RIGHT_CENTER ) ) |
| { |
| // #117968# VirtualDevice is not thread safe, but filter is used in multithreading |
| vos::OGuard aGuard( Application::GetSolarMutex() ); |
| VirtualDevice aVDev; |
| sal_Int32 nTextWidth; |
| |
| aVDev.SetMapMode( MapMode( MAP_100TH_MM ) ); |
| aVDev.SetFont( maFont ); |
| |
| if( pDXArry ) |
| { |
| sal_uInt32 nLen = rText.Len(); |
| nTextWidth = aVDev.GetTextWidth( rText.GetChar( (sal_uInt16)( nLen - 1 ) ) ); |
| if( nLen > 1 ) |
| nTextWidth += pDXArry[ nLen - 2 ]; |
| } |
| else |
| nTextWidth = aVDev.GetTextWidth( rText ); |
| |
| if( mnTextAlign & TA_UPDATECP ) |
| rPosition = maActPos; |
| |
| if ( mnTextAlign & TA_RIGHT_CENTER ) |
| { |
| double fLenght = ( ( mnTextAlign & TA_RIGHT_CENTER ) == TA_RIGHT ) ? nTextWidth : nTextWidth >> 1; |
| rPosition.X() -= (sal_Int32)( fLenght * cos( maFont.GetOrientation() * F_PI1800 ) ); |
| rPosition.Y() -= (sal_Int32)(-( fLenght * sin( maFont.GetOrientation() * F_PI1800 ) ) ); |
| } |
| |
| if( mnTextAlign & TA_UPDATECP ) |
| maActPos.X() = rPosition.X() + nTextWidth; |
| } |
| if ( bChangeFont || ( maLatestFont != aTmp ) ) |
| { |
| maLatestFont = aTmp; |
| mpGDIMetaFile->AddAction( new MetaFontAction( aTmp ) ); |
| mpGDIMetaFile->AddAction( new MetaTextAlignAction( aTmp.GetAlign() ) ); |
| mpGDIMetaFile->AddAction( new MetaTextColorAction( aTmp.GetColor() ) ); |
| mpGDIMetaFile->AddAction( new MetaTextFillColorAction( aTmp.GetFillColor(), !aTmp.IsTransparent() ) ); |
| } |
| if ( bRecordPath ) |
| { |
| // ToDo |
| } |
| else |
| { |
| /* because text without dx array is badly scaled, we |
| will create such an array if necessary */ |
| sal_Int32* pDX = pDXArry; |
| if ( !pDXArry ) |
| { |
| // #117968# VirtualDevice is not thread safe, but filter is used in multithreading |
| vos::OGuard aGuard( Application::GetSolarMutex() ); |
| VirtualDevice aVDev; |
| |
| pDX = new sal_Int32[ rText.Len() ]; |
| aVDev.SetMapMode( MAP_100TH_MM ); |
| aVDev.SetFont( maLatestFont ); |
| aVDev.GetTextArray( rText, pDX, 0, STRING_LEN ); |
| } |
| mpGDIMetaFile->AddAction( new MetaTextArrayAction( rPosition, rText, pDX, 0, STRING_LEN ) ); |
| if ( !pDXArry ) // this means we have created our own array |
| delete[] pDX; // which must be deleted |
| } |
| SetGfxMode( nOldGfxMode ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::ImplDrawBitmap( const Point& rPos, const Size& rSize, const BitmapEx rBitmap ) |
| { |
| BitmapEx aBmpEx( rBitmap ); |
| if ( aClipPath.GetType() == COMPLEX ) |
| { |
| VirtualDevice aVDev; |
| MapMode aMapMode( MAP_100TH_MM ); |
| aMapMode.SetOrigin( Point( -rPos.X(), -rPos.Y() ) ); |
| const Size aOutputSizePixel( aVDev.LogicToPixel( rSize, aMapMode ) ); |
| const Size aSizePixel( rBitmap.GetSizePixel() ); |
| if ( aOutputSizePixel.Width() && aOutputSizePixel.Height() ) |
| { |
| aMapMode.SetScaleX( Fraction( aSizePixel.Width(), aOutputSizePixel.Width() ) ); |
| aMapMode.SetScaleY( Fraction( aSizePixel.Height(), aOutputSizePixel.Height() ) ); |
| } |
| aVDev.SetMapMode( aMapMode ); |
| aVDev.SetOutputSizePixel( aSizePixel ); |
| aVDev.SetFillColor( Color( COL_BLACK ) ); |
| const PolyPolygon aClip( aClipPath.GetClipPath() ); |
| aVDev.DrawPolyPolygon( aClip ); |
| const Point aEmptyPoint; |
| |
| // #i50672# Extract whole VDev content (to match size of rBitmap) |
| aVDev.EnableMapMode( sal_False ); |
| Bitmap aMask( aVDev.GetBitmap( aEmptyPoint, aSizePixel ).CreateMask( Color( COL_WHITE ) ) ); |
| |
| if ( aBmpEx.IsTransparent() ) |
| { |
| if ( rBitmap.GetTransparentColor() == Color( COL_WHITE ) ) |
| aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_OR ); |
| else |
| aMask.CombineSimple( rBitmap.GetMask(), BMP_COMBINE_AND ); |
| aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask ); |
| } |
| else |
| aBmpEx = BitmapEx( rBitmap.GetBitmap(), aMask ); |
| } |
| if ( aBmpEx.IsTransparent() ) |
| mpGDIMetaFile->AddAction( new MetaBmpExScaleAction( rPos, rSize, aBmpEx ) ); |
| else |
| mpGDIMetaFile->AddAction( new MetaBmpScaleAction( rPos, rSize, aBmpEx.GetBitmap() ) ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::ResolveBitmapActions( List& rSaveList ) |
| { |
| UpdateClipRegion(); |
| |
| sal_uInt32 nObjects = rSaveList.Count(); |
| sal_uInt32 nObjectsLeft = nObjects; |
| |
| while ( nObjectsLeft ) |
| { |
| sal_uInt32 i, nObjectsOfSameSize = 0; |
| sal_uInt32 nObjectStartIndex = nObjects - nObjectsLeft; |
| |
| BSaveStruct* pSave = (BSaveStruct*)rSaveList.GetObject( nObjectStartIndex ); |
| Rectangle aRect( pSave->aOutRect ); |
| |
| for ( i = nObjectStartIndex; i < nObjects; ) |
| { |
| nObjectsOfSameSize++; |
| if ( ++i < nObjects ) |
| { |
| pSave = (BSaveStruct*)rSaveList.GetObject( i ); |
| if ( pSave->aOutRect != aRect ) |
| break; |
| } |
| } |
| Point aPos( ImplMap( aRect.TopLeft() ) ); |
| Size aSize( ImplMap( aRect.GetSize() ) ); |
| |
| for ( i = nObjectStartIndex; i < ( nObjectStartIndex + nObjectsOfSameSize ); i++ ) |
| { |
| pSave = (BSaveStruct*)rSaveList.GetObject( i ); |
| |
| sal_uInt32 nWinRop = pSave->nWinRop; |
| sal_uInt8 nRasterOperation = (sal_uInt8)( nWinRop >> 16 ); |
| |
| sal_uInt32 nUsed = 0; |
| if ( ( nRasterOperation & 0xf ) != ( nRasterOperation >> 4 ) ) |
| nUsed |= 1; // pattern is used |
| if ( ( nRasterOperation & 0x33 ) != ( ( nRasterOperation & 0xcc ) >> 2 ) ) |
| nUsed |= 2; // source is used |
| if ( ( nRasterOperation & 0xaa ) != ( ( nRasterOperation & 0x55 ) << 1 ) ) |
| nUsed |= 4; // destination is used |
| |
| if ( (nUsed & 1) && (( nUsed & 2 ) == 0) ) |
| { // patterns aren't well supported yet |
| sal_uInt32 nOldRop = SetRasterOp( ROP_OVERPAINT ); // in this case nRasterOperation is either 0 or 0xff |
| UpdateFillStyle(); |
| DrawRect( aRect, sal_False ); |
| SetRasterOp( nOldRop ); |
| } |
| else |
| { |
| sal_Bool bDrawn = sal_False; |
| |
| if ( i == nObjectStartIndex ) // optimizing, sometimes it is possible to create just one transparent bitmap |
| { |
| if ( nObjectsOfSameSize == 2 ) |
| { |
| BSaveStruct* pSave2 = (BSaveStruct*)rSaveList.GetObject( i + 1 ); |
| if ( ( pSave->aBmp.GetPrefSize() == pSave2->aBmp.GetPrefSize() ) && |
| ( pSave->aBmp.GetPrefMapMode() == pSave2->aBmp.GetPrefMapMode() ) ) |
| { |
| // TODO: Strictly speaking, we should |
| // check whether mask is monochrome, and |
| // whether image is black (upper branch) |
| // or white (lower branch). Otherwise, the |
| // effect is not the same as a masked |
| // bitmap. |
| if ( ( nWinRop == SRCPAINT ) && ( pSave2->nWinRop == SRCAND ) ) |
| { |
| Bitmap aMask( pSave->aBmp ); aMask.Invert(); |
| BitmapEx aBmpEx( pSave2->aBmp, aMask ); |
| ImplDrawBitmap( aPos, aSize, aBmpEx ); |
| bDrawn = sal_True; |
| i++; |
| } |
| // #i20085# This is just the other way |
| // around as above. Only difference: mask |
| // is inverted |
| else if ( ( nWinRop == SRCAND ) && ( pSave2->nWinRop == SRCPAINT ) ) |
| { |
| Bitmap aMask( pSave->aBmp ); |
| BitmapEx aBmpEx( pSave2->aBmp, aMask ); |
| ImplDrawBitmap( aPos, aSize, aBmpEx ); |
| bDrawn = sal_True; |
| i++; |
| } |
| } |
| } |
| } |
| |
| if ( !bDrawn ) |
| { |
| Push(); |
| sal_uInt32 nOldRop = SetRasterOp( R2_COPYPEN ); |
| Bitmap aBitmap( pSave->aBmp ); |
| sal_uInt32 nOperation = ( nRasterOperation & 0xf ); |
| switch( nOperation ) |
| { |
| case 0x1 : |
| case 0xe : |
| { |
| SetRasterOp( R2_XORPEN ); |
| ImplDrawBitmap( aPos, aSize, aBitmap ); |
| SetRasterOp( R2_COPYPEN ); |
| Bitmap aMask( aBitmap ); |
| aMask.Invert(); |
| BitmapEx aBmpEx( aBitmap, aMask ); |
| ImplDrawBitmap( aPos, aSize, aBmpEx ); |
| if ( nOperation == 0x1 ) |
| { |
| SetRasterOp( R2_NOT ); |
| DrawRect( aRect, sal_False ); |
| } |
| } |
| break; |
| case 0x7 : |
| case 0x8 : |
| { |
| Bitmap aMask( aBitmap ); |
| if ( ( nUsed & 1 ) && ( nRasterOperation & 0xb0 ) == 0xb0 ) // pattern used |
| { |
| aBitmap.Convert( BMP_CONVERSION_24BIT ); |
| aBitmap.Erase( maFillStyle.aFillColor ); |
| } |
| BitmapEx aBmpEx( aBitmap, aMask ); |
| ImplDrawBitmap( aPos, aSize, aBmpEx ); |
| if ( nOperation == 0x7 ) |
| { |
| SetRasterOp( R2_NOT ); |
| DrawRect( aRect, sal_False ); |
| } |
| } |
| break; |
| |
| case 0x4 : |
| case 0xb : |
| { |
| SetRasterOp( R2_NOT ); |
| DrawRect( aRect, sal_False ); |
| SetRasterOp( R2_COPYPEN ); |
| Bitmap aMask( aBitmap ); |
| aBitmap.Invert(); |
| BitmapEx aBmpEx( aBitmap, aMask ); |
| ImplDrawBitmap( aPos, aSize, aBmpEx ); |
| SetRasterOp( R2_XORPEN ); |
| ImplDrawBitmap( aPos, aSize, aBitmap ); |
| if ( nOperation == 0xb ) |
| { |
| SetRasterOp( R2_NOT ); |
| DrawRect( aRect, sal_False ); |
| } |
| } |
| break; |
| |
| case 0x2 : |
| case 0xd : |
| { |
| Bitmap aMask( aBitmap ); |
| aMask.Invert(); |
| BitmapEx aBmpEx( aBitmap, aMask ); |
| ImplDrawBitmap( aPos, aSize, aBmpEx ); |
| SetRasterOp( R2_XORPEN ); |
| ImplDrawBitmap( aPos, aSize, aBitmap ); |
| if ( nOperation == 0xd ) |
| { |
| SetRasterOp( R2_NOT ); |
| DrawRect( aRect, sal_False ); |
| } |
| } |
| break; |
| case 0x6 : |
| case 0x9 : |
| { |
| SetRasterOp( R2_XORPEN ); |
| ImplDrawBitmap( aPos, aSize, aBitmap ); |
| if ( nOperation == 0x9 ) |
| { |
| SetRasterOp( R2_NOT ); |
| DrawRect( aRect, sal_False ); |
| } |
| } |
| break; |
| |
| case 0x0 : // WHITENESS |
| case 0xf : // BLACKNESS |
| { // in this case nRasterOperation is either 0 or 0xff |
| maFillStyle = WinMtfFillStyle( Color( nRasterOperation, nRasterOperation, nRasterOperation ) ); |
| UpdateFillStyle(); |
| DrawRect( aRect, sal_False ); |
| } |
| break; |
| |
| case 0x3 : // only source is used |
| case 0xc : |
| { |
| if ( nRasterOperation == 0x33 ) |
| aBitmap.Invert(); |
| ImplDrawBitmap( aPos, aSize, aBitmap ); |
| } |
| break; |
| |
| case 0x5 : // only destination is used |
| { |
| SetRasterOp( R2_NOT ); |
| DrawRect( aRect, sal_False ); |
| } |
| case 0xa : // no operation |
| break; |
| } |
| SetRasterOp( nOldRop ); |
| Pop(); |
| } |
| } |
| } |
| nObjectsLeft -= nObjectsOfSameSize; |
| } |
| |
| void* pPtr; |
| for ( pPtr = rSaveList.First(); pPtr; pPtr = rSaveList.Next() ) |
| delete (BSaveStruct*)pPtr; |
| rSaveList.Clear(); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetDevOrg( const Point& rPoint ) |
| { |
| mnDevOrgX = rPoint.X(); |
| mnDevOrgY = rPoint.Y(); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetDevOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd ) |
| { |
| mnDevOrgX += nXAdd; |
| mnDevOrgY += nYAdd; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetDevExt( const Size& rSize ) |
| { |
| if ( rSize.Width() && rSize.Height() ) |
| { |
| switch( mnMapMode ) |
| { |
| case MM_ISOTROPIC : |
| case MM_ANISOTROPIC : |
| { |
| mnDevWidth = rSize.Width(); |
| mnDevHeight = rSize.Height(); |
| } |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::ScaleDevExt( double fX, double fY ) |
| { |
| mnDevWidth = FRound( mnDevWidth * fX ); |
| mnDevHeight = FRound( mnDevHeight * fY ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetWinOrg( const Point& rPoint ) |
| { |
| mnWinOrgX = rPoint.X(); |
| mnWinOrgY = rPoint.Y(); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetWinOrgOffset( sal_Int32 nXAdd, sal_Int32 nYAdd ) |
| { |
| mnWinOrgX += nXAdd; |
| mnWinOrgY += nYAdd; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetWinExt( const Size& rSize ) |
| { |
| |
| if( rSize.Width() && rSize.Height() ) |
| { |
| switch( mnMapMode ) |
| { |
| case MM_ISOTROPIC : |
| case MM_ANISOTROPIC : |
| { |
| mnWinExtX = rSize.Width(); |
| mnWinExtY = rSize.Height(); |
| } |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::ScaleWinExt( double fX, double fY ) |
| { |
| mnWinExtX = FRound( mnWinExtX * fX ); |
| mnWinExtY = FRound( mnWinExtY * fY ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetrclBounds( const Rectangle& rRect ) |
| { |
| mrclBounds = rRect; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetrclFrame( const Rectangle& rRect ) |
| { |
| mrclFrame = rRect; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetRefPix( const Size& rSize ) |
| { |
| mnPixX = rSize.Width(); |
| mnPixY = rSize.Height(); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetRefMill( const Size& rSize ) |
| { |
| mnMillX = rSize.Width(); |
| mnMillY = rSize.Height(); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetMapMode( sal_uInt32 nMapMode ) |
| { |
| mnMapMode = nMapMode; |
| if ( nMapMode == MM_TEXT ) |
| { |
| mnWinExtX = mnDevWidth; |
| mnWinExtY = mnDevHeight; |
| } |
| else if ( mnMapMode == MM_HIMETRIC ) |
| { |
| mnWinExtX = mnMillX * 100; |
| mnWinExtY = mnMillY * 100; |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::SetWorldTransform( const XForm& rXForm ) |
| { |
| maXForm.eM11 = rXForm.eM11; |
| maXForm.eM12 = rXForm.eM12; |
| maXForm.eM21 = rXForm.eM21; |
| maXForm.eM22 = rXForm.eM22; |
| maXForm.eDx = rXForm.eDx; |
| maXForm.eDy = rXForm.eDy; |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::ModifyWorldTransform( const XForm& rXForm, sal_uInt32 nMode ) |
| { |
| switch( nMode ) |
| { |
| case MWT_IDENTITY : |
| { |
| maXForm.eM11 = maXForm.eM22 = 1.0f; |
| maXForm.eM12 = maXForm.eM21 = maXForm.eDx = maXForm.eDy = 0.0f; |
| break; |
| } |
| |
| case MWT_RIGHTMULTIPLY : |
| case MWT_LEFTMULTIPLY : |
| { |
| const XForm* pLeft; |
| const XForm* pRight; |
| |
| if ( nMode == MWT_LEFTMULTIPLY ) |
| { |
| pLeft = &rXForm; |
| pRight = &maXForm; |
| } |
| else |
| { |
| pLeft = &maXForm; |
| pRight = &rXForm; |
| } |
| |
| float aF[3][3]; |
| float bF[3][3]; |
| float cF[3][3]; |
| |
| aF[0][0] = pLeft->eM11; |
| aF[0][1] = pLeft->eM12; |
| aF[0][2] = 0; |
| aF[1][0] = pLeft->eM21; |
| aF[1][1] = pLeft->eM22; |
| aF[1][2] = 0; |
| aF[2][0] = pLeft->eDx; |
| aF[2][1] = pLeft->eDy; |
| aF[2][2] = 1; |
| |
| bF[0][0] = pRight->eM11; |
| bF[0][1] = pRight->eM12; |
| bF[0][2] = 0; |
| bF[1][0] = pRight->eM21; |
| bF[1][1] = pRight->eM22; |
| bF[1][2] = 0; |
| bF[2][0] = pRight->eDx; |
| bF[2][1] = pRight->eDy; |
| bF[2][2] = 1; |
| |
| int i, j, k; |
| for ( i = 0; i < 3; i++ ) |
| { |
| for ( j = 0; j < 3; j++ ) |
| { |
| cF[i][j] = 0; |
| for ( k = 0; k < 3; k++ ) |
| cF[i][j] += aF[i][k] * bF[k][j]; |
| } |
| } |
| maXForm.eM11 = cF[0][0]; |
| maXForm.eM12 = cF[0][1]; |
| maXForm.eM21 = cF[1][0]; |
| maXForm.eM22 = cF[1][1]; |
| maXForm.eDx = cF[2][0]; |
| maXForm.eDy = cF[2][1]; |
| break; |
| } |
| case MWT_SET: |
| { |
| SetWorldTransform(rXForm); |
| break; |
| } |
| } |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::Push() // !! to be able to access the original ClipRegion it |
| { // is not allowed to use the MetaPushAction() |
| UpdateClipRegion(); // (the original clip region is on top of the stack) (SJ) |
| SaveStructPtr pSave( new SaveStruct ); |
| |
| pSave->aLineStyle = maLineStyle; |
| pSave->aFillStyle = maFillStyle; |
| |
| pSave->aFont = maFont; |
| pSave->aTextColor = maTextColor; |
| pSave->nTextAlign = mnTextAlign; |
| pSave->nTextLayoutMode = mnTextLayoutMode; |
| pSave->nMapMode = mnMapMode; |
| pSave->nGfxMode = mnGfxMode; |
| pSave->nBkMode = mnBkMode; |
| pSave->aBkColor = maBkColor; |
| pSave->bFillStyleSelected = mbFillStyleSelected; |
| |
| pSave->aActPos = maActPos; |
| pSave->aXForm = maXForm; |
| pSave->eRasterOp = meRasterOp; |
| |
| pSave->nWinOrgX = mnWinOrgX; |
| pSave->nWinOrgY = mnWinOrgY; |
| pSave->nWinExtX = mnWinExtX; |
| pSave->nWinExtY = mnWinExtY; |
| pSave->nDevOrgX = mnDevOrgX; |
| pSave->nDevOrgY = mnDevOrgY; |
| pSave->nDevWidth = mnDevWidth; |
| pSave->nDevHeight = mnDevHeight; |
| |
| pSave->aPathObj = aPathObj; |
| pSave->aClipPath = aClipPath; |
| |
| vSaveStack.push_back( pSave ); |
| } |
| |
| //----------------------------------------------------------------------------------- |
| |
| void WinMtfOutput::Pop() |
| { |
| // Die aktuellen Daten vom Stack holen |
| if( vSaveStack.size() ) |
| { |
| // Die aktuelle Daten auf dem Stack sichern |
| SaveStructPtr pSave( vSaveStack.back() ); |
| |
| maLineStyle = pSave->aLineStyle; |
| maFillStyle = pSave->aFillStyle; |
| |
| maFont = pSave->aFont; |
| maTextColor = pSave->aTextColor; |
| mnTextAlign = pSave->nTextAlign; |
| mnTextLayoutMode = pSave->nTextLayoutMode; |
| mnBkMode = pSave->nBkMode; |
| mnGfxMode = pSave->nGfxMode; |
| mnMapMode = pSave->nMapMode; |
| maBkColor = pSave->aBkColor; |
| mbFillStyleSelected = pSave->bFillStyleSelected; |
| |
| maActPos = pSave->aActPos; |
| maXForm = pSave->aXForm; |
| meRasterOp = pSave->eRasterOp; |
| |
| mnWinOrgX = pSave->nWinOrgX; |
| mnWinOrgY = pSave->nWinOrgY; |
| mnWinExtX = pSave->nWinExtX; |
| mnWinExtY = pSave->nWinExtY; |
| mnDevOrgX = pSave->nDevOrgX; |
| mnDevOrgY = pSave->nDevOrgY; |
| mnDevWidth = pSave->nDevWidth; |
| mnDevHeight = pSave->nDevHeight; |
| |
| aPathObj = pSave->aPathObj; |
| if ( ! ( aClipPath == pSave->aClipPath ) ) |
| { |
| aClipPath = pSave->aClipPath; |
| aClipPath.bNeedsUpdate = sal_True; |
| } |
| if ( meLatestRasterOp != meRasterOp ) |
| mpGDIMetaFile->AddAction( new MetaRasterOpAction( meRasterOp ) ); |
| vSaveStack.pop_back(); |
| } |
| } |
| |
| void WinMtfOutput::AddFromGDIMetaFile( GDIMetaFile& rGDIMetaFile ) |
| { |
| rGDIMetaFile.Play( *mpGDIMetaFile, 0xFFFFFFFF ); |
| } |