accessible/src/base/TextAttrs.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial