summaryrefslogtreecommitdiff
path: root/vcl/source/gdi
diff options
context:
space:
mode:
authorJens-Heiner Rechtien <hr@openoffice.org>2010-01-28 18:49:22 +0000
committerJens-Heiner Rechtien <hr@openoffice.org>2010-01-28 18:49:22 +0000
commit4c6cda4e38b13dc3d634f0922a734258ab153ab9 (patch)
tree7f42031fb6937ec1621c758c24fa0b8d231c92cb /vcl/source/gdi
parent2e77984f087afde2ba0ca0edc5987a6f52d1095e (diff)
parentf4ce12bb2e6f64f5b4cfed9b1b13f8e87371b4a9 (diff)
koheidatapilot03: merge with DEV300_m56
Diffstat (limited to 'vcl/source/gdi')
-rw-r--r--vcl/source/gdi/gdimtf.cxx430
-rw-r--r--vcl/source/gdi/graph.cxx38
-rw-r--r--vcl/source/gdi/impgraph.cxx38
-rw-r--r--vcl/source/gdi/impimagetree.cxx7
-rw-r--r--vcl/source/gdi/makefile.mk4
-rw-r--r--vcl/source/gdi/outdev.cxx312
-rw-r--r--vcl/source/gdi/outdev3.cxx91
-rw-r--r--vcl/source/gdi/outdev6.cxx14
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx48
-rw-r--r--vcl/source/gdi/pngread.cxx21
-rw-r--r--vcl/source/gdi/print.cxx148
-rwxr-xr-xvcl/source/gdi/sallayout.cxx140
12 files changed, 1034 insertions, 257 deletions
diff --git a/vcl/source/gdi/gdimtf.cxx b/vcl/source/gdi/gdimtf.cxx
index 3a29e6d56095..6483c8292df7 100644
--- a/vcl/source/gdi/gdimtf.cxx
+++ b/vcl/source/gdi/gdimtf.cxx
@@ -1403,6 +1403,436 @@ void GDIMetaFile::Rotate( long nAngle10 )
// ------------------------------------------------------------------------
+static void ImplActionBounds( Rectangle& o_rOutBounds,
+ const Rectangle& i_rInBounds,
+ const std::vector<Rectangle>& i_rClipStack )
+{
+ Rectangle aBounds( i_rInBounds );
+ if( ! i_rInBounds.IsEmpty() && ! i_rClipStack.empty() && ! i_rClipStack.back().IsEmpty() )
+ aBounds.Intersection( i_rClipStack.back() );
+ if( ! aBounds.IsEmpty() )
+ {
+ if( ! o_rOutBounds.IsEmpty() )
+ o_rOutBounds.Union( aBounds );
+ else
+ o_rOutBounds = aBounds;
+ }
+}
+
+Rectangle GDIMetaFile::GetBoundRect( OutputDevice& i_rReference )
+{
+ GDIMetaFile aMtf;
+ VirtualDevice aMapVDev( i_rReference );
+
+ aMapVDev.EnableOutput( FALSE );
+ aMapVDev.SetMapMode( GetPrefMapMode() );
+
+ std::vector<Rectangle> aClipStack( 1, Rectangle() );
+ std::vector<USHORT> aPushFlagStack;
+
+ Rectangle aBound;
+
+ for( MetaAction* pAction = (MetaAction*) First(); pAction; pAction = (MetaAction*) Next() )
+ {
+ const USHORT nActionType = pAction->GetType();
+
+ switch( nActionType )
+ {
+ case( META_PIXEL_ACTION ):
+ {
+ MetaPixelAction* pAct = (MetaPixelAction*) pAction;
+ ImplActionBounds( aBound,
+ Rectangle( aMapVDev.LogicToLogic( pAct->GetPoint(), aMapVDev.GetMapMode(), GetPrefMapMode() ),
+ aMapVDev.PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
+ aClipStack );
+ }
+ break;
+
+ case( META_POINT_ACTION ):
+ {
+ MetaPointAction* pAct = (MetaPointAction*) pAction;
+ ImplActionBounds( aBound,
+ Rectangle( aMapVDev.LogicToLogic( pAct->GetPoint(), aMapVDev.GetMapMode(), GetPrefMapMode() ),
+ aMapVDev.PixelToLogic( Size( 1, 1 ), GetPrefMapMode() ) ),
+ aClipStack );
+ }
+ break;
+
+ case( META_LINE_ACTION ):
+ {
+ MetaLineAction* pAct = (MetaLineAction*) pAction;
+ Point aP1( pAct->GetStartPoint() ), aP2( pAct->GetEndPoint() );
+ Rectangle aRect( aP1, aP2 );
+ aRect.Justify();
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_RECT_ACTION ):
+ {
+ MetaRectAction* pAct = (MetaRectAction*) pAction;
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_ROUNDRECT_ACTION ):
+ {
+ MetaRoundRectAction* pAct = (MetaRoundRectAction*) pAction;
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_ELLIPSE_ACTION ):
+ {
+ MetaEllipseAction* pAct = (MetaEllipseAction*) pAction;
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_ARC_ACTION ):
+ {
+ MetaArcAction* pAct = (MetaArcAction*) pAction;
+ // FIXME: this is imprecise
+ // e.g. for small arcs the whole rectangle is WAY too large
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_PIE_ACTION ):
+ {
+ MetaPieAction* pAct = (MetaPieAction*) pAction;
+ // FIXME: this is imprecise
+ // e.g. for small arcs the whole rectangle is WAY too large
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_CHORD_ACTION ):
+ {
+ MetaChordAction* pAct = (MetaChordAction*) pAction;
+ // FIXME: this is imprecise
+ // e.g. for small arcs the whole rectangle is WAY too large
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_POLYLINE_ACTION ):
+ {
+ MetaPolyLineAction* pAct = (MetaPolyLineAction*) pAction;
+ Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_POLYGON_ACTION ):
+ {
+ MetaPolygonAction* pAct = (MetaPolygonAction*) pAction;
+ Rectangle aRect( pAct->GetPolygon().GetBoundRect() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_POLYPOLYGON_ACTION ):
+ {
+ MetaPolyPolygonAction* pAct = (MetaPolyPolygonAction*) pAction;
+ Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_TEXT_ACTION ):
+ {
+ MetaTextAction* pAct = (MetaTextAction*) pAction;
+ Rectangle aRect;
+ // hdu said base = index
+ aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen() );
+ Point aPt( pAct->GetPoint() );
+ aRect.Move( aPt.X(), aPt.Y() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_TEXTARRAY_ACTION ):
+ {
+ MetaTextArrayAction* pAct = (MetaTextArrayAction*) pAction;
+ Rectangle aRect;
+ // hdu said base = index
+ aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
+ 0, pAct->GetDXArray() );
+ Point aPt( pAct->GetPoint() );
+ aRect.Move( aPt.X(), aPt.Y() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_STRETCHTEXT_ACTION ):
+ {
+ MetaStretchTextAction* pAct = (MetaStretchTextAction*) pAction;
+ Rectangle aRect;
+ // hdu said base = index
+ aMapVDev.GetTextBoundRect( aRect, pAct->GetText(), pAct->GetIndex(), pAct->GetIndex(), pAct->GetLen(),
+ pAct->GetWidth(), NULL );
+ Point aPt( pAct->GetPoint() );
+ aRect.Move( aPt.X(), aPt.Y() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_TEXTLINE_ACTION ):
+ {
+ MetaTextLineAction* pAct = (MetaTextLineAction*) pAction;
+ // measure a test string to get ascend and descent right
+ static const sal_Unicode pStr[] = { 0xc4, 0x67, 0 };
+ String aStr( pStr );
+
+ Rectangle aRect;
+ aMapVDev.GetTextBoundRect( aRect, aStr, 0, 0, aStr.Len(), 0, NULL );
+ Point aPt( pAct->GetStartPoint() );
+ aRect.Move( aPt.X(), aPt.Y() );
+ aRect.Right() = aRect.Left() + pAct->GetWidth();
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_BMPSCALE_ACTION ):
+ {
+ MetaBmpScaleAction* pAct = (MetaBmpScaleAction*) pAction;
+ Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_BMPSCALEPART_ACTION ):
+ {
+ MetaBmpScalePartAction* pAct = (MetaBmpScalePartAction*) pAction;
+ Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_BMPEXSCALE_ACTION ):
+ {
+ MetaBmpExScaleAction* pAct = (MetaBmpExScaleAction*) pAction;
+ Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_BMPEXSCALEPART_ACTION ):
+ {
+ MetaBmpExScalePartAction* pAct = (MetaBmpExScalePartAction*) pAction;
+ Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_GRADIENT_ACTION ):
+ {
+ MetaGradientAction* pAct = (MetaGradientAction*) pAction;
+ Rectangle aRect( pAct->GetRect() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_GRADIENTEX_ACTION ):
+ {
+ MetaGradientExAction* pAct = (MetaGradientExAction*) pAction;
+ Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_COMMENT_ACTION ):
+ {
+ // nothing to do
+ };
+ break;
+
+ case( META_HATCH_ACTION ):
+ {
+ MetaHatchAction* pAct = (MetaHatchAction*) pAction;
+ Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_TRANSPARENT_ACTION ):
+ {
+ MetaTransparentAction* pAct = (MetaTransparentAction*) pAction;
+ Rectangle aRect( pAct->GetPolyPolygon().GetBoundRect() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_FLOATTRANSPARENT_ACTION ):
+ {
+ MetaFloatTransparentAction* pAct = (MetaFloatTransparentAction*) pAction;
+ GDIMetaFile aTransMtf( pAct->GetGDIMetaFile() );
+ // get the bound rect of the contained metafile
+ Rectangle aRect( aTransMtf.GetBoundRect( i_rReference ) );
+ // scale the rect now on the assumption that the correct top left of the metafile
+ // (not its bounds !) is (0,0)
+ Size aPSize( aTransMtf.GetPrefSize() );
+ aPSize = aMapVDev.LogicToLogic( aPSize, aTransMtf.GetPrefMapMode(), aMapVDev.GetMapMode() );
+ Size aActSize( pAct->GetSize() );
+ double fX = double(aActSize.Width())/double(aPSize.Width());
+ double fY = double(aActSize.Height())/double(aPSize.Height());
+ aRect.Left() = long(double(aRect.Left())*fX);
+ aRect.Right() = long(double(aRect.Right())*fX);
+ aRect.Top() = long(double(aRect.Top())*fY);
+ aRect.Bottom() = long(double(aRect.Bottom())*fY);
+
+ // transform the rect to current VDev state
+ aRect = aMapVDev.LogicToLogic( aRect, aTransMtf.GetPrefMapMode(), aMapVDev.GetMapMode() );
+
+ ImplActionBounds( aBound, aRect, aClipStack );
+ }
+ break;
+
+ case( META_EPS_ACTION ):
+ {
+ MetaEPSAction* pAct = (MetaEPSAction*) pAction;
+ Rectangle aRect( pAct->GetPoint(), pAct->GetSize() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_CLIPREGION_ACTION ):
+ {
+ MetaClipRegionAction* pAct = (MetaClipRegionAction*) pAction;
+ if( pAct->IsClipping() )
+ aClipStack.back() = aMapVDev.LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev.GetMapMode(), GetPrefMapMode() );
+ else
+ aClipStack.back() = Rectangle();
+ }
+ break;
+
+ case( META_ISECTRECTCLIPREGION_ACTION ):
+ {
+ MetaISectRectClipRegionAction* pAct = (MetaISectRectClipRegionAction*) pAction;
+ Rectangle aRect( aMapVDev.LogicToLogic( pAct->GetRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ) );
+ if( aClipStack.back().IsEmpty() )
+ aClipStack.back() = aRect;
+ else
+ aClipStack.back().Intersection( aRect );
+ }
+ break;
+
+ case( META_ISECTREGIONCLIPREGION_ACTION ):
+ {
+ MetaISectRegionClipRegionAction* pAct = (MetaISectRegionClipRegionAction*) pAction;
+ Rectangle aRect( aMapVDev.LogicToLogic( pAct->GetRegion().GetBoundRect(), aMapVDev.GetMapMode(), GetPrefMapMode() ) );
+ if( aClipStack.back().IsEmpty() )
+ aClipStack.back() = aRect;
+ else
+ aClipStack.back().Intersection( aRect );
+ }
+ break;
+
+ case( META_BMP_ACTION ):
+ {
+ MetaBmpAction* pAct = (MetaBmpAction*) pAction;
+ Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_BMPEX_ACTION ):
+ {
+ MetaBmpExAction* pAct = (MetaBmpExAction*) pAction;
+ Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmapEx().GetSizePixel() ) );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_MASK_ACTION ):
+ {
+ MetaMaskAction* pAct = (MetaMaskAction*) pAction;
+ Rectangle aRect( pAct->GetPoint(), aMapVDev.PixelToLogic( pAct->GetBitmap().GetSizePixel() ) );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_MASKSCALE_ACTION ):
+ {
+ MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
+ Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_MASKSCALEPART_ACTION ):
+ {
+ MetaMaskScalePartAction* pAct = (MetaMaskScalePartAction*) pAction;
+ Rectangle aRect( pAct->GetDestPoint(), pAct->GetDestSize() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_WALLPAPER_ACTION ):
+ {
+ MetaWallpaperAction* pAct = (MetaWallpaperAction*) pAction;
+ Rectangle aRect( pAct->GetRect() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_TEXTRECT_ACTION ):
+ {
+ MetaTextRectAction* pAct = (MetaTextRectAction*) pAction;
+ Rectangle aRect( pAct->GetRect() );
+ ImplActionBounds( aBound, aMapVDev.LogicToLogic( aRect, aMapVDev.GetMapMode(), GetPrefMapMode() ), aClipStack );
+ }
+ break;
+
+ case( META_MOVECLIPREGION_ACTION ):
+ {
+ MetaMoveClipRegionAction* pAct = (MetaMoveClipRegionAction*) pAction;
+ if( ! aClipStack.back().IsEmpty() )
+ {
+ Size aDelta( pAct->GetHorzMove(), pAct->GetVertMove() );
+ aDelta = aMapVDev.LogicToLogic( aDelta, aMapVDev.GetMapMode(), GetPrefMapMode() );
+ aClipStack.back().Move( aDelta.Width(), aDelta.Width() );
+ }
+ }
+ break;
+
+ default:
+ {
+ pAction->Execute( &aMapVDev );
+
+ if( nActionType == META_PUSH_ACTION )
+ {
+ MetaPushAction* pAct = (MetaPushAction*) pAction;
+ aPushFlagStack.push_back( pAct->GetFlags() );
+ if( (aPushFlagStack.back() & PUSH_CLIPREGION) != 0 )
+ {
+ Rectangle aRect( aClipStack.back() );
+ aClipStack.push_back( aRect );
+ }
+ }
+ else if( nActionType == META_POP_ACTION )
+ {
+ // sanity check
+ if( ! aPushFlagStack.empty() )
+ {
+ if( (aPushFlagStack.back() & PUSH_CLIPREGION) != 0 )
+ {
+ if( aClipStack.size() > 1 )
+ aClipStack.pop_back();
+ }
+ aPushFlagStack.pop_back();
+ }
+ }
+ }
+ break;
+ }
+ }
+ return aBound;
+}
+
+// ------------------------------------------------------------------------
+
Color GDIMetaFile::ImplColAdjustFnc( const Color& rColor, const void* pColParam )
{
return Color( rColor.GetTransparency(),
diff --git a/vcl/source/gdi/graph.cxx b/vcl/source/gdi/graph.cxx
index dfa155e29eae..77f065912e5d 100644
--- a/vcl/source/gdi/graph.cxx
+++ b/vcl/source/gdi/graph.cxx
@@ -430,44 +430,16 @@ BOOL Graphic::IsAnimated() const
// ------------------------------------------------------------------------
-Bitmap Graphic::GetBitmap() const
+Bitmap Graphic::GetBitmap(const GraphicConversionParameters& rParameters) const
{
- return GetBitmap( NULL );
+ return mpImpGraphic->ImplGetBitmap(rParameters);
}
// ------------------------------------------------------------------------
-BitmapEx Graphic::GetBitmapEx() const
+BitmapEx Graphic::GetBitmapEx(const GraphicConversionParameters& rParameters) const
{
- return GetBitmapEx( NULL );
-}
-
-// ------------------------------------------------------------------------
-
-Bitmap Graphic::GetBitmap( const Size* pSizePixel ) const
-{
- return mpImpGraphic->ImplGetBitmap( pSizePixel, FALSE );
-}
-
-// ------------------------------------------------------------------------
-
-BitmapEx Graphic::GetBitmapEx( const Size* pSizePixel ) const
-{
- return mpImpGraphic->ImplGetBitmapEx( pSizePixel, FALSE );
-}
-
-// ------------------------------------------------------------------------
-
-Bitmap Graphic::GetUnlimitedBitmap( const Size* pSizePixel ) const
-{
- return mpImpGraphic->ImplGetBitmap( pSizePixel, TRUE ) ;
-}
-
-// ------------------------------------------------------------------------
-
-BitmapEx Graphic::GetUnlimitedBitmapEx( const Size* pSizePixel ) const
-{
- return mpImpGraphic->ImplGetBitmapEx( pSizePixel, TRUE ) ;
+ return mpImpGraphic->ImplGetBitmapEx(rParameters);
}
// ------------------------------------------------------------------------
@@ -553,7 +525,7 @@ Size Graphic::GetSizePixel( const OutputDevice* pRefDevice ) const
Size aRet;
if( GRAPHIC_BITMAP == mpImpGraphic->ImplGetType() )
- aRet = mpImpGraphic->ImplGetBitmapEx( NULL, FALSE ).GetSizePixel();
+ aRet = mpImpGraphic->ImplGetBitmapEx(GraphicConversionParameters()).GetSizePixel();
else
aRet = ( pRefDevice ? pRefDevice : Application::GetDefaultDevice() )->LogicToPixel( GetPrefSize(), GetPrefMapMode() );
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index a67d6fa7feac..d73f35bef962 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -483,7 +483,7 @@ BOOL ImpGraphic::ImplIsAnimated() const
// ------------------------------------------------------------------------
-Bitmap ImpGraphic::ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) const
+Bitmap ImpGraphic::ImplGetBitmap(const GraphicConversionParameters& rParameters) const
{
Bitmap aRetBmp;
@@ -494,8 +494,8 @@ Bitmap ImpGraphic::ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) cons
aRetBmp = rRetBmpEx.GetBitmap( &aReplaceColor );
- if( pSizePixel )
- aRetBmp.Scale( *pSizePixel );
+ if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
+ aRetBmp.Scale(rParameters.getSizePixel());
}
else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
{
@@ -508,16 +508,18 @@ Bitmap ImpGraphic::ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) cons
Size aDrawSize( aVDev.LogicToPixel( maMetaFile.GetPrefSize(), maMetaFile.GetPrefMapMode() ) );
Size aSizePix( labs( aBRPix.X() - aTLPix.X() ) + 1, labs( aBRPix.Y() - aTLPix.Y() ) + 1 );
- if( pSizePixel && aSizePix.Width() && aSizePix.Height() )
+ if(rParameters.getSizePixel().Width() && rParameters.getSizePixel().Height())
{
- aDrawSize.Width() = FRound( (double) pSizePixel->Width() * (double) aDrawSize.Width() / (double) aSizePix.Width() );
- aDrawSize.Height() = FRound( (double) pSizePixel->Height() * (double) aDrawSize.Height() / (double) aSizePix.Height() );
+ aDrawSize.Width() = FRound((double)rParameters.getSizePixel().Width() *
+ (double)aDrawSize.Width() / (double)aSizePix.Width());
+ aDrawSize.Height() = FRound((double)rParameters.getSizePixel().Height() *
+ (double)aDrawSize.Height() / (double)aSizePix.Height());
- aSizePix = *pSizePixel;
+ aSizePix = rParameters.getSizePixel();
}
- if( aSizePix.Width() && aSizePix.Height() && !bUnlimited &&
- ( aSizePix.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aSizePix.Height() > GRAPHIC_MTFTOBMP_MAXEXT ) )
+ if( aSizePix.Width() && aSizePix.Height() && !rParameters.getUnlimitedSize()
+ && (aSizePix.Width() > GRAPHIC_MTFTOBMP_MAXEXT || aSizePix.Height() > GRAPHIC_MTFTOBMP_MAXEXT))
{
const Size aOldSizePix( aSizePix );
double fWH = (double) aSizePix.Width() / aSizePix.Height();
@@ -533,6 +535,16 @@ Bitmap ImpGraphic::ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) cons
if( aVDev.SetOutputSizePixel( aSizePix ) )
{
+ if(rParameters.getAntiAliase())
+ {
+ aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_ENABLE_B2DDRAW);
+ }
+
+ if(rParameters.getSnapHorVerLines())
+ {
+ aVDev.SetAntialiasing(aVDev.GetAntialiasing() | ANTIALIASING_PIXELSNAPHAIRLINE);
+ }
+
ImplDraw( &aVDev, aNullPt, aDrawSize );
aRetBmp = aVDev.GetBitmap( aNullPt, aVDev.GetOutputSizePixel() );
}
@@ -549,7 +561,7 @@ Bitmap ImpGraphic::ImplGetBitmap( const Size* pSizePixel, BOOL bUnlimited ) cons
// ------------------------------------------------------------------------
-BitmapEx ImpGraphic::ImplGetBitmapEx( const Size* pSizePixel, BOOL bUnlimited ) const
+BitmapEx ImpGraphic::ImplGetBitmapEx(const GraphicConversionParameters& rParameters) const
{
BitmapEx aRetBmpEx;
@@ -557,13 +569,13 @@ BitmapEx ImpGraphic::ImplGetBitmapEx( const Size* pSizePixel, BOOL bUnlimited )
{
aRetBmpEx = ( mpAnimation ? mpAnimation->GetBitmapEx() : maEx );
- if( pSizePixel )
- aRetBmpEx.Scale( *pSizePixel );
+ if(rParameters.getSizePixel().Width() || rParameters.getSizePixel().Height())
+ aRetBmpEx.Scale(rParameters.getSizePixel());
}
else if( ( meType != GRAPHIC_DEFAULT ) && ImplIsSupportedGraphic() )
{
const ImpGraphic aMonoMask( maMetaFile.GetMonochromeMtf( COL_BLACK ) );
- aRetBmpEx = BitmapEx( ImplGetBitmap( pSizePixel, bUnlimited ), aMonoMask.ImplGetBitmap( pSizePixel, bUnlimited ) );
+ aRetBmpEx = BitmapEx(ImplGetBitmap(rParameters), aMonoMask.ImplGetBitmap(rParameters));
}
return aRetBmpEx;
diff --git a/vcl/source/gdi/impimagetree.cxx b/vcl/source/gdi/impimagetree.cxx
index 64cddece1199..9e1378f22326 100644
--- a/vcl/source/gdi/impimagetree.cxx
+++ b/vcl/source/gdi/impimagetree.cxx
@@ -102,8 +102,11 @@ void loadFromStream(
rtl::OUString const & path, BitmapEx & bitmap)
{
std::auto_ptr< SvStream > s(wrapStream(stream));
- if (path.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".png"))) {
- bitmap = vcl::PNGReader(*s).Read();
+ if (path.endsWithAsciiL(RTL_CONSTASCII_STRINGPARAM(".png")))
+ {
+ vcl::PNGReader aPNGReader( *s );
+ aPNGReader.SetIgnoreGammaChunk( sal_True );
+ bitmap = aPNGReader.Read();
} else {
*s >> bitmap;
}
diff --git a/vcl/source/gdi/makefile.mk b/vcl/source/gdi/makefile.mk
index 977e5386fe97..a09ae92dcb5e 100644
--- a/vcl/source/gdi/makefile.mk
+++ b/vcl/source/gdi/makefile.mk
@@ -45,6 +45,9 @@ TARGET=gdi
.IF "$(COM)"=="ICC"
CDEFS+=-D_STD_NO_NAMESPACE -D_VOS_NO_NAMESPACE -D_UNO_NO_NAMESPACE
.ENDIF
+.IF "$(ENABLE_GRAPHITE)" == "TRUE"
+CDEFS+=-DENABLE_GRAPHITE
+.ENDIF
# --- Files --------------------------------------------------------
@@ -137,6 +140,7 @@ EXCEPTIONSFILES= $(SLO)$/salmisc.obj \
$(SLO)$/pngwrite.obj \
$(SLO)$/virdev.obj \
$(SLO)$/impprn.obj \
+ $(SLO)$/gdimtf.obj \
$(SLO)$/graphictools.obj
diff --git a/vcl/source/gdi/outdev.cxx b/vcl/source/gdi/outdev.cxx
index 0e9da9f81136..5b543258cb0b 100644
--- a/vcl/source/gdi/outdev.cxx
+++ b/vcl/source/gdi/outdev.cxx
@@ -68,6 +68,8 @@
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dlinegeometry.hxx>
#include <com/sun/star/awt/XGraphics.hpp>
#include <com/sun/star/uno/Sequence.hxx>
@@ -2285,8 +2287,35 @@ void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt )
if ( mbInitLineColor )
ImplInitLineColor();
- Point aStartPt = ImplLogicToDevicePixel( rStartPt );
- Point aEndPt = ImplLogicToDevicePixel( rEndPt );
+ // #i101598# support AA and snap for lines, too
+ if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+ && ROP_OVERPAINT == GetRasterOp()
+ && IsLineColor())
+ {
+ // at least transform with double precision to device coordinates; this will
+ // avoid pixel snap of single, appended lines
+ const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
+ const basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
+ basegfx::B2DPolygon aB2DPolyLine;
+
+ aB2DPolyLine.append(basegfx::B2DPoint(rStartPt.X(), rStartPt.Y()));
+ aB2DPolyLine.append(basegfx::B2DPoint(rEndPt.X(), rEndPt.Y()));
+ aB2DPolyLine.transform( aTransform );
+
+ if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
+ {
+ aB2DPolyLine = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine);
+ }
+
+ if(mpGraphics->DrawPolyLine(aB2DPolyLine, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this))
+ {
+ return;
+ }
+ }
+
+ const Point aStartPt(ImplLogicToDevicePixel(rStartPt));
+ const Point aEndPt(ImplLogicToDevicePixel(rEndPt));
mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y(), this );
@@ -2444,22 +2473,30 @@ void OutputDevice::DrawPolyLine( const Polygon& rPoly )
if ( mbInitLineColor )
ImplInitLineColor();
+ const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+ && ROP_OVERPAINT == GetRasterOp()
+ && IsLineColor());
+
// use b2dpolygon drawing if possible
- if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+ if(bTryAA && ImpTryDrawPolyLineDirect(rPoly.getB2DPolygon(), 0.0, basegfx::B2DLINEJOIN_NONE))
{
- ::basegfx::B2DPolygon aB2DPolyLine = rPoly.getB2DPolygon();
+ basegfx::B2DPolygon aB2DPolyLine(rPoly.getB2DPolygon());
const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
- aB2DPolyLine.transform( aTransform );
const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
- if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && (mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE))
+ // transform the polygon
+ aB2DPolyLine.transform( aTransform );
+
+ if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
{
- // #i98289#
aB2DPolyLine = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine);
}
- if( mpGraphics->DrawPolyLine( aB2DPolyLine, aB2DLineWidth, basegfx::B2DLINEJOIN_ROUND, this ) )
+ if(mpGraphics->DrawPolyLine(aB2DPolyLine, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this))
+ {
return;
+ }
}
Polygon aPoly = ImplLogicToDevicePixel( rPoly );
@@ -2499,9 +2536,23 @@ void OutputDevice::DrawPolyLine( const Polygon& rPoly, const LineInfo& rLineInfo
return;
}
+ // #i101491#
+ // Try direct Fallback to B2D-Version of DrawPolyLine
+ if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && LINE_SOLID == rLineInfo.GetStyle())
+ {
+ DrawPolyLine(rPoly.getB2DPolygon(), (double)rLineInfo.GetWidth(), basegfx::B2DLINEJOIN_ROUND);
+ return;
+ }
+
if ( mpMetaFile )
mpMetaFile->AddAction( new MetaPolyLineAction( rPoly, rLineInfo ) );
+ ImpDrawPolyLineWithLineInfo(rPoly, rLineInfo);
+}
+
+void OutputDevice::ImpDrawPolyLineWithLineInfo(const Polygon& rPoly, const LineInfo& rLineInfo)
+{
USHORT nPoints = rPoly.GetSize();
if ( !IsDeviceOutputNecessary() || !mbLineColor || ( nPoints < 2 ) || ( LINE_NONE == rLineInfo.GetStyle() ) || ImplIsRecordLayout() )
@@ -2527,6 +2578,10 @@ void OutputDevice::DrawPolyLine( const Polygon& rPoly, const LineInfo& rLineInfo
return;
const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) );
+ const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+ && ROP_OVERPAINT == GetRasterOp()
+ && IsLineColor());
if( aInfo.GetWidth() > 1L )
{
@@ -2540,9 +2595,32 @@ void OutputDevice::DrawPolyLine( const Polygon& rPoly, const LineInfo& rLineInfo
ImplInitLineColor();
SetFillColor( aOldLineColor );
ImplInitFillColor();
+ bool bDone(false);
+
+ if(bTryAA)
+ {
+ // #i101491# try AAed version
+ // Use old on-the-fly geometry preparation, combine with AA
+ bool bSuccess(true);
- for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
- mpGraphics->DrawPolygon( pPoly->GetSize(), (const SalPoint*) pPoly->GetConstPointAry(), this );
+ for(const Polygon* pPoly = aLineCvt.ImplGetFirst(); bSuccess && pPoly; pPoly = aLineCvt.ImplGetNext())
+ {
+ bSuccess = mpGraphics->DrawPolyPolygon(basegfx::B2DPolyPolygon(pPoly->getB2DPolygon()), 0.0, this);
+ }
+
+ if(bSuccess)
+ {
+ bDone = true;
+ }
+ }
+
+ if(!bDone)
+ {
+ for( const Polygon* pPoly = aLineCvt.ImplGetFirst(); pPoly; pPoly = aLineCvt.ImplGetNext() )
+ {
+ mpGraphics->DrawPolygon( pPoly->GetSize(), (const SalPoint*) pPoly->GetConstPointAry(), this );
+ }
+ }
SetLineColor( aOldLineColor );
SetFillColor( aOldFillColor );
@@ -2598,13 +2676,40 @@ void OutputDevice::DrawPolygon( const Polygon& rPoly )
ImplInitFillColor();
// use b2dpolygon drawing if possible
- if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+ if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+ && ROP_OVERPAINT == GetRasterOp()
+ && (IsLineColor() || IsFillColor()))
{
- ::basegfx::B2DPolyPolygon aB2DPolyPolygon( rPoly.getB2DPolygon() );
const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
- aB2DPolyPolygon.transform( aTransform );
- if( mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, 0.0, this ) )
+ basegfx::B2DPolygon aB2DPolygon(rPoly.getB2DPolygon());
+ bool bSuccess(true);
+
+ // transform the polygon and ensure closed
+ aB2DPolygon.transform(aTransform);
+ aB2DPolygon.setClosed(true);
+
+ if(IsFillColor())
+ {
+ bSuccess = mpGraphics->DrawPolyPolygon(basegfx::B2DPolyPolygon(aB2DPolygon), 0.0, this);
+ }
+
+ if(bSuccess && IsLineColor())
+ {
+ const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
+
+ if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
+ {
+ aB2DPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon);
+ }
+
+ bSuccess = mpGraphics->DrawPolyLine(aB2DPolygon, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this);
+ }
+
+ if(bSuccess)
+ {
return;
+ }
}
Polygon aPoly = ImplLogicToDevicePixel( rPoly );
@@ -2661,13 +2766,43 @@ void OutputDevice::DrawPolyPolygon( const PolyPolygon& rPolyPoly )
ImplInitFillColor();
// use b2dpolygon drawing if possible
- if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+ if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+ && ROP_OVERPAINT == GetRasterOp()
+ && (IsLineColor() || IsFillColor()))
{
- ::basegfx::B2DPolyPolygon aB2DPolyPolygon = rPolyPoly.getB2DPolyPolygon();
const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
- aB2DPolyPolygon.transform( aTransform );
- if( mpGraphics->DrawPolyPolygon( aB2DPolyPolygon, 0.0, this ) )
+ basegfx::B2DPolyPolygon aB2DPolyPolygon(rPolyPoly.getB2DPolyPolygon());
+ bool bSuccess(true);
+
+ // transform the polygon and ensure closed
+ aB2DPolyPolygon.transform(aTransform);
+ aB2DPolyPolygon.setClosed(true);
+
+ if(IsFillColor())
+ {
+ bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this);
+ }
+
+ if(bSuccess && IsLineColor())
+ {
+ const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
+
+ if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
+ {
+ aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon);
+ }
+
+ for(sal_uInt32 a(0); bSuccess && a < aB2DPolyPolygon.count(); a++)
+ {
+ bSuccess = mpGraphics->DrawPolyLine(aB2DPolyPolygon.getB2DPolygon(a), aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this);
+ }
+ }
+
+ if(bSuccess)
+ {
return;
+ }
}
if ( nPoly == 1 )
@@ -2729,6 +2864,12 @@ void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly
mpMetaFile->AddAction( new MetaPolyPolygonAction( PolyPolygon( rB2DPolyPoly ) ) );
#endif
+ // call helper
+ ImpDrawPolyPolygonWithB2DPolyPolygon(rB2DPolyPoly);
+}
+
+void OutputDevice::ImpDrawPolyPolygonWithB2DPolyPolygon(const basegfx::B2DPolyPolygon& rB2DPolyPoly)
+{
// AW: Do NOT paint empty PolyPolygons
if(!rB2DPolyPoly.count())
return;
@@ -2748,13 +2889,43 @@ void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly
if( mbInitFillColor )
ImplInitFillColor();
- if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+ if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+ && ROP_OVERPAINT == GetRasterOp()
+ && (IsLineColor() || IsFillColor()))
{
- const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
- ::basegfx::B2DPolyPolygon aB2DPP = rB2DPolyPoly;
- aB2DPP.transform( aTransform );
- if( mpGraphics->DrawPolyPolygon( aB2DPP, 0.0, this ) )
+ const basegfx::B2DHomMatrix aTransform(ImplGetDeviceTransformation());
+ basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
+ bool bSuccess(true);
+
+ // transform the polygon and ensure closed
+ aB2DPolyPolygon.transform(aTransform);
+ aB2DPolyPolygon.setClosed(true);
+
+ if(IsFillColor())
+ {
+ bSuccess = mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, 0.0, this);
+ }
+
+ if(bSuccess && IsLineColor())
+ {
+ const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 );
+
+ if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
+ {
+ aB2DPolyPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyPolygon);
+ }
+
+ for(sal_uInt32 a(0);bSuccess && a < aB2DPolyPolygon.count(); a++)
+ {
+ bSuccess = mpGraphics->DrawPolyLine(aB2DPolyPolygon.getB2DPolygon(a), aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, this);
+ }
+ }
+
+ if(bSuccess)
+ {
return;
+ }
}
// fallback to old polygon drawing if needed
@@ -2765,6 +2936,38 @@ void OutputDevice::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rB2DPolyPoly
// -----------------------------------------------------------------------
+bool OutputDevice::ImpTryDrawPolyLineDirect(
+ const basegfx::B2DPolygon& rB2DPolygon,
+ double fLineWidth,
+ basegfx::B2DLineJoin eLineJoin)
+{
+ const basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
+ basegfx::B2DVector aB2DLineWidth(1.0, 1.0);
+
+ // transform the line width if used
+ if( fLineWidth != 0.0 )
+ {
+ aB2DLineWidth = aTransform * ::basegfx::B2DVector( fLineWidth, fLineWidth );
+ }
+
+ // transform the polygon
+ basegfx::B2DPolygon aB2DPolygon(rB2DPolygon);
+ aB2DPolygon.transform(aTransform);
+
+ if((mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE)
+ && aB2DPolygon.count() < 1000)
+ {
+ // #i98289#, #i101491#
+ // better to remove doubles on device coordinates. Also assume from a given amount
+ // of points that the single edges are not long enough to smooth
+ aB2DPolygon.removeDoublePoints();
+ aB2DPolygon = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolygon);
+ }
+
+ // draw the polyline
+ return mpGraphics->DrawPolyLine(aB2DPolygon, aB2DLineWidth, eLineJoin, this);
+}
+
void OutputDevice::DrawPolyLine(
const basegfx::B2DPolygon& rB2DPolygon,
double fLineWidth,
@@ -2808,37 +3011,62 @@ void OutputDevice::DrawPolyLine(
if( mbInitLineColor )
ImplInitLineColor();
- // #i98289# use b2dpolygon drawing if possible
- if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+ const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+ && ROP_OVERPAINT == GetRasterOp()
+ && IsLineColor());
+
+ // use b2dpolygon drawing if possible
+ if(bTryAA && ImpTryDrawPolyLineDirect(rB2DPolygon, fLineWidth, eLineJoin))
{
- const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
- ::basegfx::B2DVector aB2DLineWidth(1.0, 1.0);
+ return;
+ }
- // transform the line width if used
- if( fLineWidth != 0.0 )
- aB2DLineWidth = aTransform * ::basegfx::B2DVector( fLineWidth, fLineWidth );
+ // #i101491#
+ // no output yet; fallback to geometry decomposition and use filled polygon paint
+ // when line is fat and not too complex. ImpDrawPolyPolygonWithB2DPolyPolygon
+ // will do internal needed AA checks etc.
+ if(fLineWidth >= 2.5
+ && rB2DPolygon.count()
+ && rB2DPolygon.count() <= 1000)
+ {
+ const double fHalfLineWidth((fLineWidth * 0.5) + 0.5);
+ const basegfx::B2DPolyPolygon aAreaPolyPolygon(basegfx::tools::createAreaGeometry(
+ rB2DPolygon, fHalfLineWidth, eLineJoin));
- // transform the polygon
- ::basegfx::B2DPolygon aB2DPL = rB2DPolygon;
- aB2DPL.transform( aTransform );
+ const Color aOldLineColor(maLineColor);
+ const Color aOldFillColor(maFillColor);
+
+ SetLineColor();
+ ImplInitLineColor();
+ SetFillColor(aOldLineColor);
+ ImplInitFillColor();
+
+ ImpDrawPolyPolygonWithB2DPolyPolygon(aAreaPolyPolygon);
- if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && (mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE))
+ SetLineColor(aOldLineColor);
+ ImplInitLineColor();
+ SetFillColor(aOldFillColor);
+ ImplInitFillColor();
+
+ if(bTryAA)
{
- // #i98289#
- aB2DPL = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPL);
+ // when AA it is necessary to also paint the filled polygon's outline
+ // to avoid optical gaps
+ for(sal_uInt32 a(0); a < aAreaPolyPolygon.count(); a++)
+ {
+ ImpTryDrawPolyLineDirect(aAreaPolyPolygon.getB2DPolygon(a), 0.0, basegfx::B2DLINEJOIN_NONE);
+ }
}
-
- // draw the polyline
- if( mpGraphics->DrawPolyLine( aB2DPL, aB2DLineWidth, eLineJoin, this ) )
- return;
}
- // fallback to old polygon drawing if needed
+ // fallback to old polygon drawing if needed. This will really
+ // use ImplLineConverter, but still try to AA lines
const Polygon aToolsPolygon( rB2DPolygon );
LineInfo aLineInfo;
if( fLineWidth != 0.0 )
aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) );
- DrawPolyLine( aToolsPolygon, aLineInfo );
+ ImpDrawPolyLineWithLineInfo( aToolsPolygon, aLineInfo );
}
// -----------------------------------------------------------------------
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
index 537964582ceb..345dc162e67e 100644
--- a/vcl/source/gdi/outdev3.cxx
+++ b/vcl/source/gdi/outdev3.cxx
@@ -7,7 +7,6 @@
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: outdev3.cxx,v $
- * $Revision: 1.240.14.5 $
*
* This file is part of OpenOffice.org.
*
@@ -67,6 +66,9 @@
#ifndef _OSL_FILE_H
#include <osl/file.h>
#endif
+#ifdef ENABLE_GRAPHITE
+#include <vcl/graphite_features.hxx>
+#endif
#include <vcl/unohelp.hxx>
#include <pdfwriter_impl.hxx>
@@ -2750,6 +2752,14 @@ size_t ImplFontCache::IFSD_Hash::operator()( const ImplFontSelectData& rFSD ) co
// TODO: does it pay off to improve this hash function?
static FontNameHash aFontNameHash;
size_t nHash = aFontNameHash( rFSD.maSearchName );
+#ifdef ENABLE_GRAPHITE
+ // check for features and generate a unique hash if necessary
+ if (rFSD.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
+ != STRING_NOTFOUND)
+ {
+ nHash = aFontNameHash( rFSD.maTargetName );
+ }
+#endif
nHash += 11 * rFSD.mnHeight;
nHash += 19 * rFSD.meWeight;
nHash += 29 * rFSD.meItalic;
@@ -2801,6 +2811,15 @@ bool ImplFontCache::IFSD_Equal::operator()(const ImplFontSelectData& rA, const I
return false;
}
+#ifdef ENABLE_GRAPHITE
+ // check for features
+ if ((rA.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
+ != STRING_NOTFOUND ||
+ rB.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
+ != STRING_NOTFOUND) && rA.maTargetName != rB.maTargetName)
+ return false;
+#endif
+
return true;
}
@@ -2838,7 +2857,12 @@ ImplFontEntry* ImplFontCache::GetFontEntry( ImplDevFontList* pFontList,
// if it is already known get its normalized search name
FontNameList::const_iterator it_name = maFontNameList.find( aSearchName );
if( it_name != maFontNameList.end() )
- if( !(*it_name).second.EqualsAscii( "hg", 0, 2) )
+ if( !(*it_name).second.EqualsAscii( "hg", 0, 2)
+#ifdef ENABLE_GRAPHITE
+ && (aSearchName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
+ == STRING_NOTFOUND)
+#endif
+ )
aSearchName = (*it_name).second;
}
@@ -2943,6 +2967,22 @@ ImplDevFontListData* ImplDevFontList::ImplFindByFont( ImplFontSelectData& rFSD,
{
rFSD.maTargetName = GetNextFontToken( rFSD.maName, nTokenPos );
aSearchName = rFSD.maTargetName;
+
+#ifdef ENABLE_GRAPHITE
+ // Until features are properly supported, they are appended to the
+ // font name, so we need to strip them off so the font is found.
+ xub_StrLen nFeat = aSearchName.Search(grutils::GrFeatureParser::FEAT_PREFIX);
+ String aOrigName = rFSD.maTargetName;
+ String aBaseFontName(aSearchName, 0, (nFeat != STRING_NOTFOUND)?nFeat:aSearchName.Len());
+ if (nFeat != STRING_NOTFOUND && STRING_NOTFOUND !=
+ aSearchName.Search(grutils::GrFeatureParser::FEAT_ID_VALUE_SEPARATOR, nFeat))
+ {
+ aSearchName = aBaseFontName;
+ rFSD.maTargetName = aBaseFontName;
+ }
+
+#endif
+
ImplGetEnglishSearchFontName( aSearchName );
ImplFontSubstitute( aSearchName, nSubstFlags, pDevSpecific );
// #114999# special emboldening for Ricoh fonts
@@ -2973,6 +3013,10 @@ ImplDevFontListData* ImplDevFontList::ImplFindByFont( ImplFontSelectData& rFSD,
}
}
+#ifdef ENABLE_GRAPHITE
+ // restore the features to make the font selection data unique
+ rFSD.maTargetName = aOrigName;
+#endif
// check if the current font name token or its substitute is valid
ImplDevFontListData* pFoundData = ImplFindBySearchName( aSearchName );
if( pFoundData )
@@ -2981,16 +3025,21 @@ ImplDevFontListData* ImplDevFontList::ImplFindByFont( ImplFontSelectData& rFSD,
// some systems provide special customization
// e.g. they suggest "serif" as UI-font, but this name cannot be used directly
// because the system wants to map it to another font first, e.g. "Helvetica"
+#ifdef ENABLE_GRAPHITE
+ // use the target name to search in the prematch hook
+ rFSD.maTargetName = aBaseFontName;
+#endif
if( mpPreMatchHook )
- {
if( mpPreMatchHook->FindFontSubstitute( rFSD ) )
- {
ImplGetEnglishSearchFontName( aSearchName );
- pFoundData = ImplFindBySearchName( aSearchName );
- if( pFoundData )
- return pFoundData;
- }
- }
+#ifdef ENABLE_GRAPHITE
+ // the prematch hook uses the target name to search, but we now need
+ // to restore the features to make the font selection data unique
+ rFSD.maTargetName = aOrigName;
+#endif
+ pFoundData = ImplFindBySearchName( aSearchName );
+ if( pFoundData )
+ return pFoundData;
// break after last font name token was checked unsuccessfully
if( nTokenPos == STRING_NOTFOUND)
@@ -5441,6 +5490,7 @@ void OutputDevice::SetFont( const Font& rNewFont )
DBG_CHKOBJ( &rNewFont, Font, NULL );
Font aFont( rNewFont );
+ aFont.SetLanguage(rNewFont.GetLanguage());
if ( mnDrawMode & (DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT | DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT | DRAWMODE_SETTINGSTEXT |
DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL | DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
DRAWMODE_GHOSTEDFILL | DRAWMODE_SETTINGSFILL ) )
@@ -6484,7 +6534,7 @@ SalLayout* OutputDevice::ImplLayout( const String& rOrigStr,
nRTLOffset = nPixelWidth;
else
nRTLOffset = pSalLayout->GetTextWidth() / pSalLayout->GetUnitsPerPixel();
- pSalLayout->DrawOffset().X() = -nRTLOffset;
+ pSalLayout->DrawOffset().X() = 1 - nRTLOffset;
}
return pSalLayout;
@@ -6919,13 +6969,13 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
nStyle &= ~TEXT_DRAW_CLIP;
}
- // Vertikales Alignment
+ // horizontal text alignment
if ( nStyle & TEXT_DRAW_RIGHT )
aPos.X() += nWidth-nTextWidth;
else if ( nStyle & TEXT_DRAW_CENTER )
aPos.X() += (nWidth-nTextWidth)/2;
- // Font Alignment
+ // vertical font alignment
if ( eAlign == ALIGN_BOTTOM )
aPos.Y() += nTextHeight;
else if ( eAlign == ALIGN_BASELINE )
@@ -7919,8 +7969,8 @@ BOOL OutputDevice::GetGlyphBoundRects( const Point& rOrigin, const String& rStr,
// -----------------------------------------------------------------------
BOOL OutputDevice::GetTextBoundRect( Rectangle& rRect,
- const String& rStr, xub_StrLen nBase, xub_StrLen nIndex,
- xub_StrLen nLen ) const
+ const String& rStr, xub_StrLen nBase, xub_StrLen nIndex, xub_StrLen nLen,
+ ULONG nLayoutWidth, const sal_Int32* pDXAry ) const
{
DBG_TRACE( "OutputDevice::GetTextBoundRect()" );
DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
@@ -7929,13 +7979,14 @@ BOOL OutputDevice::GetTextBoundRect( Rectangle& rRect,
rRect.SetEmpty();
SalLayout* pSalLayout = NULL;
+ const Point aPoint;
// calculate offset when nBase!=nIndex
long nXOffset = 0;
if( nBase != nIndex )
{
xub_StrLen nStart = Min( nBase, nIndex );
xub_StrLen nOfsLen = Max( nBase, nIndex ) - nStart;
- pSalLayout = ImplLayout( rStr, nStart, nOfsLen );
+ pSalLayout = ImplLayout( rStr, nStart, nOfsLen, aPoint, nLayoutWidth, pDXAry );
if( pSalLayout )
{
nXOffset = pSalLayout->GetTextWidth();
@@ -7947,7 +7998,7 @@ BOOL OutputDevice::GetTextBoundRect( Rectangle& rRect,
}
}
- pSalLayout = ImplLayout( rStr, nIndex, nLen );
+ pSalLayout = ImplLayout( rStr, nIndex, nLen, aPoint, nLayoutWidth, pDXAry );
Rectangle aPixelRect;
if( pSalLayout )
{
@@ -7997,7 +8048,7 @@ BOOL OutputDevice::GetTextBoundRect( Rectangle& rRect,
aVDev.SetTextAlign( ALIGN_TOP );
// layout the text on the virtual device
- pSalLayout = aVDev.ImplLayout( rStr, nIndex, nLen );
+ pSalLayout = aVDev.ImplLayout( rStr, nIndex, nLen, aPoint, nLayoutWidth, pDXAry );
if( !pSalLayout )
return false;
@@ -8097,7 +8148,7 @@ BOOL OutputDevice::GetTextBoundRect( Rectangle& rRect,
BOOL OutputDevice::GetTextOutlines( ::basegfx::B2DPolyPolygonVector& rVector,
const String& rStr, xub_StrLen nBase, xub_StrLen nIndex, xub_StrLen nLen,
- BOOL bOptimize, const ULONG nTWidth, const sal_Int32* pDXArray ) const
+ BOOL bOptimize, ULONG nTWidth, const sal_Int32* pDXArray ) const
{
// the fonts need to be initialized
if( mbNewFont )
@@ -8326,7 +8377,7 @@ BOOL OutputDevice::GetTextOutlines( ::basegfx::B2DPolyPolygonVector& rVector,
BOOL OutputDevice::GetTextOutlines( PolyPolyVector& rResultVector,
const String& rStr, xub_StrLen nBase, xub_StrLen nIndex,
- xub_StrLen nLen, BOOL bOptimize, const ULONG nTWidth, const sal_Int32* pDXArray ) const
+ xub_StrLen nLen, BOOL bOptimize, ULONG nTWidth, const sal_Int32* pDXArray ) const
{
rResultVector.clear();
@@ -8349,7 +8400,7 @@ BOOL OutputDevice::GetTextOutlines( PolyPolyVector& rResultVector,
BOOL OutputDevice::GetTextOutline( PolyPolygon& rPolyPoly,
const String& rStr, xub_StrLen nBase, xub_StrLen nIndex, xub_StrLen nLen,
- BOOL bOptimize, const ULONG nTWidth, const sal_Int32* pDXArray ) const
+ BOOL bOptimize, ULONG nTWidth, const sal_Int32* pDXArray ) const
{
rPolyPoly.Clear();
diff --git a/vcl/source/gdi/outdev6.cxx b/vcl/source/gdi/outdev6.cxx
index cee4f475a577..a11e276982f7 100644
--- a/vcl/source/gdi/outdev6.cxx
+++ b/vcl/source/gdi/outdev6.cxx
@@ -185,14 +185,20 @@ void OutputDevice::DrawTransparent( const basegfx::B2DPolyPolygon& rB2DPolyPoly,
if( mbInitFillColor )
ImplInitFillColor();
- if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) && mpGraphics->supportsOperation(OutDevSupport_B2DDraw))
+ if((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW)
+ && mpGraphics->supportsOperation(OutDevSupport_B2DDraw)
+ && ROP_OVERPAINT == GetRasterOp()
+ && IsFillColor())
{
// b2dpolygon support not implemented yet on non-UNX platforms
const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
- ::basegfx::B2DPolyPolygon aB2DPP = rB2DPolyPoly;
- aB2DPP.transform( aTransform );
+ basegfx::B2DPolyPolygon aB2DPolyPolygon(rB2DPolyPoly);
- if( mpGraphics->DrawPolyPolygon( aB2DPP, fTransparency, this ) )
+ // transform the polygon and ensure closed
+ aB2DPolyPolygon.transform(aTransform);
+ aB2DPolyPolygon.setClosed(true);
+
+ if(mpGraphics->DrawPolyPolygon(aB2DPolyPolygon, fTransparency, this))
{
#if 0
// MetaB2DPolyPolygonAction is not implemented yet:
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 3f648fda8589..25f02a1b2718 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -792,7 +792,8 @@ static void appendNonStrokingColor( const Color& rColor, OStringBuffer& rBuffer
}
// matrix helper class
-namespace vcl
+// TODO: use basegfx matrix class instead or derive from it
+namespace vcl // TODO: use anonymous namespace to keep this class local
{
/* for sparse matrices of the form (2D linear transformations)
* f[0] f[1] 0
@@ -812,6 +813,7 @@ public:
void scale( double sx, double sy );
void rotate( double angle );
void translate( double tx, double ty );
+ bool invert();
void append( PDFWriterImpl::PDFPage& rPage, OStringBuffer& rBuffer, Point* pBack = NULL );
@@ -888,6 +890,36 @@ void Matrix3::translate( double tx, double ty )
f[5] += ty;
}
+bool Matrix3::invert()
+{
+ // short circuit trivial cases
+ if( f[1]==f[2] && f[1]==0.0 && f[0]==f[3] && f[0]==1.0 )
+ {
+ f[4] = -f[4];
+ f[5] = -f[5];
+ return true;
+ }
+
+ // check determinant
+ const double fDet = f[0]*f[3]-f[1]*f[2];
+ if( fDet == 0.0 )
+ return false;
+
+ // invert the matrix
+ double fn[6];
+ fn[0] = +f[3] / fDet;
+ fn[1] = -f[1] / fDet;
+ fn[2] = -f[2] / fDet;
+ fn[3] = +f[0] / fDet;
+
+ // apply inversion to translation
+ fn[4] = -(f[4]*fn[0] + f[5]*fn[2]);
+ fn[5] = -(f[4]*fn[1] + f[5]*fn[3]);
+
+ set( fn );
+ return true;
+}
+
void Matrix3::append( PDFWriterImpl::PDFPage& rPage, OStringBuffer& rBuffer, Point* pBack )
{
appendDouble( f[0], rBuffer );
@@ -6635,6 +6667,7 @@ void PDFWriterImpl::drawHorizontalGlyphs(
// subsequent use of that operator would move
// the texline matrix relative to what was set before
// making use of that would drive us into rounding issues
+ Matrix3 aMat;
if( nRun == 0 && fAngle == 0.0 && fXScale == 1.0 && fSkew == 0.0 )
{
m_aPages.back().appendPoint( aCurPos, rLine, false );
@@ -6642,7 +6675,6 @@ void PDFWriterImpl::drawHorizontalGlyphs(
}
else
{
- Matrix3 aMat;
if( fSkew != 0.0 )
aMat.skew( 0.0, fSkew );
aMat.scale( fXScale, 1.0 );
@@ -6665,15 +6697,17 @@ void PDFWriterImpl::drawHorizontalGlyphs(
appendHex( rGlyphs[nBeginRun].m_nMappedGlyphId, aKernedLine );
appendHex( rGlyphs[nBeginRun].m_nMappedGlyphId, aUnkernedLine );
+ aMat.invert();
bool bNeedKern = false;
for( sal_uInt32 nPos = nBeginRun+1; nPos < aRunEnds[nRun]; nPos++ )
{
appendHex( rGlyphs[nPos].m_nMappedGlyphId, aUnkernedLine );
- // check for adjustment
- double fTheoreticalGlyphWidth = rGlyphs[nPos].m_aPos.X() - rGlyphs[nPos-1].m_aPos.X();
- fTheoreticalGlyphWidth = fabs( fTheoreticalGlyphWidth ); // #i100522# workaround until #i87686# gets fixed
- fTheoreticalGlyphWidth = 1000.0 * fTheoreticalGlyphWidth / fXScale / double(nPixelFontHeight);
- sal_Int32 nAdjustment = rGlyphs[nPos-1].m_nNativeWidth - sal_Int32(fTheoreticalGlyphWidth+0.5);
+ // check if glyph advance matches with the width of the previous glyph, else adjust
+ const Point aThisPos = aMat.transform( rGlyphs[nPos].m_aPos );
+ const Point aPrevPos = aMat.transform( rGlyphs[nPos-1].m_aPos );
+ double fAdvance = aThisPos.X() - aPrevPos.X();
+ fAdvance *= 1000.0 / (fXScale * nPixelFontHeight);
+ const sal_Int32 nAdjustment = rGlyphs[nPos-1].m_nNativeWidth - sal_Int32(fAdvance+0.5);
if( nAdjustment != 0 )
{
bNeedKern = true;
diff --git a/vcl/source/gdi/pngread.cxx b/vcl/source/gdi/pngread.cxx
index 56c9025018b9..834116a9ffe9 100644
--- a/vcl/source/gdi/pngread.cxx
+++ b/vcl/source/gdi/pngread.cxx
@@ -156,6 +156,7 @@ private:
BOOL mbIDAT; // TRUE if finished with enough IDAT chunks
BOOL mbGamma; // TRUE if Gamma Correction available
BOOL mbpHYs; // TRUE if pysical size of pixel available
+ sal_Bool mbIgnoreGammaChunk;
bool ReadNextChunk();
void ReadRemainingChunks();
@@ -186,6 +187,7 @@ public:
BitmapEx GetBitmapEx( const Size& rPreviewSizeHint );
const std::vector< PNGReader::ChunkData >& GetAllChunks();
+ void SetIgnoreGammaChunk( sal_Bool bIgnore ){ mbIgnoreGammaChunk = bIgnore; };
};
// ------------------------------------------------------------------------------
@@ -205,8 +207,9 @@ PNGReaderImpl::PNGReaderImpl( SvStream& rPNGStream )
mbzCodecInUse ( sal_False ),
mbStatus( TRUE),
mbIDAT( FALSE ),
- mbGamma ( sal_False ),
- mbpHYs ( sal_False )
+ mbGamma ( sal_False ),
+ mbpHYs ( sal_False ),
+ mbIgnoreGammaChunk ( sal_False )
{
// prepare the PNG data stream
mnOrigStreamMode = mrPNGStream.GetNumberFormatInt();
@@ -382,9 +385,9 @@ BitmapEx PNGReaderImpl::GetBitmapEx( const Size& rPreviewSizeHint )
break;
case PNGCHUNK_gAMA : // the gamma chunk must precede
- {
- if ( mbIDAT == FALSE ) // the 'IDAT' and also the
- ImplGetGamma(); // 'PLTE'(if available )
+ { // the 'IDAT' and also the 'PLTE'(if available )
+ if ( !mbIgnoreGammaChunk && ( mbIDAT == FALSE ) )
+ ImplGetGamma();
}
break;
@@ -1568,4 +1571,12 @@ const std::vector< vcl::PNGReader::ChunkData >& PNGReader::GetChunks() const
return mpImpl->GetAllChunks();
}
+// ------------------------------------------------------------------------
+
+void PNGReader::SetIgnoreGammaChunk( sal_Bool b )
+{
+ mpImpl->SetIgnoreGammaChunk( b );
+}
+
+
} // namespace vcl
diff --git a/vcl/source/gdi/print.cxx b/vcl/source/gdi/print.cxx
index 0a5fbb189885..937d966b3978 100644
--- a/vcl/source/gdi/print.cxx
+++ b/vcl/source/gdi/print.cxx
@@ -70,44 +70,22 @@ int nImplSysDialog = 0;
// =======================================================================
-#define PAPER_SLOPPY 50 // Bigger sloppy value as PaperInfo uses only mm accuracy!
-#define PAPER_COUNT 9
-
-// Use more accurate metric values for Letter/Legal/Tabloid paper formats
-static long ImplPaperFormats[PAPER_COUNT*2] =
-{
- 29700, 42000, // A3
- 21000, 29700, // A4
- 14800, 21000, // A5
- 25000, 35300, // B4
- 17600, 25000, // B5
- 21590, 27940, // Letter
- 21590, 35570, // Legal
- 27960, 43130, // Tabloid
- 0, 0 // USER
-};
-
-// =======================================================================
-
-Paper ImplGetPaperFormat( long nWidth100thMM, long nHeight100thMM )
+namespace
{
- USHORT i;
-
- for( i = 0; i < PAPER_COUNT; i++ )
+ static Paper ImplGetPaperFormat( long nWidth100thMM, long nHeight100thMM )
{
- if ( (ImplPaperFormats[i*2] == nWidth100thMM) &&
- (ImplPaperFormats[i*2+1] == nHeight100thMM) )
- return (Paper)i;
+ PaperInfo aInfo(nWidth100thMM, nHeight100thMM);
+ aInfo.doSloppyFit();
+ return aInfo.getPaper();
}
- for( i = 0; i < PAPER_COUNT; i++ )
+// -----------------------------------------------------------------------
+
+ static const PaperInfo& ImplGetEmptyPaper()
{
- if ( (Abs( ImplPaperFormats[i*2]-nWidth100thMM ) < PAPER_SLOPPY) &&
- (Abs( ImplPaperFormats[i*2+1]-nHeight100thMM ) < PAPER_SLOPPY) )
- return (Paper)i;
+ static PaperInfo aInfo(PAPER_USER);
+ return aInfo;
}
-
- return PAPER_USER;
}
// =======================================================================
@@ -121,8 +99,9 @@ void ImplUpdateJobSetupPaper( JobSetup& rJobSetup )
if ( pConstData->mePaperFormat != PAPER_USER )
{
ImplJobSetup* pData = rJobSetup.ImplGetData();
- pData->mnPaperWidth = ImplPaperFormats[((USHORT)pConstData->mePaperFormat)*2];
- pData->mnPaperHeight = ImplPaperFormats[((USHORT)pConstData->mePaperFormat)*2+1];
+ PaperInfo aInfo(pConstData->mePaperFormat);
+ pData->mnPaperWidth = aInfo.getWidth();
+ pData->mnPaperHeight = aInfo.getHeight();
}
}
else if ( pConstData->mePaperFormat == PAPER_USER )
@@ -997,17 +976,6 @@ USHORT Printer::GetPaperBin() const
// -----------------------------------------------------------------------
-static BOOL ImplPaperSizeEqual( unsigned long nPaperWidth1, unsigned long nPaperHeight1,
- unsigned long nPaperWidth2, unsigned long nPaperHeight2 )
-{
- const long PAPER_ACCURACY = 1; // 1.0 mm accuracy
-
- return ( (Abs( long(nPaperWidth1)-long(nPaperWidth2) ) <= PAPER_ACCURACY ) &&
- (Abs( long(nPaperHeight1)-long(nPaperHeight2) ) <= PAPER_ACCURACY ) );
-}
-
-// -----------------------------------------------------------------------
-
// Map user paper format to a available printer paper formats
void Printer::ImplFindPaperFormatForUserSize( JobSetup& aJobSetup )
{
@@ -1016,21 +984,17 @@ void Printer::ImplFindPaperFormatForUserSize( JobSetup& aJobSetup )
int nLandscapeAngle = GetLandscapeAngle();
int nPaperCount = GetPaperInfoCount();
- unsigned long nPaperWidth = pSetupData->mnPaperWidth/100;
- unsigned long nPaperHeight = pSetupData->mnPaperHeight/100;
+ PaperInfo aInfo(pSetupData->mnPaperWidth, pSetupData->mnPaperHeight);
// Alle Papierformate vergleichen und ein passendes raussuchen
for ( int i = 0; i < nPaperCount; i++ )
{
- const vcl::PaperInfo& rPaperInfo = GetPaperInfo( i );
+ const PaperInfo& rPaperInfo = GetPaperInfo( i );
- if ( ImplPaperSizeEqual( rPaperInfo.m_nPaperWidth,
- rPaperInfo.m_nPaperHeight,
- nPaperWidth,
- nPaperHeight ) )
+ if ( aInfo.sloppyEqual(rPaperInfo) )
{
- pSetupData->mePaperFormat = ImplGetPaperFormat( rPaperInfo.m_nPaperWidth*100,
- rPaperInfo.m_nPaperHeight*100 );
+ pSetupData->mePaperFormat = ImplGetPaperFormat( rPaperInfo.getWidth(),
+ rPaperInfo.getHeight() );
break;
}
}
@@ -1042,17 +1006,17 @@ void Printer::ImplFindPaperFormatForUserSize( JobSetup& aJobSetup )
nLandscapeAngle != 0 &&
HasSupport( SUPPORT_SET_ORIENTATION ))
{
+
+ PaperInfo aRotatedInfo(pSetupData->mnPaperHeight, pSetupData->mnPaperWidth);
+
for ( int i = 0; i < nPaperCount; i++ )
{
- const vcl::PaperInfo& rPaperInfo = GetPaperInfo( i );
+ const PaperInfo& rPaperInfo = GetPaperInfo( i );
- if ( ImplPaperSizeEqual( rPaperInfo.m_nPaperWidth,
- rPaperInfo.m_nPaperHeight,
- nPaperHeight,
- nPaperWidth ))
+ if ( aRotatedInfo.sloppyEqual( rPaperInfo ) )
{
- pSetupData->mePaperFormat = ImplGetPaperFormat( rPaperInfo.m_nPaperWidth*100,
- rPaperInfo.m_nPaperHeight*100 );
+ pSetupData->mePaperFormat = ImplGetPaperFormat( rPaperInfo.getWidth(),
+ rPaperInfo.getHeight() );
break;
}
}
@@ -1073,8 +1037,9 @@ BOOL Printer::SetPaper( Paper ePaper )
pSetupData->mePaperFormat = ePaper;
if ( ePaper != PAPER_USER )
{
- pSetupData->mnPaperWidth = ImplPaperFormats[((USHORT)ePaper)*2];
- pSetupData->mnPaperHeight = ImplPaperFormats[((USHORT)ePaper)*2+1];
+ PaperInfo aInfo(ePaper);
+ pSetupData->mnPaperWidth = aInfo.getWidth();
+ pSetupData->mnPaperHeight = aInfo.getHeight();
}
if ( IsDisplayPrinter() )
@@ -1110,9 +1075,8 @@ BOOL Printer::SetPaperSizeUser( const Size& rSize )
if ( mbInPrintPage )
return FALSE;
- MapMode aMap100thMM( MAP_100TH_MM );
Size aPixSize = LogicToPixel( rSize );
- Size aPageSize = PixelToLogic( aPixSize, aMap100thMM );
+ Size aPageSize = PixelToLogic( aPixSize, MAP_100TH_MM );
if ( (maJobSetup.ImplGetConstData()->mePaperFormat != PAPER_USER) ||
(maJobSetup.ImplGetConstData()->mnPaperWidth != aPageSize.Width()) ||
(maJobSetup.ImplGetConstData()->mnPaperHeight != aPageSize.Height()) )
@@ -1150,15 +1114,6 @@ BOOL Printer::SetPaperSizeUser( const Size& rSize )
return TRUE;
}
-
-// -----------------------------------------------------------------------
-
-static const vcl::PaperInfo& ImplGetEmptyPaper()
-{
- static vcl::PaperInfo aInfo;
- return aInfo;
-}
-
// -----------------------------------------------------------------------
int Printer::GetPaperInfoCount() const
@@ -1172,7 +1127,7 @@ int Printer::GetPaperInfoCount() const
// -----------------------------------------------------------------------
-const vcl::PaperInfo& Printer::GetPaperInfo( int nPaper ) const
+const PaperInfo& Printer::GetPaperInfo( int nPaper ) const
{
if( ! mpInfoPrinter )
return ImplGetEmptyPaper();
@@ -1185,17 +1140,6 @@ const vcl::PaperInfo& Printer::GetPaperInfo( int nPaper ) const
// -----------------------------------------------------------------------
-BOOL Printer::SetPaperFromInfo( const vcl::PaperInfo& rInfo )
-{
- MapMode aMap( MAP_MM );
- Size aSize( rInfo.m_nPaperWidth, rInfo.m_nPaperHeight );
- aSize = LogicToPixel( aSize, aMap );
- aSize = PixelToLogic( aSize );
- return SetPaperSizeUser( aSize );
-}
-
-// -----------------------------------------------------------------------
-
DuplexMode Printer::GetDuplexMode() const
{
return mpInfoPrinter ? mpInfoPrinter->GetDuplexMode( maJobSetup.ImplGetConstData() ) : DUPLEX_UNKNOWN;
@@ -1210,38 +1154,6 @@ int Printer::GetLandscapeAngle() const
// -----------------------------------------------------------------------
-const vcl::PaperInfo& Printer::GetCurrentPaperInfo() const
-{
- if( ! mpInfoPrinter )
- return ImplGetEmptyPaper();
- if( ! mpInfoPrinter->m_bPapersInit )
- mpInfoPrinter->InitPaperFormats( maJobSetup.ImplGetConstData() );
- if( mpInfoPrinter->m_aPaperFormats.empty() )
- return ImplGetEmptyPaper();
-
- MapMode aMap( MAP_MM );
- Size aSize = PixelToLogic( GetPaperSizePixel(), aMap );
- int nMatch = -1;
- long nDelta = 0;
- for( unsigned int i = 0; i < mpInfoPrinter->m_aPaperFormats.size(); i++ )
- {
- long nW = mpInfoPrinter->m_aPaperFormats[i].m_nPaperWidth;
- long nH = mpInfoPrinter->m_aPaperFormats[i].m_nPaperHeight;
- if( nW >= (aSize.Width()-1) && nH >= (aSize.Height()-1) )
- {
- long nCurDelta = (nW - aSize.Width())*(nW - aSize.Width()) + (nH - aSize.Height() )*(nH - aSize.Height() );
- if( nMatch == -1 || nCurDelta < nDelta )
- {
- nMatch = i;
- nDelta = nCurDelta;
- }
- }
- }
- return nMatch != -1 ? mpInfoPrinter->m_aPaperFormats[nMatch] : ImplGetEmptyPaper();
-}
-
-// -----------------------------------------------------------------------
-
Paper Printer::GetPaper() const
{
return maJobSetup.ImplGetConstData()->mePaperFormat;
diff --git a/vcl/source/gdi/sallayout.cxx b/vcl/source/gdi/sallayout.cxx
index a96d4dc64b89..21ac05a498fc 100755
--- a/vcl/source/gdi/sallayout.cxx
+++ b/vcl/source/gdi/sallayout.cxx
@@ -63,6 +63,26 @@
#include <algorithm>
+#ifdef DEBUG
+//#define MULTI_SL_DEBUG
+#endif
+
+#ifdef MULTI_SL_DEBUG
+#include <string>
+FILE * mslLogFile = NULL;
+FILE * mslLog()
+{
+#ifdef MSC
+ std::string logFileName(getenv("TEMP"));
+ logFileName.append("\\msllayout.log");
+ if (mslLogFile == NULL) mslLogFile = fopen(logFileName.c_str(),"w");
+ else fflush(mslLogFile);
+ return mslLogFile;
+#else
+ return stdout;
+#endif
+}
+#endif
// =======================================================================
// TODO: ask the glyph directly, for now we need this method because of #i99367#
@@ -1157,11 +1177,17 @@ void GenericSalLayout::ApplyDXArray( ImplLayoutArgs& rArgs )
for( int nCharPos = i = -1; rArgs.GetNextPos( &nCharPos, &bRTL ); )
{
n = nCharPos - rArgs.mnMinCharPos;
- i = pLogCluster[ n ];
- long nDelta = rArgs.mpDXArray[ n ] ;
- if( n > 0 )
- nDelta -= rArgs.mpDXArray[ n-1 ];
- pNewGlyphWidths[ i ] += nDelta * mnUnitsPerPixel;
+ if( (n < 0) || (nCharCount <= n) ) continue;
+
+ if( pLogCluster[ n ] >= 0 )
+ i = pLogCluster[ n ];
+ if( i >= 0 )
+ {
+ long nDelta = rArgs.mpDXArray[ n ] ;
+ if( n > 0 )
+ nDelta -= rArgs.mpDXArray[ n-1 ];
+ pNewGlyphWidths[ i ] += nDelta * mnUnitsPerPixel;
+ }
}
// move cluster positions using the adjusted widths
@@ -1768,6 +1794,19 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
}
}
+ // Compute rtl flags, since in some scripts glyphs/char order can be
+ // reversed for a few character sequencies e.g. Myanmar
+ std::vector<bool> vRtl(rArgs.mnEndCharPos - rArgs.mnMinCharPos, false);
+ rArgs.ResetPos();
+ bool bRtl;
+ int nRunStart, nRunEnd;
+ while (rArgs.GetNextRun(&nRunStart, &nRunEnd, &bRtl))
+ {
+ if (bRtl) std::fill(vRtl.begin() + nRunStart - rArgs.mnMinCharPos,
+ vRtl.begin() + nRunEnd - rArgs.mnMinCharPos, true);
+ }
+ rArgs.ResetPos();
+
// prepare "merge sort"
int nStartOld[ MAX_FALLBACK ];
int nStartNew[ MAX_FALLBACK ];
@@ -1804,6 +1843,10 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
nStartNew[ nLevel ] = nStartOld[ nLevel ] = 0;
nValid[ nLevel ] = mpLayouts[n]->GetNextGlyphs( 1, &nDummy, aPos,
nStartNew[ nLevel ], &nGlyphAdv[ nLevel ], &nCharPos[ nLevel ] );
+#ifdef MULTI_SL_DEBUG
+ if (nValid[nLevel]) fprintf(mslLog(), "layout[%d]->GetNextGlyphs %d,%d x%d a%d c%d %x\n", n, nStartOld[nLevel], nStartNew[nLevel], aPos.X(), nGlyphAdv[nLevel], nCharPos[nLevel],
+ rArgs.mpStr[nCharPos[nLevel]]);
+#endif
if( (n > 0) && !nValid[ nLevel ] )
{
// an empty fallback layout can be released
@@ -1829,6 +1872,9 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
for( n = 0; n < nLevel; ++n )
maFallbackRuns[n].ResetPos();
int nActiveCharPos = nCharPos[0];
+ int nLastRunEndChar = (vRtl[nActiveCharPos - mnMinCharPos])?
+ rArgs.mnEndCharPos : rArgs.mnMinCharPos - 1;
+ int nRunVisibleEndChar = nCharPos[0];
while( nValid[0] && (nLevel > 0))
{
// find best fallback level
@@ -1864,6 +1910,9 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
nStartOld[0] = nStartNew[0];
nValid[0] = mpLayouts[0]->GetNextGlyphs( 1, &nDummy, aPos,
nStartNew[0], &nGlyphAdv[0], &nCharPos[0] );
+#ifdef MULTI_SL_DEBUG
+ if (nValid[0]) fprintf(mslLog(), "layout[0]->GetNextGlyphs %d,%d x%d a%d c%d %x\n", nStartOld[0], nStartNew[0], aPos.X(), nGlyphAdv[0], nCharPos[0], rArgs.mpStr[nCharPos[0]]);
+#endif
if( !nValid[0] )
break;
}
@@ -1881,7 +1930,9 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
int nOrigCharPos = nCharPos[n];
nValid[n] = mpLayouts[n]->GetNextGlyphs( 1, &nDummy, aPos,
nStartNew[n], &nGlyphAdv[n], &nCharPos[n] );
-
+#ifdef MULTI_SL_DEBUG
+ if (nValid[n]) fprintf(mslLog(), "layout[%d]->GetNextGlyphs %d,%d a%d c%d %x\n", n, nStartOld[n], nStartNew[n], nGlyphAdv[n], nCharPos[n], rArgs.mpStr[nCharPos[n]]);
+#endif
// break after last glyph of active layout
if( !nValid[n] )
{
@@ -1927,6 +1978,27 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
{ maFallbackRuns[0].NextRun(); break; }
bKeepNotDef = bNeedFallback;
}
+ // check for reordered glyphs
+ if (aMultiArgs.mpDXArray &&
+ nRunVisibleEndChar < mnEndCharPos &&
+ nRunVisibleEndChar >= mnMinCharPos &&
+ nCharPos[n] < mnEndCharPos &&
+ nCharPos[n] >= mnMinCharPos)
+ {
+ if (vRtl[nActiveCharPos - mnMinCharPos])
+ {
+ if (aMultiArgs.mpDXArray[nRunVisibleEndChar-mnMinCharPos]
+ >= aMultiArgs.mpDXArray[nCharPos[n] - mnMinCharPos])
+ {
+ nRunVisibleEndChar = nCharPos[n];
+ }
+ }
+ else if (aMultiArgs.mpDXArray[nRunVisibleEndChar-mnMinCharPos]
+ <= aMultiArgs.mpDXArray[nCharPos[n] - mnMinCharPos])
+ {
+ nRunVisibleEndChar = nCharPos[n];
+ }
+ }
}
// if a justification array is available
@@ -1936,16 +2008,40 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
// the run advance is the width from the first char
// in the run to the first char in the next run
nRunAdvance = 0;
- const bool bLTR = (nActiveCharPos < nCharPos[0]);
+#ifdef MULTI_SL_DEBUG
+ const bool bLTR = !(vRtl[nActiveCharPos - mnMinCharPos]);//(nActiveCharPos < nCharPos[0]);
+ int nOldRunAdv = 0;
int nDXIndex = nCharPos[0] - mnMinCharPos - bLTR;
if( nDXIndex >= 0 )
- nRunAdvance += aMultiArgs.mpDXArray[ nDXIndex ];
+ nOldRunAdv += aMultiArgs.mpDXArray[ nDXIndex ];
nDXIndex = nActiveCharPos - mnMinCharPos - bLTR;
if( nDXIndex >= 0 )
- nRunAdvance -= aMultiArgs.mpDXArray[ nDXIndex ];
+ nOldRunAdv -= aMultiArgs.mpDXArray[ nDXIndex ];
if( !bLTR )
- nRunAdvance = -nRunAdvance;
-
+ nOldRunAdv = -nOldRunAdv;
+#endif
+ if (vRtl[nActiveCharPos - mnMinCharPos])
+ {
+ if (nRunVisibleEndChar > mnMinCharPos && nRunVisibleEndChar <= mnEndCharPos)
+ nRunAdvance -= aMultiArgs.mpDXArray[nRunVisibleEndChar - 1 - mnMinCharPos];
+ if (nLastRunEndChar > mnMinCharPos && nLastRunEndChar <= mnEndCharPos)
+ nRunAdvance += aMultiArgs.mpDXArray[nLastRunEndChar - 1 - mnMinCharPos];
+#ifdef MULTI_SL_DEBUG
+ fprintf(mslLog(), "rtl visible %d-%d,%d-%d adv%d(%d)\n", nLastRunEndChar-1, nRunVisibleEndChar-1, nActiveCharPos - bLTR, nCharPos[0] - bLTR, nRunAdvance, nOldRunAdv);
+#endif
+ }
+ else
+ {
+ if (nRunVisibleEndChar >= mnMinCharPos)
+ nRunAdvance += aMultiArgs.mpDXArray[nRunVisibleEndChar - mnMinCharPos];
+ if (nLastRunEndChar >= mnMinCharPos)
+ nRunAdvance -= aMultiArgs.mpDXArray[nLastRunEndChar - mnMinCharPos];
+#ifdef MULTI_SL_DEBUG
+ fprintf(mslLog(), "visible %d-%d,%d-%d adv%d(%d)\n", nLastRunEndChar, nRunVisibleEndChar, nActiveCharPos - bLTR, nCharPos[0] - bLTR, nRunAdvance, nOldRunAdv);
+#endif
+ }
+ nLastRunEndChar = nRunVisibleEndChar;
+ nRunVisibleEndChar = nCharPos[0];
// the requested width is still in pixel units
// => convert it to base level font units
nRunAdvance *= mnUnitsPerPixel;
@@ -1963,9 +2059,27 @@ void MultiSalLayout::AdjustLayout( ImplLayoutArgs& rArgs )
// prepare for next fallback run
nActiveCharPos = nCharPos[0];
+ // it essential that the runs don't get ahead of themselves and in the
+ // if( bKeepNotDef && !bNeedFallback ) statement above, the next run may
+ // have already been reached on the base level
for( int i = nFBLevel; --i >= 0;)
- if( !maFallbackRuns[i].PosIsInRun( nActiveCharPos ) )
- maFallbackRuns[i].NextRun();
+ {
+ if (maFallbackRuns[i].GetRun(&nRunStart, &nRunEnd, &bRtl))
+ {
+ if (bRtl)
+ {
+ if (nRunStart > nActiveCharPos)
+ maFallbackRuns[i].NextRun();
+ }
+ else
+ {
+ if (nRunEnd <= nActiveCharPos)
+ maFallbackRuns[i].NextRun();
+ }
+ }
+ }
+// if( !maFallbackRuns[i].PosIsInRun( nActiveCharPos ) )
+// maFallbackRuns[i].NextRun();
}
mpLayouts[0]->Simplify( true );