1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is mozilla.org code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Mozilla Foundation.
19 : * Portions created by the Initial Developer are Copyright (C) 2007
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Alexander Surkov <surkov.alexander@gmail.com> (original author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "TextAttrs.h"
40 :
41 : #include "nsAccUtils.h"
42 : #include "nsCoreUtils.h"
43 : #include "nsHyperTextAccessibleWrap.h"
44 : #include "StyleInfo.h"
45 :
46 : #include "gfxFont.h"
47 : #include "gfxUserFontSet.h"
48 : #include "nsFontMetrics.h"
49 : #include "nsLayoutUtils.h"
50 :
51 : using namespace mozilla;
52 : using namespace mozilla::a11y;
53 :
54 : ////////////////////////////////////////////////////////////////////////////////
55 : // TextAttrsMgr
56 : ////////////////////////////////////////////////////////////////////////////////
57 :
58 : void
59 0 : TextAttrsMgr::GetAttributes(nsIPersistentProperties* aAttributes,
60 : PRInt32* aStartHTOffset,
61 : PRInt32* aEndHTOffset)
62 : {
63 : // 1. Hyper text accessible must be specified always.
64 : // 2. Offset accessible and result hyper text offsets must be specified in
65 : // the case of text attributes.
66 : // 3. Offset accessible and result hyper text offsets must not be specified
67 : // but include default text attributes flag and attributes list must be
68 : // specified in the case of default text attributes.
69 0 : NS_PRECONDITION(mHyperTextAcc &&
70 : ((mOffsetAcc && mOffsetAccIdx != -1 &&
71 : aStartHTOffset && aEndHTOffset) ||
72 : (!mOffsetAcc && mOffsetAccIdx == -1 &&
73 : !aStartHTOffset && !aEndHTOffset &&
74 : mIncludeDefAttrs && aAttributes)),
75 : "Wrong usage of TextAttrsMgr!");
76 :
77 : // Embedded objects are combined into own range with empty attributes set.
78 0 : if (mOffsetAcc && nsAccUtils::IsEmbeddedObject(mOffsetAcc)) {
79 0 : for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
80 0 : nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
81 0 : if (!nsAccUtils::IsEmbeddedObject(currAcc))
82 0 : break;
83 :
84 0 : (*aStartHTOffset)--;
85 : }
86 :
87 0 : PRInt32 childCount = mHyperTextAcc->GetChildCount();
88 0 : for (PRInt32 childIdx = mOffsetAccIdx + 1; childIdx < childCount;
89 : childIdx++) {
90 0 : nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
91 0 : if (!nsAccUtils::IsEmbeddedObject(currAcc))
92 0 : break;
93 :
94 0 : (*aEndHTOffset)++;
95 : }
96 :
97 0 : return;
98 : }
99 :
100 : // Get the content and frame of the accessible. In the case of document
101 : // accessible it's role content and root frame.
102 0 : nsIContent *hyperTextElm = mHyperTextAcc->GetContent();
103 0 : nsIFrame *rootFrame = mHyperTextAcc->GetFrame();
104 0 : NS_ASSERTION(rootFrame, "No frame for accessible!");
105 0 : if (!rootFrame)
106 0 : return;
107 :
108 0 : nsIContent *offsetNode = nsnull, *offsetElm = nsnull;
109 0 : nsIFrame *frame = nsnull;
110 0 : if (mOffsetAcc) {
111 0 : offsetNode = mOffsetAcc->GetContent();
112 0 : offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
113 0 : frame = offsetElm->GetPrimaryFrame();
114 : }
115 :
116 : // "language" text attribute
117 0 : LangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
118 :
119 : // "background-color" text attribute
120 0 : BGColorTextAttr bgColorTextAttr(rootFrame, frame);
121 :
122 : // "color" text attribute
123 0 : ColorTextAttr colorTextAttr(rootFrame, frame);
124 :
125 : // "font-family" text attribute
126 0 : FontFamilyTextAttr fontFamilyTextAttr(rootFrame, frame);
127 :
128 : // "font-size" text attribute
129 0 : FontSizeTextAttr fontSizeTextAttr(rootFrame, frame);
130 :
131 : // "font-style" text attribute
132 0 : FontStyleTextAttr fontStyleTextAttr(rootFrame, frame);
133 :
134 : // "font-weight" text attribute
135 0 : FontWeightTextAttr fontWeightTextAttr(rootFrame, frame);
136 :
137 : // "text-underline(line-through)-style(color)" text attributes
138 0 : TextDecorTextAttr textDecorTextAttr(rootFrame, frame);
139 :
140 : // "text-position" text attribute
141 0 : TextPosTextAttr textPosTextAttr(rootFrame, frame);
142 :
143 : TextAttr* attrArray[] =
144 : {
145 : &langTextAttr,
146 : &bgColorTextAttr,
147 : &colorTextAttr,
148 : &fontFamilyTextAttr,
149 : &fontSizeTextAttr,
150 : &fontStyleTextAttr,
151 : &fontWeightTextAttr,
152 : &textDecorTextAttr,
153 : &textPosTextAttr
154 0 : };
155 :
156 : // Expose text attributes if applicable.
157 0 : if (aAttributes) {
158 0 : for (PRUint32 idx = 0; idx < ArrayLength(attrArray); idx++)
159 0 : attrArray[idx]->Expose(aAttributes, mIncludeDefAttrs);
160 : }
161 :
162 : // Expose text attributes range where they are applied if applicable.
163 0 : if (mOffsetAcc)
164 0 : GetRange(attrArray, ArrayLength(attrArray), aStartHTOffset, aEndHTOffset);
165 : }
166 :
167 : void
168 0 : TextAttrsMgr::GetRange(TextAttr* aAttrArray[], PRUint32 aAttrArrayLen,
169 : PRInt32* aStartHTOffset, PRInt32* aEndHTOffset)
170 : {
171 : // Navigate backward from anchor accessible to find start offset.
172 0 : for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
173 0 : nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
174 :
175 : // Stop on embedded accessible since embedded accessibles are combined into
176 : // own range.
177 0 : if (nsAccUtils::IsEmbeddedObject(currAcc))
178 0 : break;
179 :
180 0 : nsIContent* currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent());
181 0 : if (!currElm)
182 0 : return;
183 :
184 0 : bool offsetFound = false;
185 0 : for (PRUint32 attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
186 0 : TextAttr* textAttr = aAttrArray[attrIdx];
187 0 : if (!textAttr->Equal(currElm)) {
188 0 : offsetFound = true;
189 0 : break;
190 : }
191 : }
192 :
193 0 : if (offsetFound)
194 0 : break;
195 :
196 0 : *(aStartHTOffset) -= nsAccUtils::TextLength(currAcc);
197 : }
198 :
199 : // Navigate forward from anchor accessible to find end offset.
200 0 : PRInt32 childLen = mHyperTextAcc->GetChildCount();
201 0 : for (PRInt32 childIdx = mOffsetAccIdx + 1; childIdx < childLen; childIdx++) {
202 0 : nsAccessible *currAcc = mHyperTextAcc->GetChildAt(childIdx);
203 0 : if (nsAccUtils::IsEmbeddedObject(currAcc))
204 0 : break;
205 :
206 0 : nsIContent* currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent());
207 0 : if (!currElm)
208 0 : return;
209 :
210 0 : bool offsetFound = false;
211 0 : for (PRUint32 attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
212 0 : TextAttr* textAttr = aAttrArray[attrIdx];
213 :
214 : // Alter the end offset when text attribute changes its value and stop
215 : // the search.
216 0 : if (!textAttr->Equal(currElm)) {
217 0 : offsetFound = true;
218 0 : break;
219 : }
220 : }
221 :
222 0 : if (offsetFound)
223 0 : break;
224 :
225 0 : (*aEndHTOffset) += nsAccUtils::TextLength(currAcc);
226 : }
227 : }
228 :
229 :
230 : ////////////////////////////////////////////////////////////////////////////////
231 : // LangTextAttr
232 : ////////////////////////////////////////////////////////////////////////////////
233 :
234 0 : TextAttrsMgr::LangTextAttr::
235 : LangTextAttr(nsHyperTextAccessible* aRoot,
236 : nsIContent* aRootElm, nsIContent* aElm) :
237 0 : TTextAttr<nsString>(!aElm), mRootContent(aRootElm)
238 : {
239 0 : aRoot->Language(mRootNativeValue);
240 0 : mIsRootDefined = !mRootNativeValue.IsEmpty();
241 :
242 0 : if (aElm)
243 0 : mIsDefined = GetLang(aElm, mNativeValue);
244 0 : }
245 :
246 : bool
247 0 : TextAttrsMgr::LangTextAttr::
248 : GetValueFor(nsIContent* aElm, nsString* aValue)
249 : {
250 0 : return GetLang(aElm, *aValue);
251 : }
252 :
253 : void
254 0 : TextAttrsMgr::LangTextAttr::
255 : ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue)
256 : {
257 0 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::language, aValue);
258 0 : }
259 :
260 : bool
261 0 : TextAttrsMgr::LangTextAttr::
262 : GetLang(nsIContent* aElm, nsAString& aLang)
263 : {
264 0 : nsCoreUtils::GetLanguageFor(aElm, mRootContent, aLang);
265 0 : return !aLang.IsEmpty();
266 : }
267 :
268 :
269 : ////////////////////////////////////////////////////////////////////////////////
270 : // BGColorTextAttr
271 : ////////////////////////////////////////////////////////////////////////////////
272 :
273 0 : TextAttrsMgr::BGColorTextAttr::
274 : BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
275 0 : TTextAttr<nscolor>(!aFrame), mRootFrame(aRootFrame)
276 : {
277 0 : mIsRootDefined = GetColor(mRootFrame, &mRootNativeValue);
278 0 : if (aFrame)
279 0 : mIsDefined = GetColor(aFrame, &mNativeValue);
280 0 : }
281 :
282 : bool
283 0 : TextAttrsMgr::BGColorTextAttr::
284 : GetValueFor(nsIContent* aElm, nscolor* aValue)
285 : {
286 0 : nsIFrame* frame = aElm->GetPrimaryFrame();
287 0 : return frame ? GetColor(frame, aValue) : false;
288 : }
289 :
290 : void
291 0 : TextAttrsMgr::BGColorTextAttr::
292 : ExposeValue(nsIPersistentProperties* aAttributes, const nscolor& aValue)
293 : {
294 0 : nsAutoString formattedValue;
295 0 : StyleInfo::FormatColor(aValue, formattedValue);
296 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::backgroundColor,
297 0 : formattedValue);
298 0 : }
299 :
300 : bool
301 0 : TextAttrsMgr::BGColorTextAttr::
302 : GetColor(nsIFrame* aFrame, nscolor* aColor)
303 : {
304 0 : const nsStyleBackground* styleBackground = aFrame->GetStyleBackground();
305 :
306 0 : if (NS_GET_A(styleBackground->mBackgroundColor) > 0) {
307 0 : *aColor = styleBackground->mBackgroundColor;
308 0 : return true;
309 : }
310 :
311 0 : nsIFrame *parentFrame = aFrame->GetParent();
312 0 : if (!parentFrame) {
313 0 : *aColor = aFrame->PresContext()->DefaultBackgroundColor();
314 0 : return true;
315 : }
316 :
317 : // Each frame of parents chain for the initially passed 'aFrame' has
318 : // transparent background color. So background color isn't changed from
319 : // 'mRootFrame' to initially passed 'aFrame'.
320 0 : if (parentFrame == mRootFrame)
321 0 : return false;
322 :
323 0 : return GetColor(parentFrame, aColor);
324 : }
325 :
326 :
327 : ////////////////////////////////////////////////////////////////////////////////
328 : // ColorTextAttr
329 : ////////////////////////////////////////////////////////////////////////////////
330 :
331 0 : TextAttrsMgr::ColorTextAttr::
332 : ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
333 0 : TTextAttr<nscolor>(!aFrame)
334 : {
335 0 : mRootNativeValue = aRootFrame->GetStyleColor()->mColor;
336 0 : mIsRootDefined = true;
337 :
338 0 : if (aFrame) {
339 0 : mNativeValue = aFrame->GetStyleColor()->mColor;
340 0 : mIsDefined = true;
341 : }
342 0 : }
343 :
344 : bool
345 0 : TextAttrsMgr::ColorTextAttr::
346 : GetValueFor(nsIContent* aElm, nscolor* aValue)
347 : {
348 0 : nsIFrame* frame = aElm->GetPrimaryFrame();
349 0 : if (frame) {
350 0 : *aValue = frame->GetStyleColor()->mColor;
351 0 : return true;
352 : }
353 :
354 0 : return false;
355 : }
356 :
357 : void
358 0 : TextAttrsMgr::ColorTextAttr::
359 : ExposeValue(nsIPersistentProperties* aAttributes, const nscolor& aValue)
360 : {
361 0 : nsAutoString formattedValue;
362 0 : StyleInfo::FormatColor(aValue, formattedValue);
363 0 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::color, formattedValue);
364 0 : }
365 :
366 :
367 : ////////////////////////////////////////////////////////////////////////////////
368 : // FontFamilyTextAttr
369 : ////////////////////////////////////////////////////////////////////////////////
370 :
371 0 : TextAttrsMgr::FontFamilyTextAttr::
372 : FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
373 0 : TTextAttr<nsString>(!aFrame)
374 : {
375 0 : mIsRootDefined = GetFontFamily(aRootFrame, mRootNativeValue);
376 :
377 0 : if (aFrame)
378 0 : mIsDefined = GetFontFamily(aFrame, mNativeValue);
379 0 : }
380 :
381 : bool
382 0 : TextAttrsMgr::FontFamilyTextAttr::
383 : GetValueFor(nsIContent* aElm, nsString* aValue)
384 : {
385 0 : nsIFrame* frame = aElm->GetPrimaryFrame();
386 0 : return frame ? GetFontFamily(frame, *aValue) : false;
387 : }
388 :
389 : void
390 0 : TextAttrsMgr::FontFamilyTextAttr::
391 : ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue)
392 : {
393 0 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_family, aValue);
394 0 : }
395 :
396 : bool
397 0 : TextAttrsMgr::FontFamilyTextAttr::
398 : GetFontFamily(nsIFrame* aFrame, nsString& aFamily)
399 : {
400 0 : nsRefPtr<nsFontMetrics> fm;
401 0 : nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
402 :
403 0 : gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
404 0 : gfxFont* font = fontGroup->GetFontAt(0);
405 0 : gfxFontEntry* fontEntry = font->GetFontEntry();
406 0 : aFamily = fontEntry->FamilyName();
407 0 : return true;
408 : }
409 :
410 :
411 : ////////////////////////////////////////////////////////////////////////////////
412 : // FontSizeTextAttr
413 : ////////////////////////////////////////////////////////////////////////////////
414 :
415 0 : TextAttrsMgr::FontSizeTextAttr::
416 : FontSizeTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
417 0 : TTextAttr<nscoord>(!aFrame)
418 : {
419 0 : mDC = aRootFrame->PresContext()->DeviceContext();
420 :
421 0 : mRootNativeValue = aRootFrame->GetStyleFont()->mSize;
422 0 : mIsRootDefined = true;
423 :
424 0 : if (aFrame) {
425 0 : mNativeValue = aFrame->GetStyleFont()->mSize;
426 0 : mIsDefined = true;
427 : }
428 0 : }
429 :
430 : bool
431 0 : TextAttrsMgr::FontSizeTextAttr::
432 : GetValueFor(nsIContent* aElm, nscoord* aValue)
433 : {
434 0 : nsIFrame* frame = aElm->GetPrimaryFrame();
435 0 : if (frame) {
436 0 : *aValue = frame->GetStyleFont()->mSize;
437 0 : return true;
438 : }
439 :
440 0 : return false;
441 : }
442 :
443 : void
444 0 : TextAttrsMgr::FontSizeTextAttr::
445 : ExposeValue(nsIPersistentProperties* aAttributes, const nscoord& aValue)
446 : {
447 : // Convert from nscoord to pt.
448 : //
449 : // Note: according to IA2, "The conversion doesn't have to be exact.
450 : // The intent is to give the user a feel for the size of the text."
451 : //
452 : // ATK does not specify a unit and will likely follow IA2 here.
453 : //
454 : // XXX todo: consider sharing this code with layout module? (bug 474621)
455 : float px =
456 0 : NSAppUnitsToFloatPixels(aValue, nsDeviceContext::AppUnitsPerCSSPixel());
457 : // Each pt is 4/3 of a CSS pixel.
458 0 : int pts = NS_lround(px*3/4);
459 :
460 0 : nsAutoString value;
461 0 : value.AppendInt(pts);
462 0 : value.Append(NS_LITERAL_STRING("pt"));
463 :
464 0 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_size, value);
465 0 : }
466 :
467 :
468 : ////////////////////////////////////////////////////////////////////////////////
469 : // FontStyleTextAttr
470 : ////////////////////////////////////////////////////////////////////////////////
471 :
472 0 : TextAttrsMgr::FontStyleTextAttr::
473 : FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
474 0 : TTextAttr<nscoord>(!aFrame)
475 : {
476 0 : mRootNativeValue = aRootFrame->GetStyleFont()->mFont.style;
477 0 : mIsRootDefined = true;
478 :
479 0 : if (aFrame) {
480 0 : mNativeValue = aFrame->GetStyleFont()->mFont.style;
481 0 : mIsDefined = true;
482 : }
483 0 : }
484 :
485 : bool
486 0 : TextAttrsMgr::FontStyleTextAttr::
487 : GetValueFor(nsIContent* aContent, nscoord* aValue)
488 : {
489 0 : nsIFrame* frame = aContent->GetPrimaryFrame();
490 0 : if (frame) {
491 0 : *aValue = frame->GetStyleFont()->mFont.style;
492 0 : return true;
493 : }
494 :
495 0 : return false;
496 : }
497 :
498 : void
499 0 : TextAttrsMgr::FontStyleTextAttr::
500 : ExposeValue(nsIPersistentProperties* aAttributes, const nscoord& aValue)
501 : {
502 0 : nsAutoString formattedValue;
503 0 : StyleInfo::FormatFontStyle(aValue, formattedValue);
504 :
505 0 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_style, formattedValue);
506 0 : }
507 :
508 :
509 : ////////////////////////////////////////////////////////////////////////////////
510 : // FontWeightTextAttr
511 : ////////////////////////////////////////////////////////////////////////////////
512 :
513 0 : TextAttrsMgr::FontWeightTextAttr::
514 : FontWeightTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
515 0 : TTextAttr<PRInt32>(!aFrame)
516 : {
517 0 : mRootNativeValue = GetFontWeight(aRootFrame);
518 0 : mIsRootDefined = true;
519 :
520 0 : if (aFrame) {
521 0 : mNativeValue = GetFontWeight(aFrame);
522 0 : mIsDefined = true;
523 : }
524 0 : }
525 :
526 : bool
527 0 : TextAttrsMgr::FontWeightTextAttr::
528 : GetValueFor(nsIContent* aElm, PRInt32* aValue)
529 : {
530 0 : nsIFrame* frame = aElm->GetPrimaryFrame();
531 0 : if (frame) {
532 0 : *aValue = GetFontWeight(frame);
533 0 : return true;
534 : }
535 :
536 0 : return false;
537 : }
538 :
539 : void
540 0 : TextAttrsMgr::FontWeightTextAttr::
541 : ExposeValue(nsIPersistentProperties* aAttributes, const PRInt32& aValue)
542 : {
543 0 : nsAutoString formattedValue;
544 0 : formattedValue.AppendInt(aValue);
545 :
546 0 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::fontWeight, formattedValue);
547 0 : }
548 :
549 : PRInt32
550 0 : TextAttrsMgr::FontWeightTextAttr::
551 : GetFontWeight(nsIFrame* aFrame)
552 : {
553 : // nsFont::width isn't suitable here because it's necessary to expose real
554 : // value of font weight (used font might not have some font weight values).
555 0 : nsRefPtr<nsFontMetrics> fm;
556 0 : nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
557 :
558 0 : gfxFontGroup *fontGroup = fm->GetThebesFontGroup();
559 0 : gfxFont *font = fontGroup->GetFontAt(0);
560 :
561 : // When there doesn't exist a bold font in the family and so the rendering of
562 : // a non-bold font face is changed so that the user sees what looks like a
563 : // bold font, i.e. synthetic bolding is used. IsSyntheticBold method is only
564 : // needed on Mac, but it is "safe" to use on all platforms. (For non-Mac
565 : // platforms it always return false.)
566 0 : if (font->IsSyntheticBold())
567 0 : return 700;
568 :
569 : #ifdef MOZ_PANGO
570 : // On Linux, font->GetStyle()->weight will give the absolute weight requested
571 : // of the font face. The Linux code uses the gfxFontEntry constructor which
572 : // doesn't initialize the weight field.
573 0 : return font->GetStyle()->weight;
574 : #else
575 : // On Windows, font->GetStyle()->weight will give the same weight as
576 : // fontEntry->Weight(), the weight of the first font in the font group, which
577 : // may not be the weight of the font face used to render the characters.
578 : // On Mac, font->GetStyle()->weight will just give the same number as
579 : // getComputedStyle(). fontEntry->Weight() will give the weight of the font
580 : // face used.
581 : gfxFontEntry *fontEntry = font->GetFontEntry();
582 : return fontEntry->Weight();
583 : #endif
584 : }
585 :
586 :
587 : ////////////////////////////////////////////////////////////////////////////////
588 : // TextDecorTextAttr
589 : ////////////////////////////////////////////////////////////////////////////////
590 :
591 0 : TextAttrsMgr::TextDecorValue::
592 : TextDecorValue(nsIFrame* aFrame)
593 : {
594 0 : const nsStyleTextReset* textReset = aFrame->GetStyleTextReset();
595 0 : mStyle = textReset->GetDecorationStyle();
596 :
597 0 : bool isForegroundColor = false;
598 0 : textReset->GetDecorationColor(mColor, isForegroundColor);
599 0 : if (isForegroundColor)
600 0 : mColor = aFrame->GetStyleColor()->mColor;
601 :
602 : mLine = textReset->mTextDecorationLine &
603 : (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE |
604 0 : NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH);
605 0 : }
606 :
607 0 : TextAttrsMgr::TextDecorTextAttr::
608 : TextDecorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
609 0 : TTextAttr<TextDecorValue>(!aFrame)
610 : {
611 0 : mRootNativeValue = TextDecorValue(aRootFrame);
612 0 : mIsRootDefined = mRootNativeValue.IsDefined();
613 :
614 0 : if (aFrame) {
615 0 : mNativeValue = TextDecorValue(aFrame);
616 0 : mIsDefined = mNativeValue.IsDefined();
617 : }
618 0 : }
619 :
620 : bool
621 0 : TextAttrsMgr::TextDecorTextAttr::
622 : GetValueFor(nsIContent* aContent, TextDecorValue* aValue)
623 : {
624 0 : nsIFrame* frame = aContent->GetPrimaryFrame();
625 0 : if (frame) {
626 0 : *aValue = TextDecorValue(frame);
627 0 : return aValue->IsDefined();
628 : }
629 :
630 0 : return false;
631 : }
632 :
633 : void
634 0 : TextAttrsMgr::TextDecorTextAttr::
635 : ExposeValue(nsIPersistentProperties* aAttributes, const TextDecorValue& aValue)
636 : {
637 0 : if (aValue.IsUnderline()) {
638 0 : nsAutoString formattedStyle;
639 0 : StyleInfo::FormatTextDecorationStyle(aValue.Style(), formattedStyle);
640 : nsAccUtils::SetAccAttr(aAttributes,
641 : nsGkAtoms::textUnderlineStyle,
642 0 : formattedStyle);
643 :
644 0 : nsAutoString formattedColor;
645 0 : StyleInfo::FormatColor(aValue.Color(), formattedColor);
646 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textUnderlineColor,
647 0 : formattedColor);
648 : return;
649 : }
650 :
651 0 : if (aValue.IsLineThrough()) {
652 0 : nsAutoString formattedStyle;
653 0 : StyleInfo::FormatTextDecorationStyle(aValue.Style(), formattedStyle);
654 : nsAccUtils::SetAccAttr(aAttributes,
655 : nsGkAtoms::textLineThroughStyle,
656 0 : formattedStyle);
657 :
658 0 : nsAutoString formattedColor;
659 0 : StyleInfo::FormatColor(aValue.Color(), formattedColor);
660 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textLineThroughColor,
661 0 : formattedColor);
662 : }
663 : }
664 :
665 : ////////////////////////////////////////////////////////////////////////////////
666 : // TextPosTextAttr
667 : ////////////////////////////////////////////////////////////////////////////////
668 :
669 0 : TextAttrsMgr::TextPosTextAttr::
670 : TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
671 0 : TTextAttr<TextPosValue>(!aFrame)
672 : {
673 0 : mRootNativeValue = GetTextPosValue(aRootFrame);
674 0 : mIsRootDefined = mRootNativeValue != eTextPosNone;
675 :
676 0 : if (aFrame) {
677 0 : mNativeValue = GetTextPosValue(aFrame);
678 0 : mIsDefined = mNativeValue != eTextPosNone;
679 : }
680 0 : }
681 :
682 : bool
683 0 : TextAttrsMgr::TextPosTextAttr::
684 : GetValueFor(nsIContent* aContent, TextPosValue* aValue)
685 : {
686 0 : nsIFrame* frame = aContent->GetPrimaryFrame();
687 0 : if (frame) {
688 0 : *aValue = GetTextPosValue(frame);
689 0 : return *aValue != eTextPosNone;
690 : }
691 :
692 0 : return false;
693 : }
694 :
695 : void
696 0 : TextAttrsMgr::TextPosTextAttr::
697 : ExposeValue(nsIPersistentProperties* aAttributes, const TextPosValue& aValue)
698 : {
699 0 : switch (aValue) {
700 : case eTextPosBaseline:
701 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
702 0 : NS_LITERAL_STRING("baseline"));
703 0 : break;
704 :
705 : case eTextPosSub:
706 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
707 0 : NS_LITERAL_STRING("sub"));
708 0 : break;
709 :
710 : case eTextPosSuper:
711 : nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
712 0 : NS_LITERAL_STRING("super"));
713 0 : break;
714 : }
715 0 : }
716 :
717 : TextAttrsMgr::TextPosValue
718 0 : TextAttrsMgr::TextPosTextAttr::
719 : GetTextPosValue(nsIFrame* aFrame) const
720 : {
721 0 : const nsStyleCoord& styleCoord = aFrame->GetStyleTextReset()->mVerticalAlign;
722 0 : switch (styleCoord.GetUnit()) {
723 : case eStyleUnit_Enumerated:
724 0 : switch (styleCoord.GetIntValue()) {
725 : case NS_STYLE_VERTICAL_ALIGN_BASELINE:
726 0 : return eTextPosBaseline;
727 : case NS_STYLE_VERTICAL_ALIGN_SUB:
728 0 : return eTextPosSub;
729 : case NS_STYLE_VERTICAL_ALIGN_SUPER:
730 0 : return eTextPosSuper;
731 :
732 : // No good guess for these:
733 : // NS_STYLE_VERTICAL_ALIGN_TOP
734 : // NS_STYLE_VERTICAL_ALIGN_TEXT_TOP
735 : // NS_STYLE_VERTICAL_ALIGN_MIDDLE
736 : // NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM
737 : // NS_STYLE_VERTICAL_ALIGN_BOTTOM
738 : // NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE
739 : // Do not expose value of text-position attribute.
740 :
741 : default:
742 : break;
743 : }
744 0 : return eTextPosNone;
745 :
746 : case eStyleUnit_Percent:
747 : {
748 0 : float percentValue = styleCoord.GetPercentValue();
749 : return percentValue > 0 ?
750 : eTextPosSuper :
751 0 : (percentValue < 0 ? eTextPosSub : eTextPosBaseline);
752 : }
753 :
754 : case eStyleUnit_Coord:
755 : {
756 0 : nscoord coordValue = styleCoord.GetCoordValue();
757 : return coordValue > 0 ?
758 : eTextPosSuper :
759 0 : (coordValue < 0 ? eTextPosSub : eTextPosBaseline);
760 : }
761 : }
762 :
763 0 : return eTextPosNone;
764 : }
|