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
43static void VECT_MAP(
const std::unique_ptr<sal_Int32 []> & pMapIn,
const std::unique_ptr<sal_Int32 []>& pMapOut,
tools::Long nVal )
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& rMap,
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; }
159ImplPointArray::ImplPointArray() :
166void 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!" );
182inline const Point& ImplPointArray::operator[](
sal_uLong nPos )
const
184 SAL_WARN_IF( nPos >= mnSize,
"vcl",
"ImplPointArray::operator[]: nPos out of range!" );
224 mpBuf ( static_cast<
Scanline>(rtl_allocateZeroMemory(nWidth * nHeight)) ),
232 for(
tools::Long nY = 0; nY < nHeight; pTmp += nWidthAl )
233 mpScan[ nY++ ] = pTmp;
236ImplVectMap::~ImplVectMap()
244 const sal_uInt8 cShift = sal::static_int_cast<sal_uInt8>(6 - ( ( nX & 3 ) << 1 ));
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 );
302ImplChain::ImplChain() :
303 mnArraySize ( 1024 ),
309void 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 );
320void ImplChain::ImplBeginAdd(
const Point& rStartPt )
323 maStartPt = rStartPt;
327inline void ImplChain::ImplAdd(
sal_uInt8 nCode )
329 if( mnCount == mnArraySize )
335void 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++ )
356 const ChainMove& rMove =
aImplMove[ 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++ )
464 const ChainMove& rMove =
aImplMove[ 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 );
566 const ChainMove& rMove =
aImplMove[ mpCodes[
i ] ];
572 aArr.ImplSetRealSize( mnCount + 1 );
575 ImplPostProcess( aArr );
581void ImplChain::ImplPostProcess(
const ImplPointArray& rArr )
583 ImplPointArray aNewArr1;
584 ImplPointArray aNewArr2;
592 aNewArr1.ImplSetSize( nCount );
593 pLast = &( aNewArr1[ 0 ] );
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::optional<Bitmap> xBmp(std::in_place, rColorBmp );
656 double fPercent = 0.0;
657 double fPercentStep_2 = 0.0;
662 std::array<ImplColorSet, 256> aColorSet;
667 for(
n = 0;
n < nColorCount;
n++ )
669 aColorSet[
n ].mnIndex =
n;
682 for(
n = 0;
n < 256;
n++ )
683 if( !aColorSet[
n ].mbSet )
687 fPercentStep_2 = 45.0 /
n;
692 for( sal_uInt16
i = 0;
i <
n;
i++ )
696 std::optional<ImplVectMap> oMap;
699 fPercent += fPercentStep_2;
708 if( aPolyPoly.
Count() )
712 aPolyPoly.
Optimize( PolyOptimizeFlags::EDGES );
714 if( aPolyPoly.
Count() )
723 fPercent += fPercentStep_2;
731 const Size aLogSize1( aVDev->PixelToLogic(
Size( 1, 1 ),
aMap ) );
755 sal_uInt16 nNewCount;
759 aNewPolyPoly.
Clear();
768 if( rPolyPoly[
i ].GetSize() )
769 aNewPolyPoly.
Insert( rPolyPoly[
i ] );
773 nNewCount = aNewPolyPoly.
Count();
777 rPolyPoly = aNewPolyPoly;
782 if( !pRAcc || !pRAcc->
Width() || !pRAcc->
Height() )
787 const tools::Long nNewWidth = ( nOldWidth << 2 ) + 4;
788 const tools::Long nNewHeight = ( nOldHeight << 2 ) + 4;
790 std::unique_ptr<sal_Int32[]> pMapIn(
new sal_Int32[ std::max( nOldWidth, nOldHeight ) ]);
791 std::unique_ptr<sal_Int32[]> pMapOut(
new sal_Int32[ std::max( nOldWidth, nOldHeight ) ]);
794 oMap.emplace( nNewWidth, nNewHeight );
796 for( nX = 0; nX < nOldWidth; nX++ )
799 for( nY = 0, nTmpY = 5; nY < nOldHeight; nY++, nTmpY += 4 )
802 for( nX = 0; nX < nOldWidth; )
806 nTmpX = pMapIn[ nX++ ];
814 while( nX < nOldWidth && pRAcc->GetPixelFromData( pScanlineRead, nX ) == aTest )
817 nTmpX = pMapOut[ nX - 1 ];
830 for( nY = 0; nY < nOldHeight; nY++ )
833 for( nX = 0, nTmpX = 5; nX < nOldWidth; nX++, nTmpX += 4 )
835 for( nY = 0; nY < nOldHeight; )
837 if( pRAcc->
GetPixel( nY, nX ) == aTest )
840 nTmpY = pMapIn[ nY++ ];
847 while( nY < nOldHeight && pRAcc->GetPixel( nY, nX ) == aTest )
851 nTmpY = pMapOut[ nY - 1 ];
866 const tools::Long nWidth = rMap.Width(), nHeight = rMap.Height();
876 while( ( nX < nWidth ) && rMap.IsFree( nY, nX ) )
882 if( rMap.IsCont( nY, nX ) )
886 const Point aStartPt( nX++, nY );
889 aChain.ImplBeginAdd( aStartPt );
903 rPolyPoly.
Insert( rPoly );
906 rPolyPoly.
Insert( rPoly );
910 while( rMap.IsCont( nY, nX ) )
918 while( rMap.IsDone( nY, nX ) )
921 if( ( ( nX - nStartSegX ) == 1 ) || (
ImplIsUp( rMap, nY, nStartSegX ) !=
ImplIsUp( rMap, nY, nX - 1 ) ) )
944 if( rMap.IsCont( nTryY, nTryX ) )
946 rChain.ImplAdd(
static_cast<sal_uInt8>(nLastDir) );
955 for( nDir = 0; nDir < 8; nDir++ )
958 if( nDir != nLastDir )
963 if( rMap.IsCont( nTryY, nTryX ) )
965 rChain.ImplAdd(
static_cast<sal_uInt8>(nDir) );
984 if( rMap.IsDone( nY - 1, nX ) )
986 else if( rMap.IsDone( nY + 1, nX ) )
988 else if( rMap.IsDone( nY - 1, nX - 1 ) || rMap.IsDone( nY - 1, nX + 1 ) )
tools::Long Height() const
tools::Long Width() const
BitmapColor GetBestMatchingColor(const BitmapColor &rBitmapColor) const
sal_uInt16 GetPaletteEntryCount() const
const BitmapColor & GetPaletteColor(sal_uInt16 nColor) const
BitmapColor GetPixel(tools::Long nY, tools::Long nX) const
BitmapColor GetPixelFromData(const sal_uInt8 *pData, tools::Long nX) const
sal_uInt8 GetIndexFromData(const sal_uInt8 *pData, tools::Long nX) const
Scanline GetScanline(tools::Long nY) const
sal_uInt8 GetBlue() const
sal_uInt8 GetGreen() const
constexpr tools::Long Y() const
void setX(tools::Long nX)
void setY(tools::Long nY)
constexpr tools::Long X() const
constexpr tools::Long Height() const
constexpr tools::Long Width() const
tools::Long FRound(double fVal)
static constexpr tools::Long BACK_MAP(tools::Long _def_nVal)
const ChainMove aImplMove[8]
static bool ImplColorSetCmpFnc(const ImplColorSet &lhs, const ImplColorSet &rhs)
#define VECT_POLY_OUTLINE_OUTER
static void VECT_MAP(const std::unique_ptr< sal_Int32[]> &pMapIn, const std::unique_ptr< sal_Int32[]> &pMapOut, tools::Long nVal)
#define VECT_POLY_OUTLINE_INNER
static void VECT_PROGRESS(const Link< tools::Long, void > *pProgress, tools::Long _def_nVal)
#define VECT_POLY_INLINE_OUTER
const ChainMove aImplMoveInner[8]
#define VECT_POLY_INLINE_INNER
const ChainMove aImplMoveOuter[8]
#define SAL_WARN_IF(condition, area, stream)
SVXCORE_DLLPUBLIC MSO_SPT Get(const OUString &)
static bool ImplGetChain(ImplVectMap &rMap, const Point &rStartPt, ImplChain &rChain)
static void ImplCalculate(ImplVectMap &rMap, tools::PolyPolygon &rPolyPoly, sal_uInt8 cReduce)
static void ImplExpand(std::optional< ImplVectMap > &rMap, const BitmapReadAccess *pRAcc, const Color &rColor)
static bool ImplIsUp(ImplVectMap const &rMap, tools::Long nY, tools::Long nX)
static void ImplLimitPolyPoly(tools::PolyPolygon &rPolyPoly)
bool ImplVectorize(const Bitmap &rColorBmp, GDIMetaFile &rMtf, sal_uInt8 cReduce, const Link< tools::Long, void > *pProgress)
HashMap_OWString_Interface aMap