summaryrefslogtreecommitdiff
path: root/vcl/source/gdi
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/gdi')
-rw-r--r--vcl/source/gdi/bitmap.cxx10
-rw-r--r--vcl/source/gdi/jobset.cxx7
-rw-r--r--vcl/source/gdi/lineinfo.cxx22
-rwxr-xr-xvcl/source/gdi/outdev.cxx847
-rwxr-xr-xvcl/source/gdi/outdev3.cxx8
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx306
-rw-r--r--vcl/source/gdi/pdfwriter_impl.hxx11
-rw-r--r--vcl/source/gdi/pdfwriter_impl2.cxx511
-rw-r--r--vcl/source/gdi/print.cxx44
-rw-r--r--vcl/source/gdi/print2.cxx35
-rwxr-xr-xvcl/source/gdi/print3.cxx43
-rwxr-xr-x[-rw-r--r--]vcl/source/gdi/region.cxx193
-rwxr-xr-xvcl/source/gdi/salgdilayout.cxx60
13 files changed, 1052 insertions, 1045 deletions
diff --git a/vcl/source/gdi/bitmap.cxx b/vcl/source/gdi/bitmap.cxx
index a99cdd91c2f5..bcf141a8e005 100644
--- a/vcl/source/gdi/bitmap.cxx
+++ b/vcl/source/gdi/bitmap.cxx
@@ -237,9 +237,13 @@ bool BitmapPalette::IsGreyPalette() const
const int nEntryCount = GetEntryCount();
if( !nEntryCount ) // NOTE: an empty palette means 1:1 mapping
return true;
- const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette( nEntryCount );
- if( rGreyPalette == *this )
- return true;
+ // see above: only certain entry values will result in a valid call to GetGreyPalette
+ if( nEntryCount == 2 || nEntryCount == 4 || nEntryCount == 16 || nEntryCount == 256 )
+ {
+ const BitmapPalette& rGreyPalette = Bitmap::GetGreyPalette( nEntryCount );
+ if( rGreyPalette == *this )
+ return true;
+ }
// TODO: is it worth to compare the entries?
return false;
}
diff --git a/vcl/source/gdi/jobset.cxx b/vcl/source/gdi/jobset.cxx
index a1291b8dd67d..b44a99b2789d 100644
--- a/vcl/source/gdi/jobset.cxx
+++ b/vcl/source/gdi/jobset.cxx
@@ -301,13 +301,16 @@ SvStream& operator>>( SvStream& rIStream, JobSetup& rJobSetup )
// Zur Zeit haben wir noch kein neues FileFormat
// if ( rIStream.GetVersion() < JOBSET_FILEFORMAT2 )
{
- sal_uInt16 nLen;
- sal_uInt16 nSystem;
sal_Size nFirstPos = rIStream.Tell();
+
+ sal_uInt16 nLen = 0;
rIStream >> nLen;
if ( !nLen )
return rIStream;
+
+ sal_uInt16 nSystem = 0;
rIStream >> nSystem;
+
char* pTempBuf = new char[nLen];
rIStream.Read( pTempBuf, nLen - sizeof( nLen ) - sizeof( nSystem ) );
if ( nLen >= sizeof(ImplOldJobSetupData)+4 )
diff --git a/vcl/source/gdi/lineinfo.cxx b/vcl/source/gdi/lineinfo.cxx
index b7020874ca9c..ebd55a48f593 100644
--- a/vcl/source/gdi/lineinfo.cxx
+++ b/vcl/source/gdi/lineinfo.cxx
@@ -70,6 +70,20 @@ ImplLineInfo::ImplLineInfo( const ImplLineInfo& rImplLineInfo ) :
{
}
+// -----------------------------------------------------------------------
+
+inline bool ImplLineInfo::operator==( const ImplLineInfo& rB ) const
+{
+ return(meStyle == rB.meStyle
+ && mnWidth == rB.mnWidth
+ && mnDashCount == rB.mnDashCount
+ && mnDashLen == rB.mnDashLen
+ && mnDotCount == rB.mnDotCount
+ && mnDotLen == rB.mnDotLen
+ && mnDistance == rB.mnDistance
+ && meLineJoin == rB.meLineJoin);
+}
+
// ------------
// - LineInfo -
// ------------
@@ -125,13 +139,7 @@ sal_Bool LineInfo::operator==( const LineInfo& rLineInfo ) const
DBG_CHKOBJ( &rLineInfo, LineInfo, NULL );
return( mpImplLineInfo == rLineInfo.mpImplLineInfo ||
- ( mpImplLineInfo->meStyle == rLineInfo.mpImplLineInfo->meStyle &&
- mpImplLineInfo->mnWidth == rLineInfo.mpImplLineInfo->mnWidth &&
- mpImplLineInfo->mnDashCount == rLineInfo.mpImplLineInfo->mnDashCount &&
- mpImplLineInfo->mnDashLen == rLineInfo.mpImplLineInfo->mnDashLen &&
- mpImplLineInfo->mnDotCount == rLineInfo.mpImplLineInfo->mnDotCount &&
- mpImplLineInfo->mnDotLen == rLineInfo.mpImplLineInfo->mnDotLen &&
- mpImplLineInfo->mnDistance == rLineInfo.mpImplLineInfo->mnDistance ) );
+ *mpImplLineInfo == *rLineInfo.mpImplLineInfo );
}
// -----------------------------------------------------------------------
diff --git a/vcl/source/gdi/outdev.cxx b/vcl/source/gdi/outdev.cxx
index 69caa0105999..dcad34c363ad 100755
--- a/vcl/source/gdi/outdev.cxx
+++ b/vcl/source/gdi/outdev.cxx
@@ -201,10 +201,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 )
@@ -213,91 +209,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;
}
@@ -1074,9 +987,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;
@@ -1121,693 +1047,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()" );
@@ -1847,42 +1086,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 );
@@ -3158,6 +2361,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()" );
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
index e6d385ced122..1681e1eeec7c 100755
--- a/vcl/source/gdi/outdev3.cxx
+++ b/vcl/source/gdi/outdev3.cxx
@@ -7422,7 +7422,6 @@ SystemTextLayoutData OutputDevice::GetSysTextLayoutData(const Point& rStartPt, c
// setup glyphs
Point aPos;
sal_GlyphId aGlyphId;
- int nFallbacklevel = 0;
for( int nStart = 0; rLayout->GetNextGlyphs( 1, &aGlyphId, aPos, nStart ); )
{
// NOTE: Windows backend is producing unicode chars (ucs4), so on windows,
@@ -7432,15 +7431,12 @@ SystemTextLayoutData OutputDevice::GetSysTextLayoutData(const Point& rStartPt, c
aGlyph.index = static_cast<unsigned long> (aGlyphId & GF_IDXMASK);
aGlyph.x = aPos.X();
aGlyph.y = aPos.Y();
- aSysLayoutData.rGlyphData.push_back(aGlyph);
-
int nLevel = (aGlyphId & GF_FONTMASK) >> GF_FONTSHIFT;
- if (nLevel > nFallbacklevel && nLevel < MAX_FALLBACK)
- nFallbacklevel = nLevel;
+ aGlyph.fallbacklevel = nLevel < MAX_FALLBACK ? nLevel : 0;
+ aSysLayoutData.rGlyphData.push_back(aGlyph);
}
// Get font data
- aSysLayoutData.aSysFontData = GetSysFontData(nFallbacklevel);
aSysLayoutData.orientation = rLayout->GetOrientation();
rLayout->Release();
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 331c264fee03..09d3e7372c22 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -898,34 +898,44 @@ static void appendDouble( double fValue, OStringBuffer& rBuffer, sal_Int32 nPrec
}
-static void appendColor( const Color& rColor, OStringBuffer& rBuffer )
+static void appendColor( const Color& rColor, OStringBuffer& rBuffer, bool bConvertToGrey = false )
{
if( rColor != Color( COL_TRANSPARENT ) )
{
- appendDouble( (double)rColor.GetRed() / 255.0, rBuffer );
- rBuffer.append( ' ' );
- appendDouble( (double)rColor.GetGreen() / 255.0, rBuffer );
- rBuffer.append( ' ' );
- appendDouble( (double)rColor.GetBlue() / 255.0, rBuffer );
+ if( bConvertToGrey )
+ {
+ sal_uInt8 cByte = rColor.GetLuminance();
+ appendDouble( (double)cByte / 255.0, rBuffer );
+ }
+ else
+ {
+ appendDouble( (double)rColor.GetRed() / 255.0, rBuffer );
+ rBuffer.append( ' ' );
+ appendDouble( (double)rColor.GetGreen() / 255.0, rBuffer );
+ rBuffer.append( ' ' );
+ appendDouble( (double)rColor.GetBlue() / 255.0, rBuffer );
+ }
}
}
-static void appendStrokingColor( const Color& rColor, OStringBuffer& rBuffer )
+void PDFWriterImpl::appendStrokingColor( const Color& rColor, OStringBuffer& rBuffer )
{
if( rColor != Color( COL_TRANSPARENT ) )
{
- appendColor( rColor, rBuffer );
- rBuffer.append( " RG" );
+ bool bGrey = m_aContext.ColorMode == PDFWriter::DrawGreyscale;
+ appendColor( rColor, rBuffer, bGrey );
+ rBuffer.append( bGrey ? " G" : " RG" );
}
}
-static void appendNonStrokingColor( const Color& rColor, OStringBuffer& rBuffer )
+void PDFWriterImpl::appendNonStrokingColor( const Color& rColor, OStringBuffer& rBuffer )
{
if( rColor != Color( COL_TRANSPARENT ) )
{
- appendColor( rColor, rBuffer );
- rBuffer.append( " rg" );
+ bool bGrey = m_aContext.ColorMode == PDFWriter::DrawGreyscale;
+ appendColor( rColor, rBuffer, bGrey );
+ rBuffer.append( bGrey ? " g" : " rg" );
}
}
@@ -2048,9 +2058,25 @@ inline void PDFWriterImpl::appendLiteralStringEncrypt( const rtl::OString& rInSt
appendLiteralStringEncrypt( aBufferString, nInObjectNumber, rOutBuffer);
}
-inline void PDFWriterImpl::appendLiteralStringEncrypt( const rtl::OUString& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer )
+void PDFWriterImpl::appendLiteralStringEncrypt( const rtl::OUString& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer, rtl_TextEncoding nEnc )
{
- rtl::OString aBufferString( rtl::OUStringToOString( rInString, RTL_TEXTENCODING_ASCII_US ) );
+ rtl::OString aBufferString( rtl::OUStringToOString( rInString, nEnc ) );
+ sal_Int32 nLen = aBufferString.getLength();
+ rtl::OStringBuffer aBuf( nLen );
+ const sal_Char* pT = aBufferString.getStr();
+
+ for( sal_Int32 i = 0; i < nLen; i++, pT++ )
+ {
+ if( (*pT & 0x80) == 0 )
+ aBuf.append( *pT );
+ else
+ {
+ aBuf.append( '<' );
+ appendHex( *pT, aBuf );
+ aBuf.append( '>' );
+ }
+ }
+ aBufferString = aBuf.makeStringAndClear();
appendLiteralStringEncrypt( aBufferString, nInObjectNumber, rOutBuffer);
}
@@ -2957,12 +2983,9 @@ bool PDFWriterImpl::emitTilings()
aTilingObj.setLength( 0 );
-#if OSL_DEBUG_LEVEL > 1
- {
- OStringBuffer aLine( "PDFWriterImpl::emitTilings" );
- emitComment( aLine.getStr() );
- }
-#endif
+ #if OSL_DEBUG_LEVEL > 1
+ emitComment( "PDFWriterImpl::emitTilings" );
+ #endif
sal_Int32 nX = (sal_Int32)it->m_aRectangle.Left();
sal_Int32 nY = (sal_Int32)it->m_aRectangle.Top();
@@ -3450,10 +3473,7 @@ std::map< sal_Int32, sal_Int32 > PDFWriterImpl::emitEmbeddedFont( const ImplFont
// now we can actually write the font stream !
#if OSL_DEBUG_LEVEL > 1
- {
- OStringBuffer aLine( " PDFWriterImpl::emitEmbeddedFont" );
- emitComment( aLine.getStr() );
- }
+ emitComment( " PDFWriterImpl::emitEmbeddedFont" );
#endif
OStringBuffer aLine( 512 );
nStreamObject = createObject();
@@ -3879,12 +3899,9 @@ sal_Int32 PDFWriterImpl::createToUnicodeCMap( sal_uInt8* pEncoding,
delete pCodec;
#endif
-#if OSL_DEBUG_LEVEL > 1
- {
- OStringBuffer aLine( " PDFWriterImpl::createToUnicodeCMap" );
- emitComment( aLine.getStr() );
- }
-#endif
+ #if OSL_DEBUG_LEVEL > 1
+ emitComment( "PDFWriterImpl::createToUnicodeCMap" );
+ #endif
OStringBuffer aLine( 40 );
aLine.append( nStream );
@@ -4071,10 +4088,7 @@ bool PDFWriterImpl::emitFonts()
CHECK_RETURN( (osl_File_E_None == osl_setFilePos( aFontFile, osl_Pos_Absolut, 0 ) ) );
#if OSL_DEBUG_LEVEL > 1
- {
- OStringBuffer aLine1( " PDFWriterImpl::emitFonts" );
- emitComment( aLine1.getStr() );
- }
+ emitComment( "PDFWriterImpl::emitFonts" );
#endif
sal_Int32 nFontStream = createObject();
sal_Int32 nStreamLengthObject = createObject();
@@ -4645,18 +4659,20 @@ we check in the following sequence:
{
aLine.append( "/Launch/Win<</F" );
// INetURLObject is not good with UNC paths, use original path
- appendLiteralStringEncrypt( rLink.m_aURL, rLink.m_nObject, aLine );
+ appendLiteralStringEncrypt( rLink.m_aURL, rLink.m_nObject, aLine, osl_getThreadTextEncoding() );
aLine.append( ">>" );
}
else
{
- sal_Int32 nSetRelative = 0;
+ bool bSetRelative = false;
+ bool bFileSpec = false;
//check if relative file link is requested and if the protocol is 'file://'
if( m_aContext.RelFsys && eBaseProtocol == eTargetProtocol && eTargetProtocol == INET_PROT_FILE )
- nSetRelative++;
+ bSetRelative = true;
rtl::OUString aFragment = aTargetURL.GetMark( INetURLObject::NO_DECODE /*DECODE_WITH_CHARSET*/ ); //fragment as is,
if( nSetGoToRMode == 0 )
+ {
switch( m_aContext.DefaultLinkAction )
{
default:
@@ -4676,19 +4692,24 @@ we check in the following sequence:
eTargetProtocol != INET_PROT_FILE )
aLine.append( "/URI/URI" );
else
+ {
aLine.append( "/Launch/F" );
+ bFileSpec = true;
+ }
break;
}
+ }
//fragment are encoded in the same way as in the named destination processing
- rtl::OUString aURLNoMark = aTargetURL.GetURLNoMark( INetURLObject::DECODE_WITH_CHARSET );
if( nSetGoToRMode )
{//add the fragment
+ rtl::OUString aURLNoMark = aTargetURL.GetURLNoMark( INetURLObject::DECODE_WITH_CHARSET );
aLine.append("/GoToR");
aLine.append("/F");
- appendLiteralStringEncrypt( nSetRelative ? INetURLObject::GetRelURL( m_aContext.BaseURL, aURLNoMark,
+ bFileSpec = true;
+ appendLiteralStringEncrypt( bSetRelative ? INetURLObject::GetRelURL( m_aContext.BaseURL, aURLNoMark,
INetURLObject::WAS_ENCODED,
INetURLObject::DECODE_WITH_CHARSET ) :
- aURLNoMark, rLink.m_nObject, aLine );
+ aURLNoMark, rLink.m_nObject, aLine, osl_getThreadTextEncoding() );
if( aFragment.getLength() > 0 )
{
aLine.append("/D/");
@@ -4707,13 +4728,16 @@ we check in the following sequence:
//substitute the fragment
aTargetURL.SetMark( aLineLoc.getStr() );
}
- rtl::OUString aURL = aTargetURL.GetMainURL( (nSetRelative || eTargetProtocol == INET_PROT_FILE) ? INetURLObject::DECODE_WITH_CHARSET : INetURLObject::NO_DECODE );
+ rtl::OUString aURL = aTargetURL.GetMainURL( bFileSpec ? INetURLObject::DECODE_WITH_CHARSET : INetURLObject::NO_DECODE );
// check if we have a URL available, if the string is empty, set it as the original one
// if( aURL.getLength() == 0 )
// appendLiteralStringEncrypt( rLink.m_aURL , rLink.m_nObject, aLine );
// else
- appendLiteralStringEncrypt( nSetRelative ? INetURLObject::GetRelURL( m_aContext.BaseURL, aURL ) :
- aURL , rLink.m_nObject, aLine );
+ appendLiteralStringEncrypt( bSetRelative ? INetURLObject::GetRelURL( m_aContext.BaseURL, aURL,
+ INetURLObject::WAS_ENCODED,
+ bFileSpec ? INetURLObject::DECODE_WITH_CHARSET : INetURLObject::NO_DECODE
+ ) :
+ aURL , rLink.m_nObject, aLine, osl_getThreadTextEncoding() );
}
//<--- i56629
}
@@ -5369,12 +5393,9 @@ bool PDFWriterImpl::emitAppearances( PDFWidget& rWidget, OStringBuffer& rAnnotDi
pApppearanceStream->Seek( STREAM_SEEK_TO_BEGIN );
sal_Int32 nObject = createObject();
CHECK_RETURN( updateObject( nObject ) );
-#if OSL_DEBUG_LEVEL > 1
- {
- OStringBuffer aLine( " PDFWriterImpl::emitAppearances" );
- emitComment( aLine.getStr() );
- }
-#endif
+ #if OSL_DEBUG_LEVEL > 1
+ emitComment( "PDFWriterImpl::emitAppearances" );
+ #endif
OStringBuffer aLine;
aLine.append( nObject );
@@ -5617,7 +5638,7 @@ bool PDFWriterImpl::emitWidgetAnnotations()
{
// create a submit form action
aLine.append( "/AA<</D<</Type/Action/S/SubmitForm/F" );
- appendLiteralStringEncrypt( rWidget.m_aListEntries.front(), rWidget.m_nObject, aLine );
+ appendLiteralStringEncrypt( rWidget.m_aListEntries.front(), rWidget.m_nObject, aLine, osl_getThreadTextEncoding() );
aLine.append( "/Flags " );
sal_Int32 nFlags = 0;
@@ -9262,12 +9283,9 @@ bool PDFWriterImpl::writeTransparentObject( TransparencyEmit& rObject )
rObject.m_pContentStream->Seek( STREAM_SEEK_TO_END );
sal_uLong nSize = rObject.m_pContentStream->Tell();
rObject.m_pContentStream->Seek( STREAM_SEEK_TO_BEGIN );
-#if OSL_DEBUG_LEVEL > 1
- {
- OStringBuffer aLine( " PDFWriterImpl::writeTransparentObject" );
- emitComment( aLine.getStr() );
- }
-#endif
+ #if OSL_DEBUG_LEVEL > 1
+ emitComment( "PDFWriterImpl::writeTransparentObject" );
+ #endif
OStringBuffer aLine( 512 );
CHECK_RETURN( updateObject( rObject.m_nObject ) );
aLine.append( rObject.m_nObject );
@@ -9411,28 +9429,25 @@ bool PDFWriterImpl::writeGradientFunction( GradientEmit& rObject )
sal_Int32 nFunctionObject = createObject();
CHECK_RETURN( updateObject( nFunctionObject ) );
- OutputDevice* pRefDevice = getReferenceDevice();
- pRefDevice->Push( PUSH_ALL );
- if( rObject.m_aSize.Width() > pRefDevice->GetOutputSizePixel().Width() )
- rObject.m_aSize.Width() = pRefDevice->GetOutputSizePixel().Width();
- if( rObject.m_aSize.Height() > pRefDevice->GetOutputSizePixel().Height() )
- rObject.m_aSize.Height() = pRefDevice->GetOutputSizePixel().Height();
- pRefDevice->SetMapMode( MapMode( MAP_PIXEL ) );
- pRefDevice->DrawGradient( Rectangle( Point( 0, 0 ), rObject.m_aSize ), rObject.m_aGradient );
+ VirtualDevice aDev;
+ aDev.SetOutputSizePixel( rObject.m_aSize );
+ aDev.SetMapMode( MapMode( MAP_PIXEL ) );
+ if( m_aContext.ColorMode == PDFWriter::DrawGreyscale )
+ aDev.SetDrawMode( aDev.GetDrawMode() |
+ ( DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL | DRAWMODE_GRAYTEXT |
+ DRAWMODE_GRAYBITMAP | DRAWMODE_GRAYGRADIENT ) );
+ aDev.DrawGradient( Rectangle( Point( 0, 0 ), rObject.m_aSize ), rObject.m_aGradient );
- Bitmap aSample = pRefDevice->GetBitmap( Point( 0, 0 ), rObject.m_aSize );
+ Bitmap aSample = aDev.GetBitmap( Point( 0, 0 ), rObject.m_aSize );
BitmapReadAccess* pAccess = aSample.AcquireReadAccess();
AccessReleaser aReleaser( pAccess );
Size aSize = aSample.GetSizePixel();
sal_Int32 nStreamLengthObject = createObject();
-#if OSL_DEBUG_LEVEL > 1
- {
- OStringBuffer aLine( " PDFWriterImpl::writeGradientFunction" );
- emitComment( aLine.getStr() );
- }
-#endif
+ #if OSL_DEBUG_LEVEL > 1
+ emitComment( "PDFWriterImpl::writeGradientFunction" );
+ #endif
OStringBuffer aLine( 120 );
aLine.append( nFunctionObject );
aLine.append( " 0 obj\n"
@@ -9445,6 +9460,7 @@ bool PDFWriterImpl::writeGradientFunction( GradientEmit& rObject )
aLine.append( " ]\n"
"/BitsPerSample 8\n"
"/Range[ 0 1 0 1 0 1 ]\n"
+ "/Order 3\n"
"/Length " );
aLine.append( nStreamLengthObject );
aLine.append( " 0 R\n"
@@ -9460,7 +9476,7 @@ bool PDFWriterImpl::writeGradientFunction( GradientEmit& rObject )
checkAndEnableStreamEncryption( nFunctionObject );
beginCompression();
- for( int y = 0; y < aSize.Height(); y++ )
+ for( int y = aSize.Height()-1; y >= 0; y-- )
{
for( int x = 0; x < aSize.Width(); x++ )
{
@@ -9511,8 +9527,6 @@ bool PDFWriterImpl::writeGradientFunction( GradientEmit& rObject )
"endobj\n\n" );
CHECK_RETURN( writeBuffer( aLine.getStr(), aLine.getLength() ) );
- pRefDevice->Pop();
-
return true;
}
@@ -9541,12 +9555,9 @@ bool PDFWriterImpl::writeJPG( JPGEmit& rObject )
m_aErrors.insert( PDFWriter::Warning_Transparency_Omitted_PDF13 );
}
-#if OSL_DEBUG_LEVEL > 1
- {
- OStringBuffer aLine( " PDFWriterImpl::writeJPG" );
- emitComment( aLine.getStr() );
- }
-#endif
+ #if OSL_DEBUG_LEVEL > 1
+ emitComment( "PDFWriterImpl::writeJPG" );
+ #endif
OStringBuffer aLine(200);
aLine.append( rObject.m_nObject );
@@ -9666,26 +9677,32 @@ bool PDFWriterImpl::writeBitmapObject( BitmapEmit& rObject, bool bMask )
sal_Int32 nStreamLengthObject = createObject();
sal_Int32 nMaskObject = 0;
-#if OSL_DEBUG_LEVEL > 1
- {
- OStringBuffer aLine( " PDFWriterImpl::writeBitmapObject" );
- emitComment( aLine.getStr() );
- }
-#endif
+ #if OSL_DEBUG_LEVEL > 1
+ emitComment( "PDFWriterImpl::writeBitmapObject" );
+ #endif
OStringBuffer aLine(1024);
aLine.append( rObject.m_nObject );
aLine.append( " 0 obj\n"
"<</Type/XObject/Subtype/Image/Width " );
aLine.append( (sal_Int32)aBitmap.GetSizePixel().Width() );
- aLine.append( " /Height " );
+ aLine.append( "/Height " );
aLine.append( (sal_Int32)aBitmap.GetSizePixel().Height() );
- aLine.append( " /BitsPerComponent " );
+ aLine.append( "/BitsPerComponent " );
aLine.append( nBitsPerComponent );
- aLine.append( " /Length " );
+ aLine.append( "/Length " );
aLine.append( nStreamLengthObject );
aLine.append( " 0 R\n" );
#ifndef DEBUG_DISABLE_PDFCOMPRESSION
- aLine.append( "/Filter/FlateDecode" );
+ if( nBitsPerComponent != 1 )
+ {
+ aLine.append( "/Filter/FlateDecode" );
+ }
+ else
+ {
+ aLine.append( "/Filter/CCITTFaxDecode/DecodeParms<</K -1/BlackIs1 true/Columns " );
+ aLine.append( (sal_Int32)aBitmap.GetSizePixel().Width() );
+ aLine.append( ">>\n" );
+ }
#endif
if( ! bMask )
{
@@ -9753,7 +9770,7 @@ bool PDFWriterImpl::writeBitmapObject( BitmapEmit& rObject, bool bMask )
{
if( aBitmap.GetBitCount() == 1 )
{
- aLine.append( " /ImageMask true\n" );
+ aLine.append( "/ImageMask true\n" );
sal_Int32 nBlackIndex = pAccess->GetBestPaletteIndex( BitmapColor( Color( COL_BLACK ) ) );
DBG_ASSERT( nBlackIndex == 0 || nBlackIndex == 1, "wrong black index" );
if( nBlackIndex )
@@ -9815,33 +9832,42 @@ bool PDFWriterImpl::writeBitmapObject( BitmapEmit& rObject, bool bMask )
CHECK_RETURN( (osl_File_E_None == osl_getFilePos( m_aFile, &nStartPos )) );
checkAndEnableStreamEncryption( rObject.m_nObject );
- beginCompression();
- if( ! bTrueColor || pAccess->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
+#ifndef DEBUG_DISABLE_PDFCOMPRESSION
+ if( nBitsPerComponent == 1 )
{
- const int nScanLineBytes = 1 + ( pAccess->GetBitCount() * ( pAccess->Width() - 1 ) / 8U );
-
- for( int i = 0; i < pAccess->Height(); i++ )
- {
- CHECK_RETURN( writeBuffer( pAccess->GetScanline( i ), nScanLineBytes ) );
- }
+ writeG4Stream( pAccess );
}
else
+#endif
{
- const int nScanLineBytes = pAccess->Width()*3;
- boost::shared_array<sal_uInt8> pCol( new sal_uInt8[ nScanLineBytes ] );
- for( int y = 0; y < pAccess->Height(); y++ )
+ beginCompression();
+ if( ! bTrueColor || pAccess->GetScanlineFormat() == BMP_FORMAT_24BIT_TC_RGB )
{
- for( int x = 0; x < pAccess->Width(); x++ )
+ const int nScanLineBytes = 1 + ( pAccess->GetBitCount() * ( pAccess->Width() - 1 ) / 8U );
+
+ for( int i = 0; i < pAccess->Height(); i++ )
{
- BitmapColor aColor = pAccess->GetColor( y, x );
- pCol[3*x+0] = aColor.GetRed();
- pCol[3*x+1] = aColor.GetGreen();
- pCol[3*x+2] = aColor.GetBlue();
+ CHECK_RETURN( writeBuffer( pAccess->GetScanline( i ), nScanLineBytes ) );
}
- CHECK_RETURN( writeBuffer( pCol.get(), nScanLineBytes ) );
}
+ else
+ {
+ const int nScanLineBytes = pAccess->Width()*3;
+ boost::shared_array<sal_uInt8> pCol( new sal_uInt8[ nScanLineBytes ] );
+ for( int y = 0; y < pAccess->Height(); y++ )
+ {
+ for( int x = 0; x < pAccess->Width(); x++ )
+ {
+ BitmapColor aColor = pAccess->GetColor( y, x );
+ pCol[3*x+0] = aColor.GetRed();
+ pCol[3*x+1] = aColor.GetGreen();
+ pCol[3*x+2] = aColor.GetBlue();
+ }
+ CHECK_RETURN( writeBuffer( pCol.get(), nScanLineBytes ) );
+ }
+ }
+ endCompression();
}
- endCompression();
disableStreamEncryption();
sal_uInt64 nEndPos = 0;
@@ -9881,8 +9907,25 @@ void PDFWriterImpl::drawJPGBitmap( SvStream& rDCTData, bool bIsTrueColor, const
if( ! (rSizePixel.Width() && rSizePixel.Height()) )
return;
- SvMemoryStream* pStream = new SvMemoryStream;
rDCTData.Seek( 0 );
+ if( bIsTrueColor && m_aContext.ColorMode == PDFWriter::DrawGreyscale )
+ {
+ // need to convert to grayscale;
+ // load stream to bitmap and draw the bitmap instead
+ Graphic aGraphic;
+ GraphicConverter::Import( rDCTData, aGraphic, CVT_JPG );
+ Bitmap aBmp( aGraphic.GetBitmap() );
+ if( !!rMask && rMask.GetSizePixel() == aBmp.GetSizePixel() )
+ {
+ BitmapEx aBmpEx( aBmp, rMask );
+ drawBitmap( rTargetArea.TopLeft(), rTargetArea.GetSize(), aBmpEx );
+ }
+ else
+ drawBitmap( rTargetArea.TopLeft(), rTargetArea.GetSize(), aBmp );
+ return;
+ }
+
+ SvMemoryStream* pStream = new SvMemoryStream;
*pStream << rDCTData;
pStream->Seek( STREAM_SEEK_TO_END );
@@ -9973,18 +10016,28 @@ void PDFWriterImpl::drawBitmap( const Point& rDestPoint, const Size& rDestSize,
writeBuffer( aLine.getStr(), aLine.getLength() );
}
-const PDFWriterImpl::BitmapEmit& PDFWriterImpl::createBitmapEmit( const BitmapEx& rBitmap, bool bDrawMask )
+const PDFWriterImpl::BitmapEmit& PDFWriterImpl::createBitmapEmit( const BitmapEx& i_rBitmap, bool bDrawMask )
{
+ BitmapEx aBitmap( i_rBitmap );
+ if( m_aContext.ColorMode == PDFWriter::DrawGreyscale )
+ {
+ BmpConversion eConv = BMP_CONVERSION_8BIT_GREYS;
+ int nDepth = aBitmap.GetBitmap().GetBitCount();
+ if( nDepth <= 4 )
+ eConv = BMP_CONVERSION_4BIT_GREYS;
+ if( nDepth > 1 )
+ aBitmap.Convert( eConv );
+ }
BitmapID aID;
- aID.m_aPixelSize = rBitmap.GetSizePixel();
- aID.m_nSize = rBitmap.GetBitCount();
- aID.m_nChecksum = rBitmap.GetBitmap().GetChecksum();
+ aID.m_aPixelSize = aBitmap.GetSizePixel();
+ aID.m_nSize = aBitmap.GetBitCount();
+ aID.m_nChecksum = aBitmap.GetBitmap().GetChecksum();
aID.m_nMaskChecksum = 0;
- if( rBitmap.IsAlpha() )
- aID.m_nMaskChecksum = rBitmap.GetAlpha().GetChecksum();
+ if( aBitmap.IsAlpha() )
+ aID.m_nMaskChecksum = aBitmap.GetAlpha().GetChecksum();
else
{
- Bitmap aMask = rBitmap.GetMask();
+ Bitmap aMask = aBitmap.GetMask();
if( ! aMask.IsEmpty() )
aID.m_nMaskChecksum = aMask.GetChecksum();
}
@@ -9998,7 +10051,7 @@ const PDFWriterImpl::BitmapEmit& PDFWriterImpl::createBitmapEmit( const BitmapEx
{
m_aBitmaps.push_front( BitmapEmit() );
m_aBitmaps.front().m_aID = aID;
- m_aBitmaps.front().m_aBitmap = rBitmap;
+ m_aBitmaps.front().m_aBitmap = aBitmap;
m_aBitmaps.front().m_nObject = createObject();
m_aBitmaps.front().m_bDrawMask = bDrawMask;
it = m_aBitmaps.begin();
@@ -10061,15 +10114,16 @@ sal_Int32 PDFWriterImpl::createGradient( const Gradient& rGradient, const Size&
rSize ) );
// check if we already have this gradient
std::list<GradientEmit>::iterator it;
+ // rounding to point will generally lose some pixels
+ // round up to point boundary
+ aPtSize.Width()++;
+ aPtSize.Height()++;
for( it = m_aGradients.begin(); it != m_aGradients.end(); ++it )
{
if( it->m_aGradient == rGradient )
{
- if( it->m_aSize.Width() < aPtSize.Width() )
- it->m_aSize.Width() = aPtSize.Width();
- if( it->m_aSize.Height() <= aPtSize.Height() )
- it->m_aSize.Height() = aPtSize.Height();
- break;
+ if( it->m_aSize == aPtSize )
+ break;
}
}
if( it == m_aGradients.end() )
@@ -10144,12 +10198,12 @@ void PDFWriterImpl::drawGradient( const PolyPolygon& rPolyPoly, const Gradient&
return;
}
- sal_Int32 nGradient = createGradient( rGradient, rPolyPoly.GetBoundRect().GetSize() );
+ Rectangle aBoundRect = rPolyPoly.GetBoundRect();
+ sal_Int32 nGradient = createGradient( rGradient, aBoundRect.GetSize() );
updateGraphicsState();
- Rectangle aBoundRect = rPolyPoly.GetBoundRect();
- Point aTranslate = aBoundRect.BottomLeft() + Point( 0, 1 );
+ Point aTranslate = aBoundRect.BottomLeft();
int nPolygons = rPolyPoly.Count();
OStringBuffer aLine( 80*nPolygons );
diff --git a/vcl/source/gdi/pdfwriter_impl.hxx b/vcl/source/gdi/pdfwriter_impl.hxx
index 06ee068343a7..4d0f2234fc31 100644
--- a/vcl/source/gdi/pdfwriter_impl.hxx
+++ b/vcl/source/gdi/pdfwriter_impl.hxx
@@ -59,6 +59,7 @@ class ImplFontMetricData;
class FontSubsetInfo;
class ZCodec;
class EncHashTransporter;
+struct BitStreamState;
// the maximum password length
#define ENCRYPTED_PWD_SIZE 32
@@ -831,7 +832,7 @@ i12626
// test if the encryption is active, if yes than encrypt the unicode string and add to the OStringBuffer parameter
void appendUnicodeTextStringEncrypt( const rtl::OUString& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer );
- void appendLiteralStringEncrypt( const rtl::OUString& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer );
+ void appendLiteralStringEncrypt( const rtl::OUString& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer, rtl_TextEncoding nEnc = RTL_TEXTENCODING_ASCII_US );
void appendLiteralStringEncrypt( const rtl::OString& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer );
void appendLiteralStringEncrypt( rtl::OStringBuffer& rInString, const sal_Int32 nInObjectNumber, rtl::OStringBuffer& rOutBuffer );
@@ -1057,6 +1058,14 @@ i12626
void implWriteBitmapEx( const Point& rPoint, const Size& rSize, const BitmapEx& rBitmapEx,
VirtualDevice* pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& );
+ // helpers for CCITT 1bit bitmap stream
+ void putG4Bits( sal_uInt32 i_nLength, sal_uInt32 i_nCode, BitStreamState& io_rState );
+ void putG4Span( long i_nSpan, bool i_bWhitePixel, BitStreamState& io_rState );
+ void writeG4Stream( BitmapReadAccess* i_pBitmap );
+
+ // color helper functions
+ void appendStrokingColor( const Color& rColor, rtl::OStringBuffer& rBuffer );
+ void appendNonStrokingColor( const Color& rColor, rtl::OStringBuffer& rBuffer );
public:
PDFWriterImpl( const PDFWriter::PDFWriterContext& rContext, const com::sun::star::uno::Reference< com::sun::star::beans::XMaterialHolder >&, PDFWriter& );
~PDFWriterImpl();
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx
index 7d1c1994c012..1e4301b5a686 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -33,6 +33,7 @@
#include "vcl/virdev.hxx"
#include "vcl/gdimtf.hxx"
#include "vcl/metaact.hxx"
+#include "vcl/bmpacc.hxx"
#include "vcl/graph.hxx"
#include "svdata.hxx"
@@ -50,6 +51,8 @@
#include <rtl/digest.h>
+#undef USE_PDFGRADIENTS
+
using namespace vcl;
using namespace rtl;
using namespace com::sun::star;
@@ -61,7 +64,7 @@ using namespace com::sun::star::beans;
void PDFWriterImpl::implWriteGradient( const PolyPolygon& i_rPolyPoly, const Gradient& i_rGradient,
VirtualDevice* i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext )
{
- GDIMetaFile aTmpMtf;
+ GDIMetaFile aTmpMtf;
i_pDummyVDev->AddGradientActions( i_rPolyPoly.GetBoundRect(), i_rGradient, aTmpMtf );
@@ -143,6 +146,15 @@ void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSiz
const Size aSizePixel( aBitmapEx.GetSizePixel() );
if ( aSizePixel.Width() && aSizePixel.Height() )
{
+ if( m_aContext.ColorMode == PDFWriter::DrawGreyscale )
+ {
+ BmpConversion eConv = BMP_CONVERSION_8BIT_GREYS;
+ int nDepth = aBitmapEx.GetBitmap().GetBitCount();
+ if( nDepth <= 4 )
+ eConv = BMP_CONVERSION_4BIT_GREYS;
+ if( nDepth > 1 )
+ aBitmapEx.Convert( eConv );
+ }
sal_Bool bUseJPGCompression = !i_rContext.m_bOnlyLosslessCompression;
if ( ( aSizePixel.Width() < 32 ) || ( aSizePixel.Height() < 32 ) )
bUseJPGCompression = sal_False;
@@ -181,13 +193,13 @@ void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSiz
try
{
uno::Reference < io::XStream > xStream = new utl::OStreamWrapper( aStrm );
- Reference< io::XSeekable > xSeekable( xStream, UNO_QUERY_THROW );
- Reference< graphic::XGraphicProvider > xGraphicProvider( ImplGetSVData()->maAppData.mxMSF->createInstance(
+ uno::Reference< io::XSeekable > xSeekable( xStream, UNO_QUERY_THROW );
+ uno::Reference< graphic::XGraphicProvider > xGraphicProvider( ImplGetSVData()->maAppData.mxMSF->createInstance(
OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ) ), UNO_QUERY );
if ( xGraphicProvider.is() )
{
- Reference< graphic::XGraphic > xGraphic( aGraphic.GetXGraphic() );
- Reference < io::XOutputStream > xOut( xStream->getOutputStream() );
+ uno::Reference< graphic::XGraphic > xGraphic( aGraphic.GetXGraphic() );
+ uno::Reference < io::XOutputStream > xOut( xStream->getOutputStream() );
rtl::OUString aMimeType( ::rtl::OUString::createFromAscii( "image/jpeg" ) );
uno::Sequence< beans::PropertyValue > aOutMediaProperties( 3 );
aOutMediaProperties[0].Name = ::rtl::OUString::createFromAscii( "OutputStream" );
@@ -210,7 +222,7 @@ void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSiz
Sequence< PropertyValue > aArgs( 1 );
aArgs[ 0 ].Name = ::rtl::OUString::createFromAscii( "InputStream" );
aArgs[ 0 ].Value <<= xStream;
- Reference< XPropertySet > xPropSet( xGraphicProvider->queryGraphicDescriptor( aArgs ) );
+ uno::Reference< XPropertySet > xPropSet( xGraphicProvider->queryGraphicDescriptor( aArgs ) );
if ( xPropSet.is() )
{
sal_Int16 nBitsPerPixel = 24;
@@ -357,16 +369,23 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa
case( META_GRADIENT_ACTION ):
{
const MetaGradientAction* pA = (const MetaGradientAction*) pAction;
+ #ifdef USE_PDFGRADIENTS
+ m_rOuterFace.DrawGradient( pA->GetRect(), pA->GetGradient() );
+ #else
const PolyPolygon aPolyPoly( pA->GetRect() );
-
implWriteGradient( aPolyPoly, pA->GetGradient(), pDummyVDev, i_rContext );
+ #endif
}
break;
case( META_GRADIENTEX_ACTION ):
{
const MetaGradientExAction* pA = (const MetaGradientExAction*) pAction;
+ #ifdef USE_PDFGRADIENTS
+ m_rOuterFace.DrawGradient( pA->GetPolyPolygon(), pA->GetGradient() );
+ #else
implWriteGradient( pA->GetPolyPolygon(), pA->GetGradient(), pDummyVDev, i_rContext );
+ #endif
}
break;
@@ -521,7 +540,13 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& i_rMtf, vcl::PDFExtOutDevDa
}
if( pGradAction )
+ {
+ #if USE_PDFGRADIENTS
+ m_rOuterFace.DrawGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient() );
+ #else
implWriteGradient( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), pDummyVDev, i_rContext );
+ #endif
+ }
}
else
{
@@ -1541,3 +1566,475 @@ bool PDFWriterImpl::computeUDictionaryValue( EncHashTransporter* i_pTransporter,
/* end i12626 methods */
+static const long unsetRun[256] =
+{
+ 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */
+};
+
+static const long setRun[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */
+};
+
+inline bool isSet( const Scanline i_pLine, long i_nIndex )
+{
+ return (i_pLine[ i_nIndex/8 ] & (0x80 >> (i_nIndex&7))) != 0;
+}
+
+long findBitRun( const Scanline i_pLine, long i_nStartIndex, long i_nW, bool i_bSet )
+{
+ if( i_nStartIndex < 0 )
+ return i_nW;
+
+ long nIndex = i_nStartIndex;
+ if( nIndex < i_nW )
+ {
+ const sal_uInt8 * pByte = static_cast<sal_uInt8*>(i_pLine) + (nIndex/8);
+ sal_uInt8 nByte = *pByte;
+
+ // run up to byte boundary
+ long nBitInByte = (nIndex & 7);
+ if( nBitInByte )
+ {
+ sal_uInt8 nMask = 0x80 >> nBitInByte;
+ while( nBitInByte != 8 )
+ {
+ if( (nByte & nMask) != (i_bSet ? nMask : 0) )
+ return nIndex < i_nW ? nIndex : i_nW;
+ nMask = nMask >> 1;
+ nBitInByte++;
+ nIndex++;
+ }
+ if( nIndex < i_nW )
+ {
+ pByte++;
+ nByte = *pByte;
+ }
+ }
+
+ sal_uInt8 nRunByte;
+ const long* pRunTable;
+ if( i_bSet )
+ {
+ nRunByte = 0xff;
+ pRunTable = setRun;
+ }
+ else
+ {
+ nRunByte = 0;
+ pRunTable = unsetRun;
+ }
+
+ while( nByte == nRunByte && nIndex < i_nW )
+ {
+ nIndex += 8;
+ pByte++;
+ nByte = *pByte;
+ }
+ if( nIndex < i_nW )
+ {
+ nIndex += pRunTable[nByte];
+ }
+ }
+ return nIndex < i_nW ? nIndex : i_nW;
+}
+
+struct BitStreamState
+{
+ sal_uInt8 mnBuffer;
+ sal_uInt32 mnNextBitPos;
+
+ BitStreamState()
+ : mnBuffer( 0 )
+ , mnNextBitPos( 8 )
+ {
+ }
+
+ const sal_uInt8* getByte() const { return &mnBuffer; }
+ void flush() { mnNextBitPos = 8; mnBuffer = 0; }
+};
+
+void PDFWriterImpl::putG4Bits( sal_uInt32 i_nLength, sal_uInt32 i_nCode, BitStreamState& io_rState )
+{
+ while( i_nLength > io_rState.mnNextBitPos )
+ {
+ io_rState.mnBuffer |= static_cast<sal_uInt8>( i_nCode >> (i_nLength - io_rState.mnNextBitPos) );
+ i_nLength -= io_rState.mnNextBitPos;
+ writeBuffer( io_rState.getByte(), 1 );
+ io_rState.flush();
+ }
+ OSL_ASSERT( i_nLength < 9 );
+ static const unsigned int msbmask[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
+ io_rState.mnBuffer |= static_cast<sal_uInt8>( (i_nCode & msbmask[i_nLength]) << (io_rState.mnNextBitPos - i_nLength) );
+ io_rState.mnNextBitPos -= i_nLength;
+ if( io_rState.mnNextBitPos == 0 )
+ {
+ writeBuffer( io_rState.getByte(), 1 );
+ io_rState.flush();
+ }
+}
+
+struct PixelCode
+{
+ sal_uInt32 mnEncodedPixels;
+ sal_uInt32 mnCodeBits;
+ sal_uInt32 mnCode;
+};
+
+static const PixelCode WhitePixelCodes[] =
+{
+ { 0, 8, 0x35 }, // 0011 0101
+ { 1, 6, 0x7 }, // 0001 11
+ { 2, 4, 0x7 }, // 0111
+ { 3, 4, 0x8 }, // 1000
+ { 4, 4, 0xB }, // 1011
+ { 5, 4, 0xC }, // 1100
+ { 6, 4, 0xE }, // 1110
+ { 7, 4, 0xF }, // 1111
+ { 8, 5, 0x13 }, // 1001 1
+ { 9, 5, 0x14 }, // 1010 0
+ { 10, 5, 0x7 }, // 0011 1
+ { 11, 5, 0x8 }, // 0100 0
+ { 12, 6, 0x8 }, // 0010 00
+ { 13, 6, 0x3 }, // 0000 11
+ { 14, 6, 0x34 }, // 1101 00
+ { 15, 6, 0x35 }, // 1101 01
+ { 16, 6, 0x2A }, // 1010 10
+ { 17, 6, 0x2B }, // 1010 11
+ { 18, 7, 0x27 }, // 0100 111
+ { 19, 7, 0xC }, // 0001 100
+ { 20, 7, 0x8 }, // 0001 000
+ { 21, 7, 0x17 }, // 0010 111
+ { 22, 7, 0x3 }, // 0000 011
+ { 23, 7, 0x4 }, // 0000 100
+ { 24, 7, 0x28 }, // 0101 000
+ { 25, 7, 0x2B }, // 0101 011
+ { 26, 7, 0x13 }, // 0010 011
+ { 27, 7, 0x24 }, // 0100 100
+ { 28, 7, 0x18 }, // 0011 000
+ { 29, 8, 0x2 }, // 0000 0010
+ { 30, 8, 0x3 }, // 0000 0011
+ { 31, 8, 0x1A }, // 0001 1010
+ { 32, 8, 0x1B }, // 0001 1011
+ { 33, 8, 0x12 }, // 0001 0010
+ { 34, 8, 0x13 }, // 0001 0011
+ { 35, 8, 0x14 }, // 0001 0100
+ { 36, 8, 0x15 }, // 0001 0101
+ { 37, 8, 0x16 }, // 0001 0110
+ { 38, 8, 0x17 }, // 0001 0111
+ { 39, 8, 0x28 }, // 0010 1000
+ { 40, 8, 0x29 }, // 0010 1001
+ { 41, 8, 0x2A }, // 0010 1010
+ { 42, 8, 0x2B }, // 0010 1011
+ { 43, 8, 0x2C }, // 0010 1100
+ { 44, 8, 0x2D }, // 0010 1101
+ { 45, 8, 0x4 }, // 0000 0100
+ { 46, 8, 0x5 }, // 0000 0101
+ { 47, 8, 0xA }, // 0000 1010
+ { 48, 8, 0xB }, // 0000 1011
+ { 49, 8, 0x52 }, // 0101 0010
+ { 50, 8, 0x53 }, // 0101 0011
+ { 51, 8, 0x54 }, // 0101 0100
+ { 52, 8, 0x55 }, // 0101 0101
+ { 53, 8, 0x24 }, // 0010 0100
+ { 54, 8, 0x25 }, // 0010 0101
+ { 55, 8, 0x58 }, // 0101 1000
+ { 56, 8, 0x59 }, // 0101 1001
+ { 57, 8, 0x5A }, // 0101 1010
+ { 58, 8, 0x5B }, // 0101 1011
+ { 59, 8, 0x4A }, // 0100 1010
+ { 60, 8, 0x4B }, // 0100 1011
+ { 61, 8, 0x32 }, // 0011 0010
+ { 62, 8, 0x33 }, // 0011 0011
+ { 63, 8, 0x34 }, // 0011 0100
+ { 64, 5, 0x1B }, // 1101 1
+ { 128, 5, 0x12 }, // 1001 0
+ { 192, 6, 0x17 }, // 0101 11
+ { 256, 7, 0x37 }, // 0110 111
+ { 320, 8, 0x36 }, // 0011 0110
+ { 384, 8, 0x37 }, // 0011 0111
+ { 448, 8, 0x64 }, // 0110 0100
+ { 512, 8, 0x65 }, // 0110 0101
+ { 576, 8, 0x68 }, // 0110 1000
+ { 640, 8, 0x67 }, // 0110 0111
+ { 704, 9, 0xCC }, // 0110 0110 0
+ { 768, 9, 0xCD }, // 0110 0110 1
+ { 832, 9, 0xD2 }, // 0110 1001 0
+ { 896, 9, 0xD3 }, // 0110 1001 1
+ { 960, 9, 0xD4 }, // 0110 1010 0
+ { 1024, 9, 0xD5 }, // 0110 1010 1
+ { 1088, 9, 0xD6 }, // 0110 1011 0
+ { 1152, 9, 0xD7 }, // 0110 1011 1
+ { 1216, 9, 0xD8 }, // 0110 1100 0
+ { 1280, 9, 0xD9 }, // 0110 1100 1
+ { 1344, 9, 0xDA }, // 0110 1101 0
+ { 1408, 9, 0xDB }, // 0110 1101 1
+ { 1472, 9, 0x98 }, // 0100 1100 0
+ { 1536, 9, 0x99 }, // 0100 1100 1
+ { 1600, 9, 0x9A }, // 0100 1101 0
+ { 1664, 6, 0x18 }, // 0110 00
+ { 1728, 9, 0x9B }, // 0100 1101 1
+ { 1792, 11, 0x8 }, // 0000 0001 000
+ { 1856, 11, 0xC }, // 0000 0001 100
+ { 1920, 11, 0xD }, // 0000 0001 101
+ { 1984, 12, 0x12 }, // 0000 0001 0010
+ { 2048, 12, 0x13 }, // 0000 0001 0011
+ { 2112, 12, 0x14 }, // 0000 0001 0100
+ { 2176, 12, 0x15 }, // 0000 0001 0101
+ { 2240, 12, 0x16 }, // 0000 0001 0110
+ { 2304, 12, 0x17 }, // 0000 0001 0111
+ { 2368, 12, 0x1C }, // 0000 0001 1100
+ { 2432, 12, 0x1D }, // 0000 0001 1101
+ { 2496, 12, 0x1E }, // 0000 0001 1110
+ { 2560, 12, 0x1F } // 0000 0001 1111
+};
+
+static const PixelCode BlackPixelCodes[] =
+{
+ { 0, 10, 0x37 }, // 0000 1101 11
+ { 1, 3, 0x2 }, // 010
+ { 2, 2, 0x3 }, // 11
+ { 3, 2, 0x2 }, // 10
+ { 4, 3, 0x3 }, // 011
+ { 5, 4, 0x3 }, // 0011
+ { 6, 4, 0x2 }, // 0010
+ { 7, 5, 0x3 }, // 0001 1
+ { 8, 6, 0x5 }, // 0001 01
+ { 9, 6, 0x4 }, // 0001 00
+ { 10, 7, 0x4 }, // 0000 100
+ { 11, 7, 0x5 }, // 0000 101
+ { 12, 7, 0x7 }, // 0000 111
+ { 13, 8, 0x4 }, // 0000 0100
+ { 14, 8, 0x7 }, // 0000 0111
+ { 15, 9, 0x18 }, // 0000 1100 0
+ { 16, 10, 0x17 }, // 0000 0101 11
+ { 17, 10, 0x18 }, // 0000 0110 00
+ { 18, 10, 0x8 }, // 0000 0010 00
+ { 19, 11, 0x67 }, // 0000 1100 111
+ { 20, 11, 0x68 }, // 0000 1101 000
+ { 21, 11, 0x6C }, // 0000 1101 100
+ { 22, 11, 0x37 }, // 0000 0110 111
+ { 23, 11, 0x28 }, // 0000 0101 000
+ { 24, 11, 0x17 }, // 0000 0010 111
+ { 25, 11, 0x18 }, // 0000 0011 000
+ { 26, 12, 0xCA }, // 0000 1100 1010
+ { 27, 12, 0xCB }, // 0000 1100 1011
+ { 28, 12, 0xCC }, // 0000 1100 1100
+ { 29, 12, 0xCD }, // 0000 1100 1101
+ { 30, 12, 0x68 }, // 0000 0110 1000
+ { 31, 12, 0x69 }, // 0000 0110 1001
+ { 32, 12, 0x6A }, // 0000 0110 1010
+ { 33, 12, 0x6B }, // 0000 0110 1011
+ { 34, 12, 0xD2 }, // 0000 1101 0010
+ { 35, 12, 0xD3 }, // 0000 1101 0011
+ { 36, 12, 0xD4 }, // 0000 1101 0100
+ { 37, 12, 0xD5 }, // 0000 1101 0101
+ { 38, 12, 0xD6 }, // 0000 1101 0110
+ { 39, 12, 0xD7 }, // 0000 1101 0111
+ { 40, 12, 0x6C }, // 0000 0110 1100
+ { 41, 12, 0x6D }, // 0000 0110 1101
+ { 42, 12, 0xDA }, // 0000 1101 1010
+ { 43, 12, 0xDB }, // 0000 1101 1011
+ { 44, 12, 0x54 }, // 0000 0101 0100
+ { 45, 12, 0x55 }, // 0000 0101 0101
+ { 46, 12, 0x56 }, // 0000 0101 0110
+ { 47, 12, 0x57 }, // 0000 0101 0111
+ { 48, 12, 0x64 }, // 0000 0110 0100
+ { 49, 12, 0x65 }, // 0000 0110 0101
+ { 50, 12, 0x52 }, // 0000 0101 0010
+ { 51, 12, 0x53 }, // 0000 0101 0011
+ { 52, 12, 0x24 }, // 0000 0010 0100
+ { 53, 12, 0x37 }, // 0000 0011 0111
+ { 54, 12, 0x38 }, // 0000 0011 1000
+ { 55, 12, 0x27 }, // 0000 0010 0111
+ { 56, 12, 0x28 }, // 0000 0010 1000
+ { 57, 12, 0x58 }, // 0000 0101 1000
+ { 58, 12, 0x59 }, // 0000 0101 1001
+ { 59, 12, 0x2B }, // 0000 0010 1011
+ { 60, 12, 0x2C }, // 0000 0010 1100
+ { 61, 12, 0x5A }, // 0000 0101 1010
+ { 62, 12, 0x66 }, // 0000 0110 0110
+ { 63, 12, 0x67 }, // 0000 0110 0111
+ { 64, 10, 0xF }, // 0000 0011 11
+ { 128, 12, 0xC8 }, // 0000 1100 1000
+ { 192, 12, 0xC9 }, // 0000 1100 1001
+ { 256, 12, 0x5B }, // 0000 0101 1011
+ { 320, 12, 0x33 }, // 0000 0011 0011
+ { 384, 12, 0x34 }, // 0000 0011 0100
+ { 448, 12, 0x35 }, // 0000 0011 0101
+ { 512, 13, 0x6C }, // 0000 0011 0110 0
+ { 576, 13, 0x6D }, // 0000 0011 0110 1
+ { 640, 13, 0x4A }, // 0000 0010 0101 0
+ { 704, 13, 0x4B }, // 0000 0010 0101 1
+ { 768, 13, 0x4C }, // 0000 0010 0110 0
+ { 832, 13, 0x4D }, // 0000 0010 0110 1
+ { 896, 13, 0x72 }, // 0000 0011 1001 0
+ { 960, 13, 0x73 }, // 0000 0011 1001 1
+ { 1024, 13, 0x74 }, // 0000 0011 1010 0
+ { 1088, 13, 0x75 }, // 0000 0011 1010 1
+ { 1152, 13, 0x76 }, // 0000 0011 1011 0
+ { 1216, 13, 0x77 }, // 0000 0011 1011 1
+ { 1280, 13, 0x52 }, // 0000 0010 1001 0
+ { 1344, 13, 0x53 }, // 0000 0010 1001 1
+ { 1408, 13, 0x54 }, // 0000 0010 1010 0
+ { 1472, 13, 0x55 }, // 0000 0010 1010 1
+ { 1536, 13, 0x5A }, // 0000 0010 1101 0
+ { 1600, 13, 0x5B }, // 0000 0010 1101 1
+ { 1664, 13, 0x64 }, // 0000 0011 0010 0
+ { 1728, 13, 0x65 }, // 0000 0011 0010 1
+ { 1792, 11, 0x8 }, // 0000 0001 000
+ { 1856, 11, 0xC }, // 0000 0001 100
+ { 1920, 11, 0xD }, // 0000 0001 101
+ { 1984, 12, 0x12 }, // 0000 0001 0010
+ { 2048, 12, 0x13 }, // 0000 0001 0011
+ { 2112, 12, 0x14 }, // 0000 0001 0100
+ { 2176, 12, 0x15 }, // 0000 0001 0101
+ { 2240, 12, 0x16 }, // 0000 0001 0110
+ { 2304, 12, 0x17 }, // 0000 0001 0111
+ { 2368, 12, 0x1C }, // 0000 0001 1100
+ { 2432, 12, 0x1D }, // 0000 0001 1101
+ { 2496, 12, 0x1E }, // 0000 0001 1110
+ { 2560, 12, 0x1F } // 0000 0001 1111
+};
+
+
+void PDFWriterImpl::putG4Span( long i_nSpan, bool i_bWhitePixel, BitStreamState& io_rState )
+{
+ const PixelCode* pTable = i_bWhitePixel ? WhitePixelCodes : BlackPixelCodes;
+ // maximum encoded span is 2560 consecutive pixels
+ while( i_nSpan > 2623 )
+ {
+ // write 2560 bits, that is entry (63 + (2560 >> 6)) == 103 in the appropriate table
+ putG4Bits( pTable[103].mnCodeBits, pTable[103].mnCode, io_rState );
+ i_nSpan -= pTable[103].mnEncodedPixels;
+ }
+ // write multiples of 64 pixels up to 2560
+ if( i_nSpan > 63 )
+ {
+ sal_uInt32 nTabIndex = 63 + (i_nSpan >> 6);
+ OSL_ASSERT( pTable[nTabIndex].mnEncodedPixels == static_cast<sal_uInt32>(64*(i_nSpan >> 6)) );
+ putG4Bits( pTable[nTabIndex].mnCodeBits, pTable[nTabIndex].mnCode, io_rState );
+ i_nSpan -= pTable[nTabIndex].mnEncodedPixels;
+ }
+ putG4Bits( pTable[i_nSpan].mnCodeBits, pTable[i_nSpan].mnCode, io_rState );
+}
+
+void PDFWriterImpl::writeG4Stream( BitmapReadAccess* i_pBitmap )
+{
+ long nW = i_pBitmap->Width();
+ long nH = i_pBitmap->Height();
+ if( nW <= 0 || nH <= 0 )
+ return;
+ if( i_pBitmap->GetBitCount() != 1 )
+ return;
+
+ BitStreamState aBitState;
+
+ // the first reference line is virtual and completely empty
+ const Scanline pFirstRefLine = (Scanline)rtl_allocateZeroMemory( nW/8 + 1 );
+ Scanline pRefLine = pFirstRefLine;
+ for( long nY = 0; nY < nH; nY++ )
+ {
+ const Scanline pCurLine = i_pBitmap->GetScanline( nY );
+ long nLineIndex = 0;
+ bool bRunSet = (*pCurLine & 0x80) ? true : false;
+ bool bRefSet = (*pRefLine & 0x80) ? true : false;
+ long nRunIndex1 = bRunSet ? 0 : findBitRun( pCurLine, 0, nW, bRunSet );
+ long nRefIndex1 = bRefSet ? 0 : findBitRun( pRefLine, 0, nW, bRefSet );
+ for( ; nLineIndex < nW; )
+ {
+ long nRefIndex2 = findBitRun( pRefLine, nRefIndex1, nW, isSet( pRefLine, nRefIndex1 ) );
+ if( nRefIndex2 >= nRunIndex1 )
+ {
+ long nDiff = nRefIndex1 - nRunIndex1;
+ if( -3 <= nDiff && nDiff <= 3 )
+ { // vertical coding
+ static const struct
+ {
+ sal_uInt32 mnCodeBits;
+ sal_uInt32 mnCode;
+ } VerticalCodes[7] = {
+ { 7, 0x03 }, // 0000 011
+ { 6, 0x03 }, // 0000 11
+ { 3, 0x03 }, // 011
+ { 1, 0x1 }, // 1
+ { 3, 0x2 }, // 010
+ { 6, 0x02 }, // 0000 10
+ { 7, 0x02 } // 0000 010
+ };
+ // convert to index
+ nDiff += 3;
+
+ // emit diff code
+ putG4Bits( VerticalCodes[nDiff].mnCodeBits, VerticalCodes[nDiff].mnCode, aBitState );
+ nLineIndex = nRunIndex1;
+ }
+ else
+ { // difference too large, horizontal coding
+ // emit horz code 001
+ putG4Bits( 3, 0x1, aBitState );
+ long nRunIndex2 = findBitRun( pCurLine, nRunIndex1, nW, isSet( pCurLine, nRunIndex1 ) );
+ bool bWhiteFirst = ( nLineIndex + nRunIndex1 == 0 || ! isSet( pCurLine, nLineIndex ) );
+ putG4Span( nRunIndex1 - nLineIndex, bWhiteFirst, aBitState );
+ putG4Span( nRunIndex2 - nRunIndex1, ! bWhiteFirst, aBitState );
+ nLineIndex = nRunIndex2;
+ }
+ }
+ else
+ { // emit pass code 0001
+ putG4Bits( 4, 0x1, aBitState );
+ nLineIndex = nRefIndex2;
+ }
+ if( nLineIndex < nW )
+ {
+ bool bSet = isSet( pCurLine, nLineIndex );
+ nRunIndex1 = findBitRun( pCurLine, nLineIndex, nW, bSet );
+ nRefIndex1 = findBitRun( pRefLine, nLineIndex, nW, ! bSet );
+ nRefIndex1 = findBitRun( pRefLine, nRefIndex1, nW, bSet );
+ }
+ }
+
+ // the current line is the reference for the next line
+ pRefLine = pCurLine;
+ }
+ // terminate strip with EOFB
+ putG4Bits( 12, 1, aBitState );
+ putG4Bits( 12, 1, aBitState );
+ if( aBitState.mnNextBitPos != 8 )
+ {
+ writeBuffer( aBitState.getByte(), 1 );
+ aBitState.flush();
+ }
+
+ rtl_freeMemory( pFirstRefLine );
+}
diff --git a/vcl/source/gdi/print.cxx b/vcl/source/gdi/print.cxx
index 4a09d30299e9..daf0d6352c46 100644
--- a/vcl/source/gdi/print.cxx
+++ b/vcl/source/gdi/print.cxx
@@ -32,6 +32,7 @@
#include <list>
#include <tools/debug.hxx>
+#include <tools/resary.hxx>
#include <tools/stream.hxx>
#include <tools/vcompat.hxx>
@@ -43,6 +44,7 @@
#include <vcl/gdimtf.hxx>
#include <vcl/metaact.hxx>
#include <vcl/print.hxx>
+#include <vcl/svids.hrc>
#include <salinst.hxx>
#include <salgdi.hxx>
@@ -1278,6 +1280,48 @@ int Printer::GetPaperInfoCount() const
// -----------------------------------------------------------------------
+rtl::OUString Printer::GetPaperName( Paper ePaper )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if( ! pSVData->mpPaperNames )
+ {
+ pSVData->mpPaperNames = new std::hash_map< int, rtl::OUString >();
+ if( ImplGetResMgr() )
+ {
+ ResStringArray aPaperStrings( VclResId( RID_STR_PAPERNAMES ) );
+ static const int PaperIndex[] =
+ {
+ PAPER_A0, PAPER_A1, PAPER_A2, PAPER_A3, PAPER_A4, PAPER_A5,
+ PAPER_B4_ISO, PAPER_B5_ISO, PAPER_LETTER, PAPER_LEGAL, PAPER_TABLOID,
+ PAPER_USER, PAPER_B6_ISO, PAPER_ENV_C4, PAPER_ENV_C5, PAPER_ENV_C6, PAPER_ENV_C65,
+ PAPER_ENV_DL, PAPER_SLIDE_DIA, PAPER_SCREEN, PAPER_C, PAPER_D, PAPER_E,
+ PAPER_EXECUTIVE, PAPER_FANFOLD_LEGAL_DE, PAPER_ENV_MONARCH, PAPER_ENV_PERSONAL,
+ PAPER_ENV_9, PAPER_ENV_10, PAPER_ENV_11, PAPER_ENV_12, PAPER_KAI16,
+ PAPER_KAI32, PAPER_KAI32BIG, PAPER_B4_JIS, PAPER_B5_JIS, PAPER_B6_JIS
+ };
+ OSL_ENSURE( sal_uInt32(sizeof(PaperIndex)/sizeof(PaperIndex[0])) == aPaperStrings.Count(), "localized paper name count wrong" );
+ for( int i = 0; i < int(sizeof(PaperIndex)/sizeof(PaperIndex[0])); i++ )
+ (*pSVData->mpPaperNames)[PaperIndex[i]] = aPaperStrings.GetString(i);
+ }
+ }
+
+ std::hash_map<int,rtl::OUString>::const_iterator it = pSVData->mpPaperNames->find( (int)ePaper );
+ return (it != pSVData->mpPaperNames->end()) ? it->second : rtl::OUString();
+}
+
+// -----------------------------------------------------------------------
+
+rtl::OUString Printer::GetPaperName( bool i_bPaperUser ) const
+{
+ Size aPageSize = PixelToLogic( GetPaperSizePixel(), MAP_100TH_MM );
+ Paper ePaper = ImplGetPaperFormat( aPageSize.Width(), aPageSize.Height() );
+ if( ePaper == PAPER_USER )
+ ePaper = ImplGetPaperFormat( aPageSize.Height(), aPageSize.Width() );
+ return (ePaper != PAPER_USER || i_bPaperUser ) ? GetPaperName( ePaper ) : rtl::OUString();
+}
+
+// -----------------------------------------------------------------------
+
const PaperInfo& Printer::GetPaperInfo( int nPaper ) const
{
if( ! mpInfoPrinter )
diff --git a/vcl/source/gdi/print2.cxx b/vcl/source/gdi/print2.cxx
index d69d8e38be93..51ca67bff9d7 100644
--- a/vcl/source/gdi/print2.cxx
+++ b/vcl/source/gdi/print2.cxx
@@ -858,13 +858,12 @@ bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf,
++nActionNum;
}
- ConnectedComponentsList aCCList; // list containing distinct sets of connected components as elements.
+ // clean up aMapModeVDev
+ sal_uInt32 nCount = aMapModeVDev.GetGCStackDepth();
+ while( nCount-- )
+ aMapModeVDev.Pop();
- // create an OutputDevice to record mapmode changes and the like
- VirtualDevice aMapModeVDev2;
- aMapModeVDev2.mnDPIX = mnDPIX;
- aMapModeVDev2.mnDPIY = mnDPIY;
- aMapModeVDev2.EnableOutput(sal_False);
+ ConnectedComponentsList aCCList; // list containing distinct sets of connected components as elements.
// fast-forward until one after the last background action
// (need to reconstruct map mode vdev state)
@@ -879,7 +878,7 @@ bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf,
pCurrAct, nActionNum) );
// execute action to get correct MapModes etc.
- pCurrAct->Execute( &aMapModeVDev2 );
+ pCurrAct->Execute( &aMapModeVDev );
pCurrAct=const_cast<GDIMetaFile&>(rInMtf).NextAction();
++nActionNum;
}
@@ -896,10 +895,10 @@ bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf,
pCurrAct=const_cast<GDIMetaFile&>(rInMtf).NextAction(), ++nActionNum )
{
// execute action to get correct MapModes etc.
- pCurrAct->Execute( &aMapModeVDev2 );
+ pCurrAct->Execute( &aMapModeVDev );
// cache bounds of current action
- const Rectangle aBBCurrAct( ImplCalcActionBounds(*pCurrAct, aMapModeVDev2) );
+ const Rectangle aBBCurrAct( ImplCalcActionBounds(*pCurrAct, aMapModeVDev) );
// accumulate collected bounds here, initialize with current action
Rectangle aTotalBounds( aBBCurrAct ); // thus,
@@ -928,7 +927,7 @@ bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf,
// not be considered for connected components,
// too. Just put each of them into a separate
// component.
- aTotalComponents.bIsFullyTransparent = !ImplIsNotTransparent(*pCurrAct, aMapModeVDev2);
+ aTotalComponents.bIsFullyTransparent = !ImplIsNotTransparent(*pCurrAct, aMapModeVDev);
if( !aBBCurrAct.IsEmpty() &&
!aTotalComponents.bIsFullyTransparent )
@@ -1314,18 +1313,16 @@ bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf,
}
}
+ // clean up aMapModeVDev
+ nCount = aMapModeVDev.GetGCStackDepth();
+ while( nCount-- )
+ aMapModeVDev.Pop();
+
//
// STAGE 4: Copy actions to output metafile
// ========================================
//
- // create an OutputDevice to record color settings, mapmode
- // changes and the like
- VirtualDevice aMapModeVDev3;
- aMapModeVDev3.mnDPIX = mnDPIX;
- aMapModeVDev3.mnDPIY = mnDPIY;
- aMapModeVDev3.EnableOutput(sal_False);
-
// iterate over all actions and duplicate the ones not in a
// special aCCList member into rOutMtf
for( pCurrAct=const_cast<GDIMetaFile&>(rInMtf).FirstAction(), nActionNum=0;
@@ -1353,7 +1350,7 @@ bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf,
// given background color
ImplConvertTransparentAction(rOutMtf,
*pCurrAct,
- aMapModeVDev3,
+ aMapModeVDev,
aBackgroundComponent.aBgColor);
}
else
@@ -1362,7 +1359,7 @@ bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf,
rOutMtf.AddAction( ( pCurrAct->Duplicate(), pCurrAct ) );
}
- pCurrAct->Execute(&aMapModeVDev3);
+ pCurrAct->Execute(&aMapModeVDev);
}
}
diff --git a/vcl/source/gdi/print3.cxx b/vcl/source/gdi/print3.cxx
index 35356913d0d2..3bc47e6cf8fb 100755
--- a/vcl/source/gdi/print3.cxx
+++ b/vcl/source/gdi/print3.cxx
@@ -334,26 +334,13 @@ void Printer::ImplPrintJob( const boost::shared_ptr<PrinterController>& i_pContr
// setup printer
- // if no specific printer is already set, create one
-
- // #i108686#
- // in case of a UI (platform independent or system dialog) print job, make the printer persistent over jobs
- // however if no printer was already set by the print job's originator,
- // and this is an API job, then use the system default location (because
- // this is the only sensible default available if the user has no means of changing
- // the destination
+ // #i114306# changed behavior back from persistence
+ // if no specific printer is already set, create the default printer
if( ! pController->getPrinter() )
{
rtl::OUString aPrinterName( i_rInitSetup.GetPrinterName() );
- if( ! aPrinterName.getLength() && pController->isShowDialogs() && ! pController->isDirectPrint() )
- {
- // get printer name from configuration
- SettingsConfigItem* pItem = SettingsConfigItem::get();
- aPrinterName = pItem->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintDialog" ) ),
- rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LastPrinterUsed" ) ) );
- }
-
boost::shared_ptr<Printer> pPrinter( new Printer( aPrinterName ) );
+ pPrinter->SetJobSetup( i_rInitSetup );
pController->setPrinter( pPrinter );
}
@@ -400,17 +387,25 @@ void Printer::ImplPrintJob( const boost::shared_ptr<PrinterController>& i_pContr
{
if( nContent == 0 )
{
- sal_Int32 nPages = i_pController->getPageCount();
- if( nPages > 0 )
+ // do not overwrite PageRange if it is already set
+ beans::PropertyValue* pRangeVal = i_pController->getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ) );
+ rtl::OUString aRange;
+ if( pRangeVal )
+ pRangeVal->Value >>= aRange;
+ if( aRange.getLength() == 0 )
{
- rtl::OUStringBuffer aBuf( 32 );
- aBuf.appendAscii( "1" );
- if( nPages > 1 )
+ sal_Int32 nPages = i_pController->getPageCount();
+ if( nPages > 0 )
{
- aBuf.appendAscii( "-" );
- aBuf.append( nPages );
+ rtl::OUStringBuffer aBuf( 32 );
+ aBuf.appendAscii( "1" );
+ if( nPages > 1 )
+ {
+ aBuf.appendAscii( "-" );
+ aBuf.append( nPages );
+ }
+ i_pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ), makeAny( aBuf.makeStringAndClear() ) );
}
- i_pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ), makeAny( aBuf.makeStringAndClear() ) );
}
}
}
diff --git a/vcl/source/gdi/region.cxx b/vcl/source/gdi/region.cxx
index 26d187c3e596..fe2e0f763e08 100644..100755
--- a/vcl/source/gdi/region.cxx
+++ b/vcl/source/gdi/region.cxx
@@ -43,6 +43,8 @@
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygonclipper.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
#include <basegfx/range/b2drange.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
@@ -1373,6 +1375,28 @@ sal_Bool Region::Union( const Rectangle& rRect )
if ( rRect.IsEmpty() )
return sal_True;
+ if( HasPolyPolygon() )
+ {
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
+ aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+
+ if( aThisPolyPoly.count() == 0 )
+ {
+ *this = rRect;
+ return true;
+ }
+
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
+ basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
+
+ basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationOr( aThisPolyPoly, aOtherPolyPoly );
+ *this = Region( aClip );
+
+ return sal_True;
+ }
+
ImplPolyPolyRegionToBandRegion();
// no instance data? -> create!
@@ -1443,6 +1467,22 @@ sal_Bool Region::Intersect( const Rectangle& rRect )
return sal_True;
}
+ else if( mpImplRegion->mpB2DPolyPoly )
+ {
+ // #127431# make ImplRegion unique, if not already.
+ if( mpImplRegion->mnRefCount > 1 )
+ {
+ mpImplRegion->mnRefCount--;
+ mpImplRegion = new ImplRegion( *mpImplRegion->mpB2DPolyPoly );
+ }
+
+ *mpImplRegion->mpB2DPolyPoly =
+ basegfx::tools::clipPolyPolygonOnRange( *mpImplRegion->mpB2DPolyPoly,
+ basegfx::B2DRange( rRect.Left(), rRect.Top(),
+ rRect.Right(), rRect.Bottom() ),
+ true, false );
+ return sal_True;
+ }
else
ImplPolyPolyRegionToBandRegion();
@@ -1526,6 +1566,25 @@ sal_Bool Region::Exclude( const Rectangle& rRect )
if ( rRect.IsEmpty() )
return sal_True;
+ if( HasPolyPolygon() )
+ {
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
+ aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+
+ if( aThisPolyPoly.count() == 0 )
+ return sal_True;
+
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
+ basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
+
+ basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
+ *this = Region( aClip );
+
+ return sal_True;
+ }
+
ImplPolyPolyRegionToBandRegion();
// no instance data? -> create!
@@ -1568,6 +1627,28 @@ sal_Bool Region::XOr( const Rectangle& rRect )
if ( rRect.IsEmpty() )
return sal_True;
+ if( HasPolyPolygon() )
+ {
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
+ aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+
+ if( aThisPolyPoly.count() == 0 )
+ {
+ *this = rRect;
+ return sal_True;
+ }
+
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
+ basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
+
+ basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );
+ *this = Region( aClip );
+
+ return sal_True;
+ }
+
ImplPolyPolyRegionToBandRegion();
// no instance data? -> create!
@@ -1601,11 +1682,38 @@ sal_Bool Region::XOr( const Rectangle& rRect )
}
// -----------------------------------------------------------------------
+void Region::ImplUnionPolyPolygon( const Region& i_rRegion )
+{
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
+ aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+
+ if( aThisPolyPoly.count() == 0 )
+ {
+ *this = i_rRegion;
+ return;
+ }
+
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
+ aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
+
+
+ basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationOr( aThisPolyPoly, aOtherPolyPoly );
+
+ *this = Region( aClip );
+}
sal_Bool Region::Union( const Region& rRegion )
{
DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
+ {
+ ImplUnionPolyPolygon( rRegion );
+ return sal_True;
+ }
+
ImplPolyPolyRegionToBandRegion();
((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
@@ -1651,6 +1759,22 @@ sal_Bool Region::Union( const Region& rRegion )
}
// -----------------------------------------------------------------------
+void Region::ImplIntersectWithPolyPolygon( const Region& i_rRegion )
+{
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
+ if( aThisPolyPoly.count() == 0 )
+ {
+ *this = i_rRegion;
+ return;
+ }
+
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
+
+ basegfx::B2DPolyPolygon aClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aOtherPolyPoly, aThisPolyPoly, true, false );
+ *this = Region( aClip );
+}
sal_Bool Region::Intersect( const Region& rRegion )
{
@@ -1660,6 +1784,12 @@ sal_Bool Region::Intersect( const Region& rRegion )
if ( mpImplRegion == rRegion.mpImplRegion )
return sal_True;
+ if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
+ {
+ ImplIntersectWithPolyPolygon( rRegion );
+ return sal_True;
+ }
+
ImplPolyPolyRegionToBandRegion();
((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
@@ -1790,11 +1920,32 @@ sal_Bool Region::Intersect( const Region& rRegion )
}
// -----------------------------------------------------------------------
+void Region::ImplExcludePolyPolygon( const Region& i_rRegion )
+{
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
+ if( aThisPolyPoly.count() == 0 )
+ return;
+ aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
+ aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
+
+ basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
+ *this = Region( aClip );
+}
sal_Bool Region::Exclude( const Region& rRegion )
{
DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
+ {
+ ImplExcludePolyPolygon( rRegion );
+ return sal_True;
+ }
+
ImplPolyPolyRegionToBandRegion();
((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
@@ -1843,11 +1994,35 @@ sal_Bool Region::Exclude( const Region& rRegion )
}
// -----------------------------------------------------------------------
+void Region::ImplXOrPolyPolygon( const Region& i_rRegion )
+{
+ // get this B2DPolyPolygon
+ basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
+ if( aThisPolyPoly.count() == 0 )
+ {
+ *this = i_rRegion;
+ return;
+ }
+ aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
+
+ // get the other B2DPolyPolygon
+ basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
+ aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
+
+ basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );
+ *this = Region( aClip );
+}
sal_Bool Region::XOr( const Region& rRegion )
{
DBG_CHKTHIS( Region, ImplDbgTestRegion );
+ if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
+ {
+ ImplXOrPolyPolygon( rRegion );
+ return sal_True;
+ }
+
ImplPolyPolyRegionToBandRegion();
((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
@@ -2028,7 +2203,7 @@ basegfx::B2DPolyPolygon Region::ConvertToB2DPolyPolygon()
// -----------------------------------------------------------------------
-sal_Bool Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
+bool Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
long& rX, long& rY,
long& rWidth, long& rHeight ) const
{
@@ -2038,11 +2213,11 @@ sal_Bool Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
// no internal data? -> region is empty!
if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- return sal_False;
+ return false;
// no band in the list? -> region is empty!
if ( mpImplRegion->mpFirstBand == NULL )
- return sal_False;
+ return false;
// initialise pointer for first access
ImplRegionBand* pCurrRectBand = mpImplRegion->mpFirstBand;
@@ -2050,7 +2225,7 @@ sal_Bool Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
DBG_ASSERT( pCurrRectBandSep != NULL, "Erstes Band wurde nicht optimiert." );
if ( !pCurrRectBandSep )
- return sal_False;
+ return false;
// get boundaries of current rectangle
rX = pCurrRectBandSep->mnXLeft;
@@ -2062,12 +2237,12 @@ sal_Bool Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
- return sal_True;
+ return true;
}
// -----------------------------------------------------------------------
-sal_Bool Region::ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
+bool Region::ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
long& rX, long& rY,
long& rWidth, long& rHeight ) const
{
@@ -2075,7 +2250,7 @@ sal_Bool Region::ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
// no internal data? -> region is empty!
if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
- return sal_False;
+ return false;
// get last pointers
ImplRegionBand* pCurrRectBand = (ImplRegionBand*)rImplRegionInfo.mpVoidCurrRectBand;
@@ -2092,7 +2267,7 @@ sal_Bool Region::ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
// no band found? -> not further rectangles!
if( !pCurrRectBand )
- return sal_False;
+ return false;
// get first separation in current band
pCurrRectBandSep = pCurrRectBand->mpFirstSep;
@@ -2108,7 +2283,7 @@ sal_Bool Region::ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
- return sal_True;
+ return true;
}
// -----------------------------------------------------------------------
diff --git a/vcl/source/gdi/salgdilayout.cxx b/vcl/source/gdi/salgdilayout.cxx
index 5522e0e0232a..0b6677b2426f 100755
--- a/vcl/source/gdi/salgdilayout.cxx
+++ b/vcl/source/gdi/salgdilayout.cxx
@@ -254,14 +254,29 @@ sal_Bool SalGraphics::mirror( sal_uInt32 nPoints, const SalPoint *pPtAry, SalPoi
void SalGraphics::mirror( Region& rRgn, const OutputDevice *pOutDev, bool bBack ) const
{
- // mirror the bounding rect and move Region by resulting offset
- Rectangle aRect( rRgn.GetBoundRect() );
- long nWidth = aRect.GetWidth();
- long x = aRect.Left();
- long x_org = x;
+ if( rRgn.HasPolyPolygon() )
+ {
+ basegfx::B2DPolyPolygon aPolyPoly( rRgn.ConvertToB2DPolyPolygon() );
+ aPolyPoly = mirror( aPolyPoly, pOutDev, bBack );
+ rRgn = Region( aPolyPoly );
+ }
+ else
+ {
+ ImplRegionInfo aInfo;
+ bool bRegionRect;
+ Region aMirroredRegion;
+ long nX, nY, nWidth, nHeight;
- mirror( x, nWidth, pOutDev, bBack );
- rRgn.Move( x - x_org, 0 );
+ bRegionRect = rRgn.ImplGetFirstRect( aInfo, nX, nY, nWidth, nHeight );
+ while ( bRegionRect )
+ {
+ Rectangle aRect( Point(nX, nY), Size(nWidth, nHeight) );
+ mirror( aRect, pOutDev, bBack );
+ aMirroredRegion.Union( aRect );
+ bRegionRect = rRgn.ImplGetNextRect( aInfo, nX, nY, nWidth, nHeight );
+ }
+ rRgn = aMirroredRegion;
+ }
}
void SalGraphics::mirror( Rectangle& rRect, const OutputDevice *pOutDev, bool bBack ) const
@@ -359,22 +374,15 @@ basegfx::B2DPolyPolygon SalGraphics::mirror( const basegfx::B2DPolyPolygon& i_rP
// ----------------------------------------------------------------------------
-sal_Bool SalGraphics::UnionClipRegion( long nX, long nY, long nWidth, long nHeight, const OutputDevice *pOutDev )
+bool SalGraphics::SetClipRegion( const Region& i_rClip, const OutputDevice *pOutDev )
{
if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
- mirror( nX, nWidth, pOutDev );
- return unionClipRegion( nX, nY, nWidth, nHeight );
-}
-
-bool SalGraphics::unionClipRegion( const ::basegfx::B2DPolyPolygon& )
-{
- return false;
-}
-
-sal_Bool SalGraphics::UnionClipRegion( const ::basegfx::B2DPolyPolygon& rPoly, const OutputDevice* pOutDev )
-{
- (void)pOutDev;// TODO: SAL_LAYOUT_BIDI_RTL
- return unionClipRegion( rPoly );
+ {
+ Region aMirror( i_rClip );
+ mirror( aMirror, pOutDev );
+ return setClipRegion( aMirror );
+ }
+ return setClipRegion( i_rClip );
}
void SalGraphics::DrawPixel( long nX, long nY, const OutputDevice *pOutDev )
@@ -466,7 +474,7 @@ void SalGraphics::DrawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints,
bool SalGraphics::DrawPolyPolygon( const ::basegfx::B2DPolyPolygon& i_rPolyPolygon, double i_fTransparency, const OutputDevice* i_pOutDev )
{
bool bRet = false;
- if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
+ if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
{
basegfx::B2DPolyPolygon aMirror( mirror( i_rPolyPolygon, i_pOutDev ) );
bRet = drawPolyPolygon( aMirror, i_fTransparency );
@@ -484,7 +492,7 @@ bool SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fT
sal_Bool SalGraphics::DrawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry, const OutputDevice* pOutDev )
{
sal_Bool bResult = sal_False;
- if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
+ if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
{
SalPoint* pPtAry2 = new SalPoint[nPoints];
sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
@@ -499,7 +507,7 @@ sal_Bool SalGraphics::DrawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPt
sal_Bool SalGraphics::DrawPolygonBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry, const OutputDevice* pOutDev )
{
sal_Bool bResult = sal_False;
- if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
+ if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (pOutDev && pOutDev->IsRTLEnabled()) )
{
SalPoint* pPtAry2 = new SalPoint[nPoints];
sal_Bool bCopied = mirror( nPoints, pPtAry, pPtAry2, pOutDev );
@@ -515,7 +523,7 @@ sal_Bool SalGraphics::DrawPolyPolygonBezier( sal_uInt32 i_nPoly, const sal_uInt3
const SalPoint* const* i_pPtAry, const sal_uInt8* const* i_pFlgAry, const OutputDevice* i_pOutDev )
{
sal_Bool bRet = sal_False;
- if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
+ if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
{
// TODO: optimize, reduce new/delete calls
SalPoint **pPtAry2 = new SalPoint*[i_nPoly];
@@ -543,7 +551,7 @@ bool SalGraphics::DrawPolyLine( const ::basegfx::B2DPolygon& i_rPolygon, double
const OutputDevice* i_pOutDev )
{
bool bRet = false;
- if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) )
+ if( (m_nLayout & SAL_LAYOUT_BIDI_RTL) || (i_pOutDev && i_pOutDev->IsRTLEnabled()) )
{
basegfx::B2DPolygon aMirror( mirror( i_rPolygon, i_pOutDev ) );
bRet = drawPolyLine( aMirror, fTransparency, i_rLineWidth, i_eLineJoin );