20#include <mtftools.hxx>
33#include <rtl/tencinfo.h>
35#include <osl/diagnose.h>
42#if OSL_DEBUG_LEVEL > 1
43#define EMFP_DEBUG(x) x
52 if (
sizeof(
float) != 4)
54 OSL_FAIL(
"EmfReader::sizeof( float ) != 4");
81 switch ( nClippingMode )
158 Point aFirst( rPoly[ 0 ] );
159 if ( aFirst != rPoly[ rPoly.
GetSize() - 1 ] )
168 rtl_TextEncoding eCharSet;
171 eCharSet = RTL_TEXTENCODING_SYMBOL;
176 eCharSet = rtl_getTextEncodingFromWindowsCharset( rFont.
lfCharSet );
177 if ( eCharSet == RTL_TEXTENCODING_DONTKNOW )
178 eCharSet = RTL_TEXTENCODING_MS_1252;
267 pVDev->SetFont(
aFont );
272 double fHeight = (
static_cast<double>(aFontSize.
Height()) * rFont.
lfHeight ) / nHeight;
273 aFontSize.
setHeight(
static_cast<sal_Int32
>( fHeight + 0.5 ) );
284 const bool bFontScaledHorizontally(aFontSize.
Width() != 0 && aFontSize.
Width() != aFontSize.
Height());
286 if(bFontScaledHorizontally)
292 if(nAverageFontWidth > 0)
294 const double fScaleFactor(
static_cast<double>(aFontSize.
Height()) /
static_cast<double>(nAverageFontWidth));
312 sal_uInt32 nPositive(0);
313 sal_uInt32 nNegative(0);
314 double fAverage(0.0);
332 if(nPositive >= nNegative)
354 if(!rNewMetaFontAction.is())
359 const vcl::Font& rCandidate(rNewMetaFontAction->GetFont());
384 pTempVirtualDevice->SetFont(rFontCandidate);
385 tools::Long nMeasuredTextLength(pTempVirtualDevice->GetTextWidth(rText));
387 if (!nMeasuredTextLength)
388 nMeasuredTextLength = nImportedTextLength;
391 if (nImportedTextLength == nMeasuredTextLength)
394 const double fFactorText(
static_cast<double>(nImportedTextLength) /
static_cast<double>(nMeasuredTextLength));
395 const double fFactorTextPercent(fabs(1.0 - fFactorText) * 100.0);
412 const double fScaleFactor(
static_cast<double>(nUnscaledAverageFontWidth) /
static_cast<double>(rFontCandidate.
GetFontHeight()));
413 const double fCorrectedAverageFontWidth(
static_cast<double>(nScaledAverageFontWidth) * fScaleFactor);
417 vcl::Font rFontCandidate2(rFontCandidate);
419 pTempVirtualDevice->SetFont(rFontCandidate2);
420 nCorrectedTextLength = pTempVirtualDevice->GetTextWidth(rText);
422 if (!nCorrectedTextLength)
423 nCorrectedTextLength = nImportedTextLength;
426 const double fFactorCorrectedText(
static_cast<double>(nImportedTextLength) /
static_cast<double>(nCorrectedTextLength));
427 const double fFactorCorrectedTextPercent(fabs(1.0 - fFactorCorrectedText) * 100.0);
438 if(fFactorCorrectedTextPercent < fFactorTextPercent)
469 rCandidate.first->correctFontScale(
static_cast<tools::Long>(rCandidate.second));
473 rCandidate.first->correctFontScale(
static_cast<tools::Long>(rCandidate.second));
483 sal_uInt32 nColor(0);
486 if ( ( nColor & 0xFFFF0000 ) == 0x01000000 )
488 size_t index = nColor & 0x0000FFFF;
492 SAL_INFO(
"emfio",
"\t\t Palette index out of range: " <<
index );
497 SAL_INFO(
"emfio",
"\t\tColor: " << aColor);
560 SAL_WARN(
"emfio",
"invalid scaling factor");
572 fX2 *=
static_cast<double>(
mnMillX) * 100.0 /
static_cast<double>(
mnPixX);
573 fY2 *=
static_cast<double>(
mnMillY) * 100.0 /
static_cast<double>(
mnPixY);
581 nDevOrgX *=
static_cast<double>(
mnMillX) * 100.0 /
static_cast<double>(
mnPixX);
585 nDevOrgY *=
static_cast<double>(
mnMillY) * 100.0 /
static_cast<double>(
mnPixY);
602 double fWidth, fHeight;
603 if (bDoWorldTransform)
614 double fRotate, fShearX;
615 if (!aMatrix.
decompose(aScale, aTranslate, fRotate, fShearX))
661 SAL_WARN(
"emfio",
"invalid scaling factor");
673 fWidth *=
static_cast<double>(
mnMillX) * 100.0 /
static_cast<double>(
mnPixX);
674 fHeight *=
static_cast<double>(
mnMillY) * 100.0 /
static_cast<double>(
mnPixY);
700 const auto nHeight = aFontSize.
Height();
708 if (!bFail && nResult < 0)
714 sal_uInt16 nPoints = rPolygon.
GetSize();
715 for ( sal_uInt16
i = 0;
i < nPoints;
i++ )
717 rPolygon[
i ] =
ImplMap( rPolygon[
i ] );
724 sal_uInt16 nPoints = rPolygon.
GetSize();
725 for ( sal_uInt16
i = 0;
i < nPoints;
i++ )
733 sal_uInt16 nPolys = rPolyPolygon.
Count();
734 for (sal_uInt16
i = 0;
i < nPolys; ++
i)
743 sal_uInt16 nPolys = rPolyPolygon.
Count();
744 for ( sal_uInt16
i = 0;
i < nPolys;
ImplMap( rPolyPolygon[
i++ ] ) ) ;
752 SAL_INFO (
"emfio",
"\t\t ENHMETA_STOCK_OBJECT, StockObject Enumeration: 0x" << std::hex <<
nIndex );
815 GDIObj *pGDIObj =
nullptr;
852 SAL_WARN(
"emfio",
"Warning: Unable to find Object with index:" <<
nIndex);
864 SAL_INFO(
"emfio",
"\t\t Arc direction: " << (bClockWise ?
"ClockWise" :
"CounterClockWise"));
895 if ( !rPolyPoly.
Count() )
899 if ( rPolyPoly.
Count() == 1 )
909 if ( aPoly[
nCount - 1 ] != aPoly[ 0 ] )
911 Point aPoint( aPoly[ 0 ] );
931 if (pFontStyle->aFont.GetFontHeight() == 0)
935 else if ( pLineStyle )
937 Size aSize(pLineStyle->aLineInfo.GetWidth(), 0);
939 pLineStyle->aLineInfo.SetWidth(aSize.
Width());
942 std::vector<std::unique_ptr<GDIObj>>::size_type
nIndex;
966 if (pFontStyle->aFont.GetFontHeight() == 0)
970 else if ( pLineStyle )
972 Size aSize(pLineStyle->aLineInfo.GetWidth(), 0);
973 pLineStyle->aLineInfo.SetWidth(
ImplMap(aSize).
Width() );
975 if ( pLineStyle->aLineInfo.GetStyle() == LineStyle::Dash )
979 pLineStyle->aLineInfo.SetDistance( nDotLen );
980 pLineStyle->aLineInfo.SetDotLen( nDotLen );
981 pLineStyle->aLineInfo.SetDashLen( nDotLen * 3 );
1051 aPolyPolygon =
ImplMap(aPolyPolygon);
1063 : mnLatestTextAlign(90),
1088 mpGDIMetaFile(&rGDIMetaFile),
1089 mpInputStream(&rStreamWMF),
1093 mbClockWiseArcDirection(false),
1094 mbFillStyleSelected(false),
1095 mbClipNeedsUpdate(true),
1096 mbComplexClip(false),
1097 mbIsMapWinSet(false),
1098 mbIsMapDevSet(false)
1208 if ( nRasterOp !=
mnRop )
1247 if ( nRetROP != nRasterOp )
1425 if ( aStart == aEnd )
1513 if ( rPolygon[
nCount - 1 ] != rPolygon[ 0 ] )
1515 Point aPoint( rPolygon[ 0 ] );
1585 for (sal_uInt16 nPoly = 0; nPoly < rPolyPolygon.
Count(); ++nPoly)
1598 sal_uInt16 nPoints = rPolygon.
GetSize();
1619 sal_uInt16 nPoints = rPolygon.
GetSize();
1620 if ( ( nPoints < 4 ) || ( ( ( nPoints - 4 ) % 3 ) != 0 ) )
1623 "EMF file error: Number of Bezier points is not set of three");
1631 maActPos = rPolygon[ nPoints - 1 ];
1634 for (
i = 0; (
i + 2 ) < nPoints; )
1636 rPolygon.
SetFlags(
i++, PolyFlags::Normal );
1637 rPolygon.
SetFlags(
i++, PolyFlags::Control );
1638 rPolygon.
SetFlags(
i++, PolyFlags::Control );
1652 rPosition =
ImplMap( rPosition );
1658 sal_Int64 nSumX = 0, nSumY = 0;
1659 for (sal_Int32
i = 0;
i < rText.getLength();
i++ )
1661 nSumX += (*pDXArry)[
i];
1670 nSumY += pDYArry[
i];
1676 pDYArry[
i] *= (nSumY >= 0 ? -1 : 1);
1693 bool bChangeFont =
false;
1706 bool bChangeFillColor =
false;
1709 bChangeFillColor =
true;
1714 bChangeFillColor =
true;
1717 if ( bChangeFillColor )
1740 double fX = aP2.
X();
1741 double fY = aP2.
Y();
1746 fOrientation = 360 - fOrientation;
1758 sal_Int32 nTextWidth;
1760 pVDev->SetMapMode(
MapMode( MapUnit::Map100thMM ) );
1761 pVDev->SetFont(
maFont );
1762 const sal_uInt32 nLen = pDXArry ? rText.getLength() : 0;
1765 nTextWidth = pVDev->GetTextWidth( OUString(rText[ nLen - 1 ]) );
1767 nTextWidth += (*pDXArry)[ nLen - 2 ];
1769 aActPosDelta.
setX( (*pDXArry)[ nLen - 1 ] );
1772 aActPosDelta.
setY( pDYArry[ nLen - 1 ] );
1777 nTextWidth = pVDev->GetTextWidth( rText );
1778 aActPosDelta.
setX( nTextWidth );
1788 rPosition -= aDisplacement;
1794 maActPos = rPosition + aActPosDelta;
1809 if(!bRecordPath &&
nullptr != pDXArry && 0 != rText.getLength())
1826 if ( pDXArry && pDYArry )
1828 for (sal_Int32
i = 0;
i < rText.getLength(); ++
i)
1830 Point aCharDisplacement(
i ? (*pDXArry)[
i-1] : 0,
i ? pDYArry[
i-1] : 0 );
1845 if(!rText.isEmpty())
1849 (*pDXArry)[rText.getLength() - 1]
1858 pVDev->SetMapMode(
MapMode(MapUnit::Map100thMM));
1860 pVDev->GetTextArray( rText, &aMyDXArray, 0, rText.getLength());
1887 size_t nObjects = rSaveList.size();
1888 size_t nObjectsLeft = nObjects;
1890 while ( nObjectsLeft )
1893 size_t nObjectsOfSameSize = 0;
1894 size_t nObjectStartIndex = nObjects - nObjectsLeft;
1896 BSaveStruct* pSave = &rSaveList[nObjectStartIndex];
1899 for (
i = nObjectStartIndex;
i < nObjects; )
1901 nObjectsOfSameSize++;
1902 if ( ++
i < nObjects )
1904 pSave = &rSaveList[
i];
1912 for (
i = nObjectStartIndex;
i < ( nObjectStartIndex + nObjectsOfSameSize );
i++ )
1914 pSave = &rSaveList[
i];
1916 sal_uInt32 nWinRop = pSave->
nWinRop;
1919 sal_uInt32 nUsed = 0;
1920 if ( ( nRasterOperation & 0xf ) != ( nRasterOperation >> 4 ) )
1922 if ( ( nRasterOperation & 0x33 ) != ( ( nRasterOperation & 0xcc ) >> 2 ) )
1924 if ( ( nRasterOperation & 0xaa ) != ( ( nRasterOperation & 0x55 ) << 1 ) )
1927 if ( (nUsed & 1) && (( nUsed & 2 ) == 0) && nWinRop !=
PATINVERT )
1936 bool bDrawn =
false;
1938 if (
i == nObjectStartIndex )
1940 if ( nObjectsOfSameSize == 2 )
1989 sal_uInt32 nOperation = ( nRasterOperation & 0xf );
1990 switch( nOperation )
2008 if ( nOperation == 0x1 )
2020 if ( ( nUsed & 1 ) && ( nRasterOperation & 0xb0 ) == 0xb0 )
2022 aBitmap.
Convert( BmpConversion::N24Bit );
2027 if ( nOperation == 0x7 )
2047 if ( nOperation == 0xb )
2064 if ( nOperation == 0xd )
2076 if ( nOperation == 0x9 )
2096 if ( nRasterOperation == 0x33 )
2124 nObjectsLeft -= nObjectsOfSameSize;
2150 case MappingMode::MM_ANISOTROPIC :
2213 case MappingMode::MM_ANISOTROPIC :
2269 sal_Int32 nWinExtX, nWinExtY;
2270 if (o3tl::checked_multiply<sal_Int32>(
mnMillX, 100, nWinExtX) ||
2271 o3tl::checked_multiply<sal_Int32>(
mnMillY, 100, nWinExtY))
2305 const XForm* pRight;
2322 aF[0][0] = pLeft->
eM11;
2323 aF[0][1] = pLeft->
eM12;
2325 aF[1][0] = pLeft->
eM21;
2326 aF[1][1] = pLeft->
eM22;
2328 aF[2][0] = pLeft->
eDx;
2329 aF[2][1] = pLeft->
eDy;
2332 bF[0][0] = pRight->
eM11;
2333 bF[0][1] = pRight->
eM12;
2335 bF[1][0] = pRight->
eM21;
2336 bF[1][1] = pRight->
eM22;
2338 bF[2][0] = pRight->
eDx;
2339 bF[2][1] = pRight->
eDy;
2343 for (
i = 0;
i < 3;
i++ )
2345 for ( j = 0; j < 3; j++ )
2348 for ( k = 0; k < 3; k++ )
2349 cF[
i][j] += aF[
i][k] * bF[k][j];
2371 auto pSave = std::make_shared<SaveStruct>();
2415 if ( nSavedDC == 0 )
2433 std::shared_ptr<SaveStruct>& pSave(
mvSaveStack.back() );
2491 EMFP_DEBUG(printf (
"\t\t\tadd EMF_PLUS header info\n"));
2494 sal_Int32 nLeft, nRight, nTop, nBottom;
2524 EMFP_DEBUG(printf (
"\t\t\tadd EMF_PLUS comment length %04x\n",(
unsigned int)
nLength));
Bitmap GetBitmap(Color aTransparentReplaceColor) const
const MapMode & GetPrefMapMode() const
const Size & GetPrefSize() const
bool Convert(BmpConversion eConversion)
bool Erase(const Color &rFillColor)
tools::Long GetDescent() const
tools::Long GetAscent() const
void set(size_t nIndex, sal_Int32 nValue)
LineStyle GetStyle() const
constexpr tools::Long Y() const
void setX(tools::Long nX)
void RotateAround(tools::Long &rX, tools::Long &rY, Degree10 nOrientation) const
void setY(tools::Long nY)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() const
constexpr tools::Long Height() const
tools::Long AdjustWidth(tools::Long n)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
void SetSynchronMode(bool bTheSync=true)
std::size_t GetEndOfData() const
virtual sal_uInt64 TellEnd() override
SvStream & WriteInt32(sal_Int32 nInt32)
SvStream & ReadFloat(float &rFloat)
SvStream & WriteFloat(float nFloat)
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
SvLockBytes * GetLockBytes() const
bool decompose(B2DTuple &rScale, B2DTuple &rTranslate, double &rRotate, double &rShearX) const
void translate(double fX, double fY)
B2DRange getB2DRange() const
void intersectPolyPolygon(const B2DPolyPolygon &)
void subtractPolyPolygon(const B2DPolyPolygon &)
void unionPolyPolygon(const B2DPolyPolygon &)
void transform(const B2DHomMatrix &)
B2DPolyPolygon const & getClipPoly() const
void xorPolyPolygon(const B2DPolyPolygon &)
rtl::Reference< MetaFontAction > maCurrentMetaFontAction
void evaluateAlternativeFontScale(OUString const &rText, tools::Long nImportedTextLength)
void endCurrentMetaFontAction()
void applyAlternativeFontScale()
ScaledFontDetectCorrectHelper()
std::vector< double > maAlternativeFontScales
std::vector< std::pair< rtl::Reference< MetaFontAction >, double > > maPositiveIdentifiedCases
std::vector< std::pair< rtl::Reference< MetaFontAction >, double > > maNegativeIdentifiedCases
void newCurrentMetaFontAction(const rtl::Reference< MetaFontAction > &rNewMetaFontAction)
void setClipPath(const basegfx::B2DPolyPolygon &, RegionMode nClippingMode)
basegfx::B2DPolyPolygon const & getClipPath() const
void excludeClip(const basegfx::B2DPolyPolygon &rPolyPolygon)
void setDefaultClipPath()
void intersectClip(const basegfx::B2DPolyPolygon &rPolyPolygon)
basegfx::utils::B2DClipState const & getClip() const
basegfx::utils::B2DClipState maClip
void moveClipRegion(const Size &rSize)
void AddPolyPolygon(const tools::PolyPolygon &rPolyPolygon)
void AddPolyLine(const tools::Polygon &rPoly)
void AddPoint(const Point &rPoint)
void AddPolygon(const tools::Polygon &rPoly)
tools::Long GetFontHeight() const
void SetFontSize(const Size &)
void SetOrientation(Degree10 nLineOrientation)
void SetAverageFontWidth(tools::Long nWidth)
void SetPitch(FontPitch ePitch)
void SetTransparent(bool bTransparent)
void SetFillColor(const Color &)
void SetColor(const Color &)
const OUString & GetStyleName() const
void SetItalic(FontItalic)
void SetWeight(FontWeight)
void SetFontHeight(tools::Long nHeight)
bool IsTransparent() const
tools::Long GetOrCalculateAverageFontWidth() const
const OUString & GetFamilyName() const
void SetFamily(FontFamily)
void SetUnderline(FontLineStyle)
TextAlign GetAlignment() const
void SetCharSet(rtl_TextEncoding)
const Size & GetFontSize() const
const Color & GetColor() const
void SetAlignment(TextAlign)
void SetFamilyName(const OUString &rFamilyName)
Degree10 GetOrientation() const
const Color & GetFillColor() const
tools::Long GetAverageFontWidth() const
void SetStrikeout(FontStrikeout)
constexpr ::Color COL_GRAY(0x80, 0x80, 0x80)
constexpr ::Color COL_WHITE(0xFF, 0xFF, 0xFF)
constexpr ::Color COL_GRAY7(0x66, 0x66, 0x66)
constexpr ::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
UNOTOOLS_DLLPUBLIC OUString utl_getLocaleForGlobalDefaultEncoding()
EmbeddedObjectRef * pObject
std::deque< AttacherIndex_Impl > aIndex
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
bool isRectangle(const B2DPolygon &rPoly)
constexpr double rad2deg(double v)
B2IRange fround(const B2DRange &rRange)
static SvStream & operator>>(SvStream &rStream, sal_Int16 &n)
constexpr sal_uInt32 ENHMETA_STOCK_OBJECT
constexpr sal_Int32 MS_FIXPOINT_BITCOUNT_28_4
constexpr sal_Int32 UNDOCUMENTED_WIN_RCL_RELATION
std::enable_if< std::is_signed< T >::value, bool >::type checked_add(T a, T b, T &result)
std::enable_if< std::is_signed< T >::value, T >::type saturating_toggle_sign(T a)
std::enable_if< std::is_signed< T >::value, bool >::type checked_multiply(T a, T b, T &result)
constexpr Point convert(const Point &rPoint, o3tl::Length eFrom, o3tl::Length eTo)
std::enable_if< std::is_signed< T >::value, bool >::type checked_sub(T a, T b, T &result)
void DrawAndClipBitmap(const Point &rPos, const Size &rSize, const BitmapEx &rBitmap, BitmapEx &aBmpEx, basegfx::B2DPolyPolygon const &rClipPath)
tools::Rectangle aOutRect
sal_uInt8 lfPitchAndFamily
WinMtfFillStyleType aType
WinMtfFontStyle(LOGFONTW const &rLogFont)
std::vector< Color > aPaletteColors
UNOTOOLS_DLLPUBLIC rtl_TextEncoding utl_getWinTextEncodingFromLangStr(const OUString &sLanguage, bool bOEM=false)