summaryrefslogtreecommitdiff
path: root/vcl/source/gdi/outdev.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/gdi/outdev.cxx')
-rwxr-xr-x[-rw-r--r--]vcl/source/gdi/outdev.cxx847
1 files changed, 32 insertions, 815 deletions
diff --git a/vcl/source/gdi/outdev.cxx b/vcl/source/gdi/outdev.cxx
index ad89fda760b9..b5ecb0761949 100644..100755
--- a/vcl/source/gdi/outdev.cxx
+++ b/vcl/source/gdi/outdev.cxx
@@ -202,10 +202,6 @@ bool OutputDevice::ImplSelectClipRegion( const Region& rRegion, SalGraphics* pGr
{
DBG_TESTSOLARMUTEX();
- // TODO(Q3): Change from static to plain method - everybody's
- // calling it with pOutDev=this!
- // => done, but only with minimal changes for now => TODO
- OutputDevice* const pOutDev = this;
if( !pGraphics )
{
if( !mpGraphics )
@@ -214,91 +210,8 @@ bool OutputDevice::ImplSelectClipRegion( const Region& rRegion, SalGraphics* pGr
pGraphics = mpGraphics;
}
- if( rRegion.HasPolyPolygon()
- && pGraphics->supportsOperation( OutDevSupport_B2DClip ) )
- {
- const ::basegfx::B2DPolyPolygon& rB2DPolyPolygon = rRegion.GetB2DPolyPolygon();
- pGraphics->BeginSetClipRegion( 0 );
- pGraphics->UnionClipRegion( rB2DPolyPolygon, pOutDev );
- pGraphics->EndSetClipRegion();
- return true;
- }
-
- long nX;
- long nY;
- long nWidth;
- long nHeight;
- sal_uLong nRectCount;
- ImplRegionInfo aInfo;
- sal_Bool bRegionRect;
- sal_Bool bClipRegion = sal_True;
- const sal_Bool bClipDeviceBounds( !pOutDev->GetPDFWriter()
- && pOutDev->GetOutDevType() != OUTDEV_PRINTER );
-
- nRectCount = rRegion.GetRectCount();
- pGraphics->BeginSetClipRegion( nRectCount );
- bRegionRect = rRegion.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
- if( bClipDeviceBounds )
- {
- // #b6520266# Perform actual rect clip against outdev
- // dimensions, to generate empty clips whenever one of the
- // values is completely off the device.
- const long nOffX( pOutDev->mnOutOffX );
- const long nOffY( pOutDev->mnOutOffY );
- const long nDeviceWidth( pOutDev->GetOutputWidthPixel() );
- const long nDeviceHeight( pOutDev->GetOutputHeightPixel() );
- Rectangle aDeviceBounds( nOffX, nOffY,
- nOffX+nDeviceWidth-1,
- nOffY+nDeviceHeight-1 );
- while ( bRegionRect )
- {
- // #i59315# Limit coordinates passed to sal layer to actual
- // outdev dimensions - everything else bears the risk of
- // overflowing internal coordinates (e.g. the 16 bit wire
- // format of X11).
- Rectangle aTmpRect(nX,nY,nX+nWidth-1,nY+nHeight-1);
- aTmpRect.Intersection(aDeviceBounds);
-
- if( !aTmpRect.IsEmpty() )
- {
- if ( !pGraphics->UnionClipRegion( aTmpRect.Left(),
- aTmpRect.Top(),
- aTmpRect.GetWidth(),
- aTmpRect.GetHeight(),
- pOutDev ) )
- {
- bClipRegion = sal_False;
- }
- }
- else
- {
- // #i79850# Fake off-screen clip
- if ( !pGraphics->UnionClipRegion( nDeviceWidth+1,
- nDeviceHeight+1,
- 1, 1,
- pOutDev ) )
- {
- bClipRegion = sal_False;
- }
- }
- DBG_ASSERT( bClipRegion, "OutputDevice::ImplSelectClipRegion() - can't create region" );
- bRegionRect = rRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
- }
- }
- else
- {
- // #i65720# Actually, _don't_ clip anything on printer or PDF
- // export, since output might be visible outside the specified
- // device boundaries.
- while ( bRegionRect )
- {
- if ( !pGraphics->UnionClipRegion( nX, nY, nWidth, nHeight, pOutDev ) )
- bClipRegion = sal_False;
- DBG_ASSERT( bClipRegion, "OutputDevice::ImplSelectClipRegion() - can't cerate region" );
- bRegionRect = rRegion.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
- }
- }
- pGraphics->EndSetClipRegion();
+ bool bClipRegion = pGraphics->SetClipRegion( rRegion, this );
+ OSL_ENSURE( bClipRegion, "OutputDevice::ImplSelectClipRegion() - can't cerate region" );
return bClipRegion;
}
@@ -1075,9 +988,22 @@ void OutputDevice::ImplInitClipRegion()
else
{
mbOutputClipped = sal_False;
- ImplSelectClipRegion(
- // #102532# Respect output offset also for clip region
- ImplPixelToDevicePixel( maRegion ) );
+
+ // #102532# Respect output offset also for clip region
+ Region aRegion( ImplPixelToDevicePixel( maRegion ) );
+ const bool bClipDeviceBounds( ! GetPDFWriter()
+ && GetOutDevType() != OUTDEV_PRINTER );
+ if( bClipDeviceBounds )
+ {
+ // #b6520266# Perform actual rect clip against outdev
+ // dimensions, to generate empty clips whenever one of the
+ // values is completely off the device.
+ Rectangle aDeviceBounds( mnOutOffX, mnOutOffY,
+ mnOutOffX+GetOutputWidthPixel()-1,
+ mnOutOffY+GetOutputHeightPixel()-1 );
+ aRegion.Intersect( aDeviceBounds );
+ }
+ ImplSelectClipRegion( aRegion );
}
mbClipRegionSet = sal_True;
@@ -1122,693 +1048,6 @@ void OutputDevice::ImplSetClipRegion( const Region* pRegion )
// -----------------------------------------------------------------------
-namespace
-{
- inline int iround( float x )
- {
- union
- {
- float f;
- sal_Int32 i;
- };
- f = x;
- sal_Int32 exponent = (127 + 31) - ((i >> 23) & 0xFF);
- sal_Int32 r = ((sal_Int32(i) << 8) | (1U << 31)) >> exponent;
- r &= ((exponent - 32) >> 31);
- sal_Int32 sign = i >> 31;
- return r = (r ^ sign) - sign;
- }
-
- inline int floorDiv(int a, int b)
- {
- if(b == 0)
- return 0x80000000;
- if(a >= 0)
- return a / b;
- int q = -(-a / b); // quotient
- int r = -a % b; // remainder
- if(r)
- q--;
- return q;
- }
-
- inline int floorMod( int a, int b )
- {
- if(b == 0)
- return 0x80000000;
- if(a >= 0)
- return a % b;
- int r = -a % b; // remainder
- if(r)
- r = b - r;
- return r;
- }
-
- inline int ceilDiv( int a, int b )
- {
- if(b == 0)
- return 0x80000000;
- a += - 1 + b;
- if(a >= 0)
- return a / b;
- int q = -(-a / b); // quotient
- int r = -a % b; // remainder
- if(r)
- q--;
- return q;
- }
-
- inline int ceilMod( int a, int b )
- {
- if(b == 0)
- return 0x80000000;
- a += - 1 + b;
- if(a >= 0)
- return (a % b) + 1 - b;
- int r = -a % b;
- if(r)
- r = b - r;
- return r + 1 - b;
- }
-
- inline int ceilFix4(int x) { return (x + 0xF) & 0xFFFFFFF0; }
-
- struct vertex
- {
- float x,y;
- inline vertex( const Point &p )
- : x((float)p.getX()),y((float)p.getY()) {}
- };
-
- template<class T> inline void swap(T &a, T &b) { T t=a; a=b; b=t; }
-
- class SpanIterator
- {
- public:
-
- SpanIterator( sal_Int32 *pTable, size_t dwPitch, sal_Int32 dwNumScanlines );
- std::pair<sal_Int32,sal_Int32> GetNextSpan( void );
- sal_Int32 GetNumRemainingScanlines( void );
- sal_Int32 GetNumEqualScanlines( void );
- SpanIterator &operator++ ();
- SpanIterator &Skip( sal_Int32 dwNumScanlines );
- sal_Int32 GetRemainingSpans( void ) const { return maNumSpans; }
-
- private:
-
- sal_Int32 *mpTable;
- sal_Int32 *mpSpanArray;
- sal_Int32 maNumSpans;
- sal_Int32 maRemainingScanlines;
- size_t maPitch;
- };
-
- inline SpanIterator::SpanIterator( sal_Int32 *pTable, size_t dwPitch, sal_Int32 dwNumScanlines )
- : mpTable(pTable),maRemainingScanlines(dwNumScanlines),maPitch(dwPitch)
- {
- sal_Int32 *pNumSpans = mpTable;
- mpSpanArray = reinterpret_cast<sal_Int32 *>(pNumSpans+2);
- maNumSpans = *pNumSpans;
- }
-
- inline SpanIterator &SpanIterator::operator++ ()
- {
- --maRemainingScanlines;
- mpTable += maPitch;
- sal_Int32 *pNumSpans = mpTable;
- mpSpanArray = reinterpret_cast<sal_Int32 *>(pNumSpans+2);
- maNumSpans = *pNumSpans;
- return (*this);
- }
-
- inline SpanIterator &SpanIterator::Skip( sal_Int32 dwNumScanlines )
- {
- // don't skip more scanlines than there are...
- if(dwNumScanlines > maRemainingScanlines)
- dwNumScanlines = maRemainingScanlines;
-
- // skip in one fellow swoop...
- maRemainingScanlines -= dwNumScanlines;
- mpTable += maPitch * dwNumScanlines;
-
- // initialize necessary query fields...
- sal_Int32 *pNumSpans = mpTable;
- mpSpanArray = reinterpret_cast<sal_Int32 *>(pNumSpans+2);
- maNumSpans = *pNumSpans;
- return (*this);
- }
-
- inline std::pair<sal_Int32,sal_Int32> SpanIterator::GetNextSpan( void )
- {
- sal_Int32 x(0);
- sal_Int32 w(0);
- if(maNumSpans)
- {
- x = *mpSpanArray++;
- w = *mpSpanArray++;
- --maNumSpans;
- }
- return std::pair<sal_Int32,sal_Int32>(x,w);
- }
-
- inline sal_Int32 SpanIterator::GetNumEqualScanlines( void )
- {
- return mpTable[1];
- }
-
- inline sal_Int32 SpanIterator::GetNumRemainingScanlines( void )
- {
- return maRemainingScanlines;
- }
-
- class ScanlineContainer
- {
-
- public:
-
- ScanlineContainer( sal_uInt32 dwNumScanlines,
- sal_uInt32 dwNumSpansPerScanline );
-
- ~ScanlineContainer( void );
-
- void InsertSpan( sal_Int32 y, sal_Int32 lx, sal_Int32 rx );
-
- SpanIterator Iterate( void ) const { return SpanIterator(mpTable,maPitch,maNumScanlines); }
-
- inline sal_uInt32 GetNumSpans( void ) const { return maNumberOfSpans; }
-
- void Consolidate( void );
-
- private:
-
- // the span table will assist in determinate exactly how many clipping
- // regions [that is *spans*] we will end up with.
- // the counter for this purpose is right ahead.
- sal_uInt32 maNumberOfSpans;
-
- struct span
- {
- sal_Int32 x;
- sal_Int32 w;
- };
-
- sal_uInt32 maNumScanlines;
- sal_uInt32 maNumSpansPerScanline;
- sal_Int32 *mpTable;
- size_t maPitch;
- };
-
- ScanlineContainer::ScanlineContainer( sal_uInt32 dwNumScanlines,
- sal_uInt32 dwNumSpansPerScanline ) : maNumScanlines(dwNumScanlines),
- maNumSpansPerScanline(dwNumSpansPerScanline)
- {
- // #128002# add one scanline buffer at the end, as
- // SpanIterator::Skip reads two bytes past the end.
- ++dwNumScanlines;
-
- // since each triangle could possibly add another span
- // we can calculate the upper limit by [num scanlines * num triangles].
- const sal_uInt32 dwNumPossibleRegions = dwNumScanlines*dwNumSpansPerScanline;
-
- // calculate the number of bytes the span table will consume
- const size_t dwTableSize = dwNumPossibleRegions*sizeof(span)+dwNumScanlines*(sizeof(sal_Int32)<<1);
-
- // allocate the span table [on the stack]
- mpTable = static_cast<sal_Int32 *>(rtl_allocateMemory(dwTableSize));
-
- // calculate the table pitch, that is how many int's do i need to get from a scanline to the next.
- maPitch = (dwNumSpansPerScanline*sizeof(span)/sizeof(sal_Int32))+2;
-
- // we need to initialize the table here.
- // the first *int* on each scanline tells us how many spans are on it.
- sal_Int32 *pNumSpans = mpTable;
- for(unsigned int i=0; i<dwNumScanlines; ++i)
- {
- pNumSpans[0] = 0;
- pNumSpans[1] = 0;
- pNumSpans += maPitch;
- }
-
- maNumberOfSpans = 0;
- }
-
- ScanlineContainer::~ScanlineContainer( void )
- {
- rtl_freeMemory(mpTable);
- }
-
- void ScanlineContainer::InsertSpan( sal_Int32 y, sal_Int32 lx, sal_Int32 rx )
- {
- // there's new incoming span which we need to store in the table.
- // first see if its width contributes a valid span.
- if(sal_Int32 dwSpanWidth = rx-lx)
- {
- // first select the appropriate scanline the new span.
- sal_Int32 *pNumSpans = mpTable+(y*maPitch);
- span *pSpanArray = reinterpret_cast<span *>(pNumSpans+2);
-
- // retrieve the number of already contained spans.
- sal_Int32 dwNumSpan = *pNumSpans;
-
- // since we need to sort the spans from top to bottom
- // and left to right, we need to find the correct location
- // in the table.
- sal_Int32 dwIndex = 0;
- while(dwIndex<dwNumSpan)
- {
- // since we would like to avoid unnecessary spans
- // we try to consolidate them if possible.
- // consolidate with right neighbour
- if(pSpanArray[dwIndex].x == rx)
- {
- pSpanArray[dwIndex].x = lx;
- pSpanArray[dwIndex].w += dwSpanWidth;
- return;
- }
-
- // consolidate with left neighbour
- if((pSpanArray[dwIndex].x+pSpanArray[dwIndex].w) == lx)
- {
- pSpanArray[dwIndex].w += rx-lx;
- return;
- }
-
- // no consolidation possible, either this is a completely
- // seperate span or it is the first in the list.
- if(pSpanArray[dwIndex].x > lx)
- break;
-
- // forward to next element in the list.
- ++dwIndex;
- }
-
- // if we reach here, the new span needs to be stored
- // in the table, increase the number of spans in the
- // current scanline.
- *pNumSpans = dwNumSpan+1;
-
- // keep the list of spans in sorted order. 'dwIndex'
- // is where we want to store the new span. 'dwNumSpan'
- // is the number of spans already there. now we need
- // to move the offending spans out of the way.
- while(dwIndex != dwNumSpan)
- {
- pSpanArray[dwNumSpan].x = pSpanArray[dwNumSpan-1].x;
- pSpanArray[dwNumSpan].w = pSpanArray[dwNumSpan-1].w;
- --dwNumSpan;
- }
-
- // insert the new span
- pSpanArray[dwIndex].x = lx;
- pSpanArray[dwIndex].w = rx-lx;
-
- // remember the total number of spans in the table.
- ++maNumberOfSpans;
- }
- }
-
- void ScanlineContainer::Consolidate( void )
- {
- sal_Int32 *pScanline = mpTable;
-
- sal_Int32 dwRemaining = maNumScanlines;
- while(dwRemaining)
- {
- sal_Int32 dwNumSpans = pScanline[0];
- sal_Int32 *pSpanArray = pScanline+2;
-
- sal_Int32 dwRest = dwRemaining-1;
- sal_Int32 *pNext = pScanline;
- while(dwRest)
- {
- pNext += maPitch;
- sal_Int32 dwNumNextSpans = pNext[0];
- sal_Int32 *pSpanArrayNext = pNext+2;
- if(dwNumSpans != dwNumNextSpans)
- break;
-
- sal_Int32 dwCompare = dwNumSpans<<1;
- while(dwCompare)
- {
- if(pSpanArray[dwCompare-1] != pSpanArrayNext[dwCompare-1])
- break;
- --dwCompare;
- }
- if(dwCompare)
- break;
-
- --dwRest;
- }
-
- const sal_Int32 dwNumEqualScanlines(dwRemaining-dwRest);
- pScanline[1] = dwNumEqualScanlines;
- pScanline += maPitch*dwNumEqualScanlines;
- dwRemaining -= dwNumEqualScanlines;
-
- // since we track the total number of spans to generate,
- // we need to account for consolidated scanlines here.
- if(dwNumEqualScanlines > 1)
- maNumberOfSpans -= dwNumSpans * (dwNumEqualScanlines-1);
- }
- }
-}
-
-// TODO: we should consider passing a basegfx b2dpolypolygon here to
-// ensure that the signature isn't misleading.
-// if we could pass a b2dpolypolygon here, we could easily triangulate it.
-void OutputDevice::ImplSetTriangleClipRegion( const PolyPolygon &rPolyPolygon )
-{
- DBG_TESTSOLARMUTEX();
-
- if(!(IsDeviceOutputNecessary()))
- return;
- if(!(mpGraphics))
- if(!(ImplGetGraphics()))
- return;
-
- if( mpGraphics->supportsOperation( OutDevSupport_B2DClip ) )
- {
-#if 0
- ::basegfx::B2DPolyPolygon aB2DPolyPolygon = rPolyPolygon.getB2DPolyPolygon();
-#else
- // getB2DPolyPolygon() "optimizes away" some points
- // which prevents reliable undoing of the "triangle thingy" parameter
- // so the toolspoly -> b2dpoly conversion has to be done manually
- ::basegfx::B2DPolyPolygon aB2DPolyPolygon;
- for( sal_uInt16 nPolyIdx = 0; nPolyIdx < rPolyPolygon.Count(); ++nPolyIdx )
- {
- const Polygon& rPolygon = rPolyPolygon[ nPolyIdx ];
- ::basegfx::B2DPolygon aB2DPoly;
- for( sal_uInt16 nPointIdx = 0; nPointIdx < rPolygon.GetSize(); ++nPointIdx )
- {
- const Point& rPoint = rPolygon[ nPointIdx ];
- const ::basegfx::B2DPoint aB2DPoint( rPoint.X(), rPoint.Y() );
- aB2DPoly.append( aB2DPoint );
- }
- aB2DPolyPolygon.append( aB2DPoly );
- }
-#endif
-
- const ::basegfx::B2DHomMatrix aTransform = ImplGetDeviceTransformation();
- aB2DPolyPolygon.transform( aTransform );
-
- // the rPolyPolygon argument is a "triangle thingy"
- // so convert it to a normal polypolyon first
- ::basegfx::B2DPolyPolygon aPolyTriangle;
- const int nPolyCount = aB2DPolyPolygon.count();
- for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
- {
- const ::basegfx::B2DPolygon rPolygon = aB2DPolyPolygon.getB2DPolygon( nPolyIdx );
- const int nPointCount = rPolygon.count();
- for( int nPointIdx = 0; nPointIdx+2 < nPointCount; nPointIdx +=3 )
- {
- ::basegfx::B2DPolygon aTriangle;
- aTriangle.append( rPolygon.getB2DPoint( nPointIdx+0 ) );
- aTriangle.append( rPolygon.getB2DPoint( nPointIdx+1 ) );
- aTriangle.append( rPolygon.getB2DPoint( nPointIdx+2 ) );
- aPolyTriangle.append( aTriangle );
- }
- }
-
- // now set the clip region with the real polypolygon
- mpGraphics->BeginSetClipRegion( 0 );
- mpGraphics->UnionClipRegion( aPolyTriangle, this );
- mpGraphics->EndSetClipRegion();
-
- // and mark the clip status as ready
- mbOutputClipped = sal_False;
- mbClipRegion = sal_True;
- mbClipRegionSet = sal_True;
- mbInitClipRegion = sal_False;
- return;
- }
-
- sal_Int32 offset_x = 0;
- sal_Int32 offset_y = 0;
- if ( GetOutDevType() == OUTDEV_WINDOW )
- {
- offset_x = mnOutOffX+mnOutOffOrigX;
- offset_y = mnOutOffY+mnOutOffOrigY;
- }
-
- // first of all we need to know the upper limit
- // of the amount of possible clipping regions.
- sal_Int32 maxy = SAL_MIN_INT32;
- sal_Int32 miny = SAL_MAX_INT32;
- sal_uInt32 dwNumTriangles = 0;
- for(sal_uInt16 i=0; i<rPolyPolygon.Count(); ++i)
- {
- const Polygon &rPoly = rPolyPolygon.GetObject(i);
- const sal_Int32 dwNumVertices = rPoly.GetSize();
- if(!(dwNumVertices % 3))
- {
- for(sal_uInt16 j=0; j<rPoly.GetSize(); ++j)
- {
- const Point &p = rPoly.GetPoint(j);
- if(p.Y() < miny)
- miny = p.Y();
- if(p.Y() > maxy)
- maxy = p.Y();
- }
- dwNumTriangles += dwNumVertices / 3;
- }
- }
-
- const sal_uInt32 dwNumScanlines = (maxy-miny);
- if(!(dwNumScanlines))
- {
- // indicates that no output needs to be produced
- // since the clipping region did not provide any
- // visible areas.
- mbOutputClipped = sal_True;
-
- // indicates that a clip region has been
- // presented to the output device.
- mbClipRegion = sal_True;
-
- // indicates that the set clipping region
- // has been processed.
- mbClipRegionSet = sal_True;
-
- // under 'normal' circumstances a new clipping region
- // needs to be processed by ImplInitClipRegion(),
- // which we need to circumvent.
- mbInitClipRegion = sal_False;
- return;
- }
-
- // this container provides all services we need to
- // efficiently store/retrieve spans from the table.
- const sal_uInt32 dwNumSpansPerScanline = dwNumTriangles;
- ScanlineContainer container(dwNumScanlines,dwNumSpansPerScanline);
-
- // convert the incoming polypolygon to spans, we assume that
- // the polypolygon has already been triangulated since we don't
- // want to use the basegfx-types here. this could be leveraged
- // after the tools-types had been removed.
- for(sal_uInt16 i=0; i<rPolyPolygon.Count(); ++i)
- {
- const Polygon &rPoly = rPolyPolygon.GetObject(i);
- const sal_uInt16 dwNumVertices = rPoly.GetSize();
- if(!(dwNumVertices % 3))
- {
- for(sal_uInt16 j=0; j<dwNumVertices; j+=3)
- {
- const Point &p0 = rPoly.GetPoint(j+0);
- const Point &p1 = rPoly.GetPoint(j+1);
- const Point &p2 = rPoly.GetPoint(j+2);
-
- // what now follows is an extremely fast triangle
- // rasterizer from which all tricky and interesting
- // parts were forcibly amputated.
- // note: top.left fill-convention
- vertex v0(p0);
- vertex v1(p1);
- vertex v2(p2);
-
- //sprintf(string,"[%f,%f] [%f,%f] [%f,%f]\n",v0.x,v0.y,v1.x,v1.y,v2.x,v2.y);
- //OSL_TRACE(string);
-
- if(v0.y > v2.y) ::swap(v0, v2);
- if(v1.y > v2.y) ::swap(v1, v2);
- if(v0.y > v1.y) ::swap(v0, v1);
-
- const float float2fixed(16.0f);
-
- // vertex coordinates of the triangle [28.4 fixed-point]
- const int i4x0 = iround(float2fixed * (v0.x - 0.5f));
- const int i4y0 = iround(float2fixed * (v0.y - 0.5f));
- const int i4x1 = iround(float2fixed * (v1.x - 0.5f));
- const int i4y1 = iround(float2fixed * (v1.y - 0.5f));
- const int i4x2 = iround(float2fixed * (v2.x - 0.5f));
- const int i4y2 = iround(float2fixed * (v2.y - 0.5f));
-
- // vertex coordinate deltas [28.4 fixed-point]
- const int i4dx12 = i4x1-i4x0;
- const int i4dy12 = i4y1-i4y0;
- const int i4dx13 = i4x2-i4x0;
- const int i4dy13 = i4y2-i4y0;
- const int i4dx23 = i4x2-i4x1;
- const int i4dy23 = i4y2-i4y1;
-
- // slope of edges [quotient,remainder]
- const int mq12 = floorDiv(i4dx12 << 4, i4dy12 << 4);
- const int mq13 = floorDiv(i4dx13 << 4, i4dy13 << 4);
- const int mq23 = floorDiv(i4dx23 << 4, i4dy23 << 4);
- const int mr12 = floorMod(i4dx12 << 4, i4dy12 << 4);
- const int mr13 = floorMod(i4dx13 << 4, i4dy13 << 4);
- const int mr23 = floorMod(i4dx23 << 4, i4dy23 << 4);
-
- // convert the vertical coordinates back to integers.
- // according to the top-left fillrule we need to step
- // the coordinates to the ceiling.
- const int y0 = (i4y0+15)>>4;
- const int y1 = (i4y1+15)>>4;
- const int y2 = (i4y2+15)>>4;
-
- // calculate the value of the horizontal coordinate
- // from the edge that 'spans' the triangle.
- const int x = ceilDiv(i4dx13*i4dy12 + i4x0*i4dy13, i4dy13);
-
- // this will hold the horizontal coordinates
- // of the seperate spans during the rasterization process.
- int lx,rx;
-
- // this pair will serve as the error accumulator while
- // we step along the edges.
- int ld,rd,lD,rD;
-
- // these are the edge and error stepping values that
- // will be used while stepping.
- int lQ,rQ,lR,rR;
-
- if(i4x1 < x)
- {
- lx = ceilDiv(i4dx12 * (ceilFix4(i4y0) - i4y0) + i4x0 * i4dy12, i4dy12 << 4);
- ld = ceilMod(i4dx12 * (ceilFix4(i4y0) - i4y0) + i4x0 * i4dy12, i4dy12 << 4);
- rx = ceilDiv(i4dx13 * (ceilFix4(i4y0) - i4y0) + i4x0 * i4dy13, i4dy13 << 4);
- rd = ceilMod(i4dx13 * (ceilFix4(i4y0) - i4y0) + i4x0 * i4dy13, i4dy13 << 4);
- lQ = mq12;
- rQ = mq13;
- lR = mr12;
- rR = mr13;
- lD = i4dy12 << 4;
- rD = i4dy13 << 4;
- }
- else
- {
- lx = ceilDiv(i4dx13 * (ceilFix4(i4y0) - i4y0) + i4x0 * i4dy13, i4dy13 << 4);
- ld = ceilMod(i4dx13 * (ceilFix4(i4y0) - i4y0) + i4x0 * i4dy13, i4dy13 << 4);
- rx = ceilDiv(i4dx12 * (ceilFix4(i4y0) - i4y0) + i4x0 * i4dy12, i4dy12 << 4);
- rd = ceilMod(i4dx12 * (ceilFix4(i4y0) - i4y0) + i4x0 * i4dy12, i4dy12 << 4);
- lQ = mq13;
- rQ = mq12;
- lR = mr13;
- rR = mr12;
- lD = i4dy13 << 4;
- rD = i4dy12 << 4;
- }
-
- for(signed int y=y0; y<y1; y++)
- {
- container.InsertSpan(y-miny,lx,rx);
-
- lx += lQ; ld += lR;
- if(ld > 0) { ld -= lD; lx += 1; }
- rx += rQ; rd += rR;
- if(rd > 0) { rd -= rD; rx += 1; }
- }
-
- if(i4x1 < x)
- {
- lx = ceilDiv(i4dx23 * (ceilFix4(i4y1) - i4y1) + i4x1 * i4dy23, i4dy23 << 4);
- ld = ceilMod(i4dx23 * (ceilFix4(i4y1) - i4y1) + i4x1 * i4dy23, i4dy23 << 4);
- rx = ceilDiv(i4dx13 * (ceilFix4(i4y1) - i4y0) + i4x0 * i4dy13, i4dy13 << 4);
- rd = ceilMod(i4dx13 * (ceilFix4(i4y1) - i4y0) + i4x0 * i4dy13, i4dy13 << 4);
- lQ = mq23;
- lR = mr23;
- lD = i4dy23 << 4;
- }
- else
- {
- rx = ceilDiv(i4dx23 * (ceilFix4(i4y1) - i4y1) + i4x1 * i4dy23, i4dy23 << 4);
- rd = ceilMod(i4dx23 * (ceilFix4(i4y1) - i4y1) + i4x1 * i4dy23, i4dy23 << 4);
- rQ = mq23;
- rR = mr23;
- rD = i4dy23 << 4;
- }
-
- for(signed int y=y1; y<y2; y++)
- {
- container.InsertSpan(y-miny,lx,rx);
-
- lx += lQ; ld += lR;
- if(ld > 0) { ld -= lD; lx += 1; }
- rx += rQ; rd += rR;
- if(rd > 0) { rd -= rD; rx += 1; }
- }
- }
- }
- }
-
- // now try to consolidate as many scanlines as possible.
- // please note that this will probably change the number
- // of spans [at least this is why we do all this hassle].
- // so, if you use 'consolidate' you should *use* this
- // information during iteration, because the 'graphics'
- // object we tell all those regions about is a bit,
- // hm, how to say, *picky* if you supply not correctly
- // the amount of regions.
- container.Consolidate();
-
- // now forward the spantable to the graphics handler.
- SpanIterator it(container.Iterate());
- mpGraphics->BeginSetClipRegion( container.GetNumSpans() );
- while(miny < maxy)
- {
- const sal_Int32 dwNumEqual(it.GetNumEqualScanlines());
- while(it.GetRemainingSpans())
- {
- // retrieve the next span [x-coordinate, width] from the current scanline.
- std::pair<sal_Int32,sal_Int32> span(it.GetNextSpan());
-
- // now forward this to the graphics object.
- // the only part that is worth noting is that we use
- // the number of equal spanlines [the current is always the
- // first one of the equal bunch] as the height of the region.
- mpGraphics->UnionClipRegion( offset_x+span.first,
- offset_y+miny,
- span.second,
- dwNumEqual,
- this );
- }
- it.Skip(dwNumEqual);
- miny += dwNumEqual;
- }
- mpGraphics->EndSetClipRegion();
-
- // indicates that no output needs to be produced
- // since the clipping region did not provide any
- // visible areas. the clip covers the whole area
- // if there's not a single region.
- mbOutputClipped = (container.GetNumSpans() == 0);
-
- // indicates that a clip region has been
- // presented to the output device.
- mbClipRegion = sal_True;
-
- // indicates that the set clipping region
- // has been processed.
- mbClipRegionSet = sal_True;
-
- // under 'normal' circumstances a new clipping region
- // needs to be processed by ImplInitClipRegion(),
- // which we need to circumvent.
- mbInitClipRegion = sal_False;
-}
-
-// -----------------------------------------------------------------------
-
void OutputDevice::SetClipRegion()
{
DBG_TRACE( "OutputDevice::SetClipRegion()" );
@@ -1848,42 +1087,6 @@ void OutputDevice::SetClipRegion( const Region& rRegion )
// -----------------------------------------------------------------------
-void OutputDevice::SetTriangleClipRegion( const PolyPolygon &rPolyPolygon )
-{
- DBG_TRACE( "OutputDevice::SetTriangleClipRegion( rPolyPolygon )" );
- DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
-
- // in case the passed polypolygon is empty, use the
- // existing SetClipRegion() method which gracefully
- // unsets any previously set clipping region.
- if(!(rPolyPolygon.Count()))
- SetClipRegion();
-
- sal_Int32 offset_x = 0;
- sal_Int32 offset_y = 0;
- if ( GetOutDevType() == OUTDEV_WINDOW )
- {
- offset_x = mnOutOffX+mnOutOffOrigX;
- offset_y = mnOutOffY+mnOutOffOrigY;
- }
-
- // play nice with the rest of the system and provide an old-style region.
- // the rest of this method does not rely on this.
- maRegion = Region::GetRegionFromPolyPolygon( LogicToPixel(rPolyPolygon) );
- maRegion.Move(offset_x,offset_x);
-
- // feed region to metafile
- if ( mpMetaFile )
- mpMetaFile->AddAction( new MetaClipRegionAction( maRegion, sal_True ) );
-
- ImplSetTriangleClipRegion( rPolyPolygon );
-
- if( mpAlphaVDev )
- mpAlphaVDev->SetTriangleClipRegion( rPolyPolygon );
-}
-
-// -----------------------------------------------------------------------
-
Region OutputDevice::GetClipRegion() const
{
DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
@@ -3159,6 +2362,20 @@ void OutputDevice::DrawPolyLine(
// -----------------------------------------------------------------------
+sal_uInt32 OutputDevice::GetGCStackDepth() const
+{
+ const ImplObjStack* pData = mpObjStack;
+ sal_uInt32 nDepth = 0;
+ while( pData )
+ {
+ nDepth++;
+ pData = pData->mpPrev;
+ }
+ return nDepth;
+}
+
+// -----------------------------------------------------------------------
+
void OutputDevice::Push( sal_uInt16 nFlags )
{
DBG_TRACE( "OutputDevice::Push()" );