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 <drawinglayer/attribute/sdrfillbitmapattribute.hxx>
21 : #include <drawinglayer/attribute/fillbitmapattribute.hxx>
22 : #include <vcl/bitmapex.hxx>
23 :
24 : //////////////////////////////////////////////////////////////////////////////
25 :
26 : namespace drawinglayer
27 : {
28 : namespace attribute
29 : {
30 0 : class ImpSdrFillBitmapAttribute
31 : {
32 : public:
33 : // refcounter
34 : sal_uInt32 mnRefCount;
35 :
36 : // data definitions
37 : Bitmap maBitmap;
38 : basegfx::B2DVector maSize;
39 : basegfx::B2DVector maOffset;
40 : basegfx::B2DVector maOffsetPosition;
41 : basegfx::B2DVector maRectPoint;
42 :
43 : // bitfield
44 : unsigned mbTiling : 1;
45 : unsigned mbStretch : 1;
46 : unsigned mbLogSize : 1;
47 :
48 9 : ImpSdrFillBitmapAttribute(
49 : const Bitmap& rBitmap,
50 : const basegfx::B2DVector& rSize,
51 : const basegfx::B2DVector& rOffset,
52 : const basegfx::B2DVector& rOffsetPosition,
53 : const basegfx::B2DVector& rRectPoint,
54 : bool bTiling,
55 : bool bStretch,
56 : bool bLogSize)
57 : : mnRefCount(0),
58 : maBitmap(rBitmap),
59 : maSize(rSize),
60 : maOffset(rOffset),
61 : maOffsetPosition(rOffsetPosition),
62 : maRectPoint(rRectPoint),
63 : mbTiling(bTiling),
64 : mbStretch(bStretch),
65 9 : mbLogSize(bLogSize)
66 : {
67 9 : }
68 :
69 : // data read access
70 0 : const Bitmap& getBitmap() const { return maBitmap; }
71 0 : const basegfx::B2DVector& getSize() const { return maSize; }
72 0 : const basegfx::B2DVector& getOffset() const { return maOffset; }
73 0 : const basegfx::B2DVector& getOffsetPosition() const { return maOffsetPosition; }
74 0 : const basegfx::B2DVector& getRectPoint() const { return maRectPoint; }
75 0 : bool getTiling() const { return mbTiling; }
76 0 : bool getStretch() const { return mbStretch; }
77 0 : bool getLogSize() const { return mbLogSize; }
78 :
79 0 : bool operator==(const ImpSdrFillBitmapAttribute& rCandidate) const
80 : {
81 0 : return (getBitmap() == rCandidate.getBitmap()
82 0 : && getSize() == rCandidate.getSize()
83 0 : && getOffset() == rCandidate.getOffset()
84 0 : && getOffsetPosition() == rCandidate.getOffsetPosition()
85 0 : && getRectPoint() == rCandidate.getRectPoint()
86 0 : && getTiling() == rCandidate.getTiling()
87 0 : && getStretch() == rCandidate.getStretch()
88 0 : && getLogSize() == rCandidate.getLogSize());
89 : }
90 :
91 71 : static ImpSdrFillBitmapAttribute* get_global_default()
92 : {
93 : static ImpSdrFillBitmapAttribute* pDefault = 0;
94 :
95 71 : if(!pDefault)
96 : {
97 : pDefault = new ImpSdrFillBitmapAttribute(
98 : Bitmap(),
99 : basegfx::B2DVector(),
100 : basegfx::B2DVector(),
101 : basegfx::B2DVector(),
102 : basegfx::B2DVector(),
103 : false,
104 : false,
105 9 : false);
106 :
107 : // never delete; start with RefCount 1, not 0
108 9 : pDefault->mnRefCount++;
109 : }
110 :
111 71 : return pDefault;
112 : }
113 : };
114 :
115 0 : SdrFillBitmapAttribute::SdrFillBitmapAttribute(
116 : const Bitmap& rBitmap,
117 : const basegfx::B2DVector& rSize,
118 : const basegfx::B2DVector& rOffset,
119 : const basegfx::B2DVector& rOffsetPosition,
120 : const basegfx::B2DVector& rRectPoint,
121 : bool bTiling,
122 : bool bStretch,
123 : bool bLogSize)
124 : : mpSdrFillBitmapAttribute(new ImpSdrFillBitmapAttribute(
125 0 : rBitmap, rSize, rOffset, rOffsetPosition, rRectPoint, bTiling, bStretch, bLogSize))
126 : {
127 0 : }
128 :
129 48 : SdrFillBitmapAttribute::SdrFillBitmapAttribute()
130 48 : : mpSdrFillBitmapAttribute(ImpSdrFillBitmapAttribute::get_global_default())
131 : {
132 48 : mpSdrFillBitmapAttribute->mnRefCount++;
133 48 : }
134 :
135 48 : SdrFillBitmapAttribute::SdrFillBitmapAttribute(const SdrFillBitmapAttribute& rCandidate)
136 48 : : mpSdrFillBitmapAttribute(rCandidate.mpSdrFillBitmapAttribute)
137 : {
138 48 : mpSdrFillBitmapAttribute->mnRefCount++;
139 48 : }
140 :
141 80 : SdrFillBitmapAttribute::~SdrFillBitmapAttribute()
142 : {
143 80 : if(mpSdrFillBitmapAttribute->mnRefCount)
144 : {
145 80 : mpSdrFillBitmapAttribute->mnRefCount--;
146 : }
147 : else
148 : {
149 0 : delete mpSdrFillBitmapAttribute;
150 : }
151 80 : }
152 :
153 23 : bool SdrFillBitmapAttribute::isDefault() const
154 : {
155 23 : return mpSdrFillBitmapAttribute == ImpSdrFillBitmapAttribute::get_global_default();
156 : }
157 :
158 0 : SdrFillBitmapAttribute& SdrFillBitmapAttribute::operator=(const SdrFillBitmapAttribute& rCandidate)
159 : {
160 0 : if(rCandidate.mpSdrFillBitmapAttribute != mpSdrFillBitmapAttribute)
161 : {
162 0 : if(mpSdrFillBitmapAttribute->mnRefCount)
163 : {
164 0 : mpSdrFillBitmapAttribute->mnRefCount--;
165 : }
166 : else
167 : {
168 0 : delete mpSdrFillBitmapAttribute;
169 : }
170 :
171 0 : mpSdrFillBitmapAttribute = rCandidate.mpSdrFillBitmapAttribute;
172 0 : mpSdrFillBitmapAttribute->mnRefCount++;
173 : }
174 :
175 0 : return *this;
176 : }
177 :
178 9 : bool SdrFillBitmapAttribute::operator==(const SdrFillBitmapAttribute& rCandidate) const
179 : {
180 9 : if(rCandidate.mpSdrFillBitmapAttribute == mpSdrFillBitmapAttribute)
181 : {
182 9 : return true;
183 : }
184 :
185 0 : if(rCandidate.isDefault() != isDefault())
186 : {
187 0 : return false;
188 : }
189 :
190 0 : return (*rCandidate.mpSdrFillBitmapAttribute == *mpSdrFillBitmapAttribute);
191 : }
192 :
193 0 : const Bitmap& SdrFillBitmapAttribute::getBitmap() const
194 : {
195 0 : return mpSdrFillBitmapAttribute->getBitmap();
196 : }
197 :
198 0 : const basegfx::B2DVector& SdrFillBitmapAttribute::getSize() const
199 : {
200 0 : return mpSdrFillBitmapAttribute->getSize();
201 : }
202 :
203 0 : const basegfx::B2DVector& SdrFillBitmapAttribute::getOffset() const
204 : {
205 0 : return mpSdrFillBitmapAttribute->getOffset();
206 : }
207 :
208 0 : const basegfx::B2DVector& SdrFillBitmapAttribute::getOffsetPosition() const
209 : {
210 0 : return mpSdrFillBitmapAttribute->getOffsetPosition();
211 : }
212 :
213 0 : const basegfx::B2DVector& SdrFillBitmapAttribute::getRectPoint() const
214 : {
215 0 : return mpSdrFillBitmapAttribute->getRectPoint();
216 : }
217 :
218 0 : bool SdrFillBitmapAttribute::getTiling() const
219 : {
220 0 : return mpSdrFillBitmapAttribute->getTiling();
221 : }
222 :
223 0 : bool SdrFillBitmapAttribute::getStretch() const
224 : {
225 0 : return mpSdrFillBitmapAttribute->getStretch();
226 : }
227 :
228 0 : FillBitmapAttribute SdrFillBitmapAttribute::getFillBitmapAttribute(const basegfx::B2DRange& rRange) const
229 : {
230 : // get logical size of bitmap (before expanding eventually)
231 0 : Bitmap aBitmap(getBitmap());
232 0 : const basegfx::B2DVector aLogicalSize(aBitmap.GetPrefSize().getWidth(), aBitmap.GetPrefSize().getHeight());
233 :
234 : // get hor/ver shiftings and apply them eventually to the bitmap, but only
235 : // when tiling is on
236 0 : bool bExpandWidth(false);
237 0 : bool bExpandHeight(false);
238 :
239 0 : if(getTiling())
240 : {
241 0 : if(0.0 != getOffset().getX() || 0.0 != getOffset().getY())
242 : {
243 0 : const sal_uInt32 nWidth(aBitmap.GetSizePixel().getWidth());
244 0 : const sal_uInt32 nHeight(aBitmap.GetSizePixel().getHeight());
245 :
246 0 : if(0.0 != getOffset().getX())
247 : {
248 0 : bExpandHeight = true;
249 0 : const sal_uInt32 nOffset(basegfx::fround(((double)nWidth * getOffset().getX()) / 100.0));
250 0 : aBitmap.Expand(0L, nHeight);
251 :
252 0 : const Size aSizeA(nOffset, nHeight);
253 0 : const Rectangle aDstA(Point(0L, nHeight), aSizeA);
254 0 : const Rectangle aSrcA(Point(nWidth - nOffset, 0L), aSizeA);
255 0 : aBitmap.CopyPixel(aDstA, aSrcA);
256 :
257 0 : const Size aSizeB(nWidth - nOffset, nHeight);
258 0 : const Rectangle aDstB(Point(nOffset, nHeight), aSizeB);
259 0 : const Rectangle aSrcB(Point(0L, 0L), aSizeB);
260 0 : aBitmap.CopyPixel(aDstB, aSrcB);
261 : }
262 : else
263 : {
264 0 : bExpandWidth = true;
265 0 : const sal_uInt32 nOffset(basegfx::fround(((double)nHeight * getOffset().getY()) / 100.0));
266 0 : aBitmap.Expand(nWidth, 0L);
267 :
268 0 : const Size aSize(nWidth, nHeight);
269 0 : const Rectangle aDst(Point(nWidth, 0L), aSize);
270 0 : const Rectangle aSrc(Point(0L, 0L), aSize);
271 0 : aBitmap.CopyPixel(aDst, aSrc);
272 :
273 0 : const Size aSizeA(nWidth, nOffset);
274 0 : const Rectangle aDstA(Point(0L, 0L), aSizeA);
275 0 : const Rectangle aSrcA(Point(nWidth, nHeight - nOffset), aSizeA);
276 0 : aBitmap.CopyPixel(aDstA, aSrcA);
277 :
278 0 : const Size aSizeB(nWidth, nHeight - nOffset);
279 0 : const Rectangle aDstB(Point(0L, nOffset), aSizeB);
280 0 : const Rectangle aSrcB(Point(nWidth, 0L), aSizeB);
281 0 : aBitmap.CopyPixel(aDstB, aSrcB);
282 : }
283 : }
284 : }
285 :
286 : // init values with defaults
287 0 : basegfx::B2DPoint aBitmapSize(1.0, 1.0);
288 0 : basegfx::B2DVector aBitmapTopLeft(0.0, 0.0);
289 :
290 : // are canges needed?
291 0 : if(getTiling() || !getStretch())
292 : {
293 : // init values with range sizes
294 0 : const double fRangeWidth(0.0 != rRange.getWidth() ? rRange.getWidth() : 1.0);
295 0 : const double fRangeHeight(0.0 != rRange.getHeight() ? rRange.getHeight() : 1.0);
296 0 : aBitmapSize = basegfx::B2DPoint(fRangeWidth, fRangeHeight);
297 :
298 : // size changes
299 0 : if(0.0 != getSize().getX())
300 : {
301 0 : if(getSize().getX() < 0.0)
302 : {
303 0 : aBitmapSize.setX(aBitmapSize.getX() * (getSize().getX() * -0.01));
304 : }
305 : else
306 : {
307 0 : aBitmapSize.setX(getSize().getX());
308 : }
309 : }
310 : else
311 : {
312 0 : aBitmapSize.setX(aLogicalSize.getX());
313 : }
314 :
315 0 : if(0.0 != getSize().getY())
316 : {
317 0 : if(getSize().getY() < 0.0)
318 : {
319 0 : aBitmapSize.setY(aBitmapSize.getY() * (getSize().getY() * -0.01));
320 : }
321 : else
322 : {
323 0 : aBitmapSize.setY(getSize().getY());
324 : }
325 : }
326 : else
327 : {
328 0 : aBitmapSize.setY(aLogicalSize.getY());
329 : }
330 :
331 : // get values, force to centered if necessary
332 0 : const basegfx::B2DVector aRectPoint(getTiling() ? getRectPoint() : basegfx::B2DVector(0.0, 0.0));
333 :
334 : // position changes X
335 0 : if(0.0 == aRectPoint.getX())
336 : {
337 0 : aBitmapTopLeft.setX((fRangeWidth - aBitmapSize.getX()) * 0.5);
338 : }
339 0 : else if(1.0 == aRectPoint.getX())
340 : {
341 0 : aBitmapTopLeft.setX(fRangeWidth - aBitmapSize.getX());
342 : }
343 :
344 0 : if(getTiling() && 0.0 != getOffsetPosition().getX())
345 : {
346 0 : aBitmapTopLeft.setX(aBitmapTopLeft.getX() + (aBitmapSize.getX() * (getOffsetPosition().getX() * 0.01)));
347 : }
348 :
349 : // position changes Y
350 0 : if(0.0 == aRectPoint.getY())
351 : {
352 0 : aBitmapTopLeft.setY((fRangeHeight - aBitmapSize.getY()) * 0.5);
353 : }
354 0 : else if(1.0 == aRectPoint.getY())
355 : {
356 0 : aBitmapTopLeft.setY(fRangeHeight - aBitmapSize.getY());
357 : }
358 :
359 0 : if(getTiling() && 0.0 != getOffsetPosition().getY())
360 : {
361 0 : aBitmapTopLeft.setY(aBitmapTopLeft.getY() + (aBitmapSize.getY() * (getOffsetPosition().getY() * 0.01)));
362 : }
363 :
364 : // apply expand
365 0 : if(bExpandWidth)
366 : {
367 0 : aBitmapSize.setX(aBitmapSize.getX() * 2.0);
368 : }
369 :
370 0 : if(bExpandHeight)
371 : {
372 0 : aBitmapSize.setY(aBitmapSize.getY() * 2.0);
373 : }
374 :
375 : // apply bitmap size scaling to unit rectangle
376 0 : aBitmapTopLeft.setX(aBitmapTopLeft.getX() / fRangeWidth);
377 0 : aBitmapTopLeft.setY(aBitmapTopLeft.getY() / fRangeHeight);
378 0 : aBitmapSize.setX(aBitmapSize.getX() / fRangeWidth);
379 0 : aBitmapSize.setY(aBitmapSize.getY() / fRangeHeight);
380 : }
381 :
382 0 : return FillBitmapAttribute(BitmapEx(aBitmap), aBitmapTopLeft, aBitmapSize, getTiling());
383 : }
384 : } // end of namespace attribute
385 : } // end of namespace drawinglayer
386 :
387 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|