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/debug.hxx>
23 #include <vcl/virdev.hxx>
24 #include <vcl/bitmapex.hxx>
25 #include <svl/style.hxx>
26 #include <editeng/memberids.h>
27 #include <svx/strings.hrc>
28 #include <svx/xtable.hxx>
29 #include <svx/xdef.hxx>
30 #include <svx/unomid.hxx>
31 #include <svx/unoapi.hxx>
32 #include <svx/svdmodel.hxx>
33 #include <svx/xbitmap.hxx>
34 #include <svx/xbtmpit.hxx>
35 #include <com/sun/star/beans/PropertyValue.hpp>
36 #include <vcl/BitmapTools.hxx>
37 #include <vcl/GraphicLoader.hxx>
38 
39 #include <libxml/xmlwriter.h>
40 
41 using namespace ::com::sun::star;
42 
XOBitmap(const BitmapEx & rBmp)43 XOBitmap::XOBitmap( const BitmapEx& rBmp ) :
44     xGraphicObject  (new GraphicObject(rBmp)),
45     bGraphicDirty   ( false )
46 {
47 }
48 
~XOBitmap()49 XOBitmap::~XOBitmap()
50 {
51 }
52 
GetBitmap() const53 BitmapEx XOBitmap::GetBitmap() const
54 {
55     return GetGraphicObject().GetGraphic().GetBitmapEx();
56 }
57 
GetGraphicObject() const58 const GraphicObject& XOBitmap::GetGraphicObject() const
59 {
60     if( bGraphicDirty )
61         const_cast<XOBitmap*>(this)->Array2Bitmap();
62 
63     return *xGraphicObject;
64 }
65 
Bitmap2Array()66 void XOBitmap::Bitmap2Array()
67 {
68     ScopedVclPtrInstance< VirtualDevice > pVDev;
69     bool            bPixelColor = false;
70     const BitmapEx  aBitmap( GetBitmap() );
71     const sal_Int32 nLines = 8; // type dependent
72 
73     if( !pPixelArray )
74         pPixelArray.reset( new sal_uInt16[ nLines * nLines ] );
75 
76     pVDev->SetOutputSizePixel( aBitmap.GetSizePixel() );
77     pVDev->DrawBitmapEx( Point(), aBitmap );
78     aPixelColor = aBckgrColor = pVDev->GetPixel( Point() );
79 
80     // create array and determine foreground and background color
81     for (sal_Int32 i = 0; i < nLines; ++i)
82     {
83         for (sal_Int32 j = 0; j < nLines; ++j)
84         {
85             if ( pVDev->GetPixel( Point( j, i ) ) == aBckgrColor )
86                 pPixelArray[ j + i * nLines ] = 0;
87             else
88             {
89                 pPixelArray[ j + i * nLines ] = 1;
90                 if( !bPixelColor )
91                 {
92                     aPixelColor = pVDev->GetPixel( Point( j, i ) );
93                     bPixelColor = true;
94                 }
95             }
96         }
97     }
98 }
99 
100 /// convert array, fore- and background color into a bitmap
Array2Bitmap()101 void XOBitmap::Array2Bitmap()
102 {
103     if (!pPixelArray)
104         return;
105 
106     ScopedVclPtrInstance< VirtualDevice > pVDev;
107     const sal_Int32 nLines = 8; // type dependent
108 
109     pVDev->SetOutputSizePixel( Size( nLines, nLines ) );
110 
111     // create bitmap
112     for (sal_Int32 i = 0; i < nLines; ++i)
113     {
114         for (sal_Int32 j = 0; j < nLines; ++j)
115         {
116             if( pPixelArray[ j + i * nLines ] == 0 )
117                 pVDev->DrawPixel( Point( j, i ), aBckgrColor );
118             else
119                 pVDev->DrawPixel( Point( j, i ), aPixelColor );
120         }
121     }
122 
123     xGraphicObject.reset(new GraphicObject(pVDev->GetBitmapEx(Point(), Size(nLines, nLines))));
124     bGraphicDirty = false;
125 }
126 
127 
CreateDefault()128 SfxPoolItem* XFillBitmapItem::CreateDefault() { return new XFillBitmapItem; }
129 
XFillBitmapItem(const OUString & rName,const GraphicObject & rGraphicObject)130 XFillBitmapItem::XFillBitmapItem(const OUString& rName, const GraphicObject& rGraphicObject)
131 :   NameOrIndex(XATTR_FILLBITMAP, rName),
132     maGraphicObject(rGraphicObject)
133 {
134 }
135 
XFillBitmapItem(const XFillBitmapItem & rItem)136 XFillBitmapItem::XFillBitmapItem(const XFillBitmapItem& rItem)
137 :   NameOrIndex(rItem),
138     maGraphicObject(rItem.maGraphicObject)
139 {
140 }
141 
XFillBitmapItem(const GraphicObject & rGraphicObject)142 XFillBitmapItem::XFillBitmapItem(const GraphicObject& rGraphicObject)
143     : NameOrIndex(XATTR_FILLBITMAP, -1)
144     , maGraphicObject(rGraphicObject)
145 {
146 }
147 
Clone(SfxItemPool *) const148 XFillBitmapItem* XFillBitmapItem::Clone(SfxItemPool* /*pPool*/) const
149 {
150     return new XFillBitmapItem(*this);
151 }
152 
operator ==(const SfxPoolItem & rItem) const153 bool XFillBitmapItem::operator==(const SfxPoolItem& rItem) const
154 {
155     return (NameOrIndex::operator==(rItem)
156         && maGraphicObject == static_cast<const XFillBitmapItem&>(rItem).maGraphicObject);
157 }
158 
159 
isPattern() const160 bool XFillBitmapItem::isPattern() const
161 {
162     Color aBack, aFront;
163     return vcl::bitmap::isHistorical8x8(GetGraphicObject().GetGraphic().GetBitmapEx(), aBack, aFront);
164 }
165 
GetPresentation(SfxItemPresentation,MapUnit,MapUnit,OUString & rText,const IntlWrapper &) const166 bool XFillBitmapItem::GetPresentation(
167     SfxItemPresentation /*ePres*/,
168     MapUnit /*eCoreUnit*/,
169     MapUnit /*ePresUnit*/,
170     OUString& rText,
171     const IntlWrapper&) const
172 {
173     rText += GetName();
174     return true;
175 }
176 
QueryValue(css::uno::Any & rVal,sal_uInt8 nMemberId) const177 bool XFillBitmapItem::QueryValue(css::uno::Any& rVal, sal_uInt8 nMemberId) const
178 {
179     nMemberId &= ~CONVERT_TWIPS;
180 
181     // needed for MID_NAME
182     OUString aApiName;
183     // needed for complete item (MID 0)
184     OUString aInternalName;
185 
186     css::uno::Reference< css::awt::XBitmap > xBmp;
187 
188     if( nMemberId == MID_NAME )
189     {
190          aApiName = SvxUnogetApiNameForItem(Which(), GetName());
191     }
192     else if( nMemberId == 0  )
193     {
194         aInternalName = GetName();
195     }
196 
197     if (nMemberId == MID_BITMAP ||
198         nMemberId == 0)
199     {
200         xBmp.set(GetGraphicObject().GetGraphic().GetXGraphic(), uno::UNO_QUERY);
201     }
202 
203     if( nMemberId == MID_NAME )
204         rVal <<= aApiName;
205     else if( nMemberId == MID_BITMAP )
206         rVal <<= xBmp;
207     else
208     {
209         // member-id 0 => complete item (e.g. for toolbars)
210         DBG_ASSERT( nMemberId == 0, "invalid member-id" );
211         uno::Sequence< beans::PropertyValue > aPropSeq( 2 );
212 
213         aPropSeq[0].Name  = "Name";
214         aPropSeq[0].Value <<= aInternalName;
215         aPropSeq[1].Name  = "Bitmap";
216         aPropSeq[1].Value <<= xBmp;
217 
218         rVal <<= aPropSeq;
219     }
220 
221     return true;
222 }
223 
PutValue(const css::uno::Any & rVal,sal_uInt8 nMemberId)224 bool XFillBitmapItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
225 {
226     nMemberId &= ~CONVERT_TWIPS;
227 
228     OUString aName;
229     OUString aURL;
230     css::uno::Reference< css::awt::XBitmap > xBmp;
231     css::uno::Reference< css::graphic::XGraphic > xGraphic;
232 
233     bool bSetURL    = false;
234     bool bSetName   = false;
235     bool bSetBitmap = false;
236 
237     if( nMemberId == MID_NAME )
238         bSetName = (rVal >>= aName);
239     else if( nMemberId == MID_BITMAP )
240     {
241         if (rVal.has<OUString>())
242         {
243             bSetURL = true;
244             aURL = rVal.get<OUString>();
245         }
246         else if (rVal.has<uno::Reference<awt::XBitmap>>())
247         {
248             bSetBitmap = true;
249             xBmp = rVal.get<uno::Reference<awt::XBitmap>>();
250         }
251         else if (rVal.has<uno::Reference<graphic::XGraphic>>())
252         {
253             bSetBitmap = true;
254             xGraphic = rVal.get<uno::Reference<graphic::XGraphic>>();
255         }
256     }
257     else
258     {
259         DBG_ASSERT( nMemberId == 0, "invalid member-id" );
260         uno::Sequence< beans::PropertyValue >   aPropSeq;
261         if( rVal >>= aPropSeq )
262         {
263             for ( const auto& rProp : std::as_const(aPropSeq) )
264             {
265                 if ( rProp.Name == "Name" )
266                     bSetName = (rProp.Value >>= aName);
267                 else if ( rProp.Name == "Bitmap" )
268                     bSetBitmap = (rProp.Value >>= xBmp);
269                 else if ( rProp.Name == "FillBitmapURL" )
270                     bSetURL = (rProp.Value >>= aURL);
271             }
272         }
273     }
274 
275     if( bSetName )
276     {
277         SetName( aName );
278     }
279     if (bSetURL && !aURL.isEmpty())
280     {
281         Graphic aGraphic = vcl::graphic::loadFromURL(aURL);
282         if (!aGraphic.IsNone())
283         {
284             maGraphicObject.SetGraphic(aGraphic.GetXGraphic());
285         }
286     }
287     else if( bSetBitmap )
288     {
289         if (xBmp.is())
290         {
291             xGraphic.set(xBmp, uno::UNO_QUERY);
292         }
293         if (xGraphic.is())
294         {
295             maGraphicObject.SetGraphic(xGraphic);
296         }
297     }
298 
299     return (bSetURL || bSetName || bSetBitmap);
300 }
301 
CompareValueFunc(const NameOrIndex * p1,const NameOrIndex * p2)302 bool XFillBitmapItem::CompareValueFunc( const NameOrIndex* p1, const NameOrIndex* p2 )
303 {
304     const GraphicObject& aGraphicObjectA(static_cast<const XFillBitmapItem*>(p1)->GetGraphicObject());
305     const GraphicObject& aGraphicObjectB(static_cast<const XFillBitmapItem*>(p2)->GetGraphicObject());
306 
307     return aGraphicObjectA == aGraphicObjectB;
308 }
309 
checkForUniqueItem(SdrModel * pModel) const310 std::unique_ptr<XFillBitmapItem> XFillBitmapItem::checkForUniqueItem( SdrModel* pModel ) const
311 {
312     if( pModel )
313     {
314         XPropertyListType aListType = XPropertyListType::Bitmap;
315         if(isPattern())
316             aListType = XPropertyListType::Pattern;
317         const OUString aUniqueName = NameOrIndex::CheckNamedItem(
318                 this, XATTR_FILLBITMAP, &pModel->GetItemPool(),
319                 XFillBitmapItem::CompareValueFunc, RID_SVXSTR_BMP21,
320                 pModel->GetPropertyList( aListType ) );
321 
322         // if the given name is not valid, replace it!
323         if( aUniqueName != GetName() )
324         {
325             return std::make_unique<XFillBitmapItem>(aUniqueName, maGraphicObject);
326         }
327     }
328 
329     return nullptr;
330 }
331 
dumpAsXml(xmlTextWriterPtr pWriter) const332 void XFillBitmapItem::dumpAsXml(xmlTextWriterPtr pWriter) const
333 {
334     (void)xmlTextWriterStartElement(pWriter, BAD_CAST("XFillBitmapItem"));
335     (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
336 
337     NameOrIndex::dumpAsXml(pWriter);
338 
339     (void)xmlTextWriterEndElement(pWriter);
340 }
341 
342 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
343