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