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/primitive2d/discreteshadowprimitive2d.hxx>
21 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
22 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
23 #include <basegfx/matrix/b2dhommatrixtools.hxx>
24 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
25 #include <drawinglayer/geometry/viewinformation2d.hxx>
26 
27 
28 namespace drawinglayer
29 {
30     namespace primitive2d
31     {
DiscreteShadow(const BitmapEx & rBitmapEx)32         DiscreteShadow::DiscreteShadow(const BitmapEx& rBitmapEx)
33         :   maBitmapEx(rBitmapEx),
34             maTopLeft(),
35             maTop(),
36             maTopRight(),
37             maRight(),
38             maBottomRight(),
39             maBottom(),
40             maBottomLeft(),
41             maLeft()
42         {
43             const Size& rBitmapSize = getBitmapEx().GetSizePixel();
44 
45             if(rBitmapSize.Width() != rBitmapSize.Height() || rBitmapSize.Width() < 7)
46             {
47                 OSL_ENSURE(false, "DiscreteShadowPrimitive2D: wrong bitmap format (!)");
48                 maBitmapEx = BitmapEx();
49             }
50         }
51 
getTopLeft() const52         const BitmapEx& DiscreteShadow::getTopLeft() const
53         {
54             if(maTopLeft.IsEmpty())
55             {
56                 const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
57                 const_cast< DiscreteShadow* >(this)->maTopLeft = getBitmapEx();
58                 const_cast< DiscreteShadow* >(this)->maTopLeft.Crop(
59                     ::tools::Rectangle(Point(0, 0), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
60             }
61 
62             return maTopLeft;
63         }
64 
getTop() const65         const BitmapEx& DiscreteShadow::getTop() const
66         {
67             if(maTop.IsEmpty())
68             {
69                 const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
70                 const_cast< DiscreteShadow* >(this)->maTop = getBitmapEx();
71                 const_cast< DiscreteShadow* >(this)->maTop.Crop(
72                     ::tools::Rectangle(Point((nQuarter * 2) + 1, 0), Size(1, nQuarter)));
73             }
74 
75             return maTop;
76         }
77 
getTopRight() const78         const BitmapEx& DiscreteShadow::getTopRight() const
79         {
80             if(maTopRight.IsEmpty())
81             {
82                 const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
83                 const_cast< DiscreteShadow* >(this)->maTopRight = getBitmapEx();
84                 const_cast< DiscreteShadow* >(this)->maTopRight.Crop(
85                     ::tools::Rectangle(Point((nQuarter * 2) + 2, 0), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
86             }
87 
88             return maTopRight;
89         }
90 
getRight() const91         const BitmapEx& DiscreteShadow::getRight() const
92         {
93             if(maRight.IsEmpty())
94             {
95                 const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
96                 const_cast< DiscreteShadow* >(this)->maRight = getBitmapEx();
97                 const_cast< DiscreteShadow* >(this)->maRight.Crop(
98                     ::tools::Rectangle(Point((nQuarter * 3) + 3, (nQuarter * 2) + 1), Size(nQuarter, 1)));
99             }
100 
101             return maRight;
102         }
103 
getBottomRight() const104         const BitmapEx& DiscreteShadow::getBottomRight() const
105         {
106             if(maBottomRight.IsEmpty())
107             {
108                 const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
109                 const_cast< DiscreteShadow* >(this)->maBottomRight = getBitmapEx();
110                 const_cast< DiscreteShadow* >(this)->maBottomRight.Crop(
111                     ::tools::Rectangle(Point((nQuarter * 2) + 2, (nQuarter * 2) + 2), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
112             }
113 
114             return maBottomRight;
115         }
116 
getBottom() const117         const BitmapEx& DiscreteShadow::getBottom() const
118         {
119             if(maBottom.IsEmpty())
120             {
121                 const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
122                 const_cast< DiscreteShadow* >(this)->maBottom = getBitmapEx();
123                 const_cast< DiscreteShadow* >(this)->maBottom.Crop(
124                     ::tools::Rectangle(Point((nQuarter * 2) + 1, (nQuarter * 3) + 3), Size(1, nQuarter)));
125             }
126 
127             return maBottom;
128         }
129 
getBottomLeft() const130         const BitmapEx& DiscreteShadow::getBottomLeft() const
131         {
132             if(maBottomLeft.IsEmpty())
133             {
134                 const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
135                 const_cast< DiscreteShadow* >(this)->maBottomLeft = getBitmapEx();
136                 const_cast< DiscreteShadow* >(this)->maBottomLeft.Crop(
137                     ::tools::Rectangle(Point(0, (nQuarter * 2) + 2), Size((nQuarter * 2) + 1, (nQuarter * 2) + 1)));
138             }
139 
140             return maBottomLeft;
141         }
142 
getLeft() const143         const BitmapEx& DiscreteShadow::getLeft() const
144         {
145             if(maLeft.IsEmpty())
146             {
147                 const sal_Int32 nQuarter((getBitmapEx().GetSizePixel().Width() - 3) >> 2);
148                 const_cast< DiscreteShadow* >(this)->maLeft = getBitmapEx();
149                 const_cast< DiscreteShadow* >(this)->maLeft.Crop(
150                     ::tools::Rectangle(Point(0, (nQuarter * 2) + 1), Size(nQuarter, 1)));
151             }
152 
153             return maLeft;
154         }
155 
156     } // end of namespace primitive2d
157 } // end of namespace drawinglayer
158 
159 
160 namespace drawinglayer
161 {
162     namespace primitive2d
163     {
create2DDecomposition(Primitive2DContainer & rContainer,const geometry::ViewInformation2D &) const164         void DiscreteShadowPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
165         {
166             Primitive2DContainer xRetval;
167 
168             if(!getDiscreteShadow().getBitmapEx().IsEmpty())
169             {
170                 const sal_Int32 nQuarter((getDiscreteShadow().getBitmapEx().GetSizePixel().Width() - 3) >> 2);
171                 const basegfx::B2DVector aScale(getTransform() * basegfx::B2DVector(1.0, 1.0));
172                 const double fSingleX(getDiscreteUnit() / aScale.getX());
173                 const double fSingleY(getDiscreteUnit() / aScale.getY());
174                 const double fBorderX(fSingleX * nQuarter);
175                 const double fBorderY(fSingleY * nQuarter);
176                 const double fBigLenX((fBorderX * 2.0) + fSingleX);
177                 const double fBigLenY((fBorderY * 2.0) + fSingleY);
178 
179                 xRetval.resize(8);
180 
181                 // TopLeft
182                 xRetval[0] = Primitive2DReference(
183                     new BitmapPrimitive2D(
184                         getDiscreteShadow().getTopLeft(),
185                         basegfx::utils::createScaleTranslateB2DHomMatrix(
186                             fBigLenX,
187                             fBigLenY,
188                             -fBorderX,
189                             -fBorderY)));
190 
191                 // Top
192                 xRetval[1] = Primitive2DReference(
193                     new BitmapPrimitive2D(
194                         getDiscreteShadow().getTop(),
195                         basegfx::utils::createScaleTranslateB2DHomMatrix(
196                             1.0 - (2.0 * (fBorderX + fSingleX)) + fSingleX,
197                             fBorderY,
198                             fBorderX + fSingleX,
199                             -fBorderY)));
200 
201                 // TopRight
202                 xRetval[2] = Primitive2DReference(
203                     new BitmapPrimitive2D(
204                         getDiscreteShadow().getTopRight(),
205                         basegfx::utils::createScaleTranslateB2DHomMatrix(
206                             fBigLenX,
207                             fBigLenY,
208                             1.0 - fBorderX,
209                             -fBorderY)));
210 
211                 // Right
212                 xRetval[3] = Primitive2DReference(
213                     new BitmapPrimitive2D(
214                         getDiscreteShadow().getRight(),
215                         basegfx::utils::createScaleTranslateB2DHomMatrix(
216                             fBorderX,
217                             1.0 - (2.0 * (fBorderY + fSingleY)) + fSingleY,
218                             1.0 + fSingleX,
219                             fBorderY + fSingleY)));
220 
221                 // BottomRight
222                 xRetval[4] = Primitive2DReference(
223                     new BitmapPrimitive2D(
224                         getDiscreteShadow().getBottomRight(),
225                         basegfx::utils::createScaleTranslateB2DHomMatrix(
226                             fBigLenX,
227                             fBigLenY,
228                             1.0 - (fBorderX + fSingleX) + fSingleX,
229                             1.0 - (fBorderY + fSingleY) + fSingleY)));
230 
231                 // Bottom
232                 xRetval[5] = Primitive2DReference(
233                     new BitmapPrimitive2D(
234                         getDiscreteShadow().getBottom(),
235                         basegfx::utils::createScaleTranslateB2DHomMatrix(
236                             1.0 - (2.0 * (fBorderX + fSingleX)) + fSingleX,
237                             fBorderY,
238                             fBorderX + fSingleX,
239                             1.0 + fSingleY)));
240 
241                 // BottomLeft
242                 xRetval[6] = Primitive2DReference(
243                     new BitmapPrimitive2D(
244                         getDiscreteShadow().getBottomLeft(),
245                         basegfx::utils::createScaleTranslateB2DHomMatrix(
246                             fBigLenX,
247                             fBigLenY,
248                             -fBorderX,
249                             1.0 - fBorderY)));
250 
251                 // Left
252                 xRetval[7] = Primitive2DReference(
253                     new BitmapPrimitive2D(
254                         getDiscreteShadow().getLeft(),
255                         basegfx::utils::createScaleTranslateB2DHomMatrix(
256                             fBorderX,
257                             1.0 - (2.0 * (fBorderY + fSingleY)) + fSingleY,
258                             -fBorderX,
259                             fBorderY + fSingleY)));
260 
261                 // put all in object transformation to get to target positions
262                 rContainer.push_back(
263                     new TransformPrimitive2D(
264                         getTransform(),
265                         xRetval));
266             }
267         }
268 
DiscreteShadowPrimitive2D(const basegfx::B2DHomMatrix & rTransform,const DiscreteShadow & rDiscreteShadow)269         DiscreteShadowPrimitive2D::DiscreteShadowPrimitive2D(
270             const basegfx::B2DHomMatrix& rTransform,
271             const DiscreteShadow& rDiscreteShadow)
272         :   DiscreteMetricDependentPrimitive2D(),
273             maTransform(rTransform),
274             maDiscreteShadow(rDiscreteShadow)
275         {
276         }
277 
operator ==(const BasePrimitive2D & rPrimitive) const278         bool DiscreteShadowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
279         {
280             if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
281             {
282                 const DiscreteShadowPrimitive2D& rCompare = static_cast<const DiscreteShadowPrimitive2D&>(rPrimitive);
283 
284                 return (getTransform() == rCompare.getTransform()
285                     && getDiscreteShadow() == rCompare.getDiscreteShadow());
286             }
287 
288             return false;
289         }
290 
getB2DRange(const geometry::ViewInformation2D & rViewInformation) const291         basegfx::B2DRange DiscreteShadowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
292         {
293             if(getDiscreteShadow().getBitmapEx().IsEmpty())
294             {
295                 // no graphics without valid bitmap definition
296                 return basegfx::B2DRange();
297             }
298             else
299             {
300                 // prepare normal objectrange
301                 basegfx::B2DRange aRetval(0.0, 0.0, 1.0, 1.0);
302                 aRetval.transform(getTransform());
303 
304                 // extract discrete shadow size and grow
305                 const basegfx::B2DVector aScale(rViewInformation.getViewTransformation() * basegfx::B2DVector(1.0, 1.0));
306                 const sal_Int32 nQuarter((getDiscreteShadow().getBitmapEx().GetSizePixel().Width() - 3) >> 2);
307                 const double fGrowX((1.0 / aScale.getX()) * nQuarter);
308                 const double fGrowY((1.0 / aScale.getY()) * nQuarter);
309                 aRetval.grow(std::max(fGrowX, fGrowY));
310 
311                 return aRetval;
312             }
313         }
314 
315         // provide unique ID
316         ImplPrimitive2DIDBlock(DiscreteShadowPrimitive2D, PRIMITIVE2D_ID_DISCRETESHADOWPRIMITIVE2D)
317 
318     } // end of namespace primitive2d
319 } // end of namespace drawinglayer
320 
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
322