Bug 1867925 - Mark some storage-access-api tests as intermittent after wpt-sync....
[gecko.git] / accessible / windows / sdn / sdnTextAccessible.cpp
blob73ef4eb6e809f5863fb9ddbaa857f2dd8f9f56ae
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"
14 #include "nsIFrame.h"
15 #include "nsFontMetrics.h"
16 #include "nsPresContext.h"
17 #include "nsLayoutUtils.h"
18 #include "nsRange.h"
19 #include "gfxTextRun.h"
20 #include "nsIAccessibleTypes.h"
21 #include "mozilla/gfx/2D.h"
23 using namespace mozilla::a11y;
25 ////////////////////////////////////////////////////////////////////////////////
26 // sdnTextAccessible
27 ////////////////////////////////////////////////////////////////////////////////
29 IMPL_IUNKNOWN_QUERY_HEAD(sdnTextAccessible)
30 IMPL_IUNKNOWN_QUERY_IFACE(ISimpleDOMText)
31 IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mMsaa)
33 STDMETHODIMP
34 sdnTextAccessible::get_domText(BSTR __RPC_FAR* aText) {
35 if (!aText) return E_INVALIDARG;
36 *aText = nullptr;
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;
50 STDMETHODIMP
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,
56 &width, &height);
57 if (FAILED(rv)) return rv;
59 DocAccessible* document = mMsaa->LocalAcc()->Document();
60 NS_ASSERTION(
61 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();
74 return S_OK;
77 STDMETHODIMP
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;
96 nsRect sum;
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();
103 rect.MoveByX(start);
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());
114 return S_OK;
117 STDMETHODIMP
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);
133 STDMETHODIMP
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,
156 int32_t aOffset,
157 bool aPreferNext,
158 nsPoint& aOutPoint) {
159 nsIFrame* textFrame = nullptr;
160 int32_t outOffset;
161 aContainingFrame->GetChildFrameContainingOffset(aOffset, aPreferNext,
162 &outOffset, &textFrame);
163 if (textFrame) textFrame->GetPointFromOffset(aOffset, &aOutPoint);
165 return textFrame;