Line data Source code
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 <com/sun/star/awt/XBitmap.hpp>
21 : #include <com/sun/star/graphic/XGraphic.hpp>
22 : #include <tools/stream.hxx>
23 : #include <vcl/window.hxx>
24 : #include <vcl/virdev.hxx>
25 : #include <vcl/bitmapex.hxx>
26 : #include <toolkit/helper/vclunohelper.hxx>
27 : #include <svl/style.hxx>
28 : #include <editeng/memberids.hrc>
29 : #include <svx/dialogs.hrc>
30 : #include "svx/xattr.hxx"
31 : #include <svx/xtable.hxx>
32 : #include <svx/xdef.hxx>
33 : #include <svx/unomid.hxx>
34 : #include <editeng/unoprnms.hxx>
35 : #include <svx/unoapi.hxx>
36 : #include <svx/svdmodel.hxx>
37 : #include <svx/xbitmap.hxx>
38 : #include <com/sun/star/beans/PropertyValue.hpp>
39 : #include <vcl/salbtype.hxx>
40 : #include <vcl/bmpacc.hxx>
41 : #include <vcl/dibtools.hxx>
42 :
43 : #include <libxml/xmlwriter.h>
44 :
45 : using namespace ::com::sun::star;
46 :
47 0 : XOBitmap::XOBitmap( const Bitmap& rBmp ) :
48 : eType ( XBITMAP_IMPORT ),
49 : aGraphicObject ( rBmp ),
50 : pPixelArray ( NULL ),
51 0 : bGraphicDirty ( false )
52 : {
53 0 : }
54 :
55 0 : XOBitmap::XOBitmap( const XOBitmap& rXBmp ) :
56 0 : pPixelArray ( NULL )
57 : {
58 0 : eType = rXBmp.eType;
59 0 : aGraphicObject = rXBmp.aGraphicObject;
60 0 : aArraySize = rXBmp.aArraySize;
61 0 : aPixelColor = rXBmp.aPixelColor;
62 0 : aBckgrColor = rXBmp.aBckgrColor;
63 0 : bGraphicDirty = rXBmp.bGraphicDirty;
64 :
65 0 : if( rXBmp.pPixelArray )
66 : {
67 0 : if( eType == XBITMAP_8X8 )
68 : {
69 0 : pPixelArray = new sal_uInt16[ 64 ];
70 :
71 0 : for( sal_uInt16 i = 0; i < 64; i++ )
72 0 : *( pPixelArray + i ) = *( rXBmp.pPixelArray + i );
73 : }
74 : }
75 0 : }
76 :
77 0 : XOBitmap::~XOBitmap()
78 : {
79 0 : delete [] pPixelArray;
80 0 : }
81 :
82 0 : XOBitmap& XOBitmap::operator=( const XOBitmap& rXBmp )
83 : {
84 0 : eType = rXBmp.eType;
85 0 : aGraphicObject = rXBmp.aGraphicObject;
86 0 : aArraySize = rXBmp.aArraySize;
87 0 : aPixelColor = rXBmp.aPixelColor;
88 0 : aBckgrColor = rXBmp.aBckgrColor;
89 0 : bGraphicDirty = rXBmp.bGraphicDirty;
90 :
91 0 : if( rXBmp.pPixelArray )
92 : {
93 0 : if( eType == XBITMAP_8X8 )
94 : {
95 0 : pPixelArray = new sal_uInt16[ 64 ];
96 :
97 0 : for( sal_uInt16 i = 0; i < 64; i++ )
98 0 : *( pPixelArray + i ) = *( rXBmp.pPixelArray + i );
99 : }
100 : }
101 0 : return *this;
102 : }
103 :
104 0 : bool XOBitmap::operator==( const XOBitmap& rXOBitmap ) const
105 : {
106 0 : if( eType != rXOBitmap.eType ||
107 0 : aGraphicObject != rXOBitmap.aGraphicObject ||
108 0 : aArraySize != rXOBitmap.aArraySize ||
109 0 : aPixelColor != rXOBitmap.aPixelColor ||
110 0 : aBckgrColor != rXOBitmap.aBckgrColor ||
111 0 : bGraphicDirty != rXOBitmap.bGraphicDirty )
112 : {
113 0 : return false;
114 : }
115 :
116 0 : if( pPixelArray && rXOBitmap.pPixelArray )
117 : {
118 0 : sal_uInt16 nCount = (sal_uInt16) ( aArraySize.Width() * aArraySize.Height() );
119 0 : for( sal_uInt16 i = 0; i < nCount; i++ )
120 : {
121 0 : if( *( pPixelArray + i ) != *( rXOBitmap.pPixelArray + i ) )
122 0 : return false;
123 : }
124 : }
125 0 : return true;
126 : }
127 :
128 0 : Bitmap XOBitmap::GetBitmap() const
129 : {
130 0 : return GetGraphicObject().GetGraphic().GetBitmap();
131 : }
132 :
133 0 : const GraphicObject& XOBitmap::GetGraphicObject() const
134 : {
135 0 : if( bGraphicDirty )
136 0 : const_cast<XOBitmap*>(this)->Array2Bitmap();
137 :
138 0 : return aGraphicObject;
139 : }
140 :
141 0 : void XOBitmap::Bitmap2Array()
142 : {
143 0 : ScopedVclPtrInstance< VirtualDevice > pVDev;
144 0 : bool bPixelColor = false;
145 0 : const Bitmap aBitmap( GetBitmap() );
146 0 : const sal_uInt16 nLines = 8; // type dependent
147 :
148 0 : if( !pPixelArray )
149 0 : pPixelArray = new sal_uInt16[ nLines * nLines ];
150 :
151 0 : pVDev->SetOutputSizePixel( aBitmap.GetSizePixel() );
152 0 : pVDev->DrawBitmap( Point(), aBitmap );
153 0 : aPixelColor = aBckgrColor = pVDev->GetPixel( Point() );
154 :
155 : // create array and determine foreground and background color
156 0 : for( sal_uInt16 i = 0; i < nLines; i++ )
157 : {
158 0 : for( sal_uInt16 j = 0; j < nLines; j++ )
159 : {
160 0 : if ( pVDev->GetPixel( Point( j, i ) ) == aBckgrColor )
161 0 : *( pPixelArray + j + i * nLines ) = 0;
162 : else
163 : {
164 0 : *( pPixelArray + j + i * nLines ) = 1;
165 0 : if( !bPixelColor )
166 : {
167 0 : aPixelColor = pVDev->GetPixel( Point( j, i ) );
168 0 : bPixelColor = true;
169 : }
170 : }
171 : }
172 0 : }
173 0 : }
174 :
175 : /// convert array, fore- and background color into a bitmap
176 0 : void XOBitmap::Array2Bitmap()
177 : {
178 0 : ScopedVclPtrInstance< VirtualDevice > pVDev;
179 0 : sal_uInt16 nLines = 8; // type dependent
180 :
181 0 : if( !pPixelArray )
182 0 : return;
183 :
184 0 : pVDev->SetOutputSizePixel( Size( nLines, nLines ) );
185 :
186 : // create bitmap
187 0 : for( sal_uInt16 i = 0; i < nLines; i++ )
188 : {
189 0 : for( sal_uInt16 j = 0; j < nLines; j++ )
190 : {
191 0 : if( *( pPixelArray + j + i * nLines ) == 0 )
192 0 : pVDev->DrawPixel( Point( j, i ), aBckgrColor );
193 : else
194 0 : pVDev->DrawPixel( Point( j, i ), aPixelColor );
195 : }
196 : }
197 :
198 0 : aGraphicObject = GraphicObject( pVDev->GetBitmap( Point(), Size( nLines, nLines ) ) );
199 0 : bGraphicDirty = false;
200 : }
201 :
202 28775 : TYPEINIT1_AUTOFACTORY(XFillBitmapItem, NameOrIndex);
203 :
204 27 : XFillBitmapItem::XFillBitmapItem(const OUString& rName, const GraphicObject& rGraphicObject)
205 : : NameOrIndex(XATTR_FILLBITMAP, rName),
206 27 : maGraphicObject(rGraphicObject)
207 : {
208 27 : }
209 :
210 720 : XFillBitmapItem::XFillBitmapItem(const XFillBitmapItem& rItem)
211 : : NameOrIndex(rItem),
212 720 : maGraphicObject(rItem.maGraphicObject)
213 : {
214 720 : }
215 :
216 0 : Bitmap createHistorical8x8FromArray(const sal_uInt16* pArray, Color aColorPix, Color aColorBack)
217 : {
218 0 : BitmapPalette aPalette(2);
219 :
220 0 : aPalette[0] = BitmapColor(aColorBack);
221 0 : aPalette[1] = BitmapColor(aColorPix);
222 :
223 0 : Bitmap aBitmap(Size(8, 8), 1, &aPalette);
224 0 : BitmapWriteAccess* pContent = aBitmap.AcquireWriteAccess();
225 :
226 0 : if(pContent)
227 : {
228 0 : for(sal_uInt16 a(0); a < 8; a++)
229 : {
230 0 : for(sal_uInt16 b(0); b < 8; b++)
231 : {
232 0 : if(pArray[(a * 8) + b])
233 : {
234 0 : pContent->SetPixelIndex(a, b, 1);
235 : }
236 : else
237 : {
238 0 : pContent->SetPixelIndex(a, b, 0);
239 : }
240 : }
241 : }
242 :
243 0 : Bitmap::ReleaseAccess(pContent);
244 : }
245 :
246 0 : return aBitmap;
247 : }
248 :
249 0 : bool isHistorical8x8(const BitmapEx& rBitmapEx, BitmapColor& o_rBack, BitmapColor& o_rFront)
250 : {
251 0 : if(!rBitmapEx.IsTransparent())
252 : {
253 0 : Bitmap aBitmap(rBitmapEx.GetBitmap());
254 :
255 0 : if(8 == aBitmap.GetSizePixel().Width() && 8 == aBitmap.GetSizePixel().Height())
256 : {
257 0 : if(2 == aBitmap.GetColorCount())
258 : {
259 0 : BitmapReadAccess* pRead = aBitmap.AcquireReadAccess();
260 :
261 0 : if(pRead)
262 : {
263 0 : if(pRead->HasPalette() && 2 == pRead->GetPaletteEntryCount())
264 : {
265 0 : const BitmapPalette& rPalette = pRead->GetPalette();
266 :
267 : // #i123564# bachground and foregrund were exchanged; of course
268 : // rPalette[0] is the background color
269 0 : o_rFront = rPalette[1];
270 0 : o_rBack = rPalette[0];
271 :
272 0 : return true;
273 : }
274 : }
275 : }
276 0 : }
277 : }
278 :
279 0 : return false;
280 : }
281 :
282 0 : XFillBitmapItem::XFillBitmapItem(SvStream& rIn, sal_uInt16 nVer)
283 0 : : NameOrIndex(XATTR_FILLBITMAP, rIn)
284 : {
285 0 : if (!IsIndex())
286 : {
287 0 : if(0 == nVer)
288 : {
289 : // work with the old bitmap
290 0 : Bitmap aBmp;
291 :
292 0 : ReadDIB(aBmp, rIn, true);
293 0 : maGraphicObject = Graphic(aBmp);
294 : }
295 0 : else if(1 == nVer)
296 : {
297 : sal_Int16 iTmp;
298 :
299 0 : rIn.ReadInt16( iTmp ); // former XBitmapStyle
300 0 : rIn.ReadInt16( iTmp ); // former XBitmapType
301 :
302 0 : if(XBITMAP_IMPORT == iTmp)
303 : {
304 0 : Bitmap aBmp;
305 :
306 0 : ReadDIB(aBmp, rIn, true);
307 0 : maGraphicObject = Graphic(aBmp);
308 : }
309 0 : else if(XBITMAP_8X8 == iTmp)
310 : {
311 : sal_uInt16 aArray[64];
312 :
313 0 : for(sal_uInt16 i(0); i < 64; i++)
314 : {
315 0 : rIn.ReadUInt16( aArray[i] );
316 : }
317 :
318 0 : Color aColorPix;
319 0 : Color aColorBack;
320 :
321 0 : ReadColor( rIn, aColorPix );
322 0 : ReadColor( rIn, aColorBack );
323 :
324 0 : const Bitmap aBitmap(createHistorical8x8FromArray(aArray, aColorPix, aColorBack));
325 :
326 0 : maGraphicObject = Graphic(aBitmap);
327 : }
328 : }
329 0 : else if(2 == nVer)
330 : {
331 0 : BitmapEx aBmpEx;
332 :
333 0 : ReadDIBBitmapEx(aBmpEx, rIn);
334 0 : maGraphicObject = Graphic(aBmpEx);
335 : }
336 : }
337 0 : }
338 :
339 5077 : XFillBitmapItem::XFillBitmapItem(SfxItemPool* /*pPool*/, const GraphicObject& rGraphicObject)
340 : : NameOrIndex( XATTR_FILLBITMAP, -1),
341 5077 : maGraphicObject(rGraphicObject)
342 : {
343 5077 : }
344 :
345 720 : SfxPoolItem* XFillBitmapItem::Clone(SfxItemPool* /*pPool*/) const
346 : {
347 720 : return new XFillBitmapItem(*this);
348 : }
349 :
350 1170 : bool XFillBitmapItem::operator==(const SfxPoolItem& rItem) const
351 : {
352 1170 : return (NameOrIndex::operator==(rItem)
353 1170 : && maGraphicObject == static_cast<const XFillBitmapItem&>(rItem).maGraphicObject);
354 : }
355 :
356 0 : SfxPoolItem* XFillBitmapItem::Create(SvStream& rIn, sal_uInt16 nVer) const
357 : {
358 0 : return new XFillBitmapItem( rIn, nVer );
359 : }
360 :
361 0 : SvStream& XFillBitmapItem::Store( SvStream& rOut, sal_uInt16 nItemVersion ) const
362 : {
363 0 : NameOrIndex::Store(rOut, nItemVersion);
364 :
365 0 : if(!IsIndex())
366 : {
367 0 : WriteDIBBitmapEx(maGraphicObject.GetGraphic().GetBitmapEx(), rOut);
368 : }
369 :
370 0 : return rOut;
371 : }
372 :
373 :
374 0 : void XFillBitmapItem::SetGraphicObject(const GraphicObject& rGraphicObject)
375 : {
376 0 : maGraphicObject = rGraphicObject;
377 0 : }
378 :
379 0 : sal_uInt16 XFillBitmapItem::GetVersion(sal_uInt16 /*nFileFormatVersion*/) const
380 : {
381 0 : return 2;
382 : }
383 :
384 0 : bool XFillBitmapItem::GetPresentation(
385 : SfxItemPresentation /*ePres*/,
386 : SfxMapUnit /*eCoreUnit*/,
387 : SfxMapUnit /*ePresUnit*/,
388 : OUString& rText,
389 : const IntlWrapper*) const
390 : {
391 0 : rText += GetName();
392 0 : return true;
393 : }
394 :
395 940 : bool XFillBitmapItem::QueryValue(::com::sun::star::uno::Any& rVal, sal_uInt8 nMemberId) const
396 : {
397 940 : nMemberId &= ~CONVERT_TWIPS;
398 :
399 : // needed for MID_NAME
400 940 : OUString aApiName;
401 : // needed for complete item (MID 0)
402 1880 : OUString aInternalName;
403 :
404 1880 : OUString aURL;
405 1880 : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap > xBmp;
406 :
407 940 : if( nMemberId == MID_NAME )
408 : {
409 291 : aApiName = SvxUnogetApiNameForItem(Which(), GetName());
410 : }
411 649 : else if( nMemberId == 0 )
412 : {
413 79 : aInternalName = GetName();
414 : }
415 :
416 940 : if( nMemberId == MID_GRAFURL ||
417 : nMemberId == 0 )
418 : {
419 375 : aURL = UNO_NAME_GRAPHOBJ_URLPREFIX;
420 750 : aURL += OStringToOUString(
421 375 : GetGraphicObject().GetUniqueID(),
422 375 : RTL_TEXTENCODING_ASCII_US);
423 : }
424 940 : if( nMemberId == MID_BITMAP ||
425 : nMemberId == 0 )
426 : {
427 353 : xBmp.set(VCLUnoHelper::CreateBitmap(GetGraphicObject().GetGraphic().GetBitmapEx()));
428 : }
429 :
430 940 : if( nMemberId == MID_NAME )
431 291 : rVal <<= aApiName;
432 649 : else if( nMemberId == MID_GRAFURL )
433 296 : rVal <<= aURL;
434 353 : else if( nMemberId == MID_BITMAP )
435 274 : rVal <<= xBmp;
436 : else
437 : {
438 : // member-id 0 => complete item (e.g. for toolbars)
439 : DBG_ASSERT( nMemberId == 0, "invalid member-id" );
440 79 : uno::Sequence< beans::PropertyValue > aPropSeq( 3 );
441 :
442 79 : aPropSeq[0].Name = "Name";
443 79 : aPropSeq[0].Value = uno::makeAny( aInternalName );
444 79 : aPropSeq[1].Name = "FillBitmapURL";
445 79 : aPropSeq[1].Value = uno::makeAny( aURL );
446 79 : aPropSeq[2].Name = "Bitmap";
447 79 : aPropSeq[2].Value = uno::makeAny( xBmp );
448 :
449 79 : rVal <<= aPropSeq;
450 : }
451 :
452 1880 : return true;
453 : }
454 :
455 239 : bool XFillBitmapItem::PutValue( const ::com::sun::star::uno::Any& rVal, sal_uInt8 nMemberId )
456 : {
457 239 : nMemberId &= ~CONVERT_TWIPS;
458 :
459 239 : OUString aName;
460 478 : OUString aURL;
461 478 : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XBitmap > xBmp;
462 478 : ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic > xGraphic;
463 :
464 239 : bool bSetName = false;
465 239 : bool bSetURL = false;
466 239 : bool bSetBitmap = false;
467 :
468 239 : if( nMemberId == MID_NAME )
469 0 : bSetName = (rVal >>= aName);
470 239 : else if( nMemberId == MID_GRAFURL )
471 152 : bSetURL = (rVal >>= aURL);
472 87 : else if( nMemberId == MID_BITMAP )
473 : {
474 8 : bSetBitmap = (rVal >>= xBmp);
475 8 : if ( !bSetBitmap )
476 0 : bSetBitmap = (rVal >>= xGraphic );
477 : }
478 : else
479 : {
480 : DBG_ASSERT( nMemberId == 0, "invalid member-id" );
481 79 : uno::Sequence< beans::PropertyValue > aPropSeq;
482 79 : if( rVal >>= aPropSeq )
483 : {
484 316 : for ( sal_Int32 n = 0; n < aPropSeq.getLength(); n++ )
485 : {
486 237 : if ( aPropSeq[n].Name == "Name" )
487 79 : bSetName = (aPropSeq[n].Value >>= aName);
488 158 : else if ( aPropSeq[n].Name == "FillBitmapURL" )
489 79 : bSetURL = (aPropSeq[n].Value >>= aURL);
490 79 : else if ( aPropSeq[n].Name == "Bitmap" )
491 79 : bSetBitmap = (aPropSeq[n].Value >>= xBmp);
492 : }
493 79 : }
494 : }
495 :
496 239 : if( bSetName )
497 : {
498 79 : SetName( aName );
499 : }
500 239 : if( bSetURL )
501 : {
502 231 : GraphicObject aGraphicObject = GraphicObject::CreateGraphicObjectFromURL(aURL);
503 231 : if( aGraphicObject.GetType() != GRAPHIC_NONE )
504 217 : maGraphicObject = aGraphicObject;
505 :
506 : // #121194# Prefer GraphicObject over bitmap object if both are provided
507 231 : if(bSetBitmap && GRAPHIC_NONE != maGraphicObject.GetType())
508 : {
509 79 : bSetBitmap = false;
510 231 : }
511 : }
512 239 : if( bSetBitmap )
513 : {
514 8 : if(xBmp.is())
515 : {
516 0 : maGraphicObject = Graphic(VCLUnoHelper::GetBitmap(xBmp));
517 : }
518 8 : else if(xGraphic.is())
519 : {
520 0 : maGraphicObject = Graphic(xGraphic);
521 : }
522 : }
523 :
524 478 : return (bSetName || bSetURL || bSetBitmap);
525 : }
526 :
527 8207 : bool XFillBitmapItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
528 : {
529 8207 : const GraphicObject& aGraphicObjectA(static_cast<const XFillBitmapItem*>(p1)->GetGraphicObject());
530 8207 : const GraphicObject& aGraphicObjectB(static_cast<const XFillBitmapItem*>(p2)->GetGraphicObject());
531 :
532 8207 : return aGraphicObjectA == aGraphicObjectB;
533 : }
534 :
535 8325 : XFillBitmapItem* XFillBitmapItem::checkForUniqueItem( SdrModel* pModel ) const
536 : {
537 8325 : if( pModel )
538 : {
539 : const OUString aUniqueName = NameOrIndex::CheckNamedItem(
540 8213 : this, XATTR_FILLBITMAP, &pModel->GetItemPool(),
541 8298 : pModel->GetStyleSheetPool() ? &pModel->GetStyleSheetPool()->GetPool() : NULL,
542 : XFillBitmapItem::CompareValueFunc, RID_SVXSTR_BMP21,
543 24724 : pModel->GetPropertyList( XBITMAP_LIST ) );
544 :
545 : // if the given name is not valid, replace it!
546 8213 : if( aUniqueName != GetName() )
547 : {
548 14 : return new XFillBitmapItem(aUniqueName, maGraphicObject);
549 8199 : }
550 : }
551 :
552 8311 : return NULL;
553 : }
554 :
555 0 : void XFillBitmapItem::dumpAsXml(xmlTextWriterPtr pWriter) const
556 : {
557 0 : xmlTextWriterStartElement(pWriter, BAD_CAST("xFillBitmapItem"));
558 0 : xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
559 :
560 0 : NameOrIndex::dumpAsXml(pWriter);
561 :
562 0 : xmlTextWriterEndElement(pWriter);
563 435 : }
564 :
565 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|