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