1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "LocalAccessible-inl.h"
9 #include "AccAttributes.h"
10 #include "nsAccUtils.h"
11 #include "nsCoreUtils.h"
12 #include "StyleInfo.h"
14 #include "gfxTextRun.h"
15 #include "nsFontMetrics.h"
16 #include "nsLayoutUtils.h"
17 #include "nsContainerFrame.h"
18 #include "nsStyleUtil.h"
19 #include "HyperTextAccessible.h"
20 #include "mozilla/AppUnits.h"
21 #include "mozilla/gfx/2D.h"
23 using namespace mozilla
;
24 using namespace mozilla::a11y
;
26 ////////////////////////////////////////////////////////////////////////////////
28 ////////////////////////////////////////////////////////////////////////////////
30 void TextAttrsMgr::GetAttributes(AccAttributes
* aAttributes
,
31 uint32_t* aStartOffset
, uint32_t* aEndOffset
) {
32 // 1. Hyper text accessible must be specified always.
33 // 2. Offset accessible must be specified in
34 // the case of text attributes. Result hyper text offsets are optional if you
35 // just want the attributes for a single text Accessible.
36 // 3. Offset accessible and result hyper text offsets must not be specified
37 // but include default text attributes flag and attributes list must be
38 // specified in the case of default text attributes.
40 mHyperTextAcc
&& ((mOffsetAcc
&& mOffsetAccIdx
!= -1) ||
41 (!mOffsetAcc
&& mOffsetAccIdx
== -1 && !aStartOffset
&&
42 !aEndOffset
&& mIncludeDefAttrs
&& aAttributes
)),
43 "Wrong usage of TextAttrsMgr!");
45 // Embedded objects are combined into own range with empty attributes set.
46 if (mOffsetAcc
&& !mOffsetAcc
->IsText()) {
50 for (int32_t childIdx
= mOffsetAccIdx
- 1; childIdx
>= 0; childIdx
--) {
51 LocalAccessible
* currAcc
= mHyperTextAcc
->LocalChildAt(childIdx
);
52 if (currAcc
->IsText()) break;
57 uint32_t childCount
= mHyperTextAcc
->ChildCount();
58 for (uint32_t childIdx
= mOffsetAccIdx
+ 1; childIdx
< childCount
;
60 LocalAccessible
* currAcc
= mHyperTextAcc
->LocalChildAt(childIdx
);
61 if (currAcc
->IsText()) break;
69 // Get the content and frame of the accessible. In the case of document
70 // accessible it's role content and root frame.
71 nsIContent
* hyperTextElm
= mHyperTextAcc
->GetContent();
73 return; // XXX: we don't support text attrs on document with no body
76 nsIFrame
* rootFrame
= mHyperTextAcc
->GetFrame();
81 nsIContent
*offsetNode
= nullptr, *offsetElm
= nullptr;
82 nsIFrame
* frame
= nullptr;
84 offsetNode
= mOffsetAcc
->GetContent();
85 offsetElm
= nsCoreUtils::GetDOMElementFor(offsetNode
);
86 MOZ_ASSERT(offsetElm
, "No element for offset accessible!");
87 if (!offsetElm
) return;
89 frame
= offsetElm
->GetPrimaryFrame();
92 // "language" text attribute
93 LangTextAttr
langTextAttr(mHyperTextAcc
, hyperTextElm
, offsetNode
);
95 // "aria-invalid" text attribute
96 InvalidTextAttr
invalidTextAttr(hyperTextElm
, offsetNode
);
98 // "background-color" text attribute
99 BGColorTextAttr
bgColorTextAttr(rootFrame
, frame
);
101 // "color" text attribute
102 ColorTextAttr
colorTextAttr(rootFrame
, frame
);
104 // "font-family" text attribute
105 FontFamilyTextAttr
fontFamilyTextAttr(rootFrame
, frame
);
107 // "font-size" text attribute
108 FontSizeTextAttr
fontSizeTextAttr(rootFrame
, frame
);
110 // "font-style" text attribute
111 FontStyleTextAttr
fontStyleTextAttr(rootFrame
, frame
);
113 // "font-weight" text attribute
114 FontWeightTextAttr
fontWeightTextAttr(rootFrame
, frame
);
116 // "auto-generated" text attribute
117 AutoGeneratedTextAttr
autoGenTextAttr(mHyperTextAcc
, mOffsetAcc
);
119 // "text-underline(line-through)-style(color)" text attributes
120 TextDecorTextAttr
textDecorTextAttr(rootFrame
, frame
);
122 // "text-position" text attribute
123 TextPosTextAttr
textPosTextAttr(rootFrame
, frame
);
125 TextAttr
* attrArray
[] = {
126 &langTextAttr
, &invalidTextAttr
, &bgColorTextAttr
,
127 &colorTextAttr
, &fontFamilyTextAttr
, &fontSizeTextAttr
,
128 &fontStyleTextAttr
, &fontWeightTextAttr
, &autoGenTextAttr
,
129 &textDecorTextAttr
, &textPosTextAttr
};
131 // Expose text attributes if applicable.
133 for (uint32_t idx
= 0; idx
< ArrayLength(attrArray
); idx
++) {
134 attrArray
[idx
]->Expose(aAttributes
, mIncludeDefAttrs
);
138 // Expose text attributes range where they are applied if applicable.
140 GetRange(attrArray
, ArrayLength(attrArray
), aStartOffset
, aEndOffset
);
144 void TextAttrsMgr::GetRange(TextAttr
* aAttrArray
[], uint32_t aAttrArrayLen
,
145 uint32_t* aStartOffset
, uint32_t* aEndOffset
) {
146 // Navigate backward from anchor accessible to find start offset.
147 for (int32_t childIdx
= mOffsetAccIdx
- 1; childIdx
>= 0; childIdx
--) {
148 LocalAccessible
* currAcc
= mHyperTextAcc
->LocalChildAt(childIdx
);
150 // Stop on embedded accessible since embedded accessibles are combined into
152 if (!currAcc
->IsText()) break;
154 MOZ_ASSERT(nsCoreUtils::GetDOMElementFor(currAcc
->GetContent()),
155 "Text accessible has to have an associated DOM element");
157 bool offsetFound
= false;
158 for (uint32_t attrIdx
= 0; attrIdx
< aAttrArrayLen
; attrIdx
++) {
159 TextAttr
* textAttr
= aAttrArray
[attrIdx
];
160 if (!textAttr
->Equal(currAcc
)) {
166 if (offsetFound
) break;
168 *(aStartOffset
) -= nsAccUtils::TextLength(currAcc
);
171 // Navigate forward from anchor accessible to find end offset.
172 uint32_t childLen
= mHyperTextAcc
->ChildCount();
173 for (uint32_t childIdx
= mOffsetAccIdx
+ 1; childIdx
< childLen
; childIdx
++) {
174 LocalAccessible
* currAcc
= mHyperTextAcc
->LocalChildAt(childIdx
);
175 if (!currAcc
->IsText()) break;
177 MOZ_ASSERT(nsCoreUtils::GetDOMElementFor(currAcc
->GetContent()),
178 "Text accessible has to have an associated DOM element");
180 bool offsetFound
= false;
181 for (uint32_t attrIdx
= 0; attrIdx
< aAttrArrayLen
; attrIdx
++) {
182 TextAttr
* textAttr
= aAttrArray
[attrIdx
];
184 // Alter the end offset when text attribute changes its value and stop
186 if (!textAttr
->Equal(currAcc
)) {
192 if (offsetFound
) break;
194 (*aEndOffset
) += nsAccUtils::TextLength(currAcc
);
198 ////////////////////////////////////////////////////////////////////////////////
200 ////////////////////////////////////////////////////////////////////////////////
202 TextAttrsMgr::LangTextAttr::LangTextAttr(HyperTextAccessible
* aRoot
,
203 nsIContent
* aRootElm
, nsIContent
* aElm
)
204 : TTextAttr
<nsString
>(!aElm
), mRootContent(aRootElm
) {
205 aRoot
->Language(mRootNativeValue
);
206 mIsRootDefined
= !mRootNativeValue
.IsEmpty();
209 nsCoreUtils::GetLanguageFor(aElm
, mRootContent
, mNativeValue
);
210 mIsDefined
= !mNativeValue
.IsEmpty();
214 TextAttrsMgr::LangTextAttr::~LangTextAttr() {}
216 bool TextAttrsMgr::LangTextAttr::GetValueFor(LocalAccessible
* aAccessible
,
218 nsCoreUtils::GetLanguageFor(aAccessible
->GetContent(), mRootContent
, *aValue
);
219 return !aValue
->IsEmpty();
222 void TextAttrsMgr::LangTextAttr::ExposeValue(AccAttributes
* aAttributes
,
223 const nsString
& aValue
) {
224 aAttributes
->SetAttributeStringCopy(nsGkAtoms::language
, aValue
);
227 ////////////////////////////////////////////////////////////////////////////////
229 ////////////////////////////////////////////////////////////////////////////////
231 TextAttrsMgr::InvalidTextAttr::InvalidTextAttr(nsIContent
* aRootElm
,
233 : TTextAttr
<uint32_t>(!aElm
), mRootElm(aRootElm
) {
234 mIsRootDefined
= GetValue(mRootElm
, &mRootNativeValue
);
235 if (aElm
) mIsDefined
= GetValue(aElm
, &mNativeValue
);
238 bool TextAttrsMgr::InvalidTextAttr::GetValueFor(LocalAccessible
* aAccessible
,
240 nsIContent
* elm
= nsCoreUtils::GetDOMElementFor(aAccessible
->GetContent());
241 return elm
? GetValue(elm
, aValue
) : false;
244 void TextAttrsMgr::InvalidTextAttr::ExposeValue(AccAttributes
* aAttributes
,
245 const uint32_t& aValue
) {
248 aAttributes
->SetAttribute(nsGkAtoms::invalid
, nsGkAtoms::_false
);
252 aAttributes
->SetAttribute(nsGkAtoms::invalid
, nsGkAtoms::grammar
);
256 aAttributes
->SetAttribute(nsGkAtoms::invalid
, nsGkAtoms::spelling
);
260 aAttributes
->SetAttribute(nsGkAtoms::invalid
, nsGkAtoms::_true
);
265 bool TextAttrsMgr::InvalidTextAttr::GetValue(nsIContent
* aElm
,
267 nsIContent
* elm
= aElm
;
269 if (nsAccUtils::HasDefinedARIAToken(elm
, nsGkAtoms::aria_invalid
)) {
270 static dom::Element::AttrValuesArray tokens
[] = {
271 nsGkAtoms::_false
, nsGkAtoms::grammar
, nsGkAtoms::spelling
, nullptr};
273 int32_t idx
= elm
->AsElement()->FindAttrValueIn(
274 kNameSpaceID_None
, nsGkAtoms::aria_invalid
, tokens
, eCaseMatters
);
290 } while ((elm
= elm
->GetParent()) && elm
!= mRootElm
);
295 ////////////////////////////////////////////////////////////////////////////////
297 ////////////////////////////////////////////////////////////////////////////////
299 TextAttrsMgr::BGColorTextAttr::BGColorTextAttr(nsIFrame
* aRootFrame
,
301 : TTextAttr
<nscolor
>(!aFrame
), mRootFrame(aRootFrame
) {
302 mIsRootDefined
= GetColor(mRootFrame
, &mRootNativeValue
);
303 if (aFrame
) mIsDefined
= GetColor(aFrame
, &mNativeValue
);
306 bool TextAttrsMgr::BGColorTextAttr::GetValueFor(LocalAccessible
* aAccessible
,
308 nsIContent
* elm
= nsCoreUtils::GetDOMElementFor(aAccessible
->GetContent());
310 nsIFrame
* frame
= elm
->GetPrimaryFrame();
312 return GetColor(frame
, aValue
);
318 void TextAttrsMgr::BGColorTextAttr::ExposeValue(AccAttributes
* aAttributes
,
319 const nscolor
& aValue
) {
320 aAttributes
->SetAttribute(nsGkAtoms::backgroundColor
, Color
{aValue
});
323 bool TextAttrsMgr::BGColorTextAttr::GetColor(nsIFrame
* aFrame
,
325 nscolor backgroundColor
= aFrame
->StyleBackground()->BackgroundColor(aFrame
);
326 if (NS_GET_A(backgroundColor
) > 0) {
327 *aColor
= backgroundColor
;
331 nsContainerFrame
* parentFrame
= aFrame
->GetParent();
333 *aColor
= aFrame
->PresContext()->DefaultBackgroundColor();
337 // Each frame of parents chain for the initially passed 'aFrame' has
338 // transparent background color. So background color isn't changed from
339 // 'mRootFrame' to initially passed 'aFrame'.
340 if (parentFrame
== mRootFrame
) return false;
342 return GetColor(parentFrame
, aColor
);
345 ////////////////////////////////////////////////////////////////////////////////
347 ////////////////////////////////////////////////////////////////////////////////
349 TextAttrsMgr::ColorTextAttr::ColorTextAttr(nsIFrame
* aRootFrame
,
351 : TTextAttr
<nscolor
>(!aFrame
) {
352 mRootNativeValue
= aRootFrame
->StyleText()->mColor
.ToColor();
353 mIsRootDefined
= true;
356 mNativeValue
= aFrame
->StyleText()->mColor
.ToColor();
361 bool TextAttrsMgr::ColorTextAttr::GetValueFor(LocalAccessible
* aAccessible
,
363 nsIContent
* elm
= nsCoreUtils::GetDOMElementFor(aAccessible
->GetContent());
365 if (nsIFrame
* frame
= elm
->GetPrimaryFrame()) {
366 *aValue
= frame
->StyleText()->mColor
.ToColor();
373 void TextAttrsMgr::ColorTextAttr::ExposeValue(AccAttributes
* aAttributes
,
374 const nscolor
& aValue
) {
375 aAttributes
->SetAttribute(nsGkAtoms::color
, Color
{aValue
});
378 ////////////////////////////////////////////////////////////////////////////////
379 // FontFamilyTextAttr
380 ////////////////////////////////////////////////////////////////////////////////
382 TextAttrsMgr::FontFamilyTextAttr::FontFamilyTextAttr(nsIFrame
* aRootFrame
,
384 : TTextAttr
<nsString
>(!aFrame
) {
385 mIsRootDefined
= GetFontFamily(aRootFrame
, mRootNativeValue
);
387 if (aFrame
) mIsDefined
= GetFontFamily(aFrame
, mNativeValue
);
390 bool TextAttrsMgr::FontFamilyTextAttr::GetValueFor(LocalAccessible
* aAccessible
,
392 nsIContent
* elm
= nsCoreUtils::GetDOMElementFor(aAccessible
->GetContent());
394 nsIFrame
* frame
= elm
->GetPrimaryFrame();
396 return GetFontFamily(frame
, *aValue
);
402 void TextAttrsMgr::FontFamilyTextAttr::ExposeValue(AccAttributes
* aAttributes
,
403 const nsString
& aValue
) {
404 aAttributes
->SetAttributeStringCopy(nsGkAtoms::font_family
, aValue
);
407 bool TextAttrsMgr::FontFamilyTextAttr::GetFontFamily(nsIFrame
* aFrame
,
409 RefPtr
<nsFontMetrics
> fm
=
410 nsLayoutUtils::GetFontMetricsForFrame(aFrame
, 1.0f
);
412 gfxFontGroup
* fontGroup
= fm
->GetThebesFontGroup();
413 gfxFont
* font
= fontGroup
->GetFirstValidFont();
414 gfxFontEntry
* fontEntry
= font
->GetFontEntry();
415 aFamily
.Append(NS_ConvertUTF8toUTF16(fontEntry
->FamilyName()));
419 ////////////////////////////////////////////////////////////////////////////////
421 ////////////////////////////////////////////////////////////////////////////////
423 TextAttrsMgr::FontSizeTextAttr::FontSizeTextAttr(nsIFrame
* aRootFrame
,
425 : TTextAttr
<nscoord
>(!aFrame
) {
426 mDC
= aRootFrame
->PresContext()->DeviceContext();
428 mRootNativeValue
= aRootFrame
->StyleFont()->mSize
.ToAppUnits();
429 mIsRootDefined
= true;
432 mNativeValue
= aFrame
->StyleFont()->mSize
.ToAppUnits();
437 bool TextAttrsMgr::FontSizeTextAttr::GetValueFor(LocalAccessible
* aAccessible
,
439 nsIContent
* el
= nsCoreUtils::GetDOMElementFor(aAccessible
->GetContent());
441 nsIFrame
* frame
= el
->GetPrimaryFrame();
443 *aValue
= frame
->StyleFont()->mSize
.ToAppUnits();
450 void TextAttrsMgr::FontSizeTextAttr::ExposeValue(AccAttributes
* aAttributes
,
451 const nscoord
& aValue
) {
452 // Convert from nscoord to pt.
454 // Note: according to IA2, "The conversion doesn't have to be exact.
455 // The intent is to give the user a feel for the size of the text."
457 // ATK does not specify a unit and will likely follow IA2 here.
459 // XXX todo: consider sharing this code with layout module? (bug 474621)
460 float px
= NSAppUnitsToFloatPixels(aValue
, mozilla::AppUnitsPerCSSPixel());
461 // Each pt is 4/3 of a CSS pixel.
462 FontSize fontSize
{NS_lround(px
* 3 / 4)};
464 aAttributes
->SetAttribute(nsGkAtoms::font_size
, fontSize
);
467 ////////////////////////////////////////////////////////////////////////////////
469 ////////////////////////////////////////////////////////////////////////////////
471 TextAttrsMgr::FontStyleTextAttr::FontStyleTextAttr(nsIFrame
* aRootFrame
,
473 : TTextAttr
<FontSlantStyle
>(!aFrame
) {
474 mRootNativeValue
= aRootFrame
->StyleFont()->mFont
.style
;
475 mIsRootDefined
= true;
478 mNativeValue
= aFrame
->StyleFont()->mFont
.style
;
483 bool TextAttrsMgr::FontStyleTextAttr::GetValueFor(LocalAccessible
* aAccessible
,
484 FontSlantStyle
* aValue
) {
485 nsIContent
* elm
= nsCoreUtils::GetDOMElementFor(aAccessible
->GetContent());
487 nsIFrame
* frame
= elm
->GetPrimaryFrame();
489 *aValue
= frame
->StyleFont()->mFont
.style
;
496 void TextAttrsMgr::FontStyleTextAttr::ExposeValue(
497 AccAttributes
* aAttributes
, const FontSlantStyle
& aValue
) {
498 if (aValue
.IsNormal()) {
499 aAttributes
->SetAttribute(nsGkAtoms::font_style
, nsGkAtoms::normal
);
500 } else if (aValue
.IsItalic()) {
501 RefPtr
<nsAtom
> atom
= NS_Atomize("italic");
502 aAttributes
->SetAttribute(nsGkAtoms::font_style
, atom
);
504 auto angle
= aValue
.ObliqueAngle();
505 nsString
string(u
"oblique"_ns
);
506 if (angle
!= FontSlantStyle::kDefaultAngle
) {
507 string
.AppendLiteral(" ");
508 nsStyleUtil::AppendCSSNumber(angle
, string
);
509 string
.AppendLiteral("deg");
511 aAttributes
->SetAttribute(nsGkAtoms::font_style
, std::move(string
));
515 ////////////////////////////////////////////////////////////////////////////////
516 // FontWeightTextAttr
517 ////////////////////////////////////////////////////////////////////////////////
519 TextAttrsMgr::FontWeightTextAttr::FontWeightTextAttr(nsIFrame
* aRootFrame
,
521 : TTextAttr
<FontWeight
>(!aFrame
) {
522 mRootNativeValue
= GetFontWeight(aRootFrame
);
523 mIsRootDefined
= true;
526 mNativeValue
= GetFontWeight(aFrame
);
531 bool TextAttrsMgr::FontWeightTextAttr::GetValueFor(LocalAccessible
* aAccessible
,
532 FontWeight
* aValue
) {
533 nsIContent
* elm
= nsCoreUtils::GetDOMElementFor(aAccessible
->GetContent());
535 nsIFrame
* frame
= elm
->GetPrimaryFrame();
537 *aValue
= GetFontWeight(frame
);
544 void TextAttrsMgr::FontWeightTextAttr::ExposeValue(AccAttributes
* aAttributes
,
545 const FontWeight
& aValue
) {
546 aAttributes
->SetAttribute(nsGkAtoms::fontWeight
, aValue
.ToIntRounded());
549 FontWeight
TextAttrsMgr::FontWeightTextAttr::GetFontWeight(nsIFrame
* aFrame
) {
550 // nsFont::width isn't suitable here because it's necessary to expose real
551 // value of font weight (used font might not have some font weight values).
552 RefPtr
<nsFontMetrics
> fm
=
553 nsLayoutUtils::GetFontMetricsForFrame(aFrame
, 1.0f
);
555 gfxFontGroup
* fontGroup
= fm
->GetThebesFontGroup();
556 gfxFont
* font
= fontGroup
->GetFirstValidFont();
558 // When there doesn't exist a bold font in the family and so the rendering of
559 // a non-bold font face is changed so that the user sees what looks like a
560 // bold font, i.e. synthetic bolding is used. (Simply returns false on any
561 // platforms that don't use the multi-strike synthetic bolding.)
562 if (font
->ApplySyntheticBold()) {
563 return FontWeight::Bold();
566 // On Windows, font->GetStyle()->weight will give the same weight as
567 // fontEntry->Weight(), the weight of the first font in the font group,
568 // which may not be the weight of the font face used to render the
569 // characters. On Mac, font->GetStyle()->weight will just give the same
570 // number as getComputedStyle(). fontEntry->Weight() will give the weight
571 // range supported by the font face used, so we clamp the weight that was
572 // requested by style to what is actually supported by the font.
573 gfxFontEntry
* fontEntry
= font
->GetFontEntry();
574 return fontEntry
->Weight().Clamp(font
->GetStyle()->weight
);
577 ////////////////////////////////////////////////////////////////////////////////
578 // AutoGeneratedTextAttr
579 ////////////////////////////////////////////////////////////////////////////////
580 TextAttrsMgr::AutoGeneratedTextAttr::AutoGeneratedTextAttr(
581 HyperTextAccessible
* aHyperTextAcc
, LocalAccessible
* aAccessible
)
582 : TTextAttr
<bool>(!aAccessible
) {
583 mRootNativeValue
= false;
584 mIsRootDefined
= false;
587 mIsDefined
= mNativeValue
=
588 ((aAccessible
->NativeRole() == roles::STATICTEXT
) ||
589 (aAccessible
->NativeRole() == roles::LISTITEM_MARKER
));
593 bool TextAttrsMgr::AutoGeneratedTextAttr::GetValueFor(
594 LocalAccessible
* aAccessible
, bool* aValue
) {
595 return *aValue
= (aAccessible
->NativeRole() == roles::STATICTEXT
);
598 void TextAttrsMgr::AutoGeneratedTextAttr::ExposeValue(
599 AccAttributes
* aAttributes
, const bool& aValue
) {
600 aAttributes
->SetAttribute(nsGkAtoms::auto_generated
, aValue
);
603 ////////////////////////////////////////////////////////////////////////////////
605 ////////////////////////////////////////////////////////////////////////////////
607 TextAttrsMgr::TextDecorValue::TextDecorValue(nsIFrame
* aFrame
) {
608 const nsStyleTextReset
* textReset
= aFrame
->StyleTextReset();
609 mStyle
= textReset
->mTextDecorationStyle
;
610 mColor
= textReset
->mTextDecorationColor
.CalcColor(aFrame
);
612 textReset
->mTextDecorationLine
& (StyleTextDecorationLine::UNDERLINE
|
613 StyleTextDecorationLine::LINE_THROUGH
);
616 TextAttrsMgr::TextDecorTextAttr::TextDecorTextAttr(nsIFrame
* aRootFrame
,
618 : TTextAttr
<TextDecorValue
>(!aFrame
) {
619 mRootNativeValue
= TextDecorValue(aRootFrame
);
620 mIsRootDefined
= mRootNativeValue
.IsDefined();
623 mNativeValue
= TextDecorValue(aFrame
);
624 mIsDefined
= mNativeValue
.IsDefined();
628 bool TextAttrsMgr::TextDecorTextAttr::GetValueFor(LocalAccessible
* aAccessible
,
629 TextDecorValue
* aValue
) {
630 nsIContent
* elm
= nsCoreUtils::GetDOMElementFor(aAccessible
->GetContent());
632 nsIFrame
* frame
= elm
->GetPrimaryFrame();
634 *aValue
= TextDecorValue(frame
);
635 return aValue
->IsDefined();
641 void TextAttrsMgr::TextDecorTextAttr::ExposeValue(
642 AccAttributes
* aAttributes
, const TextDecorValue
& aValue
) {
643 if (aValue
.IsUnderline()) {
644 RefPtr
<nsAtom
> underlineStyle
=
645 StyleInfo::TextDecorationStyleToAtom(aValue
.Style());
646 aAttributes
->SetAttribute(nsGkAtoms::textUnderlineStyle
, underlineStyle
);
648 aAttributes
->SetAttribute(nsGkAtoms::textUnderlineColor
,
649 Color
{aValue
.Color()});
653 if (aValue
.IsLineThrough()) {
654 RefPtr
<nsAtom
> lineThroughStyle
=
655 StyleInfo::TextDecorationStyleToAtom(aValue
.Style());
656 aAttributes
->SetAttribute(nsGkAtoms::textLineThroughStyle
,
659 aAttributes
->SetAttribute(nsGkAtoms::textLineThroughColor
,
660 Color
{aValue
.Color()});
664 ////////////////////////////////////////////////////////////////////////////////
666 ////////////////////////////////////////////////////////////////////////////////
668 TextAttrsMgr::TextPosTextAttr::TextPosTextAttr(nsIFrame
* aRootFrame
,
670 : TTextAttr
<TextPosValue
>(!aFrame
) {
671 mRootNativeValue
= GetTextPosValue(aRootFrame
);
672 mIsRootDefined
= mRootNativeValue
!= eTextPosNone
;
675 mNativeValue
= GetTextPosValue(aFrame
);
676 mIsDefined
= mNativeValue
!= eTextPosNone
;
680 bool TextAttrsMgr::TextPosTextAttr::GetValueFor(LocalAccessible
* aAccessible
,
681 TextPosValue
* aValue
) {
682 nsIContent
* elm
= nsCoreUtils::GetDOMElementFor(aAccessible
->GetContent());
684 nsIFrame
* frame
= elm
->GetPrimaryFrame();
686 *aValue
= GetTextPosValue(frame
);
687 return *aValue
!= eTextPosNone
;
693 void TextAttrsMgr::TextPosTextAttr::ExposeValue(AccAttributes
* aAttributes
,
694 const TextPosValue
& aValue
) {
695 RefPtr
<nsAtom
> atom
= nullptr;
697 case eTextPosBaseline
:
698 atom
= nsGkAtoms::baseline
;
702 atom
= nsGkAtoms::sub
;
706 atom
= NS_Atomize("super");
714 aAttributes
->SetAttribute(nsGkAtoms::textPosition
, atom
);
718 TextAttrsMgr::TextPosValue
TextAttrsMgr::TextPosTextAttr::GetTextPosValue(
719 nsIFrame
* aFrame
) const {
720 const auto& verticalAlign
= aFrame
->StyleDisplay()->mVerticalAlign
;
721 if (verticalAlign
.IsKeyword()) {
722 switch (verticalAlign
.AsKeyword()) {
723 case StyleVerticalAlignKeyword::Baseline
:
724 return eTextPosBaseline
;
725 case StyleVerticalAlignKeyword::Sub
:
727 case StyleVerticalAlignKeyword::Super
:
728 return eTextPosSuper
;
729 // No good guess for the rest, so do not expose value of text-position
736 const auto& length
= verticalAlign
.AsLength();
737 if (length
.ConvertsToPercentage()) {
738 float percentValue
= length
.ToPercentage();
739 return percentValue
> 0
741 : (percentValue
< 0 ? eTextPosSub
: eTextPosBaseline
);
744 if (length
.ConvertsToLength()) {
745 nscoord coordValue
= length
.ToLength();
746 return coordValue
> 0 ? eTextPosSuper
747 : (coordValue
< 0 ? eTextPosSub
: eTextPosBaseline
);
750 if (const nsIContent
* content
= aFrame
->GetContent()) {
751 if (content
->IsHTMLElement(nsGkAtoms::sup
)) return eTextPosSuper
;
752 if (content
->IsHTMLElement(nsGkAtoms::sub
)) return eTextPosSub
;