Coverage Report

Created: 2025-07-07 10:01

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