1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_xmloff.hxx" 26 #include <tools/debug.hxx> 27 #include <com/sun/star/io/XOutputStream.hpp> 28 #include <xmloff/xmltkmap.hxx> 29 #include <xmloff/xmluconv.hxx> 30 #include "xmloff/xmlnmspe.hxx" 31 #include <xmloff/xmltoken.hxx> 32 #include <xmloff/xmlimp.hxx> 33 #include <xmloff/nmspmap.hxx> 34 #include <xmloff/XMLBase64ImportContext.hxx> 35 #include "XMLBackgroundImageContext.hxx" 36 37 using ::rtl::OUString; 38 using ::rtl::OUStringBuffer; 39 40 using namespace ::com::sun::star; 41 using namespace ::com::sun::star::uno; 42 using namespace ::com::sun::star::style; 43 using namespace ::com::sun::star::io; 44 using namespace ::xmloff::token; 45 46 enum SvXMLTokenMapAttrs 47 { 48 XML_TOK_BGIMG_HREF, 49 XML_TOK_BGIMG_TYPE, 50 XML_TOK_BGIMG_ACTUATE, 51 XML_TOK_BGIMG_SHOW, 52 XML_TOK_BGIMG_POSITION, 53 XML_TOK_BGIMG_REPEAT, 54 XML_TOK_BGIMG_FILTER, 55 XML_TOK_BGIMG_OPACITY, 56 XML_TOK_NGIMG_END=XML_TOK_UNKNOWN 57 }; 58 const SvXMLTokenMapEntry* lcl_getBGImgAttributesAttrTokenMap() 59 { 60 static __FAR_DATA SvXMLTokenMapEntry aBGImgAttributesAttrTokenMap[] = 61 { 62 { XML_NAMESPACE_XLINK, XML_HREF, XML_TOK_BGIMG_HREF }, 63 { XML_NAMESPACE_XLINK, XML_TYPE, XML_TOK_BGIMG_TYPE }, 64 { XML_NAMESPACE_XLINK, XML_ACTUATE, XML_TOK_BGIMG_ACTUATE }, 65 { XML_NAMESPACE_XLINK, XML_SHOW, XML_TOK_BGIMG_SHOW }, 66 { XML_NAMESPACE_STYLE, XML_POSITION, XML_TOK_BGIMG_POSITION }, 67 { XML_NAMESPACE_STYLE, XML_REPEAT, XML_TOK_BGIMG_REPEAT }, 68 { XML_NAMESPACE_STYLE, XML_FILTER_NAME, XML_TOK_BGIMG_FILTER }, 69 { XML_NAMESPACE_DRAW, XML_OPACITY, XML_TOK_BGIMG_OPACITY }, 70 XML_TOKEN_MAP_END 71 }; 72 return aBGImgAttributesAttrTokenMap; 73 } 74 75 76 77 SvXMLEnumMapEntry psXML_BrushHoriPos[] = 78 { 79 { XML_LEFT, GraphicLocation_LEFT_MIDDLE }, 80 { XML_RIGHT, GraphicLocation_RIGHT_MIDDLE }, 81 { XML_TOKEN_INVALID, 0 } 82 }; 83 84 SvXMLEnumMapEntry psXML_BrushVertPos[] = 85 { 86 { XML_TOP, GraphicLocation_MIDDLE_TOP }, 87 { XML_BOTTOM, GraphicLocation_MIDDLE_BOTTOM }, 88 { XML_TOKEN_INVALID, 0 } 89 }; 90 91 void lcl_xmlbic_MergeHoriPos( GraphicLocation& ePos, 92 GraphicLocation eHori ) 93 { 94 DBG_ASSERT( GraphicLocation_LEFT_MIDDLE==eHori || 95 GraphicLocation_MIDDLE_MIDDLE==eHori || 96 GraphicLocation_RIGHT_MIDDLE==eHori, 97 "lcl_xmlbic_MergeHoriPos: vertical pos must be middle" ); 98 99 switch( ePos ) 100 { 101 case GraphicLocation_LEFT_TOP: 102 case GraphicLocation_MIDDLE_TOP: 103 case GraphicLocation_RIGHT_TOP: 104 ePos = GraphicLocation_LEFT_MIDDLE==eHori 105 ? GraphicLocation_LEFT_TOP 106 : (GraphicLocation_MIDDLE_MIDDLE==eHori 107 ? GraphicLocation_MIDDLE_TOP 108 : GraphicLocation_RIGHT_TOP); 109 break; 110 111 case GraphicLocation_LEFT_MIDDLE: 112 case GraphicLocation_MIDDLE_MIDDLE: 113 case GraphicLocation_RIGHT_MIDDLE: 114 ePos = eHori; 115 break; 116 117 case GraphicLocation_LEFT_BOTTOM: 118 case GraphicLocation_MIDDLE_BOTTOM: 119 case GraphicLocation_RIGHT_BOTTOM: 120 ePos = GraphicLocation_LEFT_MIDDLE==eHori 121 ? GraphicLocation_LEFT_BOTTOM 122 : (GraphicLocation_MIDDLE_MIDDLE==eHori 123 ? GraphicLocation_MIDDLE_BOTTOM 124 : GraphicLocation_RIGHT_BOTTOM); 125 break; 126 default: 127 break; 128 } 129 } 130 131 void lcl_xmlbic_MergeVertPos( GraphicLocation& ePos, 132 GraphicLocation eVert ) 133 { 134 DBG_ASSERT( GraphicLocation_MIDDLE_TOP==eVert || 135 GraphicLocation_MIDDLE_MIDDLE==eVert || 136 GraphicLocation_MIDDLE_BOTTOM==eVert, 137 "lcl_xmlbic_MergeVertPos: horizontal pos must be middle" ); 138 139 switch( ePos ) 140 { 141 case GraphicLocation_LEFT_TOP: 142 case GraphicLocation_LEFT_MIDDLE: 143 case GraphicLocation_LEFT_BOTTOM: 144 ePos = GraphicLocation_MIDDLE_TOP==eVert 145 ? GraphicLocation_LEFT_TOP 146 : (GraphicLocation_MIDDLE_MIDDLE==eVert 147 ? GraphicLocation_LEFT_MIDDLE 148 : GraphicLocation_LEFT_BOTTOM); 149 ePos = eVert; 150 break; 151 152 case GraphicLocation_MIDDLE_TOP: 153 case GraphicLocation_MIDDLE_MIDDLE: 154 case GraphicLocation_MIDDLE_BOTTOM: 155 ePos = eVert; 156 break; 157 158 case GraphicLocation_RIGHT_TOP: 159 case GraphicLocation_RIGHT_MIDDLE: 160 case GraphicLocation_RIGHT_BOTTOM: 161 ePos = GraphicLocation_MIDDLE_TOP==eVert 162 ? GraphicLocation_RIGHT_TOP 163 : (GraphicLocation_MIDDLE_MIDDLE==eVert 164 ? GraphicLocation_RIGHT_MIDDLE 165 : GraphicLocation_RIGHT_BOTTOM); 166 break; 167 default: 168 break; 169 } 170 } 171 172 TYPEINIT1( XMLBackgroundImageContext, XMLElementPropertyContext ); 173 174 void XMLBackgroundImageContext::ProcessAttrs( 175 const Reference< xml::sax::XAttributeList >& xAttrList ) 176 { 177 SvXMLTokenMap aTokenMap( lcl_getBGImgAttributesAttrTokenMap() ); 178 179 ePos = GraphicLocation_NONE; 180 181 sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; 182 for( sal_Int16 i=0; i < nAttrCount; i++ ) 183 { 184 const OUString& rAttrName = xAttrList->getNameByIndex( i ); 185 OUString aLocalName; 186 sal_uInt16 nPrefix = 187 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName, 188 &aLocalName ); 189 const OUString& rValue = xAttrList->getValueByIndex( i ); 190 191 switch( aTokenMap.Get( nPrefix, aLocalName ) ) 192 { 193 case XML_TOK_BGIMG_HREF: 194 sURL = rValue; 195 if( GraphicLocation_NONE == ePos ) 196 ePos = GraphicLocation_TILED; 197 break; 198 case XML_TOK_BGIMG_TYPE: 199 case XML_TOK_BGIMG_ACTUATE: 200 case XML_TOK_BGIMG_SHOW: 201 break; 202 case XML_TOK_BGIMG_POSITION: 203 { 204 GraphicLocation eNewPos = GraphicLocation_NONE, eTmp; 205 sal_uInt16 nTmp; 206 SvXMLTokenEnumerator aTokenEnum( rValue ); 207 OUString aToken; 208 sal_Bool bHori = sal_False, bVert = sal_False; 209 sal_Bool bOK = sal_True; 210 while( bOK && aTokenEnum.getNextToken( aToken ) ) 211 { 212 if( bHori && bVert ) 213 { 214 bOK = sal_False; 215 } 216 else if( -1 != aToken.indexOf( sal_Unicode('%') ) ) 217 { 218 sal_Int32 nPrc = 50; 219 if( SvXMLUnitConverter::convertPercent( nPrc, aToken ) ) 220 { 221 if( !bHori ) 222 { 223 eNewPos = nPrc < 25 224 ? GraphicLocation_LEFT_TOP 225 : (nPrc < 75 ? GraphicLocation_MIDDLE_MIDDLE 226 : GraphicLocation_RIGHT_BOTTOM); 227 bHori = sal_True; 228 } 229 else 230 { 231 eTmp = nPrc < 25 232 ? GraphicLocation_LEFT_TOP 233 : (nPrc < 75 ? GraphicLocation_LEFT_MIDDLE 234 : GraphicLocation_LEFT_BOTTOM); 235 lcl_xmlbic_MergeVertPos( eNewPos, eTmp ); 236 bVert = sal_True; 237 } 238 } 239 else 240 { 241 // wrong percentage 242 bOK = sal_False; 243 } 244 } 245 else if( IsXMLToken( aToken, XML_CENTER ) ) 246 { 247 if( bHori ) 248 lcl_xmlbic_MergeVertPos( eNewPos, 249 GraphicLocation_MIDDLE_MIDDLE ); 250 else if ( bVert ) 251 lcl_xmlbic_MergeHoriPos( eNewPos, 252 GraphicLocation_MIDDLE_MIDDLE ); 253 else 254 eNewPos = GraphicLocation_MIDDLE_MIDDLE; 255 } 256 else if( SvXMLUnitConverter::convertEnum( nTmp, aToken, 257 psXML_BrushHoriPos ) ) 258 { 259 if( bVert ) 260 lcl_xmlbic_MergeHoriPos( eNewPos, 261 (GraphicLocation)nTmp ); 262 else if( !bHori ) 263 eNewPos = (GraphicLocation)nTmp; 264 else 265 bOK = sal_False; 266 bHori = sal_True; 267 } 268 else if( SvXMLUnitConverter::convertEnum( nTmp, aToken, 269 psXML_BrushVertPos ) ) 270 { 271 if( bHori ) 272 lcl_xmlbic_MergeVertPos( eNewPos, 273 (GraphicLocation)nTmp ); 274 else if( !bVert ) 275 eNewPos = (GraphicLocation)nTmp; 276 else 277 bOK = sal_False; 278 bVert = sal_True; 279 } 280 else 281 { 282 bOK = sal_False; 283 } 284 } 285 286 bOK &= GraphicLocation_NONE != eNewPos; 287 if( bOK ) 288 ePos = eNewPos; 289 } 290 break; 291 case XML_TOK_BGIMG_REPEAT: 292 { 293 sal_uInt16 nPos = GraphicLocation_NONE; 294 static SvXMLEnumMapEntry psXML_BrushRepeat[] = 295 { 296 { XML_BACKGROUND_REPEAT, GraphicLocation_TILED }, 297 { XML_BACKGROUND_NO_REPEAT, GraphicLocation_MIDDLE_MIDDLE }, 298 { XML_BACKGROUND_STRETCH, GraphicLocation_AREA }, 299 { XML_TOKEN_INVALID, 0 } 300 }; 301 if( SvXMLUnitConverter::convertEnum( nPos, rValue, 302 psXML_BrushRepeat ) ) 303 { 304 if( GraphicLocation_MIDDLE_MIDDLE != nPos || 305 GraphicLocation_NONE == ePos || 306 GraphicLocation_AREA == ePos || 307 GraphicLocation_TILED == ePos ) 308 ePos = (GraphicLocation)nPos; 309 } 310 } 311 break; 312 case XML_TOK_BGIMG_FILTER: 313 sFilter = rValue; 314 break; 315 case XML_TOK_BGIMG_OPACITY: 316 { 317 sal_Int32 nTmp; 318 // convert from percent and clip 319 if( SvXMLUnitConverter::convertPercent( nTmp, rValue ) ) 320 { 321 if( (nTmp >= 0) && (nTmp <= 100) ) 322 nTransparency = static_cast<sal_Int8>( 100-nTmp ); 323 } 324 } 325 break; 326 } 327 } 328 329 } 330 331 XMLBackgroundImageContext::XMLBackgroundImageContext( 332 SvXMLImport& rImport, sal_uInt16 nPrfx, 333 const OUString& rLName, 334 const Reference< xml::sax::XAttributeList > & xAttrList, 335 const XMLPropertyState& rProp, 336 sal_Int32 nPosIdx, 337 sal_Int32 nFilterIdx, 338 sal_Int32 nTransparencyIdx, 339 ::std::vector< XMLPropertyState > &rProps ) : 340 XMLElementPropertyContext( rImport, nPrfx, rLName, rProp, rProps ), 341 aPosProp( nPosIdx ), 342 aFilterProp( nFilterIdx ), 343 aTransparencyProp( nTransparencyIdx ), 344 nTransparency( 0 ) 345 { 346 ProcessAttrs( xAttrList ); 347 } 348 349 XMLBackgroundImageContext::~XMLBackgroundImageContext() 350 { 351 } 352 353 SvXMLImportContext *XMLBackgroundImageContext::CreateChildContext( 354 sal_uInt16 nPrefix, const OUString& rLocalName, 355 const Reference< xml::sax::XAttributeList > & xAttrList ) 356 { 357 SvXMLImportContext *pContext = NULL; 358 if( (XML_NAMESPACE_OFFICE == nPrefix) && 359 xmloff::token::IsXMLToken( rLocalName, 360 xmloff::token::XML_BINARY_DATA ) ) 361 { 362 if( !sURL.getLength() && !xBase64Stream.is() ) 363 { 364 xBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64(); 365 if( xBase64Stream.is() ) 366 pContext = new XMLBase64ImportContext( GetImport(), nPrefix, 367 rLocalName, xAttrList, 368 xBase64Stream ); 369 } 370 } 371 if( !pContext ) 372 { 373 pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); 374 } 375 376 return pContext; 377 } 378 379 void XMLBackgroundImageContext::EndElement() 380 { 381 if( sURL.getLength() ) 382 { 383 sURL = GetImport().ResolveGraphicObjectURL( sURL, sal_False ); 384 } 385 else if( xBase64Stream.is() ) 386 { 387 sURL = GetImport().ResolveGraphicObjectURLFromBase64( xBase64Stream ); 388 xBase64Stream = 0; 389 } 390 391 if( !sURL.getLength() ) 392 ePos = GraphicLocation_NONE; 393 else if( GraphicLocation_NONE == ePos ) 394 ePos = GraphicLocation_TILED; 395 396 aProp.maValue <<= sURL; 397 aPosProp.maValue <<= ePos; 398 aFilterProp.maValue <<= sFilter; 399 aTransparencyProp.maValue <<= nTransparency; 400 401 SetInsert( sal_True ); 402 XMLElementPropertyContext::EndElement(); 403 404 if( -1 != aPosProp.mnIndex ) 405 rProperties.push_back( aPosProp ); 406 if( -1 != aFilterProp.mnIndex ) 407 rProperties.push_back( aFilterProp ); 408 if( -1 != aTransparencyProp.mnIndex ) 409 rProperties.push_back( aTransparencyProp ); 410 } 411