diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2010-01-28 18:49:22 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2010-01-28 18:49:22 +0000 |
commit | 4c6cda4e38b13dc3d634f0922a734258ab153ab9 (patch) | |
tree | 7f42031fb6937ec1621c758c24fa0b8d231c92cb /vcl/source/gdi | |
parent | 2e77984f087afde2ba0ca0edc5987a6f52d1095e (diff) | |
parent | f4ce12bb2e6f64f5b4cfed9b1b13f8e87371b4a9 (diff) |
koheidatapilot03: merge with DEV300_m56
Diffstat (limited to 'vcl/source/gdi')
-rw-r--r-- | vcl/source/gdi/gdimtf.cxx | 430 | ||||
-rw-r--r-- | vcl/source/gdi/graph.cxx | 38 | ||||
-rw-r--r-- | vcl/source/gdi/impgraph.cxx | 38 | ||||
-rw-r--r-- | vcl/source/gdi/impimagetree.cxx | 7 | ||||
-rw-r--r-- | vcl/source/gdi/makefile.mk | 4 | ||||
-rw-r--r-- | vcl/source/gdi/outdev.cxx | 312 | ||||
-rw-r--r-- | vcl/source/gdi/outdev3.cxx | 91 | ||||
-rw-r--r-- | vcl/source/gdi/outdev6.cxx | 14 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl.cxx | 48 | ||||
-rw-r--r-- | vcl/source/gdi/pngread.cxx | 21 | ||||
-rw-r--r-- | vcl/source/gdi/print.cxx | 148 | ||||
-rwxr-xr-x | vcl/source/gdi/sallayout.cxx | 140 |
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 ); |