summaryrefslogtreecommitdiffstats
path: root/accessible/windows/sdn/sdnTextAccessible.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/windows/sdn/sdnTextAccessible.cpp')
-rw-r--r--accessible/windows/sdn/sdnTextAccessible.cpp166
1 files changed, 166 insertions, 0 deletions
diff --git a/accessible/windows/sdn/sdnTextAccessible.cpp b/accessible/windows/sdn/sdnTextAccessible.cpp
new file mode 100644
index 0000000000..73ef4eb6e8
--- /dev/null
+++ b/accessible/windows/sdn/sdnTextAccessible.cpp
@@ -0,0 +1,166 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "sdnTextAccessible.h"
+
+#include "ISimpleDOM.h"
+
+#include "nsCoreUtils.h"
+#include "DocAccessible.h"
+
+#include "nsIFrame.h"
+#include "nsFontMetrics.h"
+#include "nsPresContext.h"
+#include "nsLayoutUtils.h"
+#include "nsRange.h"
+#include "gfxTextRun.h"
+#include "nsIAccessibleTypes.h"
+#include "mozilla/gfx/2D.h"
+
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// sdnTextAccessible
+////////////////////////////////////////////////////////////////////////////////
+
+IMPL_IUNKNOWN_QUERY_HEAD(sdnTextAccessible)
+IMPL_IUNKNOWN_QUERY_IFACE(ISimpleDOMText)
+IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mMsaa)
+
+STDMETHODIMP
+sdnTextAccessible::get_domText(BSTR __RPC_FAR* aText) {
+ if (!aText) return E_INVALIDARG;
+ *aText = nullptr;
+
+ AccessibleWrap* acc = mMsaa->LocalAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ nsAutoString nodeValue;
+
+ acc->GetContent()->GetNodeValue(nodeValue);
+ if (nodeValue.IsEmpty()) return S_FALSE;
+
+ *aText = ::SysAllocStringLen(nodeValue.get(), nodeValue.Length());
+ return *aText ? S_OK : E_OUTOFMEMORY;
+}
+
+STDMETHODIMP
+sdnTextAccessible::get_clippedSubstringBounds(
+ unsigned int aStartIndex, unsigned int aEndIndex, int __RPC_FAR* aX,
+ int __RPC_FAR* aY, int __RPC_FAR* aWidth, int __RPC_FAR* aHeight) {
+ nscoord x = 0, y = 0, width = 0, height = 0;
+ HRESULT rv = get_unclippedSubstringBounds(aStartIndex, aEndIndex, &x, &y,
+ &width, &height);
+ if (FAILED(rv)) return rv;
+
+ DocAccessible* document = mMsaa->LocalAcc()->Document();
+ NS_ASSERTION(
+ document,
+ "There must always be a doc accessible, but there isn't. Crash!");
+
+ LayoutDeviceIntRect docRect = document->Bounds();
+ LayoutDeviceIntRect unclippedRect(x, y, width, height);
+
+ LayoutDeviceIntRect clippedRect;
+ clippedRect.IntersectRect(unclippedRect, docRect);
+
+ *aX = clippedRect.X();
+ *aY = clippedRect.Y();
+ *aWidth = clippedRect.Width();
+ *aHeight = clippedRect.Height();
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnTextAccessible::get_unclippedSubstringBounds(
+ unsigned int aStartIndex, unsigned int aEndIndex, int __RPC_FAR* aX,
+ int __RPC_FAR* aY, int __RPC_FAR* aWidth, int __RPC_FAR* aHeight) {
+ if (!aX || !aY || !aWidth || !aHeight) return E_INVALIDARG;
+ *aX = *aY = *aWidth = *aHeight = 0;
+
+ AccessibleWrap* acc = mMsaa->LocalAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ nsIFrame* frame = acc->GetFrame();
+ NS_ENSURE_TRUE(frame, E_FAIL);
+
+ nsPoint startPoint, endPoint;
+ nsIFrame* startFrame =
+ GetPointFromOffset(frame, aStartIndex, true, startPoint);
+ nsIFrame* endFrame = GetPointFromOffset(frame, aEndIndex, false, endPoint);
+ if (!startFrame || !endFrame) return E_FAIL;
+
+ nsRect sum;
+ nsIFrame* iter = startFrame;
+ nsIFrame* stopLoopFrame = endFrame->GetNextContinuation();
+ for (; iter != stopLoopFrame; iter = iter->GetNextContinuation()) {
+ nsRect rect = iter->GetScreenRectInAppUnits();
+ nscoord start = (iter == startFrame) ? startPoint.x : 0;
+ nscoord end = (iter == endFrame) ? endPoint.x : rect.Width();
+ rect.MoveByX(start);
+ rect.SetWidth(end - start);
+ sum.UnionRect(sum, rect);
+ }
+
+ nsPresContext* presContext = acc->Document()->PresContext();
+ *aX = presContext->AppUnitsToDevPixels(sum.X());
+ *aY = presContext->AppUnitsToDevPixels(sum.Y());
+ *aWidth = presContext->AppUnitsToDevPixels(sum.Width());
+ *aHeight = presContext->AppUnitsToDevPixels(sum.Height());
+
+ return S_OK;
+}
+
+STDMETHODIMP
+sdnTextAccessible::scrollToSubstring(unsigned int aStartIndex,
+ unsigned int aEndIndex) {
+ AccessibleWrap* acc = mMsaa->LocalAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ RefPtr<nsRange> range = nsRange::Create(acc->GetContent());
+ if (NS_FAILED(range->SetStart(acc->GetContent(), aStartIndex))) return E_FAIL;
+
+ if (NS_FAILED(range->SetEnd(acc->GetContent(), aEndIndex))) return E_FAIL;
+
+ nsresult rv = nsCoreUtils::ScrollSubstringTo(
+ acc->GetFrame(), range, nsIAccessibleScrollType::SCROLL_TYPE_ANYWHERE);
+ return GetHRESULT(rv);
+}
+
+STDMETHODIMP
+sdnTextAccessible::get_fontFamily(BSTR __RPC_FAR* aFontFamily) {
+ if (!aFontFamily) return E_INVALIDARG;
+ *aFontFamily = nullptr;
+
+ AccessibleWrap* acc = mMsaa->LocalAcc();
+ if (!acc) return CO_E_OBJNOTCONNECTED;
+
+ nsIFrame* frame = acc->GetFrame();
+ if (!frame) return E_FAIL;
+
+ RefPtr<nsFontMetrics> fm = nsLayoutUtils::GetFontMetricsForFrame(frame, 1.0f);
+ RefPtr<gfxFont> font = fm->GetThebesFontGroup()->GetFirstValidFont();
+
+ const nsCString& name = font->GetName();
+ if (name.IsEmpty()) return S_FALSE;
+
+ NS_ConvertUTF8toUTF16 str(name);
+ *aFontFamily = ::SysAllocStringLen(str.get(), str.Length());
+ return *aFontFamily ? S_OK : E_OUTOFMEMORY;
+}
+
+nsIFrame* sdnTextAccessible::GetPointFromOffset(nsIFrame* aContainingFrame,
+ int32_t aOffset,
+ bool aPreferNext,
+ nsPoint& aOutPoint) {
+ nsIFrame* textFrame = nullptr;
+ int32_t outOffset;
+ aContainingFrame->GetChildFrameContainingOffset(aOffset, aPreferNext,
+ &outOffset, &textFrame);
+ if (textFrame) textFrame->GetPointFromOffset(aOffset, &aOutPoint);
+
+ return textFrame;
+}