Rebased ref, commits from common ancestor: commit ab69b886b4f54f7a6d42fe4faa03479d6ef0d9ee Author: Armin Le Grand <armin.le.gr...@cib.de> Date: Thu Jun 22 13:03:50 2017 +0200
emfplus: unified transformations, added test code More unifications, changed all Map*() methods to use a single B2DHomMatrix which is created based on former stuff, XForm now completely replaced. To check, added debug-only code and switches to the VclPixelProcessor so that visual checks get easy when using these modes (overlay of both methods with modded colors). Also resynched to master. Change-Id: I7b749f90bfde2ec1c2e49ee90ca2ef368da0547e diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 4b5e45c7ef04..de9b7ad2f6b6 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -860,17 +860,52 @@ namespace drawinglayer const primitive2d::MetafilePrimitive2D& rMetafilePrimitive( static_cast< const primitive2d::MetafilePrimitive2D& >(rCandidate) ); - static bool bTestMetaFilePrimitiveDecomposition( true ); - if( bTestMetaFilePrimitiveDecomposition && !rMetafilePrimitive.getMetaFile().GetUseCanvas() ) + if( !rMetafilePrimitive.getMetaFile().GetUseCanvas() ) { // use new Metafile decomposition - // TODO EMF+ stuffed into METACOMMENT support required process(rCandidate); } else { +#ifdef DBG_UTIL + // switch to test EMFPlus-enhanced MetafileDecomposition + static bool bTestEMFPDecomposition(true); + // switch to show the new visualization color.-changed behind + // the original output vor visual testing + static bool bUseChangedColorObject(true); + + if (bTestEMFPDecomposition) + { + if (bUseChangedColorObject) + { + primitive2d::Primitive2DContainer aDecomposition; + rMetafilePrimitive.get2DDecomposition(aDecomposition, getViewInformation2D()); + const primitive2d::ModifiedColorPrimitive2D aPrimitiveR( + aDecomposition, + basegfx::BColorModifierSharedPtr( + new basegfx::BColorModifier_RGBLuminanceContrast( + 0.5, // red + -0.5, // green + -0.5, // blue + 0.0, // luminance + 0.0))); // contrast + processBasePrimitive2D(aPrimitiveR); + RenderMetafilePrimitive2D(rMetafilePrimitive); + } + else + { + process(rCandidate); + } + } + else + { + // direct draw of MetaFile + RenderMetafilePrimitive2D(rMetafilePrimitive); + } +#else // DBG_UTIL // direct draw of MetaFile - RenderMetafilePrimitive2D( rMetafilePrimitive ); + RenderMetafilePrimitive2D(rMetafilePrimitive); +#endif // DBG_UTIL } if(bForceLineSnap) diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx index 80d9a7f3fafa..c9ed51e8b5ca 100644 --- a/drawinglayer/source/tools/emfphelperdata.cxx +++ b/drawinglayer/source/tools/emfphelperdata.cxx @@ -131,14 +131,14 @@ namespace emfplushelper case EmfPlusObjectTypeBrush: { EMFPBrush *brush; - aObjects[index].reset(brush = new EMFPBrush()); + maEMFPObjects[index].reset(brush = new EMFPBrush()); brush->Read(rObjectStream, *this); break; } case EmfPlusObjectTypePen: { EMFPPen *pen; - aObjects[index].reset(pen = new EMFPPen()); + maEMFPObjects[index].reset(pen = new EMFPPen()); pen->Read(rObjectStream, *this); break; } @@ -151,21 +151,21 @@ namespace emfplushelper SAL_INFO("cppcanvas.emf", "EMF+\tpath"); SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " points: " << std::dec << points << " additional flags: 0x" << std::hex << pathFlags << std::dec); EMFPPath *path; - aObjects[index].reset(path = new EMFPPath(points)); + maEMFPObjects[index].reset(path = new EMFPPath(points)); path->Read(rObjectStream, pathFlags, *this); break; } case EmfPlusObjectTypeRegion: { EMFPRegion *region; - aObjects[index].reset(region = new EMFPRegion()); + maEMFPObjects[index].reset(region = new EMFPRegion()); region->Read(rObjectStream); break; } case EmfPlusObjectTypeImage: { EMFPImage *image; - aObjects[index].reset(image = new EMFPImage); + maEMFPObjects[index].reset(image = new EMFPImage); image->type = 0; image->width = 0; image->height = 0; @@ -177,7 +177,7 @@ namespace emfplushelper case EmfPlusObjectTypeFont: { EMFPFont *font; - aObjects[index].reset(font = new EMFPFont); + maEMFPObjects[index].reset(font = new EMFPFont); font->emSize = 0; font->sizeUnit = 0; font->fontFlags = 0; @@ -187,7 +187,7 @@ namespace emfplushelper case EmfPlusObjectTypeStringFormat: { EMFPStringFormat *stringFormat; - aObjects[index].reset(stringFormat = new EMFPStringFormat()); + maEMFPObjects[index].reset(stringFormat = new EMFPStringFormat()); stringFormat->Read(rObjectStream); break; } @@ -287,49 +287,39 @@ namespace emfplushelper return true; } - void EmfPlusHelperData::MapToDevice(double& x, double& y) + void EmfPlusHelperData::mappingChanged() { - // TODO: other units - x = 100 * mnMmX*x / mnPixX; - y = 100 * mnMmY*y / mnPixY; + // Call when mnMmX/mnMmY/mnPixX/mnPixY/mnFrameLeft/mnFrameTop/maWorldTransform/ changes. + // Currently not used are mnHDPI/mnVDPI/mnFrameRight/mnFrameBottom. *If* these should + // be used in the future, this method will need to be called. + // + // Re-calculate maMapTransform to contain the complete former transformation so that + // it can be applied by a single matrix multiplication or be added to an encapsulated + // primitive later + // + // To evtl. correct and see where this came from, please compare with the implementations + // of EmfPlusHelperData::MapToDevice and EmfPlusHelperData::Map* in prev versions + maMapTransform = maWorldTransform; + maMapTransform *= basegfx::tools::createScaleB2DHomMatrix(100.0 * mnMmX / mnPixX, 100.0 * mnMmY / mnPixY); + maMapTransform *= basegfx::tools::createTranslateB2DHomMatrix(double(-mnFrameLeft), double(-mnFrameTop)); + maMapTransform *= basegfx::tools::createScaleB2DHomMatrix(maBaseTransform.get(0, 0), maBaseTransform.get(1, 1)); } ::basegfx::B2DPoint EmfPlusHelperData::Map(double ix, double iy) { - double x, y; - - x = ix*aWorldTransform.get(0,0) + iy*aWorldTransform.get(0,1) + aWorldTransform.get(0,2); - y = ix*aWorldTransform.get(1,0) + iy*aWorldTransform.get(1,1) + aWorldTransform.get(1,2); - - MapToDevice(x, y); - - x -= mnFrameLeft; - y -= mnFrameTop; - - x *= aBaseTransform.get(0,0); - y *= aBaseTransform.get(1,1); - - return ::basegfx::B2DPoint(x, y); + // map in one step using complete MapTransform (see mappingChanged) + return maMapTransform * ::basegfx::B2DPoint(ix, iy); } ::basegfx::B2DSize EmfPlusHelperData::MapSize(double iwidth, double iheight) { - double w, h; - - w = iwidth*aWorldTransform.get(0,0) + iheight*aWorldTransform.get(1,0); - h = iwidth*aWorldTransform.get(1,0) + iheight*aWorldTransform.get(1,1); - - MapToDevice(w, h); - - w *= aBaseTransform.get(0,0); - h *= aBaseTransform.get(1,1); - - return ::basegfx::B2DSize(w, h); + // map in one step using complete MapTransform (see mappingChanged) + return maMapTransform * ::basegfx::B2DSize(iwidth, iheight); } void EmfPlusHelperData::EMFPPlusDrawPolygon(const ::basegfx::B2DPolyPolygon& polygon, sal_uInt32 penIndex) { - const EMFPPen* pen = static_cast<EMFPPen*>(aObjects[penIndex & 0xff].get()); + const EMFPPen* pen = static_cast<EMFPPen*>(maEMFPObjects[penIndex & 0xff].get()); SAL_WARN_IF(!pen, "cppcanvas.emf", "emf+ missing pen"); if (pen && polygon.count()) @@ -359,14 +349,15 @@ namespace emfplushelper SvMemoryStream& rMS, wmfemfhelper::TargetHolders& rTargetHolders, wmfemfhelper::PropertyHolders& rPropertyHolders) - : aBaseTransform(), - aWorldTransform(), - aObjects(), - fPageScale(0.0), - nOriginX(0), - nOriginY(0), - nHDPI(0), - nVDPI(0), + : maBaseTransform(), + maWorldTransform(), + maMapTransform(), + maEMFPObjects(), + mfPageScale(0.0), + mnOriginX(0), + mnOriginY(0), + mnHDPI(0), + mnVDPI(0), mnFrameLeft(0), mnFrameTop(0), mnFrameRight(0), @@ -387,7 +378,8 @@ namespace emfplushelper SAL_INFO("cppcanvas.emf", "EMF+ picture frame: " << mnFrameLeft << "," << mnFrameTop << " - " << mnFrameRight << "," << mnFrameBottom); rMS.ReadInt32(mnPixX).ReadInt32(mnPixY).ReadInt32(mnMmX).ReadInt32(mnMmY); SAL_INFO("cppcanvas.emf", "EMF+ ref device pixel size: " << mnPixX << "x" << mnPixY << " mm size: " << mnMmX << "x" << mnMmY); - readXForm(rMS, aBaseTransform); + readXForm(rMS, maBaseTransform); + mappingChanged(); } EmfPlusHelperData::~EmfPlusHelperData() @@ -466,9 +458,9 @@ namespace emfplushelper { sal_uInt32 header, version; - rMS.ReadUInt32(header).ReadUInt32(version).ReadInt32(nHDPI).ReadInt32(nVDPI); + rMS.ReadUInt32(header).ReadUInt32(version).ReadInt32(mnHDPI).ReadInt32(mnVDPI); SAL_INFO("cppcanvas.emf", "EMF+ Header"); - SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " version: " << std::dec << version << " horizontal DPI: " << nHDPI << " vertical DPI: " << nVDPI << " dual: " << (flags & 1)); + SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " version: " << std::dec << version << " horizontal DPI: " << mnHDPI << " vertical DPI: " << mnVDPI << " dual: " << (flags & 1)); break; } case EmfPlusRecordTypeEndOfFile: @@ -573,8 +565,8 @@ namespace emfplushelper rMS.ReadUInt32(brushIndexOrColor); SAL_INFO("cppcanvas.emf", "EMF+ FillPath slot: " << index); - EMFPPlusFillPolygon(static_cast<EMFPPath*>(aObjects[index].get())->GetPolygon(*this), flags & 0x8000, brushIndexOrColor); - // EMFPPlusFillPolygon(static_cast<EMFPPath*>(aObjects[index])->GetPolygon(*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor); + EMFPPlusFillPolygon(static_cast<EMFPPath*>(maEMFPObjects[index].get())->GetPolygon(*this), flags & 0x8000, brushIndexOrColor); + // EMFPPlusFillPolygon(static_cast<EMFPPath*>(maEMFPObjects[index])->GetPolygon(*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor); } break; case EmfPlusRecordTypeDrawEllipse: @@ -705,7 +697,7 @@ namespace emfplushelper rMS.ReadUInt32(penIndex); SAL_INFO("cppcanvas.emf", "EMF+ DrawPath"); SAL_INFO("cppcanvas.emf", "EMF+\tpen: " << penIndex); - EMFPPath* path = static_cast<EMFPPath*>(aObjects[flags & 0xff].get()); + EMFPPath* path = static_cast<EMFPPath*>(maEMFPObjects[flags & 0xff].get()); SAL_WARN_IF(!path, "cppcanvas.emf", "EmfPlusRecordTypeDrawPath missing path"); EMFPPlusDrawPolygon(path->GetPolygon(*this), penIndex); @@ -768,10 +760,10 @@ namespace emfplushelper SAL_INFO("cppcanvas.emf", "EMF+ " << (type == EmfPlusRecordTypeDrawImagePoints ? "DrawImagePoints" : "DrawImage") << "attributes index: " << attrIndex << "source unit: " << sourceUnit); SAL_INFO("cppcanvas.emf", "EMF+\tTODO: use image attributes"); - if (sourceUnit == 2 && aObjects[flags & 0xff].get()) + if (sourceUnit == 2 && maEMFPObjects[flags & 0xff].get()) { // we handle only GraphicsUnit.Pixel now - EMFPImage& image = *static_cast<EMFPImage *>(aObjects[flags & 0xff].get()); + EMFPImage& image = *static_cast<EMFPImage *>(maEMFPObjects[flags & 0xff].get()); float sx, sy, sw, sh; sal_Int32 aCount; ReadRectangle(rMS, sx, sy, sw, sh); @@ -867,7 +859,7 @@ namespace emfplushelper rMS.ReadFloat(lx).ReadFloat(ly).ReadFloat(lw).ReadFloat(lh); SAL_INFO("cppcanvas.emf", "EMF+ DrawString layoutRect: " << lx << "," << ly << " - " << lw << "x" << lh); OUString text = read_uInt16s_ToOUString(rMS, stringLength); - EMFPStringFormat *stringFormat = static_cast< EMFPStringFormat* >(aObjects[formatId & 0xff].get()); + EMFPStringFormat *stringFormat = static_cast< EMFPStringFormat* >(maEMFPObjects[formatId & 0xff].get()); // css::rendering::FontRequest aFontRequest; // // if (stringFormat) @@ -922,9 +914,9 @@ namespace emfplushelper } case EmfPlusRecordTypeSetPageTransform: { - rMS.ReadFloat(fPageScale); + rMS.ReadFloat(mfPageScale); SAL_INFO("cppcanvas.emf", "EMF+ SetPageTransform"); - SAL_INFO("cppcanvas.emf", "EMF+\tscale: " << fPageScale << " unit: " << flags); + SAL_INFO("cppcanvas.emf", "EMF+\tscale: " << mfPageScale << " unit: " << flags); if (flags != UnitTypePixel) { @@ -932,16 +924,17 @@ namespace emfplushelper } else { - mnMmX *= fPageScale; - mnMmY *= fPageScale; + mnMmX *= mfPageScale; + mnMmY *= mfPageScale; + mappingChanged(); } break; } case EmfPlusRecordTypeSetRenderingOrigin: { - rMS.ReadInt32(nOriginX).ReadInt32(nOriginY); + rMS.ReadInt32(mnOriginX).ReadInt32(mnOriginY); SAL_INFO("cppcanvas.emf", "EMF+ SetRenderingOrigin"); - SAL_INFO("cppcanvas.emf", "EMF+\torigin [x,y]: " << nOriginX << "," << nOriginY); + SAL_INFO("cppcanvas.emf", "EMF+\torigin [x,y]: " << mnOriginX << "," << mnOriginY); break; } case EmfPlusRecordTypeSetTextRenderingHint: @@ -1017,17 +1010,19 @@ namespace emfplushelper SAL_INFO("cppcanvas.emf", "EMF+ SetWorldTransform"); basegfx::B2DHomMatrix transform; readXForm(rMS, transform); - aWorldTransform = transform; + maWorldTransform = transform; + mappingChanged(); SAL_INFO("cppcanvas.emf", - "EMF+\tm11: " << aWorldTransform.get(0,0) << "\tm12: " << aWorldTransform.get(1,0) << - "\tm21: " << aWorldTransform.get(0,1) << "\tm22: " << aWorldTransform.get(1,1) << - "\tdx: " << aWorldTransform.get(0,2) << "\tdy: " << aWorldTransform.get(1,2)); + "EMF+\tm11: " << maWorldTransform.get(0,0) << "\tm12: " << maWorldTransform.get(1,0) << + "\tm21: " << maWorldTransform.get(0,1) << "\tm22: " << maWorldTransform.get(1,1) << + "\tdx: " << maWorldTransform.get(0,2) << "\tdy: " << maWorldTransform.get(1,2)); break; } case EmfPlusRecordTypeResetWorldTransform: { SAL_INFO("cppcanvas.emf", "EMF+ ResetWorldTransform"); - aWorldTransform.identity(); + maWorldTransform.identity(); + mappingChanged(); break; } case EmfPlusRecordTypeMultiplyWorldTransform: @@ -1044,19 +1039,21 @@ namespace emfplushelper if (flags & 0x2000) { // post multiply - aWorldTransform *= transform; + maWorldTransform *= transform; } else { // pre multiply - transform *= aWorldTransform; - aWorldTransform = transform; + transform *= maWorldTransform; + maWorldTransform = transform; } + mappingChanged(); + SAL_INFO("cppcanvas.emf", - "EMF+\tmatrix m11: " << aWorldTransform.get(0, 0) << "m12: " << aWorldTransform.get(0, 1) << - "EMF+\tm21: " << aWorldTransform.get(1, 0) << "m22: " << aWorldTransform.get(1, 1) << - "EMF+\tdx: " << aWorldTransform.get(2, 0) << "dy: " << aWorldTransform.get(2, 1)); + "EMF+\tmatrix m11: " << maWorldTransform.get(0, 0) << "m12: " << maWorldTransform.get(0, 1) << + "EMF+\tm21: " << maWorldTransform.get(1, 0) << "m22: " << maWorldTransform.get(1, 1) << + "EMF+\tdx: " << maWorldTransform.get(2, 0) << "dy: " << maWorldTransform.get(2, 1)); break; } case EmfPlusRecordTypeTranslateWorldTransform: @@ -1077,19 +1074,21 @@ namespace emfplushelper if (flags & 0x2000) { // post multiply - aWorldTransform *= transform; + maWorldTransform *= transform; } else { // pre multiply - transform *= aWorldTransform; - aWorldTransform = transform; + transform *= maWorldTransform; + maWorldTransform = transform; } + mappingChanged(); + SAL_INFO("cppcanvas.emf", - "EMF+\tmatrix m11: " << aWorldTransform.get(0, 0) << "m12: " << aWorldTransform.get(0, 1) << - "EMF+\tm21: " << aWorldTransform.get(1, 0) << "m22: " << aWorldTransform.get(1, 1) << - "EMF+\tdx: " << aWorldTransform.get(2, 0) << "dy: " << aWorldTransform.get(2, 1)); + "EMF+\tmatrix m11: " << maWorldTransform.get(0, 0) << "m12: " << maWorldTransform.get(0, 1) << + "EMF+\tm21: " << maWorldTransform.get(1, 0) << "m22: " << maWorldTransform.get(1, 1) << + "EMF+\tdx: " << maWorldTransform.get(2, 0) << "dy: " << maWorldTransform.get(2, 1)); break; } case EmfPlusRecordTypeScaleWorldTransform: @@ -1102,26 +1101,28 @@ namespace emfplushelper SAL_INFO("cppcanvas.emf", "EMF+ ScaleWorldTransform Sx: " << transform.get(0,0) << " Sy: " << transform.get(1,1)); SAL_INFO("cppcanvas.emf", - "EMF+\t m11: " << aWorldTransform.get(0,0) << ", m12: " << aWorldTransform.get(0,1) << - "EMF+\t m21: " << aWorldTransform.get(1,0) << ", m22: " << aWorldTransform.get(1,1) << - "EMF+\t dx: " << aWorldTransform.get(2,0) << ", dy: " << aWorldTransform.get(2,1)); + "EMF+\t m11: " << maWorldTransform.get(0,0) << ", m12: " << maWorldTransform.get(0,1) << + "EMF+\t m21: " << maWorldTransform.get(1,0) << ", m22: " << maWorldTransform.get(1,1) << + "EMF+\t dx: " << maWorldTransform.get(2,0) << ", dy: " << maWorldTransform.get(2,1)); if (flags & 0x2000) { // post multiply - aWorldTransform *= transform; + maWorldTransform *= transform; } else { // pre multiply - transform *= aWorldTransform; - aWorldTransform = transform; + transform *= maWorldTransform; + maWorldTransform = transform; } + mappingChanged(); + SAL_INFO("cppcanvas.emf", - "EMF+\t m11: " << aWorldTransform.get(0, 0) << ", m12: " << aWorldTransform.get(0, 1) << - "EMF+\t m21: " << aWorldTransform.get(1, 0) << ", m22: " << aWorldTransform.get(1, 1) << - "EMF+\t dx: " << aWorldTransform.get(2, 0) << ", dy: " << aWorldTransform.get(2, 1)); + "EMF+\t m11: " << maWorldTransform.get(0, 0) << ", m12: " << maWorldTransform.get(0, 1) << + "EMF+\t m21: " << maWorldTransform.get(1, 0) << ", m22: " << maWorldTransform.get(1, 1) << + "EMF+\t dx: " << maWorldTransform.get(2, 0) << ", dy: " << maWorldTransform.get(2, 1)); break; } case EmfPlusRecordTypeSetClipRect: @@ -1161,7 +1162,7 @@ namespace emfplushelper SAL_INFO("cppcanvas.emf", "EMF+ SetClipPath combine mode: " << combineMode); SAL_INFO("cppcanvas.emf", "EMF+\tpath in slot: " << (flags & 0xff)); - EMFPPath& path = *static_cast<EMFPPath*>(aObjects[flags & 0xff].get()); + EMFPPath& path = *static_cast<EMFPPath*>(maEMFPObjects[flags & 0xff].get()); ::basegfx::B2DPolyPolygon& clipPoly(path.GetPolygon(*this)); // clipPoly.transform(rState.mapModeTransform); @@ -1192,7 +1193,7 @@ namespace emfplushelper int combineMode = (flags >> 8) & 0xf; SAL_INFO("cppcanvas.emf", "EMF+ SetClipRegion"); SAL_INFO("cppcanvas.emf", "EMF+\tregion in slot: " << (flags & 0xff) << " combine mode: " << combineMode); - EMFPRegion *region = static_cast<EMFPRegion*>(aObjects[flags & 0xff].get()); + EMFPRegion *region = static_cast<EMFPRegion*>(maEMFPObjects[flags & 0xff].get()); // reset clip if (region && region->parts == 0 && region->initialState == EmfPlusRegionInitialStateInfinite) diff --git a/drawinglayer/source/tools/emfphelperdata.hxx b/drawinglayer/source/tools/emfphelperdata.hxx index c2d799cfd5f5..290fd4a0ad8a 100644 --- a/drawinglayer/source/tools/emfphelperdata.hxx +++ b/drawinglayer/source/tools/emfphelperdata.hxx @@ -171,7 +171,7 @@ namespace emfplushelper // typedef struct // { -// basegfx::B2DHomMatrix aWorldTransform; +// basegfx::B2DHomMatrix maWorldTransform; // OutDevState aDevState; // } EmfPlusGraphicState; // @@ -181,29 +181,31 @@ namespace emfplushelper { private: /* EMF+ */ - basegfx::B2DHomMatrix aBaseTransform; - basegfx::B2DHomMatrix aWorldTransform; - std::unique_ptr<EMFPObject> aObjects[256]; - float fPageScale; - sal_Int32 nOriginX; - sal_Int32 nOriginY; - sal_Int32 nHDPI; - sal_Int32 nVDPI; + basegfx::B2DHomMatrix maBaseTransform; + basegfx::B2DHomMatrix maWorldTransform; + basegfx::B2DHomMatrix maMapTransform; + + std::unique_ptr<EMFPObject> maEMFPObjects[256]; + float mfPageScale; + sal_Int32 mnOriginX; + sal_Int32 mnOriginY; + sal_Int32 mnHDPI; + sal_Int32 mnVDPI; /* EMF+ emf header info */ - sal_Int32 mnFrameLeft; - sal_Int32 mnFrameTop; - sal_Int32 mnFrameRight; - sal_Int32 mnFrameBottom; - sal_Int32 mnPixX; - sal_Int32 mnPixY; - sal_Int32 mnMmX; - sal_Int32 mnMmY; + sal_Int32 mnFrameLeft; + sal_Int32 mnFrameTop; + sal_Int32 mnFrameRight; + sal_Int32 mnFrameBottom; + sal_Int32 mnPixX; + sal_Int32 mnPixY; + sal_Int32 mnMmX; + sal_Int32 mnMmY; /* multipart object data */ - bool mbMultipart; - sal_uInt16 mMFlags; - SvMemoryStream mMStream; + bool mbMultipart; + sal_uInt16 mMFlags; + SvMemoryStream mMStream; /* emf+ graphic state stack */ // GraphicStateMap mGSStack; @@ -218,7 +220,7 @@ namespace emfplushelper void ReadPoint(SvStream& s, float& x, float& y, sal_uInt32 flags); // internal mapper - void MapToDevice(double& x, double& y); + void mappingChanged(); // primitive creators void EMFPPlusDrawPolygon(const ::basegfx::B2DPolyPolygon& polygon, sal_uInt32 penIndex); commit 58f831b4cee713855301e9d66b2b627993f8d5a7 Author: Armin Le Grand <armin.le.gr...@cib.de> Date: Wed Jun 21 19:31:32 2017 +0200 emfplus: more corrections and rough geometry Corrected/streamlined more, added 1st rough geometry creation to have a proof of concept. Checked the helper classes based on EMFPObject and their derivates. First versions of EMFPPlusDrawPolygon and EMFPPlusFillPolygon, but the complex info in the data objects needs more complex primitive creation. Not sure if primitive creators like createHairlineAndFillPrimitive will be usable, these are based on PropertyHolder info. Also added usage of HandleNewClipRegion, that should be usable Change-Id: I96119be290140bee252ee21a3e1187fad60e9c7d diff --git a/drawinglayer/inc/wmfemfhelper.hxx b/drawinglayer/inc/wmfemfhelper.hxx index 699b065795df..a11b6578e572 100644 --- a/drawinglayer/inc/wmfemfhelper.hxx +++ b/drawinglayer/inc/wmfemfhelper.hxx @@ -208,6 +208,11 @@ namespace wmfemfhelper drawinglayer::primitive2d::Primitive2DContainer interpretMetafile( const GDIMetaFile& rMetaFile, const drawinglayer::geometry::ViewInformation2D& rViewInformation); + + void HandleNewClipRegion( + const basegfx::B2DPolyPolygon& rClipPolyPolygon, + TargetHolders& rTargetHolders, + PropertyHolders& rPropertyHolders); } #endif diff --git a/drawinglayer/source/tools/emfpbrush.cxx b/drawinglayer/source/tools/emfpbrush.cxx index c093a5682572..d55a16ad30d7 100644 --- a/drawinglayer/source/tools/emfpbrush.cxx +++ b/drawinglayer/source/tools/emfpbrush.cxx @@ -64,23 +64,32 @@ namespace emfplushelper EMFPBrush::~EMFPBrush() { - if (blendPositions != nullptr) { + if (blendPositions != nullptr) + { delete[] blendPositions; blendPositions = nullptr; } - if (colorblendPositions != nullptr) { + + if (colorblendPositions != nullptr) + { delete[] colorblendPositions; colorblendPositions = nullptr; } - if (colorblendColors != nullptr) { + + if (colorblendColors != nullptr) + { delete[] colorblendColors; colorblendColors = nullptr; } - if (surroundColors != nullptr) { + + if (surroundColors != nullptr) + { delete[] surroundColors; surroundColors = nullptr; } - if (path) { + + if (path) + { delete path; path = nullptr; } @@ -95,232 +104,267 @@ namespace emfplushelper SAL_INFO("cppcanvas.emf", "EMF+\tbrush"); SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " type: " << type << std::dec); - switch (type) { - case BrushTypeSolidColor: + switch (type) { - sal_uInt32 color; + case BrushTypeSolidColor: + { + sal_uInt32 color; + s.ReadUInt32(color); - s.ReadUInt32(color); - solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); - SAL_INFO("cppcanvas.emf", "EMF+\tsolid color: 0x" << std::hex << color << std::dec); - break; - } - case BrushTypeHatchFill: - { - sal_uInt32 style; - sal_uInt32 foregroundColor; - sal_uInt32 backgroundColor; - s.ReadUInt32(style); - s.ReadUInt32(foregroundColor); - s.ReadUInt32(backgroundColor); - - hatchStyle = static_cast<EmfPlusHatchStyle>(style); - solidColor = ::Color(0xff - (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff); - secondColor = ::Color(0xff - (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff); - SAL_INFO("cppcanvas.emf", "EMF+\thatch style " << style << " foregroundcolor: 0x" << solidColor.AsRGBHexString() << " background 0x" << secondColor.AsRGBHexString()); - break; - } - case BrushTypeTextureFill: - { - SAL_WARN("cppcanvas.emf", "EMF+\tTODO: implement BrushTypeTextureFill brush"); - break; - } - case BrushTypePathGradient: - { - s.ReadUInt32(additionalFlags).ReadInt32(wrapMode); + solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + SAL_INFO("cppcanvas.emf", "EMF+\tsolid color: 0x" << std::hex << color << std::dec); + break; + } + case BrushTypeHatchFill: + { + sal_uInt32 style; + sal_uInt32 foregroundColor; + sal_uInt32 backgroundColor; + s.ReadUInt32(style); + s.ReadUInt32(foregroundColor); + s.ReadUInt32(backgroundColor); + + hatchStyle = static_cast<EmfPlusHatchStyle>(style); + solidColor = ::Color(0xff - (foregroundColor >> 24), (foregroundColor >> 16) & 0xff, (foregroundColor >> 8) & 0xff, foregroundColor & 0xff); + secondColor = ::Color(0xff - (backgroundColor >> 24), (backgroundColor >> 16) & 0xff, (backgroundColor >> 8) & 0xff, backgroundColor & 0xff); + SAL_INFO("cppcanvas.emf", "EMF+\thatch style " << style << " foregroundcolor: 0x" << solidColor.AsRGBHexString() << " background 0x" << secondColor.AsRGBHexString()); + break; + } + case BrushTypeTextureFill: + { + SAL_WARN("cppcanvas.emf", "EMF+\tTODO: implement BrushTypeTextureFill brush"); + break; + } + case BrushTypePathGradient: + { + s.ReadUInt32(additionalFlags).ReadInt32(wrapMode); + SAL_INFO("cppcanvas.emf", "EMF+\tpath gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec); + sal_uInt32 color; + s.ReadUInt32(color); + solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + SAL_INFO("cppcanvas.emf", "EMF+\tcenter color: 0x" << std::hex << color << std::dec); + s.ReadFloat(areaX).ReadFloat(areaY); + SAL_INFO("cppcanvas.emf", "EMF+\tcenter point: " << areaX << "," << areaY); + s.ReadInt32(surroundColorsNumber); + SAL_INFO("cppcanvas.emf", "EMF+\t number of surround colors: " << surroundColorsNumber); + + if (surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32 / sizeof(::Color)) + { + surroundColorsNumber = SAL_MAX_INT32 / sizeof(::Color); + } - SAL_INFO("cppcanvas.emf", "EMF+\tpath gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec); + surroundColors = new ::Color[surroundColorsNumber]; - sal_uInt32 color; + for (int i = 0; i < surroundColorsNumber; i++) + { + s.ReadUInt32(color); + surroundColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + if (i == 0) + secondColor = surroundColors[0]; + SAL_INFO("cppcanvas.emf", "EMF+\tsurround color[" << i << "]: 0x" << std::hex << color << std::dec); + } - s.ReadUInt32(color); - solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); - SAL_INFO("cppcanvas.emf", "EMF+\tcenter color: 0x" << std::hex << color << std::dec); + if (additionalFlags & 0x01) + { + sal_Int32 pathLength; - s.ReadFloat(areaX).ReadFloat(areaY); - SAL_INFO("cppcanvas.emf", "EMF+\tcenter point: " << areaX << "," << areaY); + s.ReadInt32(pathLength); + SAL_INFO("cppcanvas.emf", "EMF+\tpath length: " << pathLength); - s.ReadInt32(surroundColorsNumber); - SAL_INFO("cppcanvas.emf", "EMF+\t number of surround colors: " << surroundColorsNumber); + sal_uInt64 const pos = s.Tell(); - if (surroundColorsNumber<0 || sal_uInt32(surroundColorsNumber)>SAL_MAX_INT32 / sizeof(::Color)) - surroundColorsNumber = SAL_MAX_INT32 / sizeof(::Color); + sal_uInt32 pathHeader; + sal_Int32 pathPoints, pathFlags; + s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags); - surroundColors = new ::Color[surroundColorsNumber]; - for (int i = 0; i < surroundColorsNumber; i++) { - s.ReadUInt32(color); - surroundColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); - if (i == 0) - secondColor = surroundColors[0]; - SAL_INFO("cppcanvas.emf", "EMF+\tsurround color[" << i << "]: 0x" << std::hex << color << std::dec); - } + SAL_INFO("cppcanvas.emf", "EMF+\tpath (brush path gradient)"); + SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec); - if (additionalFlags & 0x01) { - sal_Int32 pathLength; + path = new EMFPPath(pathPoints); + path->Read(s, pathFlags, rR); - s.ReadInt32(pathLength); - SAL_INFO("cppcanvas.emf", "EMF+\tpath length: " << pathLength); + s.Seek(pos + pathLength); - sal_uInt64 const pos = s.Tell(); + const ::basegfx::B2DRectangle aBounds(::basegfx::tools::getRange(path->GetPolygon(rR, false))); + areaWidth = aBounds.getWidth(); + areaHeight = aBounds.getHeight(); + SAL_INFO("cppcanvas.emf", "EMF+\t polygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " " << aBounds.getWidth() << "x" << aBounds.getHeight()); + } + else + { + sal_Int32 boundaryPointCount; + s.ReadInt32(boundaryPointCount); + + sal_uInt64 const pos = s.Tell(); + SAL_INFO("cppcanvas.emf", "EMF+\t use boundary, points: " << boundaryPointCount); + path = new EMFPPath(boundaryPointCount); + path->Read(s, 0x0, rR); + + s.Seek(pos + 8 * boundaryPointCount); + + const ::basegfx::B2DRectangle aBounds(::basegfx::tools::getRange(path->GetPolygon(rR, false))); + areaWidth = aBounds.getWidth(); + areaHeight = aBounds.getHeight(); + SAL_INFO("cppcanvas.emf", "EMF+\t polygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " " << aBounds.getWidth() << "x" << aBounds.getHeight()); + } - sal_uInt32 pathHeader; - sal_Int32 pathPoints, pathFlags; - s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags); + if (additionalFlags & 0x02) + { + SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation"); + rR.readXForm(s, brush_transformation); + hasTransformation = true; + SAL_INFO("cppcanvas.emf", + "EMF+\tm11: " << brush_transformation.get(0,0) << " m12: " << brush_transformation.get(1,0) << + "\nEMF+\tm21: " << brush_transformation.get(0,1) << " m22: " << brush_transformation.get(1,1) << + "\nEMF+\tdx: " << brush_transformation.get(0,2) << " dy: " << brush_transformation.get(1,2)); - SAL_INFO("cppcanvas.emf", "EMF+\tpath (brush path gradient)"); - SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec); + } - path = new EMFPPath(pathPoints); - path->Read(s, pathFlags, rR); + if (additionalFlags & 0x08) + { + s.ReadInt32(blendPoints); + SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints); + if (blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float))) + blendPoints = SAL_MAX_INT32 / (2 * sizeof(float)); + blendPositions = new float[2 * blendPoints]; + blendFactors = blendPositions + blendPoints; + + for (int i = 0; i < blendPoints; i++) + { + s.ReadFloat(blendPositions[i]); + SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions[i]); + } + + for (int i = 0; i < blendPoints; i++) + { + s.ReadFloat(blendFactors[i]); + SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors[i]); + } + } - s.Seek(pos + pathLength); + if (additionalFlags & 0x04) + { + s.ReadInt32(colorblendPoints); + SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints); + + if (colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(float)) + { + colorblendPoints = SAL_MAX_INT32 / sizeof(float); + } + + if (sal_uInt32(colorblendPoints) > SAL_MAX_INT32 / sizeof(::Color)) + { + colorblendPoints = SAL_MAX_INT32 / sizeof(::Color); + } + + colorblendPositions = new float[colorblendPoints]; + colorblendColors = new ::Color[colorblendPoints]; + + for (int i = 0; i < colorblendPoints; i++) + { + s.ReadFloat(colorblendPositions[i]); + SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]); + } + + for (int i = 0; i < colorblendPoints; i++) + { + s.ReadUInt32(color); + colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec); + } + } - const ::basegfx::B2DRectangle aBounds(::basegfx::tools::getRange(path->GetPolygon(rR, false))); - areaWidth = aBounds.getWidth(); - areaHeight = aBounds.getHeight(); - SAL_INFO("cppcanvas.emf", "EMF+\t polygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " " << aBounds.getWidth() << "x" << aBounds.getHeight()); + break; } - else + case BrushTypeLinearGradient: { - sal_Int32 boundaryPointCount; - s.ReadInt32(boundaryPointCount); - - sal_uInt64 const pos = s.Tell(); - SAL_INFO("cppcanvas.emf", "EMF+\t use boundary, points: " << boundaryPointCount); - path = new EMFPPath(boundaryPointCount); - path->Read(s, 0x0, rR); - - s.Seek(pos + 8 * boundaryPointCount); - - const ::basegfx::B2DRectangle aBounds(::basegfx::tools::getRange(path->GetPolygon(rR, false))); - areaWidth = aBounds.getWidth(); - areaHeight = aBounds.getHeight(); - SAL_INFO("cppcanvas.emf", "EMF+\t polygon bounding box: " << aBounds.getMinX() << "," << aBounds.getMinY() << " " << aBounds.getWidth() << "x" << aBounds.getHeight()); - } + s.ReadUInt32(additionalFlags).ReadInt32(wrapMode); + SAL_INFO("cppcanvas.emf", "EMF+\tlinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec); + s.ReadFloat(areaX).ReadFloat(areaY).ReadFloat(areaWidth).ReadFloat(areaHeight); + SAL_INFO("cppcanvas.emf", "EMF+\tarea: " << areaX << "," << areaY << " - " << areaWidth << "x" << areaHeight); + sal_uInt32 color; + s.ReadUInt32(color); + solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + SAL_INFO("cppcanvas.emf", "EMF+\tfirst color: 0x" << std::hex << color << std::dec); + s.ReadUInt32(color); + secondColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + SAL_INFO("cppcanvas.emf", "EMF+\tsecond color: 0x" << std::hex << color << std::dec); - if (additionalFlags & 0x02) { - SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation"); - rR.readXForm(s, brush_transformation); - hasTransformation = true; - SAL_INFO("cppcanvas.emf", - "EMF+\tm11: " << brush_transformation.get(0,0) << " m12: " << brush_transformation.get(1,0) << - "\nEMF+\tm21: " << brush_transformation.get(0,1) << " m22: " << brush_transformation.get(1,1) << - "\nEMF+\tdx: " << brush_transformation.get(0,2) << " dy: " << brush_transformation.get(1,2)); + // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html + s.ReadUInt32(color); + s.ReadUInt32(color); - } - if (additionalFlags & 0x08) { - s.ReadInt32(blendPoints); - SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints); - if (blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float))) - blendPoints = SAL_MAX_INT32 / (2 * sizeof(float)); - blendPositions = new float[2 * blendPoints]; - blendFactors = blendPositions + blendPoints; - for (int i = 0; i < blendPoints; i++) { - s.ReadFloat(blendPositions[i]); - SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions[i]); + if (additionalFlags & 0x02) + { + SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation"); + rR.readXForm(s, brush_transformation); + hasTransformation = true; + SAL_INFO("cppcanvas.emf", + "EMF+\tm11: " << brush_transformation.get(0,0) << " m12: " << brush_transformation.get(1,0) << + "\nEMF+\tm21: " << brush_transformation.get(0,1) << " m22: " << brush_transformation.get(1,1) << + "\nEMF+\tdx: " << brush_transformation.get(0,2) << " dy: " << brush_transformation.get(1,2)); } - for (int i = 0; i < blendPoints; i++) { - s.ReadFloat(blendFactors[i]); - SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors[i]); - } - } - if (additionalFlags & 0x04) { - s.ReadInt32(colorblendPoints); - SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints); - if (colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(float)) - colorblendPoints = SAL_MAX_INT32 / sizeof(float); - if (sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(::Color)) - colorblendPoints = SAL_MAX_INT32 / sizeof(::Color); - colorblendPositions = new float[colorblendPoints]; - colorblendColors = new ::Color[colorblendPoints]; - for (int i = 0; i < colorblendPoints; i++) { - s.ReadFloat(colorblendPositions[i]); - SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]); - } - for (int i = 0; i < colorblendPoints; i++) { - s.ReadUInt32(color); - colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); - SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec); + if (additionalFlags & 0x08) + { + s.ReadInt32(blendPoints); + SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints); + if (blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float))) + blendPoints = SAL_MAX_INT32 / (2 * sizeof(float)); + blendPositions = new float[2 * blendPoints]; + blendFactors = blendPositions + blendPoints; + + for (int i = 0; i < blendPoints; i++) + { + s.ReadFloat(blendPositions[i]); + SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions[i]); + } + + for (int i = 0; i < blendPoints; i++) + { + s.ReadFloat(blendFactors[i]); + SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors[i]); + } } - } - - break; - } - case BrushTypeLinearGradient: - { - s.ReadUInt32(additionalFlags).ReadInt32(wrapMode); - SAL_INFO("cppcanvas.emf", "EMF+\tlinear gradient, additional flags: 0x" << std::hex << additionalFlags << std::dec); - - s.ReadFloat(areaX).ReadFloat(areaY).ReadFloat(areaWidth).ReadFloat(areaHeight); - - SAL_INFO("cppcanvas.emf", "EMF+\tarea: " << areaX << "," << areaY << " - " << areaWidth << "x" << areaHeight); - - sal_uInt32 color; - - s.ReadUInt32(color); - solidColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); - SAL_INFO("cppcanvas.emf", "EMF+\tfirst color: 0x" << std::hex << color << std::dec); - - s.ReadUInt32(color); - secondColor = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); - SAL_INFO("cppcanvas.emf", "EMF+\tsecond color: 0x" << std::hex << color << std::dec); - - // repeated colors, unknown meaning, see http://www.aces.uiuc.edu/~jhtodd/Metafile/MetafileRecords/ObjectBrush.html - s.ReadUInt32(color); - s.ReadUInt32(color); - - if (additionalFlags & 0x02) { - SAL_INFO("cppcanvas.emf", "EMF+\tuse transformation"); - rR.readXForm(s, brush_transformation); - hasTransformation = true; - SAL_INFO("cppcanvas.emf", - "EMF+\tm11: " << brush_transformation.get(0,0) << " m12: " << brush_transformation.get(1,0) << - "\nEMF+\tm21: " << brush_transformation.get(0,1) << " m22: " << brush_transformation.get(1,1) << - "\nEMF+\tdx: " << brush_transformation.get(0,2) << " dy: " << brush_transformation.get(1,2)); - } - if (additionalFlags & 0x08) { - s.ReadInt32(blendPoints); - SAL_INFO("cppcanvas.emf", "EMF+\tuse blend, points: " << blendPoints); - if (blendPoints<0 || sal_uInt32(blendPoints)>SAL_MAX_INT32 / (2 * sizeof(float))) - blendPoints = SAL_MAX_INT32 / (2 * sizeof(float)); - blendPositions = new float[2 * blendPoints]; - blendFactors = blendPositions + blendPoints; - for (int i = 0; i < blendPoints; i++) { - s.ReadFloat(blendPositions[i]); - SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << blendPositions[i]); - } - for (int i = 0; i < blendPoints; i++) { - s.ReadFloat(blendFactors[i]); - SAL_INFO("cppcanvas.emf", "EMF+\tfactor[" << i << "]: " << blendFactors[i]); + if (additionalFlags & 0x04) + { + s.ReadInt32(colorblendPoints); + SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints); + + if (colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(float)) + { + colorblendPoints = SAL_MAX_INT32 / sizeof(float); + } + + if (sal_uInt32(colorblendPoints) > SAL_MAX_INT32 / sizeof(::Color)) + { + colorblendPoints = sal_uInt32(SAL_MAX_INT32) / sizeof(::Color); + } + + colorblendPositions = new float[colorblendPoints]; + colorblendColors = new ::Color[colorblendPoints]; + + for (int i = 0; i < colorblendPoints; i++) + { + s.ReadFloat(colorblendPositions[i]); + SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]); + } + + for (int i = 0; i < colorblendPoints; i++) + { + s.ReadUInt32(color); + colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec); + } } - } - if (additionalFlags & 0x04) { - s.ReadInt32(colorblendPoints); - SAL_INFO("cppcanvas.emf", "EMF+\tuse color blend, points: " << colorblendPoints); - if (colorblendPoints<0 || sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(float)) - colorblendPoints = SAL_MAX_INT32 / sizeof(float); - if (sal_uInt32(colorblendPoints)>SAL_MAX_INT32 / sizeof(::Color)) - colorblendPoints = sal_uInt32(SAL_MAX_INT32) / sizeof(::Color); - colorblendPositions = new float[colorblendPoints]; - colorblendColors = new ::Color[colorblendPoints]; - for (int i = 0; i < colorblendPoints; i++) { - s.ReadFloat(colorblendPositions[i]); - SAL_INFO("cppcanvas.emf", "EMF+\tposition[" << i << "]: " << colorblendPositions[i]); - } - for (int i = 0; i < colorblendPoints; i++) { - s.ReadUInt32(color); - colorblendColors[i] = ::Color(0xff - (color >> 24), (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); - SAL_INFO("cppcanvas.emf", "EMF+\tcolor[" << i << "]: 0x" << std::hex << color << std::dec); - } + break; + } + default: + { + SAL_INFO("cppcanvas.emf", "EMF+\tunhandled brush type: " << std::hex << type << std::dec); } - - break; - } - default: - SAL_INFO("cppcanvas.emf", "EMF+\tunhandled brush type: " << std::hex << type << std::dec); } } } diff --git a/drawinglayer/source/tools/emfpcustomlinecap.cxx b/drawinglayer/source/tools/emfpcustomlinecap.cxx index 9024a11a564e..d2d211d62d3e 100644 --- a/drawinglayer/source/tools/emfpcustomlinecap.cxx +++ b/drawinglayer/source/tools/emfpcustomlinecap.cxx @@ -46,7 +46,6 @@ namespace emfplushelper { const sal_uInt32 EmfPlusCustomLineCapDataTypeDefault = 0x00000000; const sal_uInt32 EmfPlusCustomLineCapDataTypeAdjustableArrow = 0x00000001; - const sal_uInt32 EmfPlusCustomLineCapDataFillPath = 0x00000001; const sal_uInt32 EmfPlusCustomLineCapDataLinePath = 0x00000002; @@ -75,17 +74,14 @@ namespace emfplushelper sal_Int32 pathLength; s.ReadInt32(pathLength); SAL_INFO("cppcanvas.emf", "EMF+\t\tpath length: " << pathLength); - sal_uInt32 pathHeader; sal_Int32 pathPoints, pathFlags; s.ReadUInt32(pathHeader).ReadInt32(pathPoints).ReadInt32(pathFlags); - SAL_INFO("cppcanvas.emf", "EMF+\t\tpath (custom cap line path)"); SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << pathHeader << " points: " << std::dec << pathPoints << " additional flags: 0x" << std::hex << pathFlags << std::dec); EMFPPath path(pathPoints); path.Read(s, pathFlags, rR); - polygon = path.GetPolygon(rR, false); mbIsFilled = bFill; @@ -93,16 +89,13 @@ namespace emfplushelper // expects B2DHomMatrix aMatrix; aMatrix.scale(1.0, -1.0); - polygon.transform(aMatrix); }; void EMFPCustomLineCap::Read(SvStream& s, EmfPlusHelperData& rR) { sal_uInt32 header; - s.ReadUInt32(header).ReadUInt32(type); - SAL_INFO("cppcanvas.emf", "EMF+\t\tcustom cap"); SAL_INFO("cppcanvas.emf", "EMF+\t\theader: 0x" << std::hex << header << " type: " << type << std::dec); diff --git a/drawinglayer/source/tools/emfpfont.cxx b/drawinglayer/source/tools/emfpfont.cxx index b191a8f4c7e5..754e59e94319 100644 --- a/drawinglayer/source/tools/emfpfont.cxx +++ b/drawinglayer/source/tools/emfpfont.cxx @@ -44,11 +44,8 @@ namespace emfplushelper sal_uInt32 header; sal_uInt32 reserved; sal_uInt32 length; - s.ReadUInt32(header).ReadFloat(emSize).ReadUInt32(sizeUnit).ReadInt32(fontFlags).ReadUInt32(reserved).ReadUInt32(length); - SAL_WARN_IF((header >> 12) != 0xdbc01, "cppcanvas.emf", "Invalid header - not 0xdbc01"); - SAL_INFO("cppcanvas.emf", "EMF+\tfont\nEMF+\theader: 0x" << std::hex << (header >> 12) << " version: 0x" << (header & 0x1fff) << " size: " << std::dec << emSize << " unit: 0x" << std::hex << sizeUnit << std::dec); SAL_INFO("cppcanvas.emf", "EMF+\tflags: 0x" << std::hex << fontFlags << " reserved: 0x" << reserved << " length: 0x" << std::hex << length << std::dec); @@ -58,7 +55,9 @@ namespace emfplushelper sal_Unicode *chars = pStr->buffer; for (sal_uInt32 i = 0; i < length; ++i) + { s.ReadUtf16(chars[i]); + } family = OUString(pStr, SAL_NO_ACQUIRE); SAL_INFO("cppcanvas.emf", "EMF+\tfamily: " << family); diff --git a/drawinglayer/source/tools/emfphelperdata.cxx b/drawinglayer/source/tools/emfphelperdata.cxx index fcab2bbd7a44..80d9a7f3fafa 100644 --- a/drawinglayer/source/tools/emfphelperdata.cxx +++ b/drawinglayer/source/tools/emfphelperdata.cxx @@ -26,6 +26,8 @@ #include <emfpfont.hxx> #include <emfpstringformat.hxx> #include <basegfx/curve/b2dcubicbezier.hxx> +#include <wmfemfhelper.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> namespace emfplushelper { @@ -33,45 +35,45 @@ namespace emfplushelper { switch (type) { - case EmfPlusRecordTypeHeader: return "EmfPlusRecordTypeHeader"; - case EmfPlusRecordTypeEndOfFile: return "EmfPlusRecordTypeEndOfFile"; - case EmfPlusRecordTypeGetDC: return "EmfPlusRecordTypeGetDC"; - case EmfPlusRecordTypeObject: return "EmfPlusRecordTypeObject"; - case EmfPlusRecordTypeFillRects: return "EmfPlusRecordTypeFillRects"; - case EmfPlusRecordTypeDrawRects: return "EmfPlusRecordTypeDrawRects"; - case EmfPlusRecordTypeFillPolygon: return "EmfPlusRecordTypeFillPolygon"; - case EmfPlusRecordTypeDrawLines: return "EmfPlusRecordTypeDrawLines"; - case EmfPlusRecordTypeFillEllipse: return "EmfPlusRecordTypeFillEllipse"; - case EmfPlusRecordTypeDrawEllipse: return "EmfPlusRecordTypeDrawEllipse"; - case EmfPlusRecordTypeFillPie: return "EmfPlusRecordTypeFillPie"; - case EmfPlusRecordTypeDrawPie: return "EmfPlusRecordTypeDrawPie"; - case EmfPlusRecordTypeDrawArc: return "EmfPlusRecordTypeDrawArc"; - case EmfPlusRecordTypeFillPath: return "EmfPlusRecordTypeFillPath"; - case EmfPlusRecordTypeDrawPath: return "EmfPlusRecordTypeDrawPath"; - case EmfPlusRecordTypeDrawBeziers: return "EmfPlusRecordTypeDrawBeziers"; - case EmfPlusRecordTypeDrawImage: return "EmfPlusRecordTypeDrawImage"; - case EmfPlusRecordTypeDrawImagePoints: return "EmfPlusRecordTypeDrawImagePoints"; - case EmfPlusRecordTypeDrawString: return "EmfPlusRecordTypeDrawString"; - case EmfPlusRecordTypeSetRenderingOrigin: return "EmfPlusRecordTypeSetRenderingOrigin"; - case EmfPlusRecordTypeSetAntiAliasMode: return "EmfPlusRecordTypeSetAntiAliasMode"; - case EmfPlusRecordTypeSetTextRenderingHint: return "EmfPlusRecordTypeSetTextRenderingHint"; - case EmfPlusRecordTypeSetInterpolationMode: return "EmfPlusRecordTypeSetInterpolationMode"; - case EmfPlusRecordTypeSetPixelOffsetMode: return "EmfPlusRecordTypeSetPixelOffsetMode"; - case EmfPlusRecordTypeSetCompositingQuality: return "EmfPlusRecordTypeSetCompositingQuality"; - case EmfPlusRecordTypeSave: return "EmfPlusRecordTypeSave"; - case EmfPlusRecordTypeRestore: return "EmfPlusRecordTypeRestore"; - case EmfPlusRecordTypeBeginContainerNoParams: return "EmfPlusRecordTypeBeginContainerNoParams"; - case EmfPlusRecordTypeEndContainer: return "EmfPlusRecordTypeEndContainer"; - case EmfPlusRecordTypeSetWorldTransform: return "EmfPlusRecordTypeSetWorldTransform"; - case EmfPlusRecordTypeResetWorldTransform: return "EmfPlusRecordTypeResetWorldTransform"; - case EmfPlusRecordTypeMultiplyWorldTransform: return "EmfPlusRecordTypeMultiplyWorldTransform"; - case EmfPlusRecordTypeTranslateWorldTransform: return "EmfPlusRecordTypeTranslateWorldTransform"; - case EmfPlusRecordTypeScaleWorldTransform: return "EmfPlusRecordTypeScaleWorldTransform"; - case EmfPlusRecordTypeSetPageTransform: return "EmfPlusRecordTypeSetPageTransform"; - case EmfPlusRecordTypeSetClipRect: return "EmfPlusRecordTypeSetClipRect"; - case EmfPlusRecordTypeSetClipPath: return "EmfPlusRecordTypeSetClipPath"; - case EmfPlusRecordTypeSetClipRegion: return "EmfPlusRecordTypeSetClipRegion"; - case EmfPlusRecordTypeDrawDriverString: return "EmfPlusRecordTypeDrawDriverString"; + case EmfPlusRecordTypeHeader: return "EmfPlusRecordTypeHeader"; + case EmfPlusRecordTypeEndOfFile: return "EmfPlusRecordTypeEndOfFile"; + case EmfPlusRecordTypeGetDC: return "EmfPlusRecordTypeGetDC"; + case EmfPlusRecordTypeObject: return "EmfPlusRecordTypeObject"; + case EmfPlusRecordTypeFillRects: return "EmfPlusRecordTypeFillRects"; + case EmfPlusRecordTypeDrawRects: return "EmfPlusRecordTypeDrawRects"; + case EmfPlusRecordTypeFillPolygon: return "EmfPlusRecordTypeFillPolygon"; + case EmfPlusRecordTypeDrawLines: return "EmfPlusRecordTypeDrawLines"; + case EmfPlusRecordTypeFillEllipse: return "EmfPlusRecordTypeFillEllipse"; + case EmfPlusRecordTypeDrawEllipse: return "EmfPlusRecordTypeDrawEllipse"; + case EmfPlusRecordTypeFillPie: return "EmfPlusRecordTypeFillPie"; + case EmfPlusRecordTypeDrawPie: return "EmfPlusRecordTypeDrawPie"; + case EmfPlusRecordTypeDrawArc: return "EmfPlusRecordTypeDrawArc"; + case EmfPlusRecordTypeFillPath: return "EmfPlusRecordTypeFillPath"; + case EmfPlusRecordTypeDrawPath: return "EmfPlusRecordTypeDrawPath"; + case EmfPlusRecordTypeDrawBeziers: return "EmfPlusRecordTypeDrawBeziers"; + case EmfPlusRecordTypeDrawImage: return "EmfPlusRecordTypeDrawImage"; + case EmfPlusRecordTypeDrawImagePoints: return "EmfPlusRecordTypeDrawImagePoints"; + case EmfPlusRecordTypeDrawString: return "EmfPlusRecordTypeDrawString"; + case EmfPlusRecordTypeSetRenderingOrigin: return "EmfPlusRecordTypeSetRenderingOrigin"; + case EmfPlusRecordTypeSetAntiAliasMode: return "EmfPlusRecordTypeSetAntiAliasMode"; + case EmfPlusRecordTypeSetTextRenderingHint: return "EmfPlusRecordTypeSetTextRenderingHint"; + case EmfPlusRecordTypeSetInterpolationMode: return "EmfPlusRecordTypeSetInterpolationMode"; + case EmfPlusRecordTypeSetPixelOffsetMode: return "EmfPlusRecordTypeSetPixelOffsetMode"; + case EmfPlusRecordTypeSetCompositingQuality: return "EmfPlusRecordTypeSetCompositingQuality"; + case EmfPlusRecordTypeSave: return "EmfPlusRecordTypeSave"; + case EmfPlusRecordTypeRestore: return "EmfPlusRecordTypeRestore"; + case EmfPlusRecordTypeBeginContainerNoParams: return "EmfPlusRecordTypeBeginContainerNoParams"; + case EmfPlusRecordTypeEndContainer: return "EmfPlusRecordTypeEndContainer"; + case EmfPlusRecordTypeSetWorldTransform: return "EmfPlusRecordTypeSetWorldTransform"; + case EmfPlusRecordTypeResetWorldTransform: return "EmfPlusRecordTypeResetWorldTransform"; + case EmfPlusRecordTypeMultiplyWorldTransform: return "EmfPlusRecordTypeMultiplyWorldTransform"; + case EmfPlusRecordTypeTranslateWorldTransform: return "EmfPlusRecordTypeTranslateWorldTransform"; + case EmfPlusRecordTypeScaleWorldTransform: return "EmfPlusRecordTypeScaleWorldTransform"; + case EmfPlusRecordTypeSetPageTransform: return "EmfPlusRecordTypeSetPageTransform"; + case EmfPlusRecordTypeSetClipRect: return "EmfPlusRecordTypeSetClipRect"; + case EmfPlusRecordTypeSetClipPath: return "EmfPlusRecordTypeSetClipPath"; + case EmfPlusRecordTypeSetClipRegion: return "EmfPlusRecordTypeSetClipRegion"; + case EmfPlusRecordTypeDrawDriverString: return "EmfPlusRecordTypeDrawDriverString"; } return ""; } @@ -126,82 +128,83 @@ namespace emfplushelper switch (flags & 0x7f00) { - case EmfPlusObjectTypeBrush: - { - EMFPBrush *brush; - aObjects[index].reset(brush = new EMFPBrush()); - brush->Read(rObjectStream, *this); - break; - } - case EmfPlusObjectTypePen: - { - EMFPPen *pen; - aObjects[index].reset(pen = new EMFPPen()); - pen->Read(rObjectStream, *this); - break; - } - case EmfPlusObjectTypePath: - { - sal_uInt32 header, pathFlags; - sal_Int32 points; - - rObjectStream.ReadUInt32(header).ReadInt32(points).ReadUInt32(pathFlags); - SAL_INFO("cppcanvas.emf", "EMF+\tpath"); - SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " points: " << std::dec << points << " additional flags: 0x" << std::hex << pathFlags << std::dec); - EMFPPath *path; - aObjects[index].reset(path = new EMFPPath(points)); - path->Read(rObjectStream, pathFlags, *this); - break; - } - case EmfPlusObjectTypeRegion: - { - EMFPRegion *region; - aObjects[index].reset(region = new EMFPRegion()); - region->Read(rObjectStream); - break; - } - case EmfPlusObjectTypeImage: - { - EMFPImage *image; - aObjects[index].reset(image = new EMFPImage); - image->type = 0; - image->width = 0; - image->height = 0; - image->stride = 0; - image->pixelFormat = 0; - image->Read(rObjectStream, dataSize, bUseWholeStream); - break; - } - case EmfPlusObjectTypeFont: - { - EMFPFont *font; - aObjects[index].reset(font = new EMFPFont); - font->emSize = 0; - font->sizeUnit = 0; - font->fontFlags = 0; - font->Read(rObjectStream); - break; - } - case EmfPlusObjectTypeStringFormat: - { - EMFPStringFormat *stringFormat; - aObjects[index].reset(stringFormat = new EMFPStringFormat()); - stringFormat->Read(rObjectStream); - break; - } - case EmfPlusObjectTypeImageAttributes: - { - SAL_INFO("cppcanvas.emf", "EMF+\t Object type 'image attributes' not yet implemented"); - break; - } - case EmfPlusObjectTypeCustomLineCap: - { - SAL_INFO("cppcanvas.emf", "EMF+\t Object type 'custom line cap' not yet implemented"); - break; - } - default: - SAL_INFO("cppcanvas.emf", "EMF+\tObject unhandled flags: 0x" << std::hex << (flags & 0xff00) << std::dec); - break; + case EmfPlusObjectTypeBrush: + { + EMFPBrush *brush; + aObjects[index].reset(brush = new EMFPBrush()); + brush->Read(rObjectStream, *this); + break; + } + case EmfPlusObjectTypePen: + { + EMFPPen *pen; + aObjects[index].reset(pen = new EMFPPen()); + pen->Read(rObjectStream, *this); + break; + } + case EmfPlusObjectTypePath: + { + sal_uInt32 header, pathFlags; + sal_Int32 points; + + rObjectStream.ReadUInt32(header).ReadInt32(points).ReadUInt32(pathFlags); + SAL_INFO("cppcanvas.emf", "EMF+\tpath"); + SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " points: " << std::dec << points << " additional flags: 0x" << std::hex << pathFlags << std::dec); + EMFPPath *path; + aObjects[index].reset(path = new EMFPPath(points)); + path->Read(rObjectStream, pathFlags, *this); + break; + } + case EmfPlusObjectTypeRegion: + { + EMFPRegion *region; + aObjects[index].reset(region = new EMFPRegion()); + region->Read(rObjectStream); + break; + } + case EmfPlusObjectTypeImage: + { + EMFPImage *image; + aObjects[index].reset(image = new EMFPImage); + image->type = 0; + image->width = 0; + image->height = 0; + image->stride = 0; + image->pixelFormat = 0; + image->Read(rObjectStream, dataSize, bUseWholeStream); + break; + } + case EmfPlusObjectTypeFont: + { + EMFPFont *font; + aObjects[index].reset(font = new EMFPFont); + font->emSize = 0; + font->sizeUnit = 0; + font->fontFlags = 0; + font->Read(rObjectStream); + break; + } + case EmfPlusObjectTypeStringFormat: + { + EMFPStringFormat *stringFormat; + aObjects[index].reset(stringFormat = new EMFPStringFormat()); + stringFormat->Read(rObjectStream); + break; + } + case EmfPlusObjectTypeImageAttributes: + { + SAL_INFO("cppcanvas.emf", "EMF+\t Object type 'image attributes' not yet implemented"); + break; + } + case EmfPlusObjectTypeCustomLineCap: + { + SAL_INFO("cppcanvas.emf", "EMF+\t Object type 'custom line cap' not yet implemented"); + break; + } + default: + { + SAL_INFO("cppcanvas.emf", "EMF+\tObject unhandled flags: 0x" << std::hex << (flags & 0xff00) << std::dec); + } } } @@ -324,6 +327,34 @@ namespace emfplushelper return ::basegfx::B2DSize(w, h); } + void EmfPlusHelperData::EMFPPlusDrawPolygon(const ::basegfx::B2DPolyPolygon& polygon, sal_uInt32 penIndex) + { + const EMFPPen* pen = static_cast<EMFPPen*>(aObjects[penIndex & 0xff].get()); + SAL_WARN_IF(!pen, "cppcanvas.emf", "emf+ missing pen"); + + if (pen && polygon.count()) + { + mrTargetHolders.Current().append( + new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D( + polygon, + pen->GetColor().getBColor())); + } + } + + void EmfPlusHelperData::EMFPPlusFillPolygon(const ::basegfx::B2DPolyPolygon& polygon, bool isColor, sal_uInt32 brushIndexOrColor) + { + if (polygon.count()) + { + if (isColor) + { + mrTargetHolders.Current().append( + new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + polygon, + ::Color(0xff - (brushIndexOrColor >> 24), (brushIndexOrColor >> 16) & 0xff, (brushIndexOrColor >> 8) & 0xff, brushIndexOrColor & 0xff).getBColor())); + } + } + } + EmfPlusHelperData::EmfPlusHelperData( SvMemoryStream& rMS, wmfemfhelper::TargetHolders& rTargetHolders, @@ -431,804 +462,834 @@ namespace emfplushelper { switch (type) { - case EmfPlusRecordTypeHeader: - { - sal_uInt32 header, version; - - rMS.ReadUInt32(header).ReadUInt32(version).ReadInt32(nHDPI).ReadInt32(nVDPI); - SAL_INFO("cppcanvas.emf", "EMF+ Header"); - SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " version: " << std::dec << version << " horizontal DPI: " << nHDPI << " vertical DPI: " << nVDPI << " dual: " << (flags & 1)); - break; - } - case EmfPlusRecordTypeEndOfFile: - { - SAL_INFO("cppcanvas.emf", "EMF+ EndOfFile"); - break; - } - case EmfPlusRecordTypeGetDC: - { - SAL_INFO("cppcanvas.emf", "EMF+ GetDC"); - SAL_INFO("cppcanvas.emf", "EMF+\talready used in svtools wmf/emf filter parser"); - break; - } - case EmfPlusRecordTypeObject: - { - processObjectRecord(rMS, flags, dataSize); - break; - } - case EmfPlusRecordTypeFillPie: - case EmfPlusRecordTypeDrawPie: - case EmfPlusRecordTypeDrawArc: - { - float startAngle, sweepAngle; - - // Silent MSVC warning C4701: potentially uninitialized local variable 'brushIndexOrColor' used - sal_uInt32 brushIndexOrColor = 999; - - if (type == EmfPlusRecordTypeFillPie) + case EmfPlusRecordTypeHeader: { - rMS.ReadUInt32(brushIndexOrColor); - SAL_INFO("cppcanvas.emf", "EMF+ FillPie colorOrIndex: " << brushIndexOrColor); + sal_uInt32 header, version; + + rMS.ReadUInt32(header).ReadUInt32(version).ReadInt32(nHDPI).ReadInt32(nVDPI); + SAL_INFO("cppcanvas.emf", "EMF+ Header"); + SAL_INFO("cppcanvas.emf", "EMF+\theader: 0x" << std::hex << header << " version: " << std::dec << version << " horizontal DPI: " << nHDPI << " vertical DPI: " << nVDPI << " dual: " << (flags & 1)); + break; } - else if (type == EmfPlusRecordTypeDrawPie) + case EmfPlusRecordTypeEndOfFile: { - SAL_INFO("cppcanvas.emf", "EMF+ DrawPie"); + SAL_INFO("cppcanvas.emf", "EMF+ EndOfFile"); + break; } - else + case EmfPlusRecordTypeGetDC: { - SAL_INFO("cppcanvas.emf", "EMF+ DrawArc"); + SAL_INFO("cppcanvas.emf", "EMF+ GetDC"); + SAL_INFO("cppcanvas.emf", "EMF+\talready used in svtools wmf/emf filter parser"); + break; } - - rMS.ReadFloat(startAngle).ReadFloat(sweepAngle); - float dx, dy, dw, dh; - ReadRectangle(rMS, dx, dy, dw, dh, bool(flags & 0x4000)); - SAL_INFO("cppcanvas.emf", "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh); - startAngle = 2 * M_PI*startAngle / 360; - sweepAngle = 2 * M_PI*sweepAngle / 360; - ::basegfx::B2DPoint mappedCenter(Map(dx + dw / 2, dy + dh / 2)); - ::basegfx::B2DSize mappedSize(MapSize(dw / 2, dh / 2)); - float endAngle = startAngle + sweepAngle; - startAngle = fmodf(startAngle, static_cast<float>(M_PI * 2)); - - if (startAngle < 0.0) + case EmfPlusRecordTypeObject: { - startAngle += static_cast<float>(M_PI * 2.0); + processObjectRecord(rMS, flags, dataSize); + break; } - - endAngle = fmodf(endAngle, static_cast<float>(M_PI * 2.0)); - - if (endAngle < 0.0) + case EmfPlusRecordTypeFillPie: + case EmfPlusRecordTypeDrawPie: + case EmfPlusRecordTypeDrawArc: { - endAngle += static_cast<float>(M_PI * 2.0); - } + float startAngle, sweepAngle; - if (sweepAngle < 0) - { - std::swap(endAngle, startAngle); - } + // Silent MSVC warning C4701: potentially uninitialized local variable 'brushIndexOrColor' used + sal_uInt32 brushIndexOrColor = 999; - SAL_INFO("cppcanvas.emf", "EMF+\t adjusted angles: start " << - (360.0*startAngle / M_PI) << ", end: " << (360.0*endAngle / M_PI) << - " startAngle: " << startAngle << " sweepAngle: " << sweepAngle); + if (type == EmfPlusRecordTypeFillPie) + { + rMS.ReadUInt32(brushIndexOrColor); + SAL_INFO("cppcanvas.emf", "EMF+ FillPie colorOrIndex: " << brushIndexOrColor); + } + else if (type == EmfPlusRecordTypeDrawPie) + { + SAL_INFO("cppcanvas.emf", "EMF+ DrawPie"); + } + else + { + SAL_INFO("cppcanvas.emf", "EMF+ DrawArc"); + } - ::basegfx::B2DPolygon polygon = basegfx::tools::createPolygonFromEllipseSegment( - mappedCenter, mappedSize.getX(), mappedSize.getY(), startAngle, endAngle); + rMS.ReadFloat(startAngle).ReadFloat(sweepAngle); + float dx, dy, dw, dh; + ReadRectangle(rMS, dx, dy, dw, dh, bool(flags & 0x4000)); + SAL_INFO("cppcanvas.emf", "EMF+\t RectData: " << dx << "," << dy << " " << dw << "x" << dh); + startAngle = 2 * M_PI*startAngle / 360; + sweepAngle = 2 * M_PI*sweepAngle / 360; + ::basegfx::B2DPoint mappedCenter(Map(dx + dw / 2, dy + dh / 2)); + ::basegfx::B2DSize mappedSize(MapSize(dw / 2, dh / 2)); + float endAngle = startAngle + sweepAngle; + startAngle = fmodf(startAngle, static_cast<float>(M_PI * 2)); + + if (startAngle < 0.0) + { + startAngle += static_cast<float>(M_PI * 2.0); + } - if (type != EmfPlusRecordTypeDrawArc) - { - polygon.append(mappedCenter); - polygon.setClosed(true); - } + endAngle = fmodf(endAngle, static_cast<float>(M_PI * 2.0)); - ::basegfx::B2DPolyPolygon polyPolygon(polygon); -// if (type == EmfPlusRecordTypeFillPie) -// EMFPPlusFillPolygon(polyPolygon, -// rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor); -// else -// EMFPPlusDrawPolygon(polyPolygon, -// rFactoryParms, rState, rCanvas, flags & 0xff); - } - break; - case EmfPlusRecordTypeFillPath: - { - sal_uInt32 index = flags & 0xff; - sal_uInt32 brushIndexOrColor; - rMS.ReadUInt32(brushIndexOrColor); - SAL_INFO("cppcanvas.emf", "EMF+ FillPath slot: " << index); + if (endAngle < 0.0) + { + endAngle += static_cast<float>(M_PI * 2.0); + } -// EMFPPlusFillPolygon(static_cast<EMFPPath*>(aObjects[index])->GetPolygon(*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor); - } - break; - case EmfPlusRecordTypeDrawEllipse: - case EmfPlusRecordTypeFillEllipse: - { - // Intentionally very bogus initial value to avoid MSVC complaining about potentially uninitialized local - // variable. As long as the code stays as intended, this variable will be assigned a (real) value in the case - // when it is later used. - sal_uInt32 brushIndexOrColor = 1234567; + if (sweepAngle < 0) + { + std::swap(endAngle, startAngle); + } - if (type == EmfPlusRecordTypeFillEllipse) - { - rMS.ReadUInt32(brushIndexOrColor); - } + SAL_INFO("cppcanvas.emf", "EMF+\t adjusted angles: start " << + (360.0*startAngle / M_PI) << ", end: " << (360.0*endAngle / M_PI) << + " startAngle: " << startAngle << " sweepAngle: " << sweepAngle); - SAL_INFO("cppcanvas.emf", "EMF+ " << (type == EmfPlusRecordTypeFillEllipse ? "Fill" : "Draw") << "Ellipse slot: " << (flags & 0xff)); - float dx, dy, dw, dh; - ReadRectangle(rMS, dx, dy, dw, dh, bool(flags & 0x4000)); - SAL_INFO("cppcanvas.emf", "EMF+ RectData: " << dx << "," << dy << " " << dw << "x" << dh); - ::basegfx::B2DPoint mappedCenter(Map(dx + dw / 2, dy + dh / 2)); - ::basegfx::B2DSize mappedSize(MapSize(dw / 2, dh / 2)); - ::basegfx::B2DPolyPolygon polyPolygon( - ::basegfx::B2DPolygon( - ::basegfx::tools::createPolygonFromEllipse(mappedCenter, mappedSize.getX(), mappedSize.getY()))); - -// if (type == EmfPlusRecordTypeFillEllipse) -// EMFPPlusFillPolygon(polyPolygon, -// rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor); -// else -// EMFPPlusDrawPolygon(polyPolygon, -// rFactoryParms, rState, rCanvas, flags & 0xff); - } - break; - case EmfPlusRecordTypeFillRects: - case EmfPlusRecordTypeDrawRects: - { - // Silent MSVC warning C4701: potentially uninitialized local variable 'brushIndexOrColor' used - sal_uInt32 brushIndexOrColor = 999; - sal_Int32 rectangles; - bool isColor = (flags & 0x8000); - ::basegfx::B2DPolygon polygon; + ::basegfx::B2DPolygon polygon = basegfx::tools::createPolygonFromEllipseSegment( + mappedCenter, mappedSize.getX(), mappedSize.getY(), startAngle, endAngle); + + if (type != EmfPlusRecordTypeDrawArc) + { + polygon.append(mappedCenter); + polygon.setClosed(true); + } - if (EmfPlusRecordTypeFillRects == type) + ::basegfx::B2DPolyPolygon polyPolygon(polygon); + if (type == EmfPlusRecordTypeFillPie) + { + EMFPPlusFillPolygon(polyPolygon, flags & 0x8000, brushIndexOrColor); + // EMFPPlusFillPolygon(polyPolygon, + // rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor); + } + else + { + EMFPPlusDrawPolygon(polyPolygon, flags & 0xff); + // EMFPPlusDrawPolygon(polyPolygon, + // rFactoryParms, rState, rCanvas, flags & 0xff); + } + } + break; + case EmfPlusRecordTypeFillPath: { - SAL_INFO("cppcanvas.emf", "EMF+ FillRects"); + sal_uInt32 index = flags & 0xff; + sal_uInt32 brushIndexOrColor; rMS.ReadUInt32(brushIndexOrColor); - SAL_INFO("cppcanvas.emf", "EMF+\t" << (isColor ? "color" : "brush index") << ": 0x" << std::hex << brushIndexOrColor << std::dec); + SAL_INFO("cppcanvas.emf", "EMF+ FillPath slot: " << index); + + EMFPPlusFillPolygon(static_cast<EMFPPath*>(aObjects[index].get())->GetPolygon(*this), flags & 0x8000, brushIndexOrColor); + // EMFPPlusFillPolygon(static_cast<EMFPPath*>(aObjects[index])->GetPolygon(*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor); } - else + break; + case EmfPlusRecordTypeDrawEllipse: + case EmfPlusRecordTypeFillEllipse: { - SAL_INFO("cppcanvas.emf", "EMF+ DrawRects"); - } + // Intentionally very bogus initial value to avoid MSVC complaining about potentially uninitialized local + // variable. As long as the code stays as intended, this variable will be assigned a (real) value in the case + // when it is later used. + sal_uInt32 brushIndexOrColor = 1234567; - rMS.ReadInt32(rectangles); + if (type == EmfPlusRecordTypeFillEllipse) + { + rMS.ReadUInt32(brushIndexOrColor); + } - for (int i = 0; i < rectangles; i++) + SAL_INFO("cppcanvas.emf", "EMF+ " << (type == EmfPlusRecordTypeFillEllipse ? "Fill" : "Draw") << "Ellipse slot: " << (flags & 0xff)); + float dx, dy, dw, dh; + ReadRectangle(rMS, dx, dy, dw, dh, bool(flags & 0x4000)); + SAL_INFO("cppcanvas.emf", "EMF+ RectData: " << dx << "," << dy << " " << dw << "x" << dh); + ::basegfx::B2DPoint mappedCenter(Map(dx + dw / 2, dy + dh / 2)); + ::basegfx::B2DSize mappedSize(MapSize(dw / 2, dh / 2)); + ::basegfx::B2DPolyPolygon polyPolygon( + ::basegfx::B2DPolygon( + ::basegfx::tools::createPolygonFromEllipse(mappedCenter, mappedSize.getX(), mappedSize.getY()))); + + if (type == EmfPlusRecordTypeFillEllipse) + { + EMFPPlusFillPolygon(polyPolygon, flags & 0x8000, brushIndexOrColor); + // EMFPPlusFillPolygon(polyPolygon, + // rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor); + } + else + { + EMFPPlusDrawPolygon(polyPolygon, flags & 0xff); + // EMFPPlusDrawPolygon(polyPolygon, + // rFactoryParms, rState, rCanvas, flags & 0xff); + } + } + break; + case EmfPlusRecordTypeFillRects: + case EmfPlusRecordTypeDrawRects: { - float x, y, width, height; - ReadRectangle(rMS, x, y, width, height, bool(flags & 0x4000)); + // Silent MSVC warning C4701: potentially uninitialized local variable 'brushIndexOrColor' used + sal_uInt32 brushIndexOrColor = 999; + sal_Int32 rectangles; + bool isColor = (flags & 0x8000); + ::basegfx::B2DPolygon polygon; - polygon.append(Map(x, y)); - polygon.append(Map(x + width, y)); - polygon.append(Map(x + width, y + height)); - polygon.append(Map(x, y + height)); - polygon.append(Map(x, y)); - - SAL_INFO("cppcanvas.emf", "EMF+\trectangle: " << x << ", " << width << "x" << height); + if (EmfPlusRecordTypeFillRects == type) + { + SAL_INFO("cppcanvas.emf", "EMF+ FillRects"); + rMS.ReadUInt32(brushIndexOrColor); + SAL_INFO("cppcanvas.emf", "EMF+\t" << (isColor ? "color" : "brush index") << ": 0x" << std::hex << brushIndexOrColor << std::dec); + } + else + { + SAL_INFO("cppcanvas.emf", "EMF+ DrawRects"); + } - ::basegfx::B2DPolyPolygon polyPolygon(polygon); -// if (type == EmfPlusRecordTypeFillRects) -// EMFPPlusFillPolygon(polyPolygon, -// rFactoryParms, rState, rCanvas, isColor, brushIndexOrColor); -// else -// EMFPPlusDrawPolygon(polyPolygon, -// rFactoryParms, rState, rCanvas, flags & 0xff); - } - break; - } - case EmfPlusRecordTypeFillPolygon: - { - sal_uInt8 index = flags & 0xff; - sal_uInt32 brushIndexOrColor; - sal_Int32 points; + rMS.ReadInt32(rectangles); - rMS.ReadUInt32(brushIndexOrColor); - rMS.ReadInt32(points); - SAL_INFO("cppcanvas.emf", "EMF+ FillPolygon in slot: " << +index << " points: " << points); - SAL_INFO("cppcanvas.emf", "EMF+\t: " << ((flags & 0x8000) ? "color" : "brush index") << " 0x" << std::hex << brushIndexOrColor << std::dec); + for (int i = 0; i < rectangles; i++) + { + float x, y, width, height; + ReadRectangle(rMS, x, y, width, height, bool(flags & 0x4000)); - EMFPPath path(points, true); - path.Read(rMS, flags, *this); + polygon.append(Map(x, y)); + polygon.append(Map(x + width, y)); + polygon.append(Map(x + width, y + height)); + polygon.append(Map(x, y + height)); + polygon.append(Map(x, y)); -// EMFPPlusFillPolygon(path.GetPolygon(*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor); + SAL_INFO("cppcanvas.emf", "EMF+\trectangle: " << x << ", " << width << "x" << height); - break; - } - case EmfPlusRecordTypeDrawLines: - { - sal_uInt32 points; - rMS.ReadUInt32(points); - SAL_INFO("cppcanvas.emf", "EMF+ DrawLines in slot: " << (flags & 0xff) << " points: " << points); - EMFPPath path(points, true); - path.Read(rMS, flags, *this); + ::basegfx::B2DPolyPolygon polyPolygon(polygon); + if (type == EmfPlusRecordTypeFillRects) + { + EMFPPlusFillPolygon(polyPolygon, isColor, brushIndexOrColor); + // EMFPPlusFillPolygon(polyPolygon, + // rFactoryParms, rState, rCanvas, isColor, brushIndexOrColor); + } + else + { + EMFPPlusDrawPolygon(polyPolygon, flags & 0xff); + // EMFPPlusDrawPolygon(polyPolygon, + // rFactoryParms, rState, rCanvas, flags & 0xff); + } + } + break; + } + case EmfPlusRecordTypeFillPolygon: + { + sal_uInt8 index = flags & 0xff; + sal_uInt32 brushIndexOrColor; + sal_Int32 points; - // 0x2000 bit indicates whether to draw an extra line between the last point - // and the first point, to close the shape. -// EMFPPlusDrawPolygon(path.GetPolygon(*this, true, (flags & 0x2000)), rFactoryParms, rState, rCanvas, flags); + rMS.ReadUInt32(brushIndexOrColor); + rMS.ReadInt32(points); + SAL_INFO("cppcanvas.emf", "EMF+ FillPolygon in slot: " << +index << " points: " << points); + SAL_INFO("cppcanvas.emf", "EMF+\t: " << ((flags & 0x8000) ? "color" : "brush index") << " 0x" << std::hex << brushIndexOrColor << std::dec); - break; - } - case EmfPlusRecordTypeDrawPath: - { - sal_uInt32 penIndex; - rMS.ReadUInt32(penIndex); - SAL_INFO("cppcanvas.emf", "EMF+ DrawPath"); - SAL_INFO("cppcanvas.emf", "EMF+\tpen: " << penIndex); - EMFPPath* path = static_cast<EMFPPath*>(aObjects[flags & 0xff].get()); - SAL_WARN_IF(!path, "cppcanvas.emf", "EmfPlusRecordTypeDrawPath missing path"); + EMFPPath path(points, true); + path.Read(rMS, flags, *this); -// EMFPPlusDrawPolygon(path->GetPolygon(*this), rFactoryParms, rState, rCanvas, penIndex); + EMFPPlusFillPolygon(path.GetPolygon(*this), flags & 0x8000, brushIndexOrColor); + // EMFPPlusFillPolygon(path.GetPolygon(*this), rFactoryParms, rState, rCanvas, flags & 0x8000, brushIndexOrColor); - break; - } - case EmfPlusRecordTypeDrawBeziers: - { - sal_uInt32 aCount; - float x1, y1, x2, y2, x3, y3, x4, y4; - ::basegfx::B2DPoint aStartPoint, aControlPointA, aControlPointB, aEndPoint; - ::basegfx::B2DPolygon aPolygon; - rMS.ReadUInt32(aCount); - SAL_INFO("cppcanvas.emf", "EMF+ DrawBeziers slot: " << (flags & 0xff) << "Number of points: " << aCount); - SAL_WARN_IF((aCount - 1) % 3 != 0, "cppcanvas.emf", "EMF+\t Bezier Draw not support number of points other than 4, 7, 10, 13, 16..."); - - if (aCount < 4) - { - SAL_WARN("cppcanvas.emf", "EMF+\t Bezier Draw does not support less than 4 points. Number of points: " << aCount); break; } + case EmfPlusRecordTypeDrawLines: + { + sal_uInt32 points; + rMS.ReadUInt32(points); + SAL_INFO("cppcanvas.emf", "EMF+ DrawLines in slot: " << (flags & 0xff) << " points: " << points); + EMFPPath path(points, true); + path.Read(rMS, flags, *this); - ReadPoint(rMS, x1, y1, flags); - // We need to add first starting point - aStartPoint = Map(x1, y1); - aPolygon.append(aStartPoint); + // 0x2000 bit indicates whether to draw an extra line between the last point + // and the first point, to close the shape. + EMFPPlusDrawPolygon(path.GetPolygon(*this, true, (flags & 0x2000)), flags); ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits