Coverage Report

Created: 2018-09-25 14:53

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