|
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 } |