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/primitive2d/cropprimitive2d.hxx>
21 : #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
22 : #include <basegfx/matrix/b2dhommatrix.hxx>
23 : #include <basegfx/matrix/b2dhommatrixtools.hxx>
24 : #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
25 : #include <basegfx/polygon/b2dpolygon.hxx>
26 : #include <basegfx/polygon/b2dpolygontools.hxx>
27 : #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
28 :
29 :
30 :
31 : using namespace com::sun::star;
32 :
33 :
34 :
35 : namespace drawinglayer
36 : {
37 : namespace primitive2d
38 : {
39 3 : CropPrimitive2D::CropPrimitive2D(
40 : const Primitive2DSequence& rChildren,
41 : const basegfx::B2DHomMatrix& rTransformation,
42 : double fCropLeft,
43 : double fCropTop,
44 : double fCropRight,
45 : double fCropBottom)
46 : : GroupPrimitive2D(rChildren),
47 : maTransformation(rTransformation),
48 : mfCropLeft(fCropLeft),
49 : mfCropTop(fCropTop),
50 : mfCropRight(fCropRight),
51 3 : mfCropBottom(fCropBottom)
52 : {
53 3 : }
54 :
55 0 : bool CropPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
56 : {
57 0 : if(GroupPrimitive2D::operator==(rPrimitive))
58 : {
59 0 : const CropPrimitive2D& rCompare = static_cast< const CropPrimitive2D& >(rPrimitive);
60 :
61 0 : return (getTransformation() == rCompare.getTransformation()
62 0 : && getCropLeft() == rCompare.getCropLeft()
63 0 : && getCropTop() == rCompare.getCropTop()
64 0 : && getCropRight() == rCompare.getCropRight()
65 0 : && getCropBottom() == rCompare.getCropBottom());
66 : }
67 :
68 0 : return false;
69 : }
70 :
71 3 : Primitive2DSequence CropPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
72 : {
73 3 : Primitive2DSequence xRetval;
74 :
75 3 : if(getChildren().hasElements())
76 : {
77 : // get original object scale in unit coordinates (no mirroring)
78 3 : const basegfx::B2DVector aObjectScale(basegfx::absolute(getTransformation() * basegfx::B2DVector(1.0, 1.0)));
79 :
80 : // we handle cropping, so when no width or no height, content will be empty,
81 : // so only do something when we have a width and a height
82 3 : if(!aObjectScale.equalZero())
83 : {
84 : // calculate crop distances in unit coordinates. They are already combined with CropScaleFactor, thus
85 : // are relative only to object scale
86 3 : const double fBackScaleX(basegfx::fTools::equalZero(aObjectScale.getX()) ? 1.0 : 1.0 / fabs(aObjectScale.getX()));
87 3 : const double fBackScaleY(basegfx::fTools::equalZero(aObjectScale.getY()) ? 1.0 : 1.0 / fabs(aObjectScale.getY()));
88 3 : const double fLeft(getCropLeft() * fBackScaleX);
89 3 : const double fTop(getCropTop() * fBackScaleY);
90 3 : const double fRight(getCropRight() * fBackScaleX);
91 3 : const double fBottom(getCropBottom() * fBackScaleY);
92 :
93 : // calc new unit range for comparisons; the original range is the unit range
94 3 : const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
95 : const basegfx::B2DRange aNewRange(
96 : -fLeft,
97 : -fTop,
98 : 1.0 + fRight,
99 3 : 1.0 + fBottom);
100 :
101 : // if we have no overlap the crop has removed everything, so we do only
102 : // have to create content if this is not the case
103 3 : if(aNewRange.overlaps(aUnitRange))
104 : {
105 : // create new transform; first take out old transform to get
106 : // to unit coordinates by inverting. Inverting should be flawless
107 : // since we already cheched that object size is not zero in X or Y
108 3 : basegfx::B2DHomMatrix aNewTransform(getTransformation());
109 :
110 3 : aNewTransform.invert();
111 :
112 : // apply crop enlargement in unit coordinates
113 : aNewTransform = basegfx::tools::createScaleTranslateB2DHomMatrix(
114 : aNewRange.getRange(),
115 3 : aNewRange.getMinimum()) * aNewTransform;
116 :
117 : // apply original transformation. Since we have manipulated the crop
118 : // in unit coordinates we do not need to care about mirroring or
119 : // a corrected point for a possible shear or rotation, this all comes for
120 : // free
121 3 : aNewTransform = getTransformation() * aNewTransform;
122 :
123 : // prepare TransformPrimitive2D with xPrimitive
124 : const Primitive2DReference xTransformPrimitive(
125 : new TransformPrimitive2D(
126 : aNewTransform,
127 6 : getChildren()));
128 :
129 3 : if(aUnitRange.isInside(aNewRange))
130 : {
131 : // the new range is completely inside the old range (unit range),
132 : // so no masking is needed
133 1 : xRetval = Primitive2DSequence(&xTransformPrimitive, 1);
134 : }
135 : else
136 : {
137 : // mask with original object's bounds
138 2 : basegfx::B2DPolyPolygon aMaskPolyPolygon(basegfx::tools::createUnitPolygon());
139 2 : aMaskPolyPolygon.transform(getTransformation());
140 :
141 : // create maskPrimitive with aMaskPolyPolygon and aMaskContentVector
142 : const Primitive2DReference xMask(
143 : new MaskPrimitive2D(
144 : aMaskPolyPolygon,
145 4 : Primitive2DSequence(&xTransformPrimitive, 1)));
146 :
147 4 : xRetval = Primitive2DSequence(&xMask, 1);
148 3 : }
149 : }
150 3 : }
151 : }
152 :
153 3 : return xRetval;
154 : }
155 :
156 : // provide unique ID
157 3 : ImplPrimitive2DIDBlock(CropPrimitive2D, PRIMITIVE2D_ID_CROPPRIMITIVE2D)
158 :
159 : } // end of namespace primitive2d
160 : } // end of namespace drawinglayer
161 :
162 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|