Coverage Report

Created: 2026-06-30 11:14

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