accessible/src/base/TextAttrs.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/accessible/src/base/TextAttrs.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,880 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "TextAttrs.h"
    1.10 +
    1.11 +#include "Accessible-inl.h"
    1.12 +#include "nsAccUtils.h"
    1.13 +#include "nsCoreUtils.h"
    1.14 +#include "StyleInfo.h"
    1.15 +
    1.16 +#include "gfxFont.h"
    1.17 +#include "nsFontMetrics.h"
    1.18 +#include "nsLayoutUtils.h"
    1.19 +#include "HyperTextAccessible.h"
    1.20 +#include "mozilla/AppUnits.h"
    1.21 +#include "mozilla/gfx/2D.h"
    1.22 +
    1.23 +using namespace mozilla;
    1.24 +using namespace mozilla::a11y;
    1.25 +
    1.26 +////////////////////////////////////////////////////////////////////////////////
    1.27 +// TextAttrsMgr
    1.28 +////////////////////////////////////////////////////////////////////////////////
    1.29 +
    1.30 +void
    1.31 +TextAttrsMgr::GetAttributes(nsIPersistentProperties* aAttributes,
    1.32 +                            int32_t* aStartHTOffset,
    1.33 +                            int32_t* aEndHTOffset)
    1.34 +{
    1.35 +  // 1. Hyper text accessible must be specified always.
    1.36 +  // 2. Offset accessible and result hyper text offsets must be specified in
    1.37 +  // the case of text attributes.
    1.38 +  // 3. Offset accessible and result hyper text offsets must not be specified
    1.39 +  // but include default text attributes flag and attributes list must be
    1.40 +  // specified in the case of default text attributes.
    1.41 +  NS_PRECONDITION(mHyperTextAcc &&
    1.42 +                  ((mOffsetAcc && mOffsetAccIdx != -1 &&
    1.43 +                    aStartHTOffset && aEndHTOffset) ||
    1.44 +                  (!mOffsetAcc && mOffsetAccIdx == -1 &&
    1.45 +                    !aStartHTOffset && !aEndHTOffset &&
    1.46 +                   mIncludeDefAttrs && aAttributes)),
    1.47 +                  "Wrong usage of TextAttrsMgr!");
    1.48 +
    1.49 +  // Embedded objects are combined into own range with empty attributes set.
    1.50 +  if (mOffsetAcc && nsAccUtils::IsEmbeddedObject(mOffsetAcc)) {
    1.51 +    for (int32_t childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
    1.52 +      Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);
    1.53 +      if (!nsAccUtils::IsEmbeddedObject(currAcc))
    1.54 +        break;
    1.55 +
    1.56 +      (*aStartHTOffset)--;
    1.57 +    }
    1.58 +
    1.59 +    uint32_t childCount = mHyperTextAcc->ChildCount();
    1.60 +    for (uint32_t childIdx = mOffsetAccIdx + 1; childIdx < childCount;
    1.61 +         childIdx++) {
    1.62 +      Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);
    1.63 +      if (!nsAccUtils::IsEmbeddedObject(currAcc))
    1.64 +        break;
    1.65 +
    1.66 +      (*aEndHTOffset)++;
    1.67 +    }
    1.68 +
    1.69 +    return;
    1.70 +  }
    1.71 +
    1.72 +  // Get the content and frame of the accessible. In the case of document
    1.73 +  // accessible it's role content and root frame.
    1.74 +  nsIContent *hyperTextElm = mHyperTextAcc->GetContent();
    1.75 +  nsIFrame *rootFrame = mHyperTextAcc->GetFrame();
    1.76 +  NS_ASSERTION(rootFrame, "No frame for accessible!");
    1.77 +  if (!rootFrame)
    1.78 +    return;
    1.79 +
    1.80 +  nsIContent *offsetNode = nullptr, *offsetElm = nullptr;
    1.81 +  nsIFrame *frame = nullptr;
    1.82 +  if (mOffsetAcc) {
    1.83 +    offsetNode = mOffsetAcc->GetContent();
    1.84 +    offsetElm = nsCoreUtils::GetDOMElementFor(offsetNode);
    1.85 +    NS_ASSERTION(offsetElm, "No element for offset accessible!");
    1.86 +    if (!offsetElm)
    1.87 +      return;
    1.88 +    frame = offsetElm->GetPrimaryFrame();
    1.89 +  }
    1.90 +
    1.91 +  // "language" text attribute
    1.92 +  LangTextAttr langTextAttr(mHyperTextAcc, hyperTextElm, offsetNode);
    1.93 +
    1.94 +  // "aria-invalid" text attribute
    1.95 +  InvalidTextAttr invalidTextAttr(hyperTextElm, offsetNode);
    1.96 +
    1.97 +  // "background-color" text attribute
    1.98 +  BGColorTextAttr bgColorTextAttr(rootFrame, frame);
    1.99 +
   1.100 +  // "color" text attribute
   1.101 +  ColorTextAttr colorTextAttr(rootFrame, frame);
   1.102 +
   1.103 +  // "font-family" text attribute
   1.104 +  FontFamilyTextAttr fontFamilyTextAttr(rootFrame, frame);
   1.105 +
   1.106 +  // "font-size" text attribute
   1.107 +  FontSizeTextAttr fontSizeTextAttr(rootFrame, frame);
   1.108 +
   1.109 +  // "font-style" text attribute
   1.110 +  FontStyleTextAttr fontStyleTextAttr(rootFrame, frame);
   1.111 +
   1.112 +  // "font-weight" text attribute
   1.113 +  FontWeightTextAttr fontWeightTextAttr(rootFrame, frame);
   1.114 +
   1.115 +  // "auto-generated" text attribute
   1.116 +  AutoGeneratedTextAttr autoGenTextAttr(mHyperTextAcc, mOffsetAcc);
   1.117 +
   1.118 +  // "text-underline(line-through)-style(color)" text attributes
   1.119 +  TextDecorTextAttr textDecorTextAttr(rootFrame, frame);
   1.120 +
   1.121 +  // "text-position" text attribute
   1.122 +  TextPosTextAttr textPosTextAttr(rootFrame, frame);
   1.123 +
   1.124 +  TextAttr* attrArray[] =
   1.125 +  {
   1.126 +    &langTextAttr,
   1.127 +    &invalidTextAttr,
   1.128 +    &bgColorTextAttr,
   1.129 +    &colorTextAttr,
   1.130 +    &fontFamilyTextAttr,
   1.131 +    &fontSizeTextAttr,
   1.132 +    &fontStyleTextAttr,
   1.133 +    &fontWeightTextAttr,
   1.134 +    &autoGenTextAttr,
   1.135 +    &textDecorTextAttr,
   1.136 +    &textPosTextAttr
   1.137 +  };
   1.138 +
   1.139 +  // Expose text attributes if applicable.
   1.140 +  if (aAttributes) {
   1.141 +    for (uint32_t idx = 0; idx < ArrayLength(attrArray); idx++)
   1.142 +      attrArray[idx]->Expose(aAttributes, mIncludeDefAttrs);
   1.143 +  }
   1.144 +
   1.145 +  // Expose text attributes range where they are applied if applicable.
   1.146 +  if (mOffsetAcc)
   1.147 +    GetRange(attrArray, ArrayLength(attrArray), aStartHTOffset, aEndHTOffset);
   1.148 +}
   1.149 +
   1.150 +void
   1.151 +TextAttrsMgr::GetRange(TextAttr* aAttrArray[], uint32_t aAttrArrayLen,
   1.152 +                       int32_t* aStartHTOffset, int32_t* aEndHTOffset)
   1.153 +{
   1.154 +  // Navigate backward from anchor accessible to find start offset.
   1.155 +  for (int32_t childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
   1.156 +    Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);
   1.157 +
   1.158 +    // Stop on embedded accessible since embedded accessibles are combined into
   1.159 +    // own range.
   1.160 +    if (nsAccUtils::IsEmbeddedObject(currAcc))
   1.161 +      break;
   1.162 +
   1.163 +    bool offsetFound = false;
   1.164 +    for (uint32_t attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
   1.165 +      TextAttr* textAttr = aAttrArray[attrIdx];
   1.166 +      if (!textAttr->Equal(currAcc)) {
   1.167 +        offsetFound = true;
   1.168 +        break;
   1.169 +      }
   1.170 +    }
   1.171 +
   1.172 +    if (offsetFound)
   1.173 +      break;
   1.174 +
   1.175 +    *(aStartHTOffset) -= nsAccUtils::TextLength(currAcc);
   1.176 +  }
   1.177 +
   1.178 +  // Navigate forward from anchor accessible to find end offset.
   1.179 +  uint32_t childLen = mHyperTextAcc->ChildCount();
   1.180 +  for (uint32_t childIdx = mOffsetAccIdx + 1; childIdx < childLen; childIdx++) {
   1.181 +    Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);
   1.182 +    if (nsAccUtils::IsEmbeddedObject(currAcc))
   1.183 +      break;
   1.184 +
   1.185 +    bool offsetFound = false;
   1.186 +    for (uint32_t attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
   1.187 +      TextAttr* textAttr = aAttrArray[attrIdx];
   1.188 +
   1.189 +      // Alter the end offset when text attribute changes its value and stop
   1.190 +      // the search.
   1.191 +      if (!textAttr->Equal(currAcc)) {
   1.192 +        offsetFound = true;
   1.193 +        break;
   1.194 +      }
   1.195 +    }
   1.196 +
   1.197 +    if (offsetFound)
   1.198 +      break;
   1.199 +
   1.200 +    (*aEndHTOffset) += nsAccUtils::TextLength(currAcc);
   1.201 +  }
   1.202 +}
   1.203 +
   1.204 +
   1.205 +////////////////////////////////////////////////////////////////////////////////
   1.206 +// LangTextAttr
   1.207 +////////////////////////////////////////////////////////////////////////////////
   1.208 +
   1.209 +TextAttrsMgr::LangTextAttr::
   1.210 +  LangTextAttr(HyperTextAccessible* aRoot,
   1.211 +               nsIContent* aRootElm, nsIContent* aElm) :
   1.212 +  TTextAttr<nsString>(!aElm), mRootContent(aRootElm)
   1.213 +{
   1.214 +  aRoot->Language(mRootNativeValue);
   1.215 +  mIsRootDefined =  !mRootNativeValue.IsEmpty();
   1.216 +
   1.217 +  if (aElm) {
   1.218 +    nsCoreUtils::GetLanguageFor(aElm, mRootContent, mNativeValue);
   1.219 +    mIsDefined = !mNativeValue.IsEmpty();
   1.220 +  }
   1.221 +}
   1.222 +
   1.223 +TextAttrsMgr::LangTextAttr::
   1.224 +  ~LangTextAttr() {}
   1.225 +
   1.226 +bool
   1.227 +TextAttrsMgr::LangTextAttr::
   1.228 +  GetValueFor(Accessible* aAccessible, nsString* aValue)
   1.229 +{
   1.230 +  nsCoreUtils::GetLanguageFor(aAccessible->GetContent(), mRootContent, *aValue);
   1.231 +  return !aValue->IsEmpty();
   1.232 +}
   1.233 +
   1.234 +void
   1.235 +TextAttrsMgr::LangTextAttr::
   1.236 +  ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue)
   1.237 +{
   1.238 +  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::language, aValue);
   1.239 +}
   1.240 +
   1.241 +////////////////////////////////////////////////////////////////////////////////
   1.242 +// InvalidTextAttr
   1.243 +////////////////////////////////////////////////////////////////////////////////
   1.244 +
   1.245 +TextAttrsMgr::InvalidTextAttr::
   1.246 +  InvalidTextAttr(nsIContent* aRootElm, nsIContent* aElm) :
   1.247 +  TTextAttr<uint32_t>(!aElm), mRootElm(aRootElm)
   1.248 +{
   1.249 +  mIsRootDefined = GetValue(mRootElm, &mRootNativeValue);
   1.250 +  if (aElm)
   1.251 +    mIsDefined = GetValue(aElm, &mNativeValue);
   1.252 +}
   1.253 +
   1.254 +bool
   1.255 +TextAttrsMgr::InvalidTextAttr::
   1.256 +  GetValueFor(Accessible* aAccessible, uint32_t* aValue)
   1.257 +{
   1.258 +  nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   1.259 +  return elm ? GetValue(elm, aValue) : false;
   1.260 +}
   1.261 +
   1.262 +void
   1.263 +TextAttrsMgr::InvalidTextAttr::
   1.264 +  ExposeValue(nsIPersistentProperties* aAttributes, const uint32_t& aValue)
   1.265 +{
   1.266 +  switch (aValue) {
   1.267 +    case eFalse:
   1.268 +      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::invalid,
   1.269 +                             NS_LITERAL_STRING("false"));
   1.270 +      break;
   1.271 +
   1.272 +    case eGrammar:
   1.273 +      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::invalid,
   1.274 +                             NS_LITERAL_STRING("grammar"));
   1.275 +      break;
   1.276 +
   1.277 +    case eSpelling:
   1.278 +      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::invalid,
   1.279 +                             NS_LITERAL_STRING("spelling"));
   1.280 +      break;
   1.281 +
   1.282 +    case eTrue:
   1.283 +      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::invalid,
   1.284 +                             NS_LITERAL_STRING("true"));
   1.285 +      break;
   1.286 +  }
   1.287 +}
   1.288 +
   1.289 +bool
   1.290 +TextAttrsMgr::InvalidTextAttr::
   1.291 +  GetValue(nsIContent* aElm, uint32_t* aValue)
   1.292 +{
   1.293 +  nsIContent* elm = aElm;
   1.294 +  do {
   1.295 +    if (nsAccUtils::HasDefinedARIAToken(elm, nsGkAtoms::aria_invalid)) {
   1.296 +      static nsIContent::AttrValuesArray tokens[] =
   1.297 +        { &nsGkAtoms::_false, &nsGkAtoms::grammar, &nsGkAtoms::spelling,
   1.298 +          nullptr };
   1.299 +
   1.300 +      int32_t idx = elm->FindAttrValueIn(kNameSpaceID_None,
   1.301 +                                         nsGkAtoms::aria_invalid, tokens,
   1.302 +                                         eCaseMatters);
   1.303 +      switch (idx) {
   1.304 +        case 0:
   1.305 +          *aValue = eFalse;
   1.306 +          return true;
   1.307 +        case 1:
   1.308 +          *aValue = eGrammar;
   1.309 +          return true;
   1.310 +        case 2:
   1.311 +          *aValue = eSpelling;
   1.312 +          return true;
   1.313 +        default:
   1.314 +          *aValue = eTrue;
   1.315 +          return true;
   1.316 +      }
   1.317 +    }
   1.318 +  } while ((elm = elm->GetParent()) && elm != mRootElm);
   1.319 +
   1.320 +  return false;
   1.321 +}
   1.322 +
   1.323 +
   1.324 +////////////////////////////////////////////////////////////////////////////////
   1.325 +// BGColorTextAttr
   1.326 +////////////////////////////////////////////////////////////////////////////////
   1.327 +
   1.328 +TextAttrsMgr::BGColorTextAttr::
   1.329 +  BGColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   1.330 +  TTextAttr<nscolor>(!aFrame), mRootFrame(aRootFrame)
   1.331 +{
   1.332 +  mIsRootDefined = GetColor(mRootFrame, &mRootNativeValue);
   1.333 +  if (aFrame)
   1.334 +    mIsDefined = GetColor(aFrame, &mNativeValue);
   1.335 +}
   1.336 +
   1.337 +bool
   1.338 +TextAttrsMgr::BGColorTextAttr::
   1.339 +  GetValueFor(Accessible* aAccessible, nscolor* aValue)
   1.340 +{
   1.341 +  nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   1.342 +  nsIFrame* frame = elm->GetPrimaryFrame();
   1.343 +  return frame ? GetColor(frame, aValue) : false;
   1.344 +}
   1.345 +
   1.346 +void
   1.347 +TextAttrsMgr::BGColorTextAttr::
   1.348 +  ExposeValue(nsIPersistentProperties* aAttributes, const nscolor& aValue)
   1.349 +{
   1.350 +  nsAutoString formattedValue;
   1.351 +  StyleInfo::FormatColor(aValue, formattedValue);
   1.352 +  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::backgroundColor,
   1.353 +                         formattedValue);
   1.354 +}
   1.355 +
   1.356 +bool
   1.357 +TextAttrsMgr::BGColorTextAttr::
   1.358 +  GetColor(nsIFrame* aFrame, nscolor* aColor)
   1.359 +{
   1.360 +  const nsStyleBackground* styleBackground = aFrame->StyleBackground();
   1.361 +
   1.362 +  if (NS_GET_A(styleBackground->mBackgroundColor) > 0) {
   1.363 +    *aColor = styleBackground->mBackgroundColor;
   1.364 +    return true;
   1.365 +  }
   1.366 +
   1.367 +  nsIFrame *parentFrame = aFrame->GetParent();
   1.368 +  if (!parentFrame) {
   1.369 +    *aColor = aFrame->PresContext()->DefaultBackgroundColor();
   1.370 +    return true;
   1.371 +  }
   1.372 +
   1.373 +  // Each frame of parents chain for the initially passed 'aFrame' has
   1.374 +  // transparent background color. So background color isn't changed from
   1.375 +  // 'mRootFrame' to initially passed 'aFrame'.
   1.376 +  if (parentFrame == mRootFrame)
   1.377 +    return false;
   1.378 +
   1.379 +  return GetColor(parentFrame, aColor);
   1.380 +}
   1.381 +
   1.382 +
   1.383 +////////////////////////////////////////////////////////////////////////////////
   1.384 +// ColorTextAttr
   1.385 +////////////////////////////////////////////////////////////////////////////////
   1.386 +
   1.387 +TextAttrsMgr::ColorTextAttr::
   1.388 +  ColorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   1.389 +  TTextAttr<nscolor>(!aFrame)
   1.390 +{
   1.391 +  mRootNativeValue = aRootFrame->StyleColor()->mColor;
   1.392 +  mIsRootDefined = true;
   1.393 +
   1.394 +  if (aFrame) {
   1.395 +    mNativeValue = aFrame->StyleColor()->mColor;
   1.396 +    mIsDefined = true;
   1.397 +  }
   1.398 +}
   1.399 +
   1.400 +bool
   1.401 +TextAttrsMgr::ColorTextAttr::
   1.402 +  GetValueFor(Accessible* aAccessible, nscolor* aValue)
   1.403 +{
   1.404 +  nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   1.405 +  nsIFrame* frame = elm->GetPrimaryFrame();
   1.406 +  if (frame) {
   1.407 +    *aValue = frame->StyleColor()->mColor;
   1.408 +    return true;
   1.409 +  }
   1.410 +
   1.411 +  return false;
   1.412 +}
   1.413 +
   1.414 +void
   1.415 +TextAttrsMgr::ColorTextAttr::
   1.416 +  ExposeValue(nsIPersistentProperties* aAttributes, const nscolor& aValue)
   1.417 +{
   1.418 +  nsAutoString formattedValue;
   1.419 +  StyleInfo::FormatColor(aValue, formattedValue);
   1.420 +  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::color, formattedValue);
   1.421 +}
   1.422 +
   1.423 +
   1.424 +////////////////////////////////////////////////////////////////////////////////
   1.425 +// FontFamilyTextAttr
   1.426 +////////////////////////////////////////////////////////////////////////////////
   1.427 +
   1.428 +TextAttrsMgr::FontFamilyTextAttr::
   1.429 +  FontFamilyTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   1.430 +  TTextAttr<nsString>(!aFrame)
   1.431 +{
   1.432 +  mIsRootDefined = GetFontFamily(aRootFrame, mRootNativeValue);
   1.433 +
   1.434 +  if (aFrame)
   1.435 +    mIsDefined = GetFontFamily(aFrame, mNativeValue);
   1.436 +}
   1.437 +
   1.438 +bool
   1.439 +TextAttrsMgr::FontFamilyTextAttr::
   1.440 +  GetValueFor(Accessible* aAccessible, nsString* aValue)
   1.441 +{
   1.442 +  nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   1.443 +  nsIFrame* frame = elm->GetPrimaryFrame();
   1.444 +  return frame ? GetFontFamily(frame, *aValue) : false;
   1.445 +}
   1.446 +
   1.447 +void
   1.448 +TextAttrsMgr::FontFamilyTextAttr::
   1.449 +  ExposeValue(nsIPersistentProperties* aAttributes, const nsString& aValue)
   1.450 +{
   1.451 +  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_family, aValue);
   1.452 +}
   1.453 +
   1.454 +bool
   1.455 +TextAttrsMgr::FontFamilyTextAttr::
   1.456 +  GetFontFamily(nsIFrame* aFrame, nsString& aFamily)
   1.457 +{
   1.458 +  nsRefPtr<nsFontMetrics> fm;
   1.459 +  nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
   1.460 +
   1.461 +  gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
   1.462 +  gfxFont* font = fontGroup->GetFontAt(0);
   1.463 +  gfxFontEntry* fontEntry = font->GetFontEntry();
   1.464 +  aFamily = fontEntry->FamilyName();
   1.465 +  return true;
   1.466 +}
   1.467 +
   1.468 +
   1.469 +////////////////////////////////////////////////////////////////////////////////
   1.470 +// FontSizeTextAttr
   1.471 +////////////////////////////////////////////////////////////////////////////////
   1.472 +
   1.473 +TextAttrsMgr::FontSizeTextAttr::
   1.474 +  FontSizeTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   1.475 +  TTextAttr<nscoord>(!aFrame)
   1.476 +{
   1.477 +  mDC = aRootFrame->PresContext()->DeviceContext();
   1.478 +
   1.479 +  mRootNativeValue = aRootFrame->StyleFont()->mSize;
   1.480 +  mIsRootDefined = true;
   1.481 +
   1.482 +  if (aFrame) {
   1.483 +    mNativeValue = aFrame->StyleFont()->mSize;
   1.484 +    mIsDefined = true;
   1.485 +  }
   1.486 +}
   1.487 +
   1.488 +bool
   1.489 +TextAttrsMgr::FontSizeTextAttr::
   1.490 +  GetValueFor(Accessible* aAccessible, nscoord* aValue)
   1.491 +{
   1.492 +  nsIContent* content = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   1.493 +  nsIFrame* frame = content->GetPrimaryFrame();
   1.494 +  if (frame) {
   1.495 +    *aValue = frame->StyleFont()->mSize;
   1.496 +    return true;
   1.497 +  }
   1.498 +
   1.499 +  return false;
   1.500 +}
   1.501 +
   1.502 +void
   1.503 +TextAttrsMgr::FontSizeTextAttr::
   1.504 +  ExposeValue(nsIPersistentProperties* aAttributes, const nscoord& aValue)
   1.505 +{
   1.506 +  // Convert from nscoord to pt.
   1.507 +  //
   1.508 +  // Note: according to IA2, "The conversion doesn't have to be exact.
   1.509 +  // The intent is to give the user a feel for the size of the text."
   1.510 +  //
   1.511 +  // ATK does not specify a unit and will likely follow IA2 here.
   1.512 +  //
   1.513 +  // XXX todo: consider sharing this code with layout module? (bug 474621)
   1.514 +  float px =
   1.515 +    NSAppUnitsToFloatPixels(aValue, mozilla::AppUnitsPerCSSPixel());
   1.516 +  // Each pt is 4/3 of a CSS pixel.
   1.517 +  int pts = NS_lround(px*3/4);
   1.518 +
   1.519 +  nsAutoString value;
   1.520 +  value.AppendInt(pts);
   1.521 +  value.Append(NS_LITERAL_STRING("pt"));
   1.522 +
   1.523 +  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_size, value);
   1.524 +}
   1.525 +
   1.526 +
   1.527 +////////////////////////////////////////////////////////////////////////////////
   1.528 +// FontStyleTextAttr
   1.529 +////////////////////////////////////////////////////////////////////////////////
   1.530 +
   1.531 +TextAttrsMgr::FontStyleTextAttr::
   1.532 +  FontStyleTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   1.533 +  TTextAttr<nscoord>(!aFrame)
   1.534 +{
   1.535 +  mRootNativeValue = aRootFrame->StyleFont()->mFont.style;
   1.536 +  mIsRootDefined = true;
   1.537 +
   1.538 +  if (aFrame) {
   1.539 +    mNativeValue = aFrame->StyleFont()->mFont.style;
   1.540 +    mIsDefined = true;
   1.541 +  }
   1.542 +}
   1.543 +
   1.544 +bool
   1.545 +TextAttrsMgr::FontStyleTextAttr::
   1.546 +  GetValueFor(Accessible* aAccessible, nscoord* aValue)
   1.547 +{
   1.548 +  nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   1.549 +  nsIFrame* frame = elm->GetPrimaryFrame();
   1.550 +  if (frame) {
   1.551 +    *aValue = frame->StyleFont()->mFont.style;
   1.552 +    return true;
   1.553 +  }
   1.554 +
   1.555 +  return false;
   1.556 +}
   1.557 +
   1.558 +void
   1.559 +TextAttrsMgr::FontStyleTextAttr::
   1.560 +  ExposeValue(nsIPersistentProperties* aAttributes, const nscoord& aValue)
   1.561 +{
   1.562 +  nsAutoString formattedValue;
   1.563 +  StyleInfo::FormatFontStyle(aValue, formattedValue);
   1.564 +
   1.565 +  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::font_style, formattedValue);
   1.566 +}
   1.567 +
   1.568 +
   1.569 +////////////////////////////////////////////////////////////////////////////////
   1.570 +// FontWeightTextAttr
   1.571 +////////////////////////////////////////////////////////////////////////////////
   1.572 +
   1.573 +TextAttrsMgr::FontWeightTextAttr::
   1.574 +  FontWeightTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   1.575 +  TTextAttr<int32_t>(!aFrame)
   1.576 +{
   1.577 +  mRootNativeValue = GetFontWeight(aRootFrame);
   1.578 +  mIsRootDefined = true;
   1.579 +
   1.580 +  if (aFrame) {
   1.581 +    mNativeValue = GetFontWeight(aFrame);
   1.582 +    mIsDefined = true;
   1.583 +  }
   1.584 +}
   1.585 +
   1.586 +bool
   1.587 +TextAttrsMgr::FontWeightTextAttr::
   1.588 +  GetValueFor(Accessible* aAccessible, int32_t* aValue)
   1.589 +{
   1.590 +  nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   1.591 +  nsIFrame* frame = elm->GetPrimaryFrame();
   1.592 +  if (frame) {
   1.593 +    *aValue = GetFontWeight(frame);
   1.594 +    return true;
   1.595 +  }
   1.596 +
   1.597 +  return false;
   1.598 +}
   1.599 +
   1.600 +void
   1.601 +TextAttrsMgr::FontWeightTextAttr::
   1.602 +  ExposeValue(nsIPersistentProperties* aAttributes, const int32_t& aValue)
   1.603 +{
   1.604 +  nsAutoString formattedValue;
   1.605 +  formattedValue.AppendInt(aValue);
   1.606 +
   1.607 +  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::fontWeight, formattedValue);
   1.608 +}
   1.609 +
   1.610 +int32_t
   1.611 +TextAttrsMgr::FontWeightTextAttr::
   1.612 +  GetFontWeight(nsIFrame* aFrame)
   1.613 +{
   1.614 +  // nsFont::width isn't suitable here because it's necessary to expose real
   1.615 +  // value of font weight (used font might not have some font weight values).
   1.616 +  nsRefPtr<nsFontMetrics> fm;
   1.617 +  nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
   1.618 +
   1.619 +  gfxFontGroup *fontGroup = fm->GetThebesFontGroup();
   1.620 +  gfxFont *font = fontGroup->GetFontAt(0);
   1.621 +
   1.622 +  // When there doesn't exist a bold font in the family and so the rendering of
   1.623 +  // a non-bold font face is changed so that the user sees what looks like a
   1.624 +  // bold font, i.e. synthetic bolding is used. IsSyntheticBold method is only
   1.625 +  // needed on Mac, but it is "safe" to use on all platforms.  (For non-Mac
   1.626 +  // platforms it always return false.)
   1.627 +  if (font->IsSyntheticBold())
   1.628 +    return 700;
   1.629 +
   1.630 +#if defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_QT)
   1.631 +  // On Linux, font->GetStyle()->weight will give the absolute weight requested
   1.632 +  // of the font face. The Linux code uses the gfxFontEntry constructor which
   1.633 +  // doesn't initialize the weight field.
   1.634 +  return font->GetStyle()->weight;
   1.635 +#else
   1.636 +  // On Windows, font->GetStyle()->weight will give the same weight as
   1.637 +  // fontEntry->Weight(), the weight of the first font in the font group, which
   1.638 +  // may not be the weight of the font face used to render the characters.
   1.639 +  // On Mac, font->GetStyle()->weight will just give the same number as
   1.640 +  // getComputedStyle(). fontEntry->Weight() will give the weight of the font
   1.641 +  // face used.
   1.642 +  gfxFontEntry *fontEntry = font->GetFontEntry();
   1.643 +  return fontEntry->Weight();
   1.644 +#endif
   1.645 +}
   1.646 +
   1.647 +////////////////////////////////////////////////////////////////////////////////
   1.648 +// AutoGeneratedTextAttr
   1.649 +////////////////////////////////////////////////////////////////////////////////
   1.650 +TextAttrsMgr::AutoGeneratedTextAttr::
   1.651 +  AutoGeneratedTextAttr(HyperTextAccessible* aHyperTextAcc,
   1.652 +                        Accessible* aAccessible) :
   1.653 +  TTextAttr<bool>(!aAccessible)
   1.654 +{
   1.655 +  mRootNativeValue = false;
   1.656 +  mIsRootDefined = false;
   1.657 +
   1.658 +  if (aAccessible)
   1.659 +    mIsDefined = mNativeValue = (aAccessible->NativeRole() == roles::STATICTEXT);
   1.660 +}
   1.661 +
   1.662 +bool
   1.663 +TextAttrsMgr::AutoGeneratedTextAttr::
   1.664 +  GetValueFor(Accessible* aAccessible, bool* aValue)
   1.665 +{
   1.666 +  return *aValue = (aAccessible->NativeRole() == roles::STATICTEXT);
   1.667 +}
   1.668 +
   1.669 +void
   1.670 +TextAttrsMgr::AutoGeneratedTextAttr::
   1.671 +  ExposeValue(nsIPersistentProperties* aAttributes, const bool& aValue)
   1.672 +{
   1.673 +  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::auto_generated,
   1.674 +                         aValue ? NS_LITERAL_STRING("true") : NS_LITERAL_STRING("false"));
   1.675 +}
   1.676 +
   1.677 +
   1.678 +////////////////////////////////////////////////////////////////////////////////
   1.679 +// TextDecorTextAttr
   1.680 +////////////////////////////////////////////////////////////////////////////////
   1.681 +
   1.682 +TextAttrsMgr::TextDecorValue::
   1.683 +  TextDecorValue(nsIFrame* aFrame)
   1.684 +{
   1.685 +  const nsStyleTextReset* textReset = aFrame->StyleTextReset();
   1.686 +  mStyle = textReset->GetDecorationStyle();
   1.687 +
   1.688 +  bool isForegroundColor = false;
   1.689 +  textReset->GetDecorationColor(mColor, isForegroundColor);
   1.690 +  if (isForegroundColor)
   1.691 +    mColor = aFrame->StyleColor()->mColor;
   1.692 +
   1.693 +  mLine = textReset->mTextDecorationLine &
   1.694 +    (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE |
   1.695 +     NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH);
   1.696 +}
   1.697 +
   1.698 +TextAttrsMgr::TextDecorTextAttr::
   1.699 +  TextDecorTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   1.700 +  TTextAttr<TextDecorValue>(!aFrame)
   1.701 +{
   1.702 +  mRootNativeValue = TextDecorValue(aRootFrame);
   1.703 +  mIsRootDefined = mRootNativeValue.IsDefined();
   1.704 +
   1.705 +  if (aFrame) {
   1.706 +    mNativeValue = TextDecorValue(aFrame);
   1.707 +    mIsDefined = mNativeValue.IsDefined();
   1.708 +  }
   1.709 +}
   1.710 +
   1.711 +bool
   1.712 +TextAttrsMgr::TextDecorTextAttr::
   1.713 +  GetValueFor(Accessible* aAccessible, TextDecorValue* aValue)
   1.714 +{
   1.715 +  nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   1.716 +  nsIFrame* frame = elm->GetPrimaryFrame();
   1.717 +  if (frame) {
   1.718 +    *aValue = TextDecorValue(frame);
   1.719 +    return aValue->IsDefined();
   1.720 +  }
   1.721 +
   1.722 +  return false;
   1.723 +}
   1.724 +
   1.725 +void
   1.726 +TextAttrsMgr::TextDecorTextAttr::
   1.727 +  ExposeValue(nsIPersistentProperties* aAttributes, const TextDecorValue& aValue)
   1.728 +{
   1.729 +  if (aValue.IsUnderline()) {
   1.730 +    nsAutoString formattedStyle;
   1.731 +    StyleInfo::FormatTextDecorationStyle(aValue.Style(), formattedStyle);
   1.732 +    nsAccUtils::SetAccAttr(aAttributes,
   1.733 +                           nsGkAtoms::textUnderlineStyle,
   1.734 +                           formattedStyle);
   1.735 +
   1.736 +    nsAutoString formattedColor;
   1.737 +    StyleInfo::FormatColor(aValue.Color(), formattedColor);
   1.738 +    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textUnderlineColor,
   1.739 +                           formattedColor);
   1.740 +    return;
   1.741 +  }
   1.742 +
   1.743 +  if (aValue.IsLineThrough()) {
   1.744 +    nsAutoString formattedStyle;
   1.745 +    StyleInfo::FormatTextDecorationStyle(aValue.Style(), formattedStyle);
   1.746 +    nsAccUtils::SetAccAttr(aAttributes,
   1.747 +                           nsGkAtoms::textLineThroughStyle,
   1.748 +                           formattedStyle);
   1.749 +
   1.750 +    nsAutoString formattedColor;
   1.751 +    StyleInfo::FormatColor(aValue.Color(), formattedColor);
   1.752 +    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textLineThroughColor,
   1.753 +                           formattedColor);
   1.754 +  }
   1.755 +}
   1.756 +
   1.757 +////////////////////////////////////////////////////////////////////////////////
   1.758 +// TextPosTextAttr
   1.759 +////////////////////////////////////////////////////////////////////////////////
   1.760 +
   1.761 +TextAttrsMgr::TextPosTextAttr::
   1.762 +  TextPosTextAttr(nsIFrame* aRootFrame, nsIFrame* aFrame) :
   1.763 +  TTextAttr<TextPosValue>(!aFrame)
   1.764 +{
   1.765 +  mRootNativeValue = GetTextPosValue(aRootFrame);
   1.766 +  mIsRootDefined = mRootNativeValue != eTextPosNone;
   1.767 +
   1.768 +  if (aFrame) {
   1.769 +    mNativeValue = GetTextPosValue(aFrame);
   1.770 +    mIsDefined = mNativeValue != eTextPosNone;
   1.771 +  }
   1.772 +}
   1.773 +
   1.774 +bool
   1.775 +TextAttrsMgr::TextPosTextAttr::
   1.776 +  GetValueFor(Accessible* aAccessible, TextPosValue* aValue)
   1.777 +{
   1.778 +  nsIContent* elm = nsCoreUtils::GetDOMElementFor(aAccessible->GetContent());
   1.779 +  nsIFrame* frame = elm->GetPrimaryFrame();
   1.780 +  if (frame) {
   1.781 +    *aValue = GetTextPosValue(frame);
   1.782 +    return *aValue != eTextPosNone;
   1.783 +  }
   1.784 +
   1.785 +  return false;
   1.786 +}
   1.787 +
   1.788 +void
   1.789 +TextAttrsMgr::TextPosTextAttr::
   1.790 +  ExposeValue(nsIPersistentProperties* aAttributes, const TextPosValue& aValue)
   1.791 +{
   1.792 +  switch (aValue) {
   1.793 +    case eTextPosBaseline:
   1.794 +      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
   1.795 +                             NS_LITERAL_STRING("baseline"));
   1.796 +      break;
   1.797 +
   1.798 +    case eTextPosSub:
   1.799 +      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
   1.800 +                             NS_LITERAL_STRING("sub"));
   1.801 +      break;
   1.802 +
   1.803 +    case eTextPosSuper:
   1.804 +      nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textPosition,
   1.805 +                             NS_LITERAL_STRING("super"));
   1.806 +      break;
   1.807 +
   1.808 +    case eTextPosNone:
   1.809 +      break;
   1.810 +  }
   1.811 +}
   1.812 +
   1.813 +TextAttrsMgr::TextPosValue
   1.814 +TextAttrsMgr::TextPosTextAttr::
   1.815 +  GetTextPosValue(nsIFrame* aFrame) const
   1.816 +{
   1.817 +  const nsStyleCoord& styleCoord = aFrame->StyleTextReset()->mVerticalAlign;
   1.818 +  switch (styleCoord.GetUnit()) {
   1.819 +    case eStyleUnit_Enumerated:
   1.820 +      switch (styleCoord.GetIntValue()) {
   1.821 +        case NS_STYLE_VERTICAL_ALIGN_BASELINE:
   1.822 +          return eTextPosBaseline;
   1.823 +        case NS_STYLE_VERTICAL_ALIGN_SUB:
   1.824 +          return eTextPosSub;
   1.825 +        case NS_STYLE_VERTICAL_ALIGN_SUPER:
   1.826 +          return eTextPosSuper;
   1.827 +
   1.828 +        // No good guess for these:
   1.829 +        //   NS_STYLE_VERTICAL_ALIGN_TOP
   1.830 +        //   NS_STYLE_VERTICAL_ALIGN_TEXT_TOP
   1.831 +        //   NS_STYLE_VERTICAL_ALIGN_MIDDLE
   1.832 +        //   NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM
   1.833 +        //   NS_STYLE_VERTICAL_ALIGN_BOTTOM
   1.834 +        //   NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE
   1.835 +        // Do not expose value of text-position attribute.
   1.836 +
   1.837 +        default:
   1.838 +          break;
   1.839 +      }
   1.840 +      return eTextPosNone;
   1.841 +
   1.842 +    case eStyleUnit_Percent:
   1.843 +    {
   1.844 +      float percentValue = styleCoord.GetPercentValue();
   1.845 +      return percentValue > 0 ?
   1.846 +        eTextPosSuper :
   1.847 +        (percentValue < 0 ? eTextPosSub : eTextPosBaseline);
   1.848 +    }
   1.849 +
   1.850 +    case eStyleUnit_Coord:
   1.851 +    {
   1.852 +       nscoord coordValue = styleCoord.GetCoordValue();
   1.853 +       return coordValue > 0 ?
   1.854 +         eTextPosSuper :
   1.855 +         (coordValue < 0 ? eTextPosSub : eTextPosBaseline);
   1.856 +    }
   1.857 +
   1.858 +    case eStyleUnit_Null:
   1.859 +    case eStyleUnit_Normal:
   1.860 +    case eStyleUnit_Auto:
   1.861 +    case eStyleUnit_None:
   1.862 +    case eStyleUnit_Factor:
   1.863 +    case eStyleUnit_Degree:
   1.864 +    case eStyleUnit_Grad:
   1.865 +    case eStyleUnit_Radian:
   1.866 +    case eStyleUnit_Turn:
   1.867 +    case eStyleUnit_FlexFraction:
   1.868 +    case eStyleUnit_Integer:
   1.869 +    case eStyleUnit_Calc:
   1.870 +      break;
   1.871 +  }
   1.872 +
   1.873 +  const nsIContent* content = aFrame->GetContent();
   1.874 +  if (content && content->IsHTML()) {
   1.875 +    const nsIAtom* tagName = content->Tag();
   1.876 +    if (tagName == nsGkAtoms::sup) 
   1.877 +      return eTextPosSuper;
   1.878 +    if (tagName == nsGkAtoms::sub) 
   1.879 +      return eTextPosSub;
   1.880 +  }
   1.881 +
   1.882 +  return eTextPosNone;
   1.883 +}

mercurial