1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=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/. */
7 #include "sdnTextAccessible.h"
9 #include "ISimpleDOM.h"
11 #include "nsCoreUtils.h"
12 #include "DocAccessible.h"
15 #include "nsFontMetrics.h"
16 #include "nsPresContext.h"
17 #include "nsLayoutUtils.h"
19 #include "gfxTextRun.h"
20 #include "nsIAccessibleTypes.h"
21 #include "mozilla/gfx/2D.h"
23 using namespace mozilla::a11y
;
25 ////////////////////////////////////////////////////////////////////////////////
27 ////////////////////////////////////////////////////////////////////////////////
29 IMPL_IUNKNOWN_QUERY_HEAD(sdnTextAccessible
)
30 IMPL_IUNKNOWN_QUERY_IFACE(ISimpleDOMText
)
31 IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mMsaa
)
34 sdnTextAccessible::get_domText(BSTR __RPC_FAR
* aText
) {
35 if (!aText
) return E_INVALIDARG
;
38 AccessibleWrap
* acc
= mMsaa
->LocalAcc();
39 if (!acc
) return CO_E_OBJNOTCONNECTED
;
41 nsAutoString nodeValue
;
43 acc
->GetContent()->GetNodeValue(nodeValue
);
44 if (nodeValue
.IsEmpty()) return S_FALSE
;
46 *aText
= ::SysAllocStringLen(nodeValue
.get(), nodeValue
.Length());
47 return *aText
? S_OK
: E_OUTOFMEMORY
;
51 sdnTextAccessible::get_clippedSubstringBounds(
52 unsigned int aStartIndex
, unsigned int aEndIndex
, int __RPC_FAR
* aX
,
53 int __RPC_FAR
* aY
, int __RPC_FAR
* aWidth
, int __RPC_FAR
* aHeight
) {
54 nscoord x
= 0, y
= 0, width
= 0, height
= 0;
55 HRESULT rv
= get_unclippedSubstringBounds(aStartIndex
, aEndIndex
, &x
, &y
,
57 if (FAILED(rv
)) return rv
;
59 DocAccessible
* document
= mMsaa
->LocalAcc()->Document();
62 "There must always be a doc accessible, but there isn't. Crash!");
64 LayoutDeviceIntRect docRect
= document
->Bounds();
65 LayoutDeviceIntRect
unclippedRect(x
, y
, width
, height
);
67 LayoutDeviceIntRect clippedRect
;
68 clippedRect
.IntersectRect(unclippedRect
, docRect
);
70 *aX
= clippedRect
.X();
71 *aY
= clippedRect
.Y();
72 *aWidth
= clippedRect
.Width();
73 *aHeight
= clippedRect
.Height();
78 sdnTextAccessible::get_unclippedSubstringBounds(
79 unsigned int aStartIndex
, unsigned int aEndIndex
, int __RPC_FAR
* aX
,
80 int __RPC_FAR
* aY
, int __RPC_FAR
* aWidth
, int __RPC_FAR
* aHeight
) {
81 if (!aX
|| !aY
|| !aWidth
|| !aHeight
) return E_INVALIDARG
;
82 *aX
= *aY
= *aWidth
= *aHeight
= 0;
84 AccessibleWrap
* acc
= mMsaa
->LocalAcc();
85 if (!acc
) return CO_E_OBJNOTCONNECTED
;
87 nsIFrame
* frame
= acc
->GetFrame();
88 NS_ENSURE_TRUE(frame
, E_FAIL
);
90 nsPoint startPoint
, endPoint
;
91 nsIFrame
* startFrame
=
92 GetPointFromOffset(frame
, aStartIndex
, true, startPoint
);
93 nsIFrame
* endFrame
= GetPointFromOffset(frame
, aEndIndex
, false, endPoint
);
94 if (!startFrame
|| !endFrame
) return E_FAIL
;
97 nsIFrame
* iter
= startFrame
;
98 nsIFrame
* stopLoopFrame
= endFrame
->GetNextContinuation();
99 for (; iter
!= stopLoopFrame
; iter
= iter
->GetNextContinuation()) {
100 nsRect rect
= iter
->GetScreenRectInAppUnits();
101 nscoord start
= (iter
== startFrame
) ? startPoint
.x
: 0;
102 nscoord end
= (iter
== endFrame
) ? endPoint
.x
: rect
.Width();
104 rect
.SetWidth(end
- start
);
105 sum
.UnionRect(sum
, rect
);
108 nsPresContext
* presContext
= acc
->Document()->PresContext();
109 *aX
= presContext
->AppUnitsToDevPixels(sum
.X());
110 *aY
= presContext
->AppUnitsToDevPixels(sum
.Y());
111 *aWidth
= presContext
->AppUnitsToDevPixels(sum
.Width());
112 *aHeight
= presContext
->AppUnitsToDevPixels(sum
.Height());
118 sdnTextAccessible::scrollToSubstring(unsigned int aStartIndex
,
119 unsigned int aEndIndex
) {
120 AccessibleWrap
* acc
= mMsaa
->LocalAcc();
121 if (!acc
) return CO_E_OBJNOTCONNECTED
;
123 RefPtr
<nsRange
> range
= nsRange::Create(acc
->GetContent());
124 if (NS_FAILED(range
->SetStart(acc
->GetContent(), aStartIndex
))) return E_FAIL
;
126 if (NS_FAILED(range
->SetEnd(acc
->GetContent(), aEndIndex
))) return E_FAIL
;
128 nsresult rv
= nsCoreUtils::ScrollSubstringTo(
129 acc
->GetFrame(), range
, nsIAccessibleScrollType::SCROLL_TYPE_ANYWHERE
);
130 return GetHRESULT(rv
);
134 sdnTextAccessible::get_fontFamily(BSTR __RPC_FAR
* aFontFamily
) {
135 if (!aFontFamily
) return E_INVALIDARG
;
136 *aFontFamily
= nullptr;
138 AccessibleWrap
* acc
= mMsaa
->LocalAcc();
139 if (!acc
) return CO_E_OBJNOTCONNECTED
;
141 nsIFrame
* frame
= acc
->GetFrame();
142 if (!frame
) return E_FAIL
;
144 RefPtr
<nsFontMetrics
> fm
= nsLayoutUtils::GetFontMetricsForFrame(frame
, 1.0f
);
145 RefPtr
<gfxFont
> font
= fm
->GetThebesFontGroup()->GetFirstValidFont();
147 const nsCString
& name
= font
->GetName();
148 if (name
.IsEmpty()) return S_FALSE
;
150 NS_ConvertUTF8toUTF16
str(name
);
151 *aFontFamily
= ::SysAllocStringLen(str
.get(), str
.Length());
152 return *aFontFamily
? S_OK
: E_OUTOFMEMORY
;
155 nsIFrame
* sdnTextAccessible::GetPointFromOffset(nsIFrame
* aContainingFrame
,
158 nsPoint
& aOutPoint
) {
159 nsIFrame
* textFrame
= nullptr;
161 aContainingFrame
->GetChildFrameContainingOffset(aOffset
, aPreferNext
,
162 &outOffset
, &textFrame
);
163 if (textFrame
) textFrame
->GetPointFromOffset(aOffset
, &aOutPoint
);