LibreOffice Module emfio (master) 1
xemfparser.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <com/sun/star/graphic/XEmfParser.hpp>
23#include <com/sun/star/lang/XServiceInfo.hpp>
26
27#include <utility>
28#include <vcl/outdev.hxx>
29#include <vcl/svapp.hxx>
30#include <vcl/wmfexternal.hxx>
34#include <sal/log.hxx>
36
37#include <wmfreader.hxx>
38#include <emfreader.hxx>
39
40using namespace ::com::sun::star;
41
43{
44 namespace {
45
46 class XEmfParser : public ::cppu::WeakAggImplHelper2< graphic::XEmfParser, lang::XServiceInfo >
47 {
48 private:
49 uno::Reference< uno::XComponentContext > context_;
51
52 public:
53 explicit XEmfParser(
54 uno::Reference< uno::XComponentContext > context);
55 XEmfParser(const XEmfParser&) = delete;
56 XEmfParser& operator=(const XEmfParser&) = delete;
57
58 // XEmfParser
59 virtual uno::Sequence< uno::Reference< ::graphic::XPrimitive2D > > SAL_CALL getDecomposition(
60 const uno::Reference< ::io::XInputStream >& xEmfStream,
61 const OUString& aAbsolutePath,
62 const uno::Sequence< ::beans::PropertyValue >& rProperties) override;
63 void SAL_CALL setSizeHint(const geometry::RealPoint2D& rSize) override;
64
65 // XServiceInfo
66 virtual OUString SAL_CALL getImplementationName() override;
67 virtual sal_Bool SAL_CALL supportsService(const OUString&) override;
68 virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
69 };
70
71 }
72
73 XEmfParser::XEmfParser(
74 uno::Reference< uno::XComponentContext > context):
75 context_(std::move(context))
76 {
77 }
78
79 uno::Sequence< uno::Reference< ::graphic::XPrimitive2D > > XEmfParser::getDecomposition(
80 const uno::Reference< ::io::XInputStream >& xEmfStream,
81 const OUString& /*aAbsolutePath*/,
82 const uno::Sequence< ::beans::PropertyValue >& rProperties)
83 {
85
86 if (xEmfStream.is())
87 {
88 WmfExternal aExternalHeader;
89 const bool bExternalHeaderUsed(aExternalHeader.setSequence(rProperties));
90 bool bEnableEMFPlus = true;
92 auto it = aMap.find("EMFPlusEnable");
93 if (it != aMap.end())
94 {
95 bool bValue;
96 if (it->second >>= bValue)
97 {
98 bEnableEMFPlus = bValue;
99 }
100 }
101
102 // rough check - import and conv to primitive
103 GDIMetaFile aMtf;
104 std::unique_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream(xEmfStream));
105 sal_uInt32 nOrgPos = pStream->Tell();
106
107 SvStreamEndian nOrigNumberFormat = pStream->GetEndian();
108 pStream->SetEndian(SvStreamEndian::LITTLE);
109
110 sal_uInt32 nMetaType(0);
111 if (checkSeek(*pStream, 0x28))
112 pStream->ReadUInt32(nMetaType);
113 pStream->Seek(nOrgPos);
114
115 bool bReadError(false);
116
117 try
118 {
119 if (nMetaType == 0x464d4520)
120 {
121 // read and get possible failure/error, ReadEnhWMF returns success
122 emfio::EmfReader aReader(*pStream, aMtf);
123 aReader.SetSizeHint(maSizeHint);
124 if (!bEnableEMFPlus)
125 {
126 aReader.SetEnableEMFPlus(bEnableEMFPlus);
127 }
128 bReadError = !aReader.ReadEnhWMF();
129 }
130 else
131 {
132 emfio::WmfReader aReader(*pStream, aMtf, bExternalHeaderUsed ? &aExternalHeader : nullptr);
133 if (!bEnableEMFPlus)
134 aReader.SetEnableEMFPlus(bEnableEMFPlus);
135 aReader.ReadWMF();
136
137 // Need to check for ErrCode at stream to not lose former work.
138 // This may contain important information and will behave the
139 // same as before. When we have an error, do not create content
140 ErrCode aErrCode(pStream->GetError());
141
142 bReadError = aErrCode.IsError();
143 }
144 }
145 catch (...)
146 {
147 bReadError = true;
148 }
149
150 pStream->SetEndian(nOrigNumberFormat);
151
152 if (!bReadError)
153 {
154 Size aSize(aMtf.GetPrefSize());
155
156 if (aMtf.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel)
157 {
158 aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, MapMode(MapUnit::Map100thMM));
159 }
160 else
161 {
162 aSize = OutputDevice::LogicToLogic(aSize, aMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM));
163 }
164
165 // use size
166 const basegfx::B2DHomMatrix aMetafileTransform(
168 aSize.Width(),
169 aSize.Height()));
170
171 // ...and create a single MetafilePrimitive2D containing the Metafile.
172 // CAUTION: Currently, ReadWindowMetafile uses the local VectorGraphicData
173 // and a MetafileAccessor hook at the MetafilePrimitive2D inside of
174 // ImpGraphic::ImplGetGDIMetaFile to get the Metafile. Thus, the first
175 // and only primitive in this case *has to be* a MetafilePrimitive2D.
176 aRetval.push_back(
178 aMetafileTransform,
179 aMtf));
180
181 // // force to use decomposition directly to get rid of the metafile
182 // const css::uno::Sequence< css::beans::PropertyValue > aViewParameters;
183 // drawinglayer::primitive2d::MetafilePrimitive2D aMetafilePrimitive2D(
184 // aMetafileTransform,
185 // aMtf);
186 // aRetval.append(aMetafilePrimitive2D.getDecomposition(aViewParameters));
187
188 // if (aRetval.empty())
189 // {
190 // // for test, just create some graphic data that will get visualized
191 // const basegfx::B2DRange aRange(1000, 1000, 5000, 5000);
192 // const basegfx::BColor aColor(1.0, 0.0, 0.0);
193 // const basegfx::B2DPolygon aOutline(basegfx::utils::createPolygonFromRect(aRange));
194 //
195 // aRetval.push_back(new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aOutline), aColor));
196 // }
197 }
198 }
199 else
200 {
201 SAL_WARN("emfio", "Invalid stream (!)");
202 }
203
204 return aRetval.toSequence();
205 }
206
207 void XEmfParser::setSizeHint(const geometry::RealPoint2D& rSize)
208 {
209 maSizeHint.setX(rSize.X);
210 maSizeHint.setY(rSize.Y);
211 }
212
213 OUString SAL_CALL XEmfParser::getImplementationName()
214 {
215 return "emfio::emfreader::XEmfParser";
216 }
217
218 sal_Bool SAL_CALL XEmfParser::supportsService(const OUString& rServiceName)
219 {
220 return cppu::supportsService(this, rServiceName);
221 }
222
223 uno::Sequence< OUString > SAL_CALL XEmfParser::getSupportedServiceNames()
224 {
225 return { "com.sun.star.graphic.EmfTools" };
226 }
227
228} // end of namespace emfio::emfreader
229
230
231
232extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
234 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
235{
236 return cppu::acquire(new emfio::emfreader::XEmfParser(context));
237}
238
239/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static OutputDevice * GetDefaultDevice()
const Size & GetPrefSize() const
const MapMode & GetPrefMapMode() const
MapUnit GetMapUnit() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
void setY(TYPE fY)
void setX(TYPE fX)
css::uno::Sequence< css::uno::Reference< css::graphic::XPrimitive2D > > toSequence() const
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
#define SAL_WARN(area, stream)
B2DHomMatrix createScaleB2DHomMatrix(double fScaleX, double fScaleY)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
HashMap_OWString_Interface aMap
SvStreamEndian
TOOLS_DLLPUBLIC bool checkSeek(SvStream &rSt, sal_uInt64 nOffset)
bool setSequence(const css::uno::Sequence< css::beans::PropertyValue > &rSequence)
unsigned char sal_Bool
basegfx::B2DTuple maSizeHint
Definition: xemfparser.cxx:50
uno::Reference< uno::XComponentContext > context_
Definition: xemfparser.cxx:49
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * emfio_emfreader_XEmfParser_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Definition: xemfparser.cxx:233