layout/style/nsComputedDOMStyle.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 /* vim:set tw=78 expandtab softtabstop=2 ts=2 sw=2: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /* DOM object returned from element.getComputedStyle() */
michael@0 8
michael@0 9 #include "nsComputedDOMStyle.h"
michael@0 10
michael@0 11 #include "mozilla/ArrayUtils.h"
michael@0 12 #include "mozilla/Preferences.h"
michael@0 13
michael@0 14 #include "nsError.h"
michael@0 15 #include "nsDOMString.h"
michael@0 16 #include "nsIDOMCSSPrimitiveValue.h"
michael@0 17 #include "nsStyleContext.h"
michael@0 18 #include "nsIScrollableFrame.h"
michael@0 19 #include "nsContentUtils.h"
michael@0 20 #include "nsIContent.h"
michael@0 21
michael@0 22 #include "nsDOMCSSRect.h"
michael@0 23 #include "nsDOMCSSRGBColor.h"
michael@0 24 #include "nsDOMCSSValueList.h"
michael@0 25 #include "nsGkAtoms.h"
michael@0 26 #include "nsHTMLReflowState.h"
michael@0 27 #include "nsStyleUtil.h"
michael@0 28 #include "nsStyleStructInlines.h"
michael@0 29 #include "nsROCSSPrimitiveValue.h"
michael@0 30
michael@0 31 #include "nsPresContext.h"
michael@0 32 #include "nsIDocument.h"
michael@0 33
michael@0 34 #include "nsCSSPseudoElements.h"
michael@0 35 #include "nsStyleSet.h"
michael@0 36 #include "imgIRequest.h"
michael@0 37 #include "nsLayoutUtils.h"
michael@0 38 #include "nsCSSKeywords.h"
michael@0 39 #include "nsStyleCoord.h"
michael@0 40 #include "nsDisplayList.h"
michael@0 41 #include "nsDOMCSSDeclaration.h"
michael@0 42 #include "nsStyleTransformMatrix.h"
michael@0 43 #include "mozilla/dom/Element.h"
michael@0 44 #include "prtime.h"
michael@0 45 #include "nsWrapperCacheInlines.h"
michael@0 46 #include "mozilla/AppUnits.h"
michael@0 47 #include <algorithm>
michael@0 48
michael@0 49 using namespace mozilla;
michael@0 50 using namespace mozilla::dom;
michael@0 51
michael@0 52 #if defined(DEBUG_bzbarsky) || defined(DEBUG_caillon)
michael@0 53 #define DEBUG_ComputedDOMStyle
michael@0 54 #endif
michael@0 55
michael@0 56 /*
michael@0 57 * This is the implementation of the readonly CSSStyleDeclaration that is
michael@0 58 * returned by the getComputedStyle() function.
michael@0 59 */
michael@0 60
michael@0 61 static nsComputedDOMStyle *sCachedComputedDOMStyle;
michael@0 62
michael@0 63 already_AddRefed<nsComputedDOMStyle>
michael@0 64 NS_NewComputedDOMStyle(dom::Element* aElement, const nsAString& aPseudoElt,
michael@0 65 nsIPresShell* aPresShell,
michael@0 66 nsComputedDOMStyle::StyleType aStyleType)
michael@0 67 {
michael@0 68 nsRefPtr<nsComputedDOMStyle> computedStyle;
michael@0 69 if (sCachedComputedDOMStyle) {
michael@0 70 // There's an unused nsComputedDOMStyle cached, use it.
michael@0 71 // But before we use it, re-initialize the object.
michael@0 72
michael@0 73 // Oh yeah baby, placement new!
michael@0 74 computedStyle = new (sCachedComputedDOMStyle)
michael@0 75 nsComputedDOMStyle(aElement, aPseudoElt, aPresShell, aStyleType);
michael@0 76
michael@0 77 sCachedComputedDOMStyle = nullptr;
michael@0 78 } else {
michael@0 79 // No nsComputedDOMStyle cached, create a new one.
michael@0 80
michael@0 81 computedStyle = new nsComputedDOMStyle(aElement, aPseudoElt, aPresShell,
michael@0 82 aStyleType);
michael@0 83 }
michael@0 84
michael@0 85 return computedStyle.forget();
michael@0 86 }
michael@0 87
michael@0 88 /**
michael@0 89 * An object that represents the ordered set of properties that are exposed on
michael@0 90 * an nsComputedDOMStyle object and how their computed values can be obtained.
michael@0 91 */
michael@0 92 struct nsComputedStyleMap
michael@0 93 {
michael@0 94 friend class nsComputedDOMStyle;
michael@0 95
michael@0 96 struct Entry
michael@0 97 {
michael@0 98 // Create a pointer-to-member-function type.
michael@0 99 typedef mozilla::dom::CSSValue* (nsComputedDOMStyle::*ComputeMethod)();
michael@0 100
michael@0 101 nsCSSProperty mProperty;
michael@0 102 ComputeMethod mGetter;
michael@0 103
michael@0 104 bool IsLayoutFlushNeeded() const
michael@0 105 {
michael@0 106 return nsCSSProps::PropHasFlags(mProperty,
michael@0 107 CSS_PROPERTY_GETCS_NEEDS_LAYOUT_FLUSH);
michael@0 108 }
michael@0 109
michael@0 110 bool IsEnabled() const
michael@0 111 {
michael@0 112 return nsCSSProps::IsEnabled(mProperty);
michael@0 113 }
michael@0 114 };
michael@0 115
michael@0 116 // We define this enum just to count the total number of properties that can
michael@0 117 // be exposed on an nsComputedDOMStyle, including properties that may be
michael@0 118 // disabled.
michael@0 119 enum {
michael@0 120 #define COMPUTED_STYLE_PROP(prop_, method_) \
michael@0 121 eComputedStyleProperty_##prop_,
michael@0 122 #include "nsComputedDOMStylePropertyList.h"
michael@0 123 #undef COMPUTED_STYLE_PROP
michael@0 124 eComputedStyleProperty_COUNT
michael@0 125 };
michael@0 126
michael@0 127 /**
michael@0 128 * Returns the number of properties that should be exposed on an
michael@0 129 * nsComputedDOMStyle, ecxluding any disabled properties.
michael@0 130 */
michael@0 131 uint32_t Length()
michael@0 132 {
michael@0 133 Update();
michael@0 134 return mExposedPropertyCount;
michael@0 135 }
michael@0 136
michael@0 137 /**
michael@0 138 * Returns the property at the given index in the list of properties
michael@0 139 * that should be exposed on an nsComputedDOMStyle, excluding any
michael@0 140 * disabled properties.
michael@0 141 */
michael@0 142 nsCSSProperty PropertyAt(uint32_t aIndex)
michael@0 143 {
michael@0 144 Update();
michael@0 145 return kEntries[EntryIndex(aIndex)].mProperty;
michael@0 146 }
michael@0 147
michael@0 148 /**
michael@0 149 * Searches for and returns the computed style map entry for the given
michael@0 150 * property, or nullptr if the property is not exposed on nsComputedDOMStyle
michael@0 151 * or is currently disabled.
michael@0 152 */
michael@0 153 const Entry* FindEntryForProperty(nsCSSProperty aPropID)
michael@0 154 {
michael@0 155 Update();
michael@0 156 for (uint32_t i = 0; i < mExposedPropertyCount; i++) {
michael@0 157 const Entry* entry = &kEntries[EntryIndex(i)];
michael@0 158 if (entry->mProperty == aPropID) {
michael@0 159 return entry;
michael@0 160 }
michael@0 161 }
michael@0 162 return nullptr;
michael@0 163 }
michael@0 164
michael@0 165 /**
michael@0 166 * Records that mIndexMap needs updating, due to prefs changing that could
michael@0 167 * affect the set of properties exposed on an nsComputedDOMStyle.
michael@0 168 */
michael@0 169 void MarkDirty() { mExposedPropertyCount = 0; }
michael@0 170
michael@0 171 // The member variables are public so that we can use an initializer in
michael@0 172 // nsComputedDOMStyle::GetComputedStyleMap. Use the member functions
michael@0 173 // above to get information from this object.
michael@0 174
michael@0 175 /**
michael@0 176 * An entry for each property that can be exposed on an nsComputedDOMStyle.
michael@0 177 */
michael@0 178 const Entry kEntries[eComputedStyleProperty_COUNT];
michael@0 179
michael@0 180 /**
michael@0 181 * The number of properties that should be exposed on an nsComputedDOMStyle.
michael@0 182 * This will be less than eComputedStyleProperty_COUNT if some property
michael@0 183 * prefs are disabled. A value of 0 indicates that it and mIndexMap are out
michael@0 184 * of date.
michael@0 185 */
michael@0 186 uint32_t mExposedPropertyCount;
michael@0 187
michael@0 188 /**
michael@0 189 * A map of indexes on the nsComputedDOMStyle object to indexes into kEntries.
michael@0 190 */
michael@0 191 uint32_t mIndexMap[eComputedStyleProperty_COUNT];
michael@0 192
michael@0 193 private:
michael@0 194 /**
michael@0 195 * Returns whether mExposedPropertyCount and mIndexMap are out of date.
michael@0 196 */
michael@0 197 bool IsDirty() { return mExposedPropertyCount == 0; }
michael@0 198
michael@0 199 /**
michael@0 200 * Updates mExposedPropertyCount and mIndexMap to take into account properties
michael@0 201 * whose prefs are currently disabled.
michael@0 202 */
michael@0 203 void Update();
michael@0 204
michael@0 205 /**
michael@0 206 * Maps an nsComputedDOMStyle indexed getter index to an index into kEntries.
michael@0 207 */
michael@0 208 uint32_t EntryIndex(uint32_t aIndex) const
michael@0 209 {
michael@0 210 MOZ_ASSERT(aIndex < mExposedPropertyCount);
michael@0 211 return mIndexMap[aIndex];
michael@0 212 }
michael@0 213 };
michael@0 214
michael@0 215 void
michael@0 216 nsComputedStyleMap::Update()
michael@0 217 {
michael@0 218 if (!IsDirty()) {
michael@0 219 return;
michael@0 220 }
michael@0 221
michael@0 222 uint32_t index = 0;
michael@0 223 for (uint32_t i = 0; i < eComputedStyleProperty_COUNT; i++) {
michael@0 224 if (kEntries[i].IsEnabled()) {
michael@0 225 mIndexMap[index++] = i;
michael@0 226 }
michael@0 227 }
michael@0 228 mExposedPropertyCount = index;
michael@0 229 }
michael@0 230
michael@0 231 nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement,
michael@0 232 const nsAString& aPseudoElt,
michael@0 233 nsIPresShell* aPresShell,
michael@0 234 StyleType aStyleType)
michael@0 235 : mDocumentWeak(nullptr), mOuterFrame(nullptr),
michael@0 236 mInnerFrame(nullptr), mPresShell(nullptr),
michael@0 237 mStyleType(aStyleType),
michael@0 238 mExposeVisitedStyle(false)
michael@0 239 {
michael@0 240 MOZ_ASSERT(aElement && aPresShell);
michael@0 241
michael@0 242 mDocumentWeak = do_GetWeakReference(aPresShell->GetDocument());
michael@0 243
michael@0 244 mContent = aElement;
michael@0 245
michael@0 246 if (!DOMStringIsNull(aPseudoElt) && !aPseudoElt.IsEmpty() &&
michael@0 247 aPseudoElt.First() == char16_t(':')) {
michael@0 248 // deal with two-colon forms of aPseudoElt
michael@0 249 nsAString::const_iterator start, end;
michael@0 250 aPseudoElt.BeginReading(start);
michael@0 251 aPseudoElt.EndReading(end);
michael@0 252 NS_ASSERTION(start != end, "aPseudoElt is not empty!");
michael@0 253 ++start;
michael@0 254 bool haveTwoColons = true;
michael@0 255 if (start == end || *start != char16_t(':')) {
michael@0 256 --start;
michael@0 257 haveTwoColons = false;
michael@0 258 }
michael@0 259 mPseudo = do_GetAtom(Substring(start, end));
michael@0 260 MOZ_ASSERT(mPseudo);
michael@0 261
michael@0 262 // There aren't any non-CSS2 pseudo-elements with a single ':'
michael@0 263 if (!haveTwoColons &&
michael@0 264 (!nsCSSPseudoElements::IsPseudoElement(mPseudo) ||
michael@0 265 !nsCSSPseudoElements::IsCSS2PseudoElement(mPseudo))) {
michael@0 266 // XXXbz I'd really rather we threw an exception or something, but
michael@0 267 // the DOM spec sucks.
michael@0 268 mPseudo = nullptr;
michael@0 269 }
michael@0 270 }
michael@0 271
michael@0 272 MOZ_ASSERT(aPresShell->GetPresContext());
michael@0 273 }
michael@0 274
michael@0 275
michael@0 276 nsComputedDOMStyle::~nsComputedDOMStyle()
michael@0 277 {
michael@0 278 }
michael@0 279
michael@0 280 void
michael@0 281 nsComputedDOMStyle::Shutdown()
michael@0 282 {
michael@0 283 // We want to de-allocate without calling the dtor since we
michael@0 284 // already did that manually in doDestroyComputedDOMStyle(),
michael@0 285 // so cast our cached object to something that doesn't know
michael@0 286 // about our dtor.
michael@0 287 delete reinterpret_cast<char*>(sCachedComputedDOMStyle);
michael@0 288 sCachedComputedDOMStyle = nullptr;
michael@0 289 }
michael@0 290
michael@0 291
michael@0 292 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsComputedDOMStyle, mContent)
michael@0 293
michael@0 294 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsComputedDOMStyle)
michael@0 295 return tmp->IsBlack();
michael@0 296 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
michael@0 297
michael@0 298 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsComputedDOMStyle)
michael@0 299 return tmp->IsBlack();
michael@0 300 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
michael@0 301
michael@0 302 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsComputedDOMStyle)
michael@0 303 return tmp->IsBlack();
michael@0 304 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
michael@0 305
michael@0 306 // QueryInterface implementation for nsComputedDOMStyle
michael@0 307 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsComputedDOMStyle)
michael@0 308 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
michael@0 309 NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
michael@0 310
michael@0 311
michael@0 312 static void doDestroyComputedDOMStyle(nsComputedDOMStyle *aComputedStyle)
michael@0 313 {
michael@0 314 if (!sCachedComputedDOMStyle) {
michael@0 315 // The cache is empty, store aComputedStyle in the cache.
michael@0 316
michael@0 317 sCachedComputedDOMStyle = aComputedStyle;
michael@0 318 sCachedComputedDOMStyle->~nsComputedDOMStyle();
michael@0 319 } else {
michael@0 320 // The cache is full, delete aComputedStyle
michael@0 321
michael@0 322 delete aComputedStyle;
michael@0 323 }
michael@0 324 }
michael@0 325
michael@0 326 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsComputedDOMStyle)
michael@0 327 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(nsComputedDOMStyle,
michael@0 328 doDestroyComputedDOMStyle(this))
michael@0 329
michael@0 330
michael@0 331 NS_IMETHODIMP
michael@0 332 nsComputedDOMStyle::GetPropertyValue(const nsCSSProperty aPropID,
michael@0 333 nsAString& aValue)
michael@0 334 {
michael@0 335 // This is mostly to avoid code duplication with GetPropertyCSSValue(); if
michael@0 336 // perf ever becomes an issue here (doubtful), we can look into changing
michael@0 337 // this.
michael@0 338 return GetPropertyValue(
michael@0 339 NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(aPropID)),
michael@0 340 aValue);
michael@0 341 }
michael@0 342
michael@0 343 NS_IMETHODIMP
michael@0 344 nsComputedDOMStyle::SetPropertyValue(const nsCSSProperty aPropID,
michael@0 345 const nsAString& aValue)
michael@0 346 {
michael@0 347 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
michael@0 348 }
michael@0 349
michael@0 350
michael@0 351 NS_IMETHODIMP
michael@0 352 nsComputedDOMStyle::GetCssText(nsAString& aCssText)
michael@0 353 {
michael@0 354 aCssText.Truncate();
michael@0 355
michael@0 356 return NS_OK;
michael@0 357 }
michael@0 358
michael@0 359
michael@0 360 NS_IMETHODIMP
michael@0 361 nsComputedDOMStyle::SetCssText(const nsAString& aCssText)
michael@0 362 {
michael@0 363 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
michael@0 364 }
michael@0 365
michael@0 366
michael@0 367 NS_IMETHODIMP
michael@0 368 nsComputedDOMStyle::GetLength(uint32_t* aLength)
michael@0 369 {
michael@0 370 NS_PRECONDITION(aLength, "Null aLength! Prepare to die!");
michael@0 371
michael@0 372 uint32_t length = GetComputedStyleMap()->Length();
michael@0 373
michael@0 374 // Make sure we have up to date style so that we can include custom
michael@0 375 // properties.
michael@0 376 UpdateCurrentStyleSources(false);
michael@0 377 if (mStyleContextHolder) {
michael@0 378 length += StyleVariables()->mVariables.Count();
michael@0 379 }
michael@0 380
michael@0 381 *aLength = length;
michael@0 382
michael@0 383 ClearCurrentStyleSources();
michael@0 384
michael@0 385 return NS_OK;
michael@0 386 }
michael@0 387
michael@0 388
michael@0 389 NS_IMETHODIMP
michael@0 390 nsComputedDOMStyle::GetParentRule(nsIDOMCSSRule** aParentRule)
michael@0 391 {
michael@0 392 *aParentRule = nullptr;
michael@0 393
michael@0 394 return NS_OK;
michael@0 395 }
michael@0 396
michael@0 397
michael@0 398 NS_IMETHODIMP
michael@0 399 nsComputedDOMStyle::GetPropertyValue(const nsAString& aPropertyName,
michael@0 400 nsAString& aReturn)
michael@0 401 {
michael@0 402 aReturn.Truncate();
michael@0 403
michael@0 404 ErrorResult error;
michael@0 405 nsRefPtr<CSSValue> val = GetPropertyCSSValue(aPropertyName, error);
michael@0 406 if (error.Failed()) {
michael@0 407 return error.ErrorCode();
michael@0 408 }
michael@0 409
michael@0 410 if (val) {
michael@0 411 nsString text;
michael@0 412 val->GetCssText(text, error);
michael@0 413 aReturn.Assign(text);
michael@0 414 return error.ErrorCode();
michael@0 415 }
michael@0 416
michael@0 417 return NS_OK;
michael@0 418 }
michael@0 419
michael@0 420 NS_IMETHODIMP
michael@0 421 nsComputedDOMStyle::GetAuthoredPropertyValue(const nsAString& aPropertyName,
michael@0 422 nsAString& aReturn)
michael@0 423 {
michael@0 424 // Authored style doesn't make sense to return from computed DOM style,
michael@0 425 // so just return whatever GetPropertyValue() returns.
michael@0 426 return GetPropertyValue(aPropertyName, aReturn);
michael@0 427 }
michael@0 428
michael@0 429 /* static */
michael@0 430 already_AddRefed<nsStyleContext>
michael@0 431 nsComputedDOMStyle::GetStyleContextForElement(Element* aElement,
michael@0 432 nsIAtom* aPseudo,
michael@0 433 nsIPresShell* aPresShell,
michael@0 434 StyleType aStyleType)
michael@0 435 {
michael@0 436 // If the content has a pres shell, we must use it. Otherwise we'd
michael@0 437 // potentially mix rule trees by using the wrong pres shell's style
michael@0 438 // set. Using the pres shell from the content also means that any
michael@0 439 // content that's actually *in* a document will get the style from the
michael@0 440 // correct document.
michael@0 441 nsCOMPtr<nsIPresShell> presShell = GetPresShellForContent(aElement);
michael@0 442 if (!presShell) {
michael@0 443 presShell = aPresShell;
michael@0 444 if (!presShell)
michael@0 445 return nullptr;
michael@0 446 }
michael@0 447
michael@0 448 presShell->FlushPendingNotifications(Flush_Style);
michael@0 449
michael@0 450 return GetStyleContextForElementNoFlush(aElement, aPseudo, presShell,
michael@0 451 aStyleType);
michael@0 452 }
michael@0 453
michael@0 454 /* static */
michael@0 455 already_AddRefed<nsStyleContext>
michael@0 456 nsComputedDOMStyle::GetStyleContextForElementNoFlush(Element* aElement,
michael@0 457 nsIAtom* aPseudo,
michael@0 458 nsIPresShell* aPresShell,
michael@0 459 StyleType aStyleType)
michael@0 460 {
michael@0 461 NS_ABORT_IF_FALSE(aElement, "NULL element");
michael@0 462 // If the content has a pres shell, we must use it. Otherwise we'd
michael@0 463 // potentially mix rule trees by using the wrong pres shell's style
michael@0 464 // set. Using the pres shell from the content also means that any
michael@0 465 // content that's actually *in* a document will get the style from the
michael@0 466 // correct document.
michael@0 467 nsIPresShell *presShell = GetPresShellForContent(aElement);
michael@0 468 if (!presShell) {
michael@0 469 presShell = aPresShell;
michael@0 470 if (!presShell)
michael@0 471 return nullptr;
michael@0 472 }
michael@0 473
michael@0 474 if (!aPseudo && aStyleType == eAll) {
michael@0 475 nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement);
michael@0 476 if (frame) {
michael@0 477 nsStyleContext* result = frame->StyleContext();
michael@0 478 // Don't use the style context if it was influenced by
michael@0 479 // pseudo-elements, since then it's not the primary style
michael@0 480 // for this element.
michael@0 481 if (!result->HasPseudoElementData()) {
michael@0 482 // this function returns an addrefed style context
michael@0 483 nsRefPtr<nsStyleContext> ret = result;
michael@0 484 return ret.forget();
michael@0 485 }
michael@0 486 }
michael@0 487 }
michael@0 488
michael@0 489 // No frame has been created, or we have a pseudo, or we're looking
michael@0 490 // for the default style, so resolve the style ourselves.
michael@0 491 nsRefPtr<nsStyleContext> parentContext;
michael@0 492 nsIContent* parent = aPseudo ? aElement : aElement->GetParent();
michael@0 493 // Don't resolve parent context for document fragments.
michael@0 494 if (parent && parent->IsElement())
michael@0 495 parentContext = GetStyleContextForElementNoFlush(parent->AsElement(),
michael@0 496 nullptr, presShell,
michael@0 497 aStyleType);
michael@0 498
michael@0 499 nsPresContext *presContext = presShell->GetPresContext();
michael@0 500 if (!presContext)
michael@0 501 return nullptr;
michael@0 502
michael@0 503 nsStyleSet *styleSet = presShell->StyleSet();
michael@0 504
michael@0 505 nsRefPtr<nsStyleContext> sc;
michael@0 506 if (aPseudo) {
michael@0 507 nsCSSPseudoElements::Type type = nsCSSPseudoElements::GetPseudoType(aPseudo);
michael@0 508 if (type >= nsCSSPseudoElements::ePseudo_PseudoElementCount) {
michael@0 509 return nullptr;
michael@0 510 }
michael@0 511 nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement);
michael@0 512 Element* pseudoElement = frame ? frame->GetPseudoElement(type) : nullptr;
michael@0 513 sc = styleSet->ResolvePseudoElementStyle(aElement, type, parentContext,
michael@0 514 pseudoElement);
michael@0 515 } else {
michael@0 516 sc = styleSet->ResolveStyleFor(aElement, parentContext);
michael@0 517 }
michael@0 518
michael@0 519 if (aStyleType == eDefaultOnly) {
michael@0 520 // We really only want the user and UA rules. Filter out the other ones.
michael@0 521 nsTArray< nsCOMPtr<nsIStyleRule> > rules;
michael@0 522 for (nsRuleNode* ruleNode = sc->RuleNode();
michael@0 523 !ruleNode->IsRoot();
michael@0 524 ruleNode = ruleNode->GetParent()) {
michael@0 525 if (ruleNode->GetLevel() == nsStyleSet::eAgentSheet ||
michael@0 526 ruleNode->GetLevel() == nsStyleSet::eUserSheet) {
michael@0 527 rules.AppendElement(ruleNode->GetRule());
michael@0 528 }
michael@0 529 }
michael@0 530
michael@0 531 // We want to build a list of user/ua rules that is in order from least to
michael@0 532 // most important, so we have to reverse the list.
michael@0 533 // Integer division to get "stop" is purposeful here: if length is odd, we
michael@0 534 // don't have to do anything with the middle element of the array.
michael@0 535 for (uint32_t i = 0, length = rules.Length(), stop = length / 2;
michael@0 536 i < stop; ++i) {
michael@0 537 rules[i].swap(rules[length - i - 1]);
michael@0 538 }
michael@0 539
michael@0 540 sc = styleSet->ResolveStyleForRules(parentContext, rules);
michael@0 541 }
michael@0 542
michael@0 543 return sc.forget();
michael@0 544 }
michael@0 545
michael@0 546 nsMargin
michael@0 547 nsComputedDOMStyle::GetAdjustedValuesForBoxSizing()
michael@0 548 {
michael@0 549 // We want the width/height of whatever parts 'width' or 'height' controls,
michael@0 550 // which can be different depending on the value of the 'box-sizing' property.
michael@0 551 const nsStylePosition* stylePos = StylePosition();
michael@0 552
michael@0 553 nsMargin adjustment;
michael@0 554 switch(stylePos->mBoxSizing) {
michael@0 555 case NS_STYLE_BOX_SIZING_BORDER:
michael@0 556 adjustment += mInnerFrame->GetUsedBorder();
michael@0 557 // fall through
michael@0 558
michael@0 559 case NS_STYLE_BOX_SIZING_PADDING:
michael@0 560 adjustment += mInnerFrame->GetUsedPadding();
michael@0 561 }
michael@0 562
michael@0 563 return adjustment;
michael@0 564 }
michael@0 565
michael@0 566 /* static */
michael@0 567 nsIPresShell*
michael@0 568 nsComputedDOMStyle::GetPresShellForContent(nsIContent* aContent)
michael@0 569 {
michael@0 570 nsIDocument* currentDoc = aContent->GetCurrentDoc();
michael@0 571 if (!currentDoc)
michael@0 572 return nullptr;
michael@0 573
michael@0 574 return currentDoc->GetShell();
michael@0 575 }
michael@0 576
michael@0 577 // nsDOMCSSDeclaration abstract methods which should never be called
michael@0 578 // on a nsComputedDOMStyle object, but must be defined to avoid
michael@0 579 // compile errors.
michael@0 580 css::Declaration*
michael@0 581 nsComputedDOMStyle::GetCSSDeclaration(bool)
michael@0 582 {
michael@0 583 NS_RUNTIMEABORT("called nsComputedDOMStyle::GetCSSDeclaration");
michael@0 584 return nullptr;
michael@0 585 }
michael@0 586
michael@0 587 nsresult
michael@0 588 nsComputedDOMStyle::SetCSSDeclaration(css::Declaration*)
michael@0 589 {
michael@0 590 NS_RUNTIMEABORT("called nsComputedDOMStyle::SetCSSDeclaration");
michael@0 591 return NS_ERROR_FAILURE;
michael@0 592 }
michael@0 593
michael@0 594 nsIDocument*
michael@0 595 nsComputedDOMStyle::DocToUpdate()
michael@0 596 {
michael@0 597 NS_RUNTIMEABORT("called nsComputedDOMStyle::DocToUpdate");
michael@0 598 return nullptr;
michael@0 599 }
michael@0 600
michael@0 601 void
michael@0 602 nsComputedDOMStyle::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
michael@0 603 {
michael@0 604 NS_RUNTIMEABORT("called nsComputedDOMStyle::GetCSSParsingEnvironment");
michael@0 605 // Just in case NS_RUNTIMEABORT ever stops killing us for some reason
michael@0 606 aCSSParseEnv.mPrincipal = nullptr;
michael@0 607 }
michael@0 608
michael@0 609 void
michael@0 610 nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
michael@0 611 {
michael@0 612 MOZ_ASSERT(!mStyleContextHolder);
michael@0 613
michael@0 614 nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocumentWeak);
michael@0 615 if (!document) {
michael@0 616 return;
michael@0 617 }
michael@0 618
michael@0 619 document->FlushPendingLinkUpdates();
michael@0 620
michael@0 621 // Flush _before_ getting the presshell, since that could create a new
michael@0 622 // presshell. Also note that we want to flush the style on the document
michael@0 623 // we're computing style in, not on the document mContent is in -- the two
michael@0 624 // may be different.
michael@0 625 document->FlushPendingNotifications(
michael@0 626 aNeedsLayoutFlush ? Flush_Layout : Flush_Style);
michael@0 627 #ifdef DEBUG
michael@0 628 mFlushedPendingReflows = aNeedsLayoutFlush;
michael@0 629 #endif
michael@0 630
michael@0 631 mPresShell = document->GetShell();
michael@0 632 if (!mPresShell || !mPresShell->GetPresContext()) {
michael@0 633 return;
michael@0 634 }
michael@0 635
michael@0 636 if (!mPseudo && mStyleType == eAll) {
michael@0 637 mOuterFrame = mContent->GetPrimaryFrame();
michael@0 638 mInnerFrame = mOuterFrame;
michael@0 639 if (mOuterFrame) {
michael@0 640 nsIAtom* type = mOuterFrame->GetType();
michael@0 641 if (type == nsGkAtoms::tableOuterFrame) {
michael@0 642 // If the frame is an outer table frame then we should get the style
michael@0 643 // from the inner table frame.
michael@0 644 mInnerFrame = mOuterFrame->GetFirstPrincipalChild();
michael@0 645 NS_ASSERTION(mInnerFrame, "Outer table must have an inner");
michael@0 646 NS_ASSERTION(!mInnerFrame->GetNextSibling(),
michael@0 647 "Outer table frames should have just one child, "
michael@0 648 "the inner table");
michael@0 649 }
michael@0 650
michael@0 651 mStyleContextHolder = mInnerFrame->StyleContext();
michael@0 652 NS_ASSERTION(mStyleContextHolder, "Frame without style context?");
michael@0 653 }
michael@0 654 }
michael@0 655
michael@0 656 if (!mStyleContextHolder || mStyleContextHolder->HasPseudoElementData()) {
michael@0 657 #ifdef DEBUG
michael@0 658 if (mStyleContextHolder) {
michael@0 659 // We want to check that going through this path because of
michael@0 660 // HasPseudoElementData is rare, because it slows us down a good
michael@0 661 // bit. So check that we're really inside something associated
michael@0 662 // with a pseudo-element that contains elements.
michael@0 663 nsStyleContext *topWithPseudoElementData = mStyleContextHolder;
michael@0 664 while (topWithPseudoElementData->GetParent()->HasPseudoElementData()) {
michael@0 665 topWithPseudoElementData = topWithPseudoElementData->GetParent();
michael@0 666 }
michael@0 667 nsCSSPseudoElements::Type pseudo =
michael@0 668 topWithPseudoElementData->GetPseudoType();
michael@0 669 nsIAtom* pseudoAtom = nsCSSPseudoElements::GetPseudoAtom(pseudo);
michael@0 670 nsAutoString assertMsg(
michael@0 671 NS_LITERAL_STRING("we should be in a pseudo-element that is expected to contain elements ("));
michael@0 672 assertMsg.Append(nsDependentString(pseudoAtom->GetUTF16String()));
michael@0 673 assertMsg.Append(NS_LITERAL_STRING(")"));
michael@0 674 NS_ASSERTION(nsCSSPseudoElements::PseudoElementContainsElements(pseudo),
michael@0 675 NS_LossyConvertUTF16toASCII(assertMsg).get());
michael@0 676 }
michael@0 677 #endif
michael@0 678 // Need to resolve a style context
michael@0 679 mStyleContextHolder =
michael@0 680 nsComputedDOMStyle::GetStyleContextForElement(mContent->AsElement(),
michael@0 681 mPseudo,
michael@0 682 mPresShell,
michael@0 683 mStyleType);
michael@0 684 if (!mStyleContextHolder) {
michael@0 685 return;
michael@0 686 }
michael@0 687
michael@0 688 NS_ASSERTION(mPseudo || !mStyleContextHolder->HasPseudoElementData(),
michael@0 689 "should not have pseudo-element data");
michael@0 690 }
michael@0 691
michael@0 692 // mExposeVisitedStyle is set to true only by testing APIs that
michael@0 693 // require chrome privilege.
michael@0 694 NS_ABORT_IF_FALSE(!mExposeVisitedStyle ||
michael@0 695 nsContentUtils::IsCallerChrome(),
michael@0 696 "mExposeVisitedStyle set incorrectly");
michael@0 697 if (mExposeVisitedStyle && mStyleContextHolder->RelevantLinkVisited()) {
michael@0 698 nsStyleContext *styleIfVisited = mStyleContextHolder->GetStyleIfVisited();
michael@0 699 if (styleIfVisited) {
michael@0 700 mStyleContextHolder = styleIfVisited;
michael@0 701 }
michael@0 702 }
michael@0 703 }
michael@0 704
michael@0 705 void
michael@0 706 nsComputedDOMStyle::ClearCurrentStyleSources()
michael@0 707 {
michael@0 708 mOuterFrame = nullptr;
michael@0 709 mInnerFrame = nullptr;
michael@0 710 mPresShell = nullptr;
michael@0 711
michael@0 712 // Release the current style context for it should be re-resolved
michael@0 713 // whenever a frame is not available.
michael@0 714 mStyleContextHolder = nullptr;
michael@0 715 }
michael@0 716
michael@0 717 already_AddRefed<CSSValue>
michael@0 718 nsComputedDOMStyle::GetPropertyCSSValue(const nsAString& aPropertyName, ErrorResult& aRv)
michael@0 719 {
michael@0 720 nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName,
michael@0 721 nsCSSProps::eEnabledForAllContent);
michael@0 722
michael@0 723 bool needsLayoutFlush;
michael@0 724 nsComputedStyleMap::Entry::ComputeMethod getter;
michael@0 725
michael@0 726 if (prop == eCSSPropertyExtra_variable) {
michael@0 727 needsLayoutFlush = false;
michael@0 728 getter = nullptr;
michael@0 729 } else {
michael@0 730 // We don't (for now, anyway, though it may make sense to change it
michael@0 731 // for all aliases, including those in nsCSSPropAliasList) want
michael@0 732 // aliases to be enumerable (via GetLength and IndexedGetter), so
michael@0 733 // handle them here rather than adding entries to
michael@0 734 // GetQueryablePropertyMap.
michael@0 735 if (prop != eCSSProperty_UNKNOWN &&
michael@0 736 nsCSSProps::PropHasFlags(prop, CSS_PROPERTY_IS_ALIAS)) {
michael@0 737 const nsCSSProperty* subprops = nsCSSProps::SubpropertyEntryFor(prop);
michael@0 738 NS_ABORT_IF_FALSE(subprops[1] == eCSSProperty_UNKNOWN,
michael@0 739 "must have list of length 1");
michael@0 740 prop = subprops[0];
michael@0 741 }
michael@0 742
michael@0 743 const nsComputedStyleMap::Entry* propEntry =
michael@0 744 GetComputedStyleMap()->FindEntryForProperty(prop);
michael@0 745
michael@0 746 if (!propEntry) {
michael@0 747 #ifdef DEBUG_ComputedDOMStyle
michael@0 748 NS_WARNING(PromiseFlatCString(NS_ConvertUTF16toUTF8(aPropertyName) +
michael@0 749 NS_LITERAL_CSTRING(" is not queryable!")).get());
michael@0 750 #endif
michael@0 751
michael@0 752 // NOTE: For branches, we should flush here for compatibility!
michael@0 753 return nullptr;
michael@0 754 }
michael@0 755
michael@0 756 needsLayoutFlush = propEntry->IsLayoutFlushNeeded();
michael@0 757 getter = propEntry->mGetter;
michael@0 758 }
michael@0 759
michael@0 760 UpdateCurrentStyleSources(needsLayoutFlush);
michael@0 761 if (!mStyleContextHolder) {
michael@0 762 aRv.Throw(NS_ERROR_NOT_AVAILABLE);
michael@0 763 return nullptr;
michael@0 764 }
michael@0 765
michael@0 766 nsRefPtr<CSSValue> val;
michael@0 767 if (prop == eCSSPropertyExtra_variable) {
michael@0 768 val = DoGetCustomProperty(aPropertyName);
michael@0 769 } else {
michael@0 770 // Call our pointer-to-member-function.
michael@0 771 val = (this->*getter)();
michael@0 772 }
michael@0 773
michael@0 774 ClearCurrentStyleSources();
michael@0 775
michael@0 776 return val.forget();
michael@0 777 }
michael@0 778
michael@0 779
michael@0 780 NS_IMETHODIMP
michael@0 781 nsComputedDOMStyle::RemoveProperty(const nsAString& aPropertyName,
michael@0 782 nsAString& aReturn)
michael@0 783 {
michael@0 784 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
michael@0 785 }
michael@0 786
michael@0 787
michael@0 788 NS_IMETHODIMP
michael@0 789 nsComputedDOMStyle::GetPropertyPriority(const nsAString& aPropertyName,
michael@0 790 nsAString& aReturn)
michael@0 791 {
michael@0 792 aReturn.Truncate();
michael@0 793
michael@0 794 return NS_OK;
michael@0 795 }
michael@0 796
michael@0 797
michael@0 798 NS_IMETHODIMP
michael@0 799 nsComputedDOMStyle::SetProperty(const nsAString& aPropertyName,
michael@0 800 const nsAString& aValue,
michael@0 801 const nsAString& aPriority)
michael@0 802 {
michael@0 803 return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
michael@0 804 }
michael@0 805
michael@0 806
michael@0 807 NS_IMETHODIMP
michael@0 808 nsComputedDOMStyle::Item(uint32_t aIndex, nsAString& aReturn)
michael@0 809 {
michael@0 810 return nsDOMCSSDeclaration::Item(aIndex, aReturn);
michael@0 811 }
michael@0 812
michael@0 813 void
michael@0 814 nsComputedDOMStyle::IndexedGetter(uint32_t aIndex, bool& aFound,
michael@0 815 nsAString& aPropName)
michael@0 816 {
michael@0 817 nsComputedStyleMap* map = GetComputedStyleMap();
michael@0 818 uint32_t length = map->Length();
michael@0 819
michael@0 820 if (aIndex < length) {
michael@0 821 aFound = true;
michael@0 822 CopyASCIItoUTF16(nsCSSProps::GetStringValue(map->PropertyAt(aIndex)),
michael@0 823 aPropName);
michael@0 824 return;
michael@0 825 }
michael@0 826
michael@0 827 // Custom properties are exposed with indexed properties just after all
michael@0 828 // of the built-in properties.
michael@0 829 UpdateCurrentStyleSources(false);
michael@0 830 if (!mStyleContextHolder) {
michael@0 831 aFound = false;
michael@0 832 return;
michael@0 833 }
michael@0 834
michael@0 835 const nsStyleVariables* variables = StyleVariables();
michael@0 836 if (aIndex - length < variables->mVariables.Count()) {
michael@0 837 aFound = true;
michael@0 838 variables->mVariables.GetVariableAt(aIndex - length, aPropName);
michael@0 839 } else {
michael@0 840 aFound = false;
michael@0 841 }
michael@0 842
michael@0 843 ClearCurrentStyleSources();
michael@0 844 }
michael@0 845
michael@0 846 // Property getters...
michael@0 847
michael@0 848 CSSValue*
michael@0 849 nsComputedDOMStyle::DoGetBinding()
michael@0 850 {
michael@0 851 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 852
michael@0 853 const nsStyleDisplay* display = StyleDisplay();
michael@0 854
michael@0 855 if (display->mBinding) {
michael@0 856 val->SetURI(display->mBinding->GetURI());
michael@0 857 } else {
michael@0 858 val->SetIdent(eCSSKeyword_none);
michael@0 859 }
michael@0 860
michael@0 861 return val;
michael@0 862 }
michael@0 863
michael@0 864 CSSValue*
michael@0 865 nsComputedDOMStyle::DoGetClear()
michael@0 866 {
michael@0 867 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 868 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mBreakType,
michael@0 869 nsCSSProps::kClearKTable));
michael@0 870 return val;
michael@0 871 }
michael@0 872
michael@0 873 CSSValue*
michael@0 874 nsComputedDOMStyle::DoGetFloat()
michael@0 875 {
michael@0 876 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 877 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mFloats,
michael@0 878 nsCSSProps::kFloatKTable));
michael@0 879 return val;
michael@0 880 }
michael@0 881
michael@0 882 CSSValue*
michael@0 883 nsComputedDOMStyle::DoGetBottom()
michael@0 884 {
michael@0 885 return GetOffsetWidthFor(NS_SIDE_BOTTOM);
michael@0 886 }
michael@0 887
michael@0 888 CSSValue*
michael@0 889 nsComputedDOMStyle::DoGetStackSizing()
michael@0 890 {
michael@0 891 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 892 val->SetIdent(StyleXUL()->mStretchStack ? eCSSKeyword_stretch_to_fit :
michael@0 893 eCSSKeyword_ignore);
michael@0 894 return val;
michael@0 895 }
michael@0 896
michael@0 897 void
michael@0 898 nsComputedDOMStyle::SetToRGBAColor(nsROCSSPrimitiveValue* aValue,
michael@0 899 nscolor aColor)
michael@0 900 {
michael@0 901 if (NS_GET_A(aColor) == 0) {
michael@0 902 aValue->SetIdent(eCSSKeyword_transparent);
michael@0 903 return;
michael@0 904 }
michael@0 905
michael@0 906 nsROCSSPrimitiveValue *red = new nsROCSSPrimitiveValue;
michael@0 907 nsROCSSPrimitiveValue *green = new nsROCSSPrimitiveValue;
michael@0 908 nsROCSSPrimitiveValue *blue = new nsROCSSPrimitiveValue;
michael@0 909 nsROCSSPrimitiveValue *alpha = new nsROCSSPrimitiveValue;
michael@0 910
michael@0 911 uint8_t a = NS_GET_A(aColor);
michael@0 912 nsDOMCSSRGBColor *rgbColor =
michael@0 913 new nsDOMCSSRGBColor(red, green, blue, alpha, a < 255);
michael@0 914
michael@0 915 red->SetNumber(NS_GET_R(aColor));
michael@0 916 green->SetNumber(NS_GET_G(aColor));
michael@0 917 blue->SetNumber(NS_GET_B(aColor));
michael@0 918 alpha->SetNumber(nsStyleUtil::ColorComponentToFloat(a));
michael@0 919
michael@0 920 aValue->SetColor(rgbColor);
michael@0 921 }
michael@0 922
michael@0 923 CSSValue*
michael@0 924 nsComputedDOMStyle::DoGetColor()
michael@0 925 {
michael@0 926 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 927 SetToRGBAColor(val, StyleColor()->mColor);
michael@0 928 return val;
michael@0 929 }
michael@0 930
michael@0 931 CSSValue*
michael@0 932 nsComputedDOMStyle::DoGetOpacity()
michael@0 933 {
michael@0 934 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 935 val->SetNumber(StyleDisplay()->mOpacity);
michael@0 936 return val;
michael@0 937 }
michael@0 938
michael@0 939 CSSValue*
michael@0 940 nsComputedDOMStyle::DoGetColumnCount()
michael@0 941 {
michael@0 942 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 943
michael@0 944 const nsStyleColumn* column = StyleColumn();
michael@0 945
michael@0 946 if (column->mColumnCount == NS_STYLE_COLUMN_COUNT_AUTO) {
michael@0 947 val->SetIdent(eCSSKeyword_auto);
michael@0 948 } else {
michael@0 949 val->SetNumber(column->mColumnCount);
michael@0 950 }
michael@0 951
michael@0 952 return val;
michael@0 953 }
michael@0 954
michael@0 955 CSSValue*
michael@0 956 nsComputedDOMStyle::DoGetColumnWidth()
michael@0 957 {
michael@0 958 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 959
michael@0 960 // XXX fix the auto case. When we actually have a column frame, I think
michael@0 961 // we should return the computed column width.
michael@0 962 SetValueToCoord(val, StyleColumn()->mColumnWidth, true);
michael@0 963 return val;
michael@0 964 }
michael@0 965
michael@0 966 CSSValue*
michael@0 967 nsComputedDOMStyle::DoGetColumnGap()
michael@0 968 {
michael@0 969 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 970
michael@0 971 const nsStyleColumn* column = StyleColumn();
michael@0 972 if (column->mColumnGap.GetUnit() == eStyleUnit_Normal) {
michael@0 973 val->SetAppUnits(StyleFont()->mFont.size);
michael@0 974 } else {
michael@0 975 SetValueToCoord(val, StyleColumn()->mColumnGap, true);
michael@0 976 }
michael@0 977
michael@0 978 return val;
michael@0 979 }
michael@0 980
michael@0 981 CSSValue*
michael@0 982 nsComputedDOMStyle::DoGetColumnFill()
michael@0 983 {
michael@0 984 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 985 val->SetIdent(
michael@0 986 nsCSSProps::ValueToKeywordEnum(StyleColumn()->mColumnFill,
michael@0 987 nsCSSProps::kColumnFillKTable));
michael@0 988 return val;
michael@0 989 }
michael@0 990
michael@0 991 CSSValue*
michael@0 992 nsComputedDOMStyle::DoGetColumnRuleWidth()
michael@0 993 {
michael@0 994 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 995 val->SetAppUnits(StyleColumn()->GetComputedColumnRuleWidth());
michael@0 996 return val;
michael@0 997 }
michael@0 998
michael@0 999 CSSValue*
michael@0 1000 nsComputedDOMStyle::DoGetColumnRuleStyle()
michael@0 1001 {
michael@0 1002 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 1003 val->SetIdent(
michael@0 1004 nsCSSProps::ValueToKeywordEnum(StyleColumn()->mColumnRuleStyle,
michael@0 1005 nsCSSProps::kBorderStyleKTable));
michael@0 1006 return val;
michael@0 1007 }
michael@0 1008
michael@0 1009 CSSValue*
michael@0 1010 nsComputedDOMStyle::DoGetColumnRuleColor()
michael@0 1011 {
michael@0 1012 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 1013
michael@0 1014 const nsStyleColumn* column = StyleColumn();
michael@0 1015 nscolor ruleColor;
michael@0 1016 if (column->mColumnRuleColorIsForeground) {
michael@0 1017 ruleColor = StyleColor()->mColor;
michael@0 1018 } else {
michael@0 1019 ruleColor = column->mColumnRuleColor;
michael@0 1020 }
michael@0 1021
michael@0 1022 SetToRGBAColor(val, ruleColor);
michael@0 1023 return val;
michael@0 1024 }
michael@0 1025
michael@0 1026 CSSValue*
michael@0 1027 nsComputedDOMStyle::DoGetContent()
michael@0 1028 {
michael@0 1029 const nsStyleContent *content = StyleContent();
michael@0 1030
michael@0 1031 if (content->ContentCount() == 0) {
michael@0 1032 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 1033 val->SetIdent(eCSSKeyword_none);
michael@0 1034 return val;
michael@0 1035 }
michael@0 1036
michael@0 1037 if (content->ContentCount() == 1 &&
michael@0 1038 content->ContentAt(0).mType == eStyleContentType_AltContent) {
michael@0 1039 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 1040 val->SetIdent(eCSSKeyword__moz_alt_content);
michael@0 1041 return val;
michael@0 1042 }
michael@0 1043
michael@0 1044 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 1045
michael@0 1046 for (uint32_t i = 0, i_end = content->ContentCount(); i < i_end; ++i) {
michael@0 1047 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1048 valueList->AppendCSSValue(val);
michael@0 1049
michael@0 1050 const nsStyleContentData &data = content->ContentAt(i);
michael@0 1051 switch (data.mType) {
michael@0 1052 case eStyleContentType_String:
michael@0 1053 {
michael@0 1054 nsString str;
michael@0 1055 nsStyleUtil::AppendEscapedCSSString(
michael@0 1056 nsDependentString(data.mContent.mString), str);
michael@0 1057 val->SetString(str);
michael@0 1058 }
michael@0 1059 break;
michael@0 1060 case eStyleContentType_Image:
michael@0 1061 {
michael@0 1062 nsCOMPtr<nsIURI> uri;
michael@0 1063 if (data.mContent.mImage) {
michael@0 1064 data.mContent.mImage->GetURI(getter_AddRefs(uri));
michael@0 1065 }
michael@0 1066 val->SetURI(uri);
michael@0 1067 }
michael@0 1068 break;
michael@0 1069 case eStyleContentType_Attr:
michael@0 1070 {
michael@0 1071 nsAutoString str;
michael@0 1072 nsStyleUtil::AppendEscapedCSSIdent(
michael@0 1073 nsDependentString(data.mContent.mString), str);
michael@0 1074 val->SetString(str, nsIDOMCSSPrimitiveValue::CSS_ATTR);
michael@0 1075 }
michael@0 1076 break;
michael@0 1077 case eStyleContentType_Counter:
michael@0 1078 case eStyleContentType_Counters:
michael@0 1079 {
michael@0 1080 /* FIXME: counters should really use an object */
michael@0 1081 nsAutoString str;
michael@0 1082 if (data.mType == eStyleContentType_Counter) {
michael@0 1083 str.AppendLiteral("counter(");
michael@0 1084 }
michael@0 1085 else {
michael@0 1086 str.AppendLiteral("counters(");
michael@0 1087 }
michael@0 1088 // WRITE ME
michael@0 1089 nsCSSValue::Array *a = data.mContent.mCounters;
michael@0 1090
michael@0 1091 nsStyleUtil::AppendEscapedCSSIdent(
michael@0 1092 nsDependentString(a->Item(0).GetStringBufferValue()), str);
michael@0 1093 int32_t typeItem = 1;
michael@0 1094 if (data.mType == eStyleContentType_Counters) {
michael@0 1095 typeItem = 2;
michael@0 1096 str.AppendLiteral(", ");
michael@0 1097 nsStyleUtil::AppendEscapedCSSString(
michael@0 1098 nsDependentString(a->Item(1).GetStringBufferValue()), str);
michael@0 1099 }
michael@0 1100 NS_ABORT_IF_FALSE(eCSSUnit_None != a->Item(typeItem).GetUnit(),
michael@0 1101 "'none' should be handled as enumerated value");
michael@0 1102 int32_t type = a->Item(typeItem).GetIntValue();
michael@0 1103 if (type != NS_STYLE_LIST_STYLE_DECIMAL) {
michael@0 1104 str.AppendLiteral(", ");
michael@0 1105 AppendASCIItoUTF16(
michael@0 1106 nsCSSProps::ValueToKeyword(type, nsCSSProps::kListStyleKTable),
michael@0 1107 str);
michael@0 1108 }
michael@0 1109
michael@0 1110 str.Append(char16_t(')'));
michael@0 1111 val->SetString(str, nsIDOMCSSPrimitiveValue::CSS_COUNTER);
michael@0 1112 }
michael@0 1113 break;
michael@0 1114 case eStyleContentType_OpenQuote:
michael@0 1115 val->SetIdent(eCSSKeyword_open_quote);
michael@0 1116 break;
michael@0 1117 case eStyleContentType_CloseQuote:
michael@0 1118 val->SetIdent(eCSSKeyword_close_quote);
michael@0 1119 break;
michael@0 1120 case eStyleContentType_NoOpenQuote:
michael@0 1121 val->SetIdent(eCSSKeyword_no_open_quote);
michael@0 1122 break;
michael@0 1123 case eStyleContentType_NoCloseQuote:
michael@0 1124 val->SetIdent(eCSSKeyword_no_close_quote);
michael@0 1125 break;
michael@0 1126 case eStyleContentType_AltContent:
michael@0 1127 default:
michael@0 1128 NS_NOTREACHED("unexpected type");
michael@0 1129 break;
michael@0 1130 }
michael@0 1131 }
michael@0 1132
michael@0 1133 return valueList;
michael@0 1134 }
michael@0 1135
michael@0 1136 CSSValue*
michael@0 1137 nsComputedDOMStyle::DoGetCounterIncrement()
michael@0 1138 {
michael@0 1139 const nsStyleContent *content = StyleContent();
michael@0 1140
michael@0 1141 if (content->CounterIncrementCount() == 0) {
michael@0 1142 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 1143 val->SetIdent(eCSSKeyword_none);
michael@0 1144 return val;
michael@0 1145 }
michael@0 1146
michael@0 1147 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 1148
michael@0 1149 for (uint32_t i = 0, i_end = content->CounterIncrementCount(); i < i_end; ++i) {
michael@0 1150 nsROCSSPrimitiveValue* name = new nsROCSSPrimitiveValue;
michael@0 1151 valueList->AppendCSSValue(name);
michael@0 1152
michael@0 1153 nsROCSSPrimitiveValue* value = new nsROCSSPrimitiveValue;
michael@0 1154 valueList->AppendCSSValue(value);
michael@0 1155
michael@0 1156 const nsStyleCounterData *data = content->GetCounterIncrementAt(i);
michael@0 1157 nsAutoString escaped;
michael@0 1158 nsStyleUtil::AppendEscapedCSSIdent(data->mCounter, escaped);
michael@0 1159 name->SetString(escaped);
michael@0 1160 value->SetNumber(data->mValue); // XXX This should really be integer
michael@0 1161 }
michael@0 1162
michael@0 1163 return valueList;
michael@0 1164 }
michael@0 1165
michael@0 1166 /* Convert the stored representation into a list of two values and then hand
michael@0 1167 * it back.
michael@0 1168 */
michael@0 1169 CSSValue*
michael@0 1170 nsComputedDOMStyle::DoGetTransformOrigin()
michael@0 1171 {
michael@0 1172 /* We need to build up a list of two values. We'll call them
michael@0 1173 * width and height.
michael@0 1174 */
michael@0 1175
michael@0 1176 /* Store things as a value list */
michael@0 1177 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 1178
michael@0 1179 /* Now, get the values. */
michael@0 1180 const nsStyleDisplay* display = StyleDisplay();
michael@0 1181
michael@0 1182 nsROCSSPrimitiveValue* width = new nsROCSSPrimitiveValue;
michael@0 1183 SetValueToCoord(width, display->mTransformOrigin[0], false,
michael@0 1184 &nsComputedDOMStyle::GetFrameBoundsWidthForTransform);
michael@0 1185 valueList->AppendCSSValue(width);
michael@0 1186
michael@0 1187 nsROCSSPrimitiveValue* height = new nsROCSSPrimitiveValue;
michael@0 1188 SetValueToCoord(height, display->mTransformOrigin[1], false,
michael@0 1189 &nsComputedDOMStyle::GetFrameBoundsHeightForTransform);
michael@0 1190 valueList->AppendCSSValue(height);
michael@0 1191
michael@0 1192 if (display->mTransformOrigin[2].GetUnit() != eStyleUnit_Coord ||
michael@0 1193 display->mTransformOrigin[2].GetCoordValue() != 0) {
michael@0 1194 nsROCSSPrimitiveValue* depth = new nsROCSSPrimitiveValue;
michael@0 1195 SetValueToCoord(depth, display->mTransformOrigin[2], false,
michael@0 1196 nullptr);
michael@0 1197 valueList->AppendCSSValue(depth);
michael@0 1198 }
michael@0 1199
michael@0 1200 return valueList;
michael@0 1201 }
michael@0 1202
michael@0 1203 /* Convert the stored representation into a list of two values and then hand
michael@0 1204 * it back.
michael@0 1205 */
michael@0 1206 CSSValue*
michael@0 1207 nsComputedDOMStyle::DoGetPerspectiveOrigin()
michael@0 1208 {
michael@0 1209 /* We need to build up a list of two values. We'll call them
michael@0 1210 * width and height.
michael@0 1211 */
michael@0 1212
michael@0 1213 /* Store things as a value list */
michael@0 1214 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 1215
michael@0 1216 /* Now, get the values. */
michael@0 1217 const nsStyleDisplay* display = StyleDisplay();
michael@0 1218
michael@0 1219 nsROCSSPrimitiveValue* width = new nsROCSSPrimitiveValue;
michael@0 1220 SetValueToCoord(width, display->mPerspectiveOrigin[0], false,
michael@0 1221 &nsComputedDOMStyle::GetFrameBoundsWidthForTransform);
michael@0 1222 valueList->AppendCSSValue(width);
michael@0 1223
michael@0 1224 nsROCSSPrimitiveValue* height = new nsROCSSPrimitiveValue;
michael@0 1225 SetValueToCoord(height, display->mPerspectiveOrigin[1], false,
michael@0 1226 &nsComputedDOMStyle::GetFrameBoundsHeightForTransform);
michael@0 1227 valueList->AppendCSSValue(height);
michael@0 1228
michael@0 1229 return valueList;
michael@0 1230 }
michael@0 1231
michael@0 1232 CSSValue*
michael@0 1233 nsComputedDOMStyle::DoGetPerspective()
michael@0 1234 {
michael@0 1235 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1236 SetValueToCoord(val, StyleDisplay()->mChildPerspective, false);
michael@0 1237 return val;
michael@0 1238 }
michael@0 1239
michael@0 1240 CSSValue*
michael@0 1241 nsComputedDOMStyle::DoGetBackfaceVisibility()
michael@0 1242 {
michael@0 1243 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1244 val->SetIdent(
michael@0 1245 nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mBackfaceVisibility,
michael@0 1246 nsCSSProps::kBackfaceVisibilityKTable));
michael@0 1247 return val;
michael@0 1248 }
michael@0 1249
michael@0 1250 CSSValue*
michael@0 1251 nsComputedDOMStyle::DoGetTransformStyle()
michael@0 1252 {
michael@0 1253 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 1254 val->SetIdent(
michael@0 1255 nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mTransformStyle,
michael@0 1256 nsCSSProps::kTransformStyleKTable));
michael@0 1257 return val;
michael@0 1258 }
michael@0 1259
michael@0 1260 /* If the property is "none", hand back "none" wrapped in a value.
michael@0 1261 * Otherwise, compute the aggregate transform matrix and hands it back in a
michael@0 1262 * "matrix" wrapper.
michael@0 1263 */
michael@0 1264 CSSValue*
michael@0 1265 nsComputedDOMStyle::DoGetTransform()
michael@0 1266 {
michael@0 1267 /* First, get the display data. We'll need it. */
michael@0 1268 const nsStyleDisplay* display = StyleDisplay();
michael@0 1269
michael@0 1270 /* If there are no transforms, then we should construct a single-element
michael@0 1271 * entry and hand it back.
michael@0 1272 */
michael@0 1273 if (!display->mSpecifiedTransform) {
michael@0 1274 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1275
michael@0 1276 /* Set it to "none." */
michael@0 1277 val->SetIdent(eCSSKeyword_none);
michael@0 1278 return val;
michael@0 1279 }
michael@0 1280
michael@0 1281 /* Otherwise, we need to compute the current value of the transform matrix,
michael@0 1282 * store it in a string, and hand it back to the caller.
michael@0 1283 */
michael@0 1284
michael@0 1285 /* Use the inner frame for width and height. If we fail, assume zero.
michael@0 1286 * TODO: There is no good way for us to represent the case where there's no
michael@0 1287 * frame, which is problematic. The reason is that when we have percentage
michael@0 1288 * transforms, there are a total of four stored matrix entries that influence
michael@0 1289 * the transform based on the size of the element. However, this poses a
michael@0 1290 * problem, because only two of these values can be explicitly referenced
michael@0 1291 * using the named transforms. Until a real solution is found, we'll just
michael@0 1292 * use this approach.
michael@0 1293 */
michael@0 1294 nsRect bounds =
michael@0 1295 (mInnerFrame ? nsDisplayTransform::GetFrameBoundsForTransform(mInnerFrame) :
michael@0 1296 nsRect(0, 0, 0, 0));
michael@0 1297
michael@0 1298 bool dummy;
michael@0 1299 gfx3DMatrix matrix =
michael@0 1300 nsStyleTransformMatrix::ReadTransforms(display->mSpecifiedTransform->mHead,
michael@0 1301 mStyleContextHolder,
michael@0 1302 mStyleContextHolder->PresContext(),
michael@0 1303 dummy,
michael@0 1304 bounds,
michael@0 1305 float(mozilla::AppUnitsPerCSSPixel()));
michael@0 1306
michael@0 1307 return MatrixToCSSValue(matrix);
michael@0 1308 }
michael@0 1309
michael@0 1310 /* static */ nsROCSSPrimitiveValue*
michael@0 1311 nsComputedDOMStyle::MatrixToCSSValue(gfx3DMatrix& matrix)
michael@0 1312 {
michael@0 1313 bool is3D = !matrix.Is2D();
michael@0 1314
michael@0 1315 nsAutoString resultString(NS_LITERAL_STRING("matrix"));
michael@0 1316 if (is3D) {
michael@0 1317 resultString.Append(NS_LITERAL_STRING("3d"));
michael@0 1318 }
michael@0 1319
michael@0 1320 resultString.Append(NS_LITERAL_STRING("("));
michael@0 1321 resultString.AppendFloat(matrix._11);
michael@0 1322 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1323 resultString.AppendFloat(matrix._12);
michael@0 1324 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1325 if (is3D) {
michael@0 1326 resultString.AppendFloat(matrix._13);
michael@0 1327 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1328 resultString.AppendFloat(matrix._14);
michael@0 1329 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1330 }
michael@0 1331 resultString.AppendFloat(matrix._21);
michael@0 1332 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1333 resultString.AppendFloat(matrix._22);
michael@0 1334 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1335 if (is3D) {
michael@0 1336 resultString.AppendFloat(matrix._23);
michael@0 1337 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1338 resultString.AppendFloat(matrix._24);
michael@0 1339 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1340 resultString.AppendFloat(matrix._31);
michael@0 1341 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1342 resultString.AppendFloat(matrix._32);
michael@0 1343 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1344 resultString.AppendFloat(matrix._33);
michael@0 1345 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1346 resultString.AppendFloat(matrix._34);
michael@0 1347 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1348 }
michael@0 1349 resultString.AppendFloat(matrix._41);
michael@0 1350 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1351 resultString.AppendFloat(matrix._42);
michael@0 1352 if (is3D) {
michael@0 1353 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1354 resultString.AppendFloat(matrix._43);
michael@0 1355 resultString.Append(NS_LITERAL_STRING(", "));
michael@0 1356 resultString.AppendFloat(matrix._44);
michael@0 1357 }
michael@0 1358 resultString.Append(NS_LITERAL_STRING(")"));
michael@0 1359
michael@0 1360 /* Create a value to hold our result. */
michael@0 1361 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1362
michael@0 1363 val->SetString(resultString);
michael@0 1364 return val;
michael@0 1365 }
michael@0 1366
michael@0 1367 CSSValue*
michael@0 1368 nsComputedDOMStyle::DoGetCounterReset()
michael@0 1369 {
michael@0 1370 const nsStyleContent *content = StyleContent();
michael@0 1371
michael@0 1372 if (content->CounterResetCount() == 0) {
michael@0 1373 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 1374 val->SetIdent(eCSSKeyword_none);
michael@0 1375 return val;
michael@0 1376 }
michael@0 1377
michael@0 1378 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 1379
michael@0 1380 for (uint32_t i = 0, i_end = content->CounterResetCount(); i < i_end; ++i) {
michael@0 1381 nsROCSSPrimitiveValue* name = new nsROCSSPrimitiveValue;
michael@0 1382 valueList->AppendCSSValue(name);
michael@0 1383
michael@0 1384 nsROCSSPrimitiveValue* value = new nsROCSSPrimitiveValue;
michael@0 1385 valueList->AppendCSSValue(value);
michael@0 1386
michael@0 1387 const nsStyleCounterData *data = content->GetCounterResetAt(i);
michael@0 1388 nsAutoString escaped;
michael@0 1389 nsStyleUtil::AppendEscapedCSSIdent(data->mCounter, escaped);
michael@0 1390 name->SetString(escaped);
michael@0 1391 value->SetNumber(data->mValue); // XXX This should really be integer
michael@0 1392 }
michael@0 1393
michael@0 1394 return valueList;
michael@0 1395 }
michael@0 1396
michael@0 1397 CSSValue*
michael@0 1398 nsComputedDOMStyle::DoGetQuotes()
michael@0 1399 {
michael@0 1400 const nsStyleQuotes *quotes = StyleQuotes();
michael@0 1401
michael@0 1402 if (quotes->QuotesCount() == 0) {
michael@0 1403 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 1404 val->SetIdent(eCSSKeyword_none);
michael@0 1405 return val;
michael@0 1406 }
michael@0 1407
michael@0 1408 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 1409
michael@0 1410 for (uint32_t i = 0, i_end = quotes->QuotesCount(); i < i_end; ++i) {
michael@0 1411 nsROCSSPrimitiveValue* openVal = new nsROCSSPrimitiveValue;
michael@0 1412 valueList->AppendCSSValue(openVal);
michael@0 1413
michael@0 1414 nsROCSSPrimitiveValue* closeVal = new nsROCSSPrimitiveValue;
michael@0 1415 valueList->AppendCSSValue(closeVal);
michael@0 1416
michael@0 1417 nsString s;
michael@0 1418 nsStyleUtil::AppendEscapedCSSString(*quotes->OpenQuoteAt(i), s);
michael@0 1419 openVal->SetString(s);
michael@0 1420 s.Truncate();
michael@0 1421 nsStyleUtil::AppendEscapedCSSString(*quotes->CloseQuoteAt(i), s);
michael@0 1422 closeVal->SetString(s);
michael@0 1423 }
michael@0 1424
michael@0 1425 return valueList;
michael@0 1426 }
michael@0 1427
michael@0 1428 CSSValue*
michael@0 1429 nsComputedDOMStyle::DoGetFontFamily()
michael@0 1430 {
michael@0 1431 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1432
michael@0 1433 const nsStyleFont* font = StyleFont();
michael@0 1434
michael@0 1435 nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocumentWeak);
michael@0 1436 NS_ASSERTION(doc, "document is required");
michael@0 1437 nsIPresShell* presShell = doc->GetShell();
michael@0 1438 NS_ASSERTION(presShell, "pres shell is required");
michael@0 1439 nsPresContext *presContext = presShell->GetPresContext();
michael@0 1440 NS_ASSERTION(presContext, "pres context is required");
michael@0 1441
michael@0 1442 const nsString& fontName = font->mFont.name;
michael@0 1443 if (font->mGenericID == kGenericFont_NONE && !font->mFont.systemFont) {
michael@0 1444 const nsFont* defaultFont =
michael@0 1445 presContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID,
michael@0 1446 font->mLanguage);
michael@0 1447
michael@0 1448 int32_t lendiff = fontName.Length() - defaultFont->name.Length();
michael@0 1449 if (lendiff > 0) {
michael@0 1450 val->SetString(Substring(fontName, 0, lendiff-1)); // -1 removes comma
michael@0 1451 } else {
michael@0 1452 val->SetString(fontName);
michael@0 1453 }
michael@0 1454 } else {
michael@0 1455 val->SetString(fontName);
michael@0 1456 }
michael@0 1457
michael@0 1458 return val;
michael@0 1459 }
michael@0 1460
michael@0 1461 CSSValue*
michael@0 1462 nsComputedDOMStyle::DoGetFontSize()
michael@0 1463 {
michael@0 1464 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1465
michael@0 1466 // Note: StyleFont()->mSize is the 'computed size';
michael@0 1467 // StyleFont()->mFont.size is the 'actual size'
michael@0 1468 val->SetAppUnits(StyleFont()->mSize);
michael@0 1469 return val;
michael@0 1470 }
michael@0 1471
michael@0 1472 CSSValue*
michael@0 1473 nsComputedDOMStyle::DoGetFontSizeAdjust()
michael@0 1474 {
michael@0 1475 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 1476
michael@0 1477 const nsStyleFont *font = StyleFont();
michael@0 1478
michael@0 1479 if (font->mFont.sizeAdjust) {
michael@0 1480 val->SetNumber(font->mFont.sizeAdjust);
michael@0 1481 } else {
michael@0 1482 val->SetIdent(eCSSKeyword_none);
michael@0 1483 }
michael@0 1484
michael@0 1485 return val;
michael@0 1486 }
michael@0 1487
michael@0 1488 CSSValue*
michael@0 1489 nsComputedDOMStyle::DoGetOSXFontSmoothing()
michael@0 1490 {
michael@0 1491 if (!nsContentUtils::IsCallerChrome())
michael@0 1492 return nullptr;
michael@0 1493
michael@0 1494 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1495 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.smoothing,
michael@0 1496 nsCSSProps::kFontSmoothingKTable));
michael@0 1497 return val;
michael@0 1498 }
michael@0 1499
michael@0 1500 CSSValue*
michael@0 1501 nsComputedDOMStyle::DoGetFontStretch()
michael@0 1502 {
michael@0 1503 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1504
michael@0 1505 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.stretch,
michael@0 1506 nsCSSProps::kFontStretchKTable));
michael@0 1507
michael@0 1508 return val;
michael@0 1509 }
michael@0 1510
michael@0 1511 CSSValue*
michael@0 1512 nsComputedDOMStyle::DoGetFontStyle()
michael@0 1513 {
michael@0 1514 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1515 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.style,
michael@0 1516 nsCSSProps::kFontStyleKTable));
michael@0 1517 return val;
michael@0 1518 }
michael@0 1519
michael@0 1520 CSSValue*
michael@0 1521 nsComputedDOMStyle::DoGetFontWeight()
michael@0 1522 {
michael@0 1523 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1524
michael@0 1525 const nsStyleFont* font = StyleFont();
michael@0 1526
michael@0 1527 uint16_t weight = font->mFont.weight;
michael@0 1528 NS_ASSERTION(weight % 100 == 0, "unexpected value of font-weight");
michael@0 1529 val->SetNumber(weight);
michael@0 1530
michael@0 1531 return val;
michael@0 1532 }
michael@0 1533
michael@0 1534 CSSValue*
michael@0 1535 nsComputedDOMStyle::DoGetFontVariant()
michael@0 1536 {
michael@0 1537 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1538 val->SetIdent(
michael@0 1539 nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.variant,
michael@0 1540 nsCSSProps::kFontVariantKTable));
michael@0 1541 return val;
michael@0 1542 }
michael@0 1543
michael@0 1544 CSSValue*
michael@0 1545 nsComputedDOMStyle::DoGetFontFeatureSettings()
michael@0 1546 {
michael@0 1547 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1548
michael@0 1549 const nsStyleFont* font = StyleFont();
michael@0 1550 if (font->mFont.fontFeatureSettings.IsEmpty()) {
michael@0 1551 val->SetIdent(eCSSKeyword_normal);
michael@0 1552 } else {
michael@0 1553 nsAutoString result;
michael@0 1554 nsStyleUtil::AppendFontFeatureSettings(font->mFont.fontFeatureSettings,
michael@0 1555 result);
michael@0 1556 val->SetString(result);
michael@0 1557 }
michael@0 1558 return val;
michael@0 1559 }
michael@0 1560
michael@0 1561 CSSValue*
michael@0 1562 nsComputedDOMStyle::DoGetFontKerning()
michael@0 1563 {
michael@0 1564 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1565 val->SetIdent(
michael@0 1566 nsCSSProps::ValueToKeywordEnum(StyleFont()->mFont.kerning,
michael@0 1567 nsCSSProps::kFontKerningKTable));
michael@0 1568 return val;
michael@0 1569 }
michael@0 1570
michael@0 1571 CSSValue*
michael@0 1572 nsComputedDOMStyle::DoGetFontLanguageOverride()
michael@0 1573 {
michael@0 1574 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1575
michael@0 1576 const nsStyleFont* font = StyleFont();
michael@0 1577 if (font->mFont.languageOverride.IsEmpty()) {
michael@0 1578 val->SetIdent(eCSSKeyword_normal);
michael@0 1579 } else {
michael@0 1580 nsString str;
michael@0 1581 nsStyleUtil::AppendEscapedCSSString(font->mFont.languageOverride, str);
michael@0 1582 val->SetString(str);
michael@0 1583 }
michael@0 1584 return val;
michael@0 1585 }
michael@0 1586
michael@0 1587 CSSValue*
michael@0 1588 nsComputedDOMStyle::DoGetFontSynthesis()
michael@0 1589 {
michael@0 1590 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1591
michael@0 1592 int32_t intValue = StyleFont()->mFont.synthesis;
michael@0 1593
michael@0 1594 if (0 == intValue) {
michael@0 1595 val->SetIdent(eCSSKeyword_none);
michael@0 1596 } else {
michael@0 1597 nsAutoString valueStr;
michael@0 1598
michael@0 1599 nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_synthesis,
michael@0 1600 intValue, NS_FONT_SYNTHESIS_WEIGHT,
michael@0 1601 NS_FONT_SYNTHESIS_STYLE, valueStr);
michael@0 1602 val->SetString(valueStr);
michael@0 1603 }
michael@0 1604
michael@0 1605 return val;
michael@0 1606 }
michael@0 1607
michael@0 1608 CSSValue*
michael@0 1609 nsComputedDOMStyle::DoGetFontVariantAlternates()
michael@0 1610 {
michael@0 1611 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1612
michael@0 1613 int32_t intValue = StyleFont()->mFont.variantAlternates;
michael@0 1614
michael@0 1615 if (0 == intValue) {
michael@0 1616 val->SetIdent(eCSSKeyword_normal);
michael@0 1617 return val;
michael@0 1618 }
michael@0 1619
michael@0 1620 // first, include enumerated values
michael@0 1621 nsAutoString valueStr;
michael@0 1622
michael@0 1623 nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_alternates,
michael@0 1624 intValue & NS_FONT_VARIANT_ALTERNATES_ENUMERATED_MASK,
michael@0 1625 NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
michael@0 1626 NS_FONT_VARIANT_ALTERNATES_HISTORICAL, valueStr);
michael@0 1627
michael@0 1628 // next, include functional values if present
michael@0 1629 if (intValue & NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK) {
michael@0 1630 nsStyleUtil::SerializeFunctionalAlternates(StyleFont()->mFont.alternateValues,
michael@0 1631 valueStr);
michael@0 1632 }
michael@0 1633
michael@0 1634 val->SetString(valueStr);
michael@0 1635 return val;
michael@0 1636 }
michael@0 1637
michael@0 1638
michael@0 1639 CSSValue*
michael@0 1640 nsComputedDOMStyle::DoGetFontVariantCaps()
michael@0 1641 {
michael@0 1642 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1643
michael@0 1644 int32_t intValue = StyleFont()->mFont.variantCaps;
michael@0 1645
michael@0 1646 if (0 == intValue) {
michael@0 1647 val->SetIdent(eCSSKeyword_normal);
michael@0 1648 } else {
michael@0 1649 val->SetIdent(
michael@0 1650 nsCSSProps::ValueToKeywordEnum(intValue,
michael@0 1651 nsCSSProps::kFontVariantCapsKTable));
michael@0 1652 }
michael@0 1653
michael@0 1654 return val;
michael@0 1655 }
michael@0 1656
michael@0 1657 CSSValue*
michael@0 1658 nsComputedDOMStyle::DoGetFontVariantEastAsian()
michael@0 1659 {
michael@0 1660 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1661
michael@0 1662 int32_t intValue = StyleFont()->mFont.variantEastAsian;
michael@0 1663
michael@0 1664 if (0 == intValue) {
michael@0 1665 val->SetIdent(eCSSKeyword_normal);
michael@0 1666 } else {
michael@0 1667 nsAutoString valueStr;
michael@0 1668
michael@0 1669 nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_east_asian,
michael@0 1670 intValue, NS_FONT_VARIANT_EAST_ASIAN_JIS78,
michael@0 1671 NS_FONT_VARIANT_EAST_ASIAN_RUBY, valueStr);
michael@0 1672 val->SetString(valueStr);
michael@0 1673 }
michael@0 1674
michael@0 1675 return val;
michael@0 1676 }
michael@0 1677
michael@0 1678 CSSValue*
michael@0 1679 nsComputedDOMStyle::DoGetFontVariantLigatures()
michael@0 1680 {
michael@0 1681 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1682
michael@0 1683 int32_t intValue = StyleFont()->mFont.variantLigatures;
michael@0 1684
michael@0 1685 if (0 == intValue) {
michael@0 1686 val->SetIdent(eCSSKeyword_normal);
michael@0 1687 } else {
michael@0 1688 nsAutoString valueStr;
michael@0 1689
michael@0 1690 nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_ligatures,
michael@0 1691 intValue, NS_FONT_VARIANT_LIGATURES_NONE,
michael@0 1692 NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL, valueStr);
michael@0 1693 val->SetString(valueStr);
michael@0 1694 }
michael@0 1695
michael@0 1696 return val;
michael@0 1697 }
michael@0 1698
michael@0 1699 CSSValue*
michael@0 1700 nsComputedDOMStyle::DoGetFontVariantNumeric()
michael@0 1701 {
michael@0 1702 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1703
michael@0 1704 int32_t intValue = StyleFont()->mFont.variantNumeric;
michael@0 1705
michael@0 1706 if (0 == intValue) {
michael@0 1707 val->SetIdent(eCSSKeyword_normal);
michael@0 1708 } else {
michael@0 1709 nsAutoString valueStr;
michael@0 1710
michael@0 1711 nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_font_variant_numeric,
michael@0 1712 intValue, NS_FONT_VARIANT_NUMERIC_LINING,
michael@0 1713 NS_FONT_VARIANT_NUMERIC_ORDINAL, valueStr);
michael@0 1714 val->SetString(valueStr);
michael@0 1715 }
michael@0 1716
michael@0 1717 return val;
michael@0 1718 }
michael@0 1719
michael@0 1720 CSSValue*
michael@0 1721 nsComputedDOMStyle::DoGetFontVariantPosition()
michael@0 1722 {
michael@0 1723 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1724
michael@0 1725 int32_t intValue = StyleFont()->mFont.variantPosition;
michael@0 1726
michael@0 1727 if (0 == intValue) {
michael@0 1728 val->SetIdent(eCSSKeyword_normal);
michael@0 1729 } else {
michael@0 1730 val->SetIdent(
michael@0 1731 nsCSSProps::ValueToKeywordEnum(intValue,
michael@0 1732 nsCSSProps::kFontVariantPositionKTable));
michael@0 1733 }
michael@0 1734
michael@0 1735 return val;
michael@0 1736 }
michael@0 1737
michael@0 1738 CSSValue*
michael@0 1739 nsComputedDOMStyle::GetBackgroundList(uint8_t nsStyleBackground::Layer::* aMember,
michael@0 1740 uint32_t nsStyleBackground::* aCount,
michael@0 1741 const KTableValue aTable[])
michael@0 1742 {
michael@0 1743 const nsStyleBackground* bg = StyleBackground();
michael@0 1744
michael@0 1745 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 1746
michael@0 1747 for (uint32_t i = 0, i_end = bg->*aCount; i < i_end; ++i) {
michael@0 1748 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 1749 valueList->AppendCSSValue(val);
michael@0 1750 val->SetIdent(nsCSSProps::ValueToKeywordEnum(bg->mLayers[i].*aMember,
michael@0 1751 aTable));
michael@0 1752 }
michael@0 1753
michael@0 1754 return valueList;
michael@0 1755 }
michael@0 1756
michael@0 1757 CSSValue*
michael@0 1758 nsComputedDOMStyle::DoGetBackgroundAttachment()
michael@0 1759 {
michael@0 1760 return GetBackgroundList(&nsStyleBackground::Layer::mAttachment,
michael@0 1761 &nsStyleBackground::mAttachmentCount,
michael@0 1762 nsCSSProps::kBackgroundAttachmentKTable);
michael@0 1763 }
michael@0 1764
michael@0 1765 CSSValue*
michael@0 1766 nsComputedDOMStyle::DoGetBackgroundClip()
michael@0 1767 {
michael@0 1768 return GetBackgroundList(&nsStyleBackground::Layer::mClip,
michael@0 1769 &nsStyleBackground::mClipCount,
michael@0 1770 nsCSSProps::kBackgroundOriginKTable);
michael@0 1771 }
michael@0 1772
michael@0 1773 CSSValue*
michael@0 1774 nsComputedDOMStyle::DoGetBackgroundColor()
michael@0 1775 {
michael@0 1776 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 1777 SetToRGBAColor(val, StyleBackground()->mBackgroundColor);
michael@0 1778 return val;
michael@0 1779 }
michael@0 1780
michael@0 1781
michael@0 1782 static void
michael@0 1783 SetValueToCalc(const nsStyleCoord::Calc *aCalc, nsROCSSPrimitiveValue *aValue)
michael@0 1784 {
michael@0 1785 nsRefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
michael@0 1786 nsAutoString tmp, result;
michael@0 1787
michael@0 1788 result.AppendLiteral("calc(");
michael@0 1789
michael@0 1790 val->SetAppUnits(aCalc->mLength);
michael@0 1791 val->GetCssText(tmp);
michael@0 1792 result.Append(tmp);
michael@0 1793
michael@0 1794 if (aCalc->mHasPercent) {
michael@0 1795 result.AppendLiteral(" + ");
michael@0 1796
michael@0 1797 val->SetPercent(aCalc->mPercent);
michael@0 1798 val->GetCssText(tmp);
michael@0 1799 result.Append(tmp);
michael@0 1800 }
michael@0 1801
michael@0 1802 result.AppendLiteral(")");
michael@0 1803
michael@0 1804 aValue->SetString(result); // not really SetString
michael@0 1805 }
michael@0 1806
michael@0 1807 static void
michael@0 1808 AppendCSSGradientLength(const nsStyleCoord& aValue,
michael@0 1809 nsROCSSPrimitiveValue* aPrimitive,
michael@0 1810 nsAString& aString)
michael@0 1811 {
michael@0 1812 nsAutoString tokenString;
michael@0 1813 if (aValue.IsCalcUnit())
michael@0 1814 SetValueToCalc(aValue.GetCalcValue(), aPrimitive);
michael@0 1815 else if (aValue.GetUnit() == eStyleUnit_Coord)
michael@0 1816 aPrimitive->SetAppUnits(aValue.GetCoordValue());
michael@0 1817 else
michael@0 1818 aPrimitive->SetPercent(aValue.GetPercentValue());
michael@0 1819 aPrimitive->GetCssText(tokenString);
michael@0 1820 aString.Append(tokenString);
michael@0 1821 }
michael@0 1822
michael@0 1823 static void
michael@0 1824 AppendCSSGradientToBoxPosition(const nsStyleGradient* aGradient,
michael@0 1825 nsAString& aString,
michael@0 1826 bool& aNeedSep)
michael@0 1827 {
michael@0 1828 float xValue = aGradient->mBgPosX.GetPercentValue();
michael@0 1829 float yValue = aGradient->mBgPosY.GetPercentValue();
michael@0 1830
michael@0 1831 if (yValue == 1.0f && xValue == 0.5f) {
michael@0 1832 // omit "to bottom"
michael@0 1833 return;
michael@0 1834 }
michael@0 1835 NS_ASSERTION(yValue != 0.5f || xValue != 0.5f, "invalid box position");
michael@0 1836
michael@0 1837 aString.AppendLiteral("to");
michael@0 1838
michael@0 1839 if (yValue == 0.0f) {
michael@0 1840 aString.AppendLiteral(" top");
michael@0 1841 } else if (yValue == 1.0f) {
michael@0 1842 aString.AppendLiteral(" bottom");
michael@0 1843 } else if (yValue != 0.5f) { // do not write "center" keyword
michael@0 1844 NS_NOTREACHED("invalid box position");
michael@0 1845 }
michael@0 1846
michael@0 1847 if (xValue == 0.0f) {
michael@0 1848 aString.AppendLiteral(" left");
michael@0 1849 } else if (xValue == 1.0f) {
michael@0 1850 aString.AppendLiteral(" right");
michael@0 1851 } else if (xValue != 0.5f) { // do not write "center" keyword
michael@0 1852 NS_NOTREACHED("invalid box position");
michael@0 1853 }
michael@0 1854
michael@0 1855 aNeedSep = true;
michael@0 1856 }
michael@0 1857
michael@0 1858 void
michael@0 1859 nsComputedDOMStyle::GetCSSGradientString(const nsStyleGradient* aGradient,
michael@0 1860 nsAString& aString)
michael@0 1861 {
michael@0 1862 if (!aGradient->mLegacySyntax) {
michael@0 1863 aString.Truncate();
michael@0 1864 } else {
michael@0 1865 aString.AssignLiteral("-moz-");
michael@0 1866 }
michael@0 1867 if (aGradient->mRepeating) {
michael@0 1868 aString.AppendLiteral("repeating-");
michael@0 1869 }
michael@0 1870 bool isRadial = aGradient->mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR;
michael@0 1871 if (isRadial) {
michael@0 1872 aString.AppendLiteral("radial-gradient(");
michael@0 1873 } else {
michael@0 1874 aString.AppendLiteral("linear-gradient(");
michael@0 1875 }
michael@0 1876
michael@0 1877 bool needSep = false;
michael@0 1878 nsAutoString tokenString;
michael@0 1879 nsROCSSPrimitiveValue *tmpVal = new nsROCSSPrimitiveValue;
michael@0 1880
michael@0 1881 if (isRadial && !aGradient->mLegacySyntax) {
michael@0 1882 if (aGradient->mSize != NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE) {
michael@0 1883 if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
michael@0 1884 aString.AppendLiteral("circle");
michael@0 1885 needSep = true;
michael@0 1886 }
michael@0 1887 if (aGradient->mSize != NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) {
michael@0 1888 if (needSep) {
michael@0 1889 aString.AppendLiteral(" ");
michael@0 1890 }
michael@0 1891 AppendASCIItoUTF16(nsCSSProps::
michael@0 1892 ValueToKeyword(aGradient->mSize,
michael@0 1893 nsCSSProps::kRadialGradientSizeKTable),
michael@0 1894 aString);
michael@0 1895 needSep = true;
michael@0 1896 }
michael@0 1897 } else {
michael@0 1898 AppendCSSGradientLength(aGradient->mRadiusX, tmpVal, aString);
michael@0 1899 if (aGradient->mShape != NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
michael@0 1900 aString.AppendLiteral(" ");
michael@0 1901 AppendCSSGradientLength(aGradient->mRadiusY, tmpVal, aString);
michael@0 1902 }
michael@0 1903 needSep = true;
michael@0 1904 }
michael@0 1905 }
michael@0 1906 if (aGradient->mBgPosX.GetUnit() != eStyleUnit_None) {
michael@0 1907 MOZ_ASSERT(aGradient->mBgPosY.GetUnit() != eStyleUnit_None);
michael@0 1908 if (!isRadial && !aGradient->mLegacySyntax) {
michael@0 1909 AppendCSSGradientToBoxPosition(aGradient, aString, needSep);
michael@0 1910 } else if (aGradient->mBgPosX.GetUnit() != eStyleUnit_Percent ||
michael@0 1911 aGradient->mBgPosX.GetPercentValue() != 0.5f ||
michael@0 1912 aGradient->mBgPosY.GetUnit() != eStyleUnit_Percent ||
michael@0 1913 aGradient->mBgPosY.GetPercentValue() != (isRadial ? 0.5f : 1.0f)) {
michael@0 1914 if (isRadial && !aGradient->mLegacySyntax) {
michael@0 1915 if (needSep) {
michael@0 1916 aString.AppendLiteral(" ");
michael@0 1917 }
michael@0 1918 aString.AppendLiteral("at ");
michael@0 1919 needSep = false;
michael@0 1920 }
michael@0 1921 AppendCSSGradientLength(aGradient->mBgPosX, tmpVal, aString);
michael@0 1922 if (aGradient->mBgPosY.GetUnit() != eStyleUnit_None) {
michael@0 1923 aString.AppendLiteral(" ");
michael@0 1924 AppendCSSGradientLength(aGradient->mBgPosY, tmpVal, aString);
michael@0 1925 }
michael@0 1926 needSep = true;
michael@0 1927 }
michael@0 1928 }
michael@0 1929 if (aGradient->mAngle.GetUnit() != eStyleUnit_None) {
michael@0 1930 MOZ_ASSERT(!isRadial || aGradient->mLegacySyntax);
michael@0 1931 if (needSep) {
michael@0 1932 aString.AppendLiteral(" ");
michael@0 1933 }
michael@0 1934 nsStyleUtil::AppendAngleValue(aGradient->mAngle, aString);
michael@0 1935 needSep = true;
michael@0 1936 }
michael@0 1937
michael@0 1938 if (isRadial && aGradient->mLegacySyntax &&
michael@0 1939 (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR ||
michael@0 1940 aGradient->mSize != NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)) {
michael@0 1941 MOZ_ASSERT(aGradient->mSize != NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE);
michael@0 1942 if (needSep) {
michael@0 1943 aString.AppendLiteral(", ");
michael@0 1944 needSep = false;
michael@0 1945 }
michael@0 1946 if (aGradient->mShape == NS_STYLE_GRADIENT_SHAPE_CIRCULAR) {
michael@0 1947 aString.AppendLiteral("circle");
michael@0 1948 needSep = true;
michael@0 1949 }
michael@0 1950 if (aGradient->mSize != NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) {
michael@0 1951 if (needSep) {
michael@0 1952 aString.AppendLiteral(" ");
michael@0 1953 }
michael@0 1954 AppendASCIItoUTF16(nsCSSProps::
michael@0 1955 ValueToKeyword(aGradient->mSize,
michael@0 1956 nsCSSProps::kRadialGradientSizeKTable),
michael@0 1957 aString);
michael@0 1958 }
michael@0 1959 needSep = true;
michael@0 1960 }
michael@0 1961
michael@0 1962
michael@0 1963 // color stops
michael@0 1964 for (uint32_t i = 0; i < aGradient->mStops.Length(); ++i) {
michael@0 1965 if (needSep) {
michael@0 1966 aString.AppendLiteral(", ");
michael@0 1967 }
michael@0 1968 SetToRGBAColor(tmpVal, aGradient->mStops[i].mColor);
michael@0 1969 tmpVal->GetCssText(tokenString);
michael@0 1970 aString.Append(tokenString);
michael@0 1971
michael@0 1972 if (aGradient->mStops[i].mLocation.GetUnit() != eStyleUnit_None) {
michael@0 1973 aString.AppendLiteral(" ");
michael@0 1974 AppendCSSGradientLength(aGradient->mStops[i].mLocation, tmpVal, aString);
michael@0 1975 }
michael@0 1976 needSep = true;
michael@0 1977 }
michael@0 1978
michael@0 1979 delete tmpVal;
michael@0 1980 aString.AppendLiteral(")");
michael@0 1981 }
michael@0 1982
michael@0 1983 // -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>)
michael@0 1984 void
michael@0 1985 nsComputedDOMStyle::GetImageRectString(nsIURI* aURI,
michael@0 1986 const nsStyleSides& aCropRect,
michael@0 1987 nsString& aString)
michael@0 1988 {
michael@0 1989 nsDOMCSSValueList* valueList = GetROCSSValueList(true);
michael@0 1990
michael@0 1991 // <uri>
michael@0 1992 nsROCSSPrimitiveValue *valURI = new nsROCSSPrimitiveValue;
michael@0 1993 valueList->AppendCSSValue(valURI);
michael@0 1994 valURI->SetURI(aURI);
michael@0 1995
michael@0 1996 // <top>, <right>, <bottom>, <left>
michael@0 1997 NS_FOR_CSS_SIDES(side) {
michael@0 1998 nsROCSSPrimitiveValue *valSide = new nsROCSSPrimitiveValue;
michael@0 1999 valueList->AppendCSSValue(valSide);
michael@0 2000 SetValueToCoord(valSide, aCropRect.Get(side), false);
michael@0 2001 }
michael@0 2002
michael@0 2003 nsAutoString argumentString;
michael@0 2004 valueList->GetCssText(argumentString);
michael@0 2005 delete valueList;
michael@0 2006
michael@0 2007 aString = NS_LITERAL_STRING("-moz-image-rect(") +
michael@0 2008 argumentString +
michael@0 2009 NS_LITERAL_STRING(")");
michael@0 2010 }
michael@0 2011
michael@0 2012 void
michael@0 2013 nsComputedDOMStyle::SetValueToStyleImage(const nsStyleImage& aStyleImage,
michael@0 2014 nsROCSSPrimitiveValue* aValue)
michael@0 2015 {
michael@0 2016 switch (aStyleImage.GetType()) {
michael@0 2017 case eStyleImageType_Image:
michael@0 2018 {
michael@0 2019 imgIRequest *req = aStyleImage.GetImageData();
michael@0 2020 nsCOMPtr<nsIURI> uri;
michael@0 2021 req->GetURI(getter_AddRefs(uri));
michael@0 2022
michael@0 2023 const nsStyleSides* cropRect = aStyleImage.GetCropRect();
michael@0 2024 if (cropRect) {
michael@0 2025 nsAutoString imageRectString;
michael@0 2026 GetImageRectString(uri, *cropRect, imageRectString);
michael@0 2027 aValue->SetString(imageRectString);
michael@0 2028 } else {
michael@0 2029 aValue->SetURI(uri);
michael@0 2030 }
michael@0 2031 break;
michael@0 2032 }
michael@0 2033 case eStyleImageType_Gradient:
michael@0 2034 {
michael@0 2035 nsAutoString gradientString;
michael@0 2036 GetCSSGradientString(aStyleImage.GetGradientData(),
michael@0 2037 gradientString);
michael@0 2038 aValue->SetString(gradientString);
michael@0 2039 break;
michael@0 2040 }
michael@0 2041 case eStyleImageType_Element:
michael@0 2042 {
michael@0 2043 nsAutoString elementId;
michael@0 2044 nsStyleUtil::AppendEscapedCSSIdent(
michael@0 2045 nsDependentString(aStyleImage.GetElementId()), elementId);
michael@0 2046 nsAutoString elementString = NS_LITERAL_STRING("-moz-element(#") +
michael@0 2047 elementId +
michael@0 2048 NS_LITERAL_STRING(")");
michael@0 2049 aValue->SetString(elementString);
michael@0 2050 break;
michael@0 2051 }
michael@0 2052 case eStyleImageType_Null:
michael@0 2053 aValue->SetIdent(eCSSKeyword_none);
michael@0 2054 break;
michael@0 2055 default:
michael@0 2056 NS_NOTREACHED("unexpected image type");
michael@0 2057 break;
michael@0 2058 }
michael@0 2059 }
michael@0 2060
michael@0 2061 CSSValue*
michael@0 2062 nsComputedDOMStyle::DoGetBackgroundImage()
michael@0 2063 {
michael@0 2064 const nsStyleBackground* bg = StyleBackground();
michael@0 2065
michael@0 2066 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 2067
michael@0 2068 for (uint32_t i = 0, i_end = bg->mImageCount; i < i_end; ++i) {
michael@0 2069 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2070 valueList->AppendCSSValue(val);
michael@0 2071
michael@0 2072 const nsStyleImage& image = bg->mLayers[i].mImage;
michael@0 2073 SetValueToStyleImage(image, val);
michael@0 2074 }
michael@0 2075
michael@0 2076 return valueList;
michael@0 2077 }
michael@0 2078
michael@0 2079 CSSValue*
michael@0 2080 nsComputedDOMStyle::DoGetBackgroundInlinePolicy()
michael@0 2081 {
michael@0 2082 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2083 val->SetIdent(nsCSSProps::ValueToKeywordEnum(
michael@0 2084 StyleBackground()->mBackgroundInlinePolicy,
michael@0 2085 nsCSSProps::kBackgroundInlinePolicyKTable));
michael@0 2086 return val;
michael@0 2087 }
michael@0 2088
michael@0 2089 CSSValue*
michael@0 2090 nsComputedDOMStyle::DoGetBackgroundBlendMode()
michael@0 2091 {
michael@0 2092 return GetBackgroundList(&nsStyleBackground::Layer::mBlendMode,
michael@0 2093 &nsStyleBackground::mBlendModeCount,
michael@0 2094 nsCSSProps::kBlendModeKTable);
michael@0 2095 }
michael@0 2096
michael@0 2097 CSSValue*
michael@0 2098 nsComputedDOMStyle::DoGetBackgroundOrigin()
michael@0 2099 {
michael@0 2100 return GetBackgroundList(&nsStyleBackground::Layer::mOrigin,
michael@0 2101 &nsStyleBackground::mOriginCount,
michael@0 2102 nsCSSProps::kBackgroundOriginKTable);
michael@0 2103 }
michael@0 2104
michael@0 2105 CSSValue*
michael@0 2106 nsComputedDOMStyle::DoGetBackgroundPosition()
michael@0 2107 {
michael@0 2108 const nsStyleBackground* bg = StyleBackground();
michael@0 2109
michael@0 2110 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 2111
michael@0 2112 for (uint32_t i = 0, i_end = bg->mPositionCount; i < i_end; ++i) {
michael@0 2113 nsDOMCSSValueList *itemList = GetROCSSValueList(false);
michael@0 2114 valueList->AppendCSSValue(itemList);
michael@0 2115
michael@0 2116 nsROCSSPrimitiveValue *valX = new nsROCSSPrimitiveValue;
michael@0 2117 itemList->AppendCSSValue(valX);
michael@0 2118
michael@0 2119 nsROCSSPrimitiveValue *valY = new nsROCSSPrimitiveValue;
michael@0 2120 itemList->AppendCSSValue(valY);
michael@0 2121
michael@0 2122 const nsStyleBackground::Position &pos = bg->mLayers[i].mPosition;
michael@0 2123
michael@0 2124 if (!pos.mXPosition.mHasPercent) {
michael@0 2125 NS_ABORT_IF_FALSE(pos.mXPosition.mPercent == 0.0f,
michael@0 2126 "Shouldn't have mPercent!");
michael@0 2127 valX->SetAppUnits(pos.mXPosition.mLength);
michael@0 2128 } else if (pos.mXPosition.mLength == 0) {
michael@0 2129 valX->SetPercent(pos.mXPosition.mPercent);
michael@0 2130 } else {
michael@0 2131 SetValueToCalc(&pos.mXPosition, valX);
michael@0 2132 }
michael@0 2133
michael@0 2134 if (!pos.mYPosition.mHasPercent) {
michael@0 2135 NS_ABORT_IF_FALSE(pos.mYPosition.mPercent == 0.0f,
michael@0 2136 "Shouldn't have mPercent!");
michael@0 2137 valY->SetAppUnits(pos.mYPosition.mLength);
michael@0 2138 } else if (pos.mYPosition.mLength == 0) {
michael@0 2139 valY->SetPercent(pos.mYPosition.mPercent);
michael@0 2140 } else {
michael@0 2141 SetValueToCalc(&pos.mYPosition, valY);
michael@0 2142 }
michael@0 2143 }
michael@0 2144
michael@0 2145 return valueList;
michael@0 2146 }
michael@0 2147
michael@0 2148 CSSValue*
michael@0 2149 nsComputedDOMStyle::DoGetBackgroundRepeat()
michael@0 2150 {
michael@0 2151 const nsStyleBackground* bg = StyleBackground();
michael@0 2152
michael@0 2153 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 2154
michael@0 2155 for (uint32_t i = 0, i_end = bg->mRepeatCount; i < i_end; ++i) {
michael@0 2156 nsDOMCSSValueList *itemList = GetROCSSValueList(false);
michael@0 2157 valueList->AppendCSSValue(itemList);
michael@0 2158
michael@0 2159 nsROCSSPrimitiveValue *valX = new nsROCSSPrimitiveValue;
michael@0 2160 itemList->AppendCSSValue(valX);
michael@0 2161
michael@0 2162 const uint8_t& xRepeat = bg->mLayers[i].mRepeat.mXRepeat;
michael@0 2163 const uint8_t& yRepeat = bg->mLayers[i].mRepeat.mYRepeat;
michael@0 2164
michael@0 2165 bool hasContraction = true;
michael@0 2166 unsigned contraction;
michael@0 2167 if (xRepeat == yRepeat) {
michael@0 2168 contraction = xRepeat;
michael@0 2169 } else if (xRepeat == NS_STYLE_BG_REPEAT_REPEAT &&
michael@0 2170 yRepeat == NS_STYLE_BG_REPEAT_NO_REPEAT) {
michael@0 2171 contraction = NS_STYLE_BG_REPEAT_REPEAT_X;
michael@0 2172 } else if (xRepeat == NS_STYLE_BG_REPEAT_NO_REPEAT &&
michael@0 2173 yRepeat == NS_STYLE_BG_REPEAT_REPEAT) {
michael@0 2174 contraction = NS_STYLE_BG_REPEAT_REPEAT_Y;
michael@0 2175 } else {
michael@0 2176 hasContraction = false;
michael@0 2177 }
michael@0 2178
michael@0 2179 if (hasContraction) {
michael@0 2180 valX->SetIdent(nsCSSProps::ValueToKeywordEnum(contraction,
michael@0 2181 nsCSSProps::kBackgroundRepeatKTable));
michael@0 2182 } else {
michael@0 2183 nsROCSSPrimitiveValue *valY = new nsROCSSPrimitiveValue;
michael@0 2184 itemList->AppendCSSValue(valY);
michael@0 2185
michael@0 2186 valX->SetIdent(nsCSSProps::ValueToKeywordEnum(xRepeat,
michael@0 2187 nsCSSProps::kBackgroundRepeatKTable));
michael@0 2188 valY->SetIdent(nsCSSProps::ValueToKeywordEnum(yRepeat,
michael@0 2189 nsCSSProps::kBackgroundRepeatKTable));
michael@0 2190 }
michael@0 2191 }
michael@0 2192
michael@0 2193 return valueList;
michael@0 2194 }
michael@0 2195
michael@0 2196 CSSValue*
michael@0 2197 nsComputedDOMStyle::DoGetBackgroundSize()
michael@0 2198 {
michael@0 2199 const nsStyleBackground* bg = StyleBackground();
michael@0 2200
michael@0 2201 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 2202
michael@0 2203 for (uint32_t i = 0, i_end = bg->mSizeCount; i < i_end; ++i) {
michael@0 2204 const nsStyleBackground::Size &size = bg->mLayers[i].mSize;
michael@0 2205
michael@0 2206 switch (size.mWidthType) {
michael@0 2207 case nsStyleBackground::Size::eContain:
michael@0 2208 case nsStyleBackground::Size::eCover: {
michael@0 2209 NS_ABORT_IF_FALSE(size.mWidthType == size.mHeightType,
michael@0 2210 "unsynced types");
michael@0 2211 nsCSSKeyword keyword = size.mWidthType == nsStyleBackground::Size::eContain
michael@0 2212 ? eCSSKeyword_contain
michael@0 2213 : eCSSKeyword_cover;
michael@0 2214 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2215 valueList->AppendCSSValue(val);
michael@0 2216 val->SetIdent(keyword);
michael@0 2217 break;
michael@0 2218 }
michael@0 2219 default: {
michael@0 2220 nsDOMCSSValueList *itemList = GetROCSSValueList(false);
michael@0 2221 valueList->AppendCSSValue(itemList);
michael@0 2222
michael@0 2223 nsROCSSPrimitiveValue* valX = new nsROCSSPrimitiveValue;
michael@0 2224 itemList->AppendCSSValue(valX);
michael@0 2225 nsROCSSPrimitiveValue* valY = new nsROCSSPrimitiveValue;
michael@0 2226 itemList->AppendCSSValue(valY);
michael@0 2227
michael@0 2228 if (size.mWidthType == nsStyleBackground::Size::eAuto) {
michael@0 2229 valX->SetIdent(eCSSKeyword_auto);
michael@0 2230 } else {
michael@0 2231 NS_ABORT_IF_FALSE(size.mWidthType ==
michael@0 2232 nsStyleBackground::Size::eLengthPercentage,
michael@0 2233 "bad mWidthType");
michael@0 2234 if (!size.mWidth.mHasPercent &&
michael@0 2235 // negative values must have come from calc()
michael@0 2236 size.mWidth.mLength >= 0) {
michael@0 2237 NS_ABORT_IF_FALSE(size.mWidth.mPercent == 0.0f,
michael@0 2238 "Shouldn't have mPercent");
michael@0 2239 valX->SetAppUnits(size.mWidth.mLength);
michael@0 2240 } else if (size.mWidth.mLength == 0 &&
michael@0 2241 // negative values must have come from calc()
michael@0 2242 size.mWidth.mPercent >= 0.0f) {
michael@0 2243 valX->SetPercent(size.mWidth.mPercent);
michael@0 2244 } else {
michael@0 2245 SetValueToCalc(&size.mWidth, valX);
michael@0 2246 }
michael@0 2247 }
michael@0 2248
michael@0 2249 if (size.mHeightType == nsStyleBackground::Size::eAuto) {
michael@0 2250 valY->SetIdent(eCSSKeyword_auto);
michael@0 2251 } else {
michael@0 2252 NS_ABORT_IF_FALSE(size.mHeightType ==
michael@0 2253 nsStyleBackground::Size::eLengthPercentage,
michael@0 2254 "bad mHeightType");
michael@0 2255 if (!size.mHeight.mHasPercent &&
michael@0 2256 // negative values must have come from calc()
michael@0 2257 size.mHeight.mLength >= 0) {
michael@0 2258 NS_ABORT_IF_FALSE(size.mHeight.mPercent == 0.0f,
michael@0 2259 "Shouldn't have mPercent");
michael@0 2260 valY->SetAppUnits(size.mHeight.mLength);
michael@0 2261 } else if (size.mHeight.mLength == 0 &&
michael@0 2262 // negative values must have come from calc()
michael@0 2263 size.mHeight.mPercent >= 0.0f) {
michael@0 2264 valY->SetPercent(size.mHeight.mPercent);
michael@0 2265 } else {
michael@0 2266 SetValueToCalc(&size.mHeight, valY);
michael@0 2267 }
michael@0 2268 }
michael@0 2269 break;
michael@0 2270 }
michael@0 2271 }
michael@0 2272 }
michael@0 2273
michael@0 2274 return valueList;
michael@0 2275 }
michael@0 2276
michael@0 2277 CSSValue*
michael@0 2278 nsComputedDOMStyle::DoGetGridTemplateAreas()
michael@0 2279 {
michael@0 2280 const css::GridTemplateAreasValue* areas =
michael@0 2281 StylePosition()->mGridTemplateAreas;
michael@0 2282 if (!areas) {
michael@0 2283 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2284 val->SetIdent(eCSSKeyword_none);
michael@0 2285 return val;
michael@0 2286 }
michael@0 2287
michael@0 2288 MOZ_ASSERT(!areas->mTemplates.IsEmpty(),
michael@0 2289 "Unexpected empty array in GridTemplateAreasValue");
michael@0 2290 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 2291 for (uint32_t i = 0; i < areas->mTemplates.Length(); i++) {
michael@0 2292 nsAutoString str;
michael@0 2293 nsStyleUtil::AppendEscapedCSSString(areas->mTemplates[i], str);
michael@0 2294 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2295 val->SetString(str);
michael@0 2296 valueList->AppendCSSValue(val);
michael@0 2297 }
michael@0 2298 return valueList;
michael@0 2299 }
michael@0 2300
michael@0 2301 // aLineNames must not be empty
michael@0 2302 CSSValue*
michael@0 2303 nsComputedDOMStyle::GetGridLineNames(const nsTArray<nsString>& aLineNames)
michael@0 2304 {
michael@0 2305 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2306 nsAutoString lineNamesString;
michael@0 2307 uint32_t i_end = aLineNames.Length();
michael@0 2308 lineNamesString.AssignLiteral("(");
michael@0 2309 if (i_end > 0) {
michael@0 2310 for (uint32_t i = 0;;) {
michael@0 2311 nsStyleUtil::AppendEscapedCSSIdent(aLineNames[i], lineNamesString);
michael@0 2312 if (++i == i_end) {
michael@0 2313 break;
michael@0 2314 }
michael@0 2315 lineNamesString.AppendLiteral(" ");
michael@0 2316 }
michael@0 2317 }
michael@0 2318 lineNamesString.AppendLiteral(")");
michael@0 2319 val->SetString(lineNamesString);
michael@0 2320 return val;
michael@0 2321 }
michael@0 2322
michael@0 2323 CSSValue*
michael@0 2324 nsComputedDOMStyle::GetGridTrackSize(const nsStyleCoord& aMinValue,
michael@0 2325 const nsStyleCoord& aMaxValue)
michael@0 2326 {
michael@0 2327 // FIXME bug 978212: for grid-template-columns and grid-template-rows
michael@0 2328 // (not grid-auto-columns and grid-auto-rows), if we have frame,
michael@0 2329 // every <track-size> should be resolved into 'px' here,
michael@0 2330 // based on layout results.
michael@0 2331 if (aMinValue == aMaxValue) {
michael@0 2332 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2333 SetValueToCoord(val, aMinValue, true,
michael@0 2334 nullptr, nsCSSProps::kGridTrackBreadthKTable);
michael@0 2335 return val;
michael@0 2336 }
michael@0 2337
michael@0 2338 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2339 nsAutoString argumentStr, minmaxStr;
michael@0 2340 minmaxStr.AppendLiteral("minmax(");
michael@0 2341
michael@0 2342 SetValueToCoord(val, aMinValue, true,
michael@0 2343 nullptr, nsCSSProps::kGridTrackBreadthKTable);
michael@0 2344 val->GetCssText(argumentStr);
michael@0 2345 minmaxStr.Append(argumentStr);
michael@0 2346
michael@0 2347 minmaxStr.AppendLiteral(", ");
michael@0 2348
michael@0 2349 SetValueToCoord(val, aMaxValue, true,
michael@0 2350 nullptr, nsCSSProps::kGridTrackBreadthKTable);
michael@0 2351 val->GetCssText(argumentStr);
michael@0 2352 minmaxStr.Append(argumentStr);
michael@0 2353
michael@0 2354 minmaxStr.Append(char16_t(')'));
michael@0 2355 val->SetString(minmaxStr);
michael@0 2356 return val;
michael@0 2357 }
michael@0 2358
michael@0 2359 CSSValue*
michael@0 2360 nsComputedDOMStyle::GetGridTemplateColumnsRows(const nsStyleGridTemplate& aTrackList)
michael@0 2361 {
michael@0 2362 if (aTrackList.mIsSubgrid) {
michael@0 2363 NS_ASSERTION(aTrackList.mMinTrackSizingFunctions.IsEmpty() &&
michael@0 2364 aTrackList.mMaxTrackSizingFunctions.IsEmpty(),
michael@0 2365 "Unexpected sizing functions with subgrid");
michael@0 2366 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 2367
michael@0 2368 nsROCSSPrimitiveValue* subgridKeyword = new nsROCSSPrimitiveValue;
michael@0 2369 subgridKeyword->SetIdent(eCSSKeyword_subgrid);
michael@0 2370 valueList->AppendCSSValue(subgridKeyword);
michael@0 2371
michael@0 2372 for (uint32_t i = 0; i < aTrackList.mLineNameLists.Length(); i++) {
michael@0 2373 valueList->AppendCSSValue(GetGridLineNames(aTrackList.mLineNameLists[i]));
michael@0 2374 }
michael@0 2375 return valueList;
michael@0 2376 }
michael@0 2377
michael@0 2378 uint32_t numSizes = aTrackList.mMinTrackSizingFunctions.Length();
michael@0 2379 MOZ_ASSERT(aTrackList.mMaxTrackSizingFunctions.Length() == numSizes,
michael@0 2380 "Different number of min and max track sizing functions");
michael@0 2381 // An empty <track-list> is represented as "none" in syntax.
michael@0 2382 if (numSizes == 0) {
michael@0 2383 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2384 val->SetIdent(eCSSKeyword_none);
michael@0 2385 return val;
michael@0 2386 }
michael@0 2387
michael@0 2388 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 2389 // Delimiting N tracks requires N+1 lines:
michael@0 2390 // one before each track, plus one at the very end.
michael@0 2391 MOZ_ASSERT(aTrackList.mLineNameLists.Length() == numSizes + 1,
michael@0 2392 "Unexpected number of line name lists");
michael@0 2393 for (uint32_t i = 0;; i++) {
michael@0 2394 const nsTArray<nsString>& lineNames = aTrackList.mLineNameLists[i];
michael@0 2395 if (!lineNames.IsEmpty()) {
michael@0 2396 valueList->AppendCSSValue(GetGridLineNames(lineNames));
michael@0 2397 }
michael@0 2398 if (i == numSizes) {
michael@0 2399 break;
michael@0 2400 }
michael@0 2401 valueList->AppendCSSValue(GetGridTrackSize(aTrackList.mMinTrackSizingFunctions[i],
michael@0 2402 aTrackList.mMaxTrackSizingFunctions[i]));
michael@0 2403 }
michael@0 2404
michael@0 2405 return valueList;
michael@0 2406 }
michael@0 2407
michael@0 2408 CSSValue*
michael@0 2409 nsComputedDOMStyle::DoGetGridAutoFlow()
michael@0 2410 {
michael@0 2411 nsAutoString str;
michael@0 2412 nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_grid_auto_flow,
michael@0 2413 StylePosition()->mGridAutoFlow,
michael@0 2414 NS_STYLE_GRID_AUTO_FLOW_NONE,
michael@0 2415 NS_STYLE_GRID_AUTO_FLOW_DENSE,
michael@0 2416 str);
michael@0 2417 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2418 val->SetString(str);
michael@0 2419 return val;
michael@0 2420 }
michael@0 2421
michael@0 2422 CSSValue*
michael@0 2423 nsComputedDOMStyle::DoGetGridAutoColumns()
michael@0 2424 {
michael@0 2425 return GetGridTrackSize(StylePosition()->mGridAutoColumnsMin,
michael@0 2426 StylePosition()->mGridAutoColumnsMax);
michael@0 2427 }
michael@0 2428
michael@0 2429 CSSValue*
michael@0 2430 nsComputedDOMStyle::DoGetGridAutoRows()
michael@0 2431 {
michael@0 2432 return GetGridTrackSize(StylePosition()->mGridAutoRowsMin,
michael@0 2433 StylePosition()->mGridAutoRowsMax);
michael@0 2434 }
michael@0 2435
michael@0 2436 CSSValue*
michael@0 2437 nsComputedDOMStyle::DoGetGridTemplateColumns()
michael@0 2438 {
michael@0 2439 return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns);
michael@0 2440 }
michael@0 2441
michael@0 2442 CSSValue*
michael@0 2443 nsComputedDOMStyle::DoGetGridTemplateRows()
michael@0 2444 {
michael@0 2445 return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows);
michael@0 2446 }
michael@0 2447
michael@0 2448 CSSValue*
michael@0 2449 nsComputedDOMStyle::GetGridLine(const nsStyleGridLine& aGridLine)
michael@0 2450 {
michael@0 2451 if (aGridLine.IsAuto()) {
michael@0 2452 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2453 val->SetIdent(eCSSKeyword_auto);
michael@0 2454 return val;
michael@0 2455 }
michael@0 2456
michael@0 2457 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 2458
michael@0 2459 if (aGridLine.mHasSpan) {
michael@0 2460 nsROCSSPrimitiveValue* span = new nsROCSSPrimitiveValue;
michael@0 2461 span->SetIdent(eCSSKeyword_span);
michael@0 2462 valueList->AppendCSSValue(span);
michael@0 2463 }
michael@0 2464
michael@0 2465 if (aGridLine.mInteger != 0) {
michael@0 2466 nsROCSSPrimitiveValue* integer = new nsROCSSPrimitiveValue;
michael@0 2467 integer->SetNumber(aGridLine.mInteger);
michael@0 2468 valueList->AppendCSSValue(integer);
michael@0 2469 }
michael@0 2470
michael@0 2471 if (!aGridLine.mLineName.IsEmpty()) {
michael@0 2472 nsROCSSPrimitiveValue* lineName = new nsROCSSPrimitiveValue;
michael@0 2473 nsString escapedLineName;
michael@0 2474 nsStyleUtil::AppendEscapedCSSIdent(aGridLine.mLineName, escapedLineName);
michael@0 2475 lineName->SetString(escapedLineName);
michael@0 2476 valueList->AppendCSSValue(lineName);
michael@0 2477 }
michael@0 2478
michael@0 2479 NS_ASSERTION(valueList->Length() > 0,
michael@0 2480 "Should have appended at least one value");
michael@0 2481 return valueList;
michael@0 2482 }
michael@0 2483
michael@0 2484 CSSValue*
michael@0 2485 nsComputedDOMStyle::DoGetGridAutoPosition()
michael@0 2486 {
michael@0 2487 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 2488
michael@0 2489 valueList->AppendCSSValue(
michael@0 2490 GetGridLine(StylePosition()->mGridAutoPositionColumn));
michael@0 2491
michael@0 2492 nsROCSSPrimitiveValue* slash = new nsROCSSPrimitiveValue;
michael@0 2493 slash->SetString(NS_LITERAL_STRING("/"));
michael@0 2494 valueList->AppendCSSValue(slash);
michael@0 2495
michael@0 2496 valueList->AppendCSSValue(
michael@0 2497 GetGridLine(StylePosition()->mGridAutoPositionRow));
michael@0 2498
michael@0 2499 return valueList;
michael@0 2500 }
michael@0 2501
michael@0 2502 CSSValue*
michael@0 2503 nsComputedDOMStyle::DoGetGridColumnStart()
michael@0 2504 {
michael@0 2505 return GetGridLine(StylePosition()->mGridColumnStart);
michael@0 2506 }
michael@0 2507
michael@0 2508 CSSValue*
michael@0 2509 nsComputedDOMStyle::DoGetGridColumnEnd()
michael@0 2510 {
michael@0 2511 return GetGridLine(StylePosition()->mGridColumnEnd);
michael@0 2512 }
michael@0 2513
michael@0 2514 CSSValue*
michael@0 2515 nsComputedDOMStyle::DoGetGridRowStart()
michael@0 2516 {
michael@0 2517 return GetGridLine(StylePosition()->mGridRowStart);
michael@0 2518 }
michael@0 2519
michael@0 2520 CSSValue*
michael@0 2521 nsComputedDOMStyle::DoGetGridRowEnd()
michael@0 2522 {
michael@0 2523 return GetGridLine(StylePosition()->mGridRowEnd);
michael@0 2524 }
michael@0 2525
michael@0 2526 CSSValue*
michael@0 2527 nsComputedDOMStyle::DoGetPaddingTop()
michael@0 2528 {
michael@0 2529 return GetPaddingWidthFor(NS_SIDE_TOP);
michael@0 2530 }
michael@0 2531
michael@0 2532 CSSValue*
michael@0 2533 nsComputedDOMStyle::DoGetPaddingBottom()
michael@0 2534 {
michael@0 2535 return GetPaddingWidthFor(NS_SIDE_BOTTOM);
michael@0 2536 }
michael@0 2537
michael@0 2538 CSSValue*
michael@0 2539 nsComputedDOMStyle::DoGetPaddingLeft()
michael@0 2540 {
michael@0 2541 return GetPaddingWidthFor(NS_SIDE_LEFT);
michael@0 2542 }
michael@0 2543
michael@0 2544 CSSValue*
michael@0 2545 nsComputedDOMStyle::DoGetPaddingRight()
michael@0 2546 {
michael@0 2547 return GetPaddingWidthFor(NS_SIDE_RIGHT);
michael@0 2548 }
michael@0 2549
michael@0 2550 CSSValue*
michael@0 2551 nsComputedDOMStyle::DoGetBorderCollapse()
michael@0 2552 {
michael@0 2553 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2554 val->SetIdent(
michael@0 2555 nsCSSProps::ValueToKeywordEnum(StyleTableBorder()->mBorderCollapse,
michael@0 2556 nsCSSProps::kBorderCollapseKTable));
michael@0 2557 return val;
michael@0 2558 }
michael@0 2559
michael@0 2560 CSSValue*
michael@0 2561 nsComputedDOMStyle::DoGetBorderSpacing()
michael@0 2562 {
michael@0 2563 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 2564
michael@0 2565 nsROCSSPrimitiveValue* xSpacing = new nsROCSSPrimitiveValue;
michael@0 2566 valueList->AppendCSSValue(xSpacing);
michael@0 2567
michael@0 2568 nsROCSSPrimitiveValue* ySpacing = new nsROCSSPrimitiveValue;
michael@0 2569 valueList->AppendCSSValue(ySpacing);
michael@0 2570
michael@0 2571 const nsStyleTableBorder *border = StyleTableBorder();
michael@0 2572 xSpacing->SetAppUnits(border->mBorderSpacingX);
michael@0 2573 ySpacing->SetAppUnits(border->mBorderSpacingY);
michael@0 2574
michael@0 2575 return valueList;
michael@0 2576 }
michael@0 2577
michael@0 2578 CSSValue*
michael@0 2579 nsComputedDOMStyle::DoGetCaptionSide()
michael@0 2580 {
michael@0 2581 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2582 val->SetIdent(
michael@0 2583 nsCSSProps::ValueToKeywordEnum(StyleTableBorder()->mCaptionSide,
michael@0 2584 nsCSSProps::kCaptionSideKTable));
michael@0 2585 return val;
michael@0 2586 }
michael@0 2587
michael@0 2588 CSSValue*
michael@0 2589 nsComputedDOMStyle::DoGetEmptyCells()
michael@0 2590 {
michael@0 2591 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2592 val->SetIdent(
michael@0 2593 nsCSSProps::ValueToKeywordEnum(StyleTableBorder()->mEmptyCells,
michael@0 2594 nsCSSProps::kEmptyCellsKTable));
michael@0 2595 return val;
michael@0 2596 }
michael@0 2597
michael@0 2598 CSSValue*
michael@0 2599 nsComputedDOMStyle::DoGetTableLayout()
michael@0 2600 {
michael@0 2601 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2602 val->SetIdent(
michael@0 2603 nsCSSProps::ValueToKeywordEnum(StyleTable()->mLayoutStrategy,
michael@0 2604 nsCSSProps::kTableLayoutKTable));
michael@0 2605 return val;
michael@0 2606 }
michael@0 2607
michael@0 2608 CSSValue*
michael@0 2609 nsComputedDOMStyle::DoGetBorderTopStyle()
michael@0 2610 {
michael@0 2611 return GetBorderStyleFor(NS_SIDE_TOP);
michael@0 2612 }
michael@0 2613
michael@0 2614 CSSValue*
michael@0 2615 nsComputedDOMStyle::DoGetBorderBottomStyle()
michael@0 2616 {
michael@0 2617 return GetBorderStyleFor(NS_SIDE_BOTTOM);
michael@0 2618 }
michael@0 2619
michael@0 2620 CSSValue*
michael@0 2621 nsComputedDOMStyle::DoGetBorderLeftStyle()
michael@0 2622 {
michael@0 2623 return GetBorderStyleFor(NS_SIDE_LEFT);
michael@0 2624 }
michael@0 2625
michael@0 2626 CSSValue*
michael@0 2627 nsComputedDOMStyle::DoGetBorderRightStyle()
michael@0 2628 {
michael@0 2629 return GetBorderStyleFor(NS_SIDE_RIGHT);
michael@0 2630 }
michael@0 2631
michael@0 2632 CSSValue*
michael@0 2633 nsComputedDOMStyle::DoGetBorderBottomColors()
michael@0 2634 {
michael@0 2635 return GetBorderColorsFor(NS_SIDE_BOTTOM);
michael@0 2636 }
michael@0 2637
michael@0 2638 CSSValue*
michael@0 2639 nsComputedDOMStyle::DoGetBorderLeftColors()
michael@0 2640 {
michael@0 2641 return GetBorderColorsFor(NS_SIDE_LEFT);
michael@0 2642 }
michael@0 2643
michael@0 2644 CSSValue*
michael@0 2645 nsComputedDOMStyle::DoGetBorderRightColors()
michael@0 2646 {
michael@0 2647 return GetBorderColorsFor(NS_SIDE_RIGHT);
michael@0 2648 }
michael@0 2649
michael@0 2650
michael@0 2651 CSSValue*
michael@0 2652 nsComputedDOMStyle::DoGetBorderTopColors()
michael@0 2653 {
michael@0 2654 return GetBorderColorsFor(NS_SIDE_TOP);
michael@0 2655 }
michael@0 2656
michael@0 2657 CSSValue*
michael@0 2658 nsComputedDOMStyle::DoGetBorderBottomLeftRadius()
michael@0 2659 {
michael@0 2660 return GetEllipseRadii(StyleBorder()->mBorderRadius,
michael@0 2661 NS_CORNER_BOTTOM_LEFT, true);
michael@0 2662 }
michael@0 2663
michael@0 2664 CSSValue*
michael@0 2665 nsComputedDOMStyle::DoGetBorderBottomRightRadius()
michael@0 2666 {
michael@0 2667 return GetEllipseRadii(StyleBorder()->mBorderRadius,
michael@0 2668 NS_CORNER_BOTTOM_RIGHT, true);
michael@0 2669 }
michael@0 2670
michael@0 2671 CSSValue*
michael@0 2672 nsComputedDOMStyle::DoGetBorderTopLeftRadius()
michael@0 2673 {
michael@0 2674 return GetEllipseRadii(StyleBorder()->mBorderRadius,
michael@0 2675 NS_CORNER_TOP_LEFT, true);
michael@0 2676 }
michael@0 2677
michael@0 2678 CSSValue*
michael@0 2679 nsComputedDOMStyle::DoGetBorderTopRightRadius()
michael@0 2680 {
michael@0 2681 return GetEllipseRadii(StyleBorder()->mBorderRadius,
michael@0 2682 NS_CORNER_TOP_RIGHT, true);
michael@0 2683 }
michael@0 2684
michael@0 2685 CSSValue*
michael@0 2686 nsComputedDOMStyle::DoGetBorderTopWidth()
michael@0 2687 {
michael@0 2688 return GetBorderWidthFor(NS_SIDE_TOP);
michael@0 2689 }
michael@0 2690
michael@0 2691 CSSValue*
michael@0 2692 nsComputedDOMStyle::DoGetBorderBottomWidth()
michael@0 2693 {
michael@0 2694 return GetBorderWidthFor(NS_SIDE_BOTTOM);
michael@0 2695 }
michael@0 2696
michael@0 2697 CSSValue*
michael@0 2698 nsComputedDOMStyle::DoGetBorderLeftWidth()
michael@0 2699 {
michael@0 2700 return GetBorderWidthFor(NS_SIDE_LEFT);
michael@0 2701 }
michael@0 2702
michael@0 2703 CSSValue*
michael@0 2704 nsComputedDOMStyle::DoGetBorderRightWidth()
michael@0 2705 {
michael@0 2706 return GetBorderWidthFor(NS_SIDE_RIGHT);
michael@0 2707 }
michael@0 2708
michael@0 2709 CSSValue*
michael@0 2710 nsComputedDOMStyle::DoGetBorderTopColor()
michael@0 2711 {
michael@0 2712 return GetBorderColorFor(NS_SIDE_TOP);
michael@0 2713 }
michael@0 2714
michael@0 2715 CSSValue*
michael@0 2716 nsComputedDOMStyle::DoGetBorderBottomColor()
michael@0 2717 {
michael@0 2718 return GetBorderColorFor(NS_SIDE_BOTTOM);
michael@0 2719 }
michael@0 2720
michael@0 2721 CSSValue*
michael@0 2722 nsComputedDOMStyle::DoGetBorderLeftColor()
michael@0 2723 {
michael@0 2724 return GetBorderColorFor(NS_SIDE_LEFT);
michael@0 2725 }
michael@0 2726
michael@0 2727 CSSValue*
michael@0 2728 nsComputedDOMStyle::DoGetBorderRightColor()
michael@0 2729 {
michael@0 2730 return GetBorderColorFor(NS_SIDE_RIGHT);
michael@0 2731 }
michael@0 2732
michael@0 2733 CSSValue*
michael@0 2734 nsComputedDOMStyle::DoGetMarginTopWidth()
michael@0 2735 {
michael@0 2736 return GetMarginWidthFor(NS_SIDE_TOP);
michael@0 2737 }
michael@0 2738
michael@0 2739 CSSValue*
michael@0 2740 nsComputedDOMStyle::DoGetMarginBottomWidth()
michael@0 2741 {
michael@0 2742 return GetMarginWidthFor(NS_SIDE_BOTTOM);
michael@0 2743 }
michael@0 2744
michael@0 2745 CSSValue*
michael@0 2746 nsComputedDOMStyle::DoGetMarginLeftWidth()
michael@0 2747 {
michael@0 2748 return GetMarginWidthFor(NS_SIDE_LEFT);
michael@0 2749 }
michael@0 2750
michael@0 2751 CSSValue*
michael@0 2752 nsComputedDOMStyle::DoGetMarginRightWidth()
michael@0 2753 {
michael@0 2754 return GetMarginWidthFor(NS_SIDE_RIGHT);
michael@0 2755 }
michael@0 2756
michael@0 2757 CSSValue*
michael@0 2758 nsComputedDOMStyle::DoGetMarkerOffset()
michael@0 2759 {
michael@0 2760 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2761 SetValueToCoord(val, StyleContent()->mMarkerOffset, false);
michael@0 2762 return val;
michael@0 2763 }
michael@0 2764
michael@0 2765 CSSValue*
michael@0 2766 nsComputedDOMStyle::DoGetOrient()
michael@0 2767 {
michael@0 2768 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2769 val->SetIdent(
michael@0 2770 nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mOrient,
michael@0 2771 nsCSSProps::kOrientKTable));
michael@0 2772 return val;
michael@0 2773 }
michael@0 2774
michael@0 2775 CSSValue*
michael@0 2776 nsComputedDOMStyle::DoGetOutlineWidth()
michael@0 2777 {
michael@0 2778 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2779
michael@0 2780 const nsStyleOutline* outline = StyleOutline();
michael@0 2781
michael@0 2782 nscoord width;
michael@0 2783 if (outline->GetOutlineStyle() == NS_STYLE_BORDER_STYLE_NONE) {
michael@0 2784 NS_ASSERTION(outline->GetOutlineWidth(width) && width == 0,
michael@0 2785 "unexpected width");
michael@0 2786 width = 0;
michael@0 2787 } else {
michael@0 2788 #ifdef DEBUG
michael@0 2789 bool res =
michael@0 2790 #endif
michael@0 2791 outline->GetOutlineWidth(width);
michael@0 2792 NS_ASSERTION(res, "percent outline doesn't exist");
michael@0 2793 }
michael@0 2794 val->SetAppUnits(width);
michael@0 2795
michael@0 2796 return val;
michael@0 2797 }
michael@0 2798
michael@0 2799 CSSValue*
michael@0 2800 nsComputedDOMStyle::DoGetOutlineStyle()
michael@0 2801 {
michael@0 2802 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2803 val->SetIdent(
michael@0 2804 nsCSSProps::ValueToKeywordEnum(StyleOutline()->GetOutlineStyle(),
michael@0 2805 nsCSSProps::kOutlineStyleKTable));
michael@0 2806 return val;
michael@0 2807 }
michael@0 2808
michael@0 2809 CSSValue*
michael@0 2810 nsComputedDOMStyle::DoGetOutlineOffset()
michael@0 2811 {
michael@0 2812 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2813 val->SetAppUnits(StyleOutline()->mOutlineOffset);
michael@0 2814 return val;
michael@0 2815 }
michael@0 2816
michael@0 2817 CSSValue*
michael@0 2818 nsComputedDOMStyle::DoGetOutlineRadiusBottomLeft()
michael@0 2819 {
michael@0 2820 return GetEllipseRadii(StyleOutline()->mOutlineRadius,
michael@0 2821 NS_CORNER_BOTTOM_LEFT, false);
michael@0 2822 }
michael@0 2823
michael@0 2824 CSSValue*
michael@0 2825 nsComputedDOMStyle::DoGetOutlineRadiusBottomRight()
michael@0 2826 {
michael@0 2827 return GetEllipseRadii(StyleOutline()->mOutlineRadius,
michael@0 2828 NS_CORNER_BOTTOM_RIGHT, false);
michael@0 2829 }
michael@0 2830
michael@0 2831 CSSValue*
michael@0 2832 nsComputedDOMStyle::DoGetOutlineRadiusTopLeft()
michael@0 2833 {
michael@0 2834 return GetEllipseRadii(StyleOutline()->mOutlineRadius,
michael@0 2835 NS_CORNER_TOP_LEFT, false);
michael@0 2836 }
michael@0 2837
michael@0 2838 CSSValue*
michael@0 2839 nsComputedDOMStyle::DoGetOutlineRadiusTopRight()
michael@0 2840 {
michael@0 2841 return GetEllipseRadii(StyleOutline()->mOutlineRadius,
michael@0 2842 NS_CORNER_TOP_RIGHT, false);
michael@0 2843 }
michael@0 2844
michael@0 2845 CSSValue*
michael@0 2846 nsComputedDOMStyle::DoGetOutlineColor()
michael@0 2847 {
michael@0 2848 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2849
michael@0 2850 nscolor color;
michael@0 2851 if (!StyleOutline()->GetOutlineColor(color))
michael@0 2852 color = StyleColor()->mColor;
michael@0 2853
michael@0 2854 SetToRGBAColor(val, color);
michael@0 2855 return val;
michael@0 2856 }
michael@0 2857
michael@0 2858 CSSValue*
michael@0 2859 nsComputedDOMStyle::GetEllipseRadii(const nsStyleCorners& aRadius,
michael@0 2860 uint8_t aFullCorner,
michael@0 2861 bool aIsBorder) // else outline
michael@0 2862 {
michael@0 2863 nsStyleCoord radiusX, radiusY;
michael@0 2864 if (mInnerFrame && aIsBorder) {
michael@0 2865 nscoord radii[8];
michael@0 2866 mInnerFrame->GetBorderRadii(radii);
michael@0 2867 radiusX.SetCoordValue(radii[NS_FULL_TO_HALF_CORNER(aFullCorner, false)]);
michael@0 2868 radiusY.SetCoordValue(radii[NS_FULL_TO_HALF_CORNER(aFullCorner, true)]);
michael@0 2869 } else {
michael@0 2870 radiusX = aRadius.Get(NS_FULL_TO_HALF_CORNER(aFullCorner, false));
michael@0 2871 radiusY = aRadius.Get(NS_FULL_TO_HALF_CORNER(aFullCorner, true));
michael@0 2872
michael@0 2873 if (mInnerFrame) {
michael@0 2874 // We need to convert to absolute coordinates before doing the
michael@0 2875 // equality check below.
michael@0 2876 nscoord v;
michael@0 2877
michael@0 2878 v = StyleCoordToNSCoord(radiusX,
michael@0 2879 &nsComputedDOMStyle::GetFrameBorderRectWidth,
michael@0 2880 0, true);
michael@0 2881 radiusX.SetCoordValue(v);
michael@0 2882
michael@0 2883 v = StyleCoordToNSCoord(radiusY,
michael@0 2884 &nsComputedDOMStyle::GetFrameBorderRectHeight,
michael@0 2885 0, true);
michael@0 2886 radiusY.SetCoordValue(v);
michael@0 2887 }
michael@0 2888 }
michael@0 2889
michael@0 2890 // for compatibility, return a single value if X and Y are equal
michael@0 2891 if (radiusX == radiusY) {
michael@0 2892 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2893
michael@0 2894 SetValueToCoord(val, radiusX, true);
michael@0 2895
michael@0 2896 return val;
michael@0 2897 }
michael@0 2898
michael@0 2899 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 2900
michael@0 2901 nsROCSSPrimitiveValue *valX = new nsROCSSPrimitiveValue;
michael@0 2902 valueList->AppendCSSValue(valX);
michael@0 2903
michael@0 2904 nsROCSSPrimitiveValue *valY = new nsROCSSPrimitiveValue;
michael@0 2905 valueList->AppendCSSValue(valY);
michael@0 2906
michael@0 2907 SetValueToCoord(valX, radiusX, true);
michael@0 2908 SetValueToCoord(valY, radiusY, true);
michael@0 2909
michael@0 2910 return valueList;
michael@0 2911 }
michael@0 2912
michael@0 2913 CSSValue*
michael@0 2914 nsComputedDOMStyle::GetCSSShadowArray(nsCSSShadowArray* aArray,
michael@0 2915 const nscolor& aDefaultColor,
michael@0 2916 bool aIsBoxShadow)
michael@0 2917 {
michael@0 2918 if (!aArray) {
michael@0 2919 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2920 val->SetIdent(eCSSKeyword_none);
michael@0 2921 return val;
michael@0 2922 }
michael@0 2923
michael@0 2924 static nscoord nsCSSShadowItem::* const shadowValuesNoSpread[] = {
michael@0 2925 &nsCSSShadowItem::mXOffset,
michael@0 2926 &nsCSSShadowItem::mYOffset,
michael@0 2927 &nsCSSShadowItem::mRadius
michael@0 2928 };
michael@0 2929
michael@0 2930 static nscoord nsCSSShadowItem::* const shadowValuesWithSpread[] = {
michael@0 2931 &nsCSSShadowItem::mXOffset,
michael@0 2932 &nsCSSShadowItem::mYOffset,
michael@0 2933 &nsCSSShadowItem::mRadius,
michael@0 2934 &nsCSSShadowItem::mSpread
michael@0 2935 };
michael@0 2936
michael@0 2937 nscoord nsCSSShadowItem::* const * shadowValues;
michael@0 2938 uint32_t shadowValuesLength;
michael@0 2939 if (aIsBoxShadow) {
michael@0 2940 shadowValues = shadowValuesWithSpread;
michael@0 2941 shadowValuesLength = ArrayLength(shadowValuesWithSpread);
michael@0 2942 } else {
michael@0 2943 shadowValues = shadowValuesNoSpread;
michael@0 2944 shadowValuesLength = ArrayLength(shadowValuesNoSpread);
michael@0 2945 }
michael@0 2946
michael@0 2947 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 2948
michael@0 2949 for (nsCSSShadowItem *item = aArray->ShadowAt(0),
michael@0 2950 *item_end = item + aArray->Length();
michael@0 2951 item < item_end; ++item) {
michael@0 2952 nsDOMCSSValueList *itemList = GetROCSSValueList(false);
michael@0 2953 valueList->AppendCSSValue(itemList);
michael@0 2954
michael@0 2955 // Color is either the specified shadow color or the foreground color
michael@0 2956 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 2957 itemList->AppendCSSValue(val);
michael@0 2958 nscolor shadowColor;
michael@0 2959 if (item->mHasColor) {
michael@0 2960 shadowColor = item->mColor;
michael@0 2961 } else {
michael@0 2962 shadowColor = aDefaultColor;
michael@0 2963 }
michael@0 2964 SetToRGBAColor(val, shadowColor);
michael@0 2965
michael@0 2966 // Set the offsets, blur radius, and spread if available
michael@0 2967 for (uint32_t i = 0; i < shadowValuesLength; ++i) {
michael@0 2968 val = new nsROCSSPrimitiveValue;
michael@0 2969 itemList->AppendCSSValue(val);
michael@0 2970 val->SetAppUnits(item->*(shadowValues[i]));
michael@0 2971 }
michael@0 2972
michael@0 2973 if (item->mInset && aIsBoxShadow) {
michael@0 2974 // This is an inset box-shadow
michael@0 2975 val = new nsROCSSPrimitiveValue;
michael@0 2976 itemList->AppendCSSValue(val);
michael@0 2977 val->SetIdent(
michael@0 2978 nsCSSProps::ValueToKeywordEnum(NS_STYLE_BOX_SHADOW_INSET,
michael@0 2979 nsCSSProps::kBoxShadowTypeKTable));
michael@0 2980 }
michael@0 2981 }
michael@0 2982
michael@0 2983 return valueList;
michael@0 2984 }
michael@0 2985
michael@0 2986 CSSValue*
michael@0 2987 nsComputedDOMStyle::DoGetBoxShadow()
michael@0 2988 {
michael@0 2989 return GetCSSShadowArray(StyleBorder()->mBoxShadow,
michael@0 2990 StyleColor()->mColor,
michael@0 2991 true);
michael@0 2992 }
michael@0 2993
michael@0 2994 CSSValue*
michael@0 2995 nsComputedDOMStyle::DoGetZIndex()
michael@0 2996 {
michael@0 2997 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 2998 SetValueToCoord(val, StylePosition()->mZIndex, false);
michael@0 2999 return val;
michael@0 3000 }
michael@0 3001
michael@0 3002 CSSValue*
michael@0 3003 nsComputedDOMStyle::DoGetListStyleImage()
michael@0 3004 {
michael@0 3005 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3006
michael@0 3007 const nsStyleList* list = StyleList();
michael@0 3008
michael@0 3009 if (!list->GetListStyleImage()) {
michael@0 3010 val->SetIdent(eCSSKeyword_none);
michael@0 3011 } else {
michael@0 3012 nsCOMPtr<nsIURI> uri;
michael@0 3013 if (list->GetListStyleImage()) {
michael@0 3014 list->GetListStyleImage()->GetURI(getter_AddRefs(uri));
michael@0 3015 }
michael@0 3016 val->SetURI(uri);
michael@0 3017 }
michael@0 3018
michael@0 3019 return val;
michael@0 3020 }
michael@0 3021
michael@0 3022 CSSValue*
michael@0 3023 nsComputedDOMStyle::DoGetListStylePosition()
michael@0 3024 {
michael@0 3025 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3026 val->SetIdent(
michael@0 3027 nsCSSProps::ValueToKeywordEnum(StyleList()->mListStylePosition,
michael@0 3028 nsCSSProps::kListStylePositionKTable));
michael@0 3029 return val;
michael@0 3030 }
michael@0 3031
michael@0 3032 CSSValue*
michael@0 3033 nsComputedDOMStyle::DoGetListStyleType()
michael@0 3034 {
michael@0 3035 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3036 val->SetIdent(
michael@0 3037 nsCSSProps::ValueToKeywordEnum(StyleList()->mListStyleType,
michael@0 3038 nsCSSProps::kListStyleKTable));
michael@0 3039 return val;
michael@0 3040 }
michael@0 3041
michael@0 3042 CSSValue*
michael@0 3043 nsComputedDOMStyle::DoGetImageRegion()
michael@0 3044 {
michael@0 3045 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3046
michael@0 3047 const nsStyleList* list = StyleList();
michael@0 3048
michael@0 3049 if (list->mImageRegion.width <= 0 || list->mImageRegion.height <= 0) {
michael@0 3050 val->SetIdent(eCSSKeyword_auto);
michael@0 3051 } else {
michael@0 3052 // create the cssvalues for the sides, stick them in the rect object
michael@0 3053 nsROCSSPrimitiveValue *topVal = new nsROCSSPrimitiveValue;
michael@0 3054 nsROCSSPrimitiveValue *rightVal = new nsROCSSPrimitiveValue;
michael@0 3055 nsROCSSPrimitiveValue *bottomVal = new nsROCSSPrimitiveValue;
michael@0 3056 nsROCSSPrimitiveValue *leftVal = new nsROCSSPrimitiveValue;
michael@0 3057 nsDOMCSSRect * domRect = new nsDOMCSSRect(topVal, rightVal,
michael@0 3058 bottomVal, leftVal);
michael@0 3059 topVal->SetAppUnits(list->mImageRegion.y);
michael@0 3060 rightVal->SetAppUnits(list->mImageRegion.width + list->mImageRegion.x);
michael@0 3061 bottomVal->SetAppUnits(list->mImageRegion.height + list->mImageRegion.y);
michael@0 3062 leftVal->SetAppUnits(list->mImageRegion.x);
michael@0 3063 val->SetRect(domRect);
michael@0 3064 }
michael@0 3065
michael@0 3066 return val;
michael@0 3067 }
michael@0 3068
michael@0 3069 CSSValue*
michael@0 3070 nsComputedDOMStyle::DoGetLineHeight()
michael@0 3071 {
michael@0 3072 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3073
michael@0 3074 nscoord lineHeight;
michael@0 3075 if (GetLineHeightCoord(lineHeight)) {
michael@0 3076 val->SetAppUnits(lineHeight);
michael@0 3077 } else {
michael@0 3078 SetValueToCoord(val, StyleText()->mLineHeight, true,
michael@0 3079 nullptr, nsCSSProps::kLineHeightKTable);
michael@0 3080 }
michael@0 3081
michael@0 3082 return val;
michael@0 3083 }
michael@0 3084
michael@0 3085 CSSValue*
michael@0 3086 nsComputedDOMStyle::DoGetVerticalAlign()
michael@0 3087 {
michael@0 3088 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3089 SetValueToCoord(val, StyleTextReset()->mVerticalAlign, false,
michael@0 3090 &nsComputedDOMStyle::GetLineHeightCoord,
michael@0 3091 nsCSSProps::kVerticalAlignKTable);
michael@0 3092 return val;
michael@0 3093 }
michael@0 3094
michael@0 3095 CSSValue*
michael@0 3096 nsComputedDOMStyle::CreateTextAlignValue(uint8_t aAlign, bool aAlignTrue,
michael@0 3097 const KTableValue aTable[])
michael@0 3098 {
michael@0 3099 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3100 val->SetIdent(nsCSSProps::ValueToKeywordEnum(aAlign, aTable));
michael@0 3101 if (!aAlignTrue) {
michael@0 3102 return val;
michael@0 3103 }
michael@0 3104
michael@0 3105 nsROCSSPrimitiveValue* first = new nsROCSSPrimitiveValue;
michael@0 3106 first->SetIdent(eCSSKeyword_true);
michael@0 3107
michael@0 3108 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 3109 valueList->AppendCSSValue(first);
michael@0 3110 valueList->AppendCSSValue(val);
michael@0 3111 return valueList;
michael@0 3112 }
michael@0 3113
michael@0 3114 CSSValue*
michael@0 3115 nsComputedDOMStyle::DoGetTextAlign()
michael@0 3116 {
michael@0 3117 const nsStyleText* style = StyleText();
michael@0 3118 return CreateTextAlignValue(style->mTextAlign, style->mTextAlignTrue,
michael@0 3119 nsCSSProps::kTextAlignKTable);
michael@0 3120 }
michael@0 3121
michael@0 3122 CSSValue*
michael@0 3123 nsComputedDOMStyle::DoGetTextAlignLast()
michael@0 3124 {
michael@0 3125 const nsStyleText* style = StyleText();
michael@0 3126 return CreateTextAlignValue(style->mTextAlignLast, style->mTextAlignLastTrue,
michael@0 3127 nsCSSProps::kTextAlignLastKTable);
michael@0 3128 }
michael@0 3129
michael@0 3130 CSSValue*
michael@0 3131 nsComputedDOMStyle::DoGetTextCombineUpright()
michael@0 3132 {
michael@0 3133 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3134 uint8_t tch = StyleText()->mTextCombineUpright;
michael@0 3135
michael@0 3136 if (tch <= NS_STYLE_TEXT_COMBINE_UPRIGHT_ALL) {
michael@0 3137 val->SetIdent(
michael@0 3138 nsCSSProps::ValueToKeywordEnum(tch,
michael@0 3139 nsCSSProps::kTextCombineUprightKTable));
michael@0 3140 } else if (tch <= NS_STYLE_TEXT_COMBINE_UPRIGHT_DIGITS_2) {
michael@0 3141 val->SetString(NS_LITERAL_STRING("digits 2"));
michael@0 3142 } else if (tch <= NS_STYLE_TEXT_COMBINE_UPRIGHT_DIGITS_3) {
michael@0 3143 val->SetString(NS_LITERAL_STRING("digits 3"));
michael@0 3144 } else {
michael@0 3145 val->SetString(NS_LITERAL_STRING("digits 4"));
michael@0 3146 }
michael@0 3147
michael@0 3148 return val;
michael@0 3149 }
michael@0 3150
michael@0 3151 CSSValue*
michael@0 3152 nsComputedDOMStyle::DoGetTextDecoration()
michael@0 3153 {
michael@0 3154 const nsStyleTextReset* textReset = StyleTextReset();
michael@0 3155
michael@0 3156 // If decoration style or color wasn't initial value, the author knew the
michael@0 3157 // text-decoration is a shorthand property in CSS 3.
michael@0 3158 // Return nullptr in such cases.
michael@0 3159 if (textReset->GetDecorationStyle() != NS_STYLE_TEXT_DECORATION_STYLE_SOLID) {
michael@0 3160 return nullptr;
michael@0 3161 }
michael@0 3162
michael@0 3163 nscolor color;
michael@0 3164 bool isForegroundColor;
michael@0 3165 textReset->GetDecorationColor(color, isForegroundColor);
michael@0 3166 if (!isForegroundColor) {
michael@0 3167 return nullptr;
michael@0 3168 }
michael@0 3169
michael@0 3170 // Otherwise, the web pages may have been written for CSS 2.1 or earlier,
michael@0 3171 // i.e., text-decoration was assumed as a longhand property. In that case,
michael@0 3172 // we should return computed value same as CSS 2.1 for backward compatibility.
michael@0 3173
michael@0 3174 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3175 uint8_t line = textReset->mTextDecorationLine;
michael@0 3176 // Clear the -moz-anchor-decoration bit and the OVERRIDE_ALL bits -- we
michael@0 3177 // don't want these to appear in the computed style.
michael@0 3178 line &= ~(NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS |
michael@0 3179 NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL);
michael@0 3180
michael@0 3181 if (line == NS_STYLE_TEXT_DECORATION_LINE_NONE) {
michael@0 3182 val->SetIdent(eCSSKeyword_none);
michael@0 3183 } else {
michael@0 3184 nsAutoString str;
michael@0 3185 nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_text_decoration_line,
michael@0 3186 line, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
michael@0 3187 NS_STYLE_TEXT_DECORATION_LINE_BLINK, str);
michael@0 3188 val->SetString(str);
michael@0 3189 }
michael@0 3190
michael@0 3191 return val;
michael@0 3192 }
michael@0 3193
michael@0 3194 CSSValue*
michael@0 3195 nsComputedDOMStyle::DoGetTextDecorationColor()
michael@0 3196 {
michael@0 3197 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3198
michael@0 3199 nscolor color;
michael@0 3200 bool isForeground;
michael@0 3201 StyleTextReset()->GetDecorationColor(color, isForeground);
michael@0 3202 if (isForeground) {
michael@0 3203 color = StyleColor()->mColor;
michael@0 3204 }
michael@0 3205
michael@0 3206 SetToRGBAColor(val, color);
michael@0 3207
michael@0 3208 return val;
michael@0 3209 }
michael@0 3210
michael@0 3211 CSSValue*
michael@0 3212 nsComputedDOMStyle::DoGetTextDecorationLine()
michael@0 3213 {
michael@0 3214 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3215
michael@0 3216 int32_t intValue = StyleTextReset()->mTextDecorationLine;
michael@0 3217
michael@0 3218 if (NS_STYLE_TEXT_DECORATION_LINE_NONE == intValue) {
michael@0 3219 val->SetIdent(eCSSKeyword_none);
michael@0 3220 } else {
michael@0 3221 nsAutoString decorationLineString;
michael@0 3222 // Clear the -moz-anchor-decoration bit and the OVERRIDE_ALL bits -- we
michael@0 3223 // don't want these to appear in the computed style.
michael@0 3224 intValue &= ~(NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS |
michael@0 3225 NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL);
michael@0 3226 nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_text_decoration_line,
michael@0 3227 intValue, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
michael@0 3228 NS_STYLE_TEXT_DECORATION_LINE_BLINK, decorationLineString);
michael@0 3229 val->SetString(decorationLineString);
michael@0 3230 }
michael@0 3231
michael@0 3232 return val;
michael@0 3233 }
michael@0 3234
michael@0 3235 CSSValue*
michael@0 3236 nsComputedDOMStyle::DoGetTextDecorationStyle()
michael@0 3237 {
michael@0 3238 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3239
michael@0 3240 val->SetIdent(
michael@0 3241 nsCSSProps::ValueToKeywordEnum(StyleTextReset()->GetDecorationStyle(),
michael@0 3242 nsCSSProps::kTextDecorationStyleKTable));
michael@0 3243
michael@0 3244 return val;
michael@0 3245 }
michael@0 3246
michael@0 3247 CSSValue*
michael@0 3248 nsComputedDOMStyle::DoGetTextIndent()
michael@0 3249 {
michael@0 3250 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3251 SetValueToCoord(val, StyleText()->mTextIndent, false,
michael@0 3252 &nsComputedDOMStyle::GetCBContentWidth);
michael@0 3253 return val;
michael@0 3254 }
michael@0 3255
michael@0 3256 CSSValue*
michael@0 3257 nsComputedDOMStyle::DoGetTextOrientation()
michael@0 3258 {
michael@0 3259 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3260 val->SetIdent(
michael@0 3261 nsCSSProps::ValueToKeywordEnum(StyleText()->mTextOrientation,
michael@0 3262 nsCSSProps::kTextOrientationKTable));
michael@0 3263 return val;
michael@0 3264 }
michael@0 3265
michael@0 3266 CSSValue*
michael@0 3267 nsComputedDOMStyle::DoGetTextOverflow()
michael@0 3268 {
michael@0 3269 const nsStyleTextReset *style = StyleTextReset();
michael@0 3270 nsROCSSPrimitiveValue *first = new nsROCSSPrimitiveValue;
michael@0 3271 const nsStyleTextOverflowSide *side = style->mTextOverflow.GetFirstValue();
michael@0 3272 if (side->mType == NS_STYLE_TEXT_OVERFLOW_STRING) {
michael@0 3273 nsString str;
michael@0 3274 nsStyleUtil::AppendEscapedCSSString(side->mString, str);
michael@0 3275 first->SetString(str);
michael@0 3276 } else {
michael@0 3277 first->SetIdent(
michael@0 3278 nsCSSProps::ValueToKeywordEnum(side->mType,
michael@0 3279 nsCSSProps::kTextOverflowKTable));
michael@0 3280 }
michael@0 3281 side = style->mTextOverflow.GetSecondValue();
michael@0 3282 if (!side) {
michael@0 3283 return first;
michael@0 3284 }
michael@0 3285 nsROCSSPrimitiveValue *second = new nsROCSSPrimitiveValue;
michael@0 3286 if (side->mType == NS_STYLE_TEXT_OVERFLOW_STRING) {
michael@0 3287 nsString str;
michael@0 3288 nsStyleUtil::AppendEscapedCSSString(side->mString, str);
michael@0 3289 second->SetString(str);
michael@0 3290 } else {
michael@0 3291 second->SetIdent(
michael@0 3292 nsCSSProps::ValueToKeywordEnum(side->mType,
michael@0 3293 nsCSSProps::kTextOverflowKTable));
michael@0 3294 }
michael@0 3295
michael@0 3296 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 3297 valueList->AppendCSSValue(first);
michael@0 3298 valueList->AppendCSSValue(second);
michael@0 3299 return valueList;
michael@0 3300 }
michael@0 3301
michael@0 3302 CSSValue*
michael@0 3303 nsComputedDOMStyle::DoGetTextShadow()
michael@0 3304 {
michael@0 3305 return GetCSSShadowArray(StyleText()->mTextShadow,
michael@0 3306 StyleColor()->mColor,
michael@0 3307 false);
michael@0 3308 }
michael@0 3309
michael@0 3310 CSSValue*
michael@0 3311 nsComputedDOMStyle::DoGetTextTransform()
michael@0 3312 {
michael@0 3313 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3314 val->SetIdent(
michael@0 3315 nsCSSProps::ValueToKeywordEnum(StyleText()->mTextTransform,
michael@0 3316 nsCSSProps::kTextTransformKTable));
michael@0 3317 return val;
michael@0 3318 }
michael@0 3319
michael@0 3320 CSSValue*
michael@0 3321 nsComputedDOMStyle::DoGetTabSize()
michael@0 3322 {
michael@0 3323 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3324 val->SetNumber(StyleText()->mTabSize);
michael@0 3325 return val;
michael@0 3326 }
michael@0 3327
michael@0 3328 CSSValue*
michael@0 3329 nsComputedDOMStyle::DoGetLetterSpacing()
michael@0 3330 {
michael@0 3331 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3332 SetValueToCoord(val, StyleText()->mLetterSpacing, false);
michael@0 3333 return val;
michael@0 3334 }
michael@0 3335
michael@0 3336 CSSValue*
michael@0 3337 nsComputedDOMStyle::DoGetWordSpacing()
michael@0 3338 {
michael@0 3339 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3340 val->SetAppUnits(StyleText()->mWordSpacing);
michael@0 3341 return val;
michael@0 3342 }
michael@0 3343
michael@0 3344 CSSValue*
michael@0 3345 nsComputedDOMStyle::DoGetWhiteSpace()
michael@0 3346 {
michael@0 3347 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3348 val->SetIdent(
michael@0 3349 nsCSSProps::ValueToKeywordEnum(StyleText()->mWhiteSpace,
michael@0 3350 nsCSSProps::kWhitespaceKTable));
michael@0 3351 return val;
michael@0 3352 }
michael@0 3353
michael@0 3354 CSSValue*
michael@0 3355 nsComputedDOMStyle::DoGetWindowShadow()
michael@0 3356 {
michael@0 3357 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3358 val->SetIdent(
michael@0 3359 nsCSSProps::ValueToKeywordEnum(StyleUIReset()->mWindowShadow,
michael@0 3360 nsCSSProps::kWindowShadowKTable));
michael@0 3361 return val;
michael@0 3362 }
michael@0 3363
michael@0 3364 CSSValue*
michael@0 3365 nsComputedDOMStyle::DoGetWordBreak()
michael@0 3366 {
michael@0 3367 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3368 val->SetIdent(
michael@0 3369 nsCSSProps::ValueToKeywordEnum(StyleText()->mWordBreak,
michael@0 3370 nsCSSProps::kWordBreakKTable));
michael@0 3371 return val;
michael@0 3372 }
michael@0 3373
michael@0 3374 CSSValue*
michael@0 3375 nsComputedDOMStyle::DoGetWordWrap()
michael@0 3376 {
michael@0 3377 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3378 val->SetIdent(
michael@0 3379 nsCSSProps::ValueToKeywordEnum(StyleText()->mWordWrap,
michael@0 3380 nsCSSProps::kWordWrapKTable));
michael@0 3381 return val;
michael@0 3382 }
michael@0 3383
michael@0 3384 CSSValue*
michael@0 3385 nsComputedDOMStyle::DoGetHyphens()
michael@0 3386 {
michael@0 3387 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3388 val->SetIdent(
michael@0 3389 nsCSSProps::ValueToKeywordEnum(StyleText()->mHyphens,
michael@0 3390 nsCSSProps::kHyphensKTable));
michael@0 3391 return val;
michael@0 3392 }
michael@0 3393
michael@0 3394 CSSValue*
michael@0 3395 nsComputedDOMStyle::DoGetTextSizeAdjust()
michael@0 3396 {
michael@0 3397 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3398 switch (StyleText()->mTextSizeAdjust) {
michael@0 3399 default:
michael@0 3400 NS_NOTREACHED("unexpected value");
michael@0 3401 // fall through
michael@0 3402 case NS_STYLE_TEXT_SIZE_ADJUST_AUTO:
michael@0 3403 val->SetIdent(eCSSKeyword_auto);
michael@0 3404 break;
michael@0 3405 case NS_STYLE_TEXT_SIZE_ADJUST_NONE:
michael@0 3406 val->SetIdent(eCSSKeyword_none);
michael@0 3407 break;
michael@0 3408 }
michael@0 3409 return val;
michael@0 3410 }
michael@0 3411
michael@0 3412 CSSValue*
michael@0 3413 nsComputedDOMStyle::DoGetPointerEvents()
michael@0 3414 {
michael@0 3415 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3416 val->SetIdent(
michael@0 3417 nsCSSProps::ValueToKeywordEnum(StyleVisibility()->mPointerEvents,
michael@0 3418 nsCSSProps::kPointerEventsKTable));
michael@0 3419 return val;
michael@0 3420 }
michael@0 3421
michael@0 3422 CSSValue*
michael@0 3423 nsComputedDOMStyle::DoGetVisibility()
michael@0 3424 {
michael@0 3425 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3426 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleVisibility()->mVisible,
michael@0 3427 nsCSSProps::kVisibilityKTable));
michael@0 3428 return val;
michael@0 3429 }
michael@0 3430
michael@0 3431 CSSValue*
michael@0 3432 nsComputedDOMStyle::DoGetWritingMode()
michael@0 3433 {
michael@0 3434 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3435 val->SetIdent(
michael@0 3436 nsCSSProps::ValueToKeywordEnum(StyleVisibility()->mWritingMode,
michael@0 3437 nsCSSProps::kWritingModeKTable));
michael@0 3438 return val;
michael@0 3439 }
michael@0 3440
michael@0 3441 CSSValue*
michael@0 3442 nsComputedDOMStyle::DoGetDirection()
michael@0 3443 {
michael@0 3444 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3445 val->SetIdent(
michael@0 3446 nsCSSProps::ValueToKeywordEnum(StyleVisibility()->mDirection,
michael@0 3447 nsCSSProps::kDirectionKTable));
michael@0 3448 return val;
michael@0 3449 }
michael@0 3450
michael@0 3451 static_assert(NS_STYLE_UNICODE_BIDI_NORMAL == 0,
michael@0 3452 "unicode-bidi style constants not as expected");
michael@0 3453
michael@0 3454 CSSValue*
michael@0 3455 nsComputedDOMStyle::DoGetUnicodeBidi()
michael@0 3456 {
michael@0 3457 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3458 val->SetIdent(
michael@0 3459 nsCSSProps::ValueToKeywordEnum(StyleTextReset()->mUnicodeBidi,
michael@0 3460 nsCSSProps::kUnicodeBidiKTable));
michael@0 3461 return val;
michael@0 3462 }
michael@0 3463
michael@0 3464 CSSValue*
michael@0 3465 nsComputedDOMStyle::DoGetCursor()
michael@0 3466 {
michael@0 3467 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 3468
michael@0 3469 const nsStyleUserInterface *ui = StyleUserInterface();
michael@0 3470
michael@0 3471 for (nsCursorImage *item = ui->mCursorArray,
michael@0 3472 *item_end = ui->mCursorArray + ui->mCursorArrayLength;
michael@0 3473 item < item_end; ++item) {
michael@0 3474 nsDOMCSSValueList *itemList = GetROCSSValueList(false);
michael@0 3475 valueList->AppendCSSValue(itemList);
michael@0 3476
michael@0 3477 nsCOMPtr<nsIURI> uri;
michael@0 3478 item->GetImage()->GetURI(getter_AddRefs(uri));
michael@0 3479
michael@0 3480 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3481 itemList->AppendCSSValue(val);
michael@0 3482 val->SetURI(uri);
michael@0 3483
michael@0 3484 if (item->mHaveHotspot) {
michael@0 3485 nsROCSSPrimitiveValue *valX = new nsROCSSPrimitiveValue;
michael@0 3486 itemList->AppendCSSValue(valX);
michael@0 3487 nsROCSSPrimitiveValue *valY = new nsROCSSPrimitiveValue;
michael@0 3488 itemList->AppendCSSValue(valY);
michael@0 3489
michael@0 3490 valX->SetNumber(item->mHotspotX);
michael@0 3491 valY->SetNumber(item->mHotspotY);
michael@0 3492 }
michael@0 3493 }
michael@0 3494
michael@0 3495 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3496 val->SetIdent(nsCSSProps::ValueToKeywordEnum(ui->mCursor,
michael@0 3497 nsCSSProps::kCursorKTable));
michael@0 3498 valueList->AppendCSSValue(val);
michael@0 3499 return valueList;
michael@0 3500 }
michael@0 3501
michael@0 3502 CSSValue*
michael@0 3503 nsComputedDOMStyle::DoGetAppearance()
michael@0 3504 {
michael@0 3505 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3506 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mAppearance,
michael@0 3507 nsCSSProps::kAppearanceKTable));
michael@0 3508 return val;
michael@0 3509 }
michael@0 3510
michael@0 3511
michael@0 3512 CSSValue*
michael@0 3513 nsComputedDOMStyle::DoGetBoxAlign()
michael@0 3514 {
michael@0 3515 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3516 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleXUL()->mBoxAlign,
michael@0 3517 nsCSSProps::kBoxAlignKTable));
michael@0 3518 return val;
michael@0 3519 }
michael@0 3520
michael@0 3521 CSSValue*
michael@0 3522 nsComputedDOMStyle::DoGetBoxDirection()
michael@0 3523 {
michael@0 3524 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3525 val->SetIdent(
michael@0 3526 nsCSSProps::ValueToKeywordEnum(StyleXUL()->mBoxDirection,
michael@0 3527 nsCSSProps::kBoxDirectionKTable));
michael@0 3528 return val;
michael@0 3529 }
michael@0 3530
michael@0 3531 CSSValue*
michael@0 3532 nsComputedDOMStyle::DoGetBoxFlex()
michael@0 3533 {
michael@0 3534 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3535 val->SetNumber(StyleXUL()->mBoxFlex);
michael@0 3536 return val;
michael@0 3537 }
michael@0 3538
michael@0 3539 CSSValue*
michael@0 3540 nsComputedDOMStyle::DoGetBoxOrdinalGroup()
michael@0 3541 {
michael@0 3542 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3543 val->SetNumber(StyleXUL()->mBoxOrdinal);
michael@0 3544 return val;
michael@0 3545 }
michael@0 3546
michael@0 3547 CSSValue*
michael@0 3548 nsComputedDOMStyle::DoGetBoxOrient()
michael@0 3549 {
michael@0 3550 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3551 val->SetIdent(
michael@0 3552 nsCSSProps::ValueToKeywordEnum(StyleXUL()->mBoxOrient,
michael@0 3553 nsCSSProps::kBoxOrientKTable));
michael@0 3554 return val;
michael@0 3555 }
michael@0 3556
michael@0 3557 CSSValue*
michael@0 3558 nsComputedDOMStyle::DoGetBoxPack()
michael@0 3559 {
michael@0 3560 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3561 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleXUL()->mBoxPack,
michael@0 3562 nsCSSProps::kBoxPackKTable));
michael@0 3563 return val;
michael@0 3564 }
michael@0 3565
michael@0 3566 CSSValue*
michael@0 3567 nsComputedDOMStyle::DoGetBoxSizing()
michael@0 3568 {
michael@0 3569 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3570 val->SetIdent(
michael@0 3571 nsCSSProps::ValueToKeywordEnum(StylePosition()->mBoxSizing,
michael@0 3572 nsCSSProps::kBoxSizingKTable));
michael@0 3573 return val;
michael@0 3574 }
michael@0 3575
michael@0 3576 /* Border image properties */
michael@0 3577
michael@0 3578 CSSValue*
michael@0 3579 nsComputedDOMStyle::DoGetBorderImageSource()
michael@0 3580 {
michael@0 3581 const nsStyleBorder* border = StyleBorder();
michael@0 3582
michael@0 3583 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3584 const nsStyleImage& image = border->mBorderImageSource;
michael@0 3585 SetValueToStyleImage(image, val);
michael@0 3586
michael@0 3587 return val;
michael@0 3588 }
michael@0 3589
michael@0 3590 CSSValue*
michael@0 3591 nsComputedDOMStyle::DoGetBorderImageSlice()
michael@0 3592 {
michael@0 3593 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 3594
michael@0 3595 const nsStyleBorder* border = StyleBorder();
michael@0 3596 // Four slice numbers.
michael@0 3597 NS_FOR_CSS_SIDES (side) {
michael@0 3598 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3599 valueList->AppendCSSValue(val);
michael@0 3600 SetValueToCoord(val, border->mBorderImageSlice.Get(side), true, nullptr);
michael@0 3601 }
michael@0 3602
michael@0 3603 // Fill keyword.
michael@0 3604 if (NS_STYLE_BORDER_IMAGE_SLICE_FILL == border->mBorderImageFill) {
michael@0 3605 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3606 valueList->AppendCSSValue(val);
michael@0 3607 val->SetIdent(eCSSKeyword_fill);
michael@0 3608 }
michael@0 3609
michael@0 3610 return valueList;
michael@0 3611 }
michael@0 3612
michael@0 3613 CSSValue*
michael@0 3614 nsComputedDOMStyle::DoGetBorderImageWidth()
michael@0 3615 {
michael@0 3616 const nsStyleBorder* border = StyleBorder();
michael@0 3617 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 3618 NS_FOR_CSS_SIDES (side) {
michael@0 3619 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3620 valueList->AppendCSSValue(val);
michael@0 3621 SetValueToCoord(val, border->mBorderImageWidth.Get(side),
michael@0 3622 true, nullptr);
michael@0 3623 }
michael@0 3624
michael@0 3625 return valueList;
michael@0 3626 }
michael@0 3627
michael@0 3628 CSSValue*
michael@0 3629 nsComputedDOMStyle::DoGetBorderImageOutset()
michael@0 3630 {
michael@0 3631 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 3632
michael@0 3633 const nsStyleBorder* border = StyleBorder();
michael@0 3634 // four slice numbers
michael@0 3635 NS_FOR_CSS_SIDES (side) {
michael@0 3636 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3637 valueList->AppendCSSValue(val);
michael@0 3638 SetValueToCoord(val, border->mBorderImageOutset.Get(side),
michael@0 3639 true, nullptr);
michael@0 3640 }
michael@0 3641
michael@0 3642 return valueList;
michael@0 3643 }
michael@0 3644
michael@0 3645 CSSValue*
michael@0 3646 nsComputedDOMStyle::DoGetBorderImageRepeat()
michael@0 3647 {
michael@0 3648 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 3649
michael@0 3650 const nsStyleBorder* border = StyleBorder();
michael@0 3651
michael@0 3652 // horizontal repeat
michael@0 3653 nsROCSSPrimitiveValue* valX = new nsROCSSPrimitiveValue;
michael@0 3654 valueList->AppendCSSValue(valX);
michael@0 3655 valX->SetIdent(
michael@0 3656 nsCSSProps::ValueToKeywordEnum(border->mBorderImageRepeatH,
michael@0 3657 nsCSSProps::kBorderImageRepeatKTable));
michael@0 3658
michael@0 3659 // vertical repeat
michael@0 3660 nsROCSSPrimitiveValue* valY = new nsROCSSPrimitiveValue;
michael@0 3661 valueList->AppendCSSValue(valY);
michael@0 3662 valY->SetIdent(
michael@0 3663 nsCSSProps::ValueToKeywordEnum(border->mBorderImageRepeatV,
michael@0 3664 nsCSSProps::kBorderImageRepeatKTable));
michael@0 3665 return valueList;
michael@0 3666 }
michael@0 3667
michael@0 3668 CSSValue*
michael@0 3669 nsComputedDOMStyle::DoGetAlignContent()
michael@0 3670 {
michael@0 3671 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3672 val->SetIdent(
michael@0 3673 nsCSSProps::ValueToKeywordEnum(StylePosition()->mAlignContent,
michael@0 3674 nsCSSProps::kAlignContentKTable));
michael@0 3675 return val;
michael@0 3676 }
michael@0 3677
michael@0 3678 CSSValue*
michael@0 3679 nsComputedDOMStyle::DoGetAlignItems()
michael@0 3680 {
michael@0 3681 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3682 val->SetIdent(
michael@0 3683 nsCSSProps::ValueToKeywordEnum(StylePosition()->mAlignItems,
michael@0 3684 nsCSSProps::kAlignItemsKTable));
michael@0 3685 return val;
michael@0 3686 }
michael@0 3687
michael@0 3688 CSSValue*
michael@0 3689 nsComputedDOMStyle::DoGetAlignSelf()
michael@0 3690 {
michael@0 3691 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3692 uint8_t computedAlignSelf = StylePosition()->mAlignSelf;
michael@0 3693
michael@0 3694 if (computedAlignSelf == NS_STYLE_ALIGN_SELF_AUTO) {
michael@0 3695 // "align-self: auto" needs to compute to parent's align-items value.
michael@0 3696 nsStyleContext* parentStyleContext = mStyleContextHolder->GetParent();
michael@0 3697 if (parentStyleContext) {
michael@0 3698 computedAlignSelf =
michael@0 3699 parentStyleContext->StylePosition()->mAlignItems;
michael@0 3700 } else {
michael@0 3701 // No parent --> use default.
michael@0 3702 computedAlignSelf = NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE;
michael@0 3703 }
michael@0 3704 }
michael@0 3705
michael@0 3706 NS_ABORT_IF_FALSE(computedAlignSelf != NS_STYLE_ALIGN_SELF_AUTO,
michael@0 3707 "Should have swapped out 'auto' for something non-auto");
michael@0 3708 val->SetIdent(
michael@0 3709 nsCSSProps::ValueToKeywordEnum(computedAlignSelf,
michael@0 3710 nsCSSProps::kAlignSelfKTable));
michael@0 3711 return val;
michael@0 3712 }
michael@0 3713
michael@0 3714 CSSValue*
michael@0 3715 nsComputedDOMStyle::DoGetFlexBasis()
michael@0 3716 {
michael@0 3717 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3718
michael@0 3719 // XXXdholbert We could make this more automagic and resolve percentages
michael@0 3720 // if we wanted, by passing in a PercentageBaseGetter instead of nullptr
michael@0 3721 // below. Logic would go like this:
michael@0 3722 // if (i'm a flex item) {
michael@0 3723 // if (my flex container is horizontal) {
michael@0 3724 // percentageBaseGetter = &nsComputedDOMStyle::GetCBContentWidth;
michael@0 3725 // } else {
michael@0 3726 // percentageBaseGetter = &nsComputedDOMStyle::GetCBContentHeight;
michael@0 3727 // }
michael@0 3728 // }
michael@0 3729
michael@0 3730 SetValueToCoord(val, StylePosition()->mFlexBasis, true,
michael@0 3731 nullptr, nsCSSProps::kWidthKTable);
michael@0 3732 return val;
michael@0 3733 }
michael@0 3734
michael@0 3735 CSSValue*
michael@0 3736 nsComputedDOMStyle::DoGetFlexDirection()
michael@0 3737 {
michael@0 3738 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3739 val->SetIdent(
michael@0 3740 nsCSSProps::ValueToKeywordEnum(StylePosition()->mFlexDirection,
michael@0 3741 nsCSSProps::kFlexDirectionKTable));
michael@0 3742 return val;
michael@0 3743 }
michael@0 3744
michael@0 3745 CSSValue*
michael@0 3746 nsComputedDOMStyle::DoGetFlexGrow()
michael@0 3747 {
michael@0 3748 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3749 val->SetNumber(StylePosition()->mFlexGrow);
michael@0 3750 return val;
michael@0 3751 }
michael@0 3752
michael@0 3753 CSSValue*
michael@0 3754 nsComputedDOMStyle::DoGetFlexShrink()
michael@0 3755 {
michael@0 3756 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3757 val->SetNumber(StylePosition()->mFlexShrink);
michael@0 3758 return val;
michael@0 3759 }
michael@0 3760
michael@0 3761 CSSValue*
michael@0 3762 nsComputedDOMStyle::DoGetFlexWrap()
michael@0 3763 {
michael@0 3764 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3765 val->SetIdent(
michael@0 3766 nsCSSProps::ValueToKeywordEnum(StylePosition()->mFlexWrap,
michael@0 3767 nsCSSProps::kFlexWrapKTable));
michael@0 3768 return val;
michael@0 3769 }
michael@0 3770
michael@0 3771 CSSValue*
michael@0 3772 nsComputedDOMStyle::DoGetOrder()
michael@0 3773 {
michael@0 3774 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3775 val->SetNumber(StylePosition()->mOrder);
michael@0 3776 return val;
michael@0 3777 }
michael@0 3778
michael@0 3779 CSSValue*
michael@0 3780 nsComputedDOMStyle::DoGetJustifyContent()
michael@0 3781 {
michael@0 3782 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3783 val->SetIdent(
michael@0 3784 nsCSSProps::ValueToKeywordEnum(StylePosition()->mJustifyContent,
michael@0 3785 nsCSSProps::kJustifyContentKTable));
michael@0 3786 return val;
michael@0 3787 }
michael@0 3788
michael@0 3789 CSSValue*
michael@0 3790 nsComputedDOMStyle::DoGetFloatEdge()
michael@0 3791 {
michael@0 3792 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3793 val->SetIdent(
michael@0 3794 nsCSSProps::ValueToKeywordEnum(StyleBorder()->mFloatEdge,
michael@0 3795 nsCSSProps::kFloatEdgeKTable));
michael@0 3796 return val;
michael@0 3797 }
michael@0 3798
michael@0 3799 CSSValue*
michael@0 3800 nsComputedDOMStyle::DoGetForceBrokenImageIcon()
michael@0 3801 {
michael@0 3802 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3803 val->SetNumber(StyleUIReset()->mForceBrokenImageIcon);
michael@0 3804 return val;
michael@0 3805 }
michael@0 3806
michael@0 3807 CSSValue*
michael@0 3808 nsComputedDOMStyle::DoGetImageOrientation()
michael@0 3809 {
michael@0 3810 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3811 nsAutoString string;
michael@0 3812 nsStyleImageOrientation orientation = StyleVisibility()->mImageOrientation;
michael@0 3813
michael@0 3814 if (orientation.IsFromImage()) {
michael@0 3815 string.AppendLiteral("from-image");
michael@0 3816 } else {
michael@0 3817 nsStyleUtil::AppendAngleValue(orientation.AngleAsCoord(), string);
michael@0 3818
michael@0 3819 if (orientation.IsFlipped()) {
michael@0 3820 string.AppendLiteral(" flip");
michael@0 3821 }
michael@0 3822 }
michael@0 3823
michael@0 3824 val->SetString(string);
michael@0 3825 return val;
michael@0 3826 }
michael@0 3827
michael@0 3828 CSSValue*
michael@0 3829 nsComputedDOMStyle::DoGetIMEMode()
michael@0 3830 {
michael@0 3831 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3832 val->SetIdent(
michael@0 3833 nsCSSProps::ValueToKeywordEnum(StyleUIReset()->mIMEMode,
michael@0 3834 nsCSSProps::kIMEModeKTable));
michael@0 3835 return val;
michael@0 3836 }
michael@0 3837
michael@0 3838 CSSValue*
michael@0 3839 nsComputedDOMStyle::DoGetUserFocus()
michael@0 3840 {
michael@0 3841 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3842 val->SetIdent(
michael@0 3843 nsCSSProps::ValueToKeywordEnum(StyleUserInterface()->mUserFocus,
michael@0 3844 nsCSSProps::kUserFocusKTable));
michael@0 3845 return val;
michael@0 3846 }
michael@0 3847
michael@0 3848 CSSValue*
michael@0 3849 nsComputedDOMStyle::DoGetUserInput()
michael@0 3850 {
michael@0 3851 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3852 val->SetIdent(
michael@0 3853 nsCSSProps::ValueToKeywordEnum(StyleUserInterface()->mUserInput,
michael@0 3854 nsCSSProps::kUserInputKTable));
michael@0 3855 return val;
michael@0 3856 }
michael@0 3857
michael@0 3858 CSSValue*
michael@0 3859 nsComputedDOMStyle::DoGetUserModify()
michael@0 3860 {
michael@0 3861 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3862 val->SetIdent(
michael@0 3863 nsCSSProps::ValueToKeywordEnum(StyleUserInterface()->mUserModify,
michael@0 3864 nsCSSProps::kUserModifyKTable));
michael@0 3865 return val;
michael@0 3866 }
michael@0 3867
michael@0 3868 CSSValue*
michael@0 3869 nsComputedDOMStyle::DoGetUserSelect()
michael@0 3870 {
michael@0 3871 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3872 val->SetIdent(
michael@0 3873 nsCSSProps::ValueToKeywordEnum(StyleUIReset()->mUserSelect,
michael@0 3874 nsCSSProps::kUserSelectKTable));
michael@0 3875 return val;
michael@0 3876 }
michael@0 3877
michael@0 3878 CSSValue*
michael@0 3879 nsComputedDOMStyle::DoGetDisplay()
michael@0 3880 {
michael@0 3881 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3882 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mDisplay,
michael@0 3883 nsCSSProps::kDisplayKTable));
michael@0 3884 return val;
michael@0 3885 }
michael@0 3886
michael@0 3887 CSSValue*
michael@0 3888 nsComputedDOMStyle::DoGetPosition()
michael@0 3889 {
michael@0 3890 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3891 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mPosition,
michael@0 3892 nsCSSProps::kPositionKTable));
michael@0 3893 return val;
michael@0 3894 }
michael@0 3895
michael@0 3896 CSSValue*
michael@0 3897 nsComputedDOMStyle::DoGetClip()
michael@0 3898 {
michael@0 3899 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3900
michael@0 3901 const nsStyleDisplay* display = StyleDisplay();
michael@0 3902
michael@0 3903 if (display->mClipFlags == NS_STYLE_CLIP_AUTO) {
michael@0 3904 val->SetIdent(eCSSKeyword_auto);
michael@0 3905 } else {
michael@0 3906 // create the cssvalues for the sides, stick them in the rect object
michael@0 3907 nsROCSSPrimitiveValue *topVal = new nsROCSSPrimitiveValue;
michael@0 3908 nsROCSSPrimitiveValue *rightVal = new nsROCSSPrimitiveValue;
michael@0 3909 nsROCSSPrimitiveValue *bottomVal = new nsROCSSPrimitiveValue;
michael@0 3910 nsROCSSPrimitiveValue *leftVal = new nsROCSSPrimitiveValue;
michael@0 3911 nsDOMCSSRect * domRect = new nsDOMCSSRect(topVal, rightVal,
michael@0 3912 bottomVal, leftVal);
michael@0 3913 if (display->mClipFlags & NS_STYLE_CLIP_TOP_AUTO) {
michael@0 3914 topVal->SetIdent(eCSSKeyword_auto);
michael@0 3915 } else {
michael@0 3916 topVal->SetAppUnits(display->mClip.y);
michael@0 3917 }
michael@0 3918
michael@0 3919 if (display->mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO) {
michael@0 3920 rightVal->SetIdent(eCSSKeyword_auto);
michael@0 3921 } else {
michael@0 3922 rightVal->SetAppUnits(display->mClip.width + display->mClip.x);
michael@0 3923 }
michael@0 3924
michael@0 3925 if (display->mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO) {
michael@0 3926 bottomVal->SetIdent(eCSSKeyword_auto);
michael@0 3927 } else {
michael@0 3928 bottomVal->SetAppUnits(display->mClip.height + display->mClip.y);
michael@0 3929 }
michael@0 3930
michael@0 3931 if (display->mClipFlags & NS_STYLE_CLIP_LEFT_AUTO) {
michael@0 3932 leftVal->SetIdent(eCSSKeyword_auto);
michael@0 3933 } else {
michael@0 3934 leftVal->SetAppUnits(display->mClip.x);
michael@0 3935 }
michael@0 3936 val->SetRect(domRect);
michael@0 3937 }
michael@0 3938
michael@0 3939 return val;
michael@0 3940 }
michael@0 3941
michael@0 3942 CSSValue*
michael@0 3943 nsComputedDOMStyle::DoGetWillChange()
michael@0 3944 {
michael@0 3945 const nsTArray<nsString>& willChange = StyleDisplay()->mWillChange;
michael@0 3946
michael@0 3947 if (willChange.IsEmpty()) {
michael@0 3948 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 3949 val->SetIdent(eCSSKeyword_auto);
michael@0 3950 return val;
michael@0 3951 }
michael@0 3952
michael@0 3953 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 3954 for (size_t i = 0; i < willChange.Length(); i++) {
michael@0 3955 const nsString& willChangeIdentifier = willChange[i];
michael@0 3956 nsROCSSPrimitiveValue* property = new nsROCSSPrimitiveValue;
michael@0 3957 valueList->AppendCSSValue(property);
michael@0 3958 property->SetString(willChangeIdentifier);
michael@0 3959 }
michael@0 3960
michael@0 3961 return valueList;
michael@0 3962 }
michael@0 3963
michael@0 3964 CSSValue*
michael@0 3965 nsComputedDOMStyle::DoGetOverflow()
michael@0 3966 {
michael@0 3967 const nsStyleDisplay* display = StyleDisplay();
michael@0 3968
michael@0 3969 if (display->mOverflowX != display->mOverflowY) {
michael@0 3970 // No value to return. We can't express this combination of
michael@0 3971 // values as a shorthand.
michael@0 3972 return nullptr;
michael@0 3973 }
michael@0 3974
michael@0 3975 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3976 val->SetIdent(nsCSSProps::ValueToKeywordEnum(display->mOverflowX,
michael@0 3977 nsCSSProps::kOverflowKTable));
michael@0 3978 return val;
michael@0 3979 }
michael@0 3980
michael@0 3981 CSSValue*
michael@0 3982 nsComputedDOMStyle::DoGetOverflowX()
michael@0 3983 {
michael@0 3984 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3985 val->SetIdent(
michael@0 3986 nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mOverflowX,
michael@0 3987 nsCSSProps::kOverflowSubKTable));
michael@0 3988 return val;
michael@0 3989 }
michael@0 3990
michael@0 3991 CSSValue*
michael@0 3992 nsComputedDOMStyle::DoGetOverflowY()
michael@0 3993 {
michael@0 3994 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 3995 val->SetIdent(
michael@0 3996 nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mOverflowY,
michael@0 3997 nsCSSProps::kOverflowSubKTable));
michael@0 3998 return val;
michael@0 3999 }
michael@0 4000
michael@0 4001 CSSValue*
michael@0 4002 nsComputedDOMStyle::DoGetOverflowClipBox()
michael@0 4003 {
michael@0 4004 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4005 val->SetIdent(
michael@0 4006 nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mOverflowClipBox,
michael@0 4007 nsCSSProps::kOverflowClipBoxKTable));
michael@0 4008 return val;
michael@0 4009 }
michael@0 4010
michael@0 4011 CSSValue*
michael@0 4012 nsComputedDOMStyle::DoGetResize()
michael@0 4013 {
michael@0 4014 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4015 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mResize,
michael@0 4016 nsCSSProps::kResizeKTable));
michael@0 4017 return val;
michael@0 4018 }
michael@0 4019
michael@0 4020
michael@0 4021 CSSValue*
michael@0 4022 nsComputedDOMStyle::DoGetPageBreakAfter()
michael@0 4023 {
michael@0 4024 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4025
michael@0 4026 const nsStyleDisplay *display = StyleDisplay();
michael@0 4027
michael@0 4028 if (display->mBreakAfter) {
michael@0 4029 val->SetIdent(eCSSKeyword_always);
michael@0 4030 } else {
michael@0 4031 val->SetIdent(eCSSKeyword_auto);
michael@0 4032 }
michael@0 4033
michael@0 4034 return val;
michael@0 4035 }
michael@0 4036
michael@0 4037 CSSValue*
michael@0 4038 nsComputedDOMStyle::DoGetPageBreakBefore()
michael@0 4039 {
michael@0 4040 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4041
michael@0 4042 const nsStyleDisplay *display = StyleDisplay();
michael@0 4043
michael@0 4044 if (display->mBreakBefore) {
michael@0 4045 val->SetIdent(eCSSKeyword_always);
michael@0 4046 } else {
michael@0 4047 val->SetIdent(eCSSKeyword_auto);
michael@0 4048 }
michael@0 4049
michael@0 4050 return val;
michael@0 4051 }
michael@0 4052
michael@0 4053 CSSValue*
michael@0 4054 nsComputedDOMStyle::DoGetPageBreakInside()
michael@0 4055 {
michael@0 4056 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4057 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mBreakInside,
michael@0 4058 nsCSSProps::kPageBreakInsideKTable));
michael@0 4059 return val;
michael@0 4060 }
michael@0 4061
michael@0 4062 CSSValue*
michael@0 4063 nsComputedDOMStyle::DoGetTouchAction()
michael@0 4064 {
michael@0 4065 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4066
michael@0 4067 int32_t intValue = StyleDisplay()->mTouchAction;
michael@0 4068
michael@0 4069 // None and Auto and Manipulation values aren't allowed
michael@0 4070 // to be in conjunction with other values.
michael@0 4071 // But there are all checks in CSSParserImpl::ParseTouchAction
michael@0 4072 nsAutoString valueStr;
michael@0 4073 nsStyleUtil::AppendBitmaskCSSValue(eCSSProperty_touch_action, intValue,
michael@0 4074 NS_STYLE_TOUCH_ACTION_NONE, NS_STYLE_TOUCH_ACTION_MANIPULATION,
michael@0 4075 valueStr);
michael@0 4076 val->SetString(valueStr);
michael@0 4077 return val;
michael@0 4078 }
michael@0 4079
michael@0 4080 CSSValue*
michael@0 4081 nsComputedDOMStyle::DoGetHeight()
michael@0 4082 {
michael@0 4083 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4084
michael@0 4085 bool calcHeight = false;
michael@0 4086
michael@0 4087 if (mInnerFrame) {
michael@0 4088 calcHeight = true;
michael@0 4089
michael@0 4090 const nsStyleDisplay* displayData = StyleDisplay();
michael@0 4091 if (displayData->mDisplay == NS_STYLE_DISPLAY_INLINE &&
michael@0 4092 !(mInnerFrame->IsFrameOfType(nsIFrame::eReplaced)) &&
michael@0 4093 // An outer SVG frame should behave the same as eReplaced in this case
michael@0 4094 mInnerFrame->GetType() != nsGkAtoms::svgOuterSVGFrame) {
michael@0 4095
michael@0 4096 calcHeight = false;
michael@0 4097 }
michael@0 4098 }
michael@0 4099
michael@0 4100 if (calcHeight) {
michael@0 4101 AssertFlushedPendingReflows();
michael@0 4102 nsMargin adjustedValues = GetAdjustedValuesForBoxSizing();
michael@0 4103 val->SetAppUnits(mInnerFrame->GetContentRect().height +
michael@0 4104 adjustedValues.TopBottom());
michael@0 4105 } else {
michael@0 4106 const nsStylePosition *positionData = StylePosition();
michael@0 4107
michael@0 4108 nscoord minHeight =
michael@0 4109 StyleCoordToNSCoord(positionData->mMinHeight,
michael@0 4110 &nsComputedDOMStyle::GetCBContentHeight, 0, true);
michael@0 4111
michael@0 4112 nscoord maxHeight =
michael@0 4113 StyleCoordToNSCoord(positionData->mMaxHeight,
michael@0 4114 &nsComputedDOMStyle::GetCBContentHeight,
michael@0 4115 nscoord_MAX, true);
michael@0 4116
michael@0 4117 SetValueToCoord(val, positionData->mHeight, true, nullptr, nullptr,
michael@0 4118 minHeight, maxHeight);
michael@0 4119 }
michael@0 4120
michael@0 4121 return val;
michael@0 4122 }
michael@0 4123
michael@0 4124 CSSValue*
michael@0 4125 nsComputedDOMStyle::DoGetWidth()
michael@0 4126 {
michael@0 4127 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4128
michael@0 4129 bool calcWidth = false;
michael@0 4130
michael@0 4131 if (mInnerFrame) {
michael@0 4132 calcWidth = true;
michael@0 4133
michael@0 4134 const nsStyleDisplay *displayData = StyleDisplay();
michael@0 4135 if (displayData->mDisplay == NS_STYLE_DISPLAY_INLINE &&
michael@0 4136 !(mInnerFrame->IsFrameOfType(nsIFrame::eReplaced)) &&
michael@0 4137 // An outer SVG frame should behave the same as eReplaced in this case
michael@0 4138 mInnerFrame->GetType() != nsGkAtoms::svgOuterSVGFrame) {
michael@0 4139
michael@0 4140 calcWidth = false;
michael@0 4141 }
michael@0 4142 }
michael@0 4143
michael@0 4144 if (calcWidth) {
michael@0 4145 AssertFlushedPendingReflows();
michael@0 4146 nsMargin adjustedValues = GetAdjustedValuesForBoxSizing();
michael@0 4147 val->SetAppUnits(mInnerFrame->GetContentRect().width +
michael@0 4148 adjustedValues.LeftRight());
michael@0 4149 } else {
michael@0 4150 const nsStylePosition *positionData = StylePosition();
michael@0 4151
michael@0 4152 nscoord minWidth =
michael@0 4153 StyleCoordToNSCoord(positionData->mMinWidth,
michael@0 4154 &nsComputedDOMStyle::GetCBContentWidth, 0, true);
michael@0 4155
michael@0 4156 nscoord maxWidth =
michael@0 4157 StyleCoordToNSCoord(positionData->mMaxWidth,
michael@0 4158 &nsComputedDOMStyle::GetCBContentWidth,
michael@0 4159 nscoord_MAX, true);
michael@0 4160
michael@0 4161 SetValueToCoord(val, positionData->mWidth, true, nullptr,
michael@0 4162 nsCSSProps::kWidthKTable, minWidth, maxWidth);
michael@0 4163 }
michael@0 4164
michael@0 4165 return val;
michael@0 4166 }
michael@0 4167
michael@0 4168 CSSValue*
michael@0 4169 nsComputedDOMStyle::DoGetMaxHeight()
michael@0 4170 {
michael@0 4171 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4172 SetValueToCoord(val, StylePosition()->mMaxHeight, true,
michael@0 4173 &nsComputedDOMStyle::GetCBContentHeight);
michael@0 4174 return val;
michael@0 4175 }
michael@0 4176
michael@0 4177 CSSValue*
michael@0 4178 nsComputedDOMStyle::DoGetMaxWidth()
michael@0 4179 {
michael@0 4180 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4181 SetValueToCoord(val, StylePosition()->mMaxWidth, true,
michael@0 4182 &nsComputedDOMStyle::GetCBContentWidth,
michael@0 4183 nsCSSProps::kWidthKTable);
michael@0 4184 return val;
michael@0 4185 }
michael@0 4186
michael@0 4187 CSSValue*
michael@0 4188 nsComputedDOMStyle::DoGetMinHeight()
michael@0 4189 {
michael@0 4190 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4191 SetValueToCoord(val, StylePosition()->mMinHeight, true,
michael@0 4192 &nsComputedDOMStyle::GetCBContentHeight);
michael@0 4193 return val;
michael@0 4194 }
michael@0 4195
michael@0 4196 CSSValue*
michael@0 4197 nsComputedDOMStyle::DoGetMinWidth()
michael@0 4198 {
michael@0 4199 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4200 SetValueToCoord(val, StylePosition()->mMinWidth, true,
michael@0 4201 &nsComputedDOMStyle::GetCBContentWidth,
michael@0 4202 nsCSSProps::kWidthKTable);
michael@0 4203 return val;
michael@0 4204 }
michael@0 4205
michael@0 4206 CSSValue*
michael@0 4207 nsComputedDOMStyle::DoGetMixBlendMode()
michael@0 4208 {
michael@0 4209 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4210 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleDisplay()->mMixBlendMode,
michael@0 4211 nsCSSProps::kBlendModeKTable));
michael@0 4212 return val;
michael@0 4213 }
michael@0 4214
michael@0 4215 CSSValue*
michael@0 4216 nsComputedDOMStyle::DoGetLeft()
michael@0 4217 {
michael@0 4218 return GetOffsetWidthFor(NS_SIDE_LEFT);
michael@0 4219 }
michael@0 4220
michael@0 4221 CSSValue*
michael@0 4222 nsComputedDOMStyle::DoGetRight()
michael@0 4223 {
michael@0 4224 return GetOffsetWidthFor(NS_SIDE_RIGHT);
michael@0 4225 }
michael@0 4226
michael@0 4227 CSSValue*
michael@0 4228 nsComputedDOMStyle::DoGetTop()
michael@0 4229 {
michael@0 4230 return GetOffsetWidthFor(NS_SIDE_TOP);
michael@0 4231 }
michael@0 4232
michael@0 4233 nsDOMCSSValueList*
michael@0 4234 nsComputedDOMStyle::GetROCSSValueList(bool aCommaDelimited)
michael@0 4235 {
michael@0 4236 nsDOMCSSValueList *valueList = new nsDOMCSSValueList(aCommaDelimited, true);
michael@0 4237 NS_ASSERTION(valueList != 0, "ran out of memory");
michael@0 4238
michael@0 4239 return valueList;
michael@0 4240 }
michael@0 4241
michael@0 4242 CSSValue*
michael@0 4243 nsComputedDOMStyle::GetOffsetWidthFor(mozilla::css::Side aSide)
michael@0 4244 {
michael@0 4245 const nsStyleDisplay* display = StyleDisplay();
michael@0 4246
michael@0 4247 AssertFlushedPendingReflows();
michael@0 4248
michael@0 4249 uint8_t position = display->mPosition;
michael@0 4250 if (!mOuterFrame) {
michael@0 4251 // GetRelativeOffset and GetAbsoluteOffset don't handle elements
michael@0 4252 // without frames in any sensible way. GetStaticOffset, however,
michael@0 4253 // is perfect for that case.
michael@0 4254 position = NS_STYLE_POSITION_STATIC;
michael@0 4255 }
michael@0 4256
michael@0 4257 switch (position) {
michael@0 4258 case NS_STYLE_POSITION_STATIC:
michael@0 4259 return GetStaticOffset(aSide);
michael@0 4260 case NS_STYLE_POSITION_RELATIVE:
michael@0 4261 return GetRelativeOffset(aSide);
michael@0 4262 case NS_STYLE_POSITION_STICKY:
michael@0 4263 return GetStickyOffset(aSide);
michael@0 4264 case NS_STYLE_POSITION_ABSOLUTE:
michael@0 4265 case NS_STYLE_POSITION_FIXED:
michael@0 4266 return GetAbsoluteOffset(aSide);
michael@0 4267 default:
michael@0 4268 NS_ERROR("Invalid position");
michael@0 4269 return nullptr;
michael@0 4270 }
michael@0 4271 }
michael@0 4272
michael@0 4273 CSSValue*
michael@0 4274 nsComputedDOMStyle::GetAbsoluteOffset(mozilla::css::Side aSide)
michael@0 4275 {
michael@0 4276 MOZ_ASSERT(mOuterFrame, "need a frame, so we can call GetContainingBlock()");
michael@0 4277
michael@0 4278 nsIFrame* container = mOuterFrame->GetContainingBlock();
michael@0 4279 nsMargin margin = mOuterFrame->GetUsedMargin();
michael@0 4280 nsMargin border = container->GetUsedBorder();
michael@0 4281 nsMargin scrollbarSizes(0, 0, 0, 0);
michael@0 4282 nsRect rect = mOuterFrame->GetRect();
michael@0 4283 nsRect containerRect = container->GetRect();
michael@0 4284
michael@0 4285 if (container->GetType() == nsGkAtoms::viewportFrame) {
michael@0 4286 // For absolutely positioned frames scrollbars are taken into
michael@0 4287 // account by virtue of getting a containing block that does
michael@0 4288 // _not_ include the scrollbars. For fixed positioned frames,
michael@0 4289 // the containing block is the viewport, which _does_ include
michael@0 4290 // scrollbars. We have to do some extra work.
michael@0 4291 // the first child in the default frame list is what we want
michael@0 4292 nsIFrame* scrollingChild = container->GetFirstPrincipalChild();
michael@0 4293 nsIScrollableFrame *scrollFrame = do_QueryFrame(scrollingChild);
michael@0 4294 if (scrollFrame) {
michael@0 4295 scrollbarSizes = scrollFrame->GetActualScrollbarSizes();
michael@0 4296 }
michael@0 4297 }
michael@0 4298
michael@0 4299 nscoord offset = 0;
michael@0 4300 switch (aSide) {
michael@0 4301 case NS_SIDE_TOP:
michael@0 4302 offset = rect.y - margin.top - border.top - scrollbarSizes.top;
michael@0 4303
michael@0 4304 break;
michael@0 4305 case NS_SIDE_RIGHT:
michael@0 4306 offset = containerRect.width - rect.width -
michael@0 4307 rect.x - margin.right - border.right - scrollbarSizes.right;
michael@0 4308
michael@0 4309 break;
michael@0 4310 case NS_SIDE_BOTTOM:
michael@0 4311 offset = containerRect.height - rect.height -
michael@0 4312 rect.y - margin.bottom - border.bottom - scrollbarSizes.bottom;
michael@0 4313
michael@0 4314 break;
michael@0 4315 case NS_SIDE_LEFT:
michael@0 4316 offset = rect.x - margin.left - border.left - scrollbarSizes.left;
michael@0 4317
michael@0 4318 break;
michael@0 4319 default:
michael@0 4320 NS_ERROR("Invalid side");
michael@0 4321 break;
michael@0 4322 }
michael@0 4323
michael@0 4324 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4325 val->SetAppUnits(offset);
michael@0 4326 return val;
michael@0 4327 }
michael@0 4328
michael@0 4329 static_assert(NS_SIDE_TOP == 0 && NS_SIDE_RIGHT == 1 &&
michael@0 4330 NS_SIDE_BOTTOM == 2 && NS_SIDE_LEFT == 3,
michael@0 4331 "box side constants not as expected for NS_OPPOSITE_SIDE");
michael@0 4332 #define NS_OPPOSITE_SIDE(s_) mozilla::css::Side(((s_) + 2) & 3)
michael@0 4333
michael@0 4334 CSSValue*
michael@0 4335 nsComputedDOMStyle::GetRelativeOffset(mozilla::css::Side aSide)
michael@0 4336 {
michael@0 4337 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4338
michael@0 4339 const nsStylePosition* positionData = StylePosition();
michael@0 4340 int32_t sign = 1;
michael@0 4341 nsStyleCoord coord = positionData->mOffset.Get(aSide);
michael@0 4342
michael@0 4343 NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
michael@0 4344 coord.GetUnit() == eStyleUnit_Percent ||
michael@0 4345 coord.GetUnit() == eStyleUnit_Auto ||
michael@0 4346 coord.IsCalcUnit(),
michael@0 4347 "Unexpected unit");
michael@0 4348
michael@0 4349 if (coord.GetUnit() == eStyleUnit_Auto) {
michael@0 4350 coord = positionData->mOffset.Get(NS_OPPOSITE_SIDE(aSide));
michael@0 4351 sign = -1;
michael@0 4352 }
michael@0 4353 PercentageBaseGetter baseGetter;
michael@0 4354 if (aSide == NS_SIDE_LEFT || aSide == NS_SIDE_RIGHT) {
michael@0 4355 baseGetter = &nsComputedDOMStyle::GetCBContentWidth;
michael@0 4356 } else {
michael@0 4357 baseGetter = &nsComputedDOMStyle::GetCBContentHeight;
michael@0 4358 }
michael@0 4359
michael@0 4360 val->SetAppUnits(sign * StyleCoordToNSCoord(coord, baseGetter, 0, false));
michael@0 4361 return val;
michael@0 4362 }
michael@0 4363
michael@0 4364 CSSValue*
michael@0 4365 nsComputedDOMStyle::GetStickyOffset(mozilla::css::Side aSide)
michael@0 4366 {
michael@0 4367 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4368
michael@0 4369 const nsStylePosition* positionData = StylePosition();
michael@0 4370 nsStyleCoord coord = positionData->mOffset.Get(aSide);
michael@0 4371
michael@0 4372 NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
michael@0 4373 coord.GetUnit() == eStyleUnit_Percent ||
michael@0 4374 coord.GetUnit() == eStyleUnit_Auto ||
michael@0 4375 coord.IsCalcUnit(),
michael@0 4376 "Unexpected unit");
michael@0 4377
michael@0 4378 if (coord.GetUnit() == eStyleUnit_Auto) {
michael@0 4379 val->SetIdent(eCSSKeyword_auto);
michael@0 4380 return val;
michael@0 4381 }
michael@0 4382 PercentageBaseGetter baseGetter;
michael@0 4383 if (aSide == NS_SIDE_LEFT || aSide == NS_SIDE_RIGHT) {
michael@0 4384 baseGetter = &nsComputedDOMStyle::GetScrollFrameContentWidth;
michael@0 4385 } else {
michael@0 4386 baseGetter = &nsComputedDOMStyle::GetScrollFrameContentHeight;
michael@0 4387 }
michael@0 4388
michael@0 4389 val->SetAppUnits(StyleCoordToNSCoord(coord, baseGetter, 0, false));
michael@0 4390 return val;
michael@0 4391 }
michael@0 4392
michael@0 4393
michael@0 4394 CSSValue*
michael@0 4395 nsComputedDOMStyle::GetStaticOffset(mozilla::css::Side aSide)
michael@0 4396
michael@0 4397 {
michael@0 4398 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4399 SetValueToCoord(val, StylePosition()->mOffset.Get(aSide), false);
michael@0 4400 return val;
michael@0 4401 }
michael@0 4402
michael@0 4403 CSSValue*
michael@0 4404 nsComputedDOMStyle::GetPaddingWidthFor(mozilla::css::Side aSide)
michael@0 4405 {
michael@0 4406 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4407
michael@0 4408 if (!mInnerFrame) {
michael@0 4409 SetValueToCoord(val, StylePadding()->mPadding.Get(aSide), true);
michael@0 4410 } else {
michael@0 4411 AssertFlushedPendingReflows();
michael@0 4412
michael@0 4413 val->SetAppUnits(mInnerFrame->GetUsedPadding().Side(aSide));
michael@0 4414 }
michael@0 4415
michael@0 4416 return val;
michael@0 4417 }
michael@0 4418
michael@0 4419 bool
michael@0 4420 nsComputedDOMStyle::GetLineHeightCoord(nscoord& aCoord)
michael@0 4421 {
michael@0 4422 AssertFlushedPendingReflows();
michael@0 4423
michael@0 4424 nscoord blockHeight = NS_AUTOHEIGHT;
michael@0 4425 if (StyleText()->mLineHeight.GetUnit() == eStyleUnit_Enumerated) {
michael@0 4426 if (!mInnerFrame)
michael@0 4427 return false;
michael@0 4428
michael@0 4429 if (nsLayoutUtils::IsNonWrapperBlock(mInnerFrame)) {
michael@0 4430 blockHeight = mInnerFrame->GetContentRect().height;
michael@0 4431 } else {
michael@0 4432 GetCBContentHeight(blockHeight);
michael@0 4433 }
michael@0 4434 }
michael@0 4435
michael@0 4436 // lie about font size inflation since we lie about font size (since
michael@0 4437 // the inflation only applies to text)
michael@0 4438 aCoord = nsHTMLReflowState::CalcLineHeight(mContent, mStyleContextHolder,
michael@0 4439 blockHeight, 1.0f);
michael@0 4440
michael@0 4441 // CalcLineHeight uses font->mFont.size, but we want to use
michael@0 4442 // font->mSize as the font size. Adjust for that. Also adjust for
michael@0 4443 // the text zoom, if any.
michael@0 4444 const nsStyleFont* font = StyleFont();
michael@0 4445 float fCoord = float(aCoord);
michael@0 4446 if (font->mAllowZoom) {
michael@0 4447 fCoord /= mPresShell->GetPresContext()->TextZoom();
michael@0 4448 }
michael@0 4449 if (font->mFont.size != font->mSize) {
michael@0 4450 fCoord = fCoord * (float(font->mSize) / float(font->mFont.size));
michael@0 4451 }
michael@0 4452 aCoord = NSToCoordRound(fCoord);
michael@0 4453
michael@0 4454 return true;
michael@0 4455 }
michael@0 4456
michael@0 4457 CSSValue*
michael@0 4458 nsComputedDOMStyle::GetBorderColorsFor(mozilla::css::Side aSide)
michael@0 4459 {
michael@0 4460 const nsStyleBorder *border = StyleBorder();
michael@0 4461
michael@0 4462 if (border->mBorderColors) {
michael@0 4463 nsBorderColors* borderColors = border->mBorderColors[aSide];
michael@0 4464 if (borderColors) {
michael@0 4465 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 4466
michael@0 4467 do {
michael@0 4468 nsROCSSPrimitiveValue *primitive = new nsROCSSPrimitiveValue;
michael@0 4469
michael@0 4470 SetToRGBAColor(primitive, borderColors->mColor);
michael@0 4471
michael@0 4472 valueList->AppendCSSValue(primitive);
michael@0 4473 borderColors = borderColors->mNext;
michael@0 4474 } while (borderColors);
michael@0 4475
michael@0 4476 return valueList;
michael@0 4477 }
michael@0 4478 }
michael@0 4479
michael@0 4480 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4481 val->SetIdent(eCSSKeyword_none);
michael@0 4482 return val;
michael@0 4483 }
michael@0 4484
michael@0 4485 CSSValue*
michael@0 4486 nsComputedDOMStyle::GetBorderWidthFor(mozilla::css::Side aSide)
michael@0 4487 {
michael@0 4488 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4489
michael@0 4490 nscoord width;
michael@0 4491 if (mInnerFrame) {
michael@0 4492 AssertFlushedPendingReflows();
michael@0 4493 width = mInnerFrame->GetUsedBorder().Side(aSide);
michael@0 4494 } else {
michael@0 4495 width = StyleBorder()->GetComputedBorderWidth(aSide);
michael@0 4496 }
michael@0 4497 val->SetAppUnits(width);
michael@0 4498
michael@0 4499 return val;
michael@0 4500 }
michael@0 4501
michael@0 4502 CSSValue*
michael@0 4503 nsComputedDOMStyle::GetBorderColorFor(mozilla::css::Side aSide)
michael@0 4504 {
michael@0 4505 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4506
michael@0 4507 nscolor color;
michael@0 4508 bool foreground;
michael@0 4509 StyleBorder()->GetBorderColor(aSide, color, foreground);
michael@0 4510 if (foreground) {
michael@0 4511 color = StyleColor()->mColor;
michael@0 4512 }
michael@0 4513
michael@0 4514 SetToRGBAColor(val, color);
michael@0 4515 return val;
michael@0 4516 }
michael@0 4517
michael@0 4518 CSSValue*
michael@0 4519 nsComputedDOMStyle::GetMarginWidthFor(mozilla::css::Side aSide)
michael@0 4520 {
michael@0 4521 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4522
michael@0 4523 if (!mInnerFrame) {
michael@0 4524 SetValueToCoord(val, StyleMargin()->mMargin.Get(aSide), false);
michael@0 4525 } else {
michael@0 4526 AssertFlushedPendingReflows();
michael@0 4527
michael@0 4528 // For tables, GetUsedMargin always returns an empty margin, so we
michael@0 4529 // should read the margin from the outer table frame instead.
michael@0 4530 val->SetAppUnits(mOuterFrame->GetUsedMargin().Side(aSide));
michael@0 4531 NS_ASSERTION(mOuterFrame == mInnerFrame ||
michael@0 4532 mInnerFrame->GetUsedMargin() == nsMargin(0, 0, 0, 0),
michael@0 4533 "Inner tables must have zero margins");
michael@0 4534 }
michael@0 4535
michael@0 4536 return val;
michael@0 4537 }
michael@0 4538
michael@0 4539 CSSValue*
michael@0 4540 nsComputedDOMStyle::GetBorderStyleFor(mozilla::css::Side aSide)
michael@0 4541 {
michael@0 4542 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4543 val->SetIdent(
michael@0 4544 nsCSSProps::ValueToKeywordEnum(StyleBorder()->GetBorderStyle(aSide),
michael@0 4545 nsCSSProps::kBorderStyleKTable));
michael@0 4546 return val;
michael@0 4547 }
michael@0 4548
michael@0 4549 void
michael@0 4550 nsComputedDOMStyle::SetValueToCoord(nsROCSSPrimitiveValue* aValue,
michael@0 4551 const nsStyleCoord& aCoord,
michael@0 4552 bool aClampNegativeCalc,
michael@0 4553 PercentageBaseGetter aPercentageBaseGetter,
michael@0 4554 const KTableValue aTable[],
michael@0 4555 nscoord aMinAppUnits,
michael@0 4556 nscoord aMaxAppUnits)
michael@0 4557 {
michael@0 4558 NS_PRECONDITION(aValue, "Must have a value to work with");
michael@0 4559
michael@0 4560 switch (aCoord.GetUnit()) {
michael@0 4561 case eStyleUnit_Normal:
michael@0 4562 aValue->SetIdent(eCSSKeyword_normal);
michael@0 4563 break;
michael@0 4564
michael@0 4565 case eStyleUnit_Auto:
michael@0 4566 aValue->SetIdent(eCSSKeyword_auto);
michael@0 4567 break;
michael@0 4568
michael@0 4569 case eStyleUnit_Percent:
michael@0 4570 {
michael@0 4571 nscoord percentageBase;
michael@0 4572 if (aPercentageBaseGetter &&
michael@0 4573 (this->*aPercentageBaseGetter)(percentageBase)) {
michael@0 4574 nscoord val = NSCoordSaturatingMultiply(percentageBase,
michael@0 4575 aCoord.GetPercentValue());
michael@0 4576 aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
michael@0 4577 } else {
michael@0 4578 aValue->SetPercent(aCoord.GetPercentValue());
michael@0 4579 }
michael@0 4580 }
michael@0 4581 break;
michael@0 4582
michael@0 4583 case eStyleUnit_Factor:
michael@0 4584 aValue->SetNumber(aCoord.GetFactorValue());
michael@0 4585 break;
michael@0 4586
michael@0 4587 case eStyleUnit_Coord:
michael@0 4588 {
michael@0 4589 nscoord val = aCoord.GetCoordValue();
michael@0 4590 aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
michael@0 4591 }
michael@0 4592 break;
michael@0 4593
michael@0 4594 case eStyleUnit_Integer:
michael@0 4595 aValue->SetNumber(aCoord.GetIntValue());
michael@0 4596 break;
michael@0 4597
michael@0 4598 case eStyleUnit_Enumerated:
michael@0 4599 NS_ASSERTION(aTable, "Must have table to handle this case");
michael@0 4600 aValue->SetIdent(nsCSSProps::ValueToKeywordEnum(aCoord.GetIntValue(),
michael@0 4601 aTable));
michael@0 4602 break;
michael@0 4603
michael@0 4604 case eStyleUnit_None:
michael@0 4605 aValue->SetIdent(eCSSKeyword_none);
michael@0 4606 break;
michael@0 4607
michael@0 4608 case eStyleUnit_Calc:
michael@0 4609 nscoord percentageBase;
michael@0 4610 if (!aCoord.CalcHasPercent()) {
michael@0 4611 nscoord val = nsRuleNode::ComputeCoordPercentCalc(aCoord, 0);
michael@0 4612 if (aClampNegativeCalc && val < 0) {
michael@0 4613 NS_ABORT_IF_FALSE(aCoord.IsCalcUnit(),
michael@0 4614 "parser should have rejected value");
michael@0 4615 val = 0;
michael@0 4616 }
michael@0 4617 aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
michael@0 4618 } else if (aPercentageBaseGetter &&
michael@0 4619 (this->*aPercentageBaseGetter)(percentageBase)) {
michael@0 4620 nscoord val =
michael@0 4621 nsRuleNode::ComputeCoordPercentCalc(aCoord, percentageBase);
michael@0 4622 if (aClampNegativeCalc && val < 0) {
michael@0 4623 NS_ABORT_IF_FALSE(aCoord.IsCalcUnit(),
michael@0 4624 "parser should have rejected value");
michael@0 4625 val = 0;
michael@0 4626 }
michael@0 4627 aValue->SetAppUnits(std::max(aMinAppUnits, std::min(val, aMaxAppUnits)));
michael@0 4628 } else {
michael@0 4629 nsStyleCoord::Calc *calc = aCoord.GetCalcValue();
michael@0 4630 SetValueToCalc(calc, aValue);
michael@0 4631 }
michael@0 4632 break;
michael@0 4633
michael@0 4634 case eStyleUnit_Degree:
michael@0 4635 aValue->SetDegree(aCoord.GetAngleValue());
michael@0 4636 break;
michael@0 4637
michael@0 4638 case eStyleUnit_Grad:
michael@0 4639 aValue->SetGrad(aCoord.GetAngleValue());
michael@0 4640 break;
michael@0 4641
michael@0 4642 case eStyleUnit_Radian:
michael@0 4643 aValue->SetRadian(aCoord.GetAngleValue());
michael@0 4644 break;
michael@0 4645
michael@0 4646 case eStyleUnit_Turn:
michael@0 4647 aValue->SetTurn(aCoord.GetAngleValue());
michael@0 4648 break;
michael@0 4649
michael@0 4650 case eStyleUnit_FlexFraction: {
michael@0 4651 nsAutoString tmpStr;
michael@0 4652 nsStyleUtil::AppendCSSNumber(aCoord.GetFlexFractionValue(), tmpStr);
michael@0 4653 tmpStr.AppendLiteral("fr");
michael@0 4654 aValue->SetString(tmpStr);
michael@0 4655 break;
michael@0 4656 }
michael@0 4657
michael@0 4658 default:
michael@0 4659 NS_ERROR("Can't handle this unit");
michael@0 4660 break;
michael@0 4661 }
michael@0 4662 }
michael@0 4663
michael@0 4664 nscoord
michael@0 4665 nsComputedDOMStyle::StyleCoordToNSCoord(const nsStyleCoord& aCoord,
michael@0 4666 PercentageBaseGetter aPercentageBaseGetter,
michael@0 4667 nscoord aDefaultValue,
michael@0 4668 bool aClampNegativeCalc)
michael@0 4669 {
michael@0 4670 NS_PRECONDITION(aPercentageBaseGetter, "Must have a percentage base getter");
michael@0 4671 if (aCoord.GetUnit() == eStyleUnit_Coord) {
michael@0 4672 return aCoord.GetCoordValue();
michael@0 4673 }
michael@0 4674 if (aCoord.GetUnit() == eStyleUnit_Percent || aCoord.IsCalcUnit()) {
michael@0 4675 nscoord percentageBase;
michael@0 4676 if ((this->*aPercentageBaseGetter)(percentageBase)) {
michael@0 4677 nscoord result =
michael@0 4678 nsRuleNode::ComputeCoordPercentCalc(aCoord, percentageBase);
michael@0 4679 if (aClampNegativeCalc && result < 0) {
michael@0 4680 NS_ABORT_IF_FALSE(aCoord.IsCalcUnit(),
michael@0 4681 "parser should have rejected value");
michael@0 4682 result = 0;
michael@0 4683 }
michael@0 4684 return result;
michael@0 4685 }
michael@0 4686 // Fall through to returning aDefaultValue if we have no percentage base.
michael@0 4687 }
michael@0 4688
michael@0 4689 return aDefaultValue;
michael@0 4690 }
michael@0 4691
michael@0 4692 bool
michael@0 4693 nsComputedDOMStyle::GetCBContentWidth(nscoord& aWidth)
michael@0 4694 {
michael@0 4695 if (!mOuterFrame) {
michael@0 4696 return false;
michael@0 4697 }
michael@0 4698
michael@0 4699 AssertFlushedPendingReflows();
michael@0 4700
michael@0 4701 nsIFrame* container = mOuterFrame->GetContainingBlock();
michael@0 4702 aWidth = container->GetContentRect().width;
michael@0 4703 return true;
michael@0 4704 }
michael@0 4705
michael@0 4706 bool
michael@0 4707 nsComputedDOMStyle::GetCBContentHeight(nscoord& aHeight)
michael@0 4708 {
michael@0 4709 if (!mOuterFrame) {
michael@0 4710 return false;
michael@0 4711 }
michael@0 4712
michael@0 4713 AssertFlushedPendingReflows();
michael@0 4714
michael@0 4715 nsIFrame* container = mOuterFrame->GetContainingBlock();
michael@0 4716 aHeight = container->GetContentRect().height;
michael@0 4717 return true;
michael@0 4718 }
michael@0 4719
michael@0 4720 bool
michael@0 4721 nsComputedDOMStyle::GetScrollFrameContentWidth(nscoord& aWidth)
michael@0 4722 {
michael@0 4723 if (!mOuterFrame) {
michael@0 4724 return false;
michael@0 4725 }
michael@0 4726
michael@0 4727 AssertFlushedPendingReflows();
michael@0 4728
michael@0 4729 nsIScrollableFrame* scrollableFrame =
michael@0 4730 nsLayoutUtils::GetNearestScrollableFrame(mOuterFrame->GetParent(),
michael@0 4731 nsLayoutUtils::SCROLLABLE_SAME_DOC |
michael@0 4732 nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
michael@0 4733
michael@0 4734 if (!scrollableFrame) {
michael@0 4735 return false;
michael@0 4736 }
michael@0 4737 aWidth =
michael@0 4738 scrollableFrame->GetScrolledFrame()->GetContentRectRelativeToSelf().width;
michael@0 4739 return true;
michael@0 4740 }
michael@0 4741
michael@0 4742 bool
michael@0 4743 nsComputedDOMStyle::GetScrollFrameContentHeight(nscoord& aHeight)
michael@0 4744 {
michael@0 4745 if (!mOuterFrame) {
michael@0 4746 return false;
michael@0 4747 }
michael@0 4748
michael@0 4749 AssertFlushedPendingReflows();
michael@0 4750
michael@0 4751 nsIScrollableFrame* scrollableFrame =
michael@0 4752 nsLayoutUtils::GetNearestScrollableFrame(mOuterFrame->GetParent(),
michael@0 4753 nsLayoutUtils::SCROLLABLE_SAME_DOC |
michael@0 4754 nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
michael@0 4755
michael@0 4756 if (!scrollableFrame) {
michael@0 4757 return false;
michael@0 4758 }
michael@0 4759 aHeight =
michael@0 4760 scrollableFrame->GetScrolledFrame()->GetContentRectRelativeToSelf().height;
michael@0 4761 return true;
michael@0 4762 }
michael@0 4763
michael@0 4764 bool
michael@0 4765 nsComputedDOMStyle::GetFrameBorderRectWidth(nscoord& aWidth)
michael@0 4766 {
michael@0 4767 if (!mInnerFrame) {
michael@0 4768 return false;
michael@0 4769 }
michael@0 4770
michael@0 4771 AssertFlushedPendingReflows();
michael@0 4772
michael@0 4773 aWidth = mInnerFrame->GetSize().width;
michael@0 4774 return true;
michael@0 4775 }
michael@0 4776
michael@0 4777 bool
michael@0 4778 nsComputedDOMStyle::GetFrameBorderRectHeight(nscoord& aHeight)
michael@0 4779 {
michael@0 4780 if (!mInnerFrame) {
michael@0 4781 return false;
michael@0 4782 }
michael@0 4783
michael@0 4784 AssertFlushedPendingReflows();
michael@0 4785
michael@0 4786 aHeight = mInnerFrame->GetSize().height;
michael@0 4787 return true;
michael@0 4788 }
michael@0 4789
michael@0 4790 bool
michael@0 4791 nsComputedDOMStyle::GetFrameBoundsWidthForTransform(nscoord& aWidth)
michael@0 4792 {
michael@0 4793 // We need a frame to work with.
michael@0 4794 if (!mInnerFrame) {
michael@0 4795 return false;
michael@0 4796 }
michael@0 4797
michael@0 4798 AssertFlushedPendingReflows();
michael@0 4799
michael@0 4800 aWidth = nsDisplayTransform::GetFrameBoundsForTransform(mInnerFrame).width;
michael@0 4801 return true;
michael@0 4802 }
michael@0 4803
michael@0 4804 bool
michael@0 4805 nsComputedDOMStyle::GetFrameBoundsHeightForTransform(nscoord& aHeight)
michael@0 4806 {
michael@0 4807 // We need a frame to work with.
michael@0 4808 if (!mInnerFrame) {
michael@0 4809 return false;
michael@0 4810 }
michael@0 4811
michael@0 4812 AssertFlushedPendingReflows();
michael@0 4813
michael@0 4814 aHeight = nsDisplayTransform::GetFrameBoundsForTransform(mInnerFrame).height;
michael@0 4815 return true;
michael@0 4816 }
michael@0 4817
michael@0 4818 CSSValue*
michael@0 4819 nsComputedDOMStyle::GetSVGPaintFor(bool aFill)
michael@0 4820 {
michael@0 4821 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4822
michael@0 4823 const nsStyleSVG* svg = StyleSVG();
michael@0 4824 const nsStyleSVGPaint* paint = nullptr;
michael@0 4825
michael@0 4826 if (aFill)
michael@0 4827 paint = &svg->mFill;
michael@0 4828 else
michael@0 4829 paint = &svg->mStroke;
michael@0 4830
michael@0 4831 nsAutoString paintString;
michael@0 4832
michael@0 4833 switch (paint->mType) {
michael@0 4834 case eStyleSVGPaintType_None:
michael@0 4835 {
michael@0 4836 val->SetIdent(eCSSKeyword_none);
michael@0 4837 break;
michael@0 4838 }
michael@0 4839 case eStyleSVGPaintType_Color:
michael@0 4840 {
michael@0 4841 SetToRGBAColor(val, paint->mPaint.mColor);
michael@0 4842 break;
michael@0 4843 }
michael@0 4844 case eStyleSVGPaintType_Server:
michael@0 4845 {
michael@0 4846 nsDOMCSSValueList *valueList = GetROCSSValueList(false);
michael@0 4847 valueList->AppendCSSValue(val);
michael@0 4848
michael@0 4849 nsROCSSPrimitiveValue* fallback = new nsROCSSPrimitiveValue;
michael@0 4850 valueList->AppendCSSValue(fallback);
michael@0 4851
michael@0 4852 val->SetURI(paint->mPaint.mPaintServer);
michael@0 4853 SetToRGBAColor(fallback, paint->mFallbackColor);
michael@0 4854 return valueList;
michael@0 4855 }
michael@0 4856 case eStyleSVGPaintType_ContextFill:
michael@0 4857 {
michael@0 4858 val->SetIdent(eCSSKeyword_context_fill);
michael@0 4859 break;
michael@0 4860 }
michael@0 4861 case eStyleSVGPaintType_ContextStroke:
michael@0 4862 {
michael@0 4863 val->SetIdent(eCSSKeyword_context_stroke);
michael@0 4864 break;
michael@0 4865 }
michael@0 4866 }
michael@0 4867
michael@0 4868 return val;
michael@0 4869 }
michael@0 4870
michael@0 4871 CSSValue*
michael@0 4872 nsComputedDOMStyle::DoGetFill()
michael@0 4873 {
michael@0 4874 return GetSVGPaintFor(true);
michael@0 4875 }
michael@0 4876
michael@0 4877 CSSValue*
michael@0 4878 nsComputedDOMStyle::DoGetStroke()
michael@0 4879 {
michael@0 4880 return GetSVGPaintFor(false);
michael@0 4881 }
michael@0 4882
michael@0 4883 CSSValue*
michael@0 4884 nsComputedDOMStyle::DoGetMarkerEnd()
michael@0 4885 {
michael@0 4886 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4887
michael@0 4888 const nsStyleSVG* svg = StyleSVG();
michael@0 4889
michael@0 4890 if (svg->mMarkerEnd)
michael@0 4891 val->SetURI(svg->mMarkerEnd);
michael@0 4892 else
michael@0 4893 val->SetIdent(eCSSKeyword_none);
michael@0 4894
michael@0 4895 return val;
michael@0 4896 }
michael@0 4897
michael@0 4898 CSSValue*
michael@0 4899 nsComputedDOMStyle::DoGetMarkerMid()
michael@0 4900 {
michael@0 4901 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4902
michael@0 4903 const nsStyleSVG* svg = StyleSVG();
michael@0 4904
michael@0 4905 if (svg->mMarkerMid)
michael@0 4906 val->SetURI(svg->mMarkerMid);
michael@0 4907 else
michael@0 4908 val->SetIdent(eCSSKeyword_none);
michael@0 4909
michael@0 4910 return val;
michael@0 4911 }
michael@0 4912
michael@0 4913 CSSValue*
michael@0 4914 nsComputedDOMStyle::DoGetMarkerStart()
michael@0 4915 {
michael@0 4916 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4917
michael@0 4918 const nsStyleSVG* svg = StyleSVG();
michael@0 4919
michael@0 4920 if (svg->mMarkerStart)
michael@0 4921 val->SetURI(svg->mMarkerStart);
michael@0 4922 else
michael@0 4923 val->SetIdent(eCSSKeyword_none);
michael@0 4924
michael@0 4925 return val;
michael@0 4926 }
michael@0 4927
michael@0 4928 CSSValue*
michael@0 4929 nsComputedDOMStyle::DoGetStrokeDasharray()
michael@0 4930 {
michael@0 4931 const nsStyleSVG* svg = StyleSVG();
michael@0 4932
michael@0 4933 if (!svg->mStrokeDasharrayLength || !svg->mStrokeDasharray) {
michael@0 4934 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4935 val->SetIdent(eCSSKeyword_none);
michael@0 4936 return val;
michael@0 4937 }
michael@0 4938
michael@0 4939 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 4940
michael@0 4941 for (uint32_t i = 0; i < svg->mStrokeDasharrayLength; i++) {
michael@0 4942 nsROCSSPrimitiveValue* dash = new nsROCSSPrimitiveValue;
michael@0 4943 valueList->AppendCSSValue(dash);
michael@0 4944
michael@0 4945 SetValueToCoord(dash, svg->mStrokeDasharray[i], true);
michael@0 4946 }
michael@0 4947
michael@0 4948 return valueList;
michael@0 4949 }
michael@0 4950
michael@0 4951 CSSValue*
michael@0 4952 nsComputedDOMStyle::DoGetStrokeDashoffset()
michael@0 4953 {
michael@0 4954 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4955 SetValueToCoord(val, StyleSVG()->mStrokeDashoffset, false);
michael@0 4956 return val;
michael@0 4957 }
michael@0 4958
michael@0 4959 CSSValue*
michael@0 4960 nsComputedDOMStyle::DoGetStrokeWidth()
michael@0 4961 {
michael@0 4962 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 4963 SetValueToCoord(val, StyleSVG()->mStrokeWidth, true);
michael@0 4964 return val;
michael@0 4965 }
michael@0 4966
michael@0 4967 CSSValue*
michael@0 4968 nsComputedDOMStyle::DoGetVectorEffect()
michael@0 4969 {
michael@0 4970 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4971 val->SetIdent(nsCSSProps::ValueToKeywordEnum(StyleSVGReset()->mVectorEffect,
michael@0 4972 nsCSSProps::kVectorEffectKTable));
michael@0 4973 return val;
michael@0 4974 }
michael@0 4975
michael@0 4976 CSSValue*
michael@0 4977 nsComputedDOMStyle::DoGetFillOpacity()
michael@0 4978 {
michael@0 4979 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4980 val->SetNumber(StyleSVG()->mFillOpacity);
michael@0 4981 return val;
michael@0 4982 }
michael@0 4983
michael@0 4984 CSSValue*
michael@0 4985 nsComputedDOMStyle::DoGetFloodOpacity()
michael@0 4986 {
michael@0 4987 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4988 val->SetNumber(StyleSVGReset()->mFloodOpacity);
michael@0 4989 return val;
michael@0 4990 }
michael@0 4991
michael@0 4992 CSSValue*
michael@0 4993 nsComputedDOMStyle::DoGetStopOpacity()
michael@0 4994 {
michael@0 4995 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 4996 val->SetNumber(StyleSVGReset()->mStopOpacity);
michael@0 4997 return val;
michael@0 4998 }
michael@0 4999
michael@0 5000 CSSValue*
michael@0 5001 nsComputedDOMStyle::DoGetStrokeMiterlimit()
michael@0 5002 {
michael@0 5003 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5004 val->SetNumber(StyleSVG()->mStrokeMiterlimit);
michael@0 5005 return val;
michael@0 5006 }
michael@0 5007
michael@0 5008 CSSValue*
michael@0 5009 nsComputedDOMStyle::DoGetStrokeOpacity()
michael@0 5010 {
michael@0 5011 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5012 val->SetNumber(StyleSVG()->mStrokeOpacity);
michael@0 5013 return val;
michael@0 5014 }
michael@0 5015
michael@0 5016 CSSValue*
michael@0 5017 nsComputedDOMStyle::DoGetClipRule()
michael@0 5018 {
michael@0 5019 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5020 val->SetIdent(nsCSSProps::ValueToKeywordEnum(
michael@0 5021 StyleSVG()->mClipRule, nsCSSProps::kFillRuleKTable));
michael@0 5022 return val;
michael@0 5023 }
michael@0 5024
michael@0 5025 CSSValue*
michael@0 5026 nsComputedDOMStyle::DoGetFillRule()
michael@0 5027 {
michael@0 5028 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5029 val->SetIdent(nsCSSProps::ValueToKeywordEnum(
michael@0 5030 StyleSVG()->mFillRule, nsCSSProps::kFillRuleKTable));
michael@0 5031 return val;
michael@0 5032 }
michael@0 5033
michael@0 5034 CSSValue*
michael@0 5035 nsComputedDOMStyle::DoGetStrokeLinecap()
michael@0 5036 {
michael@0 5037 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5038 val->SetIdent(
michael@0 5039 nsCSSProps::ValueToKeywordEnum(StyleSVG()->mStrokeLinecap,
michael@0 5040 nsCSSProps::kStrokeLinecapKTable));
michael@0 5041 return val;
michael@0 5042 }
michael@0 5043
michael@0 5044 CSSValue*
michael@0 5045 nsComputedDOMStyle::DoGetStrokeLinejoin()
michael@0 5046 {
michael@0 5047 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5048 val->SetIdent(
michael@0 5049 nsCSSProps::ValueToKeywordEnum(StyleSVG()->mStrokeLinejoin,
michael@0 5050 nsCSSProps::kStrokeLinejoinKTable));
michael@0 5051 return val;
michael@0 5052 }
michael@0 5053
michael@0 5054 CSSValue*
michael@0 5055 nsComputedDOMStyle::DoGetTextAnchor()
michael@0 5056 {
michael@0 5057 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5058 val->SetIdent(
michael@0 5059 nsCSSProps::ValueToKeywordEnum(StyleSVG()->mTextAnchor,
michael@0 5060 nsCSSProps::kTextAnchorKTable));
michael@0 5061 return val;
michael@0 5062 }
michael@0 5063
michael@0 5064 CSSValue*
michael@0 5065 nsComputedDOMStyle::DoGetColorInterpolation()
michael@0 5066 {
michael@0 5067 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5068 val->SetIdent(
michael@0 5069 nsCSSProps::ValueToKeywordEnum(StyleSVG()->mColorInterpolation,
michael@0 5070 nsCSSProps::kColorInterpolationKTable));
michael@0 5071 return val;
michael@0 5072 }
michael@0 5073
michael@0 5074 CSSValue*
michael@0 5075 nsComputedDOMStyle::DoGetColorInterpolationFilters()
michael@0 5076 {
michael@0 5077 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5078 val->SetIdent(
michael@0 5079 nsCSSProps::ValueToKeywordEnum(StyleSVG()->mColorInterpolationFilters,
michael@0 5080 nsCSSProps::kColorInterpolationKTable));
michael@0 5081 return val;
michael@0 5082 }
michael@0 5083
michael@0 5084 CSSValue*
michael@0 5085 nsComputedDOMStyle::DoGetDominantBaseline()
michael@0 5086 {
michael@0 5087 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5088 val->SetIdent(
michael@0 5089 nsCSSProps::ValueToKeywordEnum(StyleSVGReset()->mDominantBaseline,
michael@0 5090 nsCSSProps::kDominantBaselineKTable));
michael@0 5091 return val;
michael@0 5092 }
michael@0 5093
michael@0 5094 CSSValue*
michael@0 5095 nsComputedDOMStyle::DoGetImageRendering()
michael@0 5096 {
michael@0 5097 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5098 val->SetIdent(
michael@0 5099 nsCSSProps::ValueToKeywordEnum(StyleSVG()->mImageRendering,
michael@0 5100 nsCSSProps::kImageRenderingKTable));
michael@0 5101 return val;
michael@0 5102 }
michael@0 5103
michael@0 5104 CSSValue*
michael@0 5105 nsComputedDOMStyle::DoGetShapeRendering()
michael@0 5106 {
michael@0 5107 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5108 val->SetIdent(
michael@0 5109 nsCSSProps::ValueToKeywordEnum(StyleSVG()->mShapeRendering,
michael@0 5110 nsCSSProps::kShapeRenderingKTable));
michael@0 5111 return val;
michael@0 5112 }
michael@0 5113
michael@0 5114 CSSValue*
michael@0 5115 nsComputedDOMStyle::DoGetTextRendering()
michael@0 5116 {
michael@0 5117 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5118 val->SetIdent(
michael@0 5119 nsCSSProps::ValueToKeywordEnum(StyleSVG()->mTextRendering,
michael@0 5120 nsCSSProps::kTextRenderingKTable));
michael@0 5121 return val;
michael@0 5122 }
michael@0 5123
michael@0 5124 CSSValue*
michael@0 5125 nsComputedDOMStyle::DoGetFloodColor()
michael@0 5126 {
michael@0 5127 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5128 SetToRGBAColor(val, StyleSVGReset()->mFloodColor);
michael@0 5129 return val;
michael@0 5130 }
michael@0 5131
michael@0 5132 CSSValue*
michael@0 5133 nsComputedDOMStyle::DoGetLightingColor()
michael@0 5134 {
michael@0 5135 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5136 SetToRGBAColor(val, StyleSVGReset()->mLightingColor);
michael@0 5137 return val;
michael@0 5138 }
michael@0 5139
michael@0 5140 CSSValue*
michael@0 5141 nsComputedDOMStyle::DoGetStopColor()
michael@0 5142 {
michael@0 5143 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5144 SetToRGBAColor(val, StyleSVGReset()->mStopColor);
michael@0 5145 return val;
michael@0 5146 }
michael@0 5147
michael@0 5148 CSSValue*
michael@0 5149 nsComputedDOMStyle::DoGetClipPath()
michael@0 5150 {
michael@0 5151 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 5152
michael@0 5153 const nsStyleSVGReset* svg = StyleSVGReset();
michael@0 5154
michael@0 5155 if (svg->mClipPath)
michael@0 5156 val->SetURI(svg->mClipPath);
michael@0 5157 else
michael@0 5158 val->SetIdent(eCSSKeyword_none);
michael@0 5159
michael@0 5160 return val;
michael@0 5161 }
michael@0 5162
michael@0 5163 void
michael@0 5164 nsComputedDOMStyle::SetCssTextToCoord(nsAString& aCssText,
michael@0 5165 const nsStyleCoord& aCoord)
michael@0 5166 {
michael@0 5167 nsROCSSPrimitiveValue* value = new nsROCSSPrimitiveValue;
michael@0 5168 bool clampNegativeCalc = true;
michael@0 5169 SetValueToCoord(value, aCoord, clampNegativeCalc);
michael@0 5170 value->GetCssText(aCssText);
michael@0 5171 delete value;
michael@0 5172 }
michael@0 5173
michael@0 5174 CSSValue*
michael@0 5175 nsComputedDOMStyle::CreatePrimitiveValueForStyleFilter(
michael@0 5176 const nsStyleFilter& aStyleFilter)
michael@0 5177 {
michael@0 5178 nsROCSSPrimitiveValue* value = new nsROCSSPrimitiveValue;
michael@0 5179 // Handle url().
michael@0 5180 if (aStyleFilter.GetType() == NS_STYLE_FILTER_URL) {
michael@0 5181 value->SetURI(aStyleFilter.GetURL());
michael@0 5182 return value;
michael@0 5183 }
michael@0 5184
michael@0 5185 // Filter function name and opening parenthesis.
michael@0 5186 nsAutoString filterFunctionString;
michael@0 5187 AppendASCIItoUTF16(
michael@0 5188 nsCSSProps::ValueToKeyword(aStyleFilter.GetType(),
michael@0 5189 nsCSSProps::kFilterFunctionKTable),
michael@0 5190 filterFunctionString);
michael@0 5191 filterFunctionString.AppendLiteral("(");
michael@0 5192
michael@0 5193 nsAutoString argumentString;
michael@0 5194 if (aStyleFilter.GetType() == NS_STYLE_FILTER_DROP_SHADOW) {
michael@0 5195 // Handle drop-shadow()
michael@0 5196 nsRefPtr<CSSValue> shadowValue =
michael@0 5197 GetCSSShadowArray(aStyleFilter.GetDropShadow(),
michael@0 5198 StyleColor()->mColor,
michael@0 5199 false);
michael@0 5200 ErrorResult dummy;
michael@0 5201 shadowValue->GetCssText(argumentString, dummy);
michael@0 5202 } else {
michael@0 5203 // Filter function argument.
michael@0 5204 SetCssTextToCoord(argumentString, aStyleFilter.GetFilterParameter());
michael@0 5205 }
michael@0 5206 filterFunctionString.Append(argumentString);
michael@0 5207
michael@0 5208 // Filter function closing parenthesis.
michael@0 5209 filterFunctionString.AppendLiteral(")");
michael@0 5210
michael@0 5211 value->SetString(filterFunctionString);
michael@0 5212 return value;
michael@0 5213 }
michael@0 5214
michael@0 5215 CSSValue*
michael@0 5216 nsComputedDOMStyle::DoGetFilter()
michael@0 5217 {
michael@0 5218 const nsTArray<nsStyleFilter>& filters = StyleSVGReset()->mFilters;
michael@0 5219
michael@0 5220 if (filters.IsEmpty()) {
michael@0 5221 nsROCSSPrimitiveValue* value = new nsROCSSPrimitiveValue;
michael@0 5222 value->SetIdent(eCSSKeyword_none);
michael@0 5223 return value;
michael@0 5224 }
michael@0 5225
michael@0 5226 nsDOMCSSValueList* valueList = GetROCSSValueList(false);
michael@0 5227 for(uint32_t i = 0; i < filters.Length(); i++) {
michael@0 5228 CSSValue* value = CreatePrimitiveValueForStyleFilter(filters[i]);
michael@0 5229 valueList->AppendCSSValue(value);
michael@0 5230 }
michael@0 5231 return valueList;
michael@0 5232 }
michael@0 5233
michael@0 5234 CSSValue*
michael@0 5235 nsComputedDOMStyle::DoGetMask()
michael@0 5236 {
michael@0 5237 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 5238
michael@0 5239 const nsStyleSVGReset* svg = StyleSVGReset();
michael@0 5240
michael@0 5241 if (svg->mMask)
michael@0 5242 val->SetURI(svg->mMask);
michael@0 5243 else
michael@0 5244 val->SetIdent(eCSSKeyword_none);
michael@0 5245
michael@0 5246 return val;
michael@0 5247 }
michael@0 5248
michael@0 5249 CSSValue*
michael@0 5250 nsComputedDOMStyle::DoGetMaskType()
michael@0 5251 {
michael@0 5252 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5253 val->SetIdent(
michael@0 5254 nsCSSProps::ValueToKeywordEnum(StyleSVGReset()->mMaskType,
michael@0 5255 nsCSSProps::kMaskTypeKTable));
michael@0 5256 return val;
michael@0 5257 }
michael@0 5258
michael@0 5259 CSSValue*
michael@0 5260 nsComputedDOMStyle::DoGetPaintOrder()
michael@0 5261 {
michael@0 5262 nsROCSSPrimitiveValue *val = new nsROCSSPrimitiveValue;
michael@0 5263 nsAutoString string;
michael@0 5264 uint8_t paintOrder = StyleSVG()->mPaintOrder;
michael@0 5265 nsStyleUtil::AppendPaintOrderValue(paintOrder, string);
michael@0 5266 val->SetString(string);
michael@0 5267 return val;
michael@0 5268 }
michael@0 5269
michael@0 5270 CSSValue*
michael@0 5271 nsComputedDOMStyle::DoGetTransitionDelay()
michael@0 5272 {
michael@0 5273 const nsStyleDisplay* display = StyleDisplay();
michael@0 5274
michael@0 5275 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5276
michael@0 5277 NS_ABORT_IF_FALSE(display->mTransitionDelayCount > 0,
michael@0 5278 "first item must be explicit");
michael@0 5279 uint32_t i = 0;
michael@0 5280 do {
michael@0 5281 const nsTransition *transition = &display->mTransitions[i];
michael@0 5282 nsROCSSPrimitiveValue* delay = new nsROCSSPrimitiveValue;
michael@0 5283 valueList->AppendCSSValue(delay);
michael@0 5284 delay->SetTime((float)transition->GetDelay() / (float)PR_MSEC_PER_SEC);
michael@0 5285 } while (++i < display->mTransitionDelayCount);
michael@0 5286
michael@0 5287 return valueList;
michael@0 5288 }
michael@0 5289
michael@0 5290 CSSValue*
michael@0 5291 nsComputedDOMStyle::DoGetTransitionDuration()
michael@0 5292 {
michael@0 5293 const nsStyleDisplay* display = StyleDisplay();
michael@0 5294
michael@0 5295 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5296
michael@0 5297 NS_ABORT_IF_FALSE(display->mTransitionDurationCount > 0,
michael@0 5298 "first item must be explicit");
michael@0 5299 uint32_t i = 0;
michael@0 5300 do {
michael@0 5301 const nsTransition *transition = &display->mTransitions[i];
michael@0 5302 nsROCSSPrimitiveValue* duration = new nsROCSSPrimitiveValue;
michael@0 5303 valueList->AppendCSSValue(duration);
michael@0 5304
michael@0 5305 duration->SetTime((float)transition->GetDuration() / (float)PR_MSEC_PER_SEC);
michael@0 5306 } while (++i < display->mTransitionDurationCount);
michael@0 5307
michael@0 5308 return valueList;
michael@0 5309 }
michael@0 5310
michael@0 5311 CSSValue*
michael@0 5312 nsComputedDOMStyle::DoGetTransitionProperty()
michael@0 5313 {
michael@0 5314 const nsStyleDisplay* display = StyleDisplay();
michael@0 5315
michael@0 5316 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5317
michael@0 5318 NS_ABORT_IF_FALSE(display->mTransitionPropertyCount > 0,
michael@0 5319 "first item must be explicit");
michael@0 5320 uint32_t i = 0;
michael@0 5321 do {
michael@0 5322 const nsTransition *transition = &display->mTransitions[i];
michael@0 5323 nsROCSSPrimitiveValue* property = new nsROCSSPrimitiveValue;
michael@0 5324 valueList->AppendCSSValue(property);
michael@0 5325 nsCSSProperty cssprop = transition->GetProperty();
michael@0 5326 if (cssprop == eCSSPropertyExtra_all_properties)
michael@0 5327 property->SetIdent(eCSSKeyword_all);
michael@0 5328 else if (cssprop == eCSSPropertyExtra_no_properties)
michael@0 5329 property->SetIdent(eCSSKeyword_none);
michael@0 5330 else if (cssprop == eCSSProperty_UNKNOWN)
michael@0 5331 {
michael@0 5332 nsAutoString escaped;
michael@0 5333 nsStyleUtil::AppendEscapedCSSIdent(
michael@0 5334 nsDependentAtomString(transition->GetUnknownProperty()), escaped);
michael@0 5335 property->SetString(escaped); // really want SetIdent
michael@0 5336 }
michael@0 5337 else
michael@0 5338 property->SetString(nsCSSProps::GetStringValue(cssprop));
michael@0 5339 } while (++i < display->mTransitionPropertyCount);
michael@0 5340
michael@0 5341 return valueList;
michael@0 5342 }
michael@0 5343
michael@0 5344 void
michael@0 5345 nsComputedDOMStyle::AppendTimingFunction(nsDOMCSSValueList *aValueList,
michael@0 5346 const nsTimingFunction& aTimingFunction)
michael@0 5347 {
michael@0 5348 nsROCSSPrimitiveValue* timingFunction = new nsROCSSPrimitiveValue;
michael@0 5349 aValueList->AppendCSSValue(timingFunction);
michael@0 5350
michael@0 5351 nsAutoString tmp;
michael@0 5352
michael@0 5353 if (aTimingFunction.mType == nsTimingFunction::Function) {
michael@0 5354 // set the value from the cubic-bezier control points
michael@0 5355 // (We could try to regenerate the keywords if we want.)
michael@0 5356 tmp.AppendLiteral("cubic-bezier(");
michael@0 5357 tmp.AppendFloat(aTimingFunction.mFunc.mX1);
michael@0 5358 tmp.AppendLiteral(", ");
michael@0 5359 tmp.AppendFloat(aTimingFunction.mFunc.mY1);
michael@0 5360 tmp.AppendLiteral(", ");
michael@0 5361 tmp.AppendFloat(aTimingFunction.mFunc.mX2);
michael@0 5362 tmp.AppendLiteral(", ");
michael@0 5363 tmp.AppendFloat(aTimingFunction.mFunc.mY2);
michael@0 5364 tmp.AppendLiteral(")");
michael@0 5365 } else {
michael@0 5366 tmp.AppendLiteral("steps(");
michael@0 5367 tmp.AppendInt(aTimingFunction.mSteps);
michael@0 5368 if (aTimingFunction.mType == nsTimingFunction::StepStart) {
michael@0 5369 tmp.AppendLiteral(", start)");
michael@0 5370 } else {
michael@0 5371 tmp.AppendLiteral(", end)");
michael@0 5372 }
michael@0 5373 }
michael@0 5374 timingFunction->SetString(tmp);
michael@0 5375 }
michael@0 5376
michael@0 5377 CSSValue*
michael@0 5378 nsComputedDOMStyle::DoGetTransitionTimingFunction()
michael@0 5379 {
michael@0 5380 const nsStyleDisplay* display = StyleDisplay();
michael@0 5381
michael@0 5382 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5383
michael@0 5384 NS_ABORT_IF_FALSE(display->mTransitionTimingFunctionCount > 0,
michael@0 5385 "first item must be explicit");
michael@0 5386 uint32_t i = 0;
michael@0 5387 do {
michael@0 5388 AppendTimingFunction(valueList,
michael@0 5389 display->mTransitions[i].GetTimingFunction());
michael@0 5390 } while (++i < display->mTransitionTimingFunctionCount);
michael@0 5391
michael@0 5392 return valueList;
michael@0 5393 }
michael@0 5394
michael@0 5395 CSSValue*
michael@0 5396 nsComputedDOMStyle::DoGetAnimationName()
michael@0 5397 {
michael@0 5398 const nsStyleDisplay* display = StyleDisplay();
michael@0 5399
michael@0 5400 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5401
michael@0 5402 NS_ABORT_IF_FALSE(display->mAnimationNameCount > 0,
michael@0 5403 "first item must be explicit");
michael@0 5404 uint32_t i = 0;
michael@0 5405 do {
michael@0 5406 const nsAnimation *animation = &display->mAnimations[i];
michael@0 5407 nsROCSSPrimitiveValue* property = new nsROCSSPrimitiveValue;
michael@0 5408 valueList->AppendCSSValue(property);
michael@0 5409
michael@0 5410 const nsString& name = animation->GetName();
michael@0 5411 if (name.IsEmpty()) {
michael@0 5412 property->SetIdent(eCSSKeyword_none);
michael@0 5413 } else {
michael@0 5414 nsAutoString escaped;
michael@0 5415 nsStyleUtil::AppendEscapedCSSIdent(animation->GetName(), escaped);
michael@0 5416 property->SetString(escaped); // really want SetIdent
michael@0 5417 }
michael@0 5418 } while (++i < display->mAnimationNameCount);
michael@0 5419
michael@0 5420 return valueList;
michael@0 5421 }
michael@0 5422
michael@0 5423 CSSValue*
michael@0 5424 nsComputedDOMStyle::DoGetAnimationDelay()
michael@0 5425 {
michael@0 5426 const nsStyleDisplay* display = StyleDisplay();
michael@0 5427
michael@0 5428 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5429
michael@0 5430 NS_ABORT_IF_FALSE(display->mAnimationDelayCount > 0,
michael@0 5431 "first item must be explicit");
michael@0 5432 uint32_t i = 0;
michael@0 5433 do {
michael@0 5434 const nsAnimation *animation = &display->mAnimations[i];
michael@0 5435 nsROCSSPrimitiveValue* delay = new nsROCSSPrimitiveValue;
michael@0 5436 valueList->AppendCSSValue(delay);
michael@0 5437 delay->SetTime((float)animation->GetDelay() / (float)PR_MSEC_PER_SEC);
michael@0 5438 } while (++i < display->mAnimationDelayCount);
michael@0 5439
michael@0 5440 return valueList;
michael@0 5441 }
michael@0 5442
michael@0 5443 CSSValue*
michael@0 5444 nsComputedDOMStyle::DoGetAnimationDuration()
michael@0 5445 {
michael@0 5446 const nsStyleDisplay* display = StyleDisplay();
michael@0 5447
michael@0 5448 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5449
michael@0 5450 NS_ABORT_IF_FALSE(display->mAnimationDurationCount > 0,
michael@0 5451 "first item must be explicit");
michael@0 5452 uint32_t i = 0;
michael@0 5453 do {
michael@0 5454 const nsAnimation *animation = &display->mAnimations[i];
michael@0 5455 nsROCSSPrimitiveValue* duration = new nsROCSSPrimitiveValue;
michael@0 5456 valueList->AppendCSSValue(duration);
michael@0 5457
michael@0 5458 duration->SetTime((float)animation->GetDuration() / (float)PR_MSEC_PER_SEC);
michael@0 5459 } while (++i < display->mAnimationDurationCount);
michael@0 5460
michael@0 5461 return valueList;
michael@0 5462 }
michael@0 5463
michael@0 5464 CSSValue*
michael@0 5465 nsComputedDOMStyle::DoGetAnimationTimingFunction()
michael@0 5466 {
michael@0 5467 const nsStyleDisplay* display = StyleDisplay();
michael@0 5468
michael@0 5469 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5470
michael@0 5471 NS_ABORT_IF_FALSE(display->mAnimationTimingFunctionCount > 0,
michael@0 5472 "first item must be explicit");
michael@0 5473 uint32_t i = 0;
michael@0 5474 do {
michael@0 5475 AppendTimingFunction(valueList,
michael@0 5476 display->mAnimations[i].GetTimingFunction());
michael@0 5477 } while (++i < display->mAnimationTimingFunctionCount);
michael@0 5478
michael@0 5479 return valueList;
michael@0 5480 }
michael@0 5481
michael@0 5482 CSSValue*
michael@0 5483 nsComputedDOMStyle::DoGetAnimationDirection()
michael@0 5484 {
michael@0 5485 const nsStyleDisplay* display = StyleDisplay();
michael@0 5486
michael@0 5487 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5488
michael@0 5489 NS_ABORT_IF_FALSE(display->mAnimationDirectionCount > 0,
michael@0 5490 "first item must be explicit");
michael@0 5491 uint32_t i = 0;
michael@0 5492 do {
michael@0 5493 const nsAnimation *animation = &display->mAnimations[i];
michael@0 5494 nsROCSSPrimitiveValue* direction = new nsROCSSPrimitiveValue;
michael@0 5495 valueList->AppendCSSValue(direction);
michael@0 5496 direction->SetIdent(
michael@0 5497 nsCSSProps::ValueToKeywordEnum(animation->GetDirection(),
michael@0 5498 nsCSSProps::kAnimationDirectionKTable));
michael@0 5499 } while (++i < display->mAnimationDirectionCount);
michael@0 5500
michael@0 5501 return valueList;
michael@0 5502 }
michael@0 5503
michael@0 5504 CSSValue*
michael@0 5505 nsComputedDOMStyle::DoGetAnimationFillMode()
michael@0 5506 {
michael@0 5507 const nsStyleDisplay* display = StyleDisplay();
michael@0 5508
michael@0 5509 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5510
michael@0 5511 NS_ABORT_IF_FALSE(display->mAnimationFillModeCount > 0,
michael@0 5512 "first item must be explicit");
michael@0 5513 uint32_t i = 0;
michael@0 5514 do {
michael@0 5515 const nsAnimation *animation = &display->mAnimations[i];
michael@0 5516 nsROCSSPrimitiveValue* fillMode = new nsROCSSPrimitiveValue;
michael@0 5517 valueList->AppendCSSValue(fillMode);
michael@0 5518 fillMode->SetIdent(
michael@0 5519 nsCSSProps::ValueToKeywordEnum(animation->GetFillMode(),
michael@0 5520 nsCSSProps::kAnimationFillModeKTable));
michael@0 5521 } while (++i < display->mAnimationFillModeCount);
michael@0 5522
michael@0 5523 return valueList;
michael@0 5524 }
michael@0 5525
michael@0 5526 CSSValue*
michael@0 5527 nsComputedDOMStyle::DoGetAnimationIterationCount()
michael@0 5528 {
michael@0 5529 const nsStyleDisplay* display = StyleDisplay();
michael@0 5530
michael@0 5531 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5532
michael@0 5533 NS_ABORT_IF_FALSE(display->mAnimationIterationCountCount > 0,
michael@0 5534 "first item must be explicit");
michael@0 5535 uint32_t i = 0;
michael@0 5536 do {
michael@0 5537 const nsAnimation *animation = &display->mAnimations[i];
michael@0 5538 nsROCSSPrimitiveValue* iterationCount = new nsROCSSPrimitiveValue;
michael@0 5539 valueList->AppendCSSValue(iterationCount);
michael@0 5540
michael@0 5541 float f = animation->GetIterationCount();
michael@0 5542 /* Need a nasty hack here to work around an optimizer bug in gcc
michael@0 5543 4.2 on Mac, which somehow gets confused when directly comparing
michael@0 5544 a float to the return value of NS_IEEEPositiveInfinity when
michael@0 5545 building 32-bit builds. */
michael@0 5546 #ifdef XP_MACOSX
michael@0 5547 volatile
michael@0 5548 #endif
michael@0 5549 float inf = NS_IEEEPositiveInfinity();
michael@0 5550 if (f == inf) {
michael@0 5551 iterationCount->SetIdent(eCSSKeyword_infinite);
michael@0 5552 } else {
michael@0 5553 iterationCount->SetNumber(f);
michael@0 5554 }
michael@0 5555 } while (++i < display->mAnimationIterationCountCount);
michael@0 5556
michael@0 5557 return valueList;
michael@0 5558 }
michael@0 5559
michael@0 5560 CSSValue*
michael@0 5561 nsComputedDOMStyle::DoGetAnimationPlayState()
michael@0 5562 {
michael@0 5563 const nsStyleDisplay* display = StyleDisplay();
michael@0 5564
michael@0 5565 nsDOMCSSValueList *valueList = GetROCSSValueList(true);
michael@0 5566
michael@0 5567 NS_ABORT_IF_FALSE(display->mAnimationPlayStateCount > 0,
michael@0 5568 "first item must be explicit");
michael@0 5569 uint32_t i = 0;
michael@0 5570 do {
michael@0 5571 const nsAnimation *animation = &display->mAnimations[i];
michael@0 5572 nsROCSSPrimitiveValue* playState = new nsROCSSPrimitiveValue;
michael@0 5573 valueList->AppendCSSValue(playState);
michael@0 5574 playState->SetIdent(
michael@0 5575 nsCSSProps::ValueToKeywordEnum(animation->GetPlayState(),
michael@0 5576 nsCSSProps::kAnimationPlayStateKTable));
michael@0 5577 } while (++i < display->mAnimationPlayStateCount);
michael@0 5578
michael@0 5579 return valueList;
michael@0 5580 }
michael@0 5581
michael@0 5582 static void
michael@0 5583 MarkComputedStyleMapDirty(const char* aPref, void* aData)
michael@0 5584 {
michael@0 5585 static_cast<nsComputedStyleMap*>(aData)->MarkDirty();
michael@0 5586 }
michael@0 5587
michael@0 5588 CSSValue*
michael@0 5589 nsComputedDOMStyle::DoGetCustomProperty(const nsAString& aPropertyName)
michael@0 5590 {
michael@0 5591 MOZ_ASSERT(nsCSSProps::IsCustomPropertyName(aPropertyName));
michael@0 5592
michael@0 5593 const nsStyleVariables* variables = StyleVariables();
michael@0 5594
michael@0 5595 nsString variableValue;
michael@0 5596 const nsAString& name = Substring(aPropertyName,
michael@0 5597 CSS_CUSTOM_NAME_PREFIX_LENGTH);
michael@0 5598 if (!variables->mVariables.Get(name, variableValue)) {
michael@0 5599 return nullptr;
michael@0 5600 }
michael@0 5601
michael@0 5602 nsROCSSPrimitiveValue* val = new nsROCSSPrimitiveValue;
michael@0 5603 val->SetString(variableValue);
michael@0 5604
michael@0 5605 return val;
michael@0 5606 }
michael@0 5607
michael@0 5608 /* static */ nsComputedStyleMap*
michael@0 5609 nsComputedDOMStyle::GetComputedStyleMap()
michael@0 5610 {
michael@0 5611 static nsComputedStyleMap map = {
michael@0 5612 {
michael@0 5613 #define COMPUTED_STYLE_PROP(prop_, method_) \
michael@0 5614 { eCSSProperty_##prop_, &nsComputedDOMStyle::DoGet##method_ },
michael@0 5615 #include "nsComputedDOMStylePropertyList.h"
michael@0 5616 #undef COMPUTED_STYLE_PROP
michael@0 5617 }
michael@0 5618 };
michael@0 5619 return &map;
michael@0 5620 }
michael@0 5621
michael@0 5622 /* static */ void
michael@0 5623 nsComputedDOMStyle::RegisterPrefChangeCallbacks()
michael@0 5624 {
michael@0 5625 // Note that this will register callbacks for all properties with prefs, not
michael@0 5626 // just those that are implemented on computed style objects, as it's not
michael@0 5627 // easy to grab specific property data from nsCSSPropList.h based on the
michael@0 5628 // entries iterated in nsComputedDOMStylePropertyList.h.
michael@0 5629 nsComputedStyleMap* data = GetComputedStyleMap();
michael@0 5630 #define REGISTER_CALLBACK(pref_) \
michael@0 5631 if (pref_[0]) { \
michael@0 5632 Preferences::RegisterCallback(MarkComputedStyleMapDirty, pref_, data); \
michael@0 5633 }
michael@0 5634 #define CSS_PROP(prop_, id_, method_, flags_, pref_, parsevariant_, \
michael@0 5635 kwtable_, stylestruct_, stylestructoffset_, animtype_) \
michael@0 5636 REGISTER_CALLBACK(pref_)
michael@0 5637 #include "nsCSSPropList.h"
michael@0 5638 #undef CSS_PROP
michael@0 5639 #undef REGISTER_CALLBACK
michael@0 5640 }
michael@0 5641
michael@0 5642 /* static */ void
michael@0 5643 nsComputedDOMStyle::UnregisterPrefChangeCallbacks()
michael@0 5644 {
michael@0 5645 nsComputedStyleMap* data = GetComputedStyleMap();
michael@0 5646 #define UNREGISTER_CALLBACK(pref_) \
michael@0 5647 if (pref_[0]) { \
michael@0 5648 Preferences::UnregisterCallback(MarkComputedStyleMapDirty, pref_, data); \
michael@0 5649 }
michael@0 5650 #define CSS_PROP(prop_, id_, method_, flags_, pref_, parsevariant_, \
michael@0 5651 kwtable_, stylestruct_, stylestructoffset_, animtype_) \
michael@0 5652 UNREGISTER_CALLBACK(pref_)
michael@0 5653 #include "nsCSSPropList.h"
michael@0 5654 #undef CSS_PROP
michael@0 5655 #undef UNREGISTER_CALLBACK
michael@0 5656 }

mercurial