accessible/src/base/TextAttrs.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:f45cc53e880c
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/. */
5
6 #include "TextAttrs.h"
7
8 #include "Accessible-inl.h"
9 #include "nsAccUtils.h"
10 #include "nsCoreUtils.h"
11 #include "StyleInfo.h"
12
13 #include "gfxFont.h"
14 #include "nsFontMetrics.h"
15 #include "nsLayoutUtils.h"
16 #include "HyperTextAccessible.h"
17 #include "mozilla/AppUnits.h"
18 #include "mozilla/gfx/2D.h"
19
20 using namespace mozilla;
21 using namespace mozilla::a11y;
22
23 ////////////////////////////////////////////////////////////////////////////////
24 // TextAttrsMgr
25 ////////////////////////////////////////////////////////////////////////////////
26
27 void
28 TextAttrsMgr::GetAttributes(nsIPersistentProperties* aAttributes,
29 int32_t* aStartHTOffset,
30 int32_t* aEndHTOffset)
31 {
32 // 1. Hyper text accessible must be specified always.
33 // 2. Offset accessible and result hyper text offsets must be specified in
34 // the case of text attributes.
35 // 3. Offset accessible and result hyper text offsets must not be specified
36 // but include default text attributes flag and attributes list must be
37 // specified in the case of default text attributes.
38 NS_PRECONDITION(mHyperTextAcc &&
39 ((mOffsetAcc && mOffsetAccIdx != -1 &&
40 aStartHTOffset && aEndHTOffset) ||
41 (!mOffsetAcc && mOffsetAccIdx == -1 &&
42 !aStartHTOffset && !aEndHTOffset &&
43 mIncludeDefAttrs && aAttributes)),
44 "Wrong usage of TextAttrsMgr!");
45
46 // Embedded objects are combined into own range with empty attributes set.
47 if (mOffsetAcc && nsAccUtils::IsEmbeddedObject(mOffsetAcc)) {
48 for (int32_t childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
49 Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);
50 if (!nsAccUtils::IsEmbeddedObject(currAcc))
51 break;
52
53 (*aStartHTOffset)--;
54 }
55
56 uint32_t childCount = mHyperTextAcc->ChildCount();
57 for (uint32_t childIdx = mOffsetAccIdx + 1; childIdx < childCount;
58 childIdx++) {
59 Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);
60 if (!nsAccUtils::IsEmbeddedObject(currAcc))
61 break;
62
63 (*aEndHTOffset)++;
64 }
65
66 return;
67 }
68
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();
72 nsIFrame *rootFrame = mHyperTextAcc->GetFrame();
73 NS_ASSERTION(rootFrame, "No frame for accessible!");
74 if (!rootFrame)
75 return;
76
77 nsIContent *offsetNode = nullptr, *offsetElm = nullptr;
78 nsIFrame *frame = nullptr;
79 if (mOffsetAcc) {
80 offsetNode = mOffsetAcc->GetContent();
81 offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
82 NS_ASSERTION(offsetElm, "No element for offset accessible!");
83 if (!offsetElm)
84 return;
85 frame = offsetElm->GetPrimaryFrame();
86 }
87
88 // "language" text attribute
89 LangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
90
91 // "aria-invalid" text attribute
92 InvalidTextAttr invalidTextAttr(hyperTextElm, offsetNode);
93
94 // "background-color" text attribute
95 BGColorTextAttr bgColorTextAttr(rootFrame, frame);
96
97 // "color" text attribute
98 ColorTextAttr colorTextAttr(rootFrame, frame);
99
100 // "font-family" text attribute
101 FontFamilyTextAttr fontFamilyTextAttr(rootFrame, frame);
102
103 // "font-size" text attribute
104 FontSizeTextAttr fontSizeTextAttr(rootFrame, frame);
105
106 // "font-style" text attribute
107 FontStyleTextAttr fontStyleTextAttr(rootFrame, frame);
108
109 // "font-weight" text attribute
110 FontWeightTextAttr fontWeightTextAttr(rootFrame, frame);
111
112 // "auto-generated" text attribute
113 AutoGeneratedTextAttr autoGenTextAttr(mHyperTextAcc, mOffsetAcc);
114
115 // "text-underline(line-through)-style(color)" text attributes
116 TextDecorTextAttr textDecorTextAttr(rootFrame, frame);
117
118 // "text-position" text attribute
119 TextPosTextAttr textPosTextAttr(rootFrame, frame);
120
121 TextAttr* attrArray[] =
122 {
123 &langTextAttr,
124 &invalidTextAttr,
125 &bgColorTextAttr,
126 &colorTextAttr,
127 &fontFamilyTextAttr,
128 &fontSizeTextAttr,
129 &fontStyleTextAttr,
130 &fontWeightTextAttr,
131 &autoGenTextAttr,
132 &textDecorTextAttr,
133 &textPosTextAttr
134 };
135
136 // Expose text attributes if applicable.
137 if (aAttributes) {
138 for (uint32_t idx = 0; idx < ArrayLength(attrArray); idx++)
139 attrArray[idx]->Expose(aAttributes, mIncludeDefAttrs);
140 }
141
142 // Expose text attributes range where they are applied if applicable.
143 if (mOffsetAcc)
144 GetRange(attrArray, ArrayLength(attrArray), aStartHTOffset, aEndHTOffset);
145 }
146
147 void
148 TextAttrsMgr::GetRange(TextAttr* aAttrArray[], uint32_t aAttrArrayLen,
149 int32_t* aStartHTOffset, int32_t* aEndHTOffset)
150 {
151 // Navigate backward from anchor accessible to find start offset.
152 for (int32_t childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
153 Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);
154
155 // Stop on embedded accessible since embedded accessibles are combined into
156 // own range.
157 if (nsAccUtils::IsEmbeddedObject(currAcc))
158 break;
159
160 bool offsetFound = false;
161 for (uint32_t attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
162 TextAttr* textAttr = aAttrArray[attrIdx];
163 if (!textAttr->Equal(currAcc)) {
164 offsetFound = true;
165 break;
166 }
167 }
168
169 if (offsetFound)
170 break;
171
172 *(aStartHTOffset) -= nsAccUtils::TextLength(currAcc);
173 }
174
175 // Navigate forward from anchor accessible to find end offset.
176 uint32_t childLen = mHyperTextAcc->ChildCount();
177 for (uint32_t childIdx = mOffsetAccIdx + 1; childIdx < childLen; childIdx++) {
178 Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);
179 if (nsAccUtils::IsEmbeddedObject(currAcc))
180 break;
181
182 bool offsetFound = false;
183 for (uint32_t attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
184 TextAttr* textAttr = aAttrArray[attrIdx];
185
186 // Alter the end offset when text attribute changes its value and stop
187 // the search.
188 if (!textAttr->Equal(currAcc)) {
189 offsetFound = true;
190 break;
191 }
192 }
193
194 if (offsetFound)
195 break;
196
197 (*aEndHTOffset) += nsAccUtils::TextLength(currAcc);
198 }
199 }
200
201
202 ////////////////////////////////////////////////////////////////////////////////
203 // LangTextAttr
204 ////////////////////////////////////////////////////////////////////////////////
205
206 TextAttrsMgr::LangTextAttr::
207 LangTextAttr(HyperTextAccessible* aRoot,
208 nsIContent* aRootElm, nsIContent* aElm) :
209 TTextAttr<nsString>(!aElm), mRootContent(aRootElm)
210 {
211 aRoot->Language(mRootNativeValue);
212 mIsRootDefined = !mRootNativeValue.IsEmpty();
213
214 if (aElm) {
215 nsCoreUtils::GetLanguageFor(aElm, mRootContent, mNativeValue);
216 mIsDefined = !mNativeValue.IsEmpty();
217 }
218 }
219
220 TextAttrsMgr::LangTextAttr::
221 ~LangTextAttr() {}
222
223 bool
224 TextAttrsMgr::LangTextAttr::
225 GetValueFor(Accessible* aAccessible, nsString* aValue)
226 {
227 nsCoreUtils::GetLanguageFor(aAccessible->GetContent(), mRootContent, *aValue);
228 return !aValue->IsEmpty();
229 }
230
231 void
232 TextAttrsMgr::LangTextAttr::
233 ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue)
234 {
235 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::language, aValue);
236 }
237
238 ////////////////////////////////////////////////////////////////////////////////
239 // InvalidTextAttr
240 ////////////////////////////////////////////////////////////////////////////////
241
242 TextAttrsMgr::InvalidTextAttr::
243 InvalidTextAttr(nsIContent* aRootElm, nsIContent* aElm) :
244 TTextAttr<uint32_t>(!aElm), mRootElm(aRootElm)
245 {
246 mIsRootDefined = GetValue(mRootElm, &mRootNativeValue);
247 if (aElm)
248 mIsDefined = GetValue(aElm, &mNativeValue);
249 }
250
251 bool
252 TextAttrsMgr::InvalidTextAttr::
253 GetValueFor(Accessible* aAccessible, uint32_t* aValue)
254 {
255 nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
256 return elm ? GetValue(elm, aValue) : false;
257 }
258
259 void
260 TextAttrsMgr::InvalidTextAttr::
261 ExposeValue(nsIPersistentProperties* aAttributes, const uint32_t& aValue)
262 {
263 switch (aValue) {
264 case eFalse:
265 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::invalid,
266 NS_LITERAL_STRING("false"));
267 break;
268
269 case eGrammar:
270 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::invalid,
271 NS_LITERAL_STRING("grammar"));
272 break;
273
274 case eSpelling:
275 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::invalid,
276 NS_LITERAL_STRING("spelling"));
277 break;
278
279 case eTrue:
280 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::invalid,
281 NS_LITERAL_STRING("true"));
282 break;
283 }
284 }
285
286 bool
287 TextAttrsMgr::InvalidTextAttr::
288 GetValue(nsIContent* aElm, uint32_t* aValue)
289 {
290 nsIContent* elm = aElm;
291 do {
292 if (nsAccUtils::HasDefinedARIAToken(elm, nsGkAtoms::aria_invalid)) {
293 static nsIContent::AttrValuesArray tokens[] =
294 { &nsGkAtoms::_false, &nsGkAtoms::grammar, &nsGkAtoms::spelling,
295 nullptr };
296
297 int32_t idx = elm->FindAttrValueIn(kNameSpaceID_None,
298 nsGkAtoms::aria_invalid, tokens,
299 eCaseMatters);
300 switch (idx) {
301 case 0:
302 *aValue = eFalse;
303 return true;
304 case 1:
305 *aValue = eGrammar;
306 return true;
307 case 2:
308 *aValue = eSpelling;
309 return true;
310 default:
311 *aValue = eTrue;
312 return true;
313 }
314 }
315 } while ((elm = elm->GetParent()) && elm != mRootElm);
316
317 return false;
318 }
319
320
321 ////////////////////////////////////////////////////////////////////////////////
322 // BGColorTextAttr
323 ////////////////////////////////////////////////////////////////////////////////
324
325 TextAttrsMgr::BGColorTextAttr::
326 BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
327 TTextAttr<nscolor>(!aFrame), mRootFrame(aRootFrame)
328 {
329 mIsRootDefined = GetColor(mRootFrame, &mRootNativeValue);
330 if (aFrame)
331 mIsDefined = GetColor(aFrame, &mNativeValue);
332 }
333
334 bool
335 TextAttrsMgr::BGColorTextAttr::
336 GetValueFor(Accessible* aAccessible, nscolor* aValue)
337 {
338 nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
339 nsIFrame* frame = elm->GetPrimaryFrame();
340 return frame ? GetColor(frame, aValue) : false;
341 }
342
343 void
344 TextAttrsMgr::BGColorTextAttr::
345 ExposeValue(nsIPersistentProperties* aAttributes, const nscolor& aValue)
346 {
347 nsAutoString formattedValue;
348 StyleInfo::FormatColor(aValue, formattedValue);
349 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::backgroundColor,
350 formattedValue);
351 }
352
353 bool
354 TextAttrsMgr::BGColorTextAttr::
355 GetColor(nsIFrame* aFrame, nscolor* aColor)
356 {
357 const nsStyleBackground* styleBackground = aFrame->StyleBackground();
358
359 if (NS_GET_A(styleBackground->mBackgroundColor) > 0) {
360 *aColor = styleBackground->mBackgroundColor;
361 return true;
362 }
363
364 nsIFrame *parentFrame = aFrame->GetParent();
365 if (!parentFrame) {
366 *aColor = aFrame->PresContext()->DefaultBackgroundColor();
367 return true;
368 }
369
370 // Each frame of parents chain for the initially passed 'aFrame' has
371 // transparent background color. So background color isn't changed from
372 // 'mRootFrame' to initially passed 'aFrame'.
373 if (parentFrame == mRootFrame)
374 return false;
375
376 return GetColor(parentFrame, aColor);
377 }
378
379
380 ////////////////////////////////////////////////////////////////////////////////
381 // ColorTextAttr
382 ////////////////////////////////////////////////////////////////////////////////
383
384 TextAttrsMgr::ColorTextAttr::
385 ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
386 TTextAttr<nscolor>(!aFrame)
387 {
388 mRootNativeValue = aRootFrame->StyleColor()->mColor;
389 mIsRootDefined = true;
390
391 if (aFrame) {
392 mNativeValue = aFrame->StyleColor()->mColor;
393 mIsDefined = true;
394 }
395 }
396
397 bool
398 TextAttrsMgr::ColorTextAttr::
399 GetValueFor(Accessible* aAccessible, nscolor* aValue)
400 {
401 nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
402 nsIFrame* frame = elm->GetPrimaryFrame();
403 if (frame) {
404 *aValue = frame->StyleColor()->mColor;
405 return true;
406 }
407
408 return false;
409 }
410
411 void
412 TextAttrsMgr::ColorTextAttr::
413 ExposeValue(nsIPersistentProperties* aAttributes, const nscolor& aValue)
414 {
415 nsAutoString formattedValue;
416 StyleInfo::FormatColor(aValue, formattedValue);
417 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::color, formattedValue);
418 }
419
420
421 ////////////////////////////////////////////////////////////////////////////////
422 // FontFamilyTextAttr
423 ////////////////////////////////////////////////////////////////////////////////
424
425 TextAttrsMgr::FontFamilyTextAttr::
426 FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
427 TTextAttr<nsString>(!aFrame)
428 {
429 mIsRootDefined = GetFontFamily(aRootFrame, mRootNativeValue);
430
431 if (aFrame)
432 mIsDefined = GetFontFamily(aFrame, mNativeValue);
433 }
434
435 bool
436 TextAttrsMgr::FontFamilyTextAttr::
437 GetValueFor(Accessible* aAccessible, nsString* aValue)
438 {
439 nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
440 nsIFrame* frame = elm->GetPrimaryFrame();
441 return frame ? GetFontFamily(frame, *aValue) : false;
442 }
443
444 void
445 TextAttrsMgr::FontFamilyTextAttr::
446 ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue)
447 {
448 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_family, aValue);
449 }
450
451 bool
452 TextAttrsMgr::FontFamilyTextAttr::
453 GetFontFamily(nsIFrame* aFrame, nsString& aFamily)
454 {
455 nsRefPtr<nsFontMetrics> fm;
456 nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
457
458 gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
459 gfxFont* font = fontGroup->GetFontAt(0);
460 gfxFontEntry* fontEntry = font->GetFontEntry();
461 aFamily = fontEntry->FamilyName();
462 return true;
463 }
464
465
466 ////////////////////////////////////////////////////////////////////////////////
467 // FontSizeTextAttr
468 ////////////////////////////////////////////////////////////////////////////////
469
470 TextAttrsMgr::FontSizeTextAttr::
471 FontSizeTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
472 TTextAttr<nscoord>(!aFrame)
473 {
474 mDC = aRootFrame->PresContext()->DeviceContext();
475
476 mRootNativeValue = aRootFrame->StyleFont()->mSize;
477 mIsRootDefined = true;
478
479 if (aFrame) {
480 mNativeValue = aFrame->StyleFont()->mSize;
481 mIsDefined = true;
482 }
483 }
484
485 bool
486 TextAttrsMgr::FontSizeTextAttr::
487 GetValueFor(Accessible* aAccessible, nscoord* aValue)
488 {
489 nsIContent* content = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
490 nsIFrame* frame = content->GetPrimaryFrame();
491 if (frame) {
492 *aValue = frame->StyleFont()->mSize;
493 return true;
494 }
495
496 return false;
497 }
498
499 void
500 TextAttrsMgr::FontSizeTextAttr::
501 ExposeValue(nsIPersistentProperties* aAttributes, const nscoord& aValue)
502 {
503 // Convert from nscoord to pt.
504 //
505 // Note: according to IA2, "The conversion doesn't have to be exact.
506 // The intent is to give the user a feel for the size of the text."
507 //
508 // ATK does not specify a unit and will likely follow IA2 here.
509 //
510 // XXX todo: consider sharing this code with layout module? (bug 474621)
511 float px =
512 NSAppUnitsToFloatPixels(aValue, mozilla::AppUnitsPerCSSPixel());
513 // Each pt is 4/3 of a CSS pixel.
514 int pts = NS_lround(px*3/4);
515
516 nsAutoString value;
517 value.AppendInt(pts);
518 value.Append(NS_LITERAL_STRING("pt"));
519
520 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_size, value);
521 }
522
523
524 ////////////////////////////////////////////////////////////////////////////////
525 // FontStyleTextAttr
526 ////////////////////////////////////////////////////////////////////////////////
527
528 TextAttrsMgr::FontStyleTextAttr::
529 FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
530 TTextAttr<nscoord>(!aFrame)
531 {
532 mRootNativeValue = aRootFrame->StyleFont()->mFont.style;
533 mIsRootDefined = true;
534
535 if (aFrame) {
536 mNativeValue = aFrame->StyleFont()->mFont.style;
537 mIsDefined = true;
538 }
539 }
540
541 bool
542 TextAttrsMgr::FontStyleTextAttr::
543 GetValueFor(Accessible* aAccessible, nscoord* aValue)
544 {
545 nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
546 nsIFrame* frame = elm->GetPrimaryFrame();
547 if (frame) {
548 *aValue = frame->StyleFont()->mFont.style;
549 return true;
550 }
551
552 return false;
553 }
554
555 void
556 TextAttrsMgr::FontStyleTextAttr::
557 ExposeValue(nsIPersistentProperties* aAttributes, const nscoord& aValue)
558 {
559 nsAutoString formattedValue;
560 StyleInfo::FormatFontStyle(aValue, formattedValue);
561
562 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_style, formattedValue);
563 }
564
565
566 ////////////////////////////////////////////////////////////////////////////////
567 // FontWeightTextAttr
568 ////////////////////////////////////////////////////////////////////////////////
569
570 TextAttrsMgr::FontWeightTextAttr::
571 FontWeightTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
572 TTextAttr<int32_t>(!aFrame)
573 {
574 mRootNativeValue = GetFontWeight(aRootFrame);
575 mIsRootDefined = true;
576
577 if (aFrame) {
578 mNativeValue = GetFontWeight(aFrame);
579 mIsDefined = true;
580 }
581 }
582
583 bool
584 TextAttrsMgr::FontWeightTextAttr::
585 GetValueFor(Accessible* aAccessible, int32_t* aValue)
586 {
587 nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
588 nsIFrame* frame = elm->GetPrimaryFrame();
589 if (frame) {
590 *aValue = GetFontWeight(frame);
591 return true;
592 }
593
594 return false;
595 }
596
597 void
598 TextAttrsMgr::FontWeightTextAttr::
599 ExposeValue(nsIPersistentProperties* aAttributes, const int32_t& aValue)
600 {
601 nsAutoString formattedValue;
602 formattedValue.AppendInt(aValue);
603
604 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::fontWeight, formattedValue);
605 }
606
607 int32_t
608 TextAttrsMgr::FontWeightTextAttr::
609 GetFontWeight(nsIFrame* aFrame)
610 {
611 // nsFont::width isn't suitable here because it's necessary to expose real
612 // value of font weight (used font might not have some font weight values).
613 nsRefPtr<nsFontMetrics> fm;
614 nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
615
616 gfxFontGroup *fontGroup = fm->GetThebesFontGroup();
617 gfxFont *font = fontGroup->GetFontAt(0);
618
619 // When there doesn't exist a bold font in the family and so the rendering of
620 // a non-bold font face is changed so that the user sees what looks like a
621 // bold font, i.e. synthetic bolding is used. IsSyntheticBold method is only
622 // needed on Mac, but it is "safe" to use on all platforms. (For non-Mac
623 // platforms it always return false.)
624 if (font->IsSyntheticBold())
625 return 700;
626
627 #if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
628 // On Linux, font->GetStyle()->weight will give the absolute weight requested
629 // of the font face. The Linux code uses the gfxFontEntry constructor which
630 // doesn't initialize the weight field.
631 return font->GetStyle()->weight;
632 #else
633 // On Windows, font->GetStyle()->weight will give the same weight as
634 // fontEntry->Weight(), the weight of the first font in the font group, which
635 // may not be the weight of the font face used to render the characters.
636 // On Mac, font->GetStyle()->weight will just give the same number as
637 // getComputedStyle(). fontEntry->Weight() will give the weight of the font
638 // face used.
639 gfxFontEntry *fontEntry = font->GetFontEntry();
640 return fontEntry->Weight();
641 #endif
642 }
643
644 ////////////////////////////////////////////////////////////////////////////////
645 // AutoGeneratedTextAttr
646 ////////////////////////////////////////////////////////////////////////////////
647 TextAttrsMgr::AutoGeneratedTextAttr::
648 AutoGeneratedTextAttr(HyperTextAccessible* aHyperTextAcc,
649 Accessible* aAccessible) :
650 TTextAttr<bool>(!aAccessible)
651 {
652 mRootNativeValue = false;
653 mIsRootDefined = false;
654
655 if (aAccessible)
656 mIsDefined = mNativeValue = (aAccessible->NativeRole() == roles::STATICTEXT);
657 }
658
659 bool
660 TextAttrsMgr::AutoGeneratedTextAttr::
661 GetValueFor(Accessible* aAccessible, bool* aValue)
662 {
663 return *aValue = (aAccessible->NativeRole() == roles::STATICTEXT);
664 }
665
666 void
667 TextAttrsMgr::AutoGeneratedTextAttr::
668 ExposeValue(nsIPersistentProperties* aAttributes, const bool& aValue)
669 {
670 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::auto_generated,
671 aValue ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"));
672 }
673
674
675 ////////////////////////////////////////////////////////////////////////////////
676 // TextDecorTextAttr
677 ////////////////////////////////////////////////////////////////////////////////
678
679 TextAttrsMgr::TextDecorValue::
680 TextDecorValue(nsIFrame* aFrame)
681 {
682 const nsStyleTextReset* textReset = aFrame->StyleTextReset();
683 mStyle = textReset->GetDecorationStyle();
684
685 bool isForegroundColor = false;
686 textReset->GetDecorationColor(mColor, isForegroundColor);
687 if (isForegroundColor)
688 mColor = aFrame->StyleColor()->mColor;
689
690 mLine = textReset->mTextDecorationLine &
691 (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE |
692 NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH);
693 }
694
695 TextAttrsMgr::TextDecorTextAttr::
696 TextDecorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
697 TTextAttr<TextDecorValue>(!aFrame)
698 {
699 mRootNativeValue = TextDecorValue(aRootFrame);
700 mIsRootDefined = mRootNativeValue.IsDefined();
701
702 if (aFrame) {
703 mNativeValue = TextDecorValue(aFrame);
704 mIsDefined = mNativeValue.IsDefined();
705 }
706 }
707
708 bool
709 TextAttrsMgr::TextDecorTextAttr::
710 GetValueFor(Accessible* aAccessible, TextDecorValue* aValue)
711 {
712 nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
713 nsIFrame* frame = elm->GetPrimaryFrame();
714 if (frame) {
715 *aValue = TextDecorValue(frame);
716 return aValue->IsDefined();
717 }
718
719 return false;
720 }
721
722 void
723 TextAttrsMgr::TextDecorTextAttr::
724 ExposeValue(nsIPersistentProperties* aAttributes, const TextDecorValue& aValue)
725 {
726 if (aValue.IsUnderline()) {
727 nsAutoString formattedStyle;
728 StyleInfo::FormatTextDecorationStyle(aValue.Style(), formattedStyle);
729 nsAccUtils::SetAccAttr(aAttributes,
730 nsGkAtoms::textUnderlineStyle,
731 formattedStyle);
732
733 nsAutoString formattedColor;
734 StyleInfo::FormatColor(aValue.Color(), formattedColor);
735 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textUnderlineColor,
736 formattedColor);
737 return;
738 }
739
740 if (aValue.IsLineThrough()) {
741 nsAutoString formattedStyle;
742 StyleInfo::FormatTextDecorationStyle(aValue.Style(), formattedStyle);
743 nsAccUtils::SetAccAttr(aAttributes,
744 nsGkAtoms::textLineThroughStyle,
745 formattedStyle);
746
747 nsAutoString formattedColor;
748 StyleInfo::FormatColor(aValue.Color(), formattedColor);
749 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textLineThroughColor,
750 formattedColor);
751 }
752 }
753
754 ////////////////////////////////////////////////////////////////////////////////
755 // TextPosTextAttr
756 ////////////////////////////////////////////////////////////////////////////////
757
758 TextAttrsMgr::TextPosTextAttr::
759 TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
760 TTextAttr<TextPosValue>(!aFrame)
761 {
762 mRootNativeValue = GetTextPosValue(aRootFrame);
763 mIsRootDefined = mRootNativeValue != eTextPosNone;
764
765 if (aFrame) {
766 mNativeValue = GetTextPosValue(aFrame);
767 mIsDefined = mNativeValue != eTextPosNone;
768 }
769 }
770
771 bool
772 TextAttrsMgr::TextPosTextAttr::
773 GetValueFor(Accessible* aAccessible, TextPosValue* aValue)
774 {
775 nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
776 nsIFrame* frame = elm->GetPrimaryFrame();
777 if (frame) {
778 *aValue = GetTextPosValue(frame);
779 return *aValue != eTextPosNone;
780 }
781
782 return false;
783 }
784
785 void
786 TextAttrsMgr::TextPosTextAttr::
787 ExposeValue(nsIPersistentProperties* aAttributes, const TextPosValue& aValue)
788 {
789 switch (aValue) {
790 case eTextPosBaseline:
791 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
792 NS_LITERAL_STRING("baseline"));
793 break;
794
795 case eTextPosSub:
796 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
797 NS_LITERAL_STRING("sub"));
798 break;
799
800 case eTextPosSuper:
801 nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
802 NS_LITERAL_STRING("super"));
803 break;
804
805 case eTextPosNone:
806 break;
807 }
808 }
809
810 TextAttrsMgr::TextPosValue
811 TextAttrsMgr::TextPosTextAttr::
812 GetTextPosValue(nsIFrame* aFrame) const
813 {
814 const nsStyleCoord& styleCoord = aFrame->StyleTextReset()->mVerticalAlign;
815 switch (styleCoord.GetUnit()) {
816 case eStyleUnit_Enumerated:
817 switch (styleCoord.GetIntValue()) {
818 case NS_STYLE_VERTICAL_ALIGN_BASELINE:
819 return eTextPosBaseline;
820 case NS_STYLE_VERTICAL_ALIGN_SUB:
821 return eTextPosSub;
822 case NS_STYLE_VERTICAL_ALIGN_SUPER:
823 return eTextPosSuper;
824
825 // No good guess for these:
826 // NS_STYLE_VERTICAL_ALIGN_TOP
827 // NS_STYLE_VERTICAL_ALIGN_TEXT_TOP
828 // NS_STYLE_VERTICAL_ALIGN_MIDDLE
829 // NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM
830 // NS_STYLE_VERTICAL_ALIGN_BOTTOM
831 // NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE
832 // Do not expose value of text-position attribute.
833
834 default:
835 break;
836 }
837 return eTextPosNone;
838
839 case eStyleUnit_Percent:
840 {
841 float percentValue = styleCoord.GetPercentValue();
842 return percentValue > 0 ?
843 eTextPosSuper :
844 (percentValue < 0 ? eTextPosSub : eTextPosBaseline);
845 }
846
847 case eStyleUnit_Coord:
848 {
849 nscoord coordValue = styleCoord.GetCoordValue();
850 return coordValue > 0 ?
851 eTextPosSuper :
852 (coordValue < 0 ? eTextPosSub : eTextPosBaseline);
853 }
854
855 case eStyleUnit_Null:
856 case eStyleUnit_Normal:
857 case eStyleUnit_Auto:
858 case eStyleUnit_None:
859 case eStyleUnit_Factor:
860 case eStyleUnit_Degree:
861 case eStyleUnit_Grad:
862 case eStyleUnit_Radian:
863 case eStyleUnit_Turn:
864 case eStyleUnit_FlexFraction:
865 case eStyleUnit_Integer:
866 case eStyleUnit_Calc:
867 break;
868 }
869
870 const nsIContent* content = aFrame->GetContent();
871 if (content && content->IsHTML()) {
872 const nsIAtom* tagName = content->Tag();
873 if (tagName == nsGkAtoms::sup)
874 return eTextPosSuper;
875 if (tagName == nsGkAtoms::sub)
876 return eTextPosSub;
877 }
878
879 return eTextPosNone;
880 }

mercurial