1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is the Mozilla SVG project.
16 : *
17 : * The Initial Developer of the Original Code is IBM Corporation.
18 : * Portions created by the Initial Developer are Copyright (C) 2005
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either of the GNU General Public License Version 2 or later (the "GPL"),
25 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 : * in which case the provisions of the GPL or the LGPL are applicable instead
27 : * of those above. If you wish to allow use of your version of this file only
28 : * under the terms of either the GPL or the LGPL, and not to allow others to
29 : * use your version of this file under the terms of the MPL, indicate your
30 : * decision by deleting the provisions above and replace them with the notice
31 : * and other provisions required by the GPL or the LGPL. If you do not delete
32 : * the provisions above, a recipient may use your version of this file under
33 : * the terms of any one of the MPL, the GPL or the LGPL.
34 : *
35 : * ***** END LICENSE BLOCK ***** */
36 :
37 : #include "nsSVGTextPathFrame.h"
38 : #include "nsIDOMSVGTextPathElement.h"
39 : #include "nsSVGLength2.h"
40 : #include "nsIDOMSVGURIReference.h"
41 : #include "nsSVGEffects.h"
42 : #include "nsContentUtils.h"
43 : #include "nsSVGPathElement.h"
44 : #include "nsSVGTextPathElement.h"
45 :
46 : using namespace mozilla;
47 :
48 : //----------------------------------------------------------------------
49 : // Implementation
50 :
51 : nsIFrame*
52 0 : NS_NewSVGTextPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
53 : {
54 0 : return new (aPresShell) nsSVGTextPathFrame(aContext);
55 : }
56 :
57 0 : NS_IMPL_FRAMEARENA_HELPERS(nsSVGTextPathFrame)
58 :
59 : #ifdef DEBUG
60 : NS_IMETHODIMP
61 0 : nsSVGTextPathFrame::Init(nsIContent* aContent,
62 : nsIFrame* aParent,
63 : nsIFrame* aPrevInFlow)
64 : {
65 0 : NS_ASSERTION(aParent, "null parent");
66 :
67 0 : nsIFrame* ancestorFrame = nsSVGUtils::GetFirstNonAAncestorFrame(aParent);
68 0 : NS_ASSERTION(ancestorFrame, "Must have ancestor");
69 :
70 0 : NS_ASSERTION(ancestorFrame->GetType() == nsGkAtoms::svgTextFrame,
71 : "trying to construct an SVGTextPathFrame for an invalid "
72 : "container");
73 :
74 0 : nsCOMPtr<nsIDOMSVGTextPathElement> textPath = do_QueryInterface(aContent);
75 0 : NS_ASSERTION(textPath, "Content is not an SVG textPath");
76 :
77 :
78 0 : return nsSVGTextPathFrameBase::Init(aContent, aParent, aPrevInFlow);
79 : }
80 : #endif /* DEBUG */
81 :
82 : nsIAtom *
83 0 : nsSVGTextPathFrame::GetType() const
84 : {
85 0 : return nsGkAtoms::svgTextPathFrame;
86 : }
87 :
88 : void
89 0 : nsSVGTextPathFrame::GetXY(SVGUserUnitList *aX, SVGUserUnitList *aY)
90 : {
91 : // 'x' and 'y' don't apply to 'textPath'
92 0 : aX->Clear();
93 0 : aY->Clear();
94 0 : }
95 :
96 : void
97 0 : nsSVGTextPathFrame::GetDxDy(SVGUserUnitList *aDx, SVGUserUnitList *aDy)
98 : {
99 : // 'dx' and 'dy' don't apply to 'textPath'
100 0 : aDx->Clear();
101 0 : aDy->Clear();
102 0 : }
103 :
104 : const SVGNumberList*
105 0 : nsSVGTextPathFrame::GetRotate()
106 : {
107 0 : return nsnull;
108 : }
109 :
110 : //----------------------------------------------------------------------
111 : // nsSVGTextPathFrame methods:
112 :
113 : nsIFrame *
114 0 : nsSVGTextPathFrame::GetPathFrame()
115 : {
116 : nsSVGTextPathProperty *property = static_cast<nsSVGTextPathProperty*>
117 0 : (Properties().Get(nsSVGEffects::HrefProperty()));
118 :
119 0 : if (!property) {
120 0 : nsSVGTextPathElement *tp = static_cast<nsSVGTextPathElement*>(mContent);
121 0 : nsAutoString href;
122 0 : tp->mStringAttributes[nsSVGTextPathElement::HREF].GetAnimValue(href, tp);
123 0 : if (href.IsEmpty()) {
124 0 : return nsnull; // no URL
125 : }
126 :
127 0 : nsCOMPtr<nsIURI> targetURI;
128 0 : nsCOMPtr<nsIURI> base = mContent->GetBaseURI();
129 0 : nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(targetURI), href,
130 0 : mContent->GetCurrentDoc(), base);
131 :
132 : property =
133 0 : nsSVGEffects::GetTextPathProperty(targetURI, this, nsSVGEffects::HrefProperty());
134 0 : if (!property)
135 0 : return nsnull;
136 : }
137 :
138 0 : return property->GetReferencedFrame(nsGkAtoms::svgPathGeometryFrame, nsnull);
139 : }
140 :
141 : already_AddRefed<gfxFlattenedPath>
142 0 : nsSVGTextPathFrame::GetFlattenedPath()
143 : {
144 0 : nsIFrame *path = GetPathFrame();
145 :
146 0 : if (path) {
147 : nsSVGPathGeometryElement *element =
148 0 : static_cast<nsSVGPathGeometryElement*>(path->GetContent());
149 :
150 0 : return element->GetFlattenedPath(element->PrependLocalTransformsTo(gfxMatrix()));
151 : }
152 0 : return nsnull;
153 : }
154 :
155 : gfxFloat
156 0 : nsSVGTextPathFrame::GetStartOffset()
157 : {
158 0 : nsSVGTextPathElement *tp = static_cast<nsSVGTextPathElement*>(mContent);
159 0 : nsSVGLength2 *length = &tp->mLengthAttributes[nsSVGTextPathElement::STARTOFFSET];
160 0 : float val = length->GetAnimValInSpecifiedUnits();
161 :
162 0 : if (val == 0.0f)
163 0 : return 0.0;
164 :
165 0 : if (length->IsPercentage()) {
166 0 : nsRefPtr<gfxFlattenedPath> data = GetFlattenedPath();
167 0 : return data ? (val * data->GetLength() / 100.0) : 0.0;
168 : }
169 0 : return val * GetOffsetScale();
170 : }
171 :
172 : gfxFloat
173 0 : nsSVGTextPathFrame::GetOffsetScale()
174 : {
175 0 : nsIFrame *pathFrame = GetPathFrame();
176 0 : if (!pathFrame)
177 0 : return 1.0;
178 :
179 0 : return static_cast<nsSVGPathElement*>(pathFrame->GetContent())->
180 0 : GetPathLengthScale(nsSVGPathElement::eForTextPath);
181 : }
182 :
183 : //----------------------------------------------------------------------
184 : // nsIFrame methods
185 :
186 : NS_IMETHODIMP
187 0 : nsSVGTextPathFrame::AttributeChanged(PRInt32 aNameSpaceID,
188 : nsIAtom* aAttribute,
189 : PRInt32 aModType)
190 : {
191 0 : if (aNameSpaceID == kNameSpaceID_None &&
192 : aAttribute == nsGkAtoms::startOffset) {
193 0 : NotifyGlyphMetricsChange();
194 0 : } else if (aNameSpaceID == kNameSpaceID_XLink &&
195 : aAttribute == nsGkAtoms::href) {
196 : // Blow away our reference, if any
197 0 : Properties().Delete(nsSVGEffects::HrefProperty());
198 0 : NotifyGlyphMetricsChange();
199 : }
200 :
201 0 : return NS_OK;
202 : }
|