From 51d977e00c8481d89cb682a05536e88cdf2fffa4 Mon Sep 17 00:00:00 2001 From: hdu Date: Fri, 8 Jan 2010 13:33:22 +0100 Subject: #i107915# fix vertical writing for non-BMP CJK chars --- vcl/source/gdi/sallayout.cxx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'vcl/source/gdi') diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx index 1f44b823ce44..d937d15ce7df 100755 --- a/vcl/source/gdi/sallayout.cxx +++ b/vcl/source/gdi/sallayout.cxx @@ -6,9 +6,6 @@ * * OpenOffice.org - a multi-platform office productivity suite * - * $RCSfile: sallayout.cxx,v $ - * $Revision: 1.94.90.2 $ - * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify @@ -135,13 +132,13 @@ int GetVerticalFlags( sal_UCS4 nChar ) /* #i52932# remember: nChar == 0x2010 || nChar == 0x2015 nChar == 0x2016 || nChar == 0x2026 - are GF_NONE also, but already handled in the first if */ if((nChar >= 0x3008 && nChar <= 0x301C && nChar != 0x3012) - || nChar == 0xFF3B || nChar == 0xFF3D + || (nChar == 0xFF3B || nChar == 0xFF3D) || (nChar >= 0xFF5B && nChar <= 0xFF9F) // halfwidth forms - || nChar == 0xFFE3 ) + || (nChar == 0xFFE3) + || (nChar >= 0x02F800 && nChar <= 0x02FFFF) ) return GF_NONE; // not rotated else if( nChar == 0x30fc ) return GF_ROTR; // right -- cgit From 381b25700787c4530dc28f548a38d224c074bd12 Mon Sep 17 00:00:00 2001 From: "Philipp Lohmann [pl]" Date: Fri, 8 Jan 2010 17:29:30 +0100 Subject: vcl109: #i33688# NWF slider implementation (mac) --- vcl/source/gdi/salgdilayout.cxx | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'vcl/source/gdi') diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx index 1e9572887e0b..e71c47d61c54 100644 --- a/vcl/source/gdi/salgdilayout.cxx +++ b/vcl/source/gdi/salgdilayout.cxx @@ -693,6 +693,12 @@ void SalGraphics::mirror( ControlType nType, const ImplControlValue& rVal, const { switch( nType ) { + case CTRL_SLIDER: + { + SliderValue* pSlVal = reinterpret_cast(rVal.getOptionalVal()); + mirror(pSlVal->maThumbRect,pOutDev,bBack); + } + break; case CTRL_SCROLLBAR: { ScrollbarValue* pScVal = reinterpret_cast(rVal.getOptionalVal()); -- cgit From a334752d091f61781a0ece7f5331aaf44a0e0516 Mon Sep 17 00:00:00 2001 From: "Philipp Lohmann [pl]" Date: Tue, 19 Jan 2010 18:33:02 +0100 Subject: vcl109: #i65128# avoid breaking polygonal clip regions into rectangles in PDF export --- vcl/source/gdi/outmap.cxx | 210 ++++++++++++++++++++++++++++++++ vcl/source/gdi/pdfextoutdevdata.cxx | 15 ++- vcl/source/gdi/pdfwriter.cxx | 4 +- vcl/source/gdi/pdfwriter_impl.cxx | 231 ++++++++++++++++++++++++++---------- vcl/source/gdi/pdfwriter_impl.hxx | 45 ++++--- vcl/source/gdi/region.cxx | 27 +++++ 6 files changed, 443 insertions(+), 89 deletions(-) (limited to 'vcl/source/gdi') diff --git a/vcl/source/gdi/outmap.cxx b/vcl/source/gdi/outmap.cxx index dfa346dbab05..686f10da4b4d 100644 --- a/vcl/source/gdi/outmap.cxx +++ b/vcl/source/gdi/outmap.cxx @@ -53,6 +53,7 @@ #include #include #include +#include #include #define USE_64BIT_INTS @@ -1100,6 +1101,41 @@ basegfx::B2DHomMatrix OutputDevice::GetInverseViewTransformation() const // ----------------------------------------------------------------------- +// #i75163# +basegfx::B2DHomMatrix OutputDevice::GetViewTransformation( const MapMode& rMapMode ) const +{ + // #i82615# + ImplMapRes aMapRes; + ImplThresholdRes aThresRes; + ImplCalcMapResolution( rMapMode, mnDPIX, mnDPIY, aMapRes, aThresRes ); + + basegfx::B2DHomMatrix aTransform; + + const double fScaleFactorX((double)mnDPIX * (double)aMapRes.mnMapScNumX / (double)aMapRes.mnMapScDenomX); + const double fScaleFactorY((double)mnDPIY * (double)aMapRes.mnMapScNumY / (double)aMapRes.mnMapScDenomY); + const double fZeroPointX(((double)aMapRes.mnMapOfsX * fScaleFactorX) + (double)mnOutOffOrigX); + const double fZeroPointY(((double)aMapRes.mnMapOfsY * fScaleFactorY) + (double)mnOutOffOrigY); + + aTransform.set(0, 0, fScaleFactorX); + aTransform.set(1, 1, fScaleFactorY); + aTransform.set(0, 2, fZeroPointX); + aTransform.set(1, 2, fZeroPointY); + + return aTransform; +} + +// ----------------------------------------------------------------------- + +// #i75163# +basegfx::B2DHomMatrix OutputDevice::GetInverseViewTransformation( const MapMode& rMapMode ) const +{ + basegfx::B2DHomMatrix aMatrix( GetViewTransformation( rMapMode ) ); + aMatrix.invert(); + return aMatrix; +} + +// ----------------------------------------------------------------------- + basegfx::B2DHomMatrix OutputDevice::ImplGetDeviceTransformation() const { basegfx::B2DHomMatrix aTransformation = GetViewTransformation(); @@ -1221,6 +1257,26 @@ PolyPolygon OutputDevice::LogicToPixel( const PolyPolygon& rLogicPolyPoly ) cons // ----------------------------------------------------------------------- +basegfx::B2DPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolygon& rLogicPoly ) const +{ + basegfx::B2DPolygon aTransformedPoly = rLogicPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation(); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + +basegfx::B2DPolyPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolyPolygon& rLogicPolyPoly ) const +{ + basegfx::B2DPolyPolygon aTransformedPoly = rLogicPolyPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation(); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + Region OutputDevice::LogicToPixel( const Region& rLogicRegion ) const { DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); @@ -1405,6 +1461,28 @@ PolyPolygon OutputDevice::LogicToPixel( const PolyPolygon& rLogicPolyPoly, // ----------------------------------------------------------------------- +basegfx::B2DPolyPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolyPolygon& rLogicPolyPoly, + const MapMode& rMapMode ) const +{ + basegfx::B2DPolyPolygon aTransformedPoly = rLogicPolyPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation( rMapMode ); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + +basegfx::B2DPolygon OutputDevice::LogicToPixel( const basegfx::B2DPolygon& rLogicPoly, + const MapMode& rMapMode ) const +{ + basegfx::B2DPolygon aTransformedPoly = rLogicPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetViewTransformation( rMapMode ); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + Region OutputDevice::LogicToPixel( const Region& rLogicRegion, const MapMode& rMapMode ) const { @@ -1556,6 +1634,26 @@ PolyPolygon OutputDevice::PixelToLogic( const PolyPolygon& rDevicePolyPoly ) con // ----------------------------------------------------------------------- +basegfx::B2DPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolygon& rPixelPoly ) const +{ + basegfx::B2DPolygon aTransformedPoly = rPixelPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation(); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + +basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolyPolygon& rPixelPolyPoly ) const +{ + basegfx::B2DPolyPolygon aTransformedPoly = rPixelPolyPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation(); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + Region OutputDevice::PixelToLogic( const Region& rDeviceRegion ) const { DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice ); @@ -1735,6 +1833,28 @@ PolyPolygon OutputDevice::PixelToLogic( const PolyPolygon& rDevicePolyPoly, // ----------------------------------------------------------------------- +basegfx::B2DPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolygon& rPixelPoly, + const MapMode& rMapMode ) const +{ + basegfx::B2DPolygon aTransformedPoly = rPixelPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation( rMapMode ); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + +basegfx::B2DPolyPolygon OutputDevice::PixelToLogic( const basegfx::B2DPolyPolygon& rPixelPolyPoly, + const MapMode& rMapMode ) const +{ + basegfx::B2DPolyPolygon aTransformedPoly = rPixelPolyPoly; + const ::basegfx::B2DHomMatrix& rTransformationMatrix = GetInverseViewTransformation( rMapMode ); + aTransformedPoly.transform( rTransformationMatrix ); + return aTransformedPoly; +} + +// ----------------------------------------------------------------------- + Region OutputDevice::PixelToLogic( const Region& rDeviceRegion, const MapMode& rMapMode ) const { @@ -2162,6 +2282,96 @@ Size OutputDevice::LogicToLogic( const Size& rSzSource, // ----------------------------------------------------------------------- +basegfx::B2DPolygon OutputDevice::LogicToLogic( const basegfx::B2DPolygon& rPolySource, + const MapMode& rMapModeSource, + const MapMode& rMapModeDest ) +{ + if ( rMapModeSource == rMapModeDest ) + return rPolySource; + + MapUnit eUnitSource = rMapModeSource.GetMapUnit(); + MapUnit eUnitDest = rMapModeDest.GetMapUnit(); + ENTER2( eUnitSource, eUnitDest ); + + basegfx::B2DHomMatrix aTransform; + + if ( rMapModeSource.mpImplMapMode->mbSimple && + rMapModeDest.mpImplMapMode->mbSimple ) + { + ENTER3( eUnitSource, eUnitDest ); + + const double fScaleFactor((double)nNumerator / (double)nDenominator); + aTransform.set(0, 0, fScaleFactor); + aTransform.set(1, 1, fScaleFactor); + } + else + { + ENTER4( rMapModeSource, rMapModeDest ); + + const double fScaleFactorX( (double(aMapResSource.mnMapScNumX) * double(aMapResDest.mnMapScDenomX)) + / (double(aMapResSource.mnMapScDenomX) * double(aMapResDest.mnMapScNumX)) ); + const double fScaleFactorY( (double(aMapResSource.mnMapScNumY) * double(aMapResDest.mnMapScDenomY)) + / (double(aMapResSource.mnMapScDenomY) * double(aMapResDest.mnMapScNumY)) ); + const double fZeroPointX(double(aMapResSource.mnMapOfsX) * fScaleFactorX - double(aMapResDest.mnMapOfsX)); + const double fZeroPointY(double(aMapResSource.mnMapOfsY) * fScaleFactorY - double(aMapResDest.mnMapOfsY)); + + aTransform.set(0, 0, fScaleFactorX); + aTransform.set(1, 1, fScaleFactorY); + aTransform.set(0, 2, fZeroPointX); + aTransform.set(1, 2, fZeroPointY); + } + basegfx::B2DPolygon aPoly( rPolySource ); + aPoly.transform( aTransform ); + return aPoly; +} + +// ----------------------------------------------------------------------- + +basegfx::B2DPolyPolygon OutputDevice::LogicToLogic( const basegfx::B2DPolyPolygon& rPolySource, + const MapMode& rMapModeSource, + const MapMode& rMapModeDest ) +{ + if ( rMapModeSource == rMapModeDest ) + return rPolySource; + + MapUnit eUnitSource = rMapModeSource.GetMapUnit(); + MapUnit eUnitDest = rMapModeDest.GetMapUnit(); + ENTER2( eUnitSource, eUnitDest ); + + basegfx::B2DHomMatrix aTransform; + + if ( rMapModeSource.mpImplMapMode->mbSimple && + rMapModeDest.mpImplMapMode->mbSimple ) + { + ENTER3( eUnitSource, eUnitDest ); + + const double fScaleFactor((double)nNumerator / (double)nDenominator); + aTransform.set(0, 0, fScaleFactor); + aTransform.set(1, 1, fScaleFactor); + } + else + { + ENTER4( rMapModeSource, rMapModeDest ); + + const double fScaleFactorX( (double(aMapResSource.mnMapScNumX) * double(aMapResDest.mnMapScDenomX)) + / (double(aMapResSource.mnMapScDenomX) * double(aMapResDest.mnMapScNumX)) ); + const double fScaleFactorY( (double(aMapResSource.mnMapScNumY) * double(aMapResDest.mnMapScDenomY)) + / (double(aMapResSource.mnMapScDenomY) * double(aMapResDest.mnMapScNumY)) ); + const double fZeroPointX(double(aMapResSource.mnMapOfsX) * fScaleFactorX - double(aMapResDest.mnMapOfsX)); + const double fZeroPointY(double(aMapResSource.mnMapOfsY) * fScaleFactorY - double(aMapResDest.mnMapOfsY)); + + aTransform.set(0, 0, fScaleFactorX); + aTransform.set(1, 1, fScaleFactorY); + aTransform.set(0, 2, fZeroPointX); + aTransform.set(1, 2, fZeroPointY); + } + basegfx::B2DPolyPolygon aPoly( rPolySource ); + aPoly.transform( aTransform ); + return aPoly; +} + +// ----------------------------------------------------------------------- + Rectangle OutputDevice::LogicToLogic( const Rectangle& rRectSource, const MapMode& rMapModeSource, const MapMode& rMapModeDest ) diff --git a/vcl/source/gdi/pdfextoutdevdata.cxx b/vcl/source/gdi/pdfextoutdevdata.cxx index 9c8c1ec1bf5e..42071c2f4c0e 100644 --- a/vcl/source/gdi/pdfextoutdevdata.cxx +++ b/vcl/source/gdi/pdfextoutdevdata.cxx @@ -30,10 +30,12 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_vcl.hxx" -#include -#include -#include -#include +#include "vcl/pdfextoutdevdata.hxx" +#include "vcl/graph.hxx" +#include "vcl/outdev.hxx" +#include "vcl/gfxlink.hxx" +#include "basegfx/polygon/b2dpolygon.hxx" +#include "basegfx/polygon/b2dpolygontools.hxx" #include @@ -433,7 +435,10 @@ sal_Bool PageSyncData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIM if ( bClippingNeeded ) { rWriter.Push(); - rWriter.SetClipRegion( aVisibleOutputRect ); + basegfx::B2DPolyPolygon aRect( basegfx::tools::createPolygonFromRect( + basegfx::B2DRectangle( aVisibleOutputRect.Left(), aVisibleOutputRect.Top(), + aVisibleOutputRect.Right(), aVisibleOutputRect.Bottom() ) ) ); + rWriter.SetClipRegion( aRect); } Bitmap aMask; SvMemoryStream aTmp; diff --git a/vcl/source/gdi/pdfwriter.cxx b/vcl/source/gdi/pdfwriter.cxx index 4959a505ec41..4e323015dbac 100644 --- a/vcl/source/gdi/pdfwriter.cxx +++ b/vcl/source/gdi/pdfwriter.cxx @@ -349,7 +349,7 @@ void PDFWriter::SetClipRegion() ((PDFWriterImpl*)pImplementation)->clearClipRegion(); } -void PDFWriter::SetClipRegion( const Region& rRegion ) +void PDFWriter::SetClipRegion( const basegfx::B2DPolyPolygon& rRegion ) { ((PDFWriterImpl*)pImplementation)->setClipRegion( rRegion ); } @@ -359,7 +359,7 @@ void PDFWriter::MoveClipRegion( long nHorzMove, long nVertMove ) ((PDFWriterImpl*)pImplementation)->moveClipRegion( nHorzMove, nVertMove ); } -void PDFWriter::IntersectClipRegion( const Region& rRegion ) +void PDFWriter::IntersectClipRegion( const basegfx::B2DPolyPolygon& rRegion ) { ((PDFWriterImpl*)pImplementation)->intersectClipRegion( rRegion ); } diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 4146f1764204..723f856cac4a 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include #include @@ -117,7 +119,7 @@ void doTestCode() aDocInfo.Title = OUString( RTL_CONSTASCII_USTRINGPARAM( "PDF export test document" ) ); aDocInfo.Producer = OUString( RTL_CONSTASCII_USTRINGPARAM( "VCL" ) ); aWriter.SetDocInfo( aDocInfo ); - aWriter.NewPage(); + aWriter.NewPage( 595, 842 ); aWriter.BeginStructureElement( PDFWriter::Document ); // set duration of 3 sec for first page aWriter.SetAutoAdvanceTime( 3 ); @@ -168,7 +170,7 @@ void doTestCode() TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK ); - aWriter.NewPage(); + aWriter.NewPage( 595, 842 ); // test AddStream interface aWriter.AddStream( String( RTL_CONSTASCII_USTRINGPARAM( "text/plain" ) ), new PDFTestOutputStream(), true ); // set transitional mode @@ -210,7 +212,25 @@ void doTestCode() aWriter.BeginStructureElement( PDFWriter::Caption ); aWriter.DrawText( Point( 4500, 9000 ), String( RTL_CONSTASCII_USTRINGPARAM( "Some drawing stuff inside the structure" ) ) ); aWriter.EndStructureElement(); + + // test clipping + basegfx::B2DPolyPolygon aClip; + basegfx::B2DPolygon aClipPoly; + aClipPoly.append( basegfx::B2DPoint( 8250, 9600 ) ); + aClipPoly.append( basegfx::B2DPoint( 16500, 11100 ) ); + aClipPoly.append( basegfx::B2DPoint( 8250, 12600 ) ); + aClipPoly.append( basegfx::B2DPoint( 4500, 11100 ) ); + aClipPoly.setClosed( true ); + //aClipPoly.flip(); + aClip.append( aClipPoly ); + + aWriter.Push( PUSH_CLIPREGION | PUSH_FILLCOLOR ); + aWriter.SetClipRegion( aClip ); + aWriter.DrawEllipse( Rectangle( Point( 4500, 9600 ), Size( 12000, 3000 ) ) ); + aWriter.MoveClipRegion( 1000, 500 ); + aWriter.SetFillColor( Color( COL_RED ) ); aWriter.DrawEllipse( Rectangle( Point( 4500, 9600 ), Size( 12000, 3000 ) ) ); + aWriter.Pop(); // test transparency // draw background Rectangle aTranspRect( Point( 7500, 13500 ), Size( 9000, 6000 ) ); @@ -290,7 +310,7 @@ void doTestCode() aLIPoly.Move( 1000, 1000 ); aWriter.DrawPolyLine( aLIPoly, aLI ); - aWriter.NewPage(); + aWriter.NewPage( 595, 842 ); aWriter.SetMapMode( MapMode( MAP_100TH_MM ) ); Wallpaper aWall( aTransMask ); aWall.SetStyle( WALLPAPER_TILE ); @@ -314,7 +334,7 @@ void doTestCode() aWriter.SetLineColor( Color( COL_LIGHTBLUE ) ); aWriter.DrawRect( aPolyRect ); - aWriter.NewPage(); + aWriter.NewPage( 595, 842 ); aWriter.SetMapMode( MapMode( MAP_100TH_MM ) ); aWriter.SetFont( Font( String( RTL_CONSTASCII_USTRINGPARAM( "Times" ) ), Size( 0, 500 ) ) ); aWriter.SetTextColor( Color( COL_BLACK ) ); @@ -722,7 +742,7 @@ static void appendFixedInt( sal_Int32 nValue, OStringBuffer& rBuffer, sal_Int32 // appends a double. PDF does not accept exponential format, only fixed point -static void appendDouble( double fValue, OStringBuffer& rBuffer, int nPrecision = 5 ) +static void appendDouble( double fValue, OStringBuffer& rBuffer, sal_Int32 nPrecision = 5 ) { bool bNeg = false; if( fValue < 0.0 ) @@ -1275,6 +1295,19 @@ void PDFWriterImpl::PDFPage::appendPoint( const Point& rPoint, OStringBuffer& rB appendFixedInt( nValue, rBuffer ); } +void PDFWriterImpl::PDFPage::appendPixelPoint( const basegfx::B2DPoint& rPoint, OStringBuffer& rBuffer ) const +{ + double fValue = pixelToPoint(rPoint.getX()); + + appendDouble( fValue, rBuffer, nLog10Divisor ); + + rBuffer.append( ' ' ); + + fValue = double(getHeight()) - pixelToPoint(rPoint.getY()); + + appendDouble( fValue, rBuffer, nLog10Divisor ); +} + void PDFWriterImpl::PDFPage::appendRect( const Rectangle& rRect, OStringBuffer& rBuffer ) const { appendPoint( rRect.BottomLeft() + Point( 0, 1 ), rBuffer ); @@ -1347,6 +1380,82 @@ void PDFWriterImpl::PDFPage::appendPolygon( const Polygon& rPoly, OStringBuffer& } } +void PDFWriterImpl::PDFPage::appendPolygon( const basegfx::B2DPolygon& rPoly, OStringBuffer& rBuffer, bool bClose ) const +{ + basegfx::B2DPolygon aPoly( lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode, + m_pWriter->m_aMapMode, + m_pWriter->getReferenceDevice(), + rPoly ) ); + + if( basegfx::tools::isRectangle( aPoly ) ) + { + basegfx::B2DRange aRange( aPoly.getB2DRange() ); + basegfx::B2DPoint aBL( aRange.getMinX(), aRange.getMaxY() ); + appendPixelPoint( aBL, rBuffer ); + rBuffer.append( ' ' ); + appendMappedLength( aRange.getWidth(), rBuffer, false, NULL, nLog10Divisor ); + rBuffer.append( ' ' ); + appendMappedLength( aRange.getHeight(), rBuffer, true, NULL, nLog10Divisor ); + rBuffer.append( " re\n" ); + return; + } + sal_uInt32 nPoints = aPoly.count(); + if( nPoints > 0 ) + { + sal_uInt32 nBufLen = rBuffer.getLength(); + basegfx::B2DPoint aLastPoint( aPoly.getB2DPoint( 0 ) ); + appendPixelPoint( aLastPoint, rBuffer ); + rBuffer.append( " m\n" ); + for( sal_uInt32 i = 1; i <= nPoints; i++ ) + { + if( i != nPoints || aPoly.isClosed() ) + { + sal_uInt32 nCurPoint = i % nPoints; + sal_uInt32 nLastPoint = i-1; + basegfx::B2DPoint aPoint( aPoly.getB2DPoint( nCurPoint ) ); + if( aPoly.isNextControlPointUsed( nLastPoint ) && + aPoly.isPrevControlPointUsed( nCurPoint ) ) + { + appendPixelPoint( aPoly.getNextControlPoint( nLastPoint ), rBuffer ); + rBuffer.append( ' ' ); + appendPixelPoint( aPoly.getPrevControlPoint( nCurPoint ), rBuffer ); + rBuffer.append( ' ' ); + appendPixelPoint( aPoint, rBuffer ); + rBuffer.append( " c" ); + } + else if( aPoly.isNextControlPointUsed( nLastPoint ) ) + { + appendPixelPoint( aPoly.getNextControlPoint( nLastPoint ), rBuffer ); + rBuffer.append( ' ' ); + appendPixelPoint( aPoint, rBuffer ); + rBuffer.append( " y" ); + } + else if( aPoly.isPrevControlPointUsed( nCurPoint ) ) + { + appendPixelPoint( aPoly.getPrevControlPoint( nCurPoint ), rBuffer ); + rBuffer.append( ' ' ); + appendPixelPoint( aPoint, rBuffer ); + rBuffer.append( " v" ); + } + else + { + appendPixelPoint( aPoint, rBuffer ); + rBuffer.append( " l" ); + } + if( (rBuffer.getLength() - nBufLen) > 65 ) + { + rBuffer.append( "\n" ); + nBufLen = rBuffer.getLength(); + } + else + rBuffer.append( " " ); + } + } + if( bClose ) + rBuffer.append( "h\n" ); + } +} + void PDFWriterImpl::PDFPage::appendPolyPolygon( const PolyPolygon& rPolyPoly, OStringBuffer& rBuffer, bool bClose ) const { USHORT nPolygons = rPolyPoly.Count(); @@ -1354,6 +1463,13 @@ void PDFWriterImpl::PDFPage::appendPolyPolygon( const PolyPolygon& rPolyPoly, OS appendPolygon( rPolyPoly[n], rBuffer, bClose ); } +void PDFWriterImpl::PDFPage::appendPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly, OStringBuffer& rBuffer, bool bClose ) const +{ + sal_uInt32 nPolygons = rPolyPoly.count(); + for( sal_uInt32 n = 0; n < nPolygons; n++ ) + appendPolygon( rPolyPoly.getB2DPolygon( n ), rBuffer, bClose ); +} + void PDFWriterImpl::PDFPage::appendMappedLength( sal_Int32 nLength, OStringBuffer& rBuffer, bool bVertical, sal_Int32* pOutLength ) const { sal_Int32 nValue = nLength; @@ -1373,7 +1489,7 @@ void PDFWriterImpl::PDFPage::appendMappedLength( sal_Int32 nLength, OStringBuffe appendFixedInt( nValue, rBuffer, 1 ); } -void PDFWriterImpl::PDFPage::appendMappedLength( double fLength, OStringBuffer& rBuffer, bool bVertical, sal_Int32* pOutLength ) const +void PDFWriterImpl::PDFPage::appendMappedLength( double fLength, OStringBuffer& rBuffer, bool bVertical, sal_Int32* pOutLength, sal_Int32 nPrecision ) const { Size aSize( lcl_convert( m_pWriter->m_aGraphicsStack.front().m_aMapMode, m_pWriter->m_aMapMode, @@ -1382,7 +1498,7 @@ void PDFWriterImpl::PDFPage::appendMappedLength( double fLength, OStringBuffer& if( pOutLength ) *pOutLength = (sal_Int32)(fLength*(double)(bVertical ? aSize.Height() : aSize.Width())/1000.0); fLength *= pixelToPoint((double)(bVertical ? aSize.Height() : aSize.Width()) / 1000.0); - appendDouble( fLength, rBuffer ); + appendDouble( fLength, rBuffer, nPrecision ); } bool PDFWriterImpl::PDFPage::appendLineInfo( const LineInfo& rInfo, OStringBuffer& rBuffer ) const @@ -8257,7 +8373,7 @@ void PDFWriterImpl::beginRedirect( SvStream* pStream, const Rectangle& rTargetRe { push( PUSH_ALL ); - setClipRegion( Region() ); + clearClipRegion(); updateGraphicsState(); m_aOutputStreams.push_front( StreamRedirect() ); @@ -10194,25 +10310,17 @@ void PDFWriterImpl::updateGraphicsState() { rNewState.m_nUpdateFlags &= ~GraphicsState::updateClipRegion; - Region& rNewClip = rNewState.m_aClipRegion; - - /* #103137# equality operator is not implemented - * const as API promises but may change Region - * from Polygon to rectangles. Arrrgghh !!!! - */ - Region aLeft = m_aCurrentPDFState.m_aClipRegion; - Region aRight = rNewClip; - if( aLeft != aRight ) + if( m_aCurrentPDFState.m_bClipRegion != rNewState.m_bClipRegion || + ( rNewState.m_bClipRegion && m_aCurrentPDFState.m_aClipRegion != rNewState.m_aClipRegion ) ) { - if( ! m_aCurrentPDFState.m_aClipRegion.IsEmpty() && - ! m_aCurrentPDFState.m_aClipRegion.IsNull() ) + if( m_aCurrentPDFState.m_bClipRegion && m_aCurrentPDFState.m_aClipRegion.count() ) { aLine.append( "Q " ); // invalidate everything but the clip region m_aCurrentPDFState = GraphicsState(); rNewState.m_nUpdateFlags = sal::static_int_cast(~GraphicsState::updateClipRegion); } - if( ! rNewClip.IsEmpty() && ! rNewClip.IsNull() ) + if( rNewState.m_bClipRegion && rNewState.m_aClipRegion.count() ) { // clip region is always stored in private PDF mapmode MapMode aNewMapMode = rNewState.m_aMapMode; @@ -10221,32 +10329,8 @@ void PDFWriterImpl::updateGraphicsState() m_aCurrentPDFState.m_aMapMode = rNewState.m_aMapMode; aLine.append( "q " ); - if( rNewClip.HasPolyPolygon() ) - { - m_aPages.back().appendPolyPolygon( rNewClip.GetPolyPolygon(), aLine ); - aLine.append( "W* n\n" ); - } - else - { - // need to clip all rectangles - RegionHandle aHandle = rNewClip.BeginEnumRects(); - Rectangle aRect; - while( rNewClip.GetNextEnumRect( aHandle, aRect ) ) - { - m_aPages.back().appendRect( aRect, aLine ); - if( aLine.getLength() > 80 ) - { - aLine.append( "\n" ); - writeBuffer( aLine.getStr(), aLine.getLength() ); - aLine.setLength( 0 ); - } - else - aLine.append( ' ' ); - } - rNewClip.EndEnumRects( aHandle ); - aLine.append( "W* n\n" ); - } - + m_aPages.back().appendPolyPolygon( rNewState.m_aClipRegion, aLine ); + aLine.append( "W* n\n" ); rNewState.m_aMapMode = aNewMapMode; getReferenceDevice()->SetMapMode( rNewState.m_aMapMode ); m_aCurrentPDFState.m_aMapMode = rNewState.m_aMapMode; @@ -10360,9 +10444,12 @@ void PDFWriterImpl::pop() if( ! (aState.m_nFlags & PUSH_MAPMODE) ) setMapMode( aState.m_aMapMode ); if( ! (aState.m_nFlags & PUSH_CLIPREGION) ) + { // do not use setClipRegion here // it would convert again assuming the current mapmode rOld.m_aClipRegion = aState.m_aClipRegion; + rOld.m_bClipRegion = aState.m_bClipRegion; + } if( ! (aState.m_nFlags & PUSH_TEXTLINECOLOR ) ) setTextLineColor( aState.m_aTextLineColor ); if( ! (aState.m_nFlags & PUSH_OVERLINECOLOR ) ) @@ -10386,45 +10473,59 @@ void PDFWriterImpl::setMapMode( const MapMode& rMapMode ) m_aCurrentPDFState.m_aMapMode = rMapMode; } -void PDFWriterImpl::setClipRegion( const Region& rRegion ) +void PDFWriterImpl::setClipRegion( const basegfx::B2DPolyPolygon& rRegion ) { - Region aRegion = getReferenceDevice()->LogicToPixel( rRegion, m_aGraphicsStack.front().m_aMapMode ); + basegfx::B2DPolyPolygon aRegion = getReferenceDevice()->LogicToPixel( rRegion, m_aGraphicsStack.front().m_aMapMode ); aRegion = getReferenceDevice()->PixelToLogic( aRegion, m_aMapMode ); m_aGraphicsStack.front().m_aClipRegion = aRegion; + m_aGraphicsStack.front().m_bClipRegion = true; m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; } void PDFWriterImpl::moveClipRegion( sal_Int32 nX, sal_Int32 nY ) { - Point aPoint( lcl_convert( m_aGraphicsStack.front().m_aMapMode, + if( m_aGraphicsStack.front().m_bClipRegion && m_aGraphicsStack.front().m_aClipRegion.count() ) + { + Point aPoint( lcl_convert( m_aGraphicsStack.front().m_aMapMode, + m_aMapMode, + getReferenceDevice(), + Point( nX, nY ) ) ); + aPoint -= lcl_convert( m_aGraphicsStack.front().m_aMapMode, m_aMapMode, getReferenceDevice(), - Point( nX, nY ) ) ); - aPoint -= lcl_convert( m_aGraphicsStack.front().m_aMapMode, - m_aMapMode, - getReferenceDevice(), - Point() ); - m_aGraphicsStack.front().m_aClipRegion.Move( aPoint.X(), aPoint.Y() ); - m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; + Point() ); + basegfx::B2DHomMatrix aMat; + aMat.translate( aPoint.X(), aPoint.Y() ); + m_aGraphicsStack.front().m_aClipRegion.transform( aMat ); + m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; + } } bool PDFWriterImpl::intersectClipRegion( const Rectangle& rRect ) { - Rectangle aRect( lcl_convert( m_aGraphicsStack.front().m_aMapMode, - m_aMapMode, - getReferenceDevice(), - rRect ) ); - m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; - return m_aGraphicsStack.front().m_aClipRegion.Intersect( aRect ); + basegfx::B2DPolyPolygon aRect( basegfx::tools::createPolygonFromRect( + basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) ); + return intersectClipRegion( aRect ); } -bool PDFWriterImpl::intersectClipRegion( const Region& rRegion ) +bool PDFWriterImpl::intersectClipRegion( const basegfx::B2DPolyPolygon& rRegion ) { - Region aRegion = getReferenceDevice()->LogicToPixel( rRegion, m_aGraphicsStack.front().m_aMapMode ); + basegfx::B2DPolyPolygon aRegion( getReferenceDevice()->LogicToPixel( rRegion, m_aGraphicsStack.front().m_aMapMode ) ); aRegion = getReferenceDevice()->PixelToLogic( aRegion, m_aMapMode ); m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; - return m_aGraphicsStack.front().m_aClipRegion.Intersect( aRegion ); + if( m_aGraphicsStack.front().m_bClipRegion ) + { + basegfx::B2DPolyPolygon aOld( basegfx::tools::prepareForPolygonOperation( m_aGraphicsStack.front().m_aClipRegion ) ); + aRegion = basegfx::tools::prepareForPolygonOperation( aRegion ); + m_aGraphicsStack.front().m_aClipRegion = basegfx::tools::solvePolygonOperationAnd( aOld, aRegion ); + } + else + { + m_aGraphicsStack.front().m_aClipRegion = aRegion; + m_aGraphicsStack.front().m_bClipRegion = true; + } + return true; } void PDFWriterImpl::createNote( const Rectangle& rRect, const PDFNote& rNote, sal_Int32 nPageNr ) diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx index e058cfa487db..15158714cfee 100644 --- a/vcl/source/gdi/pdfwriter_impl.hxx +++ b/vcl/source/gdi/pdfwriter_impl.hxx @@ -144,14 +144,20 @@ public: // if pOutPoint is set it will be updated to the emitted point // (in PDF map mode, that is 10th of point) void appendPoint( const Point& rPoint, rtl::OStringBuffer& rBuffer, bool bNeg = false, Point* pOutPoint = NULL ) const; + // appends a B2DPoint without further transformation + void appendPixelPoint( const basegfx::B2DPoint& rPoint, rtl::OStringBuffer& rBuffer ) const; // appends a rectangle void appendRect( const Rectangle& rRect, rtl::OStringBuffer& rBuffer ) const; // converts a rectangle to 10th points page space void convertRect( Rectangle& rRect ) const; // appends a polygon optionally closing it void appendPolygon( const Polygon& rPoly, rtl::OStringBuffer& rBuffer, bool bClose = true ) const; + // appends a polygon optionally closing it + void appendPolygon( const basegfx::B2DPolygon& rPoly, rtl::OStringBuffer& rBuffer, bool bClose = true ) const; // appends a polypolygon optionally closing the subpaths void appendPolyPolygon( const PolyPolygon& rPolyPoly, rtl::OStringBuffer& rBuffer, bool bClose = true ) const; + // appends a polypolygon optionally closing the subpaths + void appendPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPoly, rtl::OStringBuffer& rBuffer, bool bClose = true ) const; // converts a length (either vertical or horizontal; this // can be important if the source MapMode is not // symmetrical) to page length and appends it to the buffer @@ -159,7 +165,7 @@ public: // (in PDF map mode, that is 10th of point) void appendMappedLength( sal_Int32 nLength, rtl::OStringBuffer& rBuffer, bool bVertical = true, sal_Int32* pOutLength = NULL ) const; // the same for double values - void appendMappedLength( double fLength, rtl::OStringBuffer& rBuffer, bool bVertical = true, sal_Int32* pOutLength = NULL ) const; + void appendMappedLength( double fLength, rtl::OStringBuffer& rBuffer, bool bVertical = true, sal_Int32* pOutLength = NULL, sal_Int32 nPrecision = 5 ) const; // appends LineInfo // returns false if too many dash array entry were created for // the implementation limits of some PDF readers @@ -650,19 +656,20 @@ private: // graphics state struct GraphicsState { - Font m_aFont; - MapMode m_aMapMode; - Color m_aLineColor; - Color m_aFillColor; - Color m_aTextLineColor; - Color m_aOverlineColor; - Region m_aClipRegion; - sal_Int32 m_nAntiAlias; - sal_Int32 m_nLayoutMode; - LanguageType m_aDigitLanguage; - sal_Int32 m_nTransparentPercent; - sal_uInt16 m_nFlags; - sal_uInt16 m_nUpdateFlags; + Font m_aFont; + MapMode m_aMapMode; + Color m_aLineColor; + Color m_aFillColor; + Color m_aTextLineColor; + Color m_aOverlineColor; + basegfx::B2DPolyPolygon m_aClipRegion; + bool m_bClipRegion; + sal_Int32 m_nAntiAlias; + sal_Int32 m_nLayoutMode; + LanguageType m_aDigitLanguage; + sal_Int32 m_nTransparentPercent; + sal_uInt16 m_nFlags; + sal_uInt16 m_nUpdateFlags; static const sal_uInt16 updateFont = 0x0001; static const sal_uInt16 updateMapMode = 0x0002; @@ -681,6 +688,7 @@ private: m_aFillColor( COL_TRANSPARENT ), m_aTextLineColor( COL_TRANSPARENT ), m_aOverlineColor( COL_TRANSPARENT ), + m_bClipRegion( false ), m_nAntiAlias( 1 ), m_nLayoutMode( 0 ), m_aDigitLanguage( 0 ), @@ -696,6 +704,7 @@ private: m_aTextLineColor( rState.m_aTextLineColor ), m_aOverlineColor( rState.m_aOverlineColor ), m_aClipRegion( rState.m_aClipRegion ), + m_bClipRegion( rState.m_bClipRegion ), m_nAntiAlias( rState.m_nAntiAlias ), m_nLayoutMode( rState.m_nLayoutMode ), m_aDigitLanguage( rState.m_aDigitLanguage ), @@ -714,6 +723,7 @@ private: m_aTextLineColor = rState.m_aTextLineColor; m_aOverlineColor = rState.m_aOverlineColor; m_aClipRegion = rState.m_aClipRegion; + m_bClipRegion = rState.m_bClipRegion; m_nAntiAlias = rState.m_nAntiAlias; m_nLayoutMode = rState.m_nLayoutMode; m_aDigitLanguage = rState.m_aDigitLanguage; @@ -1164,17 +1174,18 @@ public: void clearClipRegion() { - m_aGraphicsStack.front().m_aClipRegion.SetNull(); + m_aGraphicsStack.front().m_aClipRegion.clear(); + m_aGraphicsStack.front().m_bClipRegion = false; m_aGraphicsStack.front().m_nUpdateFlags |= GraphicsState::updateClipRegion; } - void setClipRegion( const Region& rRegion ); + void setClipRegion( const basegfx::B2DPolyPolygon& rRegion ); void moveClipRegion( sal_Int32 nX, sal_Int32 nY ); bool intersectClipRegion( const Rectangle& rRect ); - bool intersectClipRegion( const Region& rRegion ); + bool intersectClipRegion( const basegfx::B2DPolyPolygon& rRegion ); void setLayoutMode( sal_Int32 nLayoutMode ) { diff --git a/vcl/source/gdi/region.cxx b/vcl/source/gdi/region.cxx index 66865759db4b..642690a8d32d 100644 --- a/vcl/source/gdi/region.cxx +++ b/vcl/source/gdi/region.cxx @@ -48,6 +48,7 @@ #include #include +#include #include // ======================================================================= @@ -2010,6 +2011,32 @@ const basegfx::B2DPolyPolygon Region::GetB2DPolyPolygon() const // ----------------------------------------------------------------------- +basegfx::B2DPolyPolygon Region::ConvertToB2DPolyPolygon() +{ + DBG_CHKTHIS( Region, ImplDbgTestRegion ); + + basegfx::B2DPolyPolygon aRet; + + if( HasPolyPolygon() ) + aRet = GetB2DPolyPolygon(); + else + { + RegionHandle aHdl = BeginEnumRects(); + Rectangle aSubRect; + while( GetNextEnumRect( aHdl, aSubRect ) ) + { + basegfx::B2DPolygon aPoly( basegfx::tools::createPolygonFromRect( + basegfx::B2DRectangle( aSubRect.Left(), aSubRect.Top(), aSubRect.Right(), aSubRect.Bottom() ) ) ); + aRet.append( aPoly ); + } + EndEnumRects( aHdl ); + } + + return aRet; +} + +// ----------------------------------------------------------------------- + BOOL Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo, long& rX, long& rY, long& rWidth, long& rHeight ) const -- cgit From 2490e4eeaadb02419d4ca6535f7954bcea6c4872 Mon Sep 17 00:00:00 2001 From: "Philipp Lohmann [pl]" Date: Tue, 19 Jan 2010 18:45:21 +0100 Subject: vcl109: #i108451# fix unitialized member (thanks dtardon !) --- vcl/source/gdi/pngwrite.cxx | 1 + 1 file changed, 1 insertion(+) (limited to 'vcl/source/gdi') diff --git a/vcl/source/gdi/pngwrite.cxx b/vcl/source/gdi/pngwrite.cxx index 372be81aaef6..45f462fdf52e 100644 --- a/vcl/source/gdi/pngwrite.cxx +++ b/vcl/source/gdi/pngwrite.cxx @@ -134,6 +134,7 @@ PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx, mpAccess ( NULL ), mpMaskAccess ( NULL ), mpZCodec ( new ZCodec( DEFAULT_IN_BUFSIZE, DEFAULT_OUT_BUFSIZE, MAX_MEM_USAGE ) ), + mnCRC(0UL), mnLastPercent ( 0UL ) { if ( !rBmpEx.IsEmpty() ) -- cgit From 1dde425a12be0ea92ada5152e0d40b4ac9358f1c Mon Sep 17 00:00:00 2001 From: Armin Le Grand Date: Thu, 28 Jan 2010 17:21:44 +0100 Subject: aw079: #i99147# corrected diverse aspects of invisible object visualisation and interaction --- vcl/source/gdi/bitmapex.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'vcl/source/gdi') diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx index 4e2ed20a7966..8d7ef4ccb3be 100644 --- a/vcl/source/gdi/bitmapex.cxx +++ b/vcl/source/gdi/bitmapex.cxx @@ -814,7 +814,7 @@ sal_uInt8 BitmapEx::GetTransparency(sal_Int32 nX, sal_Int32 nY) const } else { - if(0x00 != aBitmapColor.GetIndex()) + if(0x00 == aBitmapColor.GetIndex()) { nTransparency = 0x00; } -- cgit From f82dcbead55ca073976a27c972eac2fee046c1a3 Mon Sep 17 00:00:00 2001 From: hdu Date: Thu, 18 Feb 2010 13:06:18 +0100 Subject: #i109400# no special handling required when textlen matches with strlen --- vcl/source/gdi/outdev3.cxx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'vcl/source/gdi') diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx index 28fa4f8f5461..0f8a17077ce9 100644 --- a/vcl/source/gdi/outdev3.cxx +++ b/vcl/source/gdi/outdev3.cxx @@ -5893,15 +5893,16 @@ SalLayout* OutputDevice::ImplLayout( const String& rOrigStr, ImplInitFont(); // check string index and length - String aStr = rOrigStr; - if( (ULONG)nMinIndex + nLen >= aStr.Len() ) + if( (unsigned)nMinIndex + nLen > rOrigStr.Len() ) { - if( nMinIndex < aStr.Len() ) - nLen = aStr.Len() - nMinIndex; - else + const int nNewLen = (int)rOrigStr.Len() - nMinIndex; + if( nNewLen <= 0 ) return NULL; + nLen = static_cast(nNewLen); } + String aStr = rOrigStr; + // filter out special markers if( bFilter ) { -- cgit From 362c3481b358712fc8504c5f473f23b8522c3191 Mon Sep 17 00:00:00 2001 From: "Philipp Lohmann [pl]" Date: Thu, 18 Feb 2010 14:10:43 +0100 Subject: vcl109: #i82785# support full/partial field names, allow spaces in partial field names --- vcl/source/gdi/pdfwriter_impl.cxx | 365 +++++++++++++++++++++++--------------- vcl/source/gdi/pdfwriter_impl.hxx | 2 +- 2 files changed, 223 insertions(+), 144 deletions(-) (limited to 'vcl/source/gdi') diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx index 17326bcfb7eb..3471ddac2a21 100644 --- a/vcl/source/gdi/pdfwriter_impl.cxx +++ b/vcl/source/gdi/pdfwriter_impl.cxx @@ -652,30 +652,25 @@ static void appendUnicodeTextString( const rtl::OUString& rString, OStringBuffer } } -OString PDFWriterImpl::convertWidgetFieldName( const rtl::OUString& rString ) +void PDFWriterImpl::createWidgetFieldName( sal_Int32 i_nWidgetIndex, const PDFWriter::AnyWidget& i_rControl ) { - OStringBuffer aBuffer( rString.getLength()+64 ); - /* #i80258# previously we use appendName here however we need a slightly different coding scheme than the normal name encoding for field names - - also replace all '.' by '_' as '.' indicates a hierarchy level which - we do not have here */ - - OString aStr( OUStringToOString( rString, RTL_TEXTENCODING_UTF8 ) ); + const OUString& rName = (m_aContext.Version > PDFWriter::PDF_1_2) ? i_rControl.Name : i_rControl.Text; + OString aStr( OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ) ); const sal_Char* pStr = aStr.getStr(); int nLen = aStr.getLength(); + + OStringBuffer aBuffer( rName.getLength()+64 ); for( int i = 0; i < nLen; i++ ) { /* #i16920# PDF recommendation: output UTF8, any byte - * outside the interval [33(=ASCII'!');126(=ASCII'~')] + * outside the interval [32(=ASCII' ');126(=ASCII'~')] * should be escaped hexadecimal */ - if( pStr[i] == '.' ) - aBuffer.append( '_' ); - else if( (pStr[i] >= 33 && pStr[i] <= 126 ) ) + if( (pStr[i] >= 32 && pStr[i] <= 126 ) ) aBuffer.append( pStr[i] ); else { @@ -684,31 +679,135 @@ OString PDFWriterImpl::convertWidgetFieldName( const rtl::OUString& rString ) } } - OString aRet = aBuffer.makeStringAndClear(); + OString aFullName( aBuffer.makeStringAndClear() ); + + /* #i82785# create hierarchical fields down to the for each dot in i_rName */ + sal_Int32 nTokenIndex = 0, nLastTokenIndex = 0; + OString aPartialName; + OString aDomain; + do + { + nLastTokenIndex = nTokenIndex; + aPartialName = aFullName.getToken( 0, '.', nTokenIndex ); + if( nTokenIndex != -1 ) + { + // find or create a hierarchical field + // first find the fully qualified name up to this field + aDomain = aFullName.copy( 0, nTokenIndex-1 ); + std::hash_map< rtl::OString, sal_Int32, rtl::OStringHash >::const_iterator it = m_aFieldNameMap.find( aDomain ); + if( it == m_aFieldNameMap.end() ) + { + // create new hierarchy field + sal_Int32 nNewWidget = m_aWidgets.size(); + m_aWidgets.push_back( PDFWidget() ); + m_aWidgets[nNewWidget].m_nObject = createObject(); + m_aWidgets[nNewWidget].m_eType = PDFWriter::Hierarchy; + m_aWidgets[nNewWidget].m_aName = aPartialName; + m_aWidgets[i_nWidgetIndex].m_nParent = m_aWidgets[nNewWidget].m_nObject; + m_aFieldNameMap[aDomain] = nNewWidget; + m_aWidgets[i_nWidgetIndex].m_nParent = m_aWidgets[nNewWidget].m_nObject; + if( nLastTokenIndex > 0 ) + { + // this field is not a root field and + // needs to be inserted to its parent + OString aParentDomain( aDomain.copy( 0, nLastTokenIndex-1 ) ); + it = m_aFieldNameMap.find( aParentDomain ); + OSL_ENSURE( it != m_aFieldNameMap.end(), "field name not found" ); + if( it != m_aFieldNameMap.end() ) + { + OSL_ENSURE( it->second < sal_Int32(m_aWidgets.size()), "invalid field number entry" ); + if( it->second < sal_Int32(m_aWidgets.size()) ) + { + PDFWidget& rParentField( m_aWidgets[it->second] ); + rParentField.m_aKids.push_back( m_aWidgets[nNewWidget].m_nObject ); + rParentField.m_aKidsIndex.push_back( nNewWidget ); + m_aWidgets[nNewWidget].m_nParent = rParentField.m_nObject; + } + } + } + } + else if( m_aWidgets[it->second].m_eType != PDFWriter::Hierarchy ) + { + // this is invalid, someone tries to have a terminal field as parent + // example: a button with the name foo.bar exists and + // another button is named foo.bar.no + // workaround: put the second terminal field as much up in the hierarchy as + // necessary to have a non-terminal field as parent (or none at all) + // since it->second already is terminal, we just need to use its parent + aDomain = OString(); + aPartialName = aFullName.copy( aFullName.lastIndexOf( '.' )+1 ); + if( nLastTokenIndex > 0 ) + { + aDomain = aFullName.copy( 0, nLastTokenIndex-1 ); + OStringBuffer aBuf( aDomain.getLength() + 1 + aPartialName.getLength() ); + aBuf.append( aDomain ); + aBuf.append( '.' ); + aBuf.append( aPartialName ); + aFullName = aBuf.makeStringAndClear(); + } + else + aFullName = aPartialName; + break; + } + } + } while( nTokenIndex != -1 ); + + // insert widget into its hierarchy field + if( aDomain.getLength() ) + { + std::hash_map< rtl::OString, sal_Int32, rtl::OStringHash >::const_iterator it = m_aFieldNameMap.find( aDomain ); + if( it != m_aFieldNameMap.end() ) + { + OSL_ENSURE( it->second >= 0 && it->second < sal_Int32( m_aWidgets.size() ), "invalid field index" ); + if( it->second >= 0 && it->second < sal_Int32(m_aWidgets.size()) ) + { + m_aWidgets[i_nWidgetIndex].m_nParent = m_aWidgets[it->second].m_nObject; + m_aWidgets[it->second].m_aKids.push_back( m_aWidgets[i_nWidgetIndex].m_nObject); + m_aWidgets[it->second].m_aKidsIndex.push_back( i_nWidgetIndex ); + } + } + } + + if( aPartialName.getLength() == 0 ) + { + // how funny, an empty field name + if( i_rControl.getType() == PDFWriter::RadioButton ) + { + aPartialName = "RadioGroup"; + aPartialName += OString::valueOf( static_cast(i_rControl).RadioGroup ); + } + else + aPartialName = OString( "Widget" ); + } + if( ! m_aContext.AllowDuplicateFieldNames ) { - std::hash_map::iterator it = m_aFieldNameMap.find( aRet ); + std::hash_map::iterator it = m_aFieldNameMap.find( aFullName ); if( it != m_aFieldNameMap.end() ) // not unique { std::hash_map< OString, sal_Int32, OStringHash >::const_iterator check_it; OString aTry; + sal_Int32 nTry = 2; do { - OStringBuffer aUnique( aRet.getLength() + 16 ); - aUnique.append( aRet ); + OStringBuffer aUnique( aFullName.getLength() + 16 ); + aUnique.append( aFullName ); aUnique.append( '_' ); - aUnique.append( it->second ); - it->second++; + aUnique.append( nTry++ ); aTry = aUnique.makeStringAndClear(); check_it = m_aFieldNameMap.find( aTry ); } while( check_it != m_aFieldNameMap.end() ); - aRet = aTry; + aFullName = aTry; + m_aFieldNameMap[ aFullName ] = i_nWidgetIndex; + aPartialName = aFullName.copy( aFullName.lastIndexOf( '.' )+1 ); } else - m_aFieldNameMap[ aRet ] = 2; + m_aFieldNameMap[ aFullName ] = i_nWidgetIndex; } - return aRet; + + // finally + m_aWidgets[i_nWidgetIndex].m_aName = aPartialName; } static void appendFixedInt( sal_Int32 nValue, OStringBuffer& rBuffer, sal_Int32 nPrecision = nLog10Divisor ) @@ -5305,78 +5404,82 @@ bool PDFWriterImpl::emitWidgetAnnotations() aLine.append( rWidget.m_nObject ); aLine.append( " 0 obj\n" "<<" ); - // emit widget annotation only for terminal fields - if( rWidget.m_aKids.empty() ) + if( rWidget.m_eType != PDFWriter::Hierarchy ) { - aLine.append( "/Type/Annot/Subtype/Widget/F 4\n" - "/Rect[" ); - appendFixedInt( rWidget.m_aRect.Left()-1, aLine ); - aLine.append( ' ' ); - appendFixedInt( rWidget.m_aRect.Top()+1, aLine ); - aLine.append( ' ' ); - appendFixedInt( rWidget.m_aRect.Right()+1, aLine ); - aLine.append( ' ' ); - appendFixedInt( rWidget.m_aRect.Bottom()-1, aLine ); - aLine.append( "]\n" ); - } - aLine.append( "/FT/" ); - switch( rWidget.m_eType ) - { - case PDFWriter::RadioButton: - case PDFWriter::CheckBox: - // for radio buttons only the RadioButton field, not the - // CheckBox children should have a value, else acrobat reader - // does not always check the right button - // of course real check boxes (not belonging to a readio group) - // need their values, too - if( rWidget.m_eType == PDFWriter::RadioButton || rWidget.m_nRadioGroup < 0 ) - { - aValue.append( "/" ); - // check for radio group with all buttons unpressed - if( rWidget.m_aValue.getLength() == 0 ) - aValue.append( "Off" ); - else - appendName( rWidget.m_aValue, aValue ); - } - case PDFWriter::PushButton: - aLine.append( "Btn" ); - break; - case PDFWriter::ListBox: - if( rWidget.m_nFlags & 0x200000 ) // multiselect - { - aValue.append( "[" ); - for( unsigned int i = 0; i < rWidget.m_aSelectedEntries.size(); i++ ) + // emit widget annotation only for terminal fields + if( rWidget.m_aKids.empty() ) + { + aLine.append( "/Type/Annot/Subtype/Widget/F 4\n" + "/Rect[" ); + appendFixedInt( rWidget.m_aRect.Left()-1, aLine ); + aLine.append( ' ' ); + appendFixedInt( rWidget.m_aRect.Top()+1, aLine ); + aLine.append( ' ' ); + appendFixedInt( rWidget.m_aRect.Right()+1, aLine ); + aLine.append( ' ' ); + appendFixedInt( rWidget.m_aRect.Bottom()-1, aLine ); + aLine.append( "]\n" ); + } + aLine.append( "/FT/" ); + switch( rWidget.m_eType ) + { + case PDFWriter::RadioButton: + case PDFWriter::CheckBox: + // for radio buttons only the RadioButton field, not the + // CheckBox children should have a value, else acrobat reader + // does not always check the right button + // of course real check boxes (not belonging to a readio group) + // need their values, too + if( rWidget.m_eType == PDFWriter::RadioButton || rWidget.m_nRadioGroup < 0 ) { - sal_Int32 nEntry = rWidget.m_aSelectedEntries[i]; - if( nEntry >= 0 && nEntry < sal_Int32(rWidget.m_aListEntries.size()) ) - appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ nEntry ], rWidget.m_nObject, aValue ); + aValue.append( "/" ); + // check for radio group with all buttons unpressed + if( rWidget.m_aValue.getLength() == 0 ) + aValue.append( "Off" ); + else + appendName( rWidget.m_aValue, aValue ); } - aValue.append( "]" ); - } - else if( rWidget.m_aSelectedEntries.size() > 0 && - rWidget.m_aSelectedEntries[0] >= 0 && - rWidget.m_aSelectedEntries[0] < sal_Int32(rWidget.m_aListEntries.size()) ) - { - appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ rWidget.m_aSelectedEntries[0] ], rWidget.m_nObject, aValue ); - } - else - appendUnicodeTextStringEncrypt( rtl::OUString(), rWidget.m_nObject, aValue ); - aLine.append( "Ch" ); - break; - case PDFWriter::ComboBox: - appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue ); - aLine.append( "Ch" ); - break; - case PDFWriter::Edit: - aLine.append( "Tx" ); - appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue ); - break; + case PDFWriter::PushButton: + aLine.append( "Btn" ); + break; + case PDFWriter::ListBox: + if( rWidget.m_nFlags & 0x200000 ) // multiselect + { + aValue.append( "[" ); + for( unsigned int i = 0; i < rWidget.m_aSelectedEntries.size(); i++ ) + { + sal_Int32 nEntry = rWidget.m_aSelectedEntries[i]; + if( nEntry >= 0 && nEntry < sal_Int32(rWidget.m_aListEntries.size()) ) + appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ nEntry ], rWidget.m_nObject, aValue ); + } + aValue.append( "]" ); + } + else if( rWidget.m_aSelectedEntries.size() > 0 && + rWidget.m_aSelectedEntries[0] >= 0 && + rWidget.m_aSelectedEntries[0] < sal_Int32(rWidget.m_aListEntries.size()) ) + { + appendUnicodeTextStringEncrypt( rWidget.m_aListEntries[ rWidget.m_aSelectedEntries[0] ], rWidget.m_nObject, aValue ); + } + else + appendUnicodeTextStringEncrypt( rtl::OUString(), rWidget.m_nObject, aValue ); + aLine.append( "Ch" ); + break; + case PDFWriter::ComboBox: + appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue ); + aLine.append( "Ch" ); + break; + case PDFWriter::Edit: + aLine.append( "Tx" ); + appendUnicodeTextStringEncrypt( rWidget.m_aValue, rWidget.m_nObject, aValue ); + break; + case PDFWriter::Hierarchy: // make the compiler happy + break; + } + aLine.append( "\n" ); + aLine.append( "/P " ); + aLine.append( m_aPages[ rWidget.m_nPage ].m_nPageObject ); + aLine.append( " 0 R\n" ); } - aLine.append( "\n" ); - aLine.append( "/P " ); - aLine.append( m_aPages[ rWidget.m_nPage ].m_nPageObject ); - aLine.append( " 0 R\n" ); - if( rWidget.m_nParent ) { aLine.append( "/Parent " ); @@ -5400,7 +5503,7 @@ bool PDFWriterImpl::emitWidgetAnnotations() appendLiteralStringEncrypt( rWidget.m_aName, rWidget.m_nObject, aLine ); aLine.append( "\n" ); } - if( m_aContext.Version > PDFWriter::PDF_1_2 ) + if( m_aContext.Version > PDFWriter::PDF_1_2 && rWidget.m_aDescription.getLength() ) { // the alternate field name should be unicode able since it is // supposed to be used in UI @@ -5462,7 +5565,7 @@ bool PDFWriterImpl::emitWidgetAnnotations() if(!m_bIsPDF_A1) { OStringBuffer aDest; - if( appendDest( rWidget.m_nDest, aDest ) ) + if( rWidget.m_nDest != -1 && appendDest( rWidget.m_nDest, aDest ) ) { aLine.append( "/AA<= 0 ) + { + AnnotSortContainer& rCont = sorted[ rWidget.m_nPage ]; + // optimize vector allocation + if( rCont.aSortedAnnots.empty() ) + rCont.aSortedAnnots.reserve( m_aPages[ rWidget.m_nPage ].m_aAnnotations.size() ); + // insert widget to tab sorter + // RadioButtons are not page annotations, only their individual check boxes are + if( rWidget.m_eType != PDFWriter::RadioButton ) + { + rCont.aObjects.insert( rWidget.m_nObject ); + rCont.aSortedAnnots.push_back( AnnotationSortEntry( rWidget.m_nTabOrder, rWidget.m_nObject, nW ) ); + } } } for( std::hash_map< sal_Int32, AnnotSortContainer >::iterator it = sorted.begin(); it != sorted.end(); ++it ) @@ -11629,18 +11735,7 @@ sal_Int32 PDFWriterImpl::findRadioGroupWidget( const PDFWriter::RadioButtonWidge m_aWidgets.back().m_nRadioGroup = rBtn.RadioGroup; m_aWidgets.back().m_nFlags |= 0x00008000; - // create radio button field name - const rtl::OUString& rName = (m_aContext.Version > PDFWriter::PDF_1_2) ? - rBtn.Name : rBtn.Text; - if( rName.getLength() ) - { - m_aWidgets.back().m_aName = convertWidgetFieldName( rName ); - } - else - { - m_aWidgets.back().m_aName = "RadioGroup"; - m_aWidgets.back().m_aName += OString::valueOf( rBtn.RadioGroup ); - } + createWidgetFieldName( sal_Int32(m_aWidgets.size()-1), rBtn ); } else nRadioGroupWidget = it->second; @@ -11656,44 +11751,27 @@ sal_Int32 PDFWriterImpl::createControl( const PDFWriter::AnyWidget& rControl, sa if( nPageNr < 0 || nPageNr >= (sal_Int32)m_aPages.size() ) return -1; + sal_Int32 nNewWidget = m_aWidgets.size(); m_aWidgets.push_back( PDFWidget() ); - sal_Int32 nNewWidget = m_aWidgets.size()-1; - // create eventual radio button before getting any references - // from m_aWidgets as the push_back operation potentially assigns new - // memory to the vector and thereby invalidates the reference - int nRadioGroupWidget = -1; - if( rControl.getType() == PDFWriter::RadioButton ) - nRadioGroupWidget = findRadioGroupWidget( static_cast(rControl) ); - - PDFWidget& rNewWidget = m_aWidgets[nNewWidget]; - rNewWidget.m_nObject = createObject(); - rNewWidget.m_aRect = rControl.Location; - rNewWidget.m_nPage = nPageNr; - rNewWidget.m_eType = rControl.getType(); + m_aWidgets.back().m_nObject = createObject(); + m_aWidgets.back().m_aRect = rControl.Location; + m_aWidgets.back().m_nPage = nPageNr; + m_aWidgets.back().m_eType = rControl.getType(); + sal_Int32 nRadioGroupWidget = -1; // for unknown reasons the radio buttons of a radio group must not have a // field name, else the buttons are in fact check boxes - // that is multiple buttons of the radio group can be selected - if( rControl.getType() != PDFWriter::RadioButton ) + if( rControl.getType() == PDFWriter::RadioButton ) + nRadioGroupWidget = findRadioGroupWidget( static_cast(rControl) ); + else { - // acrobat reader since 3.0 does not support unicode text - // strings for the field name; so we need to encode unicodes - // larger than 255 - - rNewWidget.m_aName = - convertWidgetFieldName( (m_aContext.Version > PDFWriter::PDF_1_2) ? - rControl.Name : rControl.Text ); - // #i88040# acrobat reader crashes on empty field names, - // so always create one - if( rNewWidget.m_aName.getLength() == 0 ) - { - OUStringBuffer aBuf( 32 ); - aBuf.appendAscii( "Widget" ); - aBuf.append( nNewWidget ); - rNewWidget.m_aName = convertWidgetFieldName( aBuf.makeStringAndClear() ); - } + createWidgetFieldName( nNewWidget, rControl ); } + + // caution: m_aWidgets must not be changed after here or rNewWidget may be invalid + PDFWidget& rNewWidget = m_aWidgets[nNewWidget]; rNewWidget.m_aDescription = rControl.Description; rNewWidget.m_aText = rControl.Text; rNewWidget.m_nTextStyle = rControl.TextStyle & @@ -11924,6 +12002,7 @@ bool PDFWriterImpl::endControlAppearance( PDFWriter::WidgetState eState ) break; case PDFWriter::ListBox: case PDFWriter::ComboBox: + case PDFWriter::Hierarchy: break; } if( aState.getLength() && aStyle.getLength() ) diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx index 83270b56159b..be548375dd62 100644 --- a/vcl/source/gdi/pdfwriter_impl.hxx +++ b/vcl/source/gdi/pdfwriter_impl.hxx @@ -1059,7 +1059,7 @@ i12626 void createDefaultListBoxAppearance( PDFWidget&, const PDFWriter::ListBoxWidget& rWidget ); /* ensure proper escapement and uniqueness of field names */ - rtl::OString convertWidgetFieldName( const rtl::OUString& rString ); + void createWidgetFieldName( sal_Int32 i_nWidgetsIndex, const PDFWriter::AnyWidget& i_rInWidget ); /* adds an entry to m_aObjects and returns its index+1, * sets the offset to ~0 */ -- cgit From b4198879145910d444b4e613fe8177ab746b0fb7 Mon Sep 17 00:00:00 2001 From: Vladimir Glazunov Date: Thu, 25 Mar 2010 13:37:28 +0100 Subject: CWS-TOOLING: integrate CWS ooo321gsl01_DEV300 --- vcl/source/gdi/outdev3.cxx | 1 + 1 file changed, 1 insertion(+) (limited to 'vcl/source/gdi') diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx index 963b7a3daa30..e13ae6cbe64a 100644 --- a/vcl/source/gdi/outdev3.cxx +++ b/vcl/source/gdi/outdev3.cxx @@ -1337,6 +1337,7 @@ void ImplDevFontList::InitGenericGlyphFallback( void ) const "muktinarrow", "", "phetsarathot", "", "padauk", "pinlonmyanmar", "", + "iskoolapota", "lklug", "", 0 }; -- cgit