Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/svg/SVGTextContentElement.cpp
Line
Count
Source (jump to first uncovered line)
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 "mozilla/dom/SVGTextContentElement.h"
8
9
#include "mozilla/dom/SVGLengthBinding.h"
10
#include "mozilla/dom/SVGTextContentElementBinding.h"
11
#include "mozilla/dom/SVGIRect.h"
12
#include "nsBidiUtils.h"
13
#include "nsISVGPoint.h"
14
#include "nsTextFragment.h"
15
#include "nsTextFrameUtils.h"
16
#include "nsTextNode.h"
17
#include "SVGTextFrame.h"
18
19
namespace mozilla {
20
namespace dom {
21
22
using namespace SVGTextContentElement_Binding;
23
24
nsSVGEnumMapping SVGTextContentElement::sLengthAdjustMap[] = {
25
  { &nsGkAtoms::spacing, LENGTHADJUST_SPACING },
26
  { &nsGkAtoms::spacingAndGlyphs, LENGTHADJUST_SPACINGANDGLYPHS },
27
  { nullptr, 0 }
28
};
29
30
nsSVGElement::EnumInfo SVGTextContentElement::sEnumInfo[1] =
31
{
32
  { &nsGkAtoms::lengthAdjust, sLengthAdjustMap, LENGTHADJUST_SPACING }
33
};
34
35
nsSVGElement::LengthInfo SVGTextContentElement::sLengthInfo[1] =
36
{
37
  { &nsGkAtoms::textLength, 0, SVGLength_Binding::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::XY }
38
};
39
40
SVGTextFrame*
41
SVGTextContentElement::GetSVGTextFrame()
42
0
{
43
0
  nsIFrame* frame = GetPrimaryFrame(FlushType::Layout);
44
0
  nsIFrame* textFrame =
45
0
    nsLayoutUtils::GetClosestFrameOfType(frame, LayoutFrameType::SVGText);
46
0
  return static_cast<SVGTextFrame*>(textFrame);
47
0
}
48
49
SVGTextFrame*
50
SVGTextContentElement::GetSVGTextFrameForNonLayoutDependentQuery()
51
0
{
52
0
  nsIFrame* frame = GetPrimaryFrame(FlushType::Frames);
53
0
  nsIFrame* textFrame =
54
0
    nsLayoutUtils::GetClosestFrameOfType(frame, LayoutFrameType::SVGText);
55
0
  return static_cast<SVGTextFrame*>(textFrame);
56
0
}
57
58
already_AddRefed<SVGAnimatedLength>
59
SVGTextContentElement::TextLength()
60
0
{
61
0
  return LengthAttributes()[TEXTLENGTH].ToDOMAnimatedLength(this);
62
0
}
63
64
already_AddRefed<SVGAnimatedEnumeration>
65
SVGTextContentElement::LengthAdjust()
66
0
{
67
0
  return EnumAttributes()[LENGTHADJUST].ToDOMAnimatedEnum(this);
68
0
}
69
70
//----------------------------------------------------------------------
71
72
template<typename T>
73
static bool
74
FragmentHasSkippableCharacter(const T* aBuffer, uint32_t aLength)
75
0
{
76
0
  for (uint32_t i = 0; i < aLength; i++) {
77
0
    if (nsTextFrameUtils::IsSkippableCharacterForTransformText(aBuffer[i])) {
78
0
      return true;
79
0
    }
80
0
  }
81
0
  return false;
82
0
}
Unexecuted instantiation: Unified_cpp_dom_svg6.cpp:bool mozilla::dom::FragmentHasSkippableCharacter<char16_t>(char16_t const*, unsigned int)
Unexecuted instantiation: Unified_cpp_dom_svg6.cpp:bool mozilla::dom::FragmentHasSkippableCharacter<unsigned char>(unsigned char const*, unsigned int)
83
84
Maybe<int32_t>
85
SVGTextContentElement::GetNonLayoutDependentNumberOfChars()
86
0
{
87
0
  SVGTextFrame* frame = GetSVGTextFrameForNonLayoutDependentQuery();
88
0
  if (!frame || frame != GetPrimaryFrame()) {
89
0
    // Only support this fast path on <text>, not child <tspan>s, etc.
90
0
    return Some(0);
91
0
  }
92
0
93
0
  uint32_t num = 0;
94
0
95
0
  for (nsINode* n = Element::GetFirstChild(); n; n = n->GetNextSibling()) {
96
0
    if (!n->IsText()) {
97
0
      return Nothing();
98
0
    }
99
0
100
0
    const nsTextFragment* text = static_cast<nsTextNode*>(n)->GetText();
101
0
    uint32_t length = text->GetLength();
102
0
103
0
    if (text->Is2b()) {
104
0
      if (FragmentHasSkippableCharacter(text->Get2b(), length)) {
105
0
        return Nothing();
106
0
      }
107
0
    } else {
108
0
      auto buffer = reinterpret_cast<const uint8_t*>(text->Get1b());
109
0
      if (FragmentHasSkippableCharacter(buffer, length)) {
110
0
        return Nothing();
111
0
      }
112
0
    }
113
0
114
0
    num += length;
115
0
  }
116
0
117
0
  return Some(num);
118
0
}
119
120
int32_t
121
SVGTextContentElement::GetNumberOfChars()
122
0
{
123
0
  Maybe<int32_t> num = GetNonLayoutDependentNumberOfChars();
124
0
  if (num) {
125
0
    return *num;
126
0
  }
127
0
128
0
  SVGTextFrame* textFrame = GetSVGTextFrame();
129
0
  return textFrame ? textFrame->GetNumberOfChars(this) : 0;
130
0
}
131
132
float
133
SVGTextContentElement::GetComputedTextLength()
134
0
{
135
0
  SVGTextFrame* textFrame = GetSVGTextFrame();
136
0
  return textFrame ? textFrame->GetComputedTextLength(this) : 0.0f;
137
0
}
138
139
void
140
SVGTextContentElement::SelectSubString(uint32_t charnum, uint32_t nchars, ErrorResult& rv)
141
0
{
142
0
  SVGTextFrame* textFrame = GetSVGTextFrame();
143
0
  if (!textFrame)
144
0
    return;
145
0
146
0
  rv = textFrame->SelectSubString(this, charnum, nchars);
147
0
}
148
149
float
150
SVGTextContentElement::GetSubStringLength(uint32_t charnum, uint32_t nchars, ErrorResult& rv)
151
0
{
152
0
  SVGTextFrame* textFrame = GetSVGTextFrameForNonLayoutDependentQuery();
153
0
  if (!textFrame)
154
0
    return 0.0f;
155
0
156
0
  float length = 0.0f;
157
0
  rv = textFrame->GetSubStringLength(this, charnum, nchars, &length);
158
0
  return length;
159
0
}
160
161
already_AddRefed<nsISVGPoint>
162
SVGTextContentElement::GetStartPositionOfChar(uint32_t charnum, ErrorResult& rv)
163
0
{
164
0
  SVGTextFrame* textFrame = GetSVGTextFrame();
165
0
  if (!textFrame) {
166
0
    rv.Throw(NS_ERROR_FAILURE);
167
0
    return nullptr;
168
0
  }
169
0
170
0
  nsCOMPtr<nsISVGPoint> point;
171
0
  rv = textFrame->GetStartPositionOfChar(this, charnum, getter_AddRefs(point));
172
0
  return point.forget();
173
0
}
174
175
already_AddRefed<nsISVGPoint>
176
SVGTextContentElement::GetEndPositionOfChar(uint32_t charnum, ErrorResult& rv)
177
0
{
178
0
  SVGTextFrame* textFrame = GetSVGTextFrame();
179
0
  if (!textFrame) {
180
0
    rv.Throw(NS_ERROR_FAILURE);
181
0
    return nullptr;
182
0
  }
183
0
184
0
  nsCOMPtr<nsISVGPoint> point;
185
0
  rv = textFrame->GetEndPositionOfChar(this, charnum, getter_AddRefs(point));
186
0
  return point.forget();
187
0
}
188
189
already_AddRefed<SVGIRect>
190
SVGTextContentElement::GetExtentOfChar(uint32_t charnum, ErrorResult& rv)
191
0
{
192
0
  SVGTextFrame* textFrame = GetSVGTextFrame();
193
0
194
0
  if (!textFrame) {
195
0
    rv.Throw(NS_ERROR_FAILURE);
196
0
    return nullptr;
197
0
  }
198
0
199
0
  RefPtr<SVGIRect> rect;
200
0
  rv = textFrame->GetExtentOfChar(this, charnum, getter_AddRefs(rect));
201
0
  return rect.forget();
202
0
}
203
204
float
205
SVGTextContentElement::GetRotationOfChar(uint32_t charnum, ErrorResult& rv)
206
0
{
207
0
  SVGTextFrame* textFrame = GetSVGTextFrame();
208
0
209
0
  if (!textFrame) {
210
0
    rv.Throw(NS_ERROR_FAILURE);
211
0
    return 0.0f;
212
0
  }
213
0
214
0
  float rotation;
215
0
  rv = textFrame->GetRotationOfChar(this, charnum, &rotation);
216
0
  return rotation;
217
0
}
218
219
int32_t
220
SVGTextContentElement::GetCharNumAtPosition(nsISVGPoint& aPoint)
221
0
{
222
0
  SVGTextFrame* textFrame = GetSVGTextFrame();
223
0
  return textFrame ? textFrame->GetCharNumAtPosition(this, &aPoint) : -1;
224
0
}
225
226
} // namespace dom
227
} // namespace mozilla