LibreOffice Module xmloff (master)  1
PageMasterImportContext.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 
21 #include <xmloff/xmlimppr.hxx>
22 #include <xmloff/xmlnamespace.hxx>
23 #include <xmloff/xmlprmap.hxx>
24 #include <xmloff/xmltoken.hxx>
25 #include "PageMasterPropHdl.hxx"
28 #include <PageMasterStyleMap.hxx>
29 #include <com/sun/star/frame/XModel.hpp>
30 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
31 #include <osl/diagnose.h>
32 
33 //
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/beans/XPropertySetInfo.hpp>
36 #include <com/sun/star/drawing/FillStyle.hpp>
37 #include <com/sun/star/drawing/BitmapMode.hpp>
38 #include <xmloff/xmlerror.hxx>
40 
41 using namespace ::com::sun::star;
42 using namespace ::xmloff::token;
43 using namespace ::com::sun::star::uno;
44 using namespace ::com::sun::star::lang;
45 
46 //
47 using namespace ::com::sun::star::beans;
48 
49 void PageStyleContext::SetAttribute( sal_Int32 nElement,
50  const OUString& rValue )
51 {
52  if( nElement == XML_ELEMENT(STYLE, XML_PAGE_USAGE) )
53  {
55  }
56  else
57  {
58  XMLPropStyleContext::SetAttribute( nElement, rValue );
59  }
60 }
61 
62 
64  SvXMLStylesContext& rStyles,
65  bool bDefaultStyle) :
66  XMLPropStyleContext( rImport, rStyles, XmlStyleFamily::PAGE_MASTER, bDefaultStyle),
67  sPageUsage(),
68  m_bIsFillStyleAlreadyConverted(false) //
69 {
70 }
71 
73 {
74 }
75 
76 css::uno::Reference< css::xml::sax::XFastContextHandler > PageStyleContext::createFastChildContext(
77  sal_Int32 nElement,
78  const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
79 {
80  if( nElement == XML_ELEMENT(STYLE, XML_HEADER_STYLE) ||
81  nElement == XML_ELEMENT(STYLE, XML_FOOTER_STYLE) )
82  {
83  bool bHeader = nElement == XML_ELEMENT(STYLE, XML_HEADER_STYLE);
86  if( xImpPrMap.is() )
87  {
88  const rtl::Reference< XMLPropertySetMapper >& rMapper = xImpPrMap->getPropertySetMapper();
89  sal_Int32 nFlag;
90  if (bHeader)
91  nFlag = CTF_PM_HEADERFLAG;
92  else
93  nFlag = CTF_PM_FOOTERFLAG;
94  sal_Int32 nStartIndex (-1);
95  sal_Int32 nEndIndex (-1);
96  bool bFirst(false);
97  bool bEnd(false);
98  sal_Int32 nIndex = 0;
99  while ( nIndex < rMapper->GetEntryCount() && !bEnd)
100  {
101  if ((rMapper->GetEntryContextId( nIndex ) & CTF_PM_FLAGMASK) == nFlag)
102  {
103  if (!bFirst)
104  {
105  bFirst = true;
106  nStartIndex = nIndex;
107  }
108  }
109  else if (bFirst)
110  {
111  bEnd = true;
112  nEndIndex = nIndex;
113  }
114  nIndex++;
115  }
116  if (!bEnd)
117  nEndIndex = nIndex;
118  return new PageHeaderFooterContext(GetImport(),
119  GetProperties(), xImpPrMap, nStartIndex, nEndIndex, bHeader);
120  }
121  }
122 
123  if( nElement == XML_ELEMENT(STYLE, XML_PAGE_LAYOUT_PROPERTIES) )
124  {
127  if( xImpPrMap.is() )
128  {
129  const rtl::Reference< XMLPropertySetMapper >& rMapper = xImpPrMap->getPropertySetMapper();
130  sal_Int32 nEndIndex (-1);
131  bool bEnd(false);
132  sal_Int32 nIndex = 0;
133  sal_Int16 nContextID;
134  while ( nIndex < rMapper->GetEntryCount() && !bEnd)
135  {
136  nContextID = rMapper->GetEntryContextId( nIndex );
137  if (nContextID && ((nContextID & CTF_PM_FLAGMASK) != XML_PM_CTF_START))
138  {
139  nEndIndex = nIndex;
140  bEnd = true;
141  }
142  nIndex++;
143  }
144  if (!bEnd)
145  nEndIndex = nIndex;
146  return new PagePropertySetContext( GetImport(), nElement,
147  xAttrList,
149  GetProperties(),
150  xImpPrMap, 0, nEndIndex, Page);
151  }
152  }
153 
154  return XMLPropStyleContext::createFastChildContext(nElement, xAttrList);
155 }
156 
157 void PageStyleContext::FillPropertySet(const uno::Reference<beans::XPropertySet > &)
158 {
159  assert(false); // don't call this virtual, call function below
160 }
161 
163  const uno::Reference<beans::XPropertySet> & xPropSet,
164  XMLPropStyleContext *const pDrawingPageStyle)
165 {
166  // need to filter out old fill definitions when the new ones are used. The new
167  // ones are used when a FillStyle is defined
169  {
170  static OUString s_FillStyle("FillStyle");
171  static OUString s_HeaderFillStyle("HeaderFillStyle");
172  static OUString s_FooterFillStyle("FooterFillStyle");
173 
174  // note: the function must only check by property name, not any id/flag!
176  || (pDrawingPageStyle && pDrawingPageStyle->doNewDrawingLayerFillStyleDefinitionsExist(s_FillStyle)))
177  {
179  }
180 
181  if(doNewDrawingLayerFillStyleDefinitionsExist(s_HeaderFillStyle))
182  {
184  }
185 
186  if(doNewDrawingLayerFillStyleDefinitionsExist(s_FooterFillStyle))
187  {
189  }
190 
192  }
193 
194  // do not use XMLPropStyleContext::FillPropertySet, we need to handle this ourselves since
195  // we have properties which use the MID_FLAG_NO_PROPERTY_IMPORT flag since they need some special
196  // handling
198 
199  if(xImpPrMap.is())
200  {
201  // properties that need special handling because they need the used name to be translated first
202  struct ContextID_Index_Pair aContextIDs[] =
203  {
204  { CTF_PM_FILLGRADIENTNAME, -1, drawing::FillStyle::FillStyle_GRADIENT },
205  { CTF_PM_FILLTRANSNAME, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
206  { CTF_PM_FILLHATCHNAME, -1, drawing::FillStyle::FillStyle_HATCH },
207  { CTF_PM_FILLBITMAPNAME, -1, drawing::FillStyle::FillStyle_BITMAP },
208 
209  // also need to special handling for header entries
210  { CTF_PM_HEADERFILLGRADIENTNAME, -1, drawing::FillStyle::FillStyle_GRADIENT },
211  { CTF_PM_HEADERFILLTRANSNAME, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
212  { CTF_PM_HEADERFILLHATCHNAME, -1, drawing::FillStyle::FillStyle_HATCH },
213  { CTF_PM_HEADERFILLBITMAPNAME, -1, drawing::FillStyle::FillStyle_BITMAP },
214 
215  // also need to special handling for footer entries
216  { CTF_PM_FOOTERFILLGRADIENTNAME, -1, drawing::FillStyle::FillStyle_GRADIENT },
217  { CTF_PM_FOOTERFILLTRANSNAME, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
218  { CTF_PM_FOOTERFILLHATCHNAME, -1, drawing::FillStyle::FillStyle_HATCH },
219  { CTF_PM_FOOTERFILLBITMAPNAME, -1, drawing::FillStyle::FillStyle_BITMAP },
220 
221  {-1, -1, drawing::FillStyle::FillStyle_GRADIENT}
222  };
223 
224  // the style families associated with the same index modulo 4
225  static const XmlStyleFamily aFamilies[] =
226  {
231  };
232 
233  // Fill PropertySet, but let it handle special properties not itself
234  xImpPrMap->FillPropertySet(GetProperties(), xPropSet, aContextIDs);
235 
236  // get property set mapper
237  const rtl::Reference< XMLPropertySetMapper >& rMapper = xImpPrMap->getPropertySetMapper();
238  Reference<XPropertySetInfo> const xInfo(xPropSet->getPropertySetInfo());
239 
240  // don't look at the attributes, look at the property, could
241  // theoretically be inherited and we don't want to delete erroneously
242  drawing::FillStyle fillStyle{drawing::FillStyle_NONE};
243  drawing::FillStyle fillStyleHeader{drawing::FillStyle_NONE};
244  drawing::FillStyle fillStyleFooter{drawing::FillStyle_NONE};
245  if (xInfo->hasPropertyByName("FillStyle")) // SwXTextDefaults lacks it?
246  {
247  xPropSet->getPropertyValue("FillStyle") >>= fillStyle;
248  xPropSet->getPropertyValue("HeaderFillStyle") >>= fillStyleHeader;
249  xPropSet->getPropertyValue("FooterFillStyle") >>= fillStyleFooter;
250  }
251 
252  // handle special attributes which have MID_FLAG_NO_PROPERTY_IMPORT set
253  for(sal_uInt16 i = 0; aContextIDs[i].nContextID != -1; i++)
254  {
255  sal_Int32 nIndex = aContextIDs[i].nIndex;
256 
257  if(nIndex != -1)
258  {
259  drawing::FillStyle const* pFillStyle(nullptr);
260  switch(aContextIDs[i].nContextID)
261  {
266  pFillStyle = &fillStyle;
267  [[fallthrough]];
272  if (!pFillStyle) { pFillStyle = &fillStyleHeader; }
273  [[fallthrough]];
278  {
279  if (!pFillStyle) { pFillStyle = &fillStyleFooter; }
280  struct XMLPropertyState& rState = GetProperties()[nIndex];
281  OUString sStyleName;
282  rState.maValue >>= sStyleName;
283 
284  if (aContextIDs[i].nExpectedFillStyle != drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE
285  && aContextIDs[i].nExpectedFillStyle != *pFillStyle)
286  {
287  SAL_INFO("xmloff.style", "PageStyleContext: dropping fill named item: " << sStyleName);
288  break; // ignore it, it's not used
289  }
290  // translate the used name from ODF intern to the name used in the Model
291  sStyleName = GetImport().GetStyleDisplayName(aFamilies[i%4], sStyleName);
292 
293  try
294  {
295  // set property
296  const OUString& rPropertyName = rMapper->GetEntryAPIName(rState.mnIndex);
297 
298  if(xInfo->hasPropertyByName(rPropertyName))
299  {
300  xPropSet->setPropertyValue(rPropertyName,Any(sStyleName));
301  }
302  }
303  catch(css::lang::IllegalArgumentException& e)
304  {
305  Sequence<OUString> aSeq { sStyleName };
308  aSeq,e.Message,nullptr);
309  }
310  break;
311  }
312  }
313  }
314  }
315  }
316  else
317  {
318  OSL_ENSURE(xImpPrMap.is(), "Got no SvXMLImportPropertyMapper (!)");
319  }
320 
321  // pDrawingPageStyle overrides this
322  if (pDrawingPageStyle)
323  {
324  pDrawingPageStyle->FillPropertySet(xPropSet);
325  }
326  // horrible heuristic to guess BackgroundFullSize for Writer < 7.0
327  else if (!IsDefaultStyle() // ignore pool default, only fix existing styles
328  && (GetImport().isGeneratorVersionOlderThan(SvXMLImport::AOO_4x, SvXMLImport::LO_7x)
329  // also for AOO 4.x, assume there won't ever be a 4.2
330  || GetImport().getGeneratorVersion() == SvXMLImport::AOO_4x))
331  {
332  bool isFullSize(true); // default is current LO default
333  drawing::FillStyle fillStyle{drawing::FillStyle_NONE};
334  xPropSet->getPropertyValue("FillStyle") >>= fillStyle;
335  if (GetImport().isGeneratorVersionOlderThan(SvXMLImport::AOO_4x, SvXMLImport::LO_63x)
336  // also for AOO 4.x, assume there won't ever be a 4.2
337  || GetImport().getGeneratorVersion() == SvXMLImport::AOO_4x)
338  {
339  // before LO 6.3, always inside the margins (but ignore it if NONE)
340  if (fillStyle != drawing::FillStyle_NONE)
341  {
342  isFullSize = false;
343  }
344  }
345  else
346  {
347  // LO 6.3/6.4: guess depending on fill style/bitmap mode
348  // this should work even if the document doesn't contain fill style
349  // but only old background attributes
350  // (can't use the aContextIDs stuff above because that requires
351  // re-routing through handleSpecialItem())
352  switch (fillStyle)
353  {
354  case drawing::FillStyle_NONE:
355  break;
356  case drawing::FillStyle_SOLID:
357  case drawing::FillStyle_GRADIENT:
358  case drawing::FillStyle_HATCH:
359  isFullSize = true;
360  break;
361  case drawing::FillStyle_BITMAP:
362  {
363  drawing::BitmapMode bitmapMode{};
364  xPropSet->getPropertyValue("FillBitmapMode") >>= bitmapMode;
365  switch (bitmapMode)
366  {
367  case drawing::BitmapMode_REPEAT:
368  isFullSize = true;
369  break;
370  case drawing::BitmapMode_STRETCH:
371  case drawing::BitmapMode_NO_REPEAT:
372  isFullSize = false;
373  break;
374  default:
375  assert(false);
376  }
377  }
378  break;
379  default:
380  assert(false);
381  }
382  }
383  // set it explicitly if it's not the default
384  if (!isFullSize)
385  {
386  SAL_INFO("xmloff.style", "FillPropertySet_PageStyle: Heuristically resetting BackgroundFullSize");
387  xPropSet->setPropertyValue("BackgroundFullSize", uno::makeAny(isFullSize));
388  }
389  }
390 
391  // old code, replaced by above stuff
392  // XMLPropStyleContext::FillPropertySet(rPropSet);
393 
394  if (!sPageUsage.isEmpty())
395  {
396  uno::Any aPageUsage;
397  XMLPMPropHdl_PageStyleLayout aPageUsageHdl;
398  if (aPageUsageHdl.importXML(sPageUsage, aPageUsage, GetImport().GetMM100UnitConverter()))
399  xPropSet->setPropertyValue("PageStyleLayout", aPageUsage);
400  }
401 }
402 
404 {
405  { CTF_PM_FILLGRADIENTNAME, -1, drawing::FillStyle::FillStyle_GRADIENT },
406  { CTF_PM_FILLTRANSNAME, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE },
407  { CTF_PM_FILLHATCHNAME, -1, drawing::FillStyle::FillStyle_HATCH },
408  { CTF_PM_FILLBITMAPNAME, -1, drawing::FillStyle::FillStyle_BITMAP },
409 
410  {-1, -1, drawing::FillStyle::FillStyle_MAKE_FIXED_SIZE}
411 };
412 
413 extern XmlStyleFamily const g_MasterPageFamilies[] =
414 {
419 };
420 
421 // text grid enhancement for better CJK support
422 //set default page layout style
424 {
425  Reference < XMultiServiceFactory > xFactory ( GetImport().GetModel(), UNO_QUERY);
426  if (xFactory.is())
427  {
428  Reference < XInterface > xInt = xFactory->createInstance( "com.sun.star.text.Defaults" );
429  Reference < beans::XPropertySet > xProperties ( xInt, UNO_QUERY );
430  if ( xProperties.is() )
431  FillPropertySet_PageStyle(xProperties, nullptr);
432  }
433 }
434 
435 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int16 nContextID
Definition: xmlimppr.hxx:59
XmlStyleFamily GetFamily() const
Definition: xmlstyle.hxx:83
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
Definition: prstylei.cxx:175
#define XML_TYPE_PROP_PAGE_LAYOUT
Definition: xmltypes.hxx:96
#define CTF_PM_HEADERFILLTRANSNAME
#define CTF_PM_FLAGMASK
sal_Int32 nIndex
#define CTF_PM_FILLGRADIENTNAME
static const OldFillStyleDefinitionSet & getStandardSet()
Definition: prstylei.cxx:160
#define CTF_PM_HEADERFILLHATCHNAME
#define CTF_PM_HEADERFILLBITMAPNAME
enum SAL_DLLPUBLIC_RTTI FillStyle
Definition: xmlimppr.hxx:42
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:59
sal_Int32 mnIndex
Definition: maptype.hxx:124
bool IsDefaultStyle() const
Definition: xmlstyle.hxx:108
css::uno::Any const & rValue
Definition: ImageStyle.hxx:38
XmlStyleFamily
Definition: families.hxx:47
static const sal_uInt16 LO_7x
Definition: xmlimp.hxx:560
PageStyleContext(SvXMLImport &rImport, SvXMLStylesContext &rStyles, bool bDefaultStyle)
#define CTF_PM_FOOTERFILLBITMAPNAME
#define XML_PM_CTF_START
Definition: contextid.hxx:30
static const sal_uInt16 AOO_4x
Definition: xmlimp.hxx:548
#define CTF_PM_FOOTERFILLGRADIENTNAME
#define XMLERROR_FLAG_WARNING
Definition: xmlerror.hxx:35
bool doNewDrawingLayerFillStyleDefinitionsExist(const OUString &rFillStyleTag) const
Definition: prstylei.cxx:519
#define CTF_PM_FILLBITMAPNAME
virtual void FillPropertySet(const css::uno::Reference< css::beans::XPropertySet > &rPropSet) override
static const sal_uInt16 LO_63x
Definition: xmlimp.hxx:559
void deactivateOldFillStyleDefinitions(const OldFillStyleDefinitionSet &rHashSetOfTags)
Definition: prstylei.cxx:565
XmlStyleFamily const g_MasterPageFamilies[]
virtual rtl::Reference< SvXMLImportPropertyMapper > GetImportPropertyMapper(XmlStyleFamily nFamily) const
Definition: xmlstyle.cxx:510
#define XMLERROR_STYLE_PROP_VALUE
Definition: xmlerror.hxx:68
int i
virtual void FillPropertySet(const css::uno::Reference< css::beans::XPropertySet > &rPropSet)
Definition: prstylei.cxx:222
#define CTF_PM_HEADERFILLGRADIENTNAME
virtual void SetAttribute(sal_Int32 nElement, const OUString &rValue) override
::std::vector< XMLPropertyState > & GetProperties()
Definition: prstylei.hxx:79
virtual bool importXML(const OUString &rStrImpValue, css::uno::Any &rValue, const SvXMLUnitConverter &rUnitConverter) const override
Imports the given value according to the XML-data-type corresponding to the derived class...
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
#define CTF_PM_HEADERFLAG
#define CTF_PM_FILLHATCHNAME
#define CTF_PM_FOOTERFILLTRANSNAME
#define CTF_PM_FOOTERFILLHATCHNAME
static const OldFillStyleDefinitionSet & getHeaderSet()
Definition: prstylei.cxx:165
static const OldFillStyleDefinitionSet & getFooterSet()
Definition: prstylei.cxx:170
void FillPropertySet_PageStyle(const css::uno::Reference< css::beans::XPropertySet > &rPropSet, XMLPropStyleContext *pDrawingPageStyle)
css::uno::Any maValue
Definition: maptype.hxx:125
OUString GetStyleDisplayName(XmlStyleFamily nFamily, const OUString &rName) const
Definition: xmlimp.cxx:1412
virtual void SetAttribute(sal_Int32 nElement, const OUString &rValue) override
Definition: prstylei.cxx:57
ContextID_Index_Pair const g_MasterPageContextIDs[]
Handling of tokens in XML:
#define SAL_INFO(area, stream)
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:97
Smart struct to transport an Any with an index to the appropriate property-name.
Definition: maptype.hxx:122
void SetError(sal_Int32 nId, const css::uno::Sequence< OUString > &rMsgParams, const OUString &rExceptionMessage, const css::uno::Reference< css::xml::sax::XLocator > &rLocator)
Record an error condition that occurred during import.
Sequence< sal_Int8 > aSeq
SvXMLStylesContext * GetStyles()
Definition: prstylei.hxx:78
This struct is used as an optional parameter to the static _FillPropertySet() methods.
Definition: xmlimppr.hxx:57
Reference< XSingleServiceFactory > xFactory
#define CTF_PM_FOOTERFLAG
#define CTF_PM_FILLTRANSNAME
virtual void SetDefaults() override
virtual ~PageStyleContext() override