diff options
author | Chris Sherlock <chris.sherlock79@gmail.com> | 2014-04-14 21:54:43 +1000 |
---|---|---|
committer | Chris Sherlock <chris.sherlock79@gmail.com> | 2014-04-16 07:33:57 +1000 |
commit | d4bf419884994cdc0966e40468d44b94b68bb4e5 (patch) | |
tree | b9bb98471ac1d0ebbfd103f5bef019277fbf055f /vcl | |
parent | 3a7ad7ee5d7daa0c93a80fbb32a677597d81ac75 (diff) |
Move lines and rectangles to seperate source files
Change-Id: I03ef9d09fed831c6d595924f1c681718a89106b2
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/source/gdi/outdev/line.cxx | 277 | ||||
-rw-r--r-- | vcl/source/gdi/outdev/outdev.cxx | 37 | ||||
-rw-r--r-- | vcl/source/gdi/outdev/outdev5.cxx | 56 | ||||
-rw-r--r-- | vcl/source/gdi/outdev/polyline.cxx | 383 | ||||
-rw-r--r-- | vcl/source/gdi/outdev/rect.cxx | 118 |
6 files changed, 779 insertions, 93 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 5348d3836e07..e1330c1e4e39 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -238,6 +238,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/source/gdi/outdev/polygon \ vcl/source/gdi/outdev/outdev2 \ vcl/source/gdi/outdev/outdev3 \ + vcl/source/gdi/outdev/rect \ vcl/source/gdi/outdev/line \ vcl/source/gdi/outdev/polyline \ vcl/source/gdi/outdev/hatch \ diff --git a/vcl/source/gdi/outdev/line.cxx b/vcl/source/gdi/outdev/line.cxx new file mode 100644 index 000000000000..08a813b019ac --- /dev/null +++ b/vcl/source/gdi/outdev/line.cxx @@ -0,0 +1,277 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <vcl/virdev.hxx> +#include <vcl/outdev.hxx> + +#include <salgdi.hxx> + +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/polygon/b2dlinegeometry.hxx> + +void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt, + const LineInfo& rLineInfo ) +{ + + if ( rLineInfo.IsDefault() ) + { + DrawLine( rStartPt, rEndPt ); + return; + } + + if ( mpMetaFile ) + mpMetaFile->AddAction( new MetaLineAction( rStartPt, rEndPt, rLineInfo ) ); + + if ( !IsDeviceOutputNecessary() || !mbLineColor || ( LINE_NONE == rLineInfo.GetStyle() ) || ImplIsRecordLayout() ) + return; + + if( !mpGraphics && !ImplGetGraphics() ) + return; + + if ( mbInitClipRegion ) + ImplInitClipRegion(); + + if ( mbOutputClipped ) + return; + + const Point aStartPt( ImplLogicToDevicePixel( rStartPt ) ); + const Point aEndPt( ImplLogicToDevicePixel( rEndPt ) ); + const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) ); + const bool bDashUsed(LINE_DASH == aInfo.GetStyle()); + const bool bLineWidthUsed(aInfo.GetWidth() > 1); + + if ( mbInitLineColor ) + ImplInitLineColor(); + + if(bDashUsed || bLineWidthUsed) + { + basegfx::B2DPolygon aLinePolygon; + aLinePolygon.append(basegfx::B2DPoint(aStartPt.X(), aStartPt.Y())); + aLinePolygon.append(basegfx::B2DPoint(aEndPt.X(), aEndPt.Y())); + + ImplPaintLineGeometryWithEvtlExpand(aInfo, basegfx::B2DPolyPolygon(aLinePolygon)); + } + else + { + mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y(), this ); + } + + if( mpAlphaVDev ) + mpAlphaVDev->DrawLine( rStartPt, rEndPt, rLineInfo ); +} + +void OutputDevice::DrawLine( const Point& rStartPt, const Point& rEndPt ) +{ + + if ( mpMetaFile ) + mpMetaFile->AddAction( new MetaLineAction( rStartPt, rEndPt ) ); + + if ( !IsDeviceOutputNecessary() || !mbLineColor || ImplIsRecordLayout() ) + return; + + if ( !mpGraphics ) + { + if ( !ImplGetGraphics() ) + return; + } + + if ( mbInitClipRegion ) + ImplInitClipRegion(); + if ( mbOutputClipped ) + return; + + if ( mbInitLineColor ) + ImplInitLineColor(); + + // #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, 0.0, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, css::drawing::LineCap_BUTT, this)) + { + return; + } + } + + const Point aStartPt(ImplLogicToDevicePixel(rStartPt)); + const Point aEndPt(ImplLogicToDevicePixel(rEndPt)); + + mpGraphics->DrawLine( aStartPt.X(), aStartPt.Y(), aEndPt.X(), aEndPt.Y(), this ); + + if( mpAlphaVDev ) + mpAlphaVDev->DrawLine( rStartPt, rEndPt ); +} + +void OutputDevice::ImplPaintLineGeometryWithEvtlExpand( + const LineInfo& rInfo, + basegfx::B2DPolyPolygon aLinePolyPolygon) +{ + const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) + && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) + && ROP_OVERPAINT == GetRasterOp() + && IsLineColor()); + basegfx::B2DPolyPolygon aFillPolyPolygon; + const bool bDashUsed(LINE_DASH == rInfo.GetStyle()); + const bool bLineWidthUsed(rInfo.GetWidth() > 1); + + if(bDashUsed && aLinePolyPolygon.count()) + { + ::std::vector< double > fDotDashArray; + const double fDashLen(rInfo.GetDashLen()); + const double fDotLen(rInfo.GetDotLen()); + const double fDistance(rInfo.GetDistance()); + + for(sal_uInt16 a(0); a < rInfo.GetDashCount(); a++) + { + fDotDashArray.push_back(fDashLen); + fDotDashArray.push_back(fDistance); + } + + for(sal_uInt16 b(0); b < rInfo.GetDotCount(); b++) + { + fDotDashArray.push_back(fDotLen); + fDotDashArray.push_back(fDistance); + } + + const double fAccumulated(::std::accumulate(fDotDashArray.begin(), fDotDashArray.end(), 0.0)); + + if(fAccumulated > 0.0) + { + basegfx::B2DPolyPolygon aResult; + + for(sal_uInt32 c(0); c < aLinePolyPolygon.count(); c++) + { + basegfx::B2DPolyPolygon aLineTraget; + basegfx::tools::applyLineDashing( + aLinePolyPolygon.getB2DPolygon(c), + fDotDashArray, + &aLineTraget); + aResult.append(aLineTraget); + } + + aLinePolyPolygon = aResult; + } + } + + if(bLineWidthUsed && aLinePolyPolygon.count()) + { + const double fHalfLineWidth((rInfo.GetWidth() * 0.5) + 0.5); + + if(aLinePolyPolygon.areControlPointsUsed()) + { + // #i110768# When area geometry has to be created, do not + // use the fallback bezier decomposition inside createAreaGeometry, + // but one that is at least as good as ImplSubdivideBezier was. + // There, Polygon::AdaptiveSubdivide was used with default parameter + // 1.0 as quality index. + aLinePolyPolygon = basegfx::tools::adaptiveSubdivideByDistance(aLinePolyPolygon, 1.0); + } + + for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++) + { + aFillPolyPolygon.append(basegfx::tools::createAreaGeometry( + aLinePolyPolygon.getB2DPolygon(a), + fHalfLineWidth, + rInfo.GetLineJoin(), + rInfo.GetLineCap())); + } + + aLinePolyPolygon.clear(); + } + + GDIMetaFile* pOldMetaFile = mpMetaFile; + mpMetaFile = NULL; + + if(aLinePolyPolygon.count()) + { + for(sal_uInt32 a(0); a < aLinePolyPolygon.count(); a++) + { + const basegfx::B2DPolygon aCandidate(aLinePolyPolygon.getB2DPolygon(a)); + bool bDone(false); + + if(bTryAA) + { + bDone = mpGraphics->DrawPolyLine( aCandidate, 0.0, basegfx::B2DVector(1.0,1.0), basegfx::B2DLINEJOIN_NONE, css::drawing::LineCap_BUTT, this); + } + + if(!bDone) + { + const Polygon aPolygon(aCandidate); + mpGraphics->DrawPolyLine(aPolygon.GetSize(), (const SalPoint*)aPolygon.GetConstPointAry(), this); + } + } + } + + if(aFillPolyPolygon.count()) + { + const Color aOldLineColor( maLineColor ); + const Color aOldFillColor( maFillColor ); + + SetLineColor(); + ImplInitLineColor(); + SetFillColor( aOldLineColor ); + ImplInitFillColor(); + + bool bDone(false); + + if(bTryAA) + { + bDone = mpGraphics->DrawPolyPolygon(aFillPolyPolygon, 0.0, this); + } + + if(!bDone) + { + for(sal_uInt32 a(0); a < aFillPolyPolygon.count(); a++) + { + Polygon aPolygon(aFillPolyPolygon.getB2DPolygon(a)); + + // need to subdivide, mpGraphics->DrawPolygon ignores curves + aPolygon.AdaptiveSubdivide(aPolygon); + mpGraphics->DrawPolygon(aPolygon.GetSize(), (const SalPoint*)aPolygon.GetConstPointAry(), this); + } + } + + SetFillColor( aOldFillColor ); + SetLineColor( aOldLineColor ); + } + + mpMetaFile = pOldMetaFile; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/gdi/outdev/outdev.cxx b/vcl/source/gdi/outdev/outdev.cxx index 004910827ca9..474b80c2b519 100644 --- a/vcl/source/gdi/outdev/outdev.cxx +++ b/vcl/source/gdi/outdev/outdev.cxx @@ -1010,43 +1010,6 @@ void OutputDevice::SetRefPoint( const Point& rRefPoint ) mpAlphaVDev->SetRefPoint( rRefPoint ); } -void OutputDevice::DrawRect( const Rectangle& rRect ) -{ - - if ( mpMetaFile ) - mpMetaFile->AddAction( new MetaRectAction( rRect ) ); - - if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() ) - return; - - Rectangle aRect( ImplLogicToDevicePixel( rRect ) ); - - if ( aRect.IsEmpty() ) - return; - aRect.Justify(); - - if ( !mpGraphics ) - { - if ( !ImplGetGraphics() ) - return; - } - - if ( mbInitClipRegion ) - ImplInitClipRegion(); - if ( mbOutputClipped ) - return; - - if ( mbInitLineColor ) - ImplInitLineColor(); - if ( mbInitFillColor ) - ImplInitFillColor(); - - mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this ); - - if( mpAlphaVDev ) - mpAlphaVDev->DrawRect( rRect ); -} - sal_uInt32 OutputDevice::GetGCStackDepth() const { const ImplObjStack* pData = mpObjStack; diff --git a/vcl/source/gdi/outdev/outdev5.cxx b/vcl/source/gdi/outdev/outdev5.cxx index f16beae8ad95..7fe7e684db58 100644 --- a/vcl/source/gdi/outdev/outdev5.cxx +++ b/vcl/source/gdi/outdev/outdev5.cxx @@ -30,62 +30,6 @@ #include <outdata.hxx> #include <outdev.h> -void OutputDevice::DrawRect( const Rectangle& rRect, - sal_uLong nHorzRound, sal_uLong nVertRound ) -{ - - if ( mpMetaFile ) - mpMetaFile->AddAction( new MetaRoundRectAction( rRect, nHorzRound, nVertRound ) ); - - if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() ) - return; - - const Rectangle aRect( ImplLogicToDevicePixel( rRect ) ); - - if ( aRect.IsEmpty() ) - return; - - nHorzRound = ImplLogicWidthToDevicePixel( nHorzRound ); - nVertRound = ImplLogicHeightToDevicePixel( nVertRound ); - - // we need a graphics - if ( !mpGraphics ) - { - if ( !ImplGetGraphics() ) - return; - } - - if ( mbInitClipRegion ) - ImplInitClipRegion(); - if ( mbOutputClipped ) - return; - - if ( mbInitLineColor ) - ImplInitLineColor(); - if ( mbInitFillColor ) - ImplInitFillColor(); - - if ( !nHorzRound && !nVertRound ) - mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this ); - else - { - const Polygon aRoundRectPoly( aRect, nHorzRound, nVertRound ); - - if ( aRoundRectPoly.GetSize() >= 2 ) - { - const SalPoint* pPtAry = (const SalPoint*) aRoundRectPoly.GetConstPointAry(); - - if ( !mbFillColor ) - mpGraphics->DrawPolyLine( aRoundRectPoly.GetSize(), pPtAry, this ); - else - mpGraphics->DrawPolygon( aRoundRectPoly.GetSize(), pPtAry, this ); - } - } - - if( mpAlphaVDev ) - mpAlphaVDev->DrawRect( rRect, nHorzRound, nVertRound ); -} - void OutputDevice::DrawEllipse( const Rectangle& rRect ) { diff --git a/vcl/source/gdi/outdev/polyline.cxx b/vcl/source/gdi/outdev/polyline.cxx new file mode 100644 index 000000000000..26693376a25b --- /dev/null +++ b/vcl/source/gdi/outdev/polyline.cxx @@ -0,0 +1,383 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <vcl/virdev.hxx> +#include <vcl/outdev.hxx> +#include <vcl/settings.hxx> + +#include <salgdi.hxx> + +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/polygon/b2dlinegeometry.hxx> + +void OutputDevice::DrawPolyLine( const Polygon& rPoly ) +{ + + if( mpMetaFile ) + mpMetaFile->AddAction( new MetaPolyLineAction( rPoly ) ); + + sal_uInt16 nPoints = rPoly.GetSize(); + + if ( !IsDeviceOutputNecessary() || !mbLineColor || (nPoints < 2) || ImplIsRecordLayout() ) + return; + + // we need a graphics + if ( !mpGraphics ) + if ( !ImplGetGraphics() ) + return; + + if ( mbInitClipRegion ) + ImplInitClipRegion(); + if ( mbOutputClipped ) + return; + + if ( mbInitLineColor ) + ImplInitLineColor(); + + const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) + && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) + && ROP_OVERPAINT == GetRasterOp() + && IsLineColor()); + + // use b2dpolygon drawing if possible + if(bTryAA && ImplTryDrawPolyLineDirect(rPoly.getB2DPolygon())) + { + basegfx::B2DPolygon aB2DPolyLine(rPoly.getB2DPolygon()); + const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation(); + const ::basegfx::B2DVector aB2DLineWidth( 1.0, 1.0 ); + + // transform the polygon + aB2DPolyLine.transform( aTransform ); + + if(mnAntialiasing & ANTIALIASING_PIXELSNAPHAIRLINE) + { + aB2DPolyLine = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aB2DPolyLine); + } + + if(mpGraphics->DrawPolyLine( aB2DPolyLine, 0.0, aB2DLineWidth, basegfx::B2DLINEJOIN_NONE, css::drawing::LineCap_BUTT, this)) + { + return; + } + } + + Polygon aPoly = ImplLogicToDevicePixel( rPoly ); + const SalPoint* pPtAry = (const SalPoint*)aPoly.GetConstPointAry(); + + // #100127# Forward beziers to sal, if any + if( aPoly.HasFlags() ) + { + const sal_uInt8* pFlgAry = aPoly.GetConstFlagAry(); + if( !mpGraphics->DrawPolyLineBezier( nPoints, pPtAry, pFlgAry, this ) ) + { + aPoly = ImplSubdivideBezier(aPoly); + pPtAry = (const SalPoint*)aPoly.GetConstPointAry(); + mpGraphics->DrawPolyLine( aPoly.GetSize(), pPtAry, this ); + } + } + else + { + mpGraphics->DrawPolyLine( nPoints, pPtAry, this ); + } + + if( mpAlphaVDev ) + mpAlphaVDev->DrawPolyLine( rPoly ); +} + +void OutputDevice::DrawPolyLine( const Polygon& rPoly, const LineInfo& rLineInfo ) +{ + + if ( rLineInfo.IsDefault() ) + { + DrawPolyLine( rPoly ); + 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(), rLineInfo.GetLineJoin(), rLineInfo.GetLineCap()); + return; + } + + if ( mpMetaFile ) + mpMetaFile->AddAction( new MetaPolyLineAction( rPoly, rLineInfo ) ); + + ImplDrawPolyLineWithLineInfo(rPoly, rLineInfo); +} + +void OutputDevice::DrawPolyLine( + const basegfx::B2DPolygon& rB2DPolygon, + double fLineWidth, + basegfx::B2DLineJoin eLineJoin, + css::drawing::LineCap eLineCap) +{ + + if( mpMetaFile ) + { + LineInfo aLineInfo; + if( fLineWidth != 0.0 ) + aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) ); + const Polygon aToolsPolygon( rB2DPolygon ); + mpMetaFile->AddAction( new MetaPolyLineAction( aToolsPolygon, aLineInfo ) ); + } + + // Do not paint empty PolyPolygons + if(!rB2DPolygon.count() || !IsDeviceOutputNecessary()) + return; + + // we need a graphics + if( !mpGraphics ) + if( !ImplGetGraphics() ) + return; + + if( mbInitClipRegion ) + ImplInitClipRegion(); + if( mbOutputClipped ) + return; + + if( mbInitLineColor ) + ImplInitLineColor(); + + const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) + && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) + && ROP_OVERPAINT == GetRasterOp() + && IsLineColor()); + + // use b2dpolygon drawing if possible + if(bTryAA && ImplTryDrawPolyLineDirect(rB2DPolygon, fLineWidth, 0.0, eLineJoin, eLineCap)) + { + return; + } + + // #i101491# + // no output yet; fallback to geometry decomposition and use filled polygon paint + // when line is fat and not too complex. ImplDrawPolyPolygonWithB2DPolyPolygon + // 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, + eLineCap)); + const Color aOldLineColor(maLineColor); + const Color aOldFillColor(maFillColor); + + SetLineColor(); + ImplInitLineColor(); + SetFillColor(aOldLineColor); + ImplInitFillColor(); + + // draw usig a loop; else the topology will paint a PolyPolygon + for(sal_uInt32 a(0); a < aAreaPolyPolygon.count(); a++) + { + ImplDrawPolyPolygonWithB2DPolyPolygon( + basegfx::B2DPolyPolygon(aAreaPolyPolygon.getB2DPolygon(a))); + } + + SetLineColor(aOldLineColor); + ImplInitLineColor(); + SetFillColor(aOldFillColor); + ImplInitFillColor(); + + if(bTryAA) + { + // 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++) + { + ImplTryDrawPolyLineDirect(aAreaPolyPolygon.getB2DPolygon(a)); + } + } + } + else + { + // fallback to old polygon drawing if needed + const Polygon aToolsPolygon( rB2DPolygon ); + LineInfo aLineInfo; + if( fLineWidth != 0.0 ) + aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) ); + ImplDrawPolyLineWithLineInfo( aToolsPolygon, aLineInfo ); + } +} + +void OutputDevice::ImplDrawPolyLineWithLineInfo(const Polygon& rPoly, const LineInfo& rLineInfo) +{ + sal_uInt16 nPoints(rPoly.GetSize()); + + if ( !IsDeviceOutputNecessary() || !mbLineColor || ( nPoints < 2 ) || ( LINE_NONE == rLineInfo.GetStyle() ) || ImplIsRecordLayout() ) + return; + + Polygon aPoly = ImplLogicToDevicePixel( rPoly ); + + // #100127# LineInfo is not curve-safe, subdivide always + + // What shall this mean? It's wrong to subdivide here when the + // polygon is a fat line. In that case, the painted geometry + // WILL be much different. + // I also have no idea how this could be related to the given ID + // which reads 'consolidate boost versions' in the task description. + // Removing. + + //if( aPoly.HasFlags() ) + //{ + // aPoly = ImplSubdivideBezier( aPoly ); + // nPoints = aPoly.GetSize(); + //} + + // we need a graphics + if ( !mpGraphics && !ImplGetGraphics() ) + return; + + if ( mbInitClipRegion ) + ImplInitClipRegion(); + + if ( mbOutputClipped ) + return; + + if ( mbInitLineColor ) + ImplInitLineColor(); + + const LineInfo aInfo( ImplLogicToDevicePixel( rLineInfo ) ); + const bool bDashUsed(LINE_DASH == aInfo.GetStyle()); + const bool bLineWidthUsed(aInfo.GetWidth() > 1); + + if(bDashUsed || bLineWidthUsed) + { + ImplPaintLineGeometryWithEvtlExpand(aInfo, basegfx::B2DPolyPolygon(aPoly.getB2DPolygon())); + } + else + { + // #100127# the subdivision HAS to be done here since only a pointer + // to an array of points is given to the DrawPolyLine method, there is + // NO way to find out there that it's a curve. + if( aPoly.HasFlags() ) + { + aPoly = ImplSubdivideBezier( aPoly ); + nPoints = aPoly.GetSize(); + } + + mpGraphics->DrawPolyLine(nPoints, (const SalPoint*)aPoly.GetConstPointAry(), this); + } + + if( mpAlphaVDev ) + mpAlphaVDev->DrawPolyLine( rPoly, rLineInfo ); +} + +bool OutputDevice::ImplTryDrawPolyLineDirect( + const basegfx::B2DPolygon& rB2DPolygon, + double fLineWidth, + double fTransparency, + basegfx::B2DLineJoin eLineJoin, + css::drawing::LineCap eLineCap) +{ + 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, + fTransparency, + aB2DLineWidth, + eLineJoin, + eLineCap, + this); +} + +bool OutputDevice::TryDrawPolyLineDirect( + const basegfx::B2DPolygon& rB2DPolygon, + double fLineWidth, + double fTransparency, + basegfx::B2DLineJoin eLineJoin, + css::drawing::LineCap eLineCap) +{ + // AW: Do NOT paint empty PolyPolygons + if(!rB2DPolygon.count()) + return true; + + // we need a graphics + if( !mpGraphics ) + if( !ImplGetGraphics() ) + return false; + + if( mbInitClipRegion ) + ImplInitClipRegion(); + + if( mbOutputClipped ) + return true; + + if( mbInitLineColor ) + ImplInitLineColor(); + + const bool bTryAA((mnAntialiasing & ANTIALIASING_ENABLE_B2DDRAW) + && mpGraphics->supportsOperation(OutDevSupport_B2DDraw) + && ROP_OVERPAINT == GetRasterOp() + && IsLineColor()); + + if(bTryAA) + { + if(ImplTryDrawPolyLineDirect(rB2DPolygon, fLineWidth, fTransparency, eLineJoin, eLineCap)) + { + // worked, add metafile action (if recorded) and return true + if( mpMetaFile ) + { + LineInfo aLineInfo; + if( fLineWidth != 0.0 ) + aLineInfo.SetWidth( static_cast<long>(fLineWidth+0.5) ); + const Polygon aToolsPolygon( rB2DPolygon ); + mpMetaFile->AddAction( new MetaPolyLineAction( aToolsPolygon, aLineInfo ) ); + } + + return true; + } + } + + return false; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/gdi/outdev/rect.cxx b/vcl/source/gdi/outdev/rect.cxx new file mode 100644 index 000000000000..c8663d868d71 --- /dev/null +++ b/vcl/source/gdi/outdev/rect.cxx @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <tools/poly.hxx> + +#include <vcl/virdev.hxx> +#include <vcl/outdev.hxx> + +#include <salgdi.hxx> + +void OutputDevice::DrawRect( const Rectangle& rRect ) +{ + + if ( mpMetaFile ) + mpMetaFile->AddAction( new MetaRectAction( rRect ) ); + + if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() ) + return; + + Rectangle aRect( ImplLogicToDevicePixel( rRect ) ); + + if ( aRect.IsEmpty() ) + return; + aRect.Justify(); + + if ( !mpGraphics ) + { + if ( !ImplGetGraphics() ) + return; + } + + if ( mbInitClipRegion ) + ImplInitClipRegion(); + if ( mbOutputClipped ) + return; + + if ( mbInitLineColor ) + ImplInitLineColor(); + if ( mbInitFillColor ) + ImplInitFillColor(); + + mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this ); + + if( mpAlphaVDev ) + mpAlphaVDev->DrawRect( rRect ); +} + +void OutputDevice::DrawRect( const Rectangle& rRect, + sal_uLong nHorzRound, sal_uLong nVertRound ) +{ + + if ( mpMetaFile ) + mpMetaFile->AddAction( new MetaRoundRectAction( rRect, nHorzRound, nVertRound ) ); + + if ( !IsDeviceOutputNecessary() || (!mbLineColor && !mbFillColor) || ImplIsRecordLayout() ) + return; + + const Rectangle aRect( ImplLogicToDevicePixel( rRect ) ); + + if ( aRect.IsEmpty() ) + return; + + nHorzRound = ImplLogicWidthToDevicePixel( nHorzRound ); + nVertRound = ImplLogicHeightToDevicePixel( nVertRound ); + + // we need a graphics + if ( !mpGraphics ) + { + if ( !ImplGetGraphics() ) + return; + } + + if ( mbInitClipRegion ) + ImplInitClipRegion(); + if ( mbOutputClipped ) + return; + + if ( mbInitLineColor ) + ImplInitLineColor(); + if ( mbInitFillColor ) + ImplInitFillColor(); + + if ( !nHorzRound && !nVertRound ) + mpGraphics->DrawRect( aRect.Left(), aRect.Top(), aRect.GetWidth(), aRect.GetHeight(), this ); + else + { + const Polygon aRoundRectPoly( aRect, nHorzRound, nVertRound ); + + if ( aRoundRectPoly.GetSize() >= 2 ) + { + const SalPoint* pPtAry = (const SalPoint*) aRoundRectPoly.GetConstPointAry(); + + if ( !mbFillColor ) + mpGraphics->DrawPolyLine( aRoundRectPoly.GetSize(), pPtAry, this ); + else + mpGraphics->DrawPolygon( aRoundRectPoly.GetSize(), pPtAry, this ); + } + } + + if( mpAlphaVDev ) + mpAlphaVDev->DrawRect( rRect, nHorzRound, nVertRound ); +} |