/src/libreoffice/drawinglayer/source/attribute/sdrfillgraphicattribute.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 <sal/config.h> |
21 | | |
22 | | #include <algorithm> |
23 | | |
24 | | #include <basegfx/point/b2dpoint.hxx> |
25 | | #include <basegfx/range/b2drange.hxx> |
26 | | #include <basegfx/vector/b2dvector.hxx> |
27 | | #include <drawinglayer/attribute/sdrfillgraphicattribute.hxx> |
28 | | #include <drawinglayer/attribute/fillgraphicattribute.hxx> |
29 | | #include <utility> |
30 | | #include <vcl/graph.hxx> |
31 | | |
32 | | |
33 | | namespace drawinglayer::attribute |
34 | | { |
35 | | class ImpSdrFillGraphicAttribute |
36 | | { |
37 | | public: |
38 | | // data definitions |
39 | | Graphic maFillGraphic; |
40 | | basegfx::B2DVector maGraphicLogicSize; |
41 | | basegfx::B2DVector maSize; |
42 | | basegfx::B2DVector maOffset; |
43 | | basegfx::B2DVector maOffsetPosition; |
44 | | basegfx::B2DVector maRectPoint; |
45 | | |
46 | | bool mbTiling : 1; |
47 | | bool mbStretch : 1; |
48 | | bool mbLogSize : 1; |
49 | | |
50 | | ImpSdrFillGraphicAttribute( |
51 | | Graphic aFillGraphic, |
52 | | const basegfx::B2DVector& rGraphicLogicSize, |
53 | | const basegfx::B2DVector& rSize, |
54 | | const basegfx::B2DVector& rOffset, |
55 | | const basegfx::B2DVector& rOffsetPosition, |
56 | | const basegfx::B2DVector& rRectPoint, |
57 | | bool bTiling, |
58 | | bool bStretch, |
59 | | bool bLogSize) |
60 | 0 | : maFillGraphic(std::move(aFillGraphic)), |
61 | 0 | maGraphicLogicSize(rGraphicLogicSize), |
62 | 0 | maSize(rSize), |
63 | 0 | maOffset(rOffset), |
64 | 0 | maOffsetPosition(rOffsetPosition), |
65 | 0 | maRectPoint(rRectPoint), |
66 | 0 | mbTiling(bTiling), |
67 | 0 | mbStretch(bStretch), |
68 | 0 | mbLogSize(bLogSize) |
69 | 0 | { |
70 | 0 | } |
71 | | |
72 | | ImpSdrFillGraphicAttribute() |
73 | 7 | : mbTiling(false), |
74 | 7 | mbStretch(false), |
75 | 7 | mbLogSize(false) |
76 | 7 | { |
77 | 7 | } |
78 | | |
79 | | // data read access |
80 | 138 | const Graphic& getFillGraphic() const { return maFillGraphic; } |
81 | 0 | const basegfx::B2DVector& getGraphicLogicSize() const { return maGraphicLogicSize; } |
82 | 0 | const basegfx::B2DVector& getSize() const { return maSize; } |
83 | 0 | const basegfx::B2DVector& getOffset() const { return maOffset; } |
84 | 0 | const basegfx::B2DVector& getOffsetPosition() const { return maOffsetPosition; } |
85 | 0 | const basegfx::B2DVector& getRectPoint() const { return maRectPoint; } |
86 | 0 | bool getTiling() const { return mbTiling; } |
87 | 0 | bool getStretch() const { return mbStretch; } |
88 | | |
89 | | bool operator==(const ImpSdrFillGraphicAttribute& rCandidate) const |
90 | 0 | { |
91 | 0 | return (getFillGraphic() == rCandidate.getFillGraphic() |
92 | 0 | && getGraphicLogicSize() == rCandidate.getGraphicLogicSize() |
93 | 0 | && getSize() == rCandidate.getSize() |
94 | 0 | && getOffset() == rCandidate.getOffset() |
95 | 0 | && getOffsetPosition() == rCandidate.getOffsetPosition() |
96 | 0 | && getRectPoint() == rCandidate.getRectPoint() |
97 | 0 | && getTiling() == rCandidate.getTiling() |
98 | 0 | && getStretch() == rCandidate.getStretch() |
99 | 0 | && mbLogSize == rCandidate.mbLogSize); |
100 | 0 | } |
101 | | }; |
102 | | |
103 | | namespace |
104 | | { |
105 | | SdrFillGraphicAttribute::ImplType& theGlobalDefault() |
106 | 4.72k | { |
107 | 4.72k | static SdrFillGraphicAttribute::ImplType SINGLETON; |
108 | 4.72k | return SINGLETON; |
109 | 4.72k | } |
110 | | } |
111 | | |
112 | | SdrFillGraphicAttribute::SdrFillGraphicAttribute( |
113 | | const Graphic& rFillGraphic, |
114 | | const basegfx::B2DVector& rGraphicLogicSize, |
115 | | const basegfx::B2DVector& rSize, |
116 | | const basegfx::B2DVector& rOffset, |
117 | | const basegfx::B2DVector& rOffsetPosition, |
118 | | const basegfx::B2DVector& rRectPoint, |
119 | | bool bTiling, |
120 | | bool bStretch, |
121 | | bool bLogSize) |
122 | 0 | : mpSdrFillGraphicAttribute( |
123 | 0 | ImpSdrFillGraphicAttribute( |
124 | 0 | rFillGraphic, |
125 | 0 | rGraphicLogicSize, |
126 | 0 | rSize, |
127 | 0 | rOffset, |
128 | 0 | rOffsetPosition, |
129 | 0 | rRectPoint, |
130 | 0 | bTiling, |
131 | 0 | bStretch, |
132 | 0 | bLogSize)) |
133 | 0 | { |
134 | 0 | } |
135 | | |
136 | | SdrFillGraphicAttribute::SdrFillGraphicAttribute() |
137 | 1.58k | : mpSdrFillGraphicAttribute(theGlobalDefault()) |
138 | 1.58k | { |
139 | 1.58k | } |
140 | | |
141 | 1.57k | SdrFillGraphicAttribute::SdrFillGraphicAttribute(const SdrFillGraphicAttribute&) = default; |
142 | | |
143 | 3.15k | SdrFillGraphicAttribute::SdrFillGraphicAttribute(SdrFillGraphicAttribute&&) = default; |
144 | | |
145 | 6.30k | SdrFillGraphicAttribute::~SdrFillGraphicAttribute() = default; |
146 | | |
147 | | bool SdrFillGraphicAttribute::isDefault() const |
148 | 3.14k | { |
149 | 3.14k | return mpSdrFillGraphicAttribute.same_object(theGlobalDefault()); |
150 | 3.14k | } |
151 | | |
152 | 0 | SdrFillGraphicAttribute& SdrFillGraphicAttribute::operator=(const SdrFillGraphicAttribute&) = default; |
153 | | |
154 | 0 | SdrFillGraphicAttribute& SdrFillGraphicAttribute::operator=(SdrFillGraphicAttribute&&) = default; |
155 | | |
156 | | bool SdrFillGraphicAttribute::operator==(const SdrFillGraphicAttribute& rCandidate) const |
157 | 390 | { |
158 | | // tdf#87509 default attr is always != non-default attr, even with same values |
159 | 390 | if(rCandidate.isDefault() != isDefault()) |
160 | 0 | return false; |
161 | | |
162 | 390 | return rCandidate.mpSdrFillGraphicAttribute == mpSdrFillGraphicAttribute; |
163 | 390 | } |
164 | | |
165 | | const Graphic& SdrFillGraphicAttribute::getFillGraphic() const |
166 | 138 | { |
167 | 138 | return mpSdrFillGraphicAttribute->getFillGraphic(); |
168 | 138 | } |
169 | | |
170 | | const basegfx::B2DVector& SdrFillGraphicAttribute::getGraphicLogicSize() const |
171 | 0 | { |
172 | 0 | return mpSdrFillGraphicAttribute->getGraphicLogicSize(); |
173 | 0 | } |
174 | | |
175 | | const basegfx::B2DVector& SdrFillGraphicAttribute::getSize() const |
176 | 0 | { |
177 | 0 | return mpSdrFillGraphicAttribute->getSize(); |
178 | 0 | } |
179 | | |
180 | | const basegfx::B2DVector& SdrFillGraphicAttribute::getOffset() const |
181 | 0 | { |
182 | 0 | return mpSdrFillGraphicAttribute->getOffset(); |
183 | 0 | } |
184 | | |
185 | | const basegfx::B2DVector& SdrFillGraphicAttribute::getOffsetPosition() const |
186 | 0 | { |
187 | 0 | return mpSdrFillGraphicAttribute->getOffsetPosition(); |
188 | 0 | } |
189 | | |
190 | | const basegfx::B2DVector& SdrFillGraphicAttribute::getRectPoint() const |
191 | 0 | { |
192 | 0 | return mpSdrFillGraphicAttribute->getRectPoint(); |
193 | 0 | } |
194 | | |
195 | | bool SdrFillGraphicAttribute::getTiling() const |
196 | 0 | { |
197 | 0 | return mpSdrFillGraphicAttribute->getTiling(); |
198 | 0 | } |
199 | | |
200 | | FillGraphicAttribute SdrFillGraphicAttribute::createFillGraphicAttribute(const basegfx::B2DRange& rRange) const |
201 | 0 | { |
202 | | // get logical size of bitmap (before possibly expanding it) |
203 | 0 | Graphic aGraphic(getFillGraphic()); |
204 | | |
205 | | // init values with defaults for stretched |
206 | 0 | basegfx::B2DPoint aBitmapSize(1.0, 1.0); |
207 | 0 | basegfx::B2DVector aBitmapTopLeft(0.0, 0.0); |
208 | | |
209 | | // are changes needed? When stretched we are already done, all other values will have no influence |
210 | 0 | if(getTiling() || !mpSdrFillGraphicAttribute->getStretch()) |
211 | 0 | { |
212 | | // init values with range sizes |
213 | 0 | const double fRangeWidth(0.0 != rRange.getWidth() ? rRange.getWidth() : 1.0); |
214 | 0 | const double fRangeHeight(0.0 != rRange.getHeight() ? rRange.getHeight() : 1.0); |
215 | 0 | aBitmapSize = basegfx::B2DPoint(fRangeWidth, fRangeHeight); |
216 | | |
217 | | // size changes |
218 | 0 | if(0.0 != getSize().getX()) |
219 | 0 | { |
220 | 0 | if(getSize().getX() < 0.0) |
221 | 0 | { |
222 | 0 | aBitmapSize.setX(aBitmapSize.getX() * (getSize().getX() * -0.01)); |
223 | 0 | } |
224 | 0 | else |
225 | 0 | { |
226 | 0 | aBitmapSize.setX(getSize().getX()); |
227 | 0 | } |
228 | 0 | } |
229 | 0 | else |
230 | 0 | { |
231 | | // #i124002# use GraphicLogicSize directly, do not try to use GetPrefSize |
232 | | // of the graphic, that may not be adapted to the MapMode of the target |
233 | 0 | aBitmapSize.setX(getGraphicLogicSize().getX()); |
234 | 0 | } |
235 | |
|
236 | 0 | if(0.0 != getSize().getY()) |
237 | 0 | { |
238 | 0 | if(getSize().getY() < 0.0) |
239 | 0 | { |
240 | 0 | aBitmapSize.setY(aBitmapSize.getY() * (getSize().getY() * -0.01)); |
241 | 0 | } |
242 | 0 | else |
243 | 0 | { |
244 | 0 | aBitmapSize.setY(getSize().getY()); |
245 | 0 | } |
246 | 0 | } |
247 | 0 | else |
248 | 0 | { |
249 | | // #i124002# use GraphicLogicSize directly, do not try to use GetPrefSize |
250 | | // of the graphic, that may not be adapted to the MapMode of the target |
251 | 0 | aBitmapSize.setY(getGraphicLogicSize().getY()); |
252 | 0 | } |
253 | | |
254 | | // position changes X |
255 | 0 | if(0.0 == getRectPoint().getX()) |
256 | 0 | { |
257 | 0 | aBitmapTopLeft.setX((fRangeWidth - aBitmapSize.getX()) * 0.5); |
258 | 0 | } |
259 | 0 | else if(1.0 == getRectPoint().getX()) |
260 | 0 | { |
261 | 0 | aBitmapTopLeft.setX(fRangeWidth - aBitmapSize.getX()); |
262 | 0 | } |
263 | | |
264 | | // offset positions are only meaningful when tiled |
265 | 0 | if(getTiling() && 0.0 != getOffsetPosition().getX()) |
266 | 0 | { |
267 | 0 | aBitmapTopLeft.setX(aBitmapTopLeft.getX() + (aBitmapSize.getX() * (getOffsetPosition().getX() * 0.01))); |
268 | 0 | } |
269 | | |
270 | | // position changes Y |
271 | 0 | if(0.0 == getRectPoint().getY()) |
272 | 0 | { |
273 | 0 | aBitmapTopLeft.setY((fRangeHeight - aBitmapSize.getY()) * 0.5); |
274 | 0 | } |
275 | 0 | else if(1.0 == getRectPoint().getY()) |
276 | 0 | { |
277 | 0 | aBitmapTopLeft.setY(fRangeHeight - aBitmapSize.getY()); |
278 | 0 | } |
279 | | |
280 | | // offset positions are only meaningful when tiled |
281 | 0 | if(getTiling() && 0.0 != getOffsetPosition().getY()) |
282 | 0 | { |
283 | 0 | aBitmapTopLeft.setY(aBitmapTopLeft.getY() + (aBitmapSize.getY() * (getOffsetPosition().getY() * 0.01))); |
284 | 0 | } |
285 | | |
286 | | // apply bitmap size scaling to unit rectangle |
287 | 0 | aBitmapTopLeft.setX(aBitmapTopLeft.getX() / fRangeWidth); |
288 | 0 | aBitmapTopLeft.setY(aBitmapTopLeft.getY() / fRangeHeight); |
289 | 0 | aBitmapSize.setX(aBitmapSize.getX() / fRangeWidth); |
290 | 0 | aBitmapSize.setY(aBitmapSize.getY() / fRangeHeight); |
291 | 0 | } |
292 | | |
293 | | // get offset in percent |
294 | 0 | const double fOffsetX(std::clamp(getOffset().getX() * 0.01, 0.0, 1.0)); |
295 | 0 | const double fOffsetY(std::clamp(getOffset().getY() * 0.01, 0.0, 1.0)); |
296 | | |
297 | | // create FillGraphicAttribute |
298 | 0 | return FillGraphicAttribute( |
299 | 0 | aGraphic, |
300 | 0 | basegfx::B2DRange(aBitmapTopLeft, aBitmapTopLeft + aBitmapSize), |
301 | 0 | getTiling(), |
302 | 0 | fOffsetX, |
303 | 0 | fOffsetY); |
304 | 0 | } |
305 | | |
306 | | } // end of namespace |
307 | | |
308 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |