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