1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "SVGViewBoxSMILType.h"
8 #include "nsSMILValue.h"
9 #include "nsSVGViewBox.h"
10 #include "nsDebug.h"
11 #include <math.h>
12
13 namespace mozilla {
14
15 /*static*/ SVGViewBoxSMILType SVGViewBoxSMILType::sSingleton;
16
Init(nsSMILValue & aValue) const17 void SVGViewBoxSMILType::Init(nsSMILValue& aValue) const {
18 MOZ_ASSERT(aValue.IsNull(), "Unexpected value type");
19
20 aValue.mU.mPtr = new nsSVGViewBoxRect();
21 aValue.mType = this;
22 }
23
Destroy(nsSMILValue & aValue) const24 void SVGViewBoxSMILType::Destroy(nsSMILValue& aValue) const {
25 NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
26 delete static_cast<nsSVGViewBoxRect*>(aValue.mU.mPtr);
27 aValue.mU.mPtr = nullptr;
28 aValue.mType = nsSMILNullType::Singleton();
29 }
30
Assign(nsSMILValue & aDest,const nsSMILValue & aSrc) const31 nsresult SVGViewBoxSMILType::Assign(nsSMILValue& aDest,
32 const nsSMILValue& aSrc) const {
33 NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types");
34 NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value");
35
36 const nsSVGViewBoxRect* src =
37 static_cast<const nsSVGViewBoxRect*>(aSrc.mU.mPtr);
38 nsSVGViewBoxRect* dst = static_cast<nsSVGViewBoxRect*>(aDest.mU.mPtr);
39 *dst = *src;
40 return NS_OK;
41 }
42
IsEqual(const nsSMILValue & aLeft,const nsSMILValue & aRight) const43 bool SVGViewBoxSMILType::IsEqual(const nsSMILValue& aLeft,
44 const nsSMILValue& aRight) const {
45 NS_PRECONDITION(aLeft.mType == aRight.mType, "Incompatible SMIL types");
46 NS_PRECONDITION(aLeft.mType == this, "Unexpected type for SMIL value");
47
48 const nsSVGViewBoxRect* leftBox =
49 static_cast<const nsSVGViewBoxRect*>(aLeft.mU.mPtr);
50 const nsSVGViewBoxRect* rightBox =
51 static_cast<nsSVGViewBoxRect*>(aRight.mU.mPtr);
52 return *leftBox == *rightBox;
53 }
54
Add(nsSMILValue & aDest,const nsSMILValue & aValueToAdd,uint32_t aCount) const55 nsresult SVGViewBoxSMILType::Add(nsSMILValue& aDest,
56 const nsSMILValue& aValueToAdd,
57 uint32_t aCount) const {
58 NS_PRECONDITION(aValueToAdd.mType == aDest.mType,
59 "Trying to add invalid types");
60 NS_PRECONDITION(aValueToAdd.mType == this, "Unexpected source type");
61
62 // See https://bugzilla.mozilla.org/show_bug.cgi?id=541884#c3 and the two
63 // comments that follow that one for arguments for and against allowing
64 // viewBox to be additive.
65
66 return NS_ERROR_FAILURE;
67 }
68
ComputeDistance(const nsSMILValue & aFrom,const nsSMILValue & aTo,double & aDistance) const69 nsresult SVGViewBoxSMILType::ComputeDistance(const nsSMILValue& aFrom,
70 const nsSMILValue& aTo,
71 double& aDistance) const {
72 NS_PRECONDITION(aFrom.mType == aTo.mType,
73 "Trying to compare different types");
74 NS_PRECONDITION(aFrom.mType == this, "Unexpected source type");
75
76 const nsSVGViewBoxRect* from =
77 static_cast<const nsSVGViewBoxRect*>(aFrom.mU.mPtr);
78 const nsSVGViewBoxRect* to =
79 static_cast<const nsSVGViewBoxRect*>(aTo.mU.mPtr);
80
81 if (from->none || to->none) {
82 return NS_ERROR_FAILURE;
83 }
84
85 // We use the distances between the edges rather than the difference between
86 // the x, y, width and height for the "distance". This is necessary in
87 // order for the "distance" result that we calculate to be the same for a
88 // given change in the left side as it is for an equal change in the opposite
89 // side. See https://bugzilla.mozilla.org/show_bug.cgi?id=541884#c12
90
91 float dLeft = to->x - from->x;
92 float dTop = to->y - from->y;
93 float dRight = (to->x + to->width) - (from->x + from->width);
94 float dBottom = (to->y + to->height) - (from->y + from->height);
95
96 aDistance =
97 sqrt(dLeft * dLeft + dTop * dTop + dRight * dRight + dBottom * dBottom);
98
99 return NS_OK;
100 }
101
Interpolate(const nsSMILValue & aStartVal,const nsSMILValue & aEndVal,double aUnitDistance,nsSMILValue & aResult) const102 nsresult SVGViewBoxSMILType::Interpolate(const nsSMILValue& aStartVal,
103 const nsSMILValue& aEndVal,
104 double aUnitDistance,
105 nsSMILValue& aResult) const {
106 NS_PRECONDITION(aStartVal.mType == aEndVal.mType,
107 "Trying to interpolate different types");
108 NS_PRECONDITION(aStartVal.mType == this,
109 "Unexpected types for interpolation");
110 NS_PRECONDITION(aResult.mType == this, "Unexpected result type");
111
112 const nsSVGViewBoxRect* start =
113 static_cast<const nsSVGViewBoxRect*>(aStartVal.mU.mPtr);
114 const nsSVGViewBoxRect* end =
115 static_cast<const nsSVGViewBoxRect*>(aEndVal.mU.mPtr);
116
117 if (start->none || end->none) {
118 return NS_ERROR_FAILURE;
119 }
120
121 nsSVGViewBoxRect* current = static_cast<nsSVGViewBoxRect*>(aResult.mU.mPtr);
122
123 float x = (start->x + (end->x - start->x) * aUnitDistance);
124 float y = (start->y + (end->y - start->y) * aUnitDistance);
125 float width = (start->width + (end->width - start->width) * aUnitDistance);
126 float height =
127 (start->height + (end->height - start->height) * aUnitDistance);
128
129 *current = nsSVGViewBoxRect(x, y, width, height);
130
131 return NS_OK;
132 }
133
134 } // namespace mozilla
135