/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
constchar *
record_type_name(sal_uInt16 nRecType)
{ #ifndef SAL_LOG_INFO
(void) nRecType; return""; #else switch( nRecType )
{ case W_META_EOF: return"W_META_EOF"; case W_META_SETBKCOLOR: return"META_SETBKCOLOR"; case W_META_SETBKMODE: return"META_SETBKMODE"; case W_META_SETMAPMODE: return"META_SETMAPMODE"; case W_META_SETROP2: return"META_SETROP2"; case W_META_SETRELABS: return"META_SETRELABS"; case W_META_SETPOLYFILLMODE: return"META_SETPOLYFILLMODE"; case W_META_SETSTRETCHBLTMODE: return"META_SETSTRETCHBLTMODE"; case W_META_SETTEXTCHAREXTRA: return"META_SETTEXTCHAREXTRA"; case W_META_SETTEXTCOLOR: return"META_SETTEXTCOLOR"; case W_META_SETTEXTJUSTIFICATION: return"META_SETTEXTJUSTIFICATION"; case W_META_SETWINDOWORG: return"META_SETWINDOWORG"; case W_META_SETWINDOWEXT: return"META_SETWINDOWEXT"; case W_META_SETVIEWPORTORG: return"META_SETVIEWPORTORG"; case W_META_SETVIEWPORTEXT: return"META_SETVIEWPORTEXT"; case W_META_OFFSETWINDOWORG: return"META_OFFSETWINDOWORG"; case W_META_SCALEWINDOWEXT: return"META_SCALEWINDOWEXT"; case W_META_OFFSETVIEWPORTORG: return"META_OFFSETVIEWPORTORG"; case W_META_SCALEVIEWPORTEXT: return"META_SCALEVIEWPORTEXT"; case W_META_LINETO: return"META_LINETO"; case W_META_MOVETO: return"META_MOVETO"; case W_META_EXCLUDECLIPRECT: return"META_EXCLUDECLIPRECT"; case W_META_INTERSECTCLIPRECT: return"META_INTERSECTCLIPRECT"; case W_META_ARC: return"META_ARC"; case W_META_ELLIPSE: return"META_ELLIPSE"; case W_META_FLOODFILL: return"META_FLOODFILL"; case W_META_PIE: return"META_PIE"; case W_META_RECTANGLE: return"META_RECTANGLE"; case W_META_ROUNDRECT: return"META_ROUNDRECT"; case W_META_PATBLT: return"META_PATBLT"; case W_META_SAVEDC: return"META_SAVEDC"; case W_META_SETPIXEL: return"META_SETPIXEL"; case W_META_OFFSETCLIPRGN: return"META_OFFSETCLIPRGN"; case W_META_TEXTOUT: return"META_TEXTOUT"; case W_META_BITBLT: return"META_BITBLT"; case W_META_STRETCHBLT: return"META_STRETCHBLT"; case W_META_POLYGON: return"META_POLYGON"; case W_META_POLYLINE: return"META_POLYLINE"; case W_META_ESCAPE: return"META_ESCAPE"; case W_META_RESTOREDC: return"META_RESTOREDC"; case W_META_FILLREGION: return"META_FILLREGION"; case W_META_FRAMEREGION: return"META_FRAMEREGION"; case W_META_INVERTREGION: return"META_INVERTREGION"; case W_META_PAINTREGION: return"META_PAINTREGION"; case W_META_SELECTCLIPREGION: return"META_SELECTCLIPREGION"; case W_META_SELECTOBJECT: return"META_SELECTOBJECT"; case W_META_SETTEXTALIGN: return"META_SETTEXTALIGN"; case W_META_DRAWTEXT: return"META_DRAWTEXT"; case W_META_CHORD: return"META_CHORD"; case W_META_SETMAPPERFLAGS: return"META_SETMAPPERFLAGS"; case W_META_EXTTEXTOUT: return"META_EXTTEXTOUT"; case W_META_SETDIBTODEV: return"META_SETDIBTODEV"; case W_META_SELECTPALETTE: return"META_SELECTPALETTE"; case W_META_REALIZEPALETTE: return"META_REALIZEPALETTE"; case W_META_ANIMATEPALETTE: return"META_ANIMATEPALETTE"; case W_META_SETPALENTRIES: return"META_SETPALENTRIES"; case W_META_POLYPOLYGON: return"META_POLYPOLYGON"; case W_META_RESIZEPALETTE: return"META_RESIZEPALETTE"; case W_META_DIBBITBLT: return"META_DIBBITBLT"; case W_META_DIBSTRETCHBLT: return"META_DIBSTRETCHBLT"; case W_META_DIBCREATEPATTERNBRUSH: return"META_DIBCREATEPATTERNBRUSH"; case W_META_STRETCHDIB: return"META_STRETCHDIB"; case W_META_EXTFLOODFILL: return"META_EXTFLOODFILL"; case W_META_RESETDC: return"META_RESETDC"; case W_META_STARTDOC: return"META_STARTDOC"; case W_META_STARTPAGE: return"META_STARTPAGE"; case W_META_ENDPAGE: return"META_ENDPAGE"; case W_META_ABORTDOC: return"META_ABORTDOC"; case W_META_ENDDOC: return"META_ENDDOC"; case W_META_DELETEOBJECT: return"META_DELETEOBJECT"; case W_META_CREATEPALETTE: return"META_CREATEPALETTE"; case W_META_CREATEBRUSH: return"META_CREATEBRUSH"; case W_META_CREATEPATTERNBRUSH: return"META_CREATEPATTERNBRUSH"; case W_META_CREATEPENINDIRECT: return"META_CREATEPENINDIRECT"; case W_META_CREATEFONTINDIRECT: return"META_CREATEFONTINDIRECT"; case W_META_CREATEBRUSHINDIRECT: return"META_CREATEBRUSHINDIRECT"; case W_META_CREATEBITMAPINDIRECT: return"META_CREATEBITMAPINDIRECT"; case W_META_CREATEBITMAP: return"META_CREATEBITMAP"; case W_META_CREATEREGION: return"META_CREATEREGION"; default: // Yes, return a pointer to a static buffer. This is a very // local debugging output function, so no big deal. staticchar buffer[11];
o3tl::sprintf(buffer, "0x%08" SAL_PRIxUINT32, sal_uInt32(nRecType)); return buffer;
} #endif
}
}
namespace emfio
{ inline Point WmfReader::ReadPoint()
{ short nX = 0, nY = 0;
mpInputStream->ReadInt16( nX ).ReadInt16( nY ); return Point( nX, nY );
}
inline Point WmfReader::ReadYX()
{ short nX = 0, nY = 0;
mpInputStream->ReadInt16( nY ).ReadInt16( nX ); return Point( nX, nY );
}
tools::Rectangle WmfReader::ReadRectangle()
{
Point aBR, aTL;
aBR = ReadYX();
aTL = ReadYX();
aBR.AdjustX( -1 );
aBR.AdjustY( -1 ); if (aTL.X() > aBR.X() || aTL.Y() > aBR.Y())
{
SAL_WARN("emfio", "broken rectangle"); return tools::Rectangle::Normalize(aTL, aBR);
} return tools::Rectangle( aTL, aBR );
}
case W_META_SETBKMODE:
{ // It could have Reserved values. Both 4 and 5 sizes are allowed if ((nRecordSize != 4) && (nRecordSize != 5))
bRecordOk = false;
sal_uInt16 nDat = 0;
mpInputStream->ReadUInt16( nDat );
SetBkMode( static_cast<BackgroundMode>(nDat) );
} break;
case W_META_SETMAPMODE:
{ if (nRecordSize != 4)
bRecordOk = false;
sal_uInt16 nMapMode = 0;
mpInputStream->ReadUInt16(nMapMode);
SetMapMode(static_cast<MappingMode>(nMapMode));
} break;
case W_META_SETROP2:
{ // It could have Reserved values. Both 4 and 5 sizes are allowed if ((nRecordSize != 4) && (nRecordSize != 5))
bRecordOk = false;
sal_uInt16 nROP2 = 0;
mpInputStream->ReadUInt16(nROP2);
SetRasterOp(static_cast<WMFRasterOp>(nROP2));
mpInputStream->SeekRel(2); // reserved data
} break;
case W_META_SETTEXTCOLOR:
{ if (nRecordSize != 5)
bRecordOk = false;
SetTextColor( ReadColor() );
} break;
case W_META_SETWINDOWORG:
{ if (nRecordSize != 5)
bRecordOk = false;
SetWinOrg( ReadYX() );
} break;
case W_META_SETWINDOWEXT:
{ if (nRecordSize != 5)
bRecordOk = false; short nWidth = 0, nHeight = 0;
mpInputStream->ReadInt16( nHeight ).ReadInt16( nWidth );
SetWinExt( Size( nWidth, nHeight ) );
} break;
case W_META_OFFSETWINDOWORG:
{ if (nRecordSize != 5)
bRecordOk = false; short nXAdd = 0, nYAdd = 0;
mpInputStream->ReadInt16( nYAdd ).ReadInt16( nXAdd );
SetWinOrgOffset( nXAdd, nYAdd );
} break;
case W_META_ELLIPSE:
{ if (nRecordSize != 7)
bRecordOk = false;
DrawEllipse(ReadRectangle());
} break;
case W_META_ARC:
{ if (nRecordSize != 11)
bRecordOk = false;
Point aEnd( ReadYX() );
Point aStart( ReadYX() );
tools::Rectangle aRect( ReadRectangle() );
aRect.Normalize();
DrawArc( aRect, aStart, aEnd );
} break;
case W_META_PIE:
{ if (nRecordSize != 11)
bRecordOk = false;
Point aEnd( ReadYX() );
Point aStart( ReadYX() );
tools::Rectangle aRect( ReadRectangle() );
aRect.Normalize();
// #i73608# OutputDevice deviates from WMF // semantics. start==end means full ellipse here. if( aStart == aEnd )
DrawEllipse( aRect ); else
DrawPie( aRect, aStart, aEnd );
} break;
case W_META_CHORD:
{ if (nRecordSize != 11)
bRecordOk = false;
Point aEnd( ReadYX() );
Point aStart( ReadYX() );
tools::Rectangle aRect( ReadRectangle() );
aRect.Normalize();
DrawChord( aRect, aStart, aEnd );
} break;
case W_META_POLYGON:
{
sal_uInt16 nPoints(0);
mpInputStream->ReadUInt16(nPoints);
if (nPoints > mpInputStream->remainingSize() / (2 * sizeof(sal_uInt16)))
{
bRecordOk = false;
} else
{
tools::Polygon aPoly(nPoints); for (sal_uInt16 i(0); i < nPoints && mpInputStream->good(); ++i)
aPoly[ i ] = ReadPoint();
DrawPolygon(std::move(aPoly), false/*bRecordPath*/);
}
SAL_WARN_IF(!bRecordOk, "emfio", "polygon record has more points than we can handle");
bRecordOk &= mpInputStream->good();
} break;
case W_META_POLYPOLYGON:
{
sal_uInt16 nPolyCount(0); // Number of polygons:
mpInputStream->ReadUInt16( nPolyCount ); if (nPolyCount && mpInputStream->good())
{ if (nPolyCount > mpInputStream->remainingSize() / sizeof(sal_uInt16)) break;
// Number of points of each polygon. Determine total number of points
std::unique_ptr<sal_uInt16[]> xPolygonPointCounts(new sal_uInt16[nPolyCount]);
sal_uInt16* pnPoints = xPolygonPointCounts.get();
tools::PolyPolygon aPolyPoly(nPolyCount);
sal_uInt16 nPoints = 0; for (sal_uInt16 a = 0; a < nPolyCount && mpInputStream->good(); ++a)
{
mpInputStream->ReadUInt16( pnPoints[a] );
// output only makes sense if the text contains characters if (nLen)
{
sal_Int32 nOriginalTextLen = nLen;
sal_Int32 nOriginalBlockLen = ( nOriginalTextLen + 1 ) &~ 1;
auto nMaxStreamPos = nRecordPos + nRecSize; auto nRemainingSize = std::min(mpInputStream->remainingSize(), nMaxStreamPos - mpInputStream->Tell()); if (nRemainingSize < o3tl::make_unsigned(nOriginalBlockLen))
{
SAL_WARN("emfio", "exttextout record claimed more data than the stream can provide");
nOriginalTextLen = nOriginalBlockLen = nRemainingSize;
}
std::vector<char> pChar(nOriginalBlockLen);
mpInputStream->ReadBytes(pChar.data(), nOriginalBlockLen);
OUString aText(pChar.data(), nOriginalTextLen, GetCharSet()); // after this conversion the text may contain
sal_Int32 nNewTextLen = aText.getLength(); // less character (japanese version), so the // dxAry will not fit if ( nNewTextLen )
{ if ( nOptions & ETO_CLIPPED )
{
Push(); // Save the current clip. It will be restored after text drawing
IntersectClipRect( aRect );
}
SAL_INFO( "emfio", "\t\t\t Text : " << aText );
KernArray aDXAry;
std::unique_ptr<tools::Long[]> pDYAry; auto nDxArySize = nMaxStreamPos - mpInputStream->Tell(); auto nDxAryEntries = nDxArySize >> 1; bool bUseDXAry = false;
if ( ( ( nDxAryEntries % nOriginalTextLen ) == 0 ) && ( nNewTextLen <= nOriginalTextLen ) )
{
sal_Int32 i; // needed just outside the for
aDXAry.resize( nNewTextLen ); if ( nOptions & ETO_PDY )
{
pDYAry.reset(new tools::Long[ nNewTextLen ]);
} for (i = 0; i < nNewTextLen; i++ )
{ if ( mpInputStream->Tell() >= nMaxStreamPos ) break;
sal_Int32 nDxCount = 1; if ( nNewTextLen != nOriginalTextLen )
{
sal_Unicode cUniChar = aText[i];
OString aTmp(&cUniChar, 1, GetCharSet()); if ( aTmp.getLength() > 1 )
{
nDxCount = aTmp.getLength();
}
}
case W_META_SELECTOBJECT: case W_META_SELECTPALETTE:
{ if (nRecordSize != 4)
bRecordOk = false;
sal_uInt16 nObjIndex = 0;
mpInputStream->ReadUInt16( nObjIndex );
SelectObject( nObjIndex );
} break;
case W_META_SETTEXTALIGN:
{ // It could have Reserved values. Both 4 and 5 sizes are allowed if ((nRecordSize != 4) && (nRecordSize != 5))
bRecordOk = false;
sal_uInt16 nAlign = 0;
mpInputStream->ReadUInt16( nAlign );
SetTextAlign( nAlign );
} break;
// nSrcHeight and nSrcWidth is the number of pixels that has to been used // If they are set to zero, it is as indicator not to scale the bitmap later if( nFunc == W_META_DIBSTRETCHBLT ||
nFunc == W_META_STRETCHDIB )
mpInputStream->ReadInt16( nSrcHeight ).ReadInt16( nSrcWidth );
// nYSrc and nXSrc is the offset of the first pixel
mpInputStream->ReadInt16( nYSrc ).ReadInt16( nXSrc );
if ( bNoSourceBitmap )
mpInputStream->SeekRel( 2 ); // Skip Reserved 2 bytes (it must be ignored)
Size aDestSize( ReadYXExt() ); if ( aDestSize.Width() && aDestSize.Height() ) // #92623# do not try to read buggy bitmaps
{
tools::Rectangle aDestRect( ReadYX(), aDestSize ); if ( !bNoSourceBitmap )
{ // tdf#142625 Read the DIBHeader and check if bitmap is supported // If bitmap is not supported don't run ReadDIB, as it will interrupt image processing constauto nOldPos(mpInputStream->Tell());
sal_uInt32 nHeaderSize(0);
mpInputStream->ReadUInt32( nHeaderSize ); if ( nHeaderSize == 0xC ) // BitmapCoreHeader
mpInputStream->SeekRel( 6 ); // skip Width (16), Height (16), Planes (16) else
mpInputStream->SeekRel( 10 ); // skip Width (32), Height (32), Planes (16)
sal_uInt16 nBitCount(0);
mpInputStream->ReadUInt16( nBitCount ); if ( nBitCount == 0 ) // TODO Undefined BitCount (JPEG/PNG), which are not supported break;
mpInputStream->Seek(nOldPos);
if ( !ReadDIB( aBmp, *mpInputStream, false ) )
SAL_WARN( "emfio", "\tTODO Read DIB failed. Interrupting processing whole image. Please report bug report." );
} // test if it is sensible to crop if ( nSrcHeight && nSrcWidth &&
( nXSrc + nSrcWidth <= aBmp.GetSizePixel().Width() ) &&
( nYSrc + nSrcHeight <= aBmp.GetSizePixel().Height() ) )
{
tools::Rectangle aCropRect( Point( nXSrc, nYSrc ), Size( nSrcWidth, nSrcHeight ) );
aBmp.Crop( aCropRect );
}
if (nRecordSize != 2u * nNumberOfEntries + 5u)
bRecordOk = false;
SAL_INFO("emfio", "\t\t Start 0x" << std::hex << nStart << std::dec << ", Number of entries: " << nNumberOfEntries);
sal_uInt32 nPalleteEntry;
std::vector< Color > aPaletteColors; for (sal_uInt16 i = 0; i < nNumberOfEntries; ++i)
{ //PALETTEENTRY: Values, Blue, Green, Red
mpInputStream->ReadUInt32( nPalleteEntry );
SAL_INFO("emfio", "\t\t " << i << ". Palette entry: " << std::setw(10) << std::showbase <<std::hex << nPalleteEntry << std::dec );
aPaletteColors.emplace_back(static_cast<sal_uInt8>(nPalleteEntry), static_cast<sal_uInt8>(nPalleteEntry >> 8), static_cast<sal_uInt8>(nPalleteEntry >> 16));
}
CreateObject(std::make_unique<WinMtfPalette>( aPaletteColors ));
} break;
case W_META_CREATEBRUSH:
{
SAL_WARN( "emfio", "TODO: Not implemented. Please fill the bug report" );
CreateObject(std::make_unique<WinMtfFillStyle>( COL_WHITE, false ));
} break;
case W_META_CREATEPATTERNBRUSH:
{
SAL_WARN( "emfio", "TODO: Not implemented. Please fill the bug report" );
CreateObject(std::make_unique<WinMtfFillStyle>( COL_WHITE, false ));
} break;
case W_META_CREATEPENINDIRECT:
{ // FIXME For some WMF correct size is 8 and for some 9 if ((nRecordSize != 8) && (nRecordSize != 9))
bRecordOk = false;
LineInfo aLineInfo;
sal_uInt16 nStyle = 0;
sal_uInt16 nWidth = 0;
sal_uInt16 nHeight = 0;
case W_META_CREATEBITMAPINDIRECT:
{
SAL_WARN( "emfio", "TODO: W_META_CREATEBITMAPINDIRECT is not implemented. Please fill the bug report" );
CreateObject();
} break;
case W_META_CREATEBITMAP:
{
SAL_WARN( "emfio", "TODO: W_META_CREATEBITMAP is not implemented. Please fill the bug report" );
CreateObject();
} break;
case W_META_CREATEREGION:
{
SAL_WARN( "emfio", "TODO: W_META_CREATEREGION is not implemented. Please fill the bug report" );
CreateObject();
} break;
case W_META_EXCLUDECLIPRECT:
{ if (nRecordSize != 7)
bRecordOk = false;
SAL_WARN("emfio", "TODO: Not working correctly. Please fill the bug report");
ExcludeClipRect(ReadRectangle());
} break;
if ((static_cast<sal_uInt64>(nEscLen) + mpInputStream->Tell())
> nMetaRecEndPos)
{
mpInputStream->SetError(SVSTREAM_FILEFORMAT_ERROR); break;
} if (nEscLen > 0)
{
pData.reset(new sal_Int8[nEscLen]);
mpInputStream->ReadBytes(pData.get(), nEscLen);
nCheckSum = rtl_crc32(nCheckSum, pData.get(), nEscLen);
} if (nCheck == nCheckSum)
{ switch (nEsc)
{ case PRIVATE_ESCAPE_UNICODE:
{ // we will use text instead of polygons only if we have the correct font if (Application::GetDefaultDevice()->IsFontAvailable(
GetFont().GetFamilyName()))
{
Point aPt;
sal_uInt32 nStringLen, nDXCount;
KernArray aDXAry;
SvMemoryStream aMemoryStream(nEscLen);
aMemoryStream.WriteBytes(pData.get(), nEscLen);
aMemoryStream.Seek(STREAM_SEEK_TO_BEGIN);
sal_Int32 nTmpX(0), nTmpY(0);
aMemoryStream.ReadInt32(nTmpX)
.ReadInt32(nTmpY)
.ReadUInt32(nStringLen);
aPt.setX(nTmpX);
aPt.setY(nTmpY);
mpInputStream->ReadUInt32(nComType)
.ReadUInt32(nVersion)
.ReadUInt16(nCheck)
.ReadUInt32(nFlags)
.ReadUInt32(nComRecCount)
.ReadUInt32(nCurRecSize)
.ReadUInt32(nRemainingSize)
.ReadUInt32(
nEMFTotalSize); // the nRemainingSize is not mentioned in MSDN documentation // but it seems to be required to read in data produced by OLE
if (nComType == 0x01 && nVersion == 0x10000 && nComRecCount)
{ if (!mnEMFRec)
{ // first EMF comment
mnEMFRecCount = nComRecCount;
mnEMFSize = nEMFTotalSize; if (mnEMFSize > mpInputStream->remainingSize())
{
SAL_WARN("emfio", "emf size claims to be larger than remaining data");
mpEMFStream.reset();
} else
mpEMFStream = std::vector<sal_uInt8>();
} elseif ((mnEMFRecCount != nComRecCount)
|| (mnEMFSize != nEMFTotalSize)) // add additional checks here
{ // total records should be the same as in previous comments
mnEMFRecCount = 0xFFFFFFFF;
mpEMFStream.reset();
}
mnEMFRec++;
if (mpEMFStream && nCurRecSize > mpInputStream->remainingSize())
{
SAL_WARN("emfio", "emf record size claims to be larger than remaining data");
mnEMFRecCount = 0xFFFFFFFF;
mpEMFStream.reset();
}
case W_META_SETRELABS: case W_META_SETPOLYFILLMODE: case W_META_SETSTRETCHBLTMODE: case W_META_SETTEXTCHAREXTRA: case W_META_SETTEXTJUSTIFICATION: case W_META_FLOODFILL: case W_META_FILLREGION: case W_META_FRAMEREGION: case W_META_INVERTREGION: case W_META_PAINTREGION: case W_META_DRAWTEXT: case W_META_SETMAPPERFLAGS: case W_META_SETDIBTODEV: case W_META_REALIZEPALETTE: case W_META_ANIMATEPALETTE: case W_META_SETPALENTRIES: case W_META_RESIZEPALETTE: case W_META_EXTFLOODFILL: case W_META_RESETDC: case W_META_STARTDOC: case W_META_STARTPAGE: case W_META_ENDPAGE: case W_META_ABORTDOC: case W_META_ENDDOC:
{
SAL_WARN("emfio", "TODO: WMF record not implemented: " << record_type_name(nFunc));
} break;
sal_uInt32 nPlaceableMetaKey(0); // if available read the METAFILEHEADER
mpInputStream->ReadUInt32( nPlaceableMetaKey ); if (!mpInputStream->good()) returnfalse;
if (mbPlaceable)
{ //TODO do some real error handling here
sal_Int16 nVal(0);
// Skip reserved bytes
mpInputStream->SeekRel(2);
// BoundRect // These are simply ignored for now
mpInputStream->ReadInt16( nVal );
aPlaceableBound.SetLeft( nVal );
mpInputStream->ReadInt16( nVal );
aPlaceableBound.SetTop( nVal );
mpInputStream->ReadInt16( nVal );
aPlaceableBound.SetRight( nVal );
mpInputStream->ReadInt16( nVal );
aPlaceableBound.SetBottom( nVal );
// inch
mpInputStream->ReadUInt16( mnUnitsPerInch );
// reserved
mpInputStream->SeekRel( 4 );
// Skip and don't check the checksum
mpInputStream->SeekRel( 2 );
// Skip wmf header
mpInputStream->Seek( nStrmPos + 40 ); // set the streampos to the start of the metaactions
GetPlaceableBound( aPlaceableBound, mpInputStream ); // Go back to the place after placeable header
mpInputStream->Seek( nStrmPos + 22);
} else
{ // Default is 1440, but it is set to 96 to show the wmf larger
mnUnitsPerInch = 96;
if (mpExternalHeader != nullptr
&& mpExternalHeader->xExt > 0
&& mpExternalHeader->yExt > 0
&& (mpExternalHeader->mapMode == MappingMode::MM_ISOTROPIC || mpExternalHeader->mapMode == MappingMode::MM_ANISOTROPIC))
{ // #n417818#: If we have an external header then overwrite the bounds!
tools::Rectangle aExtRect(0, 0,
o3tl::convert(mpExternalHeader->xExt, o3tl::Length::mm100, o3tl::Length::px),
o3tl::convert(mpExternalHeader->yExt, o3tl::Length::mm100, o3tl::Length::px));
aPlaceableBound = aExtRect;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.