32 #define VECT_POLY_MAX 8192
34 #define VECT_FREE_INDEX 0
35 #define VECT_CONT_INDEX 1
36 #define VECT_DONE_INDEX 2
38 #define VECT_POLY_INLINE_INNER 1UL
39 #define VECT_POLY_INLINE_OUTER 2UL
40 #define VECT_POLY_OUTLINE_INNER 4UL
41 #define VECT_POLY_OUTLINE_OUTER 8UL
45 pMapIn[nVal] = (nVal * 4) + 1;
46 pMapOut[nVal] = pMapIn[nVal] + 5;
50 return ((_def_nVal + 2) >> 2) - 1;
55 pProgress->
Call(_def_nVal);
69 static bool ImplGetChain( ImplVectMap* pMap,
const Point& rStartPt, ImplChain& rChain );
126 if( lhs.mbSet && rhs.mbSet )
128 const sal_uInt8 cLum1 = lhs.maColor.GetLuminance();
129 const sal_uInt8 cLum2 = rhs.maColor.GetLuminance();
130 return cLum1 < cLum2;
132 return lhs.mbSet > rhs.mbSet;
139 std::unique_ptr<Point[]>
mpArray;
148 sal_uLong ImplGetRealSize()
const {
return mnRealSize; }
149 void ImplSetRealSize(
sal_uLong nRealSize ) { mnRealSize = nRealSize; }
159 ImplPointArray::ImplPointArray() :
166 void ImplPointArray::ImplSetSize(
sal_uLong nSize )
173 mpArray = std::make_unique<Point[]>( nTotal );
178 SAL_WARN_IF( nPos >= mnSize,
"vcl",
"ImplPointArray::operator[]: nPos out of range!" );
182 inline const Point& ImplPointArray::operator[](
sal_uLong nPos )
const
184 SAL_WARN_IF( nPos >= mnSize,
"vcl",
"ImplPointArray::operator[]: nPos out of range!" );
188 void ImplPointArray::ImplCreatePoly(
tools::Polygon& rPoly )
const
224 mpBuf ( static_cast<
Scanline>(rtl_allocateZeroMemory(nWidth * nHeight)) ),
232 for(
tools::Long nY = 0; nY < nHeight; pTmp += nWidthAl )
233 mpScan[ nY++ ] = pTmp;
236 ImplVectMap::~ImplVectMap()
245 auto & rPixel = mpScan[ nY ][ nX >> 2 ];
246 rPixel = (rPixel & ~( 3 << cShift ) ) | ( cVal << cShift );
251 return sal::static_int_cast<
sal_uInt8>( ( ( mpScan[ nY ][ nX >> 2 ] ) >> ( 6 - ( ( nX & 3 ) << 1 ) ) ) & 3 );
279 std::unique_ptr<sal_uInt8[]>
284 void ImplPostProcess(
const ImplPointArray& rArr );
286 ImplChain(
const ImplChain&) =
delete;
287 ImplChain& operator=(
const ImplChain&) =
delete;
293 void ImplBeginAdd(
const Point& rStartPt );
302 ImplChain::ImplChain() :
303 mnArraySize ( 1024 ),
309 void ImplChain::ImplGetSpace()
311 const sal_uLong nOldArraySize = mnArraySize;
314 mnArraySize = mnArraySize << 1;
315 pNewCodes =
new sal_uInt8[ mnArraySize ];
316 memcpy( pNewCodes, mpCodes.get(), nOldArraySize );
317 mpCodes.reset( pNewCodes );
320 void ImplChain::ImplBeginAdd(
const Point& rStartPt )
323 maStartPt = rStartPt;
327 inline void ImplChain::ImplAdd(
sal_uInt8 nCode )
329 if( mnCount == mnArraySize )
335 void ImplChain::ImplEndAdd(
sal_uLong nFlag )
346 nFirstX = nLastX = maStartPt.X();
347 nFirstY = nLastY = maStartPt.Y();
348 aArr.ImplSetSize( mnCount << 1 );
352 for( i = 0, nPolyPos = 0; i < (
mnCount - 1 ); i++ )
355 const sal_uInt8 cNextMove = mpCodes[ i + 1 ];
356 const ChainMove& rMove = aImplMove[ cMove ];
357 const ChainMove& rMoveInner = aImplMoveInner[ cMove ];
366 if( ( cMove == 0 && cNextMove == 3 ) ||
367 ( cMove == 3 && cNextMove == 2 ) ||
368 ( cMove == 2 && cNextMove == 1 ) ||
369 ( cMove == 1 && cNextMove == 0 ) )
372 else if( cMove == 2 && cNextMove == 3 )
374 aArr[ nPolyPos ].setX( nLastX );
375 aArr[ nPolyPos++ ].setY( nLastY - 1 );
377 aArr[ nPolyPos ].setX( nLastX - 1 );
378 aArr[ nPolyPos++ ].setY( nLastY - 1 );
380 aArr[ nPolyPos ].setX( nLastX - 1 );
381 aArr[ nPolyPos++ ].setY( nLastY );
383 else if( cMove == 3 && cNextMove == 0 )
385 aArr[ nPolyPos ].setX( nLastX - 1 );
386 aArr[ nPolyPos++ ].setY( nLastY );
388 aArr[ nPolyPos ].setX( nLastX - 1 );
389 aArr[ nPolyPos++ ].setY( nLastY + 1 );
391 aArr[ nPolyPos ].setX( nLastX );
392 aArr[ nPolyPos++ ].setY( nLastY + 1 );
394 else if( cMove == 0 && cNextMove == 1 )
396 aArr[ nPolyPos ].setX( nLastX );
397 aArr[ nPolyPos++ ].setY( nLastY + 1 );
399 aArr[ nPolyPos ].setX( nLastX + 1 );
400 aArr[ nPolyPos++ ].setY( nLastY + 1 );
402 aArr[ nPolyPos ].setX( nLastX + 1 );
403 aArr[ nPolyPos++ ].setY( nLastY );
405 else if( cMove == 1 && cNextMove == 2 )
407 aArr[ nPolyPos ].setX( nLastX + 1 );
408 aArr[ nPolyPos++ ].setY( nLastY + 1 );
410 aArr[ nPolyPos ].setX( nLastX + 1 );
411 aArr[ nPolyPos++ ].setY( nLastY - 1 );
413 aArr[ nPolyPos ].setX( nLastX );
414 aArr[ nPolyPos++ ].setY( nLastY - 1 );
419 else if( cMove == 7 && cNextMove == 0 )
421 aArr[ nPolyPos ].setX( nLastX - 1 );
422 aArr[ nPolyPos++ ].setY( nLastY );
424 aArr[ nPolyPos ].setX( nLastX );
425 aArr[ nPolyPos++ ].setY( nLastY + 1 );
427 else if( cMove == 4 && cNextMove == 1 )
429 aArr[ nPolyPos ].setX( nLastX );
430 aArr[ nPolyPos++ ].setY( nLastY + 1 );
432 aArr[ nPolyPos ].setX( nLastX + 1 );
433 aArr[ nPolyPos++ ].setY( nLastY );
440 aArr[ nPolyPos ].setX( nLastX + rMoveInner.nDX );
441 aArr[ nPolyPos++ ].setY( nLastY + rMoveInner.nDY );
445 aArr[ nPolyPos ].setX( nFirstX + 1 );
446 aArr[ nPolyPos++ ].setY( nFirstY + 1 );
447 aArr.ImplSetRealSize( nPolyPos );
454 nFirstX = nLastX = maStartPt.X();
455 nFirstY = nLastY = maStartPt.Y();
456 aArr.ImplSetSize( mnCount << 1 );
460 for( i = 0, nPolyPos = 0; i < (
mnCount - 1 ); i++ )
463 const sal_uInt8 cNextMove = mpCodes[ i + 1 ];
464 const ChainMove& rMove = aImplMove[ cMove ];
465 const ChainMove& rMoveOuter = aImplMoveOuter[ cMove ];
474 if( ( cMove == 0 && cNextMove == 1 ) ||
475 ( cMove == 1 && cNextMove == 2 ) ||
476 ( cMove == 2 && cNextMove == 3 ) ||
477 ( cMove == 3 && cNextMove == 0 ) )
480 else if( cMove == 0 && cNextMove == 3 )
482 aArr[ nPolyPos ].setX( nLastX );
483 aArr[ nPolyPos++ ].setY( nLastY - 1 );
485 aArr[ nPolyPos ].setX( nLastX + 1 );
486 aArr[ nPolyPos++ ].setY( nLastY - 1 );
488 aArr[ nPolyPos ].setX( nLastX + 1 );
489 aArr[ nPolyPos++ ].setY( nLastY );
491 else if( cMove == 3 && cNextMove == 2 )
493 aArr[ nPolyPos ].setX( nLastX + 1 );
494 aArr[ nPolyPos++ ].setY( nLastY );
496 aArr[ nPolyPos ].setX( nLastX + 1 );
497 aArr[ nPolyPos++ ].setY( nLastY + 1 );
499 aArr[ nPolyPos ].setX( nLastX );
500 aArr[ nPolyPos++ ].setY( nLastY + 1 );
502 else if( cMove == 2 && cNextMove == 1 )
504 aArr[ nPolyPos ].setX( nLastX );
505 aArr[ nPolyPos++ ].setY( nLastY + 1 );
507 aArr[ nPolyPos ].setX( nLastX - 1 );
508 aArr[ nPolyPos++ ].setY( nLastY + 1 );
510 aArr[ nPolyPos ].setX( nLastX - 1 );
511 aArr[ nPolyPos++ ].setY( nLastY );
513 else if( cMove == 1 && cNextMove == 0 )
515 aArr[ nPolyPos ].setX( nLastX - 1 );
516 aArr[ nPolyPos++ ].setY( nLastY );
518 aArr[ nPolyPos ].setX( nLastX - 1 );
519 aArr[ nPolyPos++ ].setY( nLastY - 1 );
521 aArr[ nPolyPos ].setX( nLastX );
522 aArr[ nPolyPos++ ].setY( nLastY - 1 );
527 else if( cMove == 7 && cNextMove == 3 )
529 aArr[ nPolyPos ].setX( nLastX );
530 aArr[ nPolyPos++ ].setY( nLastY - 1 );
532 aArr[ nPolyPos ].setX( nLastX + 1 );
533 aArr[ nPolyPos++ ].setY( nLastY );
535 else if( cMove == 6 && cNextMove == 2 )
537 aArr[ nPolyPos ].setX( nLastX + 1 );
538 aArr[ nPolyPos++ ].setY( nLastY );
540 aArr[ nPolyPos ].setX( nLastX );
541 aArr[ nPolyPos++ ].setY( nLastY + 1 );
548 aArr[ nPolyPos ].setX( nLastX + rMoveOuter.nDX );
549 aArr[ nPolyPos++ ].setY( nLastY + rMoveOuter.nDY );
553 aArr[ nPolyPos ].setX( nFirstX - 1 );
554 aArr[ nPolyPos++ ].setY( nFirstY - 1 );
555 aArr.ImplSetRealSize( nPolyPos );
559 tools::Long nLastX = maStartPt.X(), nLastY = maStartPt.Y();
561 aArr.ImplSetSize( mnCount + 1 );
562 aArr[ 0 ] =
Point( nLastX, nLastY );
566 const ChainMove& rMove = aImplMove[ mpCodes[ i ] ];
569 aArr[ ++i ] =
Point( nLastX, nLastY );
572 aArr.ImplSetRealSize( mnCount + 1 );
575 ImplPostProcess( aArr );
581 void ImplChain::ImplPostProcess(
const ImplPointArray& rArr )
583 ImplPointArray aNewArr1;
584 ImplPointArray aNewArr2;
592 aNewArr1.ImplSetSize( nCount );
593 pLast = &( aNewArr1[ 0 ] );
594 pLast->setX(
BACK_MAP( rArr[ 0 ].
X() ) );
595 pLast->setY(
BACK_MAP( rArr[ 0 ].
Y() ) );
597 for( n = nNewPos = 1; n < nCount; )
599 const Point& rPt = rArr[ n++ ];
603 if( nX != pLast->X() || nY != pLast->Y() )
605 pLast = pLeast = &( aNewArr1[ nNewPos++ ] );
612 aNewArr1.ImplSetRealSize( nCount );
615 aNewArr2.ImplSetSize( nCount );
616 pLast = &( aNewArr2[ 0 ] );
617 *pLast = aNewArr1[ 0 ];
619 for( n = nNewPos = 1; n < nCount; )
621 pLeast = &( aNewArr1[ n++ ] );
623 if( pLeast->X() == pLast->X() )
625 while( n < nCount && aNewArr1[ n ].
X() == pLast->X() )
626 pLeast = &( aNewArr1[ n++ ] );
628 else if( pLeast->Y() == pLast->Y() )
630 while( n < nCount && aNewArr1[ n ].
Y() == pLast->Y() )
631 pLeast = &( aNewArr1[ n++ ] );
635 aNewArr2[ nNewPos++ ] = *pLast;
638 aNewArr2.ImplSetRealSize( nNewPos );
639 aNewArr2.ImplCreatePoly( maPoly );
651 std::unique_ptr<Bitmap> xBmp(
new Bitmap( rColorBmp ));
657 double fPercent = 0.0;
658 double fPercentStep_2 = 0.0;
663 std::array<ImplColorSet, 256> aColorSet;
668 for( n = 0; n < nColorCount; n++ )
670 aColorSet[ n ].mnIndex = n;
683 for( n = 0; n < 256; n++ )
684 if( !aColorSet[ n ].mbSet )
688 fPercentStep_2 = 45.0 / n;
693 for( sal_uInt16 i = 0; i < n; i++ )
696 const Color aFindColor( aBmpCol.GetRed(), aBmpCol.GetGreen(), aBmpCol.GetBlue() );
697 std::unique_ptr<ImplVectMap> xMap(
ImplExpand( pRAcc.
get(), aFindColor ));
699 fPercent += fPercentStep_2;
708 if( aPolyPoly.
Count() )
712 aPolyPoly.
Optimize( PolyOptimizeFlags::EDGES );
714 if( aPolyPoly.
Count() )
718 rMtf.
AddAction(
new MetaPolyPolygonAction( aPolyPoly ) );
723 fPercent += fPercentStep_2;
731 const Size aLogSize1( aVDev->PixelToLogic(
Size( 1, 1 ), aMap ) );
736 rMtf.
Scale( aLogSize1.Width(), aLogSize1.Height() );
755 sal_uInt16 nNewCount;
759 aNewPolyPoly.
Clear();
762 for( sal_uInt16 i = 0, nCount = rPolyPoly.
Count(); i < nCount; i++ )
768 if( rPolyPoly[ i ].GetSize() )
769 aNewPolyPoly.
Insert( rPolyPoly[ i ] );
773 nNewCount = aNewPolyPoly.
Count();
777 rPolyPoly = aNewPolyPoly;
782 ImplVectMap* pMap =
nullptr;
788 const tools::Long nNewWidth = ( nOldWidth << 2 ) + 4;
789 const tools::Long nNewHeight = ( nOldHeight << 2 ) + 4;
791 std::unique_ptr<tools::Long[]> pMapIn(
new tools::Long[ std::max( nOldWidth, nOldHeight ) ]);
792 std::unique_ptr<tools::Long[]> pMapOut(
new tools::Long[ std::max( nOldWidth, nOldHeight ) ]);
795 pMap =
new ImplVectMap( nNewWidth, nNewHeight );
797 for( nX = 0; nX < nOldWidth; nX++ )
800 for( nY = 0, nTmpY = 5; nY < nOldHeight; nY++, nTmpY += 4 )
803 for( nX = 0; nX < nOldWidth; )
807 nTmpX = pMapIn[ nX++ ];
815 while( nX < nOldWidth && pRAcc->GetPixelFromData( pScanlineRead, nX ) == aTest )
818 nTmpX = pMapOut[ nX - 1 ];
831 for( nY = 0; nY < nOldHeight; nY++ )
834 for( nX = 0, nTmpX = 5; nX < nOldWidth; nX++, nTmpX += 4 )
836 for( nY = 0; nY < nOldHeight; )
838 if( pRAcc->
GetPixel( nY, nX ) == aTest )
841 nTmpY = pMapIn[ nY++ ];
848 while( nY < nOldHeight && pRAcc->GetPixel( nY, nX ) == aTest )
852 nTmpY = pMapOut[ nY - 1 ];
870 const tools::Long nWidth = pMap->Width(), nHeight= pMap->Height();
880 while( ( nX < nWidth ) && pMap->IsFree( nY, nX ) )
886 if( pMap->IsCont( nY, nX ) )
890 const Point aStartPt( nX++, nY );
893 aChain.ImplBeginAdd( aStartPt );
906 if( aBound.GetWidth() > cReduce && aBound.GetHeight() > cReduce )
907 rPolyPoly.
Insert( rPoly );
910 rPolyPoly.
Insert( rPoly );
914 while( pMap->IsCont( nY, nX ) )
922 while( pMap->IsDone( nY, nX ) )
925 if( ( ( nX - nStartSegX ) == 1 ) || (
ImplIsUp( pMap, nY, nStartSegX ) !=
ImplIsUp( pMap, nY, nX - 1 ) ) )
932 bool ImplGetChain( ImplVectMap* pMap,
const Point& rStartPt, ImplChain& rChain )
945 tools::Long nTryX = nActX + aImplMove[ nLastDir ].nDX;
946 tools::Long nTryY = nActY + aImplMove[ nLastDir ].nDY;
948 if( pMap->IsCont( nTryY, nTryX ) )
950 rChain.ImplAdd( static_cast<sal_uInt8>(nLastDir) );
959 for( nDir = 0; nDir < 8; nDir++ )
962 if( nDir != nLastDir )
964 nTryX = nActX + aImplMove[ nDir ].nDX;
965 nTryY = nActY + aImplMove[ nDir ].nDY;
967 if( pMap->IsCont( nTryY, nTryX ) )
969 rChain.ImplAdd( static_cast<sal_uInt8>(nDir) );
988 if( pMap->IsDone( nY - 1, nX ) )
990 else if( pMap->IsDone( nY + 1, nX ) )
992 else if( pMap->IsDone( nY - 1, nX - 1 ) || pMap->IsDone( nY - 1, nX + 1 ) )
#define VECT_POLY_OUTLINE_OUTER
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
tools::Long Height() const
static void VECT_PROGRESS(const Link< tools::Long, void > *pProgress, tools::Long _def_nVal)
const ChainMove aImplMoveOuter[8]
#define VECT_POLY_OUTLINE_INNER
static void ImplLimitPolyPoly(tools::PolyPolygon &rPolyPoly)
static ImplVectMap * ImplExpand(BitmapReadAccess *pRAcc, const Color &rColor)
#define VECT_POLY_INLINE_INNER
HashMap_OWString_Interface aMap
static constexpr tools::Long BACK_MAP(tools::Long _def_nVal)
Scanline GetScanline(tools::Long nY) const
static void VECT_MAP(const std::unique_ptr< tools::Long[]> &pMapIn, const std::unique_ptr< tools::Long[]> &pMapOut, tools::Long nVal)
static bool ImplColorSetCmpFnc(const ImplColorSet &lhs, const ImplColorSet &rhs)
tools::Long FRound(double fVal)
tools::Long Width() const
static void ImplCalculate(ImplVectMap *pMap, tools::PolyPolygon &rPolyPoly, sal_uInt8 cReduce)
const ChainMove aImplMove[8]
bool ImplVectorize(const Bitmap &rColorBmp, GDIMetaFile &rMtf, sal_uInt8 cReduce, const Link< tools::Long, void > *pProgress)
sal_uInt16 GetPaletteEntryCount() const
static bool ImplIsUp(ImplVectMap const *pMap, tools::Long nY, tools::Long nX)
const ChainMove aImplMoveInner[8]
#define SAL_WARN_IF(condition, area, stream)
BitmapColor GetPixelFromData(const sal_uInt8 *pData, tools::Long nX) const
SVXCORE_DLLPUBLIC MSO_SPT Get(const OUString &)
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
static bool ImplGetChain(ImplVectMap *pMap, const Point &rStartPt, ImplChain &rChain)
#define VECT_POLY_INLINE_OUTER
BitmapColor GetPixel(tools::Long nY, tools::Long nX) const
BitmapColor GetBestMatchingColor(const BitmapColor &rBitmapColor)