1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/nsRuleNode.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,9247 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=78: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* 1.11 + * a node in the lexicographic tree of rules that match an element, 1.12 + * responsible for converting the rules' information into computed style 1.13 + */ 1.14 + 1.15 +#include <algorithm> 1.16 + 1.17 +#include "mozilla/ArrayUtils.h" 1.18 +#include "mozilla/Assertions.h" 1.19 +#include "mozilla/DebugOnly.h" 1.20 +#include "mozilla/Likely.h" 1.21 +#include "mozilla/LookAndFeel.h" 1.22 + 1.23 +#include "nsRuleNode.h" 1.24 +#include "nscore.h" 1.25 +#include "nsIWidget.h" 1.26 +#include "nsIPresShell.h" 1.27 +#include "nsFontMetrics.h" 1.28 +#include "gfxFont.h" 1.29 +#include "nsCSSPseudoElements.h" 1.30 +#include "nsThemeConstants.h" 1.31 +#include "pldhash.h" 1.32 +#include "nsStyleContext.h" 1.33 +#include "nsStyleSet.h" 1.34 +#include "nsStyleStruct.h" 1.35 +#include "nsSize.h" 1.36 +#include "nsRuleData.h" 1.37 +#include "gfxUserFontSet.h" 1.38 +#include "nsIStyleRule.h" 1.39 +#include "nsBidiUtils.h" 1.40 +#include "nsStyleStructInlines.h" 1.41 +#include "nsCSSProps.h" 1.42 +#include "nsTArray.h" 1.43 +#include "nsContentUtils.h" 1.44 +#include "CSSCalc.h" 1.45 +#include "nsPrintfCString.h" 1.46 +#include "nsRenderingContext.h" 1.47 +#include "nsStyleUtil.h" 1.48 +#include "nsIDocument.h" 1.49 +#include "prtime.h" 1.50 +#include "CSSVariableResolver.h" 1.51 +#include "nsCSSParser.h" 1.52 + 1.53 +#if defined(_MSC_VER) || defined(__MINGW32__) 1.54 +#include <malloc.h> 1.55 +#ifdef _MSC_VER 1.56 +#define alloca _alloca 1.57 +#endif 1.58 +#endif 1.59 +#ifdef SOLARIS 1.60 +#include <alloca.h> 1.61 +#endif 1.62 + 1.63 +using std::max; 1.64 +using std::min; 1.65 +using namespace mozilla; 1.66 +using namespace mozilla::dom; 1.67 + 1.68 +#define NS_SET_IMAGE_REQUEST(method_, context_, request_) \ 1.69 + if ((context_)->PresContext()->IsDynamic()) { \ 1.70 + method_(request_); \ 1.71 + } else { \ 1.72 + nsRefPtr<imgRequestProxy> req = nsContentUtils::GetStaticRequest(request_); \ 1.73 + method_(req); \ 1.74 + } 1.75 + 1.76 +#define NS_SET_IMAGE_REQUEST_WITH_DOC(method_, context_, requestgetter_) \ 1.77 + { \ 1.78 + nsIDocument* doc = (context_)->PresContext()->Document(); \ 1.79 + NS_SET_IMAGE_REQUEST(method_, context_, requestgetter_(doc)) \ 1.80 + } 1.81 + 1.82 +/* 1.83 + * For storage of an |nsRuleNode|'s children in a PLDHashTable. 1.84 + */ 1.85 + 1.86 +struct ChildrenHashEntry : public PLDHashEntryHdr { 1.87 + // key is |mRuleNode->GetKey()| 1.88 + nsRuleNode *mRuleNode; 1.89 +}; 1.90 + 1.91 +/* static */ PLDHashNumber 1.92 +nsRuleNode::ChildrenHashHashKey(PLDHashTable *aTable, const void *aKey) 1.93 +{ 1.94 + const nsRuleNode::Key *key = 1.95 + static_cast<const nsRuleNode::Key*>(aKey); 1.96 + // Disagreement on importance and level for the same rule is extremely 1.97 + // rare, so hash just on the rule. 1.98 + return PL_DHashVoidPtrKeyStub(aTable, key->mRule); 1.99 +} 1.100 + 1.101 +/* static */ bool 1.102 +nsRuleNode::ChildrenHashMatchEntry(PLDHashTable *aTable, 1.103 + const PLDHashEntryHdr *aHdr, 1.104 + const void *aKey) 1.105 +{ 1.106 + const ChildrenHashEntry *entry = 1.107 + static_cast<const ChildrenHashEntry*>(aHdr); 1.108 + const nsRuleNode::Key *key = 1.109 + static_cast<const nsRuleNode::Key*>(aKey); 1.110 + return entry->mRuleNode->GetKey() == *key; 1.111 +} 1.112 + 1.113 +/* static */ const PLDHashTableOps 1.114 +nsRuleNode::ChildrenHashOps = { 1.115 + // It's probably better to allocate the table itself using malloc and 1.116 + // free rather than the pres shell's arena because the table doesn't 1.117 + // grow very often and the pres shell's arena doesn't recycle very 1.118 + // large size allocations. 1.119 + PL_DHashAllocTable, 1.120 + PL_DHashFreeTable, 1.121 + ChildrenHashHashKey, 1.122 + ChildrenHashMatchEntry, 1.123 + PL_DHashMoveEntryStub, 1.124 + PL_DHashClearEntryStub, 1.125 + PL_DHashFinalizeStub, 1.126 + nullptr 1.127 +}; 1.128 + 1.129 + 1.130 +// EnsureBlockDisplay: 1.131 +// - if the display value (argument) is not a block-type 1.132 +// then we set it to a valid block display value 1.133 +// - For enforcing the floated/positioned element CSS2 rules 1.134 +// - We allow the behavior of "list-item" to be customized. 1.135 +// CSS21 says that position/float do not convert 'list-item' to 'block', 1.136 +// but it explicitly does not define whether 'list-item' should be 1.137 +// converted to block *on the root node*. To allow for flexibility 1.138 +// (so that we don't have to support a list-item root node), this method 1.139 +// lets the caller pick either behavior, using the 'aConvertListItem' arg. 1.140 +// Reference: http://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo 1.141 +/* static */ 1.142 +void 1.143 +nsRuleNode::EnsureBlockDisplay(uint8_t& display, 1.144 + bool aConvertListItem /* = false */) 1.145 +{ 1.146 + // see if the display value is already a block 1.147 + switch (display) { 1.148 + case NS_STYLE_DISPLAY_LIST_ITEM : 1.149 + if (aConvertListItem) { 1.150 + display = NS_STYLE_DISPLAY_BLOCK; 1.151 + break; 1.152 + } // else, fall through to share the 'break' for non-changing display vals 1.153 + case NS_STYLE_DISPLAY_NONE : 1.154 + // never change display:none *ever* 1.155 + case NS_STYLE_DISPLAY_TABLE : 1.156 + case NS_STYLE_DISPLAY_BLOCK : 1.157 + case NS_STYLE_DISPLAY_FLEX : 1.158 + case NS_STYLE_DISPLAY_GRID : 1.159 + // do not muck with these at all - already blocks 1.160 + // This is equivalent to nsStyleDisplay::IsBlockOutside. (XXX Maybe we 1.161 + // should just call that?) 1.162 + // This needs to match the check done in 1.163 + // nsCSSFrameConstructor::FindMathMLData for <math>. 1.164 + break; 1.165 + 1.166 + case NS_STYLE_DISPLAY_INLINE_TABLE : 1.167 + // make inline tables into tables 1.168 + display = NS_STYLE_DISPLAY_TABLE; 1.169 + break; 1.170 + 1.171 + case NS_STYLE_DISPLAY_INLINE_FLEX: 1.172 + // make inline flex containers into flex containers 1.173 + display = NS_STYLE_DISPLAY_FLEX; 1.174 + break; 1.175 + 1.176 + case NS_STYLE_DISPLAY_INLINE_GRID: 1.177 + // make inline grid containers into grid containers 1.178 + display = NS_STYLE_DISPLAY_GRID; 1.179 + break; 1.180 + 1.181 + default : 1.182 + // make it a block 1.183 + display = NS_STYLE_DISPLAY_BLOCK; 1.184 + } 1.185 +} 1.186 + 1.187 +static nscoord CalcLengthWith(const nsCSSValue& aValue, 1.188 + nscoord aFontSize, 1.189 + const nsStyleFont* aStyleFont, 1.190 + nsStyleContext* aStyleContext, 1.191 + nsPresContext* aPresContext, 1.192 + bool aUseProvidedRootEmSize, 1.193 + bool aUseUserFontSet, 1.194 + bool& aCanStoreInRuleTree); 1.195 + 1.196 +struct CalcLengthCalcOps : public css::BasicCoordCalcOps, 1.197 + public css::NumbersAlreadyNormalizedOps 1.198 +{ 1.199 + // All of the parameters to CalcLengthWith except aValue. 1.200 + const nscoord mFontSize; 1.201 + const nsStyleFont* const mStyleFont; 1.202 + nsStyleContext* const mStyleContext; 1.203 + nsPresContext* const mPresContext; 1.204 + const bool mUseProvidedRootEmSize; 1.205 + const bool mUseUserFontSet; 1.206 + bool& mCanStoreInRuleTree; 1.207 + 1.208 + CalcLengthCalcOps(nscoord aFontSize, const nsStyleFont* aStyleFont, 1.209 + nsStyleContext* aStyleContext, nsPresContext* aPresContext, 1.210 + bool aUseProvidedRootEmSize, bool aUseUserFontSet, 1.211 + bool& aCanStoreInRuleTree) 1.212 + : mFontSize(aFontSize), 1.213 + mStyleFont(aStyleFont), 1.214 + mStyleContext(aStyleContext), 1.215 + mPresContext(aPresContext), 1.216 + mUseProvidedRootEmSize(aUseProvidedRootEmSize), 1.217 + mUseUserFontSet(aUseUserFontSet), 1.218 + mCanStoreInRuleTree(aCanStoreInRuleTree) 1.219 + { 1.220 + } 1.221 + 1.222 + result_type ComputeLeafValue(const nsCSSValue& aValue) 1.223 + { 1.224 + return CalcLengthWith(aValue, mFontSize, mStyleFont, 1.225 + mStyleContext, mPresContext, mUseProvidedRootEmSize, 1.226 + mUseUserFontSet, mCanStoreInRuleTree); 1.227 + } 1.228 +}; 1.229 + 1.230 +static inline nscoord ScaleCoord(const nsCSSValue &aValue, float factor) 1.231 +{ 1.232 + return NSToCoordRoundWithClamp(aValue.GetFloatValue() * factor); 1.233 +} 1.234 + 1.235 +already_AddRefed<nsFontMetrics> 1.236 +GetMetricsFor(nsPresContext* aPresContext, 1.237 + nsStyleContext* aStyleContext, 1.238 + const nsStyleFont* aStyleFont, 1.239 + nscoord aFontSize, // overrides value from aStyleFont 1.240 + bool aUseUserFontSet) 1.241 +{ 1.242 + nsFont font = aStyleFont->mFont; 1.243 + font.size = aFontSize; 1.244 + gfxUserFontSet *fs = nullptr; 1.245 + if (aUseUserFontSet) { 1.246 + fs = aPresContext->GetUserFontSet(); 1.247 + } 1.248 + gfxTextPerfMetrics *tp = aPresContext->GetTextPerfMetrics(); 1.249 + nsRefPtr<nsFontMetrics> fm; 1.250 + aPresContext->DeviceContext()->GetMetricsFor(font, 1.251 + aStyleFont->mLanguage, 1.252 + fs, tp, *getter_AddRefs(fm)); 1.253 + return fm.forget(); 1.254 +} 1.255 + 1.256 + 1.257 +static nsSize CalcViewportUnitsScale(nsPresContext* aPresContext) 1.258 +{ 1.259 + // The caller is making use of viewport units, so notify the pres context 1.260 + // that it will need to rebuild the rule tree if the size of the viewport 1.261 + // changes. 1.262 + aPresContext->SetUsesViewportUnits(true); 1.263 + 1.264 + // The default (when we have 'overflow: auto' on the root element, or 1.265 + // trivially for 'overflow: hidden' since we never have scrollbars in that 1.266 + // case) is to define the scale of the viewport units without considering 1.267 + // scrollbars. 1.268 + nsSize viewportSize(aPresContext->GetVisibleArea().Size()); 1.269 + 1.270 + // Check for 'overflow: scroll' styles on the root scroll frame. If we find 1.271 + // any, the standard requires us to take scrollbars into account. 1.272 + nsIScrollableFrame* scrollFrame = 1.273 + aPresContext->PresShell()->GetRootScrollFrameAsScrollable(); 1.274 + if (scrollFrame) { 1.275 + ScrollbarStyles styles(scrollFrame->GetScrollbarStyles()); 1.276 + 1.277 + if (styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL || 1.278 + styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) { 1.279 + // Gather scrollbar size information. 1.280 + nsRefPtr<nsRenderingContext> context = 1.281 + aPresContext->PresShell()->CreateReferenceRenderingContext(); 1.282 + nsMargin sizes(scrollFrame->GetDesiredScrollbarSizes(aPresContext, context)); 1.283 + 1.284 + if (styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL) { 1.285 + // 'overflow-x: scroll' means we must consider the horizontal scrollbar, 1.286 + // which affects the scale of viewport height units. 1.287 + viewportSize.height -= sizes.TopBottom(); 1.288 + } 1.289 + 1.290 + if (styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) { 1.291 + // 'overflow-y: scroll' means we must consider the vertical scrollbar, 1.292 + // which affects the scale of viewport width units. 1.293 + viewportSize.width -= sizes.LeftRight(); 1.294 + } 1.295 + } 1.296 + } 1.297 + 1.298 + return viewportSize; 1.299 +} 1.300 + 1.301 +static nscoord CalcLengthWith(const nsCSSValue& aValue, 1.302 + nscoord aFontSize, 1.303 + const nsStyleFont* aStyleFont, 1.304 + nsStyleContext* aStyleContext, 1.305 + nsPresContext* aPresContext, 1.306 + bool aUseProvidedRootEmSize, 1.307 + // aUseUserFontSet should always be true 1.308 + // except when called from 1.309 + // CalcLengthWithInitialFont. 1.310 + bool aUseUserFontSet, 1.311 + bool& aCanStoreInRuleTree) 1.312 +{ 1.313 + NS_ASSERTION(aValue.IsLengthUnit() || aValue.IsCalcUnit(), 1.314 + "not a length or calc unit"); 1.315 + NS_ASSERTION(aStyleFont || aStyleContext, 1.316 + "Must have style data"); 1.317 + NS_ASSERTION(!aStyleFont || !aStyleContext, 1.318 + "Duplicate sources of data"); 1.319 + NS_ASSERTION(aPresContext, "Must have prescontext"); 1.320 + 1.321 + if (aValue.IsFixedLengthUnit()) { 1.322 + return aValue.GetFixedLength(aPresContext); 1.323 + } 1.324 + if (aValue.IsPixelLengthUnit()) { 1.325 + return aValue.GetPixelLength(); 1.326 + } 1.327 + if (aValue.IsCalcUnit()) { 1.328 + // For properties for which lengths are the *only* units accepted in 1.329 + // calc(), we can handle calc() here and just compute a final 1.330 + // result. We ensure that we don't get to this code for other 1.331 + // properties by not calling CalcLength in those cases: SetCoord 1.332 + // only calls CalcLength for a calc when it is appropriate to do so. 1.333 + CalcLengthCalcOps ops(aFontSize, aStyleFont, 1.334 + aStyleContext, aPresContext, 1.335 + aUseProvidedRootEmSize, aUseUserFontSet, 1.336 + aCanStoreInRuleTree); 1.337 + return css::ComputeCalc(aValue, ops); 1.338 + } 1.339 + switch (aValue.GetUnit()) { 1.340 + // nsPresContext::SetVisibleArea and 1.341 + // nsPresContext::MediaFeatureValuesChanged handle dynamic changes 1.342 + // of the basis for viewport units by rebuilding the rule tree and 1.343 + // style context tree. Not caching them in the rule tree wouldn't 1.344 + // be sufficient to handle these changes because we also need a way 1.345 + // to get rid of cached values in the style context tree without any 1.346 + // changes in specified style. We can either do this by not caching 1.347 + // in the rule tree and then throwing away the style context tree 1.348 + // for dynamic viewport size changes, or by allowing caching in the 1.349 + // rule tree and using the existing rebuild style data path that 1.350 + // throws away the style context and the rule tree. 1.351 + // Thus we do cache viewport units in the rule tree. This allows us 1.352 + // to benefit from the performance advantages of the rule tree 1.353 + // (e.g., faster dynamic changes on other things, like transforms) 1.354 + // and allows us not to need an additional code path, in exchange 1.355 + // for an increased cost to dynamic changes to the viewport size 1.356 + // when viewport units are in use. 1.357 + case eCSSUnit_ViewportWidth: { 1.358 + return ScaleCoord(aValue, 0.01f * CalcViewportUnitsScale(aPresContext).width); 1.359 + } 1.360 + case eCSSUnit_ViewportHeight: { 1.361 + return ScaleCoord(aValue, 0.01f * CalcViewportUnitsScale(aPresContext).height); 1.362 + } 1.363 + case eCSSUnit_ViewportMin: { 1.364 + nsSize vuScale(CalcViewportUnitsScale(aPresContext)); 1.365 + return ScaleCoord(aValue, 0.01f * min(vuScale.width, vuScale.height)); 1.366 + } 1.367 + case eCSSUnit_ViewportMax: { 1.368 + nsSize vuScale(CalcViewportUnitsScale(aPresContext)); 1.369 + return ScaleCoord(aValue, 0.01f * max(vuScale.width, vuScale.height)); 1.370 + } 1.371 + // While we could deal with 'rem' units correctly by simply not 1.372 + // caching any data that uses them in the rule tree, it's valuable 1.373 + // to store them in the rule tree (for faster dynamic changes of 1.374 + // other things). And since the font size of the root element 1.375 + // changes rarely, we instead handle dynamic changes to the root 1.376 + // element's font size by rebuilding all style data in 1.377 + // nsCSSFrameConstructor::RestyleElement. 1.378 + case eCSSUnit_RootEM: { 1.379 + aPresContext->SetUsesRootEMUnits(true); 1.380 + nscoord rootFontSize; 1.381 + 1.382 + // NOTE: Be very careful with |styleFont|, since we haven't set 1.383 + // aCanStoreInRuleTree to false yet, so we don't want to introduce 1.384 + // any dependencies on aStyleContext's data here. 1.385 + const nsStyleFont *styleFont = 1.386 + aStyleFont ? aStyleFont : aStyleContext->StyleFont(); 1.387 + 1.388 + if (aUseProvidedRootEmSize) { 1.389 + // We should use the provided aFontSize as the reference length to 1.390 + // scale. This only happens when we are calculating font-size or 1.391 + // an equivalent (scriptminsize or CalcLengthWithInitialFont) on 1.392 + // the root element, in which case aFontSize is already the 1.393 + // value we want. 1.394 + if (aFontSize == -1) { 1.395 + // XXX Should this be styleFont->mSize instead to avoid taking 1.396 + // minfontsize prefs into account? 1.397 + aFontSize = styleFont->mFont.size; 1.398 + } 1.399 + rootFontSize = aFontSize; 1.400 + } else if (aStyleContext && !aStyleContext->GetParent()) { 1.401 + // This is the root element (XXX we don't really know this, but 1.402 + // nsRuleNode::SetFont makes the same assumption!), so we should 1.403 + // use StyleFont on this context to get the root element's 1.404 + // font size. 1.405 + rootFontSize = styleFont->mFont.size; 1.406 + } else { 1.407 + // This is not the root element or we are calculating something other 1.408 + // than font size, so rem is relative to the root element's font size. 1.409 + nsRefPtr<nsStyleContext> rootStyle; 1.410 + const nsStyleFont *rootStyleFont = styleFont; 1.411 + Element* docElement = aPresContext->Document()->GetRootElement(); 1.412 + 1.413 + if (docElement) { 1.414 + rootStyle = aPresContext->StyleSet()->ResolveStyleFor(docElement, 1.415 + nullptr); 1.416 + rootStyleFont = rootStyle->StyleFont(); 1.417 + } 1.418 + 1.419 + rootFontSize = rootStyleFont->mFont.size; 1.420 + } 1.421 + 1.422 + return ScaleCoord(aValue, float(rootFontSize)); 1.423 + } 1.424 + default: 1.425 + // Fall through to the code for units that can't be stored in the 1.426 + // rule tree because they depend on font data. 1.427 + break; 1.428 + } 1.429 + // Common code for units that depend on the element's font data and 1.430 + // thus can't be stored in the rule tree: 1.431 + aCanStoreInRuleTree = false; 1.432 + const nsStyleFont *styleFont = 1.433 + aStyleFont ? aStyleFont : aStyleContext->StyleFont(); 1.434 + if (aFontSize == -1) { 1.435 + // XXX Should this be styleFont->mSize instead to avoid taking minfontsize 1.436 + // prefs into account? 1.437 + aFontSize = styleFont->mFont.size; 1.438 + } 1.439 + switch (aValue.GetUnit()) { 1.440 + case eCSSUnit_EM: { 1.441 + // CSS2.1 specifies that this unit scales to the computed font 1.442 + // size, not the em-width in the font metrics, despite the name. 1.443 + return ScaleCoord(aValue, float(aFontSize)); 1.444 + } 1.445 + case eCSSUnit_XHeight: { 1.446 + nsRefPtr<nsFontMetrics> fm = 1.447 + GetMetricsFor(aPresContext, aStyleContext, styleFont, 1.448 + aFontSize, aUseUserFontSet); 1.449 + return ScaleCoord(aValue, float(fm->XHeight())); 1.450 + } 1.451 + case eCSSUnit_Char: { 1.452 + nsRefPtr<nsFontMetrics> fm = 1.453 + GetMetricsFor(aPresContext, aStyleContext, styleFont, 1.454 + aFontSize, aUseUserFontSet); 1.455 + gfxFloat zeroWidth = (fm->GetThebesFontGroup()->GetFontAt(0) 1.456 + ->GetMetrics().zeroOrAveCharWidth); 1.457 + 1.458 + return ScaleCoord(aValue, ceil(aPresContext->AppUnitsPerDevPixel() * 1.459 + zeroWidth)); 1.460 + } 1.461 + default: 1.462 + NS_NOTREACHED("unexpected unit"); 1.463 + break; 1.464 + } 1.465 + return 0; 1.466 +} 1.467 + 1.468 +/* static */ nscoord 1.469 +nsRuleNode::CalcLength(const nsCSSValue& aValue, 1.470 + nsStyleContext* aStyleContext, 1.471 + nsPresContext* aPresContext, 1.472 + bool& aCanStoreInRuleTree) 1.473 +{ 1.474 + NS_ASSERTION(aStyleContext, "Must have style data"); 1.475 + 1.476 + return CalcLengthWith(aValue, -1, nullptr, 1.477 + aStyleContext, aPresContext, 1.478 + false, true, aCanStoreInRuleTree); 1.479 +} 1.480 + 1.481 +/* Inline helper function to redirect requests to CalcLength. */ 1.482 +static inline nscoord CalcLength(const nsCSSValue& aValue, 1.483 + nsStyleContext* aStyleContext, 1.484 + nsPresContext* aPresContext, 1.485 + bool& aCanStoreInRuleTree) 1.486 +{ 1.487 + return nsRuleNode::CalcLength(aValue, aStyleContext, 1.488 + aPresContext, aCanStoreInRuleTree); 1.489 +} 1.490 + 1.491 +/* static */ nscoord 1.492 +nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext, 1.493 + const nsCSSValue& aValue) 1.494 +{ 1.495 + nsStyleFont defaultFont(aPresContext); // FIXME: best language? 1.496 + bool canStoreInRuleTree; 1.497 + return CalcLengthWith(aValue, -1, &defaultFont, 1.498 + nullptr, aPresContext, 1.499 + true, false, canStoreInRuleTree); 1.500 +} 1.501 + 1.502 +struct LengthPercentPairCalcOps : public css::NumbersAlreadyNormalizedOps 1.503 +{ 1.504 + typedef nsRuleNode::ComputedCalc result_type; 1.505 + 1.506 + LengthPercentPairCalcOps(nsStyleContext* aContext, 1.507 + nsPresContext* aPresContext, 1.508 + bool& aCanStoreInRuleTree) 1.509 + : mContext(aContext), 1.510 + mPresContext(aPresContext), 1.511 + mCanStoreInRuleTree(aCanStoreInRuleTree), 1.512 + mHasPercent(false) {} 1.513 + 1.514 + nsStyleContext* mContext; 1.515 + nsPresContext* mPresContext; 1.516 + bool& mCanStoreInRuleTree; 1.517 + bool mHasPercent; 1.518 + 1.519 + result_type ComputeLeafValue(const nsCSSValue& aValue) 1.520 + { 1.521 + if (aValue.GetUnit() == eCSSUnit_Percent) { 1.522 + mHasPercent = true; 1.523 + return result_type(0, aValue.GetPercentValue()); 1.524 + } 1.525 + return result_type(CalcLength(aValue, mContext, mPresContext, 1.526 + mCanStoreInRuleTree), 1.527 + 0.0f); 1.528 + } 1.529 + 1.530 + result_type 1.531 + MergeAdditive(nsCSSUnit aCalcFunction, 1.532 + result_type aValue1, result_type aValue2) 1.533 + { 1.534 + if (aCalcFunction == eCSSUnit_Calc_Plus) { 1.535 + return result_type(NSCoordSaturatingAdd(aValue1.mLength, 1.536 + aValue2.mLength), 1.537 + aValue1.mPercent + aValue2.mPercent); 1.538 + } 1.539 + NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Minus, 1.540 + "min() and max() are not allowed in calc() on " 1.541 + "transform"); 1.542 + return result_type(NSCoordSaturatingSubtract(aValue1.mLength, 1.543 + aValue2.mLength, 0), 1.544 + aValue1.mPercent - aValue2.mPercent); 1.545 + } 1.546 + 1.547 + result_type 1.548 + MergeMultiplicativeL(nsCSSUnit aCalcFunction, 1.549 + float aValue1, result_type aValue2) 1.550 + { 1.551 + NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Times_L, 1.552 + "unexpected unit"); 1.553 + return result_type(NSCoordSaturatingMultiply(aValue2.mLength, aValue1), 1.554 + aValue1 * aValue2.mPercent); 1.555 + } 1.556 + 1.557 + result_type 1.558 + MergeMultiplicativeR(nsCSSUnit aCalcFunction, 1.559 + result_type aValue1, float aValue2) 1.560 + { 1.561 + NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Times_R || 1.562 + aCalcFunction == eCSSUnit_Calc_Divided, 1.563 + "unexpected unit"); 1.564 + if (aCalcFunction == eCSSUnit_Calc_Divided) { 1.565 + aValue2 = 1.0f / aValue2; 1.566 + } 1.567 + return result_type(NSCoordSaturatingMultiply(aValue1.mLength, aValue2), 1.568 + aValue1.mPercent * aValue2); 1.569 + } 1.570 + 1.571 +}; 1.572 + 1.573 +static void 1.574 +SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord, 1.575 + nsStyleContext* aStyleContext, 1.576 + bool& aCanStoreInRuleTree) 1.577 +{ 1.578 + LengthPercentPairCalcOps ops(aStyleContext, aStyleContext->PresContext(), 1.579 + aCanStoreInRuleTree); 1.580 + nsRuleNode::ComputedCalc vals = ComputeCalc(aValue, ops); 1.581 + 1.582 + nsStyleCoord::Calc *calcObj = 1.583 + new (aStyleContext->Alloc(sizeof(nsStyleCoord::Calc))) nsStyleCoord::Calc; 1.584 + // Because we use aStyleContext->Alloc(), we have to store the result 1.585 + // on the style context and not in the rule tree. 1.586 + aCanStoreInRuleTree = false; 1.587 + 1.588 + calcObj->mLength = vals.mLength; 1.589 + calcObj->mPercent = vals.mPercent; 1.590 + calcObj->mHasPercent = ops.mHasPercent; 1.591 + 1.592 + aCoord.SetCalcValue(calcObj); 1.593 +} 1.594 + 1.595 +/* static */ nsRuleNode::ComputedCalc 1.596 +nsRuleNode::SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, 1.597 + nsStyleContext* aStyleContext, 1.598 + nsPresContext* aPresContext, 1.599 + bool& aCanStoreInRuleTree) 1.600 +{ 1.601 + LengthPercentPairCalcOps ops(aStyleContext, aPresContext, 1.602 + aCanStoreInRuleTree); 1.603 + return ComputeCalc(aValue, ops); 1.604 +} 1.605 + 1.606 +// This is our public API for handling calc() expressions that involve 1.607 +// percentages. 1.608 +/* static */ nscoord 1.609 +nsRuleNode::ComputeComputedCalc(const nsStyleCoord& aValue, 1.610 + nscoord aPercentageBasis) 1.611 +{ 1.612 + nsStyleCoord::Calc *calc = aValue.GetCalcValue(); 1.613 + return calc->mLength + 1.614 + NSToCoordFloorClamped(aPercentageBasis * calc->mPercent); 1.615 +} 1.616 + 1.617 +/* static */ nscoord 1.618 +nsRuleNode::ComputeCoordPercentCalc(const nsStyleCoord& aCoord, 1.619 + nscoord aPercentageBasis) 1.620 +{ 1.621 + switch (aCoord.GetUnit()) { 1.622 + case eStyleUnit_Coord: 1.623 + return aCoord.GetCoordValue(); 1.624 + case eStyleUnit_Percent: 1.625 + return NSToCoordFloorClamped(aPercentageBasis * aCoord.GetPercentValue()); 1.626 + case eStyleUnit_Calc: 1.627 + return ComputeComputedCalc(aCoord, aPercentageBasis); 1.628 + default: 1.629 + NS_ABORT_IF_FALSE(false, "unexpected unit"); 1.630 + return 0; 1.631 + } 1.632 +} 1.633 + 1.634 +/* Given an enumerated value that represents a box position, converts it to 1.635 + * a float representing the percentage of the box it corresponds to. For 1.636 + * example, "center" becomes 0.5f. 1.637 + * 1.638 + * @param aEnumValue The enumerated value. 1.639 + * @return The float percent it corresponds to. 1.640 + */ 1.641 +static float 1.642 +GetFloatFromBoxPosition(int32_t aEnumValue) 1.643 +{ 1.644 + switch (aEnumValue) { 1.645 + case NS_STYLE_BG_POSITION_LEFT: 1.646 + case NS_STYLE_BG_POSITION_TOP: 1.647 + return 0.0f; 1.648 + case NS_STYLE_BG_POSITION_RIGHT: 1.649 + case NS_STYLE_BG_POSITION_BOTTOM: 1.650 + return 1.0f; 1.651 + default: 1.652 + NS_NOTREACHED("unexpected value"); 1.653 + // fall through 1.654 + case NS_STYLE_BG_POSITION_CENTER: 1.655 + return 0.5f; 1.656 + } 1.657 +} 1.658 + 1.659 +#define SETCOORD_NORMAL 0x01 // N 1.660 +#define SETCOORD_AUTO 0x02 // A 1.661 +#define SETCOORD_INHERIT 0x04 // H 1.662 +#define SETCOORD_PERCENT 0x08 // P 1.663 +#define SETCOORD_FACTOR 0x10 // F 1.664 +#define SETCOORD_LENGTH 0x20 // L 1.665 +#define SETCOORD_INTEGER 0x40 // I 1.666 +#define SETCOORD_ENUMERATED 0x80 // E 1.667 +#define SETCOORD_NONE 0x100 // O 1.668 +#define SETCOORD_INITIAL_ZERO 0x200 1.669 +#define SETCOORD_INITIAL_AUTO 0x400 1.670 +#define SETCOORD_INITIAL_NONE 0x800 1.671 +#define SETCOORD_INITIAL_NORMAL 0x1000 1.672 +#define SETCOORD_INITIAL_HALF 0x2000 1.673 +#define SETCOORD_INITIAL_HUNDRED_PCT 0x00004000 1.674 +#define SETCOORD_INITIAL_FACTOR_ONE 0x00008000 1.675 +#define SETCOORD_INITIAL_FACTOR_ZERO 0x00010000 1.676 +#define SETCOORD_CALC_LENGTH_ONLY 0x00020000 1.677 +#define SETCOORD_CALC_CLAMP_NONNEGATIVE 0x00040000 // modifier for CALC_LENGTH_ONLY 1.678 +#define SETCOORD_STORE_CALC 0x00080000 1.679 +#define SETCOORD_BOX_POSITION 0x00100000 // exclusive with _ENUMERATED 1.680 +#define SETCOORD_ANGLE 0x00200000 1.681 +#define SETCOORD_UNSET_INHERIT 0x00400000 1.682 +#define SETCOORD_UNSET_INITIAL 0x00800000 1.683 + 1.684 +#define SETCOORD_LP (SETCOORD_LENGTH | SETCOORD_PERCENT) 1.685 +#define SETCOORD_LH (SETCOORD_LENGTH | SETCOORD_INHERIT) 1.686 +#define SETCOORD_AH (SETCOORD_AUTO | SETCOORD_INHERIT) 1.687 +#define SETCOORD_LAH (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT) 1.688 +#define SETCOORD_LPH (SETCOORD_LP | SETCOORD_INHERIT) 1.689 +#define SETCOORD_LPAH (SETCOORD_LP | SETCOORD_AH) 1.690 +#define SETCOORD_LPE (SETCOORD_LP | SETCOORD_ENUMERATED) 1.691 +#define SETCOORD_LPEH (SETCOORD_LPE | SETCOORD_INHERIT) 1.692 +#define SETCOORD_LPAEH (SETCOORD_LPAH | SETCOORD_ENUMERATED) 1.693 +#define SETCOORD_LPO (SETCOORD_LP | SETCOORD_NONE) 1.694 +#define SETCOORD_LPOH (SETCOORD_LPH | SETCOORD_NONE) 1.695 +#define SETCOORD_LPOEH (SETCOORD_LPOH | SETCOORD_ENUMERATED) 1.696 +#define SETCOORD_LE (SETCOORD_LENGTH | SETCOORD_ENUMERATED) 1.697 +#define SETCOORD_LEH (SETCOORD_LE | SETCOORD_INHERIT) 1.698 +#define SETCOORD_IA (SETCOORD_INTEGER | SETCOORD_AUTO) 1.699 +#define SETCOORD_LAE (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED) 1.700 + 1.701 +// changes aCoord iff it returns true 1.702 +static bool SetCoord(const nsCSSValue& aValue, nsStyleCoord& aCoord, 1.703 + const nsStyleCoord& aParentCoord, 1.704 + int32_t aMask, nsStyleContext* aStyleContext, 1.705 + nsPresContext* aPresContext, 1.706 + bool& aCanStoreInRuleTree) 1.707 +{ 1.708 + bool result = true; 1.709 + if (aValue.GetUnit() == eCSSUnit_Null) { 1.710 + result = false; 1.711 + } 1.712 + else if ((((aMask & SETCOORD_LENGTH) != 0) && 1.713 + aValue.IsLengthUnit()) || 1.714 + (((aMask & SETCOORD_CALC_LENGTH_ONLY) != 0) && 1.715 + aValue.IsCalcUnit())) { 1.716 + nscoord len = CalcLength(aValue, aStyleContext, aPresContext, 1.717 + aCanStoreInRuleTree); 1.718 + if ((aMask & SETCOORD_CALC_CLAMP_NONNEGATIVE) && len < 0) { 1.719 + NS_ASSERTION(aValue.IsCalcUnit(), 1.720 + "parser should have ensured no nonnegative lengths"); 1.721 + len = 0; 1.722 + } 1.723 + aCoord.SetCoordValue(len); 1.724 + } 1.725 + else if (((aMask & SETCOORD_PERCENT) != 0) && 1.726 + (aValue.GetUnit() == eCSSUnit_Percent)) { 1.727 + aCoord.SetPercentValue(aValue.GetPercentValue()); 1.728 + } 1.729 + else if (((aMask & SETCOORD_INTEGER) != 0) && 1.730 + (aValue.GetUnit() == eCSSUnit_Integer)) { 1.731 + aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Integer); 1.732 + } 1.733 + else if (((aMask & SETCOORD_ENUMERATED) != 0) && 1.734 + (aValue.GetUnit() == eCSSUnit_Enumerated)) { 1.735 + aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Enumerated); 1.736 + } 1.737 + else if (((aMask & SETCOORD_BOX_POSITION) != 0) && 1.738 + (aValue.GetUnit() == eCSSUnit_Enumerated)) { 1.739 + aCoord.SetPercentValue(GetFloatFromBoxPosition(aValue.GetIntValue())); 1.740 + } 1.741 + else if (((aMask & SETCOORD_AUTO) != 0) && 1.742 + (aValue.GetUnit() == eCSSUnit_Auto)) { 1.743 + aCoord.SetAutoValue(); 1.744 + } 1.745 + else if ((((aMask & SETCOORD_INHERIT) != 0) && 1.746 + aValue.GetUnit() == eCSSUnit_Inherit) || 1.747 + (((aMask & SETCOORD_UNSET_INHERIT) != 0) && 1.748 + aValue.GetUnit() == eCSSUnit_Unset)) { 1.749 + aCoord = aParentCoord; // just inherit value from parent 1.750 + aCanStoreInRuleTree = false; 1.751 + } 1.752 + else if (((aMask & SETCOORD_NORMAL) != 0) && 1.753 + (aValue.GetUnit() == eCSSUnit_Normal)) { 1.754 + aCoord.SetNormalValue(); 1.755 + } 1.756 + else if (((aMask & SETCOORD_NONE) != 0) && 1.757 + (aValue.GetUnit() == eCSSUnit_None)) { 1.758 + aCoord.SetNoneValue(); 1.759 + } 1.760 + else if (((aMask & SETCOORD_FACTOR) != 0) && 1.761 + (aValue.GetUnit() == eCSSUnit_Number)) { 1.762 + aCoord.SetFactorValue(aValue.GetFloatValue()); 1.763 + } 1.764 + else if (((aMask & SETCOORD_STORE_CALC) != 0) && 1.765 + (aValue.IsCalcUnit())) { 1.766 + SpecifiedCalcToComputedCalc(aValue, aCoord, aStyleContext, 1.767 + aCanStoreInRuleTree); 1.768 + } 1.769 + else if (aValue.GetUnit() == eCSSUnit_Initial || 1.770 + (aValue.GetUnit() == eCSSUnit_Unset && 1.771 + ((aMask & SETCOORD_UNSET_INITIAL) != 0))) { 1.772 + if ((aMask & SETCOORD_INITIAL_AUTO) != 0) { 1.773 + aCoord.SetAutoValue(); 1.774 + } 1.775 + else if ((aMask & SETCOORD_INITIAL_ZERO) != 0) { 1.776 + aCoord.SetCoordValue(0); 1.777 + } 1.778 + else if ((aMask & SETCOORD_INITIAL_FACTOR_ZERO) != 0) { 1.779 + aCoord.SetFactorValue(0.0f); 1.780 + } 1.781 + else if ((aMask & SETCOORD_INITIAL_NONE) != 0) { 1.782 + aCoord.SetNoneValue(); 1.783 + } 1.784 + else if ((aMask & SETCOORD_INITIAL_NORMAL) != 0) { 1.785 + aCoord.SetNormalValue(); 1.786 + } 1.787 + else if ((aMask & SETCOORD_INITIAL_HALF) != 0) { 1.788 + aCoord.SetPercentValue(0.5f); 1.789 + } 1.790 + else if ((aMask & SETCOORD_INITIAL_HUNDRED_PCT) != 0) { 1.791 + aCoord.SetPercentValue(1.0f); 1.792 + } 1.793 + else if ((aMask & SETCOORD_INITIAL_FACTOR_ONE) != 0) { 1.794 + aCoord.SetFactorValue(1.0f); 1.795 + } 1.796 + else { 1.797 + result = false; // didn't set anything 1.798 + } 1.799 + } 1.800 + else if ((aMask & SETCOORD_ANGLE) != 0 && 1.801 + (aValue.IsAngularUnit())) { 1.802 + nsStyleUnit unit; 1.803 + switch (aValue.GetUnit()) { 1.804 + case eCSSUnit_Degree: unit = eStyleUnit_Degree; break; 1.805 + case eCSSUnit_Grad: unit = eStyleUnit_Grad; break; 1.806 + case eCSSUnit_Radian: unit = eStyleUnit_Radian; break; 1.807 + case eCSSUnit_Turn: unit = eStyleUnit_Turn; break; 1.808 + default: NS_NOTREACHED("unrecognized angular unit"); 1.809 + unit = eStyleUnit_Degree; 1.810 + } 1.811 + aCoord.SetAngleValue(aValue.GetAngleValue(), unit); 1.812 + } 1.813 + else { 1.814 + result = false; // didn't set anything 1.815 + } 1.816 + return result; 1.817 +} 1.818 + 1.819 +// This inline function offers a shortcut for SetCoord() by refusing to accept 1.820 +// SETCOORD_LENGTH, SETCOORD_INHERIT and SETCOORD_UNSET_* masks. 1.821 +static inline bool SetAbsCoord(const nsCSSValue& aValue, 1.822 + nsStyleCoord& aCoord, 1.823 + int32_t aMask) 1.824 +{ 1.825 + NS_ABORT_IF_FALSE((aMask & (SETCOORD_LH | SETCOORD_UNSET_INHERIT | 1.826 + SETCOORD_UNSET_INITIAL)) == 0, 1.827 + "does not handle SETCOORD_LENGTH, SETCOORD_INHERIT and " 1.828 + "SETCOORD_UNSET_*"); 1.829 + 1.830 + // The values of the following variables will never be used; so it does not 1.831 + // matter what to set. 1.832 + const nsStyleCoord dummyParentCoord; 1.833 + nsStyleContext* dummyStyleContext = nullptr; 1.834 + nsPresContext* dummyPresContext = nullptr; 1.835 + bool dummyCanStoreInRuleTree = true; 1.836 + 1.837 + bool rv = SetCoord(aValue, aCoord, dummyParentCoord, aMask, 1.838 + dummyStyleContext, dummyPresContext, 1.839 + dummyCanStoreInRuleTree); 1.840 + NS_ABORT_IF_FALSE(dummyCanStoreInRuleTree, 1.841 + "SetCoord() should not modify dummyCanStoreInRuleTree."); 1.842 + 1.843 + return rv; 1.844 +} 1.845 + 1.846 +/* Given a specified value that might be a pair value, call SetCoord twice, 1.847 + * either using each member of the pair, or using the unpaired value twice. 1.848 + */ 1.849 +static bool 1.850 +SetPairCoords(const nsCSSValue& aValue, 1.851 + nsStyleCoord& aCoordX, nsStyleCoord& aCoordY, 1.852 + const nsStyleCoord& aParentX, const nsStyleCoord& aParentY, 1.853 + int32_t aMask, nsStyleContext* aStyleContext, 1.854 + nsPresContext* aPresContext, bool& aCanStoreInRuleTree) 1.855 +{ 1.856 + const nsCSSValue& valX = 1.857 + aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mXValue : aValue; 1.858 + const nsCSSValue& valY = 1.859 + aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mYValue : aValue; 1.860 + 1.861 + bool cX = SetCoord(valX, aCoordX, aParentX, aMask, aStyleContext, 1.862 + aPresContext, aCanStoreInRuleTree); 1.863 + mozilla::DebugOnly<bool> cY = SetCoord(valY, aCoordY, aParentY, aMask, 1.864 + aStyleContext, aPresContext, aCanStoreInRuleTree); 1.865 + NS_ABORT_IF_FALSE(cX == cY, "changed one but not the other"); 1.866 + return cX; 1.867 +} 1.868 + 1.869 +static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor, 1.870 + nsPresContext* aPresContext, nsStyleContext *aContext, 1.871 + nscolor& aResult, bool& aCanStoreInRuleTree) 1.872 +{ 1.873 + bool result = false; 1.874 + nsCSSUnit unit = aValue.GetUnit(); 1.875 + 1.876 + if (aValue.IsNumericColorUnit()) { 1.877 + aResult = aValue.GetColorValue(); 1.878 + result = true; 1.879 + } 1.880 + else if (eCSSUnit_Ident == unit) { 1.881 + nsAutoString value; 1.882 + aValue.GetStringValue(value); 1.883 + nscolor rgba; 1.884 + if (NS_ColorNameToRGB(value, &rgba)) { 1.885 + aResult = rgba; 1.886 + result = true; 1.887 + } 1.888 + } 1.889 + else if (eCSSUnit_EnumColor == unit) { 1.890 + int32_t intValue = aValue.GetIntValue(); 1.891 + if (0 <= intValue) { 1.892 + LookAndFeel::ColorID colorID = (LookAndFeel::ColorID) intValue; 1.893 + bool useStandinsForNativeColors = aPresContext && 1.894 + !aPresContext->IsChrome(); 1.895 + if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID, 1.896 + useStandinsForNativeColors, &aResult))) { 1.897 + result = true; 1.898 + } 1.899 + } 1.900 + else { 1.901 + aResult = NS_RGB(0, 0, 0); 1.902 + result = false; 1.903 + switch (intValue) { 1.904 + case NS_COLOR_MOZ_HYPERLINKTEXT: 1.905 + if (aPresContext) { 1.906 + aResult = aPresContext->DefaultLinkColor(); 1.907 + result = true; 1.908 + } 1.909 + break; 1.910 + case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT: 1.911 + if (aPresContext) { 1.912 + aResult = aPresContext->DefaultVisitedLinkColor(); 1.913 + result = true; 1.914 + } 1.915 + break; 1.916 + case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT: 1.917 + if (aPresContext) { 1.918 + aResult = aPresContext->DefaultActiveLinkColor(); 1.919 + result = true; 1.920 + } 1.921 + break; 1.922 + case NS_COLOR_CURRENTCOLOR: 1.923 + // The data computed from this can't be shared in the rule tree 1.924 + // because they could be used on a node with a different color 1.925 + aCanStoreInRuleTree = false; 1.926 + if (aContext) { 1.927 + aResult = aContext->StyleColor()->mColor; 1.928 + result = true; 1.929 + } 1.930 + break; 1.931 + case NS_COLOR_MOZ_DEFAULT_COLOR: 1.932 + if (aPresContext) { 1.933 + aResult = aPresContext->DefaultColor(); 1.934 + result = true; 1.935 + } 1.936 + break; 1.937 + case NS_COLOR_MOZ_DEFAULT_BACKGROUND_COLOR: 1.938 + if (aPresContext) { 1.939 + aResult = aPresContext->DefaultBackgroundColor(); 1.940 + result = true; 1.941 + } 1.942 + break; 1.943 + default: 1.944 + NS_NOTREACHED("Should never have an unknown negative colorID."); 1.945 + break; 1.946 + } 1.947 + } 1.948 + } 1.949 + else if (eCSSUnit_Inherit == unit) { 1.950 + aResult = aParentColor; 1.951 + result = true; 1.952 + aCanStoreInRuleTree = false; 1.953 + } 1.954 + else if (eCSSUnit_Enumerated == unit && 1.955 + aValue.GetIntValue() == NS_STYLE_COLOR_INHERIT_FROM_BODY) { 1.956 + NS_ASSERTION(aPresContext->CompatibilityMode() == eCompatibility_NavQuirks, 1.957 + "Should only get this value in quirks mode"); 1.958 + // We just grab the color from the prescontext, and rely on the fact that 1.959 + // if the body color ever changes all its descendants will get new style 1.960 + // contexts (but NOT necessarily new rulenodes). 1.961 + aResult = aPresContext->BodyTextColor(); 1.962 + result = true; 1.963 + aCanStoreInRuleTree = false; 1.964 + } 1.965 + return result; 1.966 +} 1.967 + 1.968 +static void SetGradientCoord(const nsCSSValue& aValue, nsPresContext* aPresContext, 1.969 + nsStyleContext* aContext, nsStyleCoord& aResult, 1.970 + bool& aCanStoreInRuleTree) 1.971 +{ 1.972 + // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT 1.973 + if (!SetCoord(aValue, aResult, nsStyleCoord(), 1.974 + SETCOORD_LPO | SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC, 1.975 + aContext, aPresContext, aCanStoreInRuleTree)) { 1.976 + NS_NOTREACHED("unexpected unit for gradient anchor point"); 1.977 + aResult.SetNoneValue(); 1.978 + } 1.979 +} 1.980 + 1.981 +static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext, 1.982 + nsStyleContext* aContext, nsStyleGradient& aResult, 1.983 + bool& aCanStoreInRuleTree) 1.984 +{ 1.985 + NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Gradient, 1.986 + "The given data is not a gradient"); 1.987 + 1.988 + const nsCSSValueGradient* gradient = aValue.GetGradientValue(); 1.989 + 1.990 + if (gradient->mIsExplicitSize) { 1.991 + SetCoord(gradient->GetRadiusX(), aResult.mRadiusX, nsStyleCoord(), 1.992 + SETCOORD_LP | SETCOORD_STORE_CALC, 1.993 + aContext, aPresContext, aCanStoreInRuleTree); 1.994 + if (gradient->GetRadiusY().GetUnit() != eCSSUnit_None) { 1.995 + SetCoord(gradient->GetRadiusY(), aResult.mRadiusY, nsStyleCoord(), 1.996 + SETCOORD_LP | SETCOORD_STORE_CALC, 1.997 + aContext, aPresContext, aCanStoreInRuleTree); 1.998 + aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL; 1.999 + } else { 1.1000 + aResult.mRadiusY = aResult.mRadiusX; 1.1001 + aResult.mShape = NS_STYLE_GRADIENT_SHAPE_CIRCULAR; 1.1002 + } 1.1003 + aResult.mSize = NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE; 1.1004 + } else if (gradient->mIsRadial) { 1.1005 + if (gradient->GetRadialShape().GetUnit() == eCSSUnit_Enumerated) { 1.1006 + aResult.mShape = gradient->GetRadialShape().GetIntValue(); 1.1007 + } else { 1.1008 + NS_ASSERTION(gradient->GetRadialShape().GetUnit() == eCSSUnit_None, 1.1009 + "bad unit for radial shape"); 1.1010 + aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL; 1.1011 + } 1.1012 + if (gradient->GetRadialSize().GetUnit() == eCSSUnit_Enumerated) { 1.1013 + aResult.mSize = gradient->GetRadialSize().GetIntValue(); 1.1014 + } else { 1.1015 + NS_ASSERTION(gradient->GetRadialSize().GetUnit() == eCSSUnit_None, 1.1016 + "bad unit for radial shape"); 1.1017 + aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER; 1.1018 + } 1.1019 + } else { 1.1020 + NS_ASSERTION(gradient->GetRadialShape().GetUnit() == eCSSUnit_None, 1.1021 + "bad unit for linear shape"); 1.1022 + NS_ASSERTION(gradient->GetRadialSize().GetUnit() == eCSSUnit_None, 1.1023 + "bad unit for linear size"); 1.1024 + aResult.mShape = NS_STYLE_GRADIENT_SHAPE_LINEAR; 1.1025 + aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER; 1.1026 + } 1.1027 + 1.1028 + aResult.mLegacySyntax = gradient->mIsLegacySyntax; 1.1029 + 1.1030 + // bg-position 1.1031 + SetGradientCoord(gradient->mBgPos.mXValue, aPresContext, aContext, 1.1032 + aResult.mBgPosX, aCanStoreInRuleTree); 1.1033 + 1.1034 + SetGradientCoord(gradient->mBgPos.mYValue, aPresContext, aContext, 1.1035 + aResult.mBgPosY, aCanStoreInRuleTree); 1.1036 + 1.1037 + aResult.mRepeating = gradient->mIsRepeating; 1.1038 + 1.1039 + // angle 1.1040 + const nsStyleCoord dummyParentCoord; 1.1041 + if (!SetCoord(gradient->mAngle, aResult.mAngle, dummyParentCoord, SETCOORD_ANGLE, 1.1042 + aContext, aPresContext, aCanStoreInRuleTree)) { 1.1043 + NS_ASSERTION(gradient->mAngle.GetUnit() == eCSSUnit_None, 1.1044 + "bad unit for gradient angle"); 1.1045 + aResult.mAngle.SetNoneValue(); 1.1046 + } 1.1047 + 1.1048 + // stops 1.1049 + for (uint32_t i = 0; i < gradient->mStops.Length(); i++) { 1.1050 + nsStyleGradientStop stop; 1.1051 + const nsCSSValueGradientStop &valueStop = gradient->mStops[i]; 1.1052 + 1.1053 + if (!SetCoord(valueStop.mLocation, stop.mLocation, 1.1054 + nsStyleCoord(), SETCOORD_LPO | SETCOORD_STORE_CALC, 1.1055 + aContext, aPresContext, aCanStoreInRuleTree)) { 1.1056 + NS_NOTREACHED("unexpected unit for gradient stop location"); 1.1057 + } 1.1058 + 1.1059 + // inherit is not a valid color for stops, so we pass in a dummy 1.1060 + // parent color 1.1061 + NS_ASSERTION(valueStop.mColor.GetUnit() != eCSSUnit_Inherit, 1.1062 + "inherit is not a valid color for gradient stops"); 1.1063 + SetColor(valueStop.mColor, NS_RGB(0, 0, 0), aPresContext, 1.1064 + aContext, stop.mColor, aCanStoreInRuleTree); 1.1065 + 1.1066 + aResult.mStops.AppendElement(stop); 1.1067 + } 1.1068 +} 1.1069 + 1.1070 +// -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>) 1.1071 +static void SetStyleImageToImageRect(nsStyleContext* aStyleContext, 1.1072 + const nsCSSValue& aValue, 1.1073 + nsStyleImage& aResult) 1.1074 +{ 1.1075 + NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Function && 1.1076 + aValue.EqualsFunction(eCSSKeyword__moz_image_rect), 1.1077 + "the value is not valid -moz-image-rect()"); 1.1078 + 1.1079 + nsCSSValue::Array* arr = aValue.GetArrayValue(); 1.1080 + NS_ABORT_IF_FALSE(arr && arr->Count() == 6, "invalid number of arguments"); 1.1081 + 1.1082 + // <uri> 1.1083 + if (arr->Item(1).GetUnit() == eCSSUnit_Image) { 1.1084 + NS_SET_IMAGE_REQUEST_WITH_DOC(aResult.SetImageData, 1.1085 + aStyleContext, 1.1086 + arr->Item(1).GetImageValue) 1.1087 + } else { 1.1088 + NS_WARNING("nsCSSValue::Image::Image() failed?"); 1.1089 + } 1.1090 + 1.1091 + // <top>, <right>, <bottom>, <left> 1.1092 + nsStyleSides cropRect; 1.1093 + NS_FOR_CSS_SIDES(side) { 1.1094 + nsStyleCoord coord; 1.1095 + const nsCSSValue& val = arr->Item(2 + side); 1.1096 + 1.1097 +#ifdef DEBUG 1.1098 + bool unitOk = 1.1099 +#endif 1.1100 + SetAbsCoord(val, coord, SETCOORD_FACTOR | SETCOORD_PERCENT); 1.1101 + NS_ABORT_IF_FALSE(unitOk, "Incorrect data structure created by CSS parser"); 1.1102 + cropRect.Set(side, coord); 1.1103 + } 1.1104 + aResult.SetCropRect(&cropRect); 1.1105 +} 1.1106 + 1.1107 +static void SetStyleImage(nsStyleContext* aStyleContext, 1.1108 + const nsCSSValue& aValue, 1.1109 + nsStyleImage& aResult, 1.1110 + bool& aCanStoreInRuleTree) 1.1111 +{ 1.1112 + if (aValue.GetUnit() == eCSSUnit_Null) { 1.1113 + return; 1.1114 + } 1.1115 + 1.1116 + aResult.SetNull(); 1.1117 + 1.1118 + switch (aValue.GetUnit()) { 1.1119 + case eCSSUnit_Image: 1.1120 + NS_SET_IMAGE_REQUEST_WITH_DOC(aResult.SetImageData, 1.1121 + aStyleContext, 1.1122 + aValue.GetImageValue) 1.1123 + break; 1.1124 + case eCSSUnit_Function: 1.1125 + if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) { 1.1126 + SetStyleImageToImageRect(aStyleContext, aValue, aResult); 1.1127 + } else { 1.1128 + NS_NOTREACHED("-moz-image-rect() is the only expected function"); 1.1129 + } 1.1130 + break; 1.1131 + case eCSSUnit_Gradient: 1.1132 + { 1.1133 + nsStyleGradient* gradient = new nsStyleGradient(); 1.1134 + if (gradient) { 1.1135 + SetGradient(aValue, aStyleContext->PresContext(), aStyleContext, 1.1136 + *gradient, aCanStoreInRuleTree); 1.1137 + aResult.SetGradientData(gradient); 1.1138 + } 1.1139 + break; 1.1140 + } 1.1141 + case eCSSUnit_Element: 1.1142 + aResult.SetElementId(aValue.GetStringBufferValue()); 1.1143 + break; 1.1144 + case eCSSUnit_Initial: 1.1145 + case eCSSUnit_Unset: 1.1146 + case eCSSUnit_None: 1.1147 + break; 1.1148 + default: 1.1149 + // We might have eCSSUnit_URL values for if-visited style 1.1150 + // contexts, which we can safely treat like 'none'. Otherwise 1.1151 + // this is an unexpected unit. 1.1152 + NS_ASSERTION(aStyleContext->IsStyleIfVisited() && 1.1153 + aValue.GetUnit() == eCSSUnit_URL, 1.1154 + "unexpected unit; maybe nsCSSValue::Image::Image() failed?"); 1.1155 + break; 1.1156 + } 1.1157 +} 1.1158 + 1.1159 +// flags for SetDiscrete - align values with SETCOORD_* constants 1.1160 +// where possible 1.1161 + 1.1162 +#define SETDSC_NORMAL 0x01 // N 1.1163 +#define SETDSC_AUTO 0x02 // A 1.1164 +#define SETDSC_INTEGER 0x40 // I 1.1165 +#define SETDSC_ENUMERATED 0x80 // E 1.1166 +#define SETDSC_NONE 0x100 // O 1.1167 +#define SETDSC_SYSTEM_FONT 0x2000 1.1168 +#define SETDSC_UNSET_INHERIT 0x00400000 1.1169 +#define SETDSC_UNSET_INITIAL 0x00800000 1.1170 + 1.1171 +// no caller cares whether aField was changed or not 1.1172 +template <typename FieldT, 1.1173 + typename T1, typename T2, typename T3, typename T4, typename T5> 1.1174 +static void 1.1175 +SetDiscrete(const nsCSSValue& aValue, FieldT & aField, 1.1176 + bool& aCanStoreInRuleTree, uint32_t aMask, 1.1177 + FieldT aParentValue, 1.1178 + T1 aInitialValue, 1.1179 + T2 aAutoValue, 1.1180 + T3 aNoneValue, 1.1181 + T4 aNormalValue, 1.1182 + T5 aSystemFontValue) 1.1183 +{ 1.1184 + switch (aValue.GetUnit()) { 1.1185 + case eCSSUnit_Null: 1.1186 + return; 1.1187 + 1.1188 + // every caller of SetDiscrete provides inherit and initial 1.1189 + // alternatives, so we don't require them to say so in the mask 1.1190 + case eCSSUnit_Inherit: 1.1191 + aCanStoreInRuleTree = false; 1.1192 + aField = aParentValue; 1.1193 + return; 1.1194 + 1.1195 + case eCSSUnit_Initial: 1.1196 + aField = aInitialValue; 1.1197 + return; 1.1198 + 1.1199 + // every caller provides one or other of these alternatives, 1.1200 + // but they have to say which 1.1201 + case eCSSUnit_Enumerated: 1.1202 + if (aMask & SETDSC_ENUMERATED) { 1.1203 + aField = aValue.GetIntValue(); 1.1204 + return; 1.1205 + } 1.1206 + break; 1.1207 + 1.1208 + case eCSSUnit_Integer: 1.1209 + if (aMask & SETDSC_INTEGER) { 1.1210 + aField = aValue.GetIntValue(); 1.1211 + return; 1.1212 + } 1.1213 + break; 1.1214 + 1.1215 + // remaining possibilities in descending order of frequency of use 1.1216 + case eCSSUnit_Auto: 1.1217 + if (aMask & SETDSC_AUTO) { 1.1218 + aField = aAutoValue; 1.1219 + return; 1.1220 + } 1.1221 + break; 1.1222 + 1.1223 + case eCSSUnit_None: 1.1224 + if (aMask & SETDSC_NONE) { 1.1225 + aField = aNoneValue; 1.1226 + return; 1.1227 + } 1.1228 + break; 1.1229 + 1.1230 + case eCSSUnit_Normal: 1.1231 + if (aMask & SETDSC_NORMAL) { 1.1232 + aField = aNormalValue; 1.1233 + return; 1.1234 + } 1.1235 + break; 1.1236 + 1.1237 + case eCSSUnit_System_Font: 1.1238 + if (aMask & SETDSC_SYSTEM_FONT) { 1.1239 + aField = aSystemFontValue; 1.1240 + return; 1.1241 + } 1.1242 + break; 1.1243 + 1.1244 + case eCSSUnit_Unset: 1.1245 + if (aMask & SETDSC_UNSET_INHERIT) { 1.1246 + aCanStoreInRuleTree = false; 1.1247 + aField = aParentValue; 1.1248 + return; 1.1249 + } 1.1250 + if (aMask & SETDSC_UNSET_INITIAL) { 1.1251 + aField = aInitialValue; 1.1252 + return; 1.1253 + } 1.1254 + break; 1.1255 + 1.1256 + default: 1.1257 + break; 1.1258 + } 1.1259 + 1.1260 + NS_NOTREACHED("SetDiscrete: inappropriate unit"); 1.1261 +} 1.1262 + 1.1263 +// flags for SetFactor 1.1264 +#define SETFCT_POSITIVE 0x01 // assert value is >= 0.0f 1.1265 +#define SETFCT_OPACITY 0x02 // clamp value to [0.0f .. 1.0f] 1.1266 +#define SETFCT_NONE 0x04 // allow _None (uses aInitialValue). 1.1267 +#define SETFCT_UNSET_INHERIT 0x00400000 1.1268 +#define SETFCT_UNSET_INITIAL 0x00800000 1.1269 + 1.1270 +static void 1.1271 +SetFactor(const nsCSSValue& aValue, float& aField, bool& aCanStoreInRuleTree, 1.1272 + float aParentValue, float aInitialValue, uint32_t aFlags = 0) 1.1273 +{ 1.1274 + switch (aValue.GetUnit()) { 1.1275 + case eCSSUnit_Null: 1.1276 + return; 1.1277 + 1.1278 + case eCSSUnit_Number: 1.1279 + aField = aValue.GetFloatValue(); 1.1280 + if (aFlags & SETFCT_POSITIVE) { 1.1281 + NS_ASSERTION(aField >= 0.0f, "negative value for positive-only property"); 1.1282 + if (aField < 0.0f) 1.1283 + aField = 0.0f; 1.1284 + } 1.1285 + if (aFlags & SETFCT_OPACITY) { 1.1286 + if (aField < 0.0f) 1.1287 + aField = 0.0f; 1.1288 + if (aField > 1.0f) 1.1289 + aField = 1.0f; 1.1290 + } 1.1291 + return; 1.1292 + 1.1293 + case eCSSUnit_Inherit: 1.1294 + aCanStoreInRuleTree = false; 1.1295 + aField = aParentValue; 1.1296 + return; 1.1297 + 1.1298 + case eCSSUnit_Initial: 1.1299 + aField = aInitialValue; 1.1300 + return; 1.1301 + 1.1302 + case eCSSUnit_None: 1.1303 + if (aFlags & SETFCT_NONE) { 1.1304 + aField = aInitialValue; 1.1305 + return; 1.1306 + } 1.1307 + break; 1.1308 + 1.1309 + case eCSSUnit_Unset: 1.1310 + if (aFlags & SETFCT_UNSET_INHERIT) { 1.1311 + aCanStoreInRuleTree = false; 1.1312 + aField = aParentValue; 1.1313 + return; 1.1314 + } 1.1315 + if (aFlags & SETFCT_UNSET_INITIAL) { 1.1316 + aField = aInitialValue; 1.1317 + return; 1.1318 + } 1.1319 + break; 1.1320 + 1.1321 + default: 1.1322 + break; 1.1323 + } 1.1324 + 1.1325 + NS_NOTREACHED("SetFactor: inappropriate unit"); 1.1326 +} 1.1327 + 1.1328 +// Overloaded new operator. Initializes the memory to 0 and relies on an arena 1.1329 +// (which comes from the presShell) to perform the allocation. 1.1330 +void* 1.1331 +nsRuleNode::operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW 1.1332 +{ 1.1333 + // Check the recycle list first. 1.1334 + return aPresContext->PresShell()->AllocateByObjectID(nsPresArena::nsRuleNode_id, sz); 1.1335 +} 1.1336 + 1.1337 +/* static */ PLDHashOperator 1.1338 +nsRuleNode::EnqueueRuleNodeChildren(PLDHashTable *table, PLDHashEntryHdr *hdr, 1.1339 + uint32_t number, void *arg) 1.1340 +{ 1.1341 + ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(hdr); 1.1342 + nsRuleNode ***destroyQueueTail = static_cast<nsRuleNode***>(arg); 1.1343 + **destroyQueueTail = entry->mRuleNode; 1.1344 + *destroyQueueTail = &entry->mRuleNode->mNextSibling; 1.1345 + return PL_DHASH_NEXT; 1.1346 +} 1.1347 + 1.1348 +// Overridden to prevent the global delete from being called, since the memory 1.1349 +// came out of an nsIArena instead of the global delete operator's heap. 1.1350 +void 1.1351 +nsRuleNode::DestroyInternal(nsRuleNode ***aDestroyQueueTail) 1.1352 +{ 1.1353 + nsRuleNode *destroyQueue, **destroyQueueTail; 1.1354 + if (aDestroyQueueTail) { 1.1355 + destroyQueueTail = *aDestroyQueueTail; 1.1356 + } else { 1.1357 + destroyQueue = nullptr; 1.1358 + destroyQueueTail = &destroyQueue; 1.1359 + } 1.1360 + 1.1361 + if (ChildrenAreHashed()) { 1.1362 + PLDHashTable *children = ChildrenHash(); 1.1363 + PL_DHashTableEnumerate(children, EnqueueRuleNodeChildren, 1.1364 + &destroyQueueTail); 1.1365 + *destroyQueueTail = nullptr; // ensure null-termination 1.1366 + PL_DHashTableDestroy(children); 1.1367 + } else if (HaveChildren()) { 1.1368 + *destroyQueueTail = ChildrenList(); 1.1369 + do { 1.1370 + destroyQueueTail = &(*destroyQueueTail)->mNextSibling; 1.1371 + } while (*destroyQueueTail); 1.1372 + } 1.1373 + mChildren.asVoid = nullptr; 1.1374 + 1.1375 + if (aDestroyQueueTail) { 1.1376 + // Our caller destroys the queue. 1.1377 + *aDestroyQueueTail = destroyQueueTail; 1.1378 + } else { 1.1379 + // We have to do destroy the queue. When we destroy each node, it 1.1380 + // will add its children to the queue. 1.1381 + while (destroyQueue) { 1.1382 + nsRuleNode *cur = destroyQueue; 1.1383 + destroyQueue = destroyQueue->mNextSibling; 1.1384 + if (!destroyQueue) { 1.1385 + NS_ASSERTION(destroyQueueTail == &cur->mNextSibling, "mangled list"); 1.1386 + destroyQueueTail = &destroyQueue; 1.1387 + } 1.1388 + cur->DestroyInternal(&destroyQueueTail); 1.1389 + } 1.1390 + } 1.1391 + 1.1392 + // Destroy ourselves. 1.1393 + this->~nsRuleNode(); 1.1394 + 1.1395 + // Don't let the memory be freed, since it will be recycled 1.1396 + // instead. Don't call the global operator delete. 1.1397 + mPresContext->PresShell()->FreeByObjectID(nsPresArena::nsRuleNode_id, this); 1.1398 +} 1.1399 + 1.1400 +nsRuleNode* nsRuleNode::CreateRootNode(nsPresContext* aPresContext) 1.1401 +{ 1.1402 + return new (aPresContext) 1.1403 + nsRuleNode(aPresContext, nullptr, nullptr, 0xff, false); 1.1404 +} 1.1405 + 1.1406 +nsRuleNode::nsRuleNode(nsPresContext* aContext, nsRuleNode* aParent, 1.1407 + nsIStyleRule* aRule, uint8_t aLevel, 1.1408 + bool aIsImportant) 1.1409 + : mPresContext(aContext), 1.1410 + mParent(aParent), 1.1411 + mRule(aRule), 1.1412 + mDependentBits((uint32_t(aLevel) << NS_RULE_NODE_LEVEL_SHIFT) | 1.1413 + (aIsImportant ? NS_RULE_NODE_IS_IMPORTANT : 0)), 1.1414 + mNoneBits(0), 1.1415 + mRefCnt(0) 1.1416 +{ 1.1417 + MOZ_ASSERT(aContext); 1.1418 + NS_ABORT_IF_FALSE(IsRoot() == !aRule, 1.1419 + "non-root rule nodes must have a rule"); 1.1420 + 1.1421 + mChildren.asVoid = nullptr; 1.1422 + MOZ_COUNT_CTOR(nsRuleNode); 1.1423 + 1.1424 + if (mRule) { 1.1425 + mRule->AddRef(); 1.1426 + } 1.1427 + 1.1428 + NS_ASSERTION(IsRoot() || GetLevel() == aLevel, "not enough bits"); 1.1429 + NS_ASSERTION(IsRoot() || IsImportantRule() == aIsImportant, "yikes"); 1.1430 + /* If IsRoot(), then aContext->StyleSet() is typically null at this 1.1431 + point. In any case, we don't want to treat the root rulenode as 1.1432 + unused. */ 1.1433 + if (!IsRoot()) { 1.1434 + mParent->AddRef(); 1.1435 + aContext->StyleSet()->RuleNodeUnused(); 1.1436 + } 1.1437 + 1.1438 + // nsStyleSet::GetContext depends on there being only one animation 1.1439 + // rule. 1.1440 + NS_ABORT_IF_FALSE(IsRoot() || GetLevel() != nsStyleSet::eAnimationSheet || 1.1441 + mParent->IsRoot() || 1.1442 + mParent->GetLevel() != nsStyleSet::eAnimationSheet, 1.1443 + "must be only one rule at animation level"); 1.1444 +} 1.1445 + 1.1446 +nsRuleNode::~nsRuleNode() 1.1447 +{ 1.1448 + MOZ_COUNT_DTOR(nsRuleNode); 1.1449 + if (mStyleData.mResetData || mStyleData.mInheritedData) 1.1450 + mStyleData.Destroy(mDependentBits, mPresContext); 1.1451 + if (mRule) { 1.1452 + mRule->Release(); 1.1453 + } 1.1454 +} 1.1455 + 1.1456 +nsRuleNode* 1.1457 +nsRuleNode::Transition(nsIStyleRule* aRule, uint8_t aLevel, 1.1458 + bool aIsImportantRule) 1.1459 +{ 1.1460 + nsRuleNode* next = nullptr; 1.1461 + nsRuleNode::Key key(aRule, aLevel, aIsImportantRule); 1.1462 + 1.1463 + if (HaveChildren() && !ChildrenAreHashed()) { 1.1464 + int32_t numKids = 0; 1.1465 + nsRuleNode* curr = ChildrenList(); 1.1466 + while (curr && curr->GetKey() != key) { 1.1467 + curr = curr->mNextSibling; 1.1468 + ++numKids; 1.1469 + } 1.1470 + if (curr) 1.1471 + next = curr; 1.1472 + else if (numKids >= kMaxChildrenInList) 1.1473 + ConvertChildrenToHash(); 1.1474 + } 1.1475 + 1.1476 + if (ChildrenAreHashed()) { 1.1477 + ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*> 1.1478 + (PL_DHashTableOperate(ChildrenHash(), &key, PL_DHASH_ADD)); 1.1479 + if (!entry) { 1.1480 + NS_WARNING("out of memory"); 1.1481 + return this; 1.1482 + } 1.1483 + if (entry->mRuleNode) 1.1484 + next = entry->mRuleNode; 1.1485 + else { 1.1486 + next = entry->mRuleNode = new (mPresContext) 1.1487 + nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule); 1.1488 + if (!next) { 1.1489 + PL_DHashTableRawRemove(ChildrenHash(), entry); 1.1490 + NS_WARNING("out of memory"); 1.1491 + return this; 1.1492 + } 1.1493 + } 1.1494 + } else if (!next) { 1.1495 + // Create the new entry in our list. 1.1496 + next = new (mPresContext) 1.1497 + nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule); 1.1498 + if (!next) { 1.1499 + NS_WARNING("out of memory"); 1.1500 + return this; 1.1501 + } 1.1502 + next->mNextSibling = ChildrenList(); 1.1503 + SetChildrenList(next); 1.1504 + } 1.1505 + 1.1506 + return next; 1.1507 +} 1.1508 + 1.1509 +void nsRuleNode::SetUsedDirectly() 1.1510 +{ 1.1511 + mDependentBits |= NS_RULE_NODE_USED_DIRECTLY; 1.1512 + 1.1513 + // Maintain the invariant that any rule node that is used directly has 1.1514 + // all structs that live in the rule tree cached (which 1.1515 + // nsRuleNode::GetStyleData depends on for speed). 1.1516 + if (mDependentBits & NS_STYLE_INHERIT_MASK) { 1.1517 + for (nsStyleStructID sid = nsStyleStructID(0); sid < nsStyleStructID_Length; 1.1518 + sid = nsStyleStructID(sid + 1)) { 1.1519 + uint32_t bit = nsCachedStyleData::GetBitForSID(sid); 1.1520 + if (mDependentBits & bit) { 1.1521 + nsRuleNode *source = mParent; 1.1522 + while ((source->mDependentBits & bit) && !source->IsUsedDirectly()) { 1.1523 + source = source->mParent; 1.1524 + } 1.1525 + void *data = source->mStyleData.GetStyleData(sid); 1.1526 + NS_ASSERTION(data, "unexpected null struct"); 1.1527 + mStyleData.SetStyleData(sid, mPresContext, data); 1.1528 + } 1.1529 + } 1.1530 + } 1.1531 +} 1.1532 + 1.1533 +void 1.1534 +nsRuleNode::ConvertChildrenToHash() 1.1535 +{ 1.1536 + NS_ASSERTION(!ChildrenAreHashed() && HaveChildren(), 1.1537 + "must have a non-empty list of children"); 1.1538 + PLDHashTable *hash = PL_NewDHashTable(&ChildrenHashOps, nullptr, 1.1539 + sizeof(ChildrenHashEntry), 1.1540 + kMaxChildrenInList * 4); 1.1541 + if (!hash) 1.1542 + return; 1.1543 + for (nsRuleNode* curr = ChildrenList(); curr; curr = curr->mNextSibling) { 1.1544 + // This will never fail because of the initial size we gave the table. 1.1545 + ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>( 1.1546 + PL_DHashTableOperate(hash, curr->mRule, PL_DHASH_ADD)); 1.1547 + NS_ASSERTION(!entry->mRuleNode, "duplicate entries in list"); 1.1548 + entry->mRuleNode = curr; 1.1549 + } 1.1550 + SetChildrenHash(hash); 1.1551 +} 1.1552 + 1.1553 +inline void 1.1554 +nsRuleNode::PropagateNoneBit(uint32_t aBit, nsRuleNode* aHighestNode) 1.1555 +{ 1.1556 + nsRuleNode* curr = this; 1.1557 + for (;;) { 1.1558 + NS_ASSERTION(!(curr->mNoneBits & aBit), "propagating too far"); 1.1559 + curr->mNoneBits |= aBit; 1.1560 + if (curr == aHighestNode) 1.1561 + break; 1.1562 + curr = curr->mParent; 1.1563 + } 1.1564 +} 1.1565 + 1.1566 +inline void 1.1567 +nsRuleNode::PropagateDependentBit(nsStyleStructID aSID, nsRuleNode* aHighestNode, 1.1568 + void* aStruct) 1.1569 +{ 1.1570 + NS_ASSERTION(aStruct, "expected struct"); 1.1571 + 1.1572 + uint32_t bit = nsCachedStyleData::GetBitForSID(aSID); 1.1573 + for (nsRuleNode* curr = this; curr != aHighestNode; curr = curr->mParent) { 1.1574 + if (curr->mDependentBits & bit) { 1.1575 +#ifdef DEBUG 1.1576 + while (curr != aHighestNode) { 1.1577 + NS_ASSERTION(curr->mDependentBits & bit, "bit not set"); 1.1578 + curr = curr->mParent; 1.1579 + } 1.1580 +#endif 1.1581 + break; 1.1582 + } 1.1583 + 1.1584 + curr->mDependentBits |= bit; 1.1585 + 1.1586 + if (curr->IsUsedDirectly()) { 1.1587 + curr->mStyleData.SetStyleData(aSID, mPresContext, aStruct); 1.1588 + } 1.1589 + } 1.1590 +} 1.1591 + 1.1592 +/* 1.1593 + * The following "Check" functions are used for determining what type of 1.1594 + * sharing can be used for the data on this rule node. MORE HERE... 1.1595 + */ 1.1596 + 1.1597 +/* 1.1598 + * a callback function that that can revise the result of 1.1599 + * CheckSpecifiedProperties before finishing; aResult is the current 1.1600 + * result, and it returns the revised one. 1.1601 + */ 1.1602 +typedef nsRuleNode::RuleDetail 1.1603 + (* CheckCallbackFn)(const nsRuleData* aRuleData, 1.1604 + nsRuleNode::RuleDetail aResult); 1.1605 + 1.1606 +/** 1.1607 + * @param aValue the value being examined 1.1608 + * @param aSpecifiedCount to be incremented by one if the value is specified 1.1609 + * @param aInheritedCount to be incremented by one if the value is set to inherit 1.1610 + * @param aUnsetCount to be incremented by one if the value is set to unset 1.1611 + */ 1.1612 +inline void 1.1613 +ExamineCSSValue(const nsCSSValue& aValue, 1.1614 + uint32_t& aSpecifiedCount, 1.1615 + uint32_t& aInheritedCount, 1.1616 + uint32_t& aUnsetCount) 1.1617 +{ 1.1618 + if (aValue.GetUnit() != eCSSUnit_Null) { 1.1619 + ++aSpecifiedCount; 1.1620 + if (aValue.GetUnit() == eCSSUnit_Inherit) { 1.1621 + ++aInheritedCount; 1.1622 + } else if (aValue.GetUnit() == eCSSUnit_Unset) { 1.1623 + ++aUnsetCount; 1.1624 + } 1.1625 + } 1.1626 +} 1.1627 + 1.1628 +static nsRuleNode::RuleDetail 1.1629 +CheckFontCallback(const nsRuleData* aRuleData, 1.1630 + nsRuleNode::RuleDetail aResult) 1.1631 +{ 1.1632 + // em, ex, percent, 'larger', and 'smaller' values on font-size depend 1.1633 + // on the parent context's font-size 1.1634 + // Likewise, 'lighter' and 'bolder' values of 'font-weight', and 'wider' 1.1635 + // and 'narrower' values of 'font-stretch' depend on the parent. 1.1636 + const nsCSSValue& size = *aRuleData->ValueForFontSize(); 1.1637 + const nsCSSValue& weight = *aRuleData->ValueForFontWeight(); 1.1638 + if ((size.IsRelativeLengthUnit() && size.GetUnit() != eCSSUnit_RootEM) || 1.1639 + size.GetUnit() == eCSSUnit_Percent || 1.1640 + (size.GetUnit() == eCSSUnit_Enumerated && 1.1641 + (size.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER || 1.1642 + size.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER)) || 1.1643 + aRuleData->ValueForScriptLevel()->GetUnit() == eCSSUnit_Integer || 1.1644 + (weight.GetUnit() == eCSSUnit_Enumerated && 1.1645 + (weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER || 1.1646 + weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER))) { 1.1647 + NS_ASSERTION(aResult == nsRuleNode::eRulePartialReset || 1.1648 + aResult == nsRuleNode::eRuleFullReset || 1.1649 + aResult == nsRuleNode::eRulePartialMixed || 1.1650 + aResult == nsRuleNode::eRuleFullMixed, 1.1651 + "we know we already have a reset-counted property"); 1.1652 + // Promote reset to mixed since we have something that depends on 1.1653 + // the parent. But never promote to inherited since that could 1.1654 + // cause inheritance of the exact value. 1.1655 + if (aResult == nsRuleNode::eRulePartialReset) 1.1656 + aResult = nsRuleNode::eRulePartialMixed; 1.1657 + else if (aResult == nsRuleNode::eRuleFullReset) 1.1658 + aResult = nsRuleNode::eRuleFullMixed; 1.1659 + } 1.1660 + 1.1661 + return aResult; 1.1662 +} 1.1663 + 1.1664 +static nsRuleNode::RuleDetail 1.1665 +CheckColorCallback(const nsRuleData* aRuleData, 1.1666 + nsRuleNode::RuleDetail aResult) 1.1667 +{ 1.1668 + // currentColor values for color require inheritance 1.1669 + const nsCSSValue* colorValue = aRuleData->ValueForColor(); 1.1670 + if (colorValue->GetUnit() == eCSSUnit_EnumColor && 1.1671 + colorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) { 1.1672 + NS_ASSERTION(aResult == nsRuleNode::eRuleFullReset, 1.1673 + "we should already be counted as full-reset"); 1.1674 + aResult = nsRuleNode::eRuleFullInherited; 1.1675 + } 1.1676 + 1.1677 + return aResult; 1.1678 +} 1.1679 + 1.1680 +static nsRuleNode::RuleDetail 1.1681 +CheckTextCallback(const nsRuleData* aRuleData, 1.1682 + nsRuleNode::RuleDetail aResult) 1.1683 +{ 1.1684 + const nsCSSValue* textAlignValue = aRuleData->ValueForTextAlign(); 1.1685 + if (textAlignValue->GetUnit() == eCSSUnit_Enumerated && 1.1686 + textAlignValue->GetIntValue() == 1.1687 + NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT) { 1.1688 + // Promote reset to mixed since we have something that depends on 1.1689 + // the parent. 1.1690 + if (aResult == nsRuleNode::eRulePartialReset) 1.1691 + aResult = nsRuleNode::eRulePartialMixed; 1.1692 + else if (aResult == nsRuleNode::eRuleFullReset) 1.1693 + aResult = nsRuleNode::eRuleFullMixed; 1.1694 + } 1.1695 + 1.1696 + return aResult; 1.1697 +} 1.1698 + 1.1699 +static nsRuleNode::RuleDetail 1.1700 +CheckVariablesCallback(const nsRuleData* aRuleData, 1.1701 + nsRuleNode::RuleDetail aResult) 1.1702 +{ 1.1703 + // We don't actually have any properties on nsStyleVariables, so we do 1.1704 + // all of the RuleDetail calculation in here. 1.1705 + if (aRuleData->mVariables) { 1.1706 + return nsRuleNode::eRulePartialMixed; 1.1707 + } 1.1708 + return nsRuleNode::eRuleNone; 1.1709 +} 1.1710 + 1.1711 +#define FLAG_DATA_FOR_PROPERTY(name_, id_, method_, flags_, pref_, \ 1.1712 + parsevariant_, kwtable_, stylestructoffset_, \ 1.1713 + animtype_) \ 1.1714 + flags_, 1.1715 + 1.1716 +// The order here must match the enums in *CheckCounter in nsCSSProps.cpp. 1.1717 + 1.1718 +static const uint32_t gFontFlags[] = { 1.1719 +#define CSS_PROP_FONT FLAG_DATA_FOR_PROPERTY 1.1720 +#include "nsCSSPropList.h" 1.1721 +#undef CSS_PROP_FONT 1.1722 +}; 1.1723 + 1.1724 +static const uint32_t gDisplayFlags[] = { 1.1725 +#define CSS_PROP_DISPLAY FLAG_DATA_FOR_PROPERTY 1.1726 +#include "nsCSSPropList.h" 1.1727 +#undef CSS_PROP_DISPLAY 1.1728 +}; 1.1729 + 1.1730 +static const uint32_t gVisibilityFlags[] = { 1.1731 +#define CSS_PROP_VISIBILITY FLAG_DATA_FOR_PROPERTY 1.1732 +#include "nsCSSPropList.h" 1.1733 +#undef CSS_PROP_VISIBILITY 1.1734 +}; 1.1735 + 1.1736 +static const uint32_t gMarginFlags[] = { 1.1737 +#define CSS_PROP_MARGIN FLAG_DATA_FOR_PROPERTY 1.1738 +#include "nsCSSPropList.h" 1.1739 +#undef CSS_PROP_MARGIN 1.1740 +}; 1.1741 + 1.1742 +static const uint32_t gBorderFlags[] = { 1.1743 +#define CSS_PROP_BORDER FLAG_DATA_FOR_PROPERTY 1.1744 +#include "nsCSSPropList.h" 1.1745 +#undef CSS_PROP_BORDER 1.1746 +}; 1.1747 + 1.1748 +static const uint32_t gPaddingFlags[] = { 1.1749 +#define CSS_PROP_PADDING FLAG_DATA_FOR_PROPERTY 1.1750 +#include "nsCSSPropList.h" 1.1751 +#undef CSS_PROP_PADDING 1.1752 +}; 1.1753 + 1.1754 +static const uint32_t gOutlineFlags[] = { 1.1755 +#define CSS_PROP_OUTLINE FLAG_DATA_FOR_PROPERTY 1.1756 +#include "nsCSSPropList.h" 1.1757 +#undef CSS_PROP_OUTLINE 1.1758 +}; 1.1759 + 1.1760 +static const uint32_t gListFlags[] = { 1.1761 +#define CSS_PROP_LIST FLAG_DATA_FOR_PROPERTY 1.1762 +#include "nsCSSPropList.h" 1.1763 +#undef CSS_PROP_LIST 1.1764 +}; 1.1765 + 1.1766 +static const uint32_t gColorFlags[] = { 1.1767 +#define CSS_PROP_COLOR FLAG_DATA_FOR_PROPERTY 1.1768 +#include "nsCSSPropList.h" 1.1769 +#undef CSS_PROP_COLOR 1.1770 +}; 1.1771 + 1.1772 +static const uint32_t gBackgroundFlags[] = { 1.1773 +#define CSS_PROP_BACKGROUND FLAG_DATA_FOR_PROPERTY 1.1774 +#include "nsCSSPropList.h" 1.1775 +#undef CSS_PROP_BACKGROUND 1.1776 +}; 1.1777 + 1.1778 +static const uint32_t gPositionFlags[] = { 1.1779 +#define CSS_PROP_POSITION FLAG_DATA_FOR_PROPERTY 1.1780 +#include "nsCSSPropList.h" 1.1781 +#undef CSS_PROP_POSITION 1.1782 +}; 1.1783 + 1.1784 +static const uint32_t gTableFlags[] = { 1.1785 +#define CSS_PROP_TABLE FLAG_DATA_FOR_PROPERTY 1.1786 +#include "nsCSSPropList.h" 1.1787 +#undef CSS_PROP_TABLE 1.1788 +}; 1.1789 + 1.1790 +static const uint32_t gTableBorderFlags[] = { 1.1791 +#define CSS_PROP_TABLEBORDER FLAG_DATA_FOR_PROPERTY 1.1792 +#include "nsCSSPropList.h" 1.1793 +#undef CSS_PROP_TABLEBORDER 1.1794 +}; 1.1795 + 1.1796 +static const uint32_t gContentFlags[] = { 1.1797 +#define CSS_PROP_CONTENT FLAG_DATA_FOR_PROPERTY 1.1798 +#include "nsCSSPropList.h" 1.1799 +#undef CSS_PROP_CONTENT 1.1800 +}; 1.1801 + 1.1802 +static const uint32_t gQuotesFlags[] = { 1.1803 +#define CSS_PROP_QUOTES FLAG_DATA_FOR_PROPERTY 1.1804 +#include "nsCSSPropList.h" 1.1805 +#undef CSS_PROP_QUOTES 1.1806 +}; 1.1807 + 1.1808 +static const uint32_t gTextFlags[] = { 1.1809 +#define CSS_PROP_TEXT FLAG_DATA_FOR_PROPERTY 1.1810 +#include "nsCSSPropList.h" 1.1811 +#undef CSS_PROP_TEXT 1.1812 +}; 1.1813 + 1.1814 +static const uint32_t gTextResetFlags[] = { 1.1815 +#define CSS_PROP_TEXTRESET FLAG_DATA_FOR_PROPERTY 1.1816 +#include "nsCSSPropList.h" 1.1817 +#undef CSS_PROP_TEXTRESET 1.1818 +}; 1.1819 + 1.1820 +static const uint32_t gUserInterfaceFlags[] = { 1.1821 +#define CSS_PROP_USERINTERFACE FLAG_DATA_FOR_PROPERTY 1.1822 +#include "nsCSSPropList.h" 1.1823 +#undef CSS_PROP_USERINTERFACE 1.1824 +}; 1.1825 + 1.1826 +static const uint32_t gUIResetFlags[] = { 1.1827 +#define CSS_PROP_UIRESET FLAG_DATA_FOR_PROPERTY 1.1828 +#include "nsCSSPropList.h" 1.1829 +#undef CSS_PROP_UIRESET 1.1830 +}; 1.1831 + 1.1832 +static const uint32_t gXULFlags[] = { 1.1833 +#define CSS_PROP_XUL FLAG_DATA_FOR_PROPERTY 1.1834 +#include "nsCSSPropList.h" 1.1835 +#undef CSS_PROP_XUL 1.1836 +}; 1.1837 + 1.1838 +static const uint32_t gSVGFlags[] = { 1.1839 +#define CSS_PROP_SVG FLAG_DATA_FOR_PROPERTY 1.1840 +#include "nsCSSPropList.h" 1.1841 +#undef CSS_PROP_SVG 1.1842 +}; 1.1843 + 1.1844 +static const uint32_t gSVGResetFlags[] = { 1.1845 +#define CSS_PROP_SVGRESET FLAG_DATA_FOR_PROPERTY 1.1846 +#include "nsCSSPropList.h" 1.1847 +#undef CSS_PROP_SVGRESET 1.1848 +}; 1.1849 + 1.1850 +static const uint32_t gColumnFlags[] = { 1.1851 +#define CSS_PROP_COLUMN FLAG_DATA_FOR_PROPERTY 1.1852 +#include "nsCSSPropList.h" 1.1853 +#undef CSS_PROP_COLUMN 1.1854 +}; 1.1855 + 1.1856 +// There are no properties in nsStyleVariables, but we can't have a 1.1857 +// zero length array. 1.1858 +static const uint32_t gVariablesFlags[] = { 1.1859 + 0, 1.1860 +#define CSS_PROP_VARIABLES FLAG_DATA_FOR_PROPERTY 1.1861 +#include "nsCSSPropList.h" 1.1862 +#undef CSS_PROP_VARIABLES 1.1863 +}; 1.1864 +static_assert(sizeof(gVariablesFlags) == sizeof(uint32_t), 1.1865 + "if nsStyleVariables has properties now you can remove the dummy " 1.1866 + "gVariablesFlags entry"); 1.1867 + 1.1868 +#undef FLAG_DATA_FOR_PROPERTY 1.1869 + 1.1870 +static const uint32_t* gFlagsByStruct[] = { 1.1871 + 1.1872 +#define STYLE_STRUCT(name, checkdata_cb) \ 1.1873 + g##name##Flags, 1.1874 +#include "nsStyleStructList.h" 1.1875 +#undef STYLE_STRUCT 1.1876 + 1.1877 +}; 1.1878 + 1.1879 +static const CheckCallbackFn gCheckCallbacks[] = { 1.1880 + 1.1881 +#define STYLE_STRUCT(name, checkdata_cb) \ 1.1882 + checkdata_cb, 1.1883 +#include "nsStyleStructList.h" 1.1884 +#undef STYLE_STRUCT 1.1885 + 1.1886 +}; 1.1887 + 1.1888 +#ifdef DEBUG 1.1889 +static bool 1.1890 +AreAllMathMLPropertiesUndefined(const nsRuleData* aRuleData) 1.1891 +{ 1.1892 + return 1.1893 + aRuleData->ValueForScriptLevel()->GetUnit() == eCSSUnit_Null && 1.1894 + aRuleData->ValueForScriptSizeMultiplier()->GetUnit() == eCSSUnit_Null && 1.1895 + aRuleData->ValueForScriptMinSize()->GetUnit() == eCSSUnit_Null && 1.1896 + aRuleData->ValueForMathVariant()->GetUnit() == eCSSUnit_Null && 1.1897 + aRuleData->ValueForMathDisplay()->GetUnit() == eCSSUnit_Null; 1.1898 +} 1.1899 +#endif 1.1900 + 1.1901 +inline nsRuleNode::RuleDetail 1.1902 +nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID, 1.1903 + const nsRuleData* aRuleData) 1.1904 +{ 1.1905 + // Build a count of the: 1.1906 + uint32_t total = 0, // total number of props in the struct 1.1907 + specified = 0, // number that were specified for this node 1.1908 + inherited = 0, // number that were 'inherit' (and not 1.1909 + // eCSSUnit_Inherit) for this node 1.1910 + unset = 0; // number that were 'unset' 1.1911 + 1.1912 + // See comment in nsRuleData.h above mValueOffsets. 1.1913 + NS_ABORT_IF_FALSE(aRuleData->mValueOffsets[aSID] == 0, 1.1914 + "we assume the value offset is zero instead of adding it"); 1.1915 + for (nsCSSValue *values = aRuleData->mValueStorage, 1.1916 + *values_end = values + nsCSSProps::PropertyCountInStruct(aSID); 1.1917 + values != values_end; ++values) { 1.1918 + ++total; 1.1919 + ExamineCSSValue(*values, specified, inherited, unset); 1.1920 + } 1.1921 + 1.1922 + if (!nsCachedStyleData::IsReset(aSID)) { 1.1923 + // For inherited properties, 'unset' means the same as 'inherit'. 1.1924 + inherited += unset; 1.1925 + unset = 0; 1.1926 + } 1.1927 + 1.1928 +#if 0 1.1929 + printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n", 1.1930 + aSID, total, specified, inherited); 1.1931 +#endif 1.1932 + 1.1933 + NS_ASSERTION(aSID != eStyleStruct_Font || 1.1934 + mPresContext->Document()->GetMathMLEnabled() || 1.1935 + AreAllMathMLPropertiesUndefined(aRuleData), 1.1936 + "MathML style property was defined even though MathML is disabled"); 1.1937 + 1.1938 + /* 1.1939 + * Return the most specific information we can: prefer None or Full 1.1940 + * over Partial, and Reset or Inherited over Mixed, since we can 1.1941 + * optimize based on the edge cases and not the in-between cases. 1.1942 + */ 1.1943 + nsRuleNode::RuleDetail result; 1.1944 + if (inherited == total) 1.1945 + result = eRuleFullInherited; 1.1946 + else if (specified == total 1.1947 + // MathML defines 5 properties in Font that will never be set when 1.1948 + // MathML is not in use. Therefore if all but five 1.1949 + // properties have been set, and MathML is not enabled, we can treat 1.1950 + // this as fully specified. Code in nsMathMLElementFactory will 1.1951 + // rebuild the rule tree and style data when MathML is first enabled 1.1952 + // (see nsMathMLElement::BindToTree). 1.1953 + || (aSID == eStyleStruct_Font && specified + 5 == total && 1.1954 + !mPresContext->Document()->GetMathMLEnabled()) 1.1955 + ) { 1.1956 + if (inherited == 0) 1.1957 + result = eRuleFullReset; 1.1958 + else 1.1959 + result = eRuleFullMixed; 1.1960 + } else if (specified == 0) 1.1961 + result = eRuleNone; 1.1962 + else if (specified == inherited) 1.1963 + result = eRulePartialInherited; 1.1964 + else if (inherited == 0) 1.1965 + result = eRulePartialReset; 1.1966 + else 1.1967 + result = eRulePartialMixed; 1.1968 + 1.1969 + CheckCallbackFn cb = gCheckCallbacks[aSID]; 1.1970 + if (cb) { 1.1971 + result = (*cb)(aRuleData, result); 1.1972 + } 1.1973 + 1.1974 + return result; 1.1975 +} 1.1976 + 1.1977 +// If we need to restrict which properties apply to the style context, 1.1978 +// return the bit to check in nsCSSProp's flags table. Otherwise, 1.1979 +// return 0. 1.1980 +inline uint32_t 1.1981 +GetPseudoRestriction(nsStyleContext *aContext) 1.1982 +{ 1.1983 + // This needs to match nsStyleSet::WalkRestrictionRule. 1.1984 + uint32_t pseudoRestriction = 0; 1.1985 + nsIAtom *pseudoType = aContext->GetPseudo(); 1.1986 + if (pseudoType) { 1.1987 + if (pseudoType == nsCSSPseudoElements::firstLetter) { 1.1988 + pseudoRestriction = CSS_PROPERTY_APPLIES_TO_FIRST_LETTER; 1.1989 + } else if (pseudoType == nsCSSPseudoElements::firstLine) { 1.1990 + pseudoRestriction = CSS_PROPERTY_APPLIES_TO_FIRST_LINE; 1.1991 + } else if (pseudoType == nsCSSPseudoElements::mozPlaceholder) { 1.1992 + pseudoRestriction = CSS_PROPERTY_APPLIES_TO_PLACEHOLDER; 1.1993 + } 1.1994 + } 1.1995 + return pseudoRestriction; 1.1996 +} 1.1997 + 1.1998 +static void 1.1999 +UnsetPropertiesWithoutFlags(const nsStyleStructID aSID, 1.2000 + nsRuleData* aRuleData, 1.2001 + uint32_t aFlags) 1.2002 +{ 1.2003 + NS_ASSERTION(aFlags != 0, "aFlags must be nonzero"); 1.2004 + 1.2005 + const uint32_t *flagData = gFlagsByStruct[aSID]; 1.2006 + 1.2007 + // See comment in nsRuleData.h above mValueOffsets. 1.2008 + NS_ABORT_IF_FALSE(aRuleData->mValueOffsets[aSID] == 0, 1.2009 + "we assume the value offset is zero instead of adding it"); 1.2010 + nsCSSValue *values = aRuleData->mValueStorage; 1.2011 + 1.2012 + for (size_t i = 0, i_end = nsCSSProps::PropertyCountInStruct(aSID); 1.2013 + i != i_end; ++i) { 1.2014 + if ((flagData[i] & aFlags) != aFlags) 1.2015 + values[i].Reset(); 1.2016 + } 1.2017 +} 1.2018 + 1.2019 +/** 1.2020 + * We allocate arrays of CSS values with alloca. (These arrays are a 1.2021 + * fixed size per style struct, but we don't want to waste the 1.2022 + * allocation and construction/destruction costs of the big structs when 1.2023 + * we're handling much smaller ones.) Since the lifetime of an alloca 1.2024 + * allocation is the life of the calling function, the caller must call 1.2025 + * alloca. However, to ensure that constructors and destructors are 1.2026 + * balanced, we do the constructor and destructor calling from this RAII 1.2027 + * class, AutoCSSValueArray. 1.2028 + */ 1.2029 +struct AutoCSSValueArray { 1.2030 + /** 1.2031 + * aStorage must be the result of alloca(aCount * sizeof(nsCSSValue)) 1.2032 + */ 1.2033 + AutoCSSValueArray(void* aStorage, size_t aCount) { 1.2034 + NS_ABORT_IF_FALSE(size_t(aStorage) % NS_ALIGNMENT_OF(nsCSSValue) == 0, 1.2035 + "bad alignment from alloca"); 1.2036 + mCount = aCount; 1.2037 + // Don't use placement new[], since it might store extra data 1.2038 + // for the count (on Windows!). 1.2039 + mArray = static_cast<nsCSSValue*>(aStorage); 1.2040 + for (size_t i = 0; i < mCount; ++i) { 1.2041 + new (mArray + i) nsCSSValue(); 1.2042 + } 1.2043 + } 1.2044 + 1.2045 + ~AutoCSSValueArray() { 1.2046 + for (size_t i = 0; i < mCount; ++i) { 1.2047 + mArray[i].~nsCSSValue(); 1.2048 + } 1.2049 + } 1.2050 + 1.2051 + nsCSSValue* get() { return mArray; } 1.2052 + 1.2053 +private: 1.2054 + nsCSSValue *mArray; 1.2055 + size_t mCount; 1.2056 +}; 1.2057 + 1.2058 +/* static */ bool 1.2059 +nsRuleNode::ResolveVariableReferences(const nsStyleStructID aSID, 1.2060 + nsRuleData* aRuleData, 1.2061 + nsStyleContext* aContext) 1.2062 +{ 1.2063 + MOZ_ASSERT(aSID != eStyleStruct_Variables); 1.2064 + MOZ_ASSERT(aRuleData->mSIDs & nsCachedStyleData::GetBitForSID(aSID)); 1.2065 + MOZ_ASSERT(aRuleData->mValueOffsets[aSID] == 0); 1.2066 + 1.2067 + nsCSSParser parser; 1.2068 + bool anyTokenStreams = false; 1.2069 + 1.2070 + // Look at each property in the nsRuleData for the given style struct. 1.2071 + size_t nprops = nsCSSProps::PropertyCountInStruct(aSID); 1.2072 + for (nsCSSValue* value = aRuleData->mValueStorage, 1.2073 + *values_end = aRuleData->mValueStorage + nprops; 1.2074 + value != values_end; value++) { 1.2075 + if (value->GetUnit() != eCSSUnit_TokenStream) { 1.2076 + continue; 1.2077 + } 1.2078 + 1.2079 + const CSSVariableValues* variables = 1.2080 + &aContext->StyleVariables()->mVariables; 1.2081 + nsCSSValueTokenStream* tokenStream = value->GetTokenStreamValue(); 1.2082 + 1.2083 + // Note that ParsePropertyWithVariableReferences relies on the fact 1.2084 + // that the nsCSSValue in aRuleData for the property we are re-parsing 1.2085 + // is still the token stream value. When 1.2086 + // ParsePropertyWithVariableReferences calls 1.2087 + // nsCSSExpandedDataBlock::MapRuleInfoInto, that function will add 1.2088 + // the ImageValue that is created into the token stream object's 1.2089 + // mImageValues table; see the comment above mImageValues for why. 1.2090 + 1.2091 + // XXX Should pass in sheet here (see bug 952338). 1.2092 + parser.ParsePropertyWithVariableReferences( 1.2093 + tokenStream->mPropertyID, tokenStream->mShorthandPropertyID, 1.2094 + tokenStream->mTokenStream, variables, aRuleData, 1.2095 + tokenStream->mSheetURI, tokenStream->mBaseURI, 1.2096 + tokenStream->mSheetPrincipal, nullptr, 1.2097 + tokenStream->mLineNumber, tokenStream->mLineOffset); 1.2098 + aRuleData->mCanStoreInRuleTree = false; 1.2099 + anyTokenStreams = true; 1.2100 + } 1.2101 + 1.2102 + return anyTokenStreams; 1.2103 +} 1.2104 + 1.2105 +const void* 1.2106 +nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, 1.2107 + nsStyleContext* aContext) 1.2108 +{ 1.2109 + // use placement new[] on the result of alloca() to allocate a 1.2110 + // variable-sized stack array, including execution of constructors, 1.2111 + // and use an RAII class to run the destructors too. 1.2112 + size_t nprops = nsCSSProps::PropertyCountInStruct(aSID); 1.2113 + void* dataStorage = alloca(nprops * sizeof(nsCSSValue)); 1.2114 + AutoCSSValueArray dataArray(dataStorage, nprops); 1.2115 + 1.2116 + nsRuleData ruleData(nsCachedStyleData::GetBitForSID(aSID), 1.2117 + dataArray.get(), mPresContext, aContext); 1.2118 + ruleData.mValueOffsets[aSID] = 0; 1.2119 + 1.2120 + // We start at the most specific rule in the tree. 1.2121 + void* startStruct = nullptr; 1.2122 + 1.2123 + nsRuleNode* ruleNode = this; 1.2124 + nsRuleNode* highestNode = nullptr; // The highest node in the rule tree 1.2125 + // that has the same properties 1.2126 + // specified for struct |aSID| as 1.2127 + // |this| does. 1.2128 + nsRuleNode* rootNode = this; // After the loop below, this will be the 1.2129 + // highest node that we've walked without 1.2130 + // finding cached data on the rule tree. 1.2131 + // If we don't find any cached data, it 1.2132 + // will be the root. (XXX misnamed) 1.2133 + RuleDetail detail = eRuleNone; 1.2134 + uint32_t bit = nsCachedStyleData::GetBitForSID(aSID); 1.2135 + 1.2136 + while (ruleNode) { 1.2137 + // See if this rule node has cached the fact that the remaining 1.2138 + // nodes along this path specify no data whatsoever. 1.2139 + if (ruleNode->mNoneBits & bit) 1.2140 + break; 1.2141 + 1.2142 + // If the dependent bit is set on a rule node for this struct, that 1.2143 + // means its rule won't have any information to add, so skip it. 1.2144 + // NOTE: If we exit the loop because of the !IsUsedDirectly() check, 1.2145 + // then we're guaranteed to break immediately afterwards due to a 1.2146 + // non-null startStruct. 1.2147 + while ((ruleNode->mDependentBits & bit) && !ruleNode->IsUsedDirectly()) { 1.2148 + NS_ASSERTION(ruleNode->mStyleData.GetStyleData(aSID) == nullptr, 1.2149 + "dependent bit with cached data makes no sense"); 1.2150 + // Climb up to the next rule in the tree (a less specific rule). 1.2151 + rootNode = ruleNode; 1.2152 + ruleNode = ruleNode->mParent; 1.2153 + NS_ASSERTION(!(ruleNode->mNoneBits & bit), "can't have both bits set"); 1.2154 + } 1.2155 + 1.2156 + // Check for cached data after the inner loop above -- otherwise 1.2157 + // we'll miss it. 1.2158 + startStruct = ruleNode->mStyleData.GetStyleData(aSID); 1.2159 + if (startStruct) 1.2160 + break; // We found a rule with fully specified data. We don't 1.2161 + // need to go up the tree any further, since the remainder 1.2162 + // of this branch has already been computed. 1.2163 + 1.2164 + // Ask the rule to fill in the properties that it specifies. 1.2165 + nsIStyleRule *rule = ruleNode->mRule; 1.2166 + if (rule) { 1.2167 + ruleData.mLevel = ruleNode->GetLevel(); 1.2168 + ruleData.mIsImportantRule = ruleNode->IsImportantRule(); 1.2169 + rule->MapRuleInfoInto(&ruleData); 1.2170 + } 1.2171 + 1.2172 + // Now we check to see how many properties have been specified by 1.2173 + // the rules we've examined so far. 1.2174 + RuleDetail oldDetail = detail; 1.2175 + detail = CheckSpecifiedProperties(aSID, &ruleData); 1.2176 + 1.2177 + if (oldDetail == eRuleNone && detail != eRuleNone) 1.2178 + highestNode = ruleNode; 1.2179 + 1.2180 + if (detail == eRuleFullReset || 1.2181 + detail == eRuleFullMixed || 1.2182 + detail == eRuleFullInherited) 1.2183 + break; // We don't need to examine any more rules. All properties 1.2184 + // have been fully specified. 1.2185 + 1.2186 + // Climb up to the next rule in the tree (a less specific rule). 1.2187 + rootNode = ruleNode; 1.2188 + ruleNode = ruleNode->mParent; 1.2189 + } 1.2190 + 1.2191 + bool recomputeDetail = false; 1.2192 + 1.2193 + // If we are computing a style struct other than nsStyleVariables, and 1.2194 + // ruleData has any properties with variable references (nsCSSValues of 1.2195 + // type eCSSUnit_TokenStream), then we need to resolve these. 1.2196 + if (aSID != eStyleStruct_Variables) { 1.2197 + // A property's value might have became 'inherit' after resolving 1.2198 + // variable references. (This happens when an inherited property 1.2199 + // fails to parse its resolved value.) We need to recompute 1.2200 + // |detail| in case this happened. 1.2201 + recomputeDetail = ResolveVariableReferences(aSID, &ruleData, aContext); 1.2202 + } 1.2203 + 1.2204 + // If needed, unset the properties that don't have a flag that allows 1.2205 + // them to be set for this style context. (For example, only some 1.2206 + // properties apply to :first-line and :first-letter.) 1.2207 + uint32_t pseudoRestriction = GetPseudoRestriction(aContext); 1.2208 + if (pseudoRestriction) { 1.2209 + UnsetPropertiesWithoutFlags(aSID, &ruleData, pseudoRestriction); 1.2210 + 1.2211 + // We need to recompute |detail| based on the restrictions we just applied. 1.2212 + // We can adjust |detail| arbitrarily because of the restriction 1.2213 + // rule added in nsStyleSet::WalkRestrictionRule. 1.2214 + recomputeDetail = true; 1.2215 + } 1.2216 + 1.2217 + if (recomputeDetail) { 1.2218 + detail = CheckSpecifiedProperties(aSID, &ruleData); 1.2219 + } 1.2220 + 1.2221 + NS_ASSERTION(!startStruct || (detail != eRuleFullReset && 1.2222 + detail != eRuleFullMixed && 1.2223 + detail != eRuleFullInherited), 1.2224 + "can't have start struct and be fully specified"); 1.2225 + 1.2226 + bool isReset = nsCachedStyleData::IsReset(aSID); 1.2227 + if (!highestNode) 1.2228 + highestNode = rootNode; 1.2229 + 1.2230 + if (!ruleData.mCanStoreInRuleTree) 1.2231 + detail = eRulePartialMixed; // Treat as though some data is specified to avoid 1.2232 + // the optimizations and force data computation. 1.2233 + 1.2234 + if (detail == eRuleNone && startStruct) { 1.2235 + // We specified absolutely no rule information, but a parent rule in the tree 1.2236 + // specified all the rule information. We set a bit along the branch from our 1.2237 + // node in the tree to the node that specified the data that tells nodes on that 1.2238 + // branch that they never need to examine their rules for this particular struct type 1.2239 + // ever again. 1.2240 + PropagateDependentBit(aSID, ruleNode, startStruct); 1.2241 + return startStruct; 1.2242 + } 1.2243 + if ((!startStruct && !isReset && 1.2244 + (detail == eRuleNone || detail == eRulePartialInherited)) || 1.2245 + detail == eRuleFullInherited) { 1.2246 + // We specified no non-inherited information and neither did any of 1.2247 + // our parent rules. 1.2248 + 1.2249 + // We set a bit along the branch from the highest node (ruleNode) 1.2250 + // down to our node (this) indicating that no non-inherited data was 1.2251 + // specified. This bit is guaranteed to be set already on the path 1.2252 + // from the highest node to the root node in the case where 1.2253 + // (detail == eRuleNone), which is the most common case here. 1.2254 + // We must check |!isReset| because the Compute*Data functions for 1.2255 + // reset structs wouldn't handle none bits correctly. 1.2256 + if (highestNode != this && !isReset) 1.2257 + PropagateNoneBit(bit, highestNode); 1.2258 + 1.2259 + // All information must necessarily be inherited from our parent style context. 1.2260 + // In the absence of any computed data in the rule tree and with 1.2261 + // no rules specified that didn't have values of 'inherit', we should check our parent. 1.2262 + nsStyleContext* parentContext = aContext->GetParent(); 1.2263 + if (isReset) { 1.2264 + /* Reset structs don't inherit from first-line. */ 1.2265 + /* See similar code in COMPUTE_START_RESET */ 1.2266 + while (parentContext && 1.2267 + parentContext->GetPseudo() == nsCSSPseudoElements::firstLine) { 1.2268 + parentContext = parentContext->GetParent(); 1.2269 + } 1.2270 + } 1.2271 + if (parentContext) { 1.2272 + // We have a parent, and so we should just inherit from the parent. 1.2273 + // Set the inherit bits on our context. These bits tell the style context that 1.2274 + // it never has to go back to the rule tree for data. Instead the style context tree 1.2275 + // should be walked to find the data. 1.2276 + const void* parentStruct = parentContext->StyleData(aSID); 1.2277 + aContext->AddStyleBit(bit); // makes const_cast OK. 1.2278 + aContext->SetStyle(aSID, const_cast<void*>(parentStruct)); 1.2279 + return parentStruct; 1.2280 + } 1.2281 + else 1.2282 + // We are the root. In the case of fonts, the default values just 1.2283 + // come from the pres context. 1.2284 + return SetDefaultOnRoot(aSID, aContext); 1.2285 + } 1.2286 + 1.2287 + // We need to compute the data from the information that the rules specified. 1.2288 + const void* res; 1.2289 +#define STYLE_STRUCT_TEST aSID 1.2290 +#define STYLE_STRUCT(name, checkdata_cb) \ 1.2291 + res = Compute##name##Data(startStruct, &ruleData, aContext, \ 1.2292 + highestNode, detail, ruleData.mCanStoreInRuleTree); 1.2293 +#include "nsStyleStructList.h" 1.2294 +#undef STYLE_STRUCT 1.2295 +#undef STYLE_STRUCT_TEST 1.2296 + 1.2297 + // Now return the result. 1.2298 + return res; 1.2299 +} 1.2300 + 1.2301 +const void* 1.2302 +nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID, nsStyleContext* aContext) 1.2303 +{ 1.2304 + switch (aSID) { 1.2305 + case eStyleStruct_Font: 1.2306 + { 1.2307 + nsStyleFont* fontData = new (mPresContext) nsStyleFont(mPresContext); 1.2308 + nscoord minimumFontSize = mPresContext->MinFontSize(fontData->mLanguage); 1.2309 + 1.2310 + if (minimumFontSize > 0 && !mPresContext->IsChrome()) { 1.2311 + fontData->mFont.size = std::max(fontData->mSize, minimumFontSize); 1.2312 + } 1.2313 + else { 1.2314 + fontData->mFont.size = fontData->mSize; 1.2315 + } 1.2316 + aContext->SetStyle(eStyleStruct_Font, fontData); 1.2317 + return fontData; 1.2318 + } 1.2319 + case eStyleStruct_Display: 1.2320 + { 1.2321 + nsStyleDisplay* disp = new (mPresContext) nsStyleDisplay(); 1.2322 + aContext->SetStyle(eStyleStruct_Display, disp); 1.2323 + return disp; 1.2324 + } 1.2325 + case eStyleStruct_Visibility: 1.2326 + { 1.2327 + nsStyleVisibility* vis = new (mPresContext) nsStyleVisibility(mPresContext); 1.2328 + aContext->SetStyle(eStyleStruct_Visibility, vis); 1.2329 + return vis; 1.2330 + } 1.2331 + case eStyleStruct_Text: 1.2332 + { 1.2333 + nsStyleText* text = new (mPresContext) nsStyleText(); 1.2334 + aContext->SetStyle(eStyleStruct_Text, text); 1.2335 + return text; 1.2336 + } 1.2337 + case eStyleStruct_TextReset: 1.2338 + { 1.2339 + nsStyleTextReset* text = new (mPresContext) nsStyleTextReset(); 1.2340 + aContext->SetStyle(eStyleStruct_TextReset, text); 1.2341 + return text; 1.2342 + } 1.2343 + case eStyleStruct_Color: 1.2344 + { 1.2345 + nsStyleColor* color = new (mPresContext) nsStyleColor(mPresContext); 1.2346 + aContext->SetStyle(eStyleStruct_Color, color); 1.2347 + return color; 1.2348 + } 1.2349 + case eStyleStruct_Background: 1.2350 + { 1.2351 + nsStyleBackground* bg = new (mPresContext) nsStyleBackground(); 1.2352 + aContext->SetStyle(eStyleStruct_Background, bg); 1.2353 + return bg; 1.2354 + } 1.2355 + case eStyleStruct_Margin: 1.2356 + { 1.2357 + nsStyleMargin* margin = new (mPresContext) nsStyleMargin(); 1.2358 + aContext->SetStyle(eStyleStruct_Margin, margin); 1.2359 + return margin; 1.2360 + } 1.2361 + case eStyleStruct_Border: 1.2362 + { 1.2363 + nsStyleBorder* border = new (mPresContext) nsStyleBorder(mPresContext); 1.2364 + aContext->SetStyle(eStyleStruct_Border, border); 1.2365 + return border; 1.2366 + } 1.2367 + case eStyleStruct_Padding: 1.2368 + { 1.2369 + nsStylePadding* padding = new (mPresContext) nsStylePadding(); 1.2370 + aContext->SetStyle(eStyleStruct_Padding, padding); 1.2371 + return padding; 1.2372 + } 1.2373 + case eStyleStruct_Outline: 1.2374 + { 1.2375 + nsStyleOutline* outline = new (mPresContext) nsStyleOutline(mPresContext); 1.2376 + aContext->SetStyle(eStyleStruct_Outline, outline); 1.2377 + return outline; 1.2378 + } 1.2379 + case eStyleStruct_List: 1.2380 + { 1.2381 + nsStyleList* list = new (mPresContext) nsStyleList(); 1.2382 + aContext->SetStyle(eStyleStruct_List, list); 1.2383 + return list; 1.2384 + } 1.2385 + case eStyleStruct_Position: 1.2386 + { 1.2387 + nsStylePosition* pos = new (mPresContext) nsStylePosition(); 1.2388 + aContext->SetStyle(eStyleStruct_Position, pos); 1.2389 + return pos; 1.2390 + } 1.2391 + case eStyleStruct_Table: 1.2392 + { 1.2393 + nsStyleTable* table = new (mPresContext) nsStyleTable(); 1.2394 + aContext->SetStyle(eStyleStruct_Table, table); 1.2395 + return table; 1.2396 + } 1.2397 + case eStyleStruct_TableBorder: 1.2398 + { 1.2399 + nsStyleTableBorder* table = new (mPresContext) nsStyleTableBorder(mPresContext); 1.2400 + aContext->SetStyle(eStyleStruct_TableBorder, table); 1.2401 + return table; 1.2402 + } 1.2403 + case eStyleStruct_Content: 1.2404 + { 1.2405 + nsStyleContent* content = new (mPresContext) nsStyleContent(); 1.2406 + aContext->SetStyle(eStyleStruct_Content, content); 1.2407 + return content; 1.2408 + } 1.2409 + case eStyleStruct_Quotes: 1.2410 + { 1.2411 + nsStyleQuotes* quotes = new (mPresContext) nsStyleQuotes(); 1.2412 + aContext->SetStyle(eStyleStruct_Quotes, quotes); 1.2413 + return quotes; 1.2414 + } 1.2415 + case eStyleStruct_UserInterface: 1.2416 + { 1.2417 + nsStyleUserInterface* ui = new (mPresContext) nsStyleUserInterface(); 1.2418 + aContext->SetStyle(eStyleStruct_UserInterface, ui); 1.2419 + return ui; 1.2420 + } 1.2421 + case eStyleStruct_UIReset: 1.2422 + { 1.2423 + nsStyleUIReset* ui = new (mPresContext) nsStyleUIReset(); 1.2424 + aContext->SetStyle(eStyleStruct_UIReset, ui); 1.2425 + return ui; 1.2426 + } 1.2427 + case eStyleStruct_XUL: 1.2428 + { 1.2429 + nsStyleXUL* xul = new (mPresContext) nsStyleXUL(); 1.2430 + aContext->SetStyle(eStyleStruct_XUL, xul); 1.2431 + return xul; 1.2432 + } 1.2433 + case eStyleStruct_Column: 1.2434 + { 1.2435 + nsStyleColumn* column = new (mPresContext) nsStyleColumn(mPresContext); 1.2436 + aContext->SetStyle(eStyleStruct_Column, column); 1.2437 + return column; 1.2438 + } 1.2439 + case eStyleStruct_SVG: 1.2440 + { 1.2441 + nsStyleSVG* svg = new (mPresContext) nsStyleSVG(); 1.2442 + aContext->SetStyle(eStyleStruct_SVG, svg); 1.2443 + return svg; 1.2444 + } 1.2445 + case eStyleStruct_SVGReset: 1.2446 + { 1.2447 + nsStyleSVGReset* svgReset = new (mPresContext) nsStyleSVGReset(); 1.2448 + aContext->SetStyle(eStyleStruct_SVGReset, svgReset); 1.2449 + return svgReset; 1.2450 + } 1.2451 + case eStyleStruct_Variables: 1.2452 + { 1.2453 + nsStyleVariables* vars = new (mPresContext) nsStyleVariables(); 1.2454 + aContext->SetStyle(eStyleStruct_Variables, vars); 1.2455 + return vars; 1.2456 + } 1.2457 + default: 1.2458 + /* 1.2459 + * unhandled case: nsStyleStructID_Length. 1.2460 + * last item of nsStyleStructID, to know its length. 1.2461 + */ 1.2462 + NS_ABORT_IF_FALSE(false, "unexpected SID"); 1.2463 + return nullptr; 1.2464 + } 1.2465 + return nullptr; 1.2466 +} 1.2467 + 1.2468 +/* 1.2469 + * This function handles cascading of *-left or *-right box properties 1.2470 + * against *-start (which is L for LTR and R for RTL) or *-end (which is 1.2471 + * R for LTR and L for RTL). 1.2472 + * 1.2473 + * Cascading these properties correctly is hard because we need to 1.2474 + * cascade two properties as one, but which two properties depends on a 1.2475 + * third property ('direction'). We solve this by treating each of 1.2476 + * these properties (say, 'margin-start') as a shorthand that sets a 1.2477 + * property containing the value of the property specified 1.2478 + * ('margin-start-value') and sets a pair of properties 1.2479 + * ('margin-left-ltr-source' and 'margin-right-rtl-source') saying which 1.2480 + * of the properties we use. Thus, when we want to compute the value of 1.2481 + * 'margin-left' when 'direction' is 'ltr', we look at the value of 1.2482 + * 'margin-left-ltr-source', which tells us whether to use the highest 1.2483 + * 'margin-left' in the cascade or the highest 'margin-start'. 1.2484 + * 1.2485 + * Finally, since we can compute the normal (*-left and *-right) 1.2486 + * properties in a loop, this function works by modifying the data we 1.2487 + * will use in that loop (which the caller must copy from the const 1.2488 + * input). 1.2489 + */ 1.2490 +void 1.2491 +nsRuleNode::AdjustLogicalBoxProp(nsStyleContext* aContext, 1.2492 + const nsCSSValue& aLTRSource, 1.2493 + const nsCSSValue& aRTLSource, 1.2494 + const nsCSSValue& aLTRLogicalValue, 1.2495 + const nsCSSValue& aRTLLogicalValue, 1.2496 + mozilla::css::Side aSide, 1.2497 + nsCSSRect& aValueRect, 1.2498 + bool& aCanStoreInRuleTree) 1.2499 +{ 1.2500 + bool LTRlogical = aLTRSource.GetUnit() == eCSSUnit_Enumerated && 1.2501 + aLTRSource.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL; 1.2502 + bool RTLlogical = aRTLSource.GetUnit() == eCSSUnit_Enumerated && 1.2503 + aRTLSource.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL; 1.2504 + if (LTRlogical || RTLlogical) { 1.2505 + // We can't cache anything on the rule tree if we use any data from 1.2506 + // the style context, since data cached in the rule tree could be 1.2507 + // used with a style context with a different value. 1.2508 + aCanStoreInRuleTree = false; 1.2509 + uint8_t dir = aContext->StyleVisibility()->mDirection; 1.2510 + 1.2511 + if (dir == NS_STYLE_DIRECTION_LTR) { 1.2512 + if (LTRlogical) 1.2513 + aValueRect.*(nsCSSRect::sides[aSide]) = aLTRLogicalValue; 1.2514 + } else { 1.2515 + if (RTLlogical) 1.2516 + aValueRect.*(nsCSSRect::sides[aSide]) = aRTLLogicalValue; 1.2517 + } 1.2518 + } else if (aLTRLogicalValue.GetUnit() == eCSSUnit_Inherit || 1.2519 + aRTLLogicalValue.GetUnit() == eCSSUnit_Inherit) { 1.2520 + // It actually is valid to store this in the ruletree, since 1.2521 + // LTRlogical and RTLlogical are both false, but doing that will 1.2522 + // trigger asserts. Silence those. 1.2523 + aCanStoreInRuleTree = false; 1.2524 + } 1.2525 +} 1.2526 + 1.2527 +/** 1.2528 + * Begin an nsRuleNode::Compute*Data function for an inherited struct. 1.2529 + * 1.2530 + * @param type_ The nsStyle* type this function computes. 1.2531 + * @param ctorargs_ The arguments used for the default nsStyle* constructor. 1.2532 + * @param data_ Variable (declared here) holding the result of this 1.2533 + * function. 1.2534 + * @param parentdata_ Variable (declared here) holding the parent style 1.2535 + * context's data for this struct. 1.2536 + */ 1.2537 +#define COMPUTE_START_INHERITED(type_, ctorargs_, data_, parentdata_) \ 1.2538 + NS_ASSERTION(aRuleDetail != eRuleFullInherited, \ 1.2539 + "should not have bothered calling Compute*Data"); \ 1.2540 + \ 1.2541 + nsStyleContext* parentContext = aContext->GetParent(); \ 1.2542 + \ 1.2543 + nsStyle##type_* data_ = nullptr; \ 1.2544 + mozilla::Maybe<nsStyle##type_> maybeFakeParentData; \ 1.2545 + const nsStyle##type_* parentdata_ = nullptr; \ 1.2546 + bool canStoreInRuleTree = aCanStoreInRuleTree; \ 1.2547 + \ 1.2548 + /* If |canStoreInRuleTree| might be true by the time we're done, we */ \ 1.2549 + /* can't call parentContext->Style##type_() since it could recur into */ \ 1.2550 + /* setting the same struct on the same rule node, causing a leak. */ \ 1.2551 + if (aRuleDetail != eRuleFullReset && \ 1.2552 + (!aStartStruct || (aRuleDetail != eRulePartialReset && \ 1.2553 + aRuleDetail != eRuleNone))) { \ 1.2554 + if (parentContext) { \ 1.2555 + parentdata_ = parentContext->Style##type_(); \ 1.2556 + } else { \ 1.2557 + maybeFakeParentData.construct ctorargs_; \ 1.2558 + parentdata_ = maybeFakeParentData.addr(); \ 1.2559 + } \ 1.2560 + } \ 1.2561 + if (aStartStruct) \ 1.2562 + /* We only need to compute the delta between this computed data and */ \ 1.2563 + /* our computed data. */ \ 1.2564 + data_ = new (mPresContext) \ 1.2565 + nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \ 1.2566 + else { \ 1.2567 + if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) { \ 1.2568 + /* No question. We will have to inherit. Go ahead and init */ \ 1.2569 + /* with inherited vals from parent. */ \ 1.2570 + canStoreInRuleTree = false; \ 1.2571 + if (parentdata_) \ 1.2572 + data_ = new (mPresContext) nsStyle##type_(*parentdata_); \ 1.2573 + else \ 1.2574 + data_ = new (mPresContext) nsStyle##type_ ctorargs_; \ 1.2575 + } \ 1.2576 + else \ 1.2577 + data_ = new (mPresContext) nsStyle##type_ ctorargs_; \ 1.2578 + } \ 1.2579 + \ 1.2580 + if (!parentdata_) \ 1.2581 + parentdata_ = data_; 1.2582 + 1.2583 +/** 1.2584 + * Begin an nsRuleNode::Compute*Data function for a reset struct. 1.2585 + * 1.2586 + * @param type_ The nsStyle* type this function computes. 1.2587 + * @param ctorargs_ The arguments used for the default nsStyle* constructor. 1.2588 + * @param data_ Variable (declared here) holding the result of this 1.2589 + * function. 1.2590 + * @param parentdata_ Variable (declared here) holding the parent style 1.2591 + * context's data for this struct. 1.2592 + */ 1.2593 +#define COMPUTE_START_RESET(type_, ctorargs_, data_, parentdata_) \ 1.2594 + NS_ASSERTION(aRuleDetail != eRuleFullInherited, \ 1.2595 + "should not have bothered calling Compute*Data"); \ 1.2596 + \ 1.2597 + nsStyleContext* parentContext = aContext->GetParent(); \ 1.2598 + /* Reset structs don't inherit from first-line */ \ 1.2599 + /* See similar code in WalkRuleTree */ \ 1.2600 + while (parentContext && \ 1.2601 + parentContext->GetPseudo() == nsCSSPseudoElements::firstLine) { \ 1.2602 + parentContext = parentContext->GetParent(); \ 1.2603 + } \ 1.2604 + \ 1.2605 + nsStyle##type_* data_; \ 1.2606 + if (aStartStruct) \ 1.2607 + /* We only need to compute the delta between this computed data and */ \ 1.2608 + /* our computed data. */ \ 1.2609 + data_ = new (mPresContext) \ 1.2610 + nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \ 1.2611 + else \ 1.2612 + data_ = new (mPresContext) nsStyle##type_ ctorargs_; \ 1.2613 + \ 1.2614 + /* If |canStoreInRuleTree| might be true by the time we're done, we */ \ 1.2615 + /* can't call parentContext->Style##type_() since it could recur into */ \ 1.2616 + /* setting the same struct on the same rule node, causing a leak. */ \ 1.2617 + mozilla::Maybe<nsStyle##type_> maybeFakeParentData; \ 1.2618 + const nsStyle##type_* parentdata_ = data_; \ 1.2619 + if (aRuleDetail != eRuleFullReset && \ 1.2620 + aRuleDetail != eRulePartialReset && \ 1.2621 + aRuleDetail != eRuleNone) { \ 1.2622 + if (parentContext) { \ 1.2623 + parentdata_ = parentContext->Style##type_(); \ 1.2624 + } else { \ 1.2625 + maybeFakeParentData.construct ctorargs_; \ 1.2626 + parentdata_ = maybeFakeParentData.addr(); \ 1.2627 + } \ 1.2628 + } \ 1.2629 + bool canStoreInRuleTree = aCanStoreInRuleTree; 1.2630 + 1.2631 +/** 1.2632 + * End an nsRuleNode::Compute*Data function for an inherited struct. 1.2633 + * 1.2634 + * @param type_ The nsStyle* type this function computes. 1.2635 + * @param data_ Variable holding the result of this function. 1.2636 + */ 1.2637 +#define COMPUTE_END_INHERITED(type_, data_) \ 1.2638 + NS_POSTCONDITION(!canStoreInRuleTree || aRuleDetail == eRuleFullReset || \ 1.2639 + (aStartStruct && aRuleDetail == eRulePartialReset), \ 1.2640 + "canStoreInRuleTree must be false for inherited structs " \ 1.2641 + "unless all properties have been specified with values " \ 1.2642 + "other than inherit"); \ 1.2643 + if (canStoreInRuleTree) { \ 1.2644 + /* We were fully specified and can therefore be cached right on the */ \ 1.2645 + /* rule node. */ \ 1.2646 + if (!aHighestNode->mStyleData.mInheritedData) { \ 1.2647 + aHighestNode->mStyleData.mInheritedData = \ 1.2648 + new (mPresContext) nsInheritedStyleData; \ 1.2649 + } \ 1.2650 + NS_ASSERTION(!aHighestNode->mStyleData.mInheritedData-> \ 1.2651 + mStyleStructs[eStyleStruct_##type_], \ 1.2652 + "Going to leak style data"); \ 1.2653 + aHighestNode->mStyleData.mInheritedData-> \ 1.2654 + mStyleStructs[eStyleStruct_##type_] = data_; \ 1.2655 + /* Propagate the bit down. */ \ 1.2656 + PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_); \ 1.2657 + /* Tell the style context that it doesn't own the data */ \ 1.2658 + aContext-> \ 1.2659 + AddStyleBit(nsCachedStyleData::GetBitForSID(eStyleStruct_##type_)); \ 1.2660 + } \ 1.2661 + /* Always cache inherited data on the style context */ \ 1.2662 + aContext->SetStyle##type_(data_); \ 1.2663 + \ 1.2664 + return data_; 1.2665 + 1.2666 +/** 1.2667 + * End an nsRuleNode::Compute*Data function for a reset struct. 1.2668 + * 1.2669 + * @param type_ The nsStyle* type this function computes. 1.2670 + * @param data_ Variable holding the result of this function. 1.2671 + */ 1.2672 +#define COMPUTE_END_RESET(type_, data_) \ 1.2673 + NS_POSTCONDITION(!canStoreInRuleTree || \ 1.2674 + aRuleDetail == eRuleNone || \ 1.2675 + aRuleDetail == eRulePartialReset || \ 1.2676 + aRuleDetail == eRuleFullReset, \ 1.2677 + "canStoreInRuleTree must be false for reset structs " \ 1.2678 + "if any properties were specified as inherit"); \ 1.2679 + if (!canStoreInRuleTree) \ 1.2680 + /* We can't be cached in the rule node. We have to be put right */ \ 1.2681 + /* on the style context. */ \ 1.2682 + aContext->SetStyle(eStyleStruct_##type_, data_); \ 1.2683 + else { \ 1.2684 + /* We were fully specified and can therefore be cached right on the */ \ 1.2685 + /* rule node. */ \ 1.2686 + if (!aHighestNode->mStyleData.mResetData) { \ 1.2687 + aHighestNode->mStyleData.mResetData = \ 1.2688 + new (mPresContext) nsResetStyleData; \ 1.2689 + } \ 1.2690 + NS_ASSERTION(!aHighestNode->mStyleData.mResetData-> \ 1.2691 + mStyleStructs[eStyleStruct_##type_], \ 1.2692 + "Going to leak style data"); \ 1.2693 + aHighestNode->mStyleData.mResetData-> \ 1.2694 + mStyleStructs[eStyleStruct_##type_] = data_; \ 1.2695 + /* Propagate the bit down. */ \ 1.2696 + PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_); \ 1.2697 + } \ 1.2698 + \ 1.2699 + return data_; 1.2700 + 1.2701 +// This function figures out how much scaling should be suppressed to 1.2702 +// satisfy scriptminsize. This is our attempt to implement 1.2703 +// http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2 1.2704 +// This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier 1.2705 +// have been set in aFont. 1.2706 +// 1.2707 +// Here are the invariants we enforce: 1.2708 +// 1) A decrease in size must not reduce the size below minscriptsize. 1.2709 +// 2) An increase in size must not increase the size above the size we would 1.2710 +// have if minscriptsize had not been applied anywhere. 1.2711 +// 3) The scriptlevel-induced size change must between 1.0 and the parent's 1.2712 +// scriptsizemultiplier^(new script level - old script level), as close to the 1.2713 +// latter as possible subject to constraints 1 and 2. 1.2714 +static nscoord 1.2715 +ComputeScriptLevelSize(const nsStyleFont* aFont, const nsStyleFont* aParentFont, 1.2716 + nsPresContext* aPresContext, nscoord* aUnconstrainedSize) 1.2717 +{ 1.2718 + int32_t scriptLevelChange = 1.2719 + aFont->mScriptLevel - aParentFont->mScriptLevel; 1.2720 + if (scriptLevelChange == 0) { 1.2721 + *aUnconstrainedSize = aParentFont->mScriptUnconstrainedSize; 1.2722 + // Constraint #3 says that we cannot change size, and #1 and #2 are always 1.2723 + // satisfied with no change. It's important this be fast because it covers 1.2724 + // all non-MathML content. 1.2725 + return aParentFont->mSize; 1.2726 + } 1.2727 + 1.2728 + // Compute actual value of minScriptSize 1.2729 + nscoord minScriptSize = aParentFont->mScriptMinSize; 1.2730 + if (aFont->mAllowZoom) { 1.2731 + minScriptSize = nsStyleFont::ZoomText(aPresContext, minScriptSize); 1.2732 + } 1.2733 + 1.2734 + double scriptLevelScale = 1.2735 + pow(aParentFont->mScriptSizeMultiplier, scriptLevelChange); 1.2736 + // Compute the size we would have had if minscriptsize had never been 1.2737 + // applied, also prevent overflow (bug 413274) 1.2738 + *aUnconstrainedSize = 1.2739 + NSToCoordRound(std::min(aParentFont->mScriptUnconstrainedSize*scriptLevelScale, 1.2740 + double(nscoord_MAX))); 1.2741 + // Compute the size we could get via scriptlevel change 1.2742 + nscoord scriptLevelSize = 1.2743 + NSToCoordRound(std::min(aParentFont->mSize*scriptLevelScale, 1.2744 + double(nscoord_MAX))); 1.2745 + if (scriptLevelScale <= 1.0) { 1.2746 + if (aParentFont->mSize <= minScriptSize) { 1.2747 + // We can't decrease the font size at all, so just stick to no change 1.2748 + // (authors are allowed to explicitly set the font size smaller than 1.2749 + // minscriptsize) 1.2750 + return aParentFont->mSize; 1.2751 + } 1.2752 + // We can decrease, so apply constraint #1 1.2753 + return std::max(minScriptSize, scriptLevelSize); 1.2754 + } else { 1.2755 + // scriptminsize can only make sizes larger than the unconstrained size 1.2756 + NS_ASSERTION(*aUnconstrainedSize <= scriptLevelSize, "How can this ever happen?"); 1.2757 + // Apply constraint #2 1.2758 + return std::min(scriptLevelSize, std::max(*aUnconstrainedSize, minScriptSize)); 1.2759 + } 1.2760 +} 1.2761 + 1.2762 + 1.2763 +/* static */ nscoord 1.2764 +nsRuleNode::CalcFontPointSize(int32_t aHTMLSize, int32_t aBasePointSize, 1.2765 + nsPresContext* aPresContext, 1.2766 + nsFontSizeType aFontSizeType) 1.2767 +{ 1.2768 +#define sFontSizeTableMin 9 1.2769 +#define sFontSizeTableMax 16 1.2770 + 1.2771 +// This table seems to be the one used by MacIE5. We hope its adoption in Mozilla 1.2772 +// and eventually in WinIE5.5 will help to establish a standard rendering across 1.2773 +// platforms and browsers. For now, it is used only in Strict mode. More can be read 1.2774 +// in the document written by Todd Farhner at: 1.2775 +// http://style.verso.com/font_size_intervals/altintervals.html 1.2776 +// 1.2777 + static int32_t sStrictFontSizeTable[sFontSizeTableMax - sFontSizeTableMin + 1][8] = 1.2778 + { 1.2779 + { 9, 9, 9, 9, 11, 14, 18, 27}, 1.2780 + { 9, 9, 9, 10, 12, 15, 20, 30}, 1.2781 + { 9, 9, 10, 11, 13, 17, 22, 33}, 1.2782 + { 9, 9, 10, 12, 14, 18, 24, 36}, 1.2783 + { 9, 10, 12, 13, 16, 20, 26, 39}, 1.2784 + { 9, 10, 12, 14, 17, 21, 28, 42}, 1.2785 + { 9, 10, 13, 15, 18, 23, 30, 45}, 1.2786 + { 9, 10, 13, 16, 18, 24, 32, 48} 1.2787 + }; 1.2788 +// HTML 1 2 3 4 5 6 7 1.2789 +// CSS xxs xs s m l xl xxl 1.2790 +// | 1.2791 +// user pref 1.2792 +// 1.2793 +//------------------------------------------------------------ 1.2794 +// 1.2795 +// This table gives us compatibility with WinNav4 for the default fonts only. 1.2796 +// In WinNav4, the default fonts were: 1.2797 +// 1.2798 +// Times/12pt == Times/16px at 96ppi 1.2799 +// Courier/10pt == Courier/13px at 96ppi 1.2800 +// 1.2801 +// The 2 lines below marked "anchored" have the exact pixel sizes used by 1.2802 +// WinNav4 for Times/12pt and Courier/10pt at 96ppi. As you can see, the 1.2803 +// HTML size 3 (user pref) for those 2 anchored lines is 13px and 16px. 1.2804 +// 1.2805 +// All values other than the anchored values were filled in by hand, never 1.2806 +// going below 9px, and maintaining a "diagonal" relationship. See for 1.2807 +// example the 13s -- they follow a diagonal line through the table. 1.2808 +// 1.2809 + static int32_t sQuirksFontSizeTable[sFontSizeTableMax - sFontSizeTableMin + 1][8] = 1.2810 + { 1.2811 + { 9, 9, 9, 9, 11, 14, 18, 28 }, 1.2812 + { 9, 9, 9, 10, 12, 15, 20, 31 }, 1.2813 + { 9, 9, 9, 11, 13, 17, 22, 34 }, 1.2814 + { 9, 9, 10, 12, 14, 18, 24, 37 }, 1.2815 + { 9, 9, 10, 13, 16, 20, 26, 40 }, // anchored (13) 1.2816 + { 9, 9, 11, 14, 17, 21, 28, 42 }, 1.2817 + { 9, 10, 12, 15, 17, 23, 30, 45 }, 1.2818 + { 9, 10, 13, 16, 18, 24, 32, 48 } // anchored (16) 1.2819 + }; 1.2820 +// HTML 1 2 3 4 5 6 7 1.2821 +// CSS xxs xs s m l xl xxl 1.2822 +// | 1.2823 +// user pref 1.2824 + 1.2825 +#if 0 1.2826 +// 1.2827 +// These are the exact pixel values used by WinIE5 at 96ppi. 1.2828 +// 1.2829 + { ?, 8, 11, 12, 13, 16, 21, 32 }, // smallest 1.2830 + { ?, 9, 12, 13, 16, 21, 27, 40 }, // smaller 1.2831 + { ?, 10, 13, 16, 18, 24, 32, 48 }, // medium 1.2832 + { ?, 13, 16, 19, 21, 27, 37, ?? }, // larger 1.2833 + { ?, 16, 19, 21, 24, 32, 43, ?? } // largest 1.2834 +// 1.2835 +// HTML 1 2 3 4 5 6 7 1.2836 +// CSS ? ? ? ? ? ? ? ? 1.2837 +// 1.2838 +// (CSS not tested yet.) 1.2839 +// 1.2840 +#endif 1.2841 + 1.2842 + static int32_t sFontSizeFactors[8] = { 60,75,89,100,120,150,200,300 }; 1.2843 + 1.2844 + static int32_t sCSSColumns[7] = {0, 1, 2, 3, 4, 5, 6}; // xxs...xxl 1.2845 + static int32_t sHTMLColumns[7] = {1, 2, 3, 4, 5, 6, 7}; // 1...7 1.2846 + 1.2847 + double dFontSize; 1.2848 + 1.2849 + if (aFontSizeType == eFontSize_HTML) { 1.2850 + aHTMLSize--; // input as 1-7 1.2851 + } 1.2852 + 1.2853 + if (aHTMLSize < 0) 1.2854 + aHTMLSize = 0; 1.2855 + else if (aHTMLSize > 6) 1.2856 + aHTMLSize = 6; 1.2857 + 1.2858 + int32_t* column; 1.2859 + switch (aFontSizeType) 1.2860 + { 1.2861 + case eFontSize_HTML: column = sHTMLColumns; break; 1.2862 + case eFontSize_CSS: column = sCSSColumns; break; 1.2863 + } 1.2864 + 1.2865 + // Make special call specifically for fonts (needed PrintPreview) 1.2866 + int32_t fontSize = nsPresContext::AppUnitsToIntCSSPixels(aBasePointSize); 1.2867 + 1.2868 + if ((fontSize >= sFontSizeTableMin) && (fontSize <= sFontSizeTableMax)) 1.2869 + { 1.2870 + int32_t row = fontSize - sFontSizeTableMin; 1.2871 + 1.2872 + if (aPresContext->CompatibilityMode() == eCompatibility_NavQuirks) { 1.2873 + dFontSize = nsPresContext::CSSPixelsToAppUnits(sQuirksFontSizeTable[row][column[aHTMLSize]]); 1.2874 + } else { 1.2875 + dFontSize = nsPresContext::CSSPixelsToAppUnits(sStrictFontSizeTable[row][column[aHTMLSize]]); 1.2876 + } 1.2877 + } 1.2878 + else 1.2879 + { 1.2880 + int32_t factor = sFontSizeFactors[column[aHTMLSize]]; 1.2881 + dFontSize = (factor * aBasePointSize) / 100; 1.2882 + } 1.2883 + 1.2884 + 1.2885 + if (1.0 < dFontSize) { 1.2886 + return (nscoord)dFontSize; 1.2887 + } 1.2888 + return (nscoord)1; 1.2889 +} 1.2890 + 1.2891 + 1.2892 +//------------------------------------------------------------------------------ 1.2893 +// 1.2894 +//------------------------------------------------------------------------------ 1.2895 + 1.2896 +/* static */ nscoord 1.2897 +nsRuleNode::FindNextSmallerFontSize(nscoord aFontSize, int32_t aBasePointSize, 1.2898 + nsPresContext* aPresContext, 1.2899 + nsFontSizeType aFontSizeType) 1.2900 +{ 1.2901 + int32_t index; 1.2902 + int32_t indexMin; 1.2903 + int32_t indexMax; 1.2904 + float relativePosition; 1.2905 + nscoord smallerSize; 1.2906 + nscoord indexFontSize = aFontSize; // XXX initialize to quell a spurious gcc3.2 warning 1.2907 + nscoord smallestIndexFontSize; 1.2908 + nscoord largestIndexFontSize; 1.2909 + nscoord smallerIndexFontSize; 1.2910 + nscoord largerIndexFontSize; 1.2911 + 1.2912 + nscoord onePx = nsPresContext::CSSPixelsToAppUnits(1); 1.2913 + 1.2914 + if (aFontSizeType == eFontSize_HTML) { 1.2915 + indexMin = 1; 1.2916 + indexMax = 7; 1.2917 + } else { 1.2918 + indexMin = 0; 1.2919 + indexMax = 6; 1.2920 + } 1.2921 + 1.2922 + smallestIndexFontSize = CalcFontPointSize(indexMin, aBasePointSize, aPresContext, aFontSizeType); 1.2923 + largestIndexFontSize = CalcFontPointSize(indexMax, aBasePointSize, aPresContext, aFontSizeType); 1.2924 + if (aFontSize > smallestIndexFontSize) { 1.2925 + if (aFontSize < NSToCoordRound(float(largestIndexFontSize) * 1.5)) { // smaller will be in HTML table 1.2926 + // find largest index smaller than current 1.2927 + for (index = indexMax; index >= indexMin; index--) { 1.2928 + indexFontSize = CalcFontPointSize(index, aBasePointSize, aPresContext, aFontSizeType); 1.2929 + if (indexFontSize < aFontSize) 1.2930 + break; 1.2931 + } 1.2932 + // set up points beyond table for interpolation purposes 1.2933 + if (indexFontSize == smallestIndexFontSize) { 1.2934 + smallerIndexFontSize = indexFontSize - onePx; 1.2935 + largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType); 1.2936 + } else if (indexFontSize == largestIndexFontSize) { 1.2937 + smallerIndexFontSize = CalcFontPointSize(index-1, aBasePointSize, aPresContext, aFontSizeType); 1.2938 + largerIndexFontSize = NSToCoordRound(float(largestIndexFontSize) * 1.5); 1.2939 + } else { 1.2940 + smallerIndexFontSize = CalcFontPointSize(index-1, aBasePointSize, aPresContext, aFontSizeType); 1.2941 + largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType); 1.2942 + } 1.2943 + // compute the relative position of the parent size between the two closest indexed sizes 1.2944 + relativePosition = float(aFontSize - indexFontSize) / float(largerIndexFontSize - indexFontSize); 1.2945 + // set the new size to have the same relative position between the next smallest two indexed sizes 1.2946 + smallerSize = smallerIndexFontSize + NSToCoordRound(relativePosition * (indexFontSize - smallerIndexFontSize)); 1.2947 + } 1.2948 + else { // larger than HTML table, drop by 33% 1.2949 + smallerSize = NSToCoordRound(float(aFontSize) / 1.5); 1.2950 + } 1.2951 + } 1.2952 + else { // smaller than HTML table, drop by 1px 1.2953 + smallerSize = std::max(aFontSize - onePx, onePx); 1.2954 + } 1.2955 + return smallerSize; 1.2956 +} 1.2957 + 1.2958 +//------------------------------------------------------------------------------ 1.2959 +// 1.2960 +//------------------------------------------------------------------------------ 1.2961 + 1.2962 +/* static */ nscoord 1.2963 +nsRuleNode::FindNextLargerFontSize(nscoord aFontSize, int32_t aBasePointSize, 1.2964 + nsPresContext* aPresContext, 1.2965 + nsFontSizeType aFontSizeType) 1.2966 +{ 1.2967 + int32_t index; 1.2968 + int32_t indexMin; 1.2969 + int32_t indexMax; 1.2970 + float relativePosition; 1.2971 + nscoord adjustment; 1.2972 + nscoord largerSize; 1.2973 + nscoord indexFontSize = aFontSize; // XXX initialize to quell a spurious gcc3.2 warning 1.2974 + nscoord smallestIndexFontSize; 1.2975 + nscoord largestIndexFontSize; 1.2976 + nscoord smallerIndexFontSize; 1.2977 + nscoord largerIndexFontSize; 1.2978 + 1.2979 + nscoord onePx = nsPresContext::CSSPixelsToAppUnits(1); 1.2980 + 1.2981 + if (aFontSizeType == eFontSize_HTML) { 1.2982 + indexMin = 1; 1.2983 + indexMax = 7; 1.2984 + } else { 1.2985 + indexMin = 0; 1.2986 + indexMax = 6; 1.2987 + } 1.2988 + 1.2989 + smallestIndexFontSize = CalcFontPointSize(indexMin, aBasePointSize, aPresContext, aFontSizeType); 1.2990 + largestIndexFontSize = CalcFontPointSize(indexMax, aBasePointSize, aPresContext, aFontSizeType); 1.2991 + if (aFontSize > (smallestIndexFontSize - onePx)) { 1.2992 + if (aFontSize < largestIndexFontSize) { // larger will be in HTML table 1.2993 + // find smallest index larger than current 1.2994 + for (index = indexMin; index <= indexMax; index++) { 1.2995 + indexFontSize = CalcFontPointSize(index, aBasePointSize, aPresContext, aFontSizeType); 1.2996 + if (indexFontSize > aFontSize) 1.2997 + break; 1.2998 + } 1.2999 + // set up points beyond table for interpolation purposes 1.3000 + if (indexFontSize == smallestIndexFontSize) { 1.3001 + smallerIndexFontSize = indexFontSize - onePx; 1.3002 + largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType); 1.3003 + } else if (indexFontSize == largestIndexFontSize) { 1.3004 + smallerIndexFontSize = CalcFontPointSize(index-1, aBasePointSize, aPresContext, aFontSizeType); 1.3005 + largerIndexFontSize = NSCoordSaturatingMultiply(largestIndexFontSize, 1.5); 1.3006 + } else { 1.3007 + smallerIndexFontSize = CalcFontPointSize(index-1, aBasePointSize, aPresContext, aFontSizeType); 1.3008 + largerIndexFontSize = CalcFontPointSize(index+1, aBasePointSize, aPresContext, aFontSizeType); 1.3009 + } 1.3010 + // compute the relative position of the parent size between the two closest indexed sizes 1.3011 + relativePosition = float(aFontSize - smallerIndexFontSize) / float(indexFontSize - smallerIndexFontSize); 1.3012 + // set the new size to have the same relative position between the next largest two indexed sizes 1.3013 + adjustment = NSCoordSaturatingNonnegativeMultiply(largerIndexFontSize - indexFontSize, relativePosition); 1.3014 + largerSize = NSCoordSaturatingAdd(indexFontSize, adjustment); 1.3015 + } 1.3016 + else { // larger than HTML table, increase by 50% 1.3017 + largerSize = NSCoordSaturatingMultiply(aFontSize, 1.5); 1.3018 + } 1.3019 + } 1.3020 + else { // smaller than HTML table, increase by 1px 1.3021 + largerSize = NSCoordSaturatingAdd(aFontSize, onePx); 1.3022 + } 1.3023 + return largerSize; 1.3024 +} 1.3025 + 1.3026 +struct SetFontSizeCalcOps : public css::BasicCoordCalcOps, 1.3027 + public css::NumbersAlreadyNormalizedOps 1.3028 +{ 1.3029 + // The parameters beyond aValue that we need for CalcLengthWith. 1.3030 + const nscoord mParentSize; 1.3031 + const nsStyleFont* const mParentFont; 1.3032 + nsPresContext* const mPresContext; 1.3033 + const bool mAtRoot; 1.3034 + bool& mCanStoreInRuleTree; 1.3035 + 1.3036 + SetFontSizeCalcOps(nscoord aParentSize, const nsStyleFont* aParentFont, 1.3037 + nsPresContext* aPresContext, bool aAtRoot, 1.3038 + bool& aCanStoreInRuleTree) 1.3039 + : mParentSize(aParentSize), 1.3040 + mParentFont(aParentFont), 1.3041 + mPresContext(aPresContext), 1.3042 + mAtRoot(aAtRoot), 1.3043 + mCanStoreInRuleTree(aCanStoreInRuleTree) 1.3044 + { 1.3045 + } 1.3046 + 1.3047 + result_type ComputeLeafValue(const nsCSSValue& aValue) 1.3048 + { 1.3049 + nscoord size; 1.3050 + if (aValue.IsLengthUnit()) { 1.3051 + // Note that font-based length units use the parent's size 1.3052 + // unadjusted for scriptlevel changes. A scriptlevel change 1.3053 + // between us and the parent is simply ignored. 1.3054 + size = CalcLengthWith(aValue, mParentSize, 1.3055 + mParentFont, 1.3056 + nullptr, mPresContext, mAtRoot, 1.3057 + true, mCanStoreInRuleTree); 1.3058 + if (!aValue.IsRelativeLengthUnit() && mParentFont->mAllowZoom) { 1.3059 + size = nsStyleFont::ZoomText(mPresContext, size); 1.3060 + } 1.3061 + } 1.3062 + else if (eCSSUnit_Percent == aValue.GetUnit()) { 1.3063 + mCanStoreInRuleTree = false; 1.3064 + // Note that % units use the parent's size unadjusted for scriptlevel 1.3065 + // changes. A scriptlevel change between us and the parent is simply 1.3066 + // ignored. 1.3067 + // aValue.GetPercentValue() may be negative for, e.g., calc(-50%) 1.3068 + size = NSCoordSaturatingMultiply(mParentSize, aValue.GetPercentValue()); 1.3069 + } else { 1.3070 + NS_ABORT_IF_FALSE(false, "unexpected value"); 1.3071 + size = mParentSize; 1.3072 + } 1.3073 + 1.3074 + return size; 1.3075 + } 1.3076 +}; 1.3077 + 1.3078 +/* static */ void 1.3079 +nsRuleNode::SetFontSize(nsPresContext* aPresContext, 1.3080 + const nsRuleData* aRuleData, 1.3081 + const nsStyleFont* aFont, 1.3082 + const nsStyleFont* aParentFont, 1.3083 + nscoord* aSize, 1.3084 + const nsFont& aSystemFont, 1.3085 + nscoord aParentSize, 1.3086 + nscoord aScriptLevelAdjustedParentSize, 1.3087 + bool aUsedStartStruct, 1.3088 + bool aAtRoot, 1.3089 + bool& aCanStoreInRuleTree) 1.3090 +{ 1.3091 + // If false, means that *aSize has not been zoomed. If true, means that 1.3092 + // *aSize has been zoomed iff aParentFont->mAllowZoom is true. 1.3093 + bool sizeIsZoomedAccordingToParent = false; 1.3094 + 1.3095 + int32_t baseSize = (int32_t) aPresContext-> 1.3096 + GetDefaultFont(aFont->mGenericID, aFont->mLanguage)->size; 1.3097 + const nsCSSValue* sizeValue = aRuleData->ValueForFontSize(); 1.3098 + if (eCSSUnit_Enumerated == sizeValue->GetUnit()) { 1.3099 + int32_t value = sizeValue->GetIntValue(); 1.3100 + 1.3101 + if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) && 1.3102 + (value <= NS_STYLE_FONT_SIZE_XXLARGE)) { 1.3103 + *aSize = CalcFontPointSize(value, baseSize, 1.3104 + aPresContext, eFontSize_CSS); 1.3105 + } 1.3106 + else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) { 1.3107 + // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS. 1.3108 + *aSize = CalcFontPointSize(value, baseSize, aPresContext); 1.3109 + } 1.3110 + else if (NS_STYLE_FONT_SIZE_LARGER == value || 1.3111 + NS_STYLE_FONT_SIZE_SMALLER == value) { 1.3112 + aCanStoreInRuleTree = false; 1.3113 + 1.3114 + // Un-zoom so we use the tables correctly. We'll then rezoom due 1.3115 + // to the |zoom = true| above. 1.3116 + // Note that relative units here use the parent's size unadjusted 1.3117 + // for scriptlevel changes. A scriptlevel change between us and the parent 1.3118 + // is simply ignored. 1.3119 + nscoord parentSize = aParentSize; 1.3120 + if (aParentFont->mAllowZoom) { 1.3121 + parentSize = nsStyleFont::UnZoomText(aPresContext, parentSize); 1.3122 + } 1.3123 + 1.3124 + if (NS_STYLE_FONT_SIZE_LARGER == value) { 1.3125 + *aSize = FindNextLargerFontSize(parentSize, 1.3126 + baseSize, aPresContext, eFontSize_CSS); 1.3127 + 1.3128 + NS_ASSERTION(*aSize >= parentSize, 1.3129 + "FindNextLargerFontSize failed"); 1.3130 + } 1.3131 + else { 1.3132 + *aSize = FindNextSmallerFontSize(parentSize, 1.3133 + baseSize, aPresContext, eFontSize_CSS); 1.3134 + NS_ASSERTION(*aSize < parentSize || 1.3135 + parentSize <= nsPresContext::CSSPixelsToAppUnits(1), 1.3136 + "FindNextSmallerFontSize failed"); 1.3137 + } 1.3138 + } else { 1.3139 + NS_NOTREACHED("unexpected value"); 1.3140 + } 1.3141 + } 1.3142 + else if (sizeValue->IsLengthUnit() || 1.3143 + sizeValue->GetUnit() == eCSSUnit_Percent || 1.3144 + sizeValue->IsCalcUnit()) { 1.3145 + SetFontSizeCalcOps ops(aParentSize, aParentFont, 1.3146 + aPresContext, aAtRoot, 1.3147 + aCanStoreInRuleTree); 1.3148 + *aSize = css::ComputeCalc(*sizeValue, ops); 1.3149 + if (*aSize < 0) { 1.3150 + NS_ABORT_IF_FALSE(sizeValue->IsCalcUnit(), 1.3151 + "negative lengths and percents should be rejected " 1.3152 + "by parser"); 1.3153 + *aSize = 0; 1.3154 + } 1.3155 + // The calc ops will always zoom its result according to the value 1.3156 + // of aParentFont->mAllowZoom. 1.3157 + sizeIsZoomedAccordingToParent = true; 1.3158 + } 1.3159 + else if (eCSSUnit_System_Font == sizeValue->GetUnit()) { 1.3160 + // this becomes our cascading size 1.3161 + *aSize = aSystemFont.size; 1.3162 + } 1.3163 + else if (eCSSUnit_Inherit == sizeValue->GetUnit() || 1.3164 + eCSSUnit_Unset == sizeValue->GetUnit()) { 1.3165 + aCanStoreInRuleTree = false; 1.3166 + // We apply scriptlevel change for this case, because the default is 1.3167 + // to inherit and we don't want explicit "inherit" to differ from the 1.3168 + // default. 1.3169 + *aSize = aScriptLevelAdjustedParentSize; 1.3170 + sizeIsZoomedAccordingToParent = true; 1.3171 + } 1.3172 + else if (eCSSUnit_Initial == sizeValue->GetUnit()) { 1.3173 + // The initial value is 'medium', which has magical sizing based on 1.3174 + // the generic font family, so do that here too. 1.3175 + *aSize = baseSize; 1.3176 + } else { 1.3177 + NS_ASSERTION(eCSSUnit_Null == sizeValue->GetUnit(), 1.3178 + "What kind of font-size value is this?"); 1.3179 + // if aUsedStartStruct is true, then every single property in the 1.3180 + // font struct is being set all at once. This means scriptlevel is not 1.3181 + // going to have any influence on the font size; there is no need to 1.3182 + // do anything here. 1.3183 + if (!aUsedStartStruct && aParentSize != aScriptLevelAdjustedParentSize) { 1.3184 + // There was no rule affecting the size but the size has been 1.3185 + // affected by the parent's size via scriptlevel change. So we cannot 1.3186 + // store the data in the rule tree. 1.3187 + aCanStoreInRuleTree = false; 1.3188 + *aSize = aScriptLevelAdjustedParentSize; 1.3189 + sizeIsZoomedAccordingToParent = true; 1.3190 + } else { 1.3191 + return; 1.3192 + } 1.3193 + } 1.3194 + 1.3195 + // We want to zoom the cascaded size so that em-based measurements, 1.3196 + // line-heights, etc., work. 1.3197 + bool currentlyZoomed = sizeIsZoomedAccordingToParent && 1.3198 + aParentFont->mAllowZoom; 1.3199 + if (!currentlyZoomed && aFont->mAllowZoom) { 1.3200 + *aSize = nsStyleFont::ZoomText(aPresContext, *aSize); 1.3201 + } else if (currentlyZoomed && !aFont->mAllowZoom) { 1.3202 + *aSize = nsStyleFont::UnZoomText(aPresContext, *aSize); 1.3203 + } 1.3204 +} 1.3205 + 1.3206 +static int8_t ClampTo8Bit(int32_t aValue) { 1.3207 + if (aValue < -128) 1.3208 + return -128; 1.3209 + if (aValue > 127) 1.3210 + return 127; 1.3211 + return int8_t(aValue); 1.3212 +} 1.3213 + 1.3214 +/* static */ void 1.3215 +nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext, 1.3216 + uint8_t aGenericFontID, const nsRuleData* aRuleData, 1.3217 + const nsStyleFont* aParentFont, 1.3218 + nsStyleFont* aFont, bool aUsedStartStruct, 1.3219 + bool& aCanStoreInRuleTree) 1.3220 +{ 1.3221 + bool atRoot = !aContext->GetParent(); 1.3222 + 1.3223 + // -x-text-zoom: none, inherit, initial 1.3224 + bool allowZoom; 1.3225 + const nsCSSValue* textZoomValue = aRuleData->ValueForTextZoom(); 1.3226 + if (eCSSUnit_Null != textZoomValue->GetUnit()) { 1.3227 + if (eCSSUnit_Inherit == textZoomValue->GetUnit()) { 1.3228 + allowZoom = aParentFont->mAllowZoom; 1.3229 + } else if (eCSSUnit_None == textZoomValue->GetUnit()) { 1.3230 + allowZoom = false; 1.3231 + } else { 1.3232 + MOZ_ASSERT(eCSSUnit_Initial == textZoomValue->GetUnit(), 1.3233 + "unexpected unit"); 1.3234 + allowZoom = true; 1.3235 + } 1.3236 + aFont->EnableZoom(aPresContext, allowZoom); 1.3237 + } 1.3238 + 1.3239 + // mLanguage must be set before before any of the CalcLengthWith calls 1.3240 + // (direct calls or calls via SetFontSize) for the cases where |aParentFont| 1.3241 + // is the same as |aFont|. 1.3242 + // 1.3243 + // -x-lang: string, inherit 1.3244 + // This is not a real CSS property, it is an HTML attribute mapped to CSS. 1.3245 + const nsCSSValue* langValue = aRuleData->ValueForLang(); 1.3246 + if (eCSSUnit_Ident == langValue->GetUnit()) { 1.3247 + nsAutoString lang; 1.3248 + langValue->GetStringValue(lang); 1.3249 + 1.3250 + nsContentUtils::ASCIIToLower(lang); 1.3251 + aFont->mLanguage = do_GetAtom(lang); 1.3252 + aFont->mExplicitLanguage = true; 1.3253 + } 1.3254 + 1.3255 + const nsFont* defaultVariableFont = 1.3256 + aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID, 1.3257 + aFont->mLanguage); 1.3258 + 1.3259 + // XXX: Bleh. Disable these somehow? 1.3260 + // -moz-system-font: enum (never inherit!) 1.3261 + static_assert( 1.3262 + NS_STYLE_FONT_CAPTION == LookAndFeel::eFont_Caption && 1.3263 + NS_STYLE_FONT_ICON == LookAndFeel::eFont_Icon && 1.3264 + NS_STYLE_FONT_MENU == LookAndFeel::eFont_Menu && 1.3265 + NS_STYLE_FONT_MESSAGE_BOX == LookAndFeel::eFont_MessageBox && 1.3266 + NS_STYLE_FONT_SMALL_CAPTION == LookAndFeel::eFont_SmallCaption && 1.3267 + NS_STYLE_FONT_STATUS_BAR == LookAndFeel::eFont_StatusBar && 1.3268 + NS_STYLE_FONT_WINDOW == LookAndFeel::eFont_Window && 1.3269 + NS_STYLE_FONT_DOCUMENT == LookAndFeel::eFont_Document && 1.3270 + NS_STYLE_FONT_WORKSPACE == LookAndFeel::eFont_Workspace && 1.3271 + NS_STYLE_FONT_DESKTOP == LookAndFeel::eFont_Desktop && 1.3272 + NS_STYLE_FONT_INFO == LookAndFeel::eFont_Info && 1.3273 + NS_STYLE_FONT_DIALOG == LookAndFeel::eFont_Dialog && 1.3274 + NS_STYLE_FONT_BUTTON == LookAndFeel::eFont_Button && 1.3275 + NS_STYLE_FONT_PULL_DOWN_MENU == LookAndFeel::eFont_PullDownMenu && 1.3276 + NS_STYLE_FONT_LIST == LookAndFeel::eFont_List && 1.3277 + NS_STYLE_FONT_FIELD == LookAndFeel::eFont_Field, 1.3278 + "LookAndFeel.h system-font constants out of sync with nsStyleConsts.h"); 1.3279 + 1.3280 + // Fall back to defaultVariableFont. 1.3281 + nsFont systemFont = *defaultVariableFont; 1.3282 + const nsCSSValue* systemFontValue = aRuleData->ValueForSystemFont(); 1.3283 + if (eCSSUnit_Enumerated == systemFontValue->GetUnit()) { 1.3284 + gfxFontStyle fontStyle; 1.3285 + LookAndFeel::FontID fontID = 1.3286 + (LookAndFeel::FontID)systemFontValue->GetIntValue(); 1.3287 + float devPerCSS = 1.3288 + (float)nsPresContext::AppUnitsPerCSSPixel() / 1.3289 + aPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel(); 1.3290 + if (LookAndFeel::GetFont(fontID, systemFont.name, fontStyle, devPerCSS)) { 1.3291 + systemFont.style = fontStyle.style; 1.3292 + systemFont.systemFont = fontStyle.systemFont; 1.3293 + systemFont.variant = NS_FONT_VARIANT_NORMAL; 1.3294 + systemFont.weight = fontStyle.weight; 1.3295 + systemFont.stretch = fontStyle.stretch; 1.3296 + systemFont.decorations = NS_FONT_DECORATION_NONE; 1.3297 + systemFont.size = NSFloatPixelsToAppUnits(fontStyle.size, 1.3298 + aPresContext->DeviceContext()-> 1.3299 + UnscaledAppUnitsPerDevPixel()); 1.3300 + //systemFont.langGroup = fontStyle.langGroup; 1.3301 + systemFont.sizeAdjust = fontStyle.sizeAdjust; 1.3302 + 1.3303 +#ifdef XP_WIN 1.3304 + // XXXldb This platform-specific stuff should be in the 1.3305 + // LookAndFeel implementation, not here. 1.3306 + // XXXzw Should we even still *have* this code? It looks to be making 1.3307 + // old, probably obsolete assumptions. 1.3308 + 1.3309 + if (fontID == LookAndFeel::eFont_Field || 1.3310 + fontID == LookAndFeel::eFont_Button || 1.3311 + fontID == LookAndFeel::eFont_List) { 1.3312 + // As far as I can tell the system default fonts and sizes 1.3313 + // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are 1.3314 + // all pre-determined and cannot be changed by either the control panel 1.3315 + // or programmatically. 1.3316 + // Fields (text fields) 1.3317 + // Button and Selects (listboxes/comboboxes) 1.3318 + // We use whatever font is defined by the system. Which it appears 1.3319 + // (and the assumption is) it is always a proportional font. Then we 1.3320 + // always use 2 points smaller than what the browser has defined as 1.3321 + // the default proportional font. 1.3322 + // Assumption: system defined font is proportional 1.3323 + systemFont.size = 1.3324 + std::max(defaultVariableFont->size - 1.3325 + nsPresContext::CSSPointsToAppUnits(2), 0); 1.3326 + } 1.3327 +#endif 1.3328 + } 1.3329 + } 1.3330 + 1.3331 + // font-family: string list, enum, inherit 1.3332 + const nsCSSValue* familyValue = aRuleData->ValueForFontFamily(); 1.3333 + NS_ASSERTION(eCSSUnit_Enumerated != familyValue->GetUnit(), 1.3334 + "system fonts should not be in mFamily anymore"); 1.3335 + if (eCSSUnit_Families == familyValue->GetUnit()) { 1.3336 + // set the correct font if we are using DocumentFonts OR we are overriding for XUL 1.3337 + // MJA: bug 31816 1.3338 + if (aGenericFontID == kGenericFont_NONE) { 1.3339 + // only bother appending fallback fonts if this isn't a fallback generic font itself 1.3340 + if (!aFont->mFont.name.IsEmpty()) 1.3341 + aFont->mFont.name.Append((char16_t)','); 1.3342 + // defaultVariableFont.name should always be "serif" or "sans-serif". 1.3343 + aFont->mFont.name.Append(defaultVariableFont->name); 1.3344 + } 1.3345 + aFont->mFont.systemFont = false; 1.3346 + // Technically this is redundant with the code below, but it's good 1.3347 + // to have since we'll still want it once we get rid of 1.3348 + // SetGenericFont (bug 380915). 1.3349 + aFont->mGenericID = aGenericFontID; 1.3350 + } 1.3351 + else if (eCSSUnit_System_Font == familyValue->GetUnit()) { 1.3352 + aFont->mFont.name = systemFont.name; 1.3353 + aFont->mFont.systemFont = true; 1.3354 + aFont->mGenericID = kGenericFont_NONE; 1.3355 + } 1.3356 + else if (eCSSUnit_Inherit == familyValue->GetUnit() || 1.3357 + eCSSUnit_Unset == familyValue->GetUnit()) { 1.3358 + aCanStoreInRuleTree = false; 1.3359 + aFont->mFont.name = aParentFont->mFont.name; 1.3360 + aFont->mFont.systemFont = aParentFont->mFont.systemFont; 1.3361 + aFont->mGenericID = aParentFont->mGenericID; 1.3362 + } 1.3363 + else if (eCSSUnit_Initial == familyValue->GetUnit()) { 1.3364 + aFont->mFont.name = defaultVariableFont->name; 1.3365 + aFont->mFont.systemFont = defaultVariableFont->systemFont; 1.3366 + aFont->mGenericID = kGenericFont_NONE; 1.3367 + } 1.3368 + 1.3369 + // When we're in the loop in SetGenericFont, we must ensure that we 1.3370 + // always keep aFont->mFlags set to the correct generic. But we have 1.3371 + // to be careful not to touch it when we're called directly from 1.3372 + // ComputeFontData, because we could have a start struct. 1.3373 + if (aGenericFontID != kGenericFont_NONE) { 1.3374 + aFont->mGenericID = aGenericFontID; 1.3375 + } 1.3376 + 1.3377 + // -moz-math-variant: enum, inherit, initial 1.3378 + SetDiscrete(*aRuleData->ValueForMathVariant(), aFont->mMathVariant, 1.3379 + aCanStoreInRuleTree, 1.3380 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.3381 + aParentFont->mMathVariant, NS_MATHML_MATHVARIANT_NONE, 1.3382 + 0, 0, 0, 0); 1.3383 + 1.3384 + // -moz-math-display: enum, inherit, initial 1.3385 + SetDiscrete(*aRuleData->ValueForMathDisplay(), aFont->mMathDisplay, 1.3386 + aCanStoreInRuleTree, 1.3387 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.3388 + aParentFont->mMathDisplay, NS_MATHML_DISPLAYSTYLE_INLINE, 1.3389 + 0, 0, 0, 0); 1.3390 + 1.3391 + // font-smoothing: enum, inherit, initial 1.3392 + SetDiscrete(*aRuleData->ValueForOSXFontSmoothing(), 1.3393 + aFont->mFont.smoothing, aCanStoreInRuleTree, 1.3394 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.3395 + aParentFont->mFont.smoothing, 1.3396 + defaultVariableFont->smoothing, 1.3397 + 0, 0, 0, 0); 1.3398 + 1.3399 + // font-style: enum, inherit, initial, -moz-system-font 1.3400 + if (aFont->mMathVariant != NS_MATHML_MATHVARIANT_NONE) { 1.3401 + // -moz-math-variant overrides font-style 1.3402 + aFont->mFont.style = NS_FONT_STYLE_NORMAL; 1.3403 + } else { 1.3404 + SetDiscrete(*aRuleData->ValueForFontStyle(), 1.3405 + aFont->mFont.style, aCanStoreInRuleTree, 1.3406 + SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, 1.3407 + aParentFont->mFont.style, 1.3408 + defaultVariableFont->style, 1.3409 + 0, 0, 0, systemFont.style); 1.3410 + } 1.3411 + 1.3412 + // font-variant: enum, inherit, initial, -moz-system-font 1.3413 + SetDiscrete(*aRuleData->ValueForFontVariant(), 1.3414 + aFont->mFont.variant, aCanStoreInRuleTree, 1.3415 + SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, 1.3416 + aParentFont->mFont.variant, 1.3417 + defaultVariableFont->variant, 1.3418 + 0, 0, 0, systemFont.variant); 1.3419 + 1.3420 + // font-weight: int, enum, inherit, initial, -moz-system-font 1.3421 + // special handling for enum 1.3422 + const nsCSSValue* weightValue = aRuleData->ValueForFontWeight(); 1.3423 + if (aFont->mMathVariant != NS_MATHML_MATHVARIANT_NONE) { 1.3424 + // -moz-math-variant overrides font-weight 1.3425 + aFont->mFont.weight = NS_FONT_WEIGHT_NORMAL; 1.3426 + } else if (eCSSUnit_Enumerated == weightValue->GetUnit()) { 1.3427 + int32_t value = weightValue->GetIntValue(); 1.3428 + switch (value) { 1.3429 + case NS_STYLE_FONT_WEIGHT_NORMAL: 1.3430 + case NS_STYLE_FONT_WEIGHT_BOLD: 1.3431 + aFont->mFont.weight = value; 1.3432 + break; 1.3433 + case NS_STYLE_FONT_WEIGHT_BOLDER: { 1.3434 + aCanStoreInRuleTree = false; 1.3435 + int32_t inheritedValue = aParentFont->mFont.weight; 1.3436 + if (inheritedValue <= 300) { 1.3437 + aFont->mFont.weight = 400; 1.3438 + } else if (inheritedValue <= 500) { 1.3439 + aFont->mFont.weight = 700; 1.3440 + } else { 1.3441 + aFont->mFont.weight = 900; 1.3442 + } 1.3443 + break; 1.3444 + } 1.3445 + case NS_STYLE_FONT_WEIGHT_LIGHTER: { 1.3446 + aCanStoreInRuleTree = false; 1.3447 + int32_t inheritedValue = aParentFont->mFont.weight; 1.3448 + if (inheritedValue < 600) { 1.3449 + aFont->mFont.weight = 100; 1.3450 + } else if (inheritedValue < 800) { 1.3451 + aFont->mFont.weight = 400; 1.3452 + } else { 1.3453 + aFont->mFont.weight = 700; 1.3454 + } 1.3455 + break; 1.3456 + } 1.3457 + } 1.3458 + } else 1.3459 + SetDiscrete(*weightValue, aFont->mFont.weight, aCanStoreInRuleTree, 1.3460 + SETDSC_INTEGER | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, 1.3461 + aParentFont->mFont.weight, 1.3462 + defaultVariableFont->weight, 1.3463 + 0, 0, 0, systemFont.weight); 1.3464 + 1.3465 + // font-stretch: enum, inherit, initial, -moz-system-font 1.3466 + SetDiscrete(*aRuleData->ValueForFontStretch(), 1.3467 + aFont->mFont.stretch, aCanStoreInRuleTree, 1.3468 + SETDSC_SYSTEM_FONT | SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.3469 + aParentFont->mFont.stretch, 1.3470 + defaultVariableFont->stretch, 1.3471 + 0, 0, 0, systemFont.stretch); 1.3472 + 1.3473 + // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so 1.3474 + // they're available for font-size computation. 1.3475 + 1.3476 + // -moz-script-min-size: length 1.3477 + const nsCSSValue* scriptMinSizeValue = aRuleData->ValueForScriptMinSize(); 1.3478 + if (scriptMinSizeValue->IsLengthUnit()) { 1.3479 + // scriptminsize in font units (em, ex) has to be interpreted relative 1.3480 + // to the parent font, or the size definitions are circular and we 1.3481 + // 1.3482 + aFont->mScriptMinSize = 1.3483 + CalcLengthWith(*scriptMinSizeValue, aParentFont->mSize, 1.3484 + aParentFont, 1.3485 + nullptr, aPresContext, atRoot, true, 1.3486 + aCanStoreInRuleTree); 1.3487 + } 1.3488 + 1.3489 + // -moz-script-size-multiplier: factor, inherit, initial 1.3490 + SetFactor(*aRuleData->ValueForScriptSizeMultiplier(), 1.3491 + aFont->mScriptSizeMultiplier, 1.3492 + aCanStoreInRuleTree, aParentFont->mScriptSizeMultiplier, 1.3493 + NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER, 1.3494 + SETFCT_POSITIVE | SETFCT_UNSET_INHERIT); 1.3495 + 1.3496 + // -moz-script-level: integer, number, inherit 1.3497 + const nsCSSValue* scriptLevelValue = aRuleData->ValueForScriptLevel(); 1.3498 + if (eCSSUnit_Integer == scriptLevelValue->GetUnit()) { 1.3499 + // "relative" 1.3500 + aCanStoreInRuleTree = false; 1.3501 + aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel + scriptLevelValue->GetIntValue()); 1.3502 + } 1.3503 + else if (eCSSUnit_Number == scriptLevelValue->GetUnit()) { 1.3504 + // "absolute" 1.3505 + aFont->mScriptLevel = ClampTo8Bit(int32_t(scriptLevelValue->GetFloatValue())); 1.3506 + } 1.3507 + else if (eCSSUnit_Auto == scriptLevelValue->GetUnit()) { 1.3508 + // auto 1.3509 + aCanStoreInRuleTree = false; 1.3510 + aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel + 1.3511 + (aParentFont->mMathDisplay == 1.3512 + NS_MATHML_DISPLAYSTYLE_INLINE ? 1 : 0)); 1.3513 + } 1.3514 + else if (eCSSUnit_Inherit == scriptLevelValue->GetUnit() || 1.3515 + eCSSUnit_Unset == scriptLevelValue->GetUnit()) { 1.3516 + aCanStoreInRuleTree = false; 1.3517 + aFont->mScriptLevel = aParentFont->mScriptLevel; 1.3518 + } 1.3519 + else if (eCSSUnit_Initial == scriptLevelValue->GetUnit()) { 1.3520 + aFont->mScriptLevel = 0; 1.3521 + } 1.3522 + 1.3523 + // font-kerning: none, enum, inherit, initial, -moz-system-font 1.3524 + SetDiscrete(*aRuleData->ValueForFontKerning(), 1.3525 + aFont->mFont.kerning, aCanStoreInRuleTree, 1.3526 + SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, 1.3527 + aParentFont->mFont.kerning, 1.3528 + defaultVariableFont->kerning, 1.3529 + 0, 0, 0, systemFont.kerning); 1.3530 + 1.3531 + // font-synthesis: none, enum (bit field), inherit, initial, -moz-system-font 1.3532 + SetDiscrete(*aRuleData->ValueForFontSynthesis(), 1.3533 + aFont->mFont.synthesis, aCanStoreInRuleTree, 1.3534 + SETDSC_NONE | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | 1.3535 + SETDSC_UNSET_INHERIT, 1.3536 + aParentFont->mFont.synthesis, 1.3537 + defaultVariableFont->synthesis, 1.3538 + 0, 0, 0, systemFont.synthesis); 1.3539 + 1.3540 + // font-variant-alternates: normal, enum (bit field) + functions, inherit, 1.3541 + // initial, -moz-system-font 1.3542 + const nsCSSValue* variantAlternatesValue = 1.3543 + aRuleData->ValueForFontVariantAlternates(); 1.3544 + int32_t variantAlternates = 0; 1.3545 + 1.3546 + switch (variantAlternatesValue->GetUnit()) { 1.3547 + case eCSSUnit_Inherit: 1.3548 + case eCSSUnit_Unset: 1.3549 + aFont->mFont.CopyAlternates(aParentFont->mFont); 1.3550 + aCanStoreInRuleTree = false; 1.3551 + break; 1.3552 + 1.3553 + case eCSSUnit_Initial: 1.3554 + case eCSSUnit_Normal: 1.3555 + aFont->mFont.variantAlternates = 0; 1.3556 + aFont->mFont.alternateValues.Clear(); 1.3557 + aFont->mFont.featureValueLookup = nullptr; 1.3558 + break; 1.3559 + 1.3560 + case eCSSUnit_Pair: 1.3561 + NS_ASSERTION(variantAlternatesValue->GetPairValue().mXValue.GetUnit() == 1.3562 + eCSSUnit_Enumerated, "strange unit for variantAlternates"); 1.3563 + variantAlternates = 1.3564 + variantAlternatesValue->GetPairValue().mXValue.GetIntValue(); 1.3565 + aFont->mFont.variantAlternates = variantAlternates; 1.3566 + 1.3567 + if (variantAlternates & NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK) { 1.3568 + // fetch the feature lookup object from the styleset 1.3569 + aFont->mFont.featureValueLookup = 1.3570 + aPresContext->StyleSet()->GetFontFeatureValuesLookup(); 1.3571 + 1.3572 + NS_ASSERTION(variantAlternatesValue->GetPairValue().mYValue.GetUnit() == 1.3573 + eCSSUnit_List, "function list not a list value"); 1.3574 + nsStyleUtil::ComputeFunctionalAlternates( 1.3575 + variantAlternatesValue->GetPairValue().mYValue.GetListValue(), 1.3576 + aFont->mFont.alternateValues); 1.3577 + } 1.3578 + break; 1.3579 + 1.3580 + default: 1.3581 + break; 1.3582 + } 1.3583 + 1.3584 + // font-variant-caps: normal, enum, inherit, initial, -moz-system-font 1.3585 + SetDiscrete(*aRuleData->ValueForFontVariantCaps(), 1.3586 + aFont->mFont.variantCaps, aCanStoreInRuleTree, 1.3587 + SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | 1.3588 + SETDSC_UNSET_INHERIT, 1.3589 + aParentFont->mFont.variantCaps, 1.3590 + defaultVariableFont->variantCaps, 1.3591 + 0, 0, 0, systemFont.variantCaps); 1.3592 + 1.3593 + // font-variant-east-asian: normal, enum (bit field), inherit, initial, 1.3594 + // -moz-system-font 1.3595 + SetDiscrete(*aRuleData->ValueForFontVariantEastAsian(), 1.3596 + aFont->mFont.variantEastAsian, aCanStoreInRuleTree, 1.3597 + SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | 1.3598 + SETDSC_UNSET_INHERIT, 1.3599 + aParentFont->mFont.variantEastAsian, 1.3600 + defaultVariableFont->variantEastAsian, 1.3601 + 0, 0, 0, systemFont.variantEastAsian); 1.3602 + 1.3603 + // font-variant-ligatures: normal, enum (bit field), inherit, initial, 1.3604 + // -moz-system-font 1.3605 + SetDiscrete(*aRuleData->ValueForFontVariantLigatures(), 1.3606 + aFont->mFont.variantLigatures, aCanStoreInRuleTree, 1.3607 + SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | 1.3608 + SETDSC_UNSET_INHERIT, 1.3609 + aParentFont->mFont.variantLigatures, 1.3610 + defaultVariableFont->variantLigatures, 1.3611 + 0, 0, 0, systemFont.variantLigatures); 1.3612 + 1.3613 + // font-variant-numeric: normal, enum (bit field), inherit, initial, 1.3614 + // -moz-system-font 1.3615 + SetDiscrete(*aRuleData->ValueForFontVariantNumeric(), 1.3616 + aFont->mFont.variantNumeric, aCanStoreInRuleTree, 1.3617 + SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | 1.3618 + SETDSC_UNSET_INHERIT, 1.3619 + aParentFont->mFont.variantNumeric, 1.3620 + defaultVariableFont->variantNumeric, 1.3621 + 0, 0, 0, systemFont.variantNumeric); 1.3622 + 1.3623 + // font-variant-position: normal, enum, inherit, initial, 1.3624 + // -moz-system-font 1.3625 + SetDiscrete(*aRuleData->ValueForFontVariantPosition(), 1.3626 + aFont->mFont.variantPosition, aCanStoreInRuleTree, 1.3627 + SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | 1.3628 + SETDSC_UNSET_INHERIT, 1.3629 + aParentFont->mFont.variantPosition, 1.3630 + defaultVariableFont->variantPosition, 1.3631 + 0, 0, 0, systemFont.variantPosition); 1.3632 + 1.3633 + // font-feature-settings 1.3634 + const nsCSSValue* featureSettingsValue = 1.3635 + aRuleData->ValueForFontFeatureSettings(); 1.3636 + 1.3637 + switch (featureSettingsValue->GetUnit()) { 1.3638 + case eCSSUnit_Null: 1.3639 + break; 1.3640 + 1.3641 + case eCSSUnit_Normal: 1.3642 + case eCSSUnit_Initial: 1.3643 + aFont->mFont.fontFeatureSettings.Clear(); 1.3644 + break; 1.3645 + 1.3646 + case eCSSUnit_Inherit: 1.3647 + case eCSSUnit_Unset: 1.3648 + aCanStoreInRuleTree = false; 1.3649 + aFont->mFont.fontFeatureSettings = aParentFont->mFont.fontFeatureSettings; 1.3650 + break; 1.3651 + 1.3652 + case eCSSUnit_System_Font: 1.3653 + aFont->mFont.fontFeatureSettings = systemFont.fontFeatureSettings; 1.3654 + break; 1.3655 + 1.3656 + case eCSSUnit_PairList: 1.3657 + case eCSSUnit_PairListDep: 1.3658 + ComputeFontFeatures(featureSettingsValue->GetPairListValue(), 1.3659 + aFont->mFont.fontFeatureSettings); 1.3660 + break; 1.3661 + 1.3662 + default: 1.3663 + NS_ABORT_IF_FALSE(false, "unexpected value unit"); 1.3664 + break; 1.3665 + } 1.3666 + 1.3667 + // font-language-override 1.3668 + const nsCSSValue* languageOverrideValue = 1.3669 + aRuleData->ValueForFontLanguageOverride(); 1.3670 + if (eCSSUnit_Inherit == languageOverrideValue->GetUnit() || 1.3671 + eCSSUnit_Unset == languageOverrideValue->GetUnit()) { 1.3672 + aCanStoreInRuleTree = false; 1.3673 + aFont->mFont.languageOverride = aParentFont->mFont.languageOverride; 1.3674 + } else if (eCSSUnit_Normal == languageOverrideValue->GetUnit() || 1.3675 + eCSSUnit_Initial == languageOverrideValue->GetUnit()) { 1.3676 + aFont->mFont.languageOverride.Truncate(); 1.3677 + } else if (eCSSUnit_System_Font == languageOverrideValue->GetUnit()) { 1.3678 + aFont->mFont.languageOverride = systemFont.languageOverride; 1.3679 + } else if (eCSSUnit_String == languageOverrideValue->GetUnit()) { 1.3680 + languageOverrideValue->GetStringValue(aFont->mFont.languageOverride); 1.3681 + } 1.3682 + 1.3683 + // font-size: enum, length, percent, inherit 1.3684 + nscoord scriptLevelAdjustedParentSize = aParentFont->mSize; 1.3685 + nscoord scriptLevelAdjustedUnconstrainedParentSize; 1.3686 + scriptLevelAdjustedParentSize = 1.3687 + ComputeScriptLevelSize(aFont, aParentFont, aPresContext, 1.3688 + &scriptLevelAdjustedUnconstrainedParentSize); 1.3689 + NS_ASSERTION(!aUsedStartStruct || aFont->mScriptUnconstrainedSize == aFont->mSize, 1.3690 + "If we have a start struct, we should have reset everything coming in here"); 1.3691 + SetFontSize(aPresContext, aRuleData, aFont, aParentFont, 1.3692 + &aFont->mSize, 1.3693 + systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize, 1.3694 + aUsedStartStruct, atRoot, aCanStoreInRuleTree); 1.3695 + if (aParentFont->mSize == aParentFont->mScriptUnconstrainedSize && 1.3696 + scriptLevelAdjustedParentSize == scriptLevelAdjustedUnconstrainedParentSize) { 1.3697 + // Fast path: we have not been affected by scriptminsize so we don't 1.3698 + // need to call SetFontSize again to compute the 1.3699 + // scriptminsize-unconstrained size. This is OK even if we have a 1.3700 + // start struct, because if we have a start struct then 'font-size' 1.3701 + // was specified and so scriptminsize has no effect. 1.3702 + aFont->mScriptUnconstrainedSize = aFont->mSize; 1.3703 + } else { 1.3704 + SetFontSize(aPresContext, aRuleData, aFont, aParentFont, 1.3705 + &aFont->mScriptUnconstrainedSize, 1.3706 + systemFont, aParentFont->mScriptUnconstrainedSize, 1.3707 + scriptLevelAdjustedUnconstrainedParentSize, 1.3708 + aUsedStartStruct, atRoot, aCanStoreInRuleTree); 1.3709 + } 1.3710 + NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize, 1.3711 + "scriptminsize should never be making things bigger"); 1.3712 + 1.3713 + nscoord fontSize = aFont->mSize; 1.3714 + 1.3715 + // enforce the user' specified minimum font-size on the value that we expose 1.3716 + // (but don't change font-size:0, since that would unhide hidden text) 1.3717 + if (fontSize > 0) { 1.3718 + nscoord minFontSize = aPresContext->MinFontSize(aFont->mLanguage); 1.3719 + if (minFontSize < 0) { 1.3720 + minFontSize = 0; 1.3721 + } 1.3722 + if (fontSize < minFontSize && !aPresContext->IsChrome()) { 1.3723 + // override the minimum font-size constraint 1.3724 + fontSize = minFontSize; 1.3725 + } 1.3726 + } 1.3727 + aFont->mFont.size = fontSize; 1.3728 + 1.3729 + // font-size-adjust: number, none, inherit, initial, -moz-system-font 1.3730 + const nsCSSValue* sizeAdjustValue = aRuleData->ValueForFontSizeAdjust(); 1.3731 + if (eCSSUnit_System_Font == sizeAdjustValue->GetUnit()) { 1.3732 + aFont->mFont.sizeAdjust = systemFont.sizeAdjust; 1.3733 + } else 1.3734 + SetFactor(*sizeAdjustValue, aFont->mFont.sizeAdjust, 1.3735 + aCanStoreInRuleTree, aParentFont->mFont.sizeAdjust, 0.0f, 1.3736 + SETFCT_NONE | SETFCT_UNSET_INHERIT); 1.3737 +} 1.3738 + 1.3739 +/* static */ void 1.3740 +nsRuleNode::ComputeFontFeatures(const nsCSSValuePairList *aFeaturesList, 1.3741 + nsTArray<gfxFontFeature>& aFeatureSettings) 1.3742 +{ 1.3743 + aFeatureSettings.Clear(); 1.3744 + for (const nsCSSValuePairList* p = aFeaturesList; p; p = p->mNext) { 1.3745 + gfxFontFeature feat = {0, 0}; 1.3746 + 1.3747 + NS_ABORT_IF_FALSE(aFeaturesList->mXValue.GetUnit() == eCSSUnit_String, 1.3748 + "unexpected value unit"); 1.3749 + 1.3750 + // tag is a 4-byte ASCII sequence 1.3751 + nsAutoString tag; 1.3752 + p->mXValue.GetStringValue(tag); 1.3753 + if (tag.Length() != 4) { 1.3754 + continue; 1.3755 + } 1.3756 + // parsing validates that these are ASCII chars 1.3757 + // tags are always big-endian 1.3758 + feat.mTag = (tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3]; 1.3759 + 1.3760 + // value 1.3761 + NS_ASSERTION(p->mYValue.GetUnit() == eCSSUnit_Integer, 1.3762 + "should have found an integer unit"); 1.3763 + feat.mValue = p->mYValue.GetIntValue(); 1.3764 + 1.3765 + aFeatureSettings.AppendElement(feat); 1.3766 + } 1.3767 +} 1.3768 + 1.3769 +// This should die (bug 380915). 1.3770 +// 1.3771 +// SetGenericFont: 1.3772 +// - backtrack to an ancestor with the same generic font name (possibly 1.3773 +// up to the root where default values come from the presentation context) 1.3774 +// - re-apply cascading rules from there without caching intermediate values 1.3775 +/* static */ void 1.3776 +nsRuleNode::SetGenericFont(nsPresContext* aPresContext, 1.3777 + nsStyleContext* aContext, 1.3778 + uint8_t aGenericFontID, 1.3779 + nsStyleFont* aFont) 1.3780 +{ 1.3781 + // walk up the contexts until a context with the desired generic font 1.3782 + nsAutoTArray<nsStyleContext*, 8> contextPath; 1.3783 + contextPath.AppendElement(aContext); 1.3784 + nsStyleContext* higherContext = aContext->GetParent(); 1.3785 + while (higherContext) { 1.3786 + if (higherContext->StyleFont()->mGenericID == aGenericFontID) { 1.3787 + // done walking up the higher contexts 1.3788 + break; 1.3789 + } 1.3790 + contextPath.AppendElement(higherContext); 1.3791 + higherContext = higherContext->GetParent(); 1.3792 + } 1.3793 + 1.3794 + // re-apply the cascading rules, starting from the higher context 1.3795 + 1.3796 + // If we stopped earlier because we reached the root of the style tree, 1.3797 + // we will start with the default generic font from the presentation 1.3798 + // context. Otherwise we start with the higher context. 1.3799 + const nsFont* defaultFont = 1.3800 + aPresContext->GetDefaultFont(aGenericFontID, aFont->mLanguage); 1.3801 + nsStyleFont parentFont(*defaultFont, aPresContext); 1.3802 + if (higherContext) { 1.3803 + const nsStyleFont* tmpFont = higherContext->StyleFont(); 1.3804 + parentFont = *tmpFont; 1.3805 + } 1.3806 + *aFont = parentFont; 1.3807 + 1.3808 + bool dummy; 1.3809 + uint32_t fontBit = nsCachedStyleData::GetBitForSID(eStyleStruct_Font); 1.3810 + 1.3811 + // use placement new[] on the result of alloca() to allocate a 1.3812 + // variable-sized stack array, including execution of constructors, 1.3813 + // and use an RAII class to run the destructors too. 1.3814 + size_t nprops = nsCSSProps::PropertyCountInStruct(eStyleStruct_Font); 1.3815 + void* dataStorage = alloca(nprops * sizeof(nsCSSValue)); 1.3816 + 1.3817 + for (int32_t i = contextPath.Length() - 1; i >= 0; --i) { 1.3818 + nsStyleContext* context = contextPath[i]; 1.3819 + AutoCSSValueArray dataArray(dataStorage, nprops); 1.3820 + 1.3821 + nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Font), dataArray.get(), 1.3822 + aPresContext, context); 1.3823 + ruleData.mValueOffsets[eStyleStruct_Font] = 0; 1.3824 + 1.3825 + // Trimmed down version of ::WalkRuleTree() to re-apply the style rules 1.3826 + // Note that we *do* need to do this for our own data, since what is 1.3827 + // in |fontData| in ComputeFontData is only for the rules below 1.3828 + // aStartStruct. 1.3829 + for (nsRuleNode* ruleNode = context->RuleNode(); ruleNode; 1.3830 + ruleNode = ruleNode->GetParent()) { 1.3831 + if (ruleNode->mNoneBits & fontBit) 1.3832 + // no more font rules on this branch, get out 1.3833 + break; 1.3834 + 1.3835 + nsIStyleRule *rule = ruleNode->GetRule(); 1.3836 + if (rule) { 1.3837 + ruleData.mLevel = ruleNode->GetLevel(); 1.3838 + ruleData.mIsImportantRule = ruleNode->IsImportantRule(); 1.3839 + rule->MapRuleInfoInto(&ruleData); 1.3840 + } 1.3841 + } 1.3842 + 1.3843 + // Compute the delta from the information that the rules specified 1.3844 + 1.3845 + // Avoid unnecessary operations in SetFont(). But we care if it's 1.3846 + // the final value that we're computing. 1.3847 + if (i != 0) 1.3848 + ruleData.ValueForFontFamily()->Reset(); 1.3849 + 1.3850 + ResolveVariableReferences(eStyleStruct_Font, &ruleData, aContext); 1.3851 + 1.3852 + nsRuleNode::SetFont(aPresContext, context, 1.3853 + aGenericFontID, &ruleData, &parentFont, aFont, 1.3854 + false, dummy); 1.3855 + 1.3856 + parentFont = *aFont; 1.3857 + } 1.3858 +} 1.3859 + 1.3860 +static bool ExtractGeneric(const nsString& aFamily, bool aGeneric, 1.3861 + void *aData) 1.3862 +{ 1.3863 + nsAutoString *data = static_cast<nsAutoString*>(aData); 1.3864 + 1.3865 + if (aGeneric) { 1.3866 + *data = aFamily; 1.3867 + return false; // stop enumeration 1.3868 + } 1.3869 + return true; 1.3870 +} 1.3871 + 1.3872 +struct smugglerStruct { 1.3873 + nsStyleFont *font; 1.3874 + gfxUserFontSet *userFonts; 1.3875 +}; 1.3876 + 1.3877 +/* This function forces the use of the first @font-face font we find */ 1.3878 +static bool ForceFirstWebFont(const nsString& aFamily, bool aGeneric, 1.3879 + void *smuggled) 1.3880 +{ 1.3881 + smugglerStruct *sm = static_cast<smugglerStruct*>(smuggled); 1.3882 + 1.3883 + if (aGeneric) { 1.3884 + return true; 1.3885 + } 1.3886 + 1.3887 + if (sm->userFonts->HasFamily(aFamily)) { 1.3888 + // Force use of this exact @font-face font since we have it. 1.3889 + sm->font->mFont.name = aFamily; 1.3890 + 1.3891 + return false; // Stop enumeration. 1.3892 + } 1.3893 + 1.3894 + return true; 1.3895 +} 1.3896 + 1.3897 +const void* 1.3898 +nsRuleNode::ComputeFontData(void* aStartStruct, 1.3899 + const nsRuleData* aRuleData, 1.3900 + nsStyleContext* aContext, 1.3901 + nsRuleNode* aHighestNode, 1.3902 + const RuleDetail aRuleDetail, 1.3903 + const bool aCanStoreInRuleTree) 1.3904 +{ 1.3905 + COMPUTE_START_INHERITED(Font, (mPresContext), font, parentFont) 1.3906 + 1.3907 + // NOTE: The |aRuleDetail| passed in is a little bit conservative due 1.3908 + // to the -moz-system-font property. We really don't need to consider 1.3909 + // it here in determining whether to cache in the rule tree. However, 1.3910 + // we do need to consider it in WalkRuleTree when deciding whether to 1.3911 + // walk further up the tree. So this means that when the font struct 1.3912 + // is fully specified using *longhand* properties (excluding 1.3913 + // -moz-system-font), we won't cache in the rule tree even though we 1.3914 + // could. However, it's pretty unlikely authors will do that 1.3915 + // (although there is a pretty good chance they'll fully specify it 1.3916 + // using the 'font' shorthand). 1.3917 + 1.3918 + bool useDocumentFonts = 1.3919 + mPresContext->GetCachedBoolPref(kPresContext_UseDocumentFonts); 1.3920 + bool isXUL = PR_FALSE; 1.3921 + bool forcedWebFont = false; 1.3922 + 1.3923 + // See if we are in the chrome 1.3924 + // We only need to know this to determine if we have to use the 1.3925 + // document fonts (overriding the useDocumentFonts flag). 1.3926 + if (mPresContext->IsChrome()) { 1.3927 + // if we are not using document fonts, but this is a XUL document, 1.3928 + // then we use the document fonts anyway 1.3929 + isXUL = true; 1.3930 + } 1.3931 + 1.3932 + // Figure out if we are a generic font 1.3933 + uint8_t generic = kGenericFont_NONE; 1.3934 + // XXXldb What if we would have had a string if we hadn't been doing 1.3935 + // the optimization with a non-null aStartStruct? 1.3936 + const nsCSSValue* familyValue = aRuleData->ValueForFontFamily(); 1.3937 + if (eCSSUnit_Families == familyValue->GetUnit()) { 1.3938 + familyValue->GetStringValue(font->mFont.name); 1.3939 + // XXXldb Do we want to extract the generic for this if it's not only a 1.3940 + // generic? 1.3941 + nsFont::GetGenericID(font->mFont.name, &generic); 1.3942 + 1.3943 + if (!isXUL) { 1.3944 + gfxUserFontSet *userFonts = mPresContext->GetUserFontSet(); 1.3945 + if (userFonts) { 1.3946 + smugglerStruct sm; 1.3947 + sm.userFonts = userFonts; 1.3948 + sm.font = font; 1.3949 + 1.3950 + if (!sm.font->mFont.EnumerateFamilies(ForceFirstWebFont, &sm)) { 1.3951 + isXUL = true; // Always allow WebFont use. 1.3952 + forcedWebFont = true; 1.3953 + } 1.3954 + } 1.3955 + } 1.3956 + 1.3957 + if (!forcedWebFont && generic == kGenericFont_NONE) 1.3958 + mPresContext->AddFontAttempt(font->mFont); 1.3959 + 1.3960 + // If we aren't allowed to use document fonts, then we are only entitled 1.3961 + // to use the user's default variable-width font and fixed-width font 1.3962 + if (!isXUL && (!useDocumentFonts || 1.3963 + mPresContext->FontAttemptCountReached(font->mFont) || 1.3964 + mPresContext->FontUseCountReached(font->mFont))) { 1.3965 + // Extract the generic from the specified font family... 1.3966 + nsAutoString genericName; 1.3967 + if (!font->mFont.EnumerateFamilies(ExtractGeneric, &genericName)) { 1.3968 + // The specified font had a generic family. 1.3969 + font->mFont.name = genericName; 1.3970 + nsFont::GetGenericID(genericName, &generic); 1.3971 + 1.3972 + // ... and only use it if it's -moz-fixed or monospace 1.3973 + if (generic != kGenericFont_moz_fixed && 1.3974 + generic != kGenericFont_monospace) { 1.3975 + font->mFont.name.Truncate(); 1.3976 + generic = kGenericFont_NONE; 1.3977 + } 1.3978 + } else { 1.3979 + // The specified font did not have a generic family. 1.3980 + font->mFont.name.Truncate(); 1.3981 + generic = kGenericFont_NONE; 1.3982 + } 1.3983 + } 1.3984 + } 1.3985 + 1.3986 + // Now compute our font struct 1.3987 + if (generic == kGenericFont_NONE) { 1.3988 + // continue the normal processing 1.3989 + nsRuleNode::SetFont(mPresContext, aContext, generic, 1.3990 + aRuleData, parentFont, font, 1.3991 + aStartStruct != nullptr, canStoreInRuleTree); 1.3992 + } 1.3993 + else { 1.3994 + // re-calculate the font as a generic font 1.3995 + canStoreInRuleTree = false; 1.3996 + nsRuleNode::SetGenericFont(mPresContext, aContext, generic, 1.3997 + font); 1.3998 + } 1.3999 + 1.4000 + if (!forcedWebFont && font->mGenericID == kGenericFont_NONE) 1.4001 + mPresContext->AddFontUse(font->mFont); 1.4002 + COMPUTE_END_INHERITED(Font, font) 1.4003 +} 1.4004 + 1.4005 +template <typename T> 1.4006 +inline uint32_t ListLength(const T* aList) 1.4007 +{ 1.4008 + uint32_t len = 0; 1.4009 + while (aList) { 1.4010 + len++; 1.4011 + aList = aList->mNext; 1.4012 + } 1.4013 + return len; 1.4014 +} 1.4015 + 1.4016 + 1.4017 + 1.4018 +already_AddRefed<nsCSSShadowArray> 1.4019 +nsRuleNode::GetShadowData(const nsCSSValueList* aList, 1.4020 + nsStyleContext* aContext, 1.4021 + bool aIsBoxShadow, 1.4022 + bool& aCanStoreInRuleTree) 1.4023 +{ 1.4024 + uint32_t arrayLength = ListLength(aList); 1.4025 + 1.4026 + NS_ABORT_IF_FALSE(arrayLength > 0, 1.4027 + "Non-null text-shadow list, yet we counted 0 items."); 1.4028 + nsRefPtr<nsCSSShadowArray> shadowList = 1.4029 + new(arrayLength) nsCSSShadowArray(arrayLength); 1.4030 + 1.4031 + if (!shadowList) 1.4032 + return nullptr; 1.4033 + 1.4034 + nsStyleCoord tempCoord; 1.4035 + DebugOnly<bool> unitOK; 1.4036 + for (nsCSSShadowItem* item = shadowList->ShadowAt(0); 1.4037 + aList; 1.4038 + aList = aList->mNext, ++item) { 1.4039 + NS_ABORT_IF_FALSE(aList->mValue.GetUnit() == eCSSUnit_Array, 1.4040 + "expecting a plain array value"); 1.4041 + nsCSSValue::Array *arr = aList->mValue.GetArrayValue(); 1.4042 + // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT 1.4043 + unitOK = SetCoord(arr->Item(0), tempCoord, nsStyleCoord(), 1.4044 + SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY, 1.4045 + aContext, mPresContext, aCanStoreInRuleTree); 1.4046 + NS_ASSERTION(unitOK, "unexpected unit"); 1.4047 + item->mXOffset = tempCoord.GetCoordValue(); 1.4048 + 1.4049 + unitOK = SetCoord(arr->Item(1), tempCoord, nsStyleCoord(), 1.4050 + SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY, 1.4051 + aContext, mPresContext, aCanStoreInRuleTree); 1.4052 + NS_ASSERTION(unitOK, "unexpected unit"); 1.4053 + item->mYOffset = tempCoord.GetCoordValue(); 1.4054 + 1.4055 + // Blur radius is optional in the current box-shadow spec 1.4056 + if (arr->Item(2).GetUnit() != eCSSUnit_Null) { 1.4057 + unitOK = SetCoord(arr->Item(2), tempCoord, nsStyleCoord(), 1.4058 + SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY | 1.4059 + SETCOORD_CALC_CLAMP_NONNEGATIVE, 1.4060 + aContext, mPresContext, aCanStoreInRuleTree); 1.4061 + NS_ASSERTION(unitOK, "unexpected unit"); 1.4062 + item->mRadius = tempCoord.GetCoordValue(); 1.4063 + } else { 1.4064 + item->mRadius = 0; 1.4065 + } 1.4066 + 1.4067 + // Find the spread radius 1.4068 + if (aIsBoxShadow && arr->Item(3).GetUnit() != eCSSUnit_Null) { 1.4069 + unitOK = SetCoord(arr->Item(3), tempCoord, nsStyleCoord(), 1.4070 + SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY, 1.4071 + aContext, mPresContext, aCanStoreInRuleTree); 1.4072 + NS_ASSERTION(unitOK, "unexpected unit"); 1.4073 + item->mSpread = tempCoord.GetCoordValue(); 1.4074 + } else { 1.4075 + item->mSpread = 0; 1.4076 + } 1.4077 + 1.4078 + if (arr->Item(4).GetUnit() != eCSSUnit_Null) { 1.4079 + item->mHasColor = true; 1.4080 + // 2nd argument can be bogus since inherit is not a valid color 1.4081 + unitOK = SetColor(arr->Item(4), 0, mPresContext, aContext, item->mColor, 1.4082 + aCanStoreInRuleTree); 1.4083 + NS_ASSERTION(unitOK, "unexpected unit"); 1.4084 + } 1.4085 + 1.4086 + if (aIsBoxShadow && arr->Item(5).GetUnit() == eCSSUnit_Enumerated) { 1.4087 + NS_ASSERTION(arr->Item(5).GetIntValue() == NS_STYLE_BOX_SHADOW_INSET, 1.4088 + "invalid keyword type for box shadow"); 1.4089 + item->mInset = true; 1.4090 + } else { 1.4091 + item->mInset = false; 1.4092 + } 1.4093 + } 1.4094 + 1.4095 + return shadowList.forget(); 1.4096 +} 1.4097 + 1.4098 +const void* 1.4099 +nsRuleNode::ComputeTextData(void* aStartStruct, 1.4100 + const nsRuleData* aRuleData, 1.4101 + nsStyleContext* aContext, 1.4102 + nsRuleNode* aHighestNode, 1.4103 + const RuleDetail aRuleDetail, 1.4104 + const bool aCanStoreInRuleTree) 1.4105 +{ 1.4106 + COMPUTE_START_INHERITED(Text, (), text, parentText) 1.4107 + 1.4108 + // tab-size: integer, inherit 1.4109 + SetDiscrete(*aRuleData->ValueForTabSize(), 1.4110 + text->mTabSize, canStoreInRuleTree, 1.4111 + SETDSC_INTEGER | SETDSC_UNSET_INHERIT, parentText->mTabSize, 1.4112 + NS_STYLE_TABSIZE_INITIAL, 0, 0, 0, 0); 1.4113 + 1.4114 + // letter-spacing: normal, length, inherit 1.4115 + SetCoord(*aRuleData->ValueForLetterSpacing(), 1.4116 + text->mLetterSpacing, parentText->mLetterSpacing, 1.4117 + SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL | 1.4118 + SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INHERIT, 1.4119 + aContext, mPresContext, canStoreInRuleTree); 1.4120 + 1.4121 + // text-shadow: none, list, inherit, initial 1.4122 + const nsCSSValue* textShadowValue = aRuleData->ValueForTextShadow(); 1.4123 + if (textShadowValue->GetUnit() != eCSSUnit_Null) { 1.4124 + text->mTextShadow = nullptr; 1.4125 + 1.4126 + // Don't need to handle none/initial explicitly: The above assignment 1.4127 + // takes care of that 1.4128 + if (textShadowValue->GetUnit() == eCSSUnit_Inherit || 1.4129 + textShadowValue->GetUnit() == eCSSUnit_Unset) { 1.4130 + canStoreInRuleTree = false; 1.4131 + text->mTextShadow = parentText->mTextShadow; 1.4132 + } else if (textShadowValue->GetUnit() == eCSSUnit_List || 1.4133 + textShadowValue->GetUnit() == eCSSUnit_ListDep) { 1.4134 + // List of arrays 1.4135 + text->mTextShadow = GetShadowData(textShadowValue->GetListValue(), 1.4136 + aContext, false, canStoreInRuleTree); 1.4137 + } 1.4138 + } 1.4139 + 1.4140 + // line-height: normal, number, length, percent, inherit 1.4141 + const nsCSSValue* lineHeightValue = aRuleData->ValueForLineHeight(); 1.4142 + if (eCSSUnit_Percent == lineHeightValue->GetUnit()) { 1.4143 + canStoreInRuleTree = false; 1.4144 + // Use |mFont.size| to pick up minimum font size. 1.4145 + text->mLineHeight.SetCoordValue( 1.4146 + NSToCoordRound(float(aContext->StyleFont()->mFont.size) * 1.4147 + lineHeightValue->GetPercentValue())); 1.4148 + } 1.4149 + else if (eCSSUnit_Initial == lineHeightValue->GetUnit() || 1.4150 + eCSSUnit_System_Font == lineHeightValue->GetUnit()) { 1.4151 + text->mLineHeight.SetNormalValue(); 1.4152 + } 1.4153 + else { 1.4154 + SetCoord(*lineHeightValue, text->mLineHeight, parentText->mLineHeight, 1.4155 + SETCOORD_LEH | SETCOORD_FACTOR | SETCOORD_NORMAL | 1.4156 + SETCOORD_UNSET_INHERIT, 1.4157 + aContext, mPresContext, canStoreInRuleTree); 1.4158 + if (lineHeightValue->IsLengthUnit() && 1.4159 + !lineHeightValue->IsRelativeLengthUnit()) { 1.4160 + nscoord lh = nsStyleFont::ZoomText(mPresContext, 1.4161 + text->mLineHeight.GetCoordValue()); 1.4162 + 1.4163 + canStoreInRuleTree = false; 1.4164 + const nsStyleFont *font = aContext->StyleFont(); 1.4165 + nscoord minimumFontSize = mPresContext->MinFontSize(font->mLanguage); 1.4166 + 1.4167 + if (minimumFontSize > 0 && !mPresContext->IsChrome()) { 1.4168 + if (font->mSize != 0) { 1.4169 + lh = nscoord(float(lh) * float(font->mFont.size) / float(font->mSize)); 1.4170 + } else { 1.4171 + lh = minimumFontSize; 1.4172 + } 1.4173 + } 1.4174 + text->mLineHeight.SetCoordValue(lh); 1.4175 + } 1.4176 + } 1.4177 + 1.4178 + 1.4179 + // text-align: enum, string, pair(enum|string), inherit, initial 1.4180 + // NOTE: string is not implemented yet. 1.4181 + const nsCSSValue* textAlignValue = aRuleData->ValueForTextAlign(); 1.4182 + text->mTextAlignTrue = false; 1.4183 + if (eCSSUnit_String == textAlignValue->GetUnit()) { 1.4184 + NS_NOTYETIMPLEMENTED("align string"); 1.4185 + } else if (eCSSUnit_Enumerated == textAlignValue->GetUnit() && 1.4186 + NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT == 1.4187 + textAlignValue->GetIntValue()) { 1.4188 + canStoreInRuleTree = false; 1.4189 + uint8_t parentAlign = parentText->mTextAlign; 1.4190 + text->mTextAlign = (NS_STYLE_TEXT_ALIGN_DEFAULT == parentAlign) ? 1.4191 + NS_STYLE_TEXT_ALIGN_CENTER : parentAlign; 1.4192 + } else { 1.4193 + if (eCSSUnit_Pair == textAlignValue->GetUnit()) { 1.4194 + // Two values were specified, one must be 'true'. 1.4195 + text->mTextAlignTrue = true; 1.4196 + const nsCSSValuePair& textAlignValuePair = textAlignValue->GetPairValue(); 1.4197 + textAlignValue = &textAlignValuePair.mXValue; 1.4198 + if (eCSSUnit_Enumerated == textAlignValue->GetUnit()) { 1.4199 + if (textAlignValue->GetIntValue() == NS_STYLE_TEXT_ALIGN_TRUE) { 1.4200 + textAlignValue = &textAlignValuePair.mYValue; 1.4201 + } 1.4202 + } else if (eCSSUnit_String == textAlignValue->GetUnit()) { 1.4203 + NS_NOTYETIMPLEMENTED("align string"); 1.4204 + } 1.4205 + } else if (eCSSUnit_Inherit == textAlignValue->GetUnit() || 1.4206 + eCSSUnit_Unset == textAlignValue->GetUnit()) { 1.4207 + text->mTextAlignTrue = parentText->mTextAlignTrue; 1.4208 + } 1.4209 + SetDiscrete(*textAlignValue, text->mTextAlign, canStoreInRuleTree, 1.4210 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4211 + parentText->mTextAlign, 1.4212 + NS_STYLE_TEXT_ALIGN_DEFAULT, 0, 0, 0, 0); 1.4213 + } 1.4214 + 1.4215 + // text-align-last: enum, pair(enum), inherit, initial 1.4216 + const nsCSSValue* textAlignLastValue = aRuleData->ValueForTextAlignLast(); 1.4217 + text->mTextAlignLastTrue = false; 1.4218 + if (eCSSUnit_Pair == textAlignLastValue->GetUnit()) { 1.4219 + // Two values were specified, one must be 'true'. 1.4220 + text->mTextAlignLastTrue = true; 1.4221 + const nsCSSValuePair& textAlignLastValuePair = textAlignLastValue->GetPairValue(); 1.4222 + textAlignLastValue = &textAlignLastValuePair.mXValue; 1.4223 + if (eCSSUnit_Enumerated == textAlignLastValue->GetUnit()) { 1.4224 + if (textAlignLastValue->GetIntValue() == NS_STYLE_TEXT_ALIGN_TRUE) { 1.4225 + textAlignLastValue = &textAlignLastValuePair.mYValue; 1.4226 + } 1.4227 + } 1.4228 + } else if (eCSSUnit_Inherit == textAlignLastValue->GetUnit() || 1.4229 + eCSSUnit_Unset == textAlignLastValue->GetUnit()) { 1.4230 + text->mTextAlignLastTrue = parentText->mTextAlignLastTrue; 1.4231 + } 1.4232 + SetDiscrete(*textAlignLastValue, text->mTextAlignLast, 1.4233 + canStoreInRuleTree, 1.4234 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4235 + parentText->mTextAlignLast, 1.4236 + NS_STYLE_TEXT_ALIGN_AUTO, 0, 0, 0, 0); 1.4237 + 1.4238 + // text-indent: length, percent, calc, inherit, initial 1.4239 + SetCoord(*aRuleData->ValueForTextIndent(), text->mTextIndent, parentText->mTextIndent, 1.4240 + SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC | 1.4241 + SETCOORD_UNSET_INHERIT, 1.4242 + aContext, mPresContext, canStoreInRuleTree); 1.4243 + 1.4244 + // text-transform: enum, inherit, initial 1.4245 + SetDiscrete(*aRuleData->ValueForTextTransform(), text->mTextTransform, canStoreInRuleTree, 1.4246 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4247 + parentText->mTextTransform, 1.4248 + NS_STYLE_TEXT_TRANSFORM_NONE, 0, 0, 0, 0); 1.4249 + 1.4250 + // white-space: enum, inherit, initial 1.4251 + SetDiscrete(*aRuleData->ValueForWhiteSpace(), text->mWhiteSpace, canStoreInRuleTree, 1.4252 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4253 + parentText->mWhiteSpace, 1.4254 + NS_STYLE_WHITESPACE_NORMAL, 0, 0, 0, 0); 1.4255 + 1.4256 + // word-break: enum, inherit, initial 1.4257 + SetDiscrete(*aRuleData->ValueForWordBreak(), text->mWordBreak, canStoreInRuleTree, 1.4258 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4259 + parentText->mWordBreak, 1.4260 + NS_STYLE_WORDBREAK_NORMAL, 0, 0, 0, 0); 1.4261 + 1.4262 + // word-spacing: normal, length, inherit 1.4263 + nsStyleCoord tempCoord; 1.4264 + const nsCSSValue* wordSpacingValue = aRuleData->ValueForWordSpacing(); 1.4265 + if (SetCoord(*wordSpacingValue, tempCoord, 1.4266 + nsStyleCoord(parentText->mWordSpacing, 1.4267 + nsStyleCoord::CoordConstructor), 1.4268 + SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL | 1.4269 + SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INHERIT, 1.4270 + aContext, mPresContext, canStoreInRuleTree)) { 1.4271 + if (tempCoord.GetUnit() == eStyleUnit_Coord) { 1.4272 + text->mWordSpacing = tempCoord.GetCoordValue(); 1.4273 + } else if (tempCoord.GetUnit() == eStyleUnit_Normal) { 1.4274 + text->mWordSpacing = 0; 1.4275 + } else { 1.4276 + NS_NOTREACHED("unexpected unit"); 1.4277 + } 1.4278 + } else { 1.4279 + NS_ASSERTION(wordSpacingValue->GetUnit() == eCSSUnit_Null, 1.4280 + "unexpected unit"); 1.4281 + } 1.4282 + 1.4283 + // word-wrap: enum, inherit, initial 1.4284 + SetDiscrete(*aRuleData->ValueForWordWrap(), text->mWordWrap, canStoreInRuleTree, 1.4285 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4286 + parentText->mWordWrap, 1.4287 + NS_STYLE_WORDWRAP_NORMAL, 0, 0, 0, 0); 1.4288 + 1.4289 + // hyphens: enum, inherit, initial 1.4290 + SetDiscrete(*aRuleData->ValueForHyphens(), text->mHyphens, canStoreInRuleTree, 1.4291 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4292 + parentText->mHyphens, 1.4293 + NS_STYLE_HYPHENS_MANUAL, 0, 0, 0, 0); 1.4294 + 1.4295 + // text-size-adjust: none, auto, inherit, initial 1.4296 + SetDiscrete(*aRuleData->ValueForTextSizeAdjust(), text->mTextSizeAdjust, 1.4297 + canStoreInRuleTree, 1.4298 + SETDSC_NONE | SETDSC_AUTO | SETDSC_UNSET_INHERIT, 1.4299 + parentText->mTextSizeAdjust, 1.4300 + NS_STYLE_TEXT_SIZE_ADJUST_AUTO, // initial value 1.4301 + NS_STYLE_TEXT_SIZE_ADJUST_AUTO, // auto value 1.4302 + NS_STYLE_TEXT_SIZE_ADJUST_NONE, // none value 1.4303 + 0, 0); 1.4304 + 1.4305 + // -moz-text-discard: enum, inherit, initial 1.4306 + SetDiscrete(*aRuleData->ValueForControlCharacterVisibility(), 1.4307 + text->mControlCharacterVisibility, 1.4308 + canStoreInRuleTree, 1.4309 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4310 + parentText->mControlCharacterVisibility, 1.4311 + NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN, 0, 0, 0, 0); 1.4312 + 1.4313 + // text-orientation: enum, inherit, initial 1.4314 + SetDiscrete(*aRuleData->ValueForTextOrientation(), text->mTextOrientation, 1.4315 + canStoreInRuleTree, 1.4316 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4317 + parentText->mTextOrientation, 1.4318 + NS_STYLE_TEXT_ORIENTATION_AUTO, 0, 0, 0, 0); 1.4319 + 1.4320 + // text-combine-upright: enum, inherit, initial 1.4321 + SetDiscrete(*aRuleData->ValueForTextCombineUpright(), 1.4322 + text->mTextCombineUpright, 1.4323 + canStoreInRuleTree, 1.4324 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4325 + parentText->mTextCombineUpright, 1.4326 + NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE, 0, 0, 0, 0); 1.4327 + 1.4328 + COMPUTE_END_INHERITED(Text, text) 1.4329 +} 1.4330 + 1.4331 +const void* 1.4332 +nsRuleNode::ComputeTextResetData(void* aStartStruct, 1.4333 + const nsRuleData* aRuleData, 1.4334 + nsStyleContext* aContext, 1.4335 + nsRuleNode* aHighestNode, 1.4336 + const RuleDetail aRuleDetail, 1.4337 + const bool aCanStoreInRuleTree) 1.4338 +{ 1.4339 + COMPUTE_START_RESET(TextReset, (), text, parentText) 1.4340 + 1.4341 + // vertical-align: enum, length, percent, calc, inherit 1.4342 + const nsCSSValue* verticalAlignValue = aRuleData->ValueForVerticalAlign(); 1.4343 + if (!SetCoord(*verticalAlignValue, text->mVerticalAlign, 1.4344 + parentText->mVerticalAlign, 1.4345 + SETCOORD_LPH | SETCOORD_ENUMERATED | SETCOORD_STORE_CALC, 1.4346 + aContext, mPresContext, canStoreInRuleTree)) { 1.4347 + if (eCSSUnit_Initial == verticalAlignValue->GetUnit() || 1.4348 + eCSSUnit_Unset == verticalAlignValue->GetUnit()) { 1.4349 + text->mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE, 1.4350 + eStyleUnit_Enumerated); 1.4351 + } 1.4352 + } 1.4353 + 1.4354 + // text-decoration-line: enum (bit field), inherit, initial 1.4355 + const nsCSSValue* decorationLineValue = 1.4356 + aRuleData->ValueForTextDecorationLine(); 1.4357 + if (eCSSUnit_Enumerated == decorationLineValue->GetUnit()) { 1.4358 + int32_t td = decorationLineValue->GetIntValue(); 1.4359 + text->mTextDecorationLine = td; 1.4360 + if (td & NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS) { 1.4361 + bool underlineLinks = 1.4362 + mPresContext->GetCachedBoolPref(kPresContext_UnderlineLinks); 1.4363 + if (underlineLinks) { 1.4364 + text->mTextDecorationLine |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE; 1.4365 + } 1.4366 + else { 1.4367 + text->mTextDecorationLine &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE; 1.4368 + } 1.4369 + } 1.4370 + } else if (eCSSUnit_Inherit == decorationLineValue->GetUnit()) { 1.4371 + canStoreInRuleTree = false; 1.4372 + text->mTextDecorationLine = parentText->mTextDecorationLine; 1.4373 + } else if (eCSSUnit_Initial == decorationLineValue->GetUnit() || 1.4374 + eCSSUnit_Unset == decorationLineValue->GetUnit()) { 1.4375 + text->mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE; 1.4376 + } 1.4377 + 1.4378 + // text-decoration-color: color, string, enum, inherit, initial 1.4379 + const nsCSSValue* decorationColorValue = 1.4380 + aRuleData->ValueForTextDecorationColor(); 1.4381 + nscolor decorationColor; 1.4382 + if (eCSSUnit_Inherit == decorationColorValue->GetUnit()) { 1.4383 + canStoreInRuleTree = false; 1.4384 + if (parentContext) { 1.4385 + bool isForeground; 1.4386 + parentText->GetDecorationColor(decorationColor, isForeground); 1.4387 + if (isForeground) { 1.4388 + text->SetDecorationColor(parentContext->StyleColor()->mColor); 1.4389 + } else { 1.4390 + text->SetDecorationColor(decorationColor); 1.4391 + } 1.4392 + } else { 1.4393 + text->SetDecorationColorToForeground(); 1.4394 + } 1.4395 + } 1.4396 + else if (eCSSUnit_EnumColor == decorationColorValue->GetUnit() && 1.4397 + decorationColorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) { 1.4398 + text->SetDecorationColorToForeground(); 1.4399 + } 1.4400 + else if (SetColor(*decorationColorValue, 0, mPresContext, aContext, 1.4401 + decorationColor, canStoreInRuleTree)) { 1.4402 + text->SetDecorationColor(decorationColor); 1.4403 + } 1.4404 + else if (eCSSUnit_Initial == decorationColorValue->GetUnit() || 1.4405 + eCSSUnit_Unset == decorationColorValue->GetUnit() || 1.4406 + eCSSUnit_Enumerated == decorationColorValue->GetUnit()) { 1.4407 + NS_ABORT_IF_FALSE(eCSSUnit_Enumerated != decorationColorValue->GetUnit() || 1.4408 + decorationColorValue->GetIntValue() == 1.4409 + NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR, 1.4410 + "unexpected enumerated value"); 1.4411 + text->SetDecorationColorToForeground(); 1.4412 + } 1.4413 + 1.4414 + // text-decoration-style: enum, inherit, initial 1.4415 + const nsCSSValue* decorationStyleValue = 1.4416 + aRuleData->ValueForTextDecorationStyle(); 1.4417 + if (eCSSUnit_Enumerated == decorationStyleValue->GetUnit()) { 1.4418 + text->SetDecorationStyle(decorationStyleValue->GetIntValue()); 1.4419 + } else if (eCSSUnit_Inherit == decorationStyleValue->GetUnit()) { 1.4420 + text->SetDecorationStyle(parentText->GetDecorationStyle()); 1.4421 + canStoreInRuleTree = false; 1.4422 + } else if (eCSSUnit_Initial == decorationStyleValue->GetUnit() || 1.4423 + eCSSUnit_Unset == decorationStyleValue->GetUnit()) { 1.4424 + text->SetDecorationStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID); 1.4425 + } 1.4426 + 1.4427 + // text-overflow: enum, string, pair(enum|string), inherit, initial 1.4428 + const nsCSSValue* textOverflowValue = 1.4429 + aRuleData->ValueForTextOverflow(); 1.4430 + if (eCSSUnit_Initial == textOverflowValue->GetUnit() || 1.4431 + eCSSUnit_Unset == textOverflowValue->GetUnit()) { 1.4432 + text->mTextOverflow = nsStyleTextOverflow(); 1.4433 + } else if (eCSSUnit_Inherit == textOverflowValue->GetUnit()) { 1.4434 + canStoreInRuleTree = false; 1.4435 + text->mTextOverflow = parentText->mTextOverflow; 1.4436 + } else if (eCSSUnit_Enumerated == textOverflowValue->GetUnit()) { 1.4437 + // A single enumerated value. 1.4438 + SetDiscrete(*textOverflowValue, text->mTextOverflow.mRight.mType, 1.4439 + canStoreInRuleTree, 1.4440 + SETDSC_ENUMERATED, parentText->mTextOverflow.mRight.mType, 1.4441 + NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0); 1.4442 + text->mTextOverflow.mRight.mString.Truncate(); 1.4443 + text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP; 1.4444 + text->mTextOverflow.mLeft.mString.Truncate(); 1.4445 + text->mTextOverflow.mLogicalDirections = true; 1.4446 + } else if (eCSSUnit_String == textOverflowValue->GetUnit()) { 1.4447 + // A single string value. 1.4448 + text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING; 1.4449 + textOverflowValue->GetStringValue(text->mTextOverflow.mRight.mString); 1.4450 + text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP; 1.4451 + text->mTextOverflow.mLeft.mString.Truncate(); 1.4452 + text->mTextOverflow.mLogicalDirections = true; 1.4453 + } else if (eCSSUnit_Pair == textOverflowValue->GetUnit()) { 1.4454 + // Two values were specified. 1.4455 + text->mTextOverflow.mLogicalDirections = false; 1.4456 + const nsCSSValuePair& textOverflowValuePair = 1.4457 + textOverflowValue->GetPairValue(); 1.4458 + 1.4459 + const nsCSSValue *textOverflowLeftValue = &textOverflowValuePair.mXValue; 1.4460 + if (eCSSUnit_Enumerated == textOverflowLeftValue->GetUnit()) { 1.4461 + SetDiscrete(*textOverflowLeftValue, text->mTextOverflow.mLeft.mType, 1.4462 + canStoreInRuleTree, 1.4463 + SETDSC_ENUMERATED, parentText->mTextOverflow.mLeft.mType, 1.4464 + NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0); 1.4465 + text->mTextOverflow.mLeft.mString.Truncate(); 1.4466 + } else if (eCSSUnit_String == textOverflowLeftValue->GetUnit()) { 1.4467 + textOverflowLeftValue->GetStringValue(text->mTextOverflow.mLeft.mString); 1.4468 + text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_STRING; 1.4469 + } 1.4470 + 1.4471 + const nsCSSValue *textOverflowRightValue = &textOverflowValuePair.mYValue; 1.4472 + if (eCSSUnit_Enumerated == textOverflowRightValue->GetUnit()) { 1.4473 + SetDiscrete(*textOverflowRightValue, text->mTextOverflow.mRight.mType, 1.4474 + canStoreInRuleTree, 1.4475 + SETDSC_ENUMERATED, parentText->mTextOverflow.mRight.mType, 1.4476 + NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0); 1.4477 + text->mTextOverflow.mRight.mString.Truncate(); 1.4478 + } else if (eCSSUnit_String == textOverflowRightValue->GetUnit()) { 1.4479 + textOverflowRightValue->GetStringValue(text->mTextOverflow.mRight.mString); 1.4480 + text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING; 1.4481 + } 1.4482 + } 1.4483 + 1.4484 + // unicode-bidi: enum, inherit, initial 1.4485 + SetDiscrete(*aRuleData->ValueForUnicodeBidi(), text->mUnicodeBidi, canStoreInRuleTree, 1.4486 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.4487 + parentText->mUnicodeBidi, 1.4488 + NS_STYLE_UNICODE_BIDI_NORMAL, 0, 0, 0, 0); 1.4489 + 1.4490 + COMPUTE_END_RESET(TextReset, text) 1.4491 +} 1.4492 + 1.4493 +const void* 1.4494 +nsRuleNode::ComputeUserInterfaceData(void* aStartStruct, 1.4495 + const nsRuleData* aRuleData, 1.4496 + nsStyleContext* aContext, 1.4497 + nsRuleNode* aHighestNode, 1.4498 + const RuleDetail aRuleDetail, 1.4499 + const bool aCanStoreInRuleTree) 1.4500 +{ 1.4501 + COMPUTE_START_INHERITED(UserInterface, (), ui, parentUI) 1.4502 + 1.4503 + // cursor: enum, url, inherit 1.4504 + const nsCSSValue* cursorValue = aRuleData->ValueForCursor(); 1.4505 + nsCSSUnit cursorUnit = cursorValue->GetUnit(); 1.4506 + if (cursorUnit != eCSSUnit_Null) { 1.4507 + delete [] ui->mCursorArray; 1.4508 + ui->mCursorArray = nullptr; 1.4509 + ui->mCursorArrayLength = 0; 1.4510 + 1.4511 + if (cursorUnit == eCSSUnit_Inherit || 1.4512 + cursorUnit == eCSSUnit_Unset) { 1.4513 + canStoreInRuleTree = false; 1.4514 + ui->mCursor = parentUI->mCursor; 1.4515 + ui->CopyCursorArrayFrom(*parentUI); 1.4516 + } 1.4517 + else if (cursorUnit == eCSSUnit_Initial) { 1.4518 + ui->mCursor = NS_STYLE_CURSOR_AUTO; 1.4519 + } 1.4520 + else { 1.4521 + // The parser will never create a list that is *all* URL values -- 1.4522 + // that's invalid. 1.4523 + NS_ABORT_IF_FALSE(cursorUnit == eCSSUnit_List || 1.4524 + cursorUnit == eCSSUnit_ListDep, 1.4525 + nsPrintfCString("unrecognized cursor unit %d", 1.4526 + cursorUnit).get()); 1.4527 + const nsCSSValueList* list = cursorValue->GetListValue(); 1.4528 + const nsCSSValueList* list2 = list; 1.4529 + nsIDocument* doc = aContext->PresContext()->Document(); 1.4530 + uint32_t arrayLength = 0; 1.4531 + for ( ; list->mValue.GetUnit() == eCSSUnit_Array; list = list->mNext) 1.4532 + if (list->mValue.GetArrayValue()->Item(0).GetImageValue(doc)) 1.4533 + ++arrayLength; 1.4534 + 1.4535 + if (arrayLength != 0) { 1.4536 + ui->mCursorArray = new nsCursorImage[arrayLength]; 1.4537 + if (ui->mCursorArray) { 1.4538 + ui->mCursorArrayLength = arrayLength; 1.4539 + 1.4540 + for (nsCursorImage *item = ui->mCursorArray; 1.4541 + list2->mValue.GetUnit() == eCSSUnit_Array; 1.4542 + list2 = list2->mNext) { 1.4543 + nsCSSValue::Array *arr = list2->mValue.GetArrayValue(); 1.4544 + imgIRequest *req = arr->Item(0).GetImageValue(doc); 1.4545 + if (req) { 1.4546 + item->SetImage(req); 1.4547 + if (arr->Item(1).GetUnit() != eCSSUnit_Null) { 1.4548 + item->mHaveHotspot = true; 1.4549 + item->mHotspotX = arr->Item(1).GetFloatValue(), 1.4550 + item->mHotspotY = arr->Item(2).GetFloatValue(); 1.4551 + } 1.4552 + ++item; 1.4553 + } 1.4554 + } 1.4555 + } 1.4556 + } 1.4557 + 1.4558 + NS_ASSERTION(list, "Must have non-array value at the end"); 1.4559 + NS_ASSERTION(list->mValue.GetUnit() == eCSSUnit_Enumerated, 1.4560 + "Unexpected fallback value at end of cursor list"); 1.4561 + ui->mCursor = list->mValue.GetIntValue(); 1.4562 + } 1.4563 + } 1.4564 + 1.4565 + // user-input: enum, inherit, initial 1.4566 + SetDiscrete(*aRuleData->ValueForUserInput(), 1.4567 + ui->mUserInput, canStoreInRuleTree, 1.4568 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4569 + parentUI->mUserInput, 1.4570 + NS_STYLE_USER_INPUT_AUTO, 0, 0, 0, 0); 1.4571 + 1.4572 + // user-modify: enum, inherit, initial 1.4573 + SetDiscrete(*aRuleData->ValueForUserModify(), 1.4574 + ui->mUserModify, canStoreInRuleTree, 1.4575 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4576 + parentUI->mUserModify, 1.4577 + NS_STYLE_USER_MODIFY_READ_ONLY, 1.4578 + 0, 0, 0, 0); 1.4579 + 1.4580 + // user-focus: enum, inherit, initial 1.4581 + SetDiscrete(*aRuleData->ValueForUserFocus(), 1.4582 + ui->mUserFocus, canStoreInRuleTree, 1.4583 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.4584 + parentUI->mUserFocus, 1.4585 + NS_STYLE_USER_FOCUS_NONE, 0, 0, 0, 0); 1.4586 + 1.4587 + COMPUTE_END_INHERITED(UserInterface, ui) 1.4588 +} 1.4589 + 1.4590 +const void* 1.4591 +nsRuleNode::ComputeUIResetData(void* aStartStruct, 1.4592 + const nsRuleData* aRuleData, 1.4593 + nsStyleContext* aContext, 1.4594 + nsRuleNode* aHighestNode, 1.4595 + const RuleDetail aRuleDetail, 1.4596 + const bool aCanStoreInRuleTree) 1.4597 +{ 1.4598 + COMPUTE_START_RESET(UIReset, (), ui, parentUI) 1.4599 + 1.4600 + // user-select: enum, inherit, initial 1.4601 + SetDiscrete(*aRuleData->ValueForUserSelect(), 1.4602 + ui->mUserSelect, canStoreInRuleTree, 1.4603 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.4604 + parentUI->mUserSelect, 1.4605 + NS_STYLE_USER_SELECT_AUTO, 0, 0, 0, 0); 1.4606 + 1.4607 + // ime-mode: enum, inherit, initial 1.4608 + SetDiscrete(*aRuleData->ValueForImeMode(), 1.4609 + ui->mIMEMode, canStoreInRuleTree, 1.4610 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.4611 + parentUI->mIMEMode, 1.4612 + NS_STYLE_IME_MODE_AUTO, 0, 0, 0, 0); 1.4613 + 1.4614 + // force-broken-image-icons: integer, inherit, initial 1.4615 + SetDiscrete(*aRuleData->ValueForForceBrokenImageIcon(), 1.4616 + ui->mForceBrokenImageIcon, 1.4617 + canStoreInRuleTree, 1.4618 + SETDSC_INTEGER | SETDSC_UNSET_INITIAL, 1.4619 + parentUI->mForceBrokenImageIcon, 1.4620 + 0, 0, 0, 0, 0); 1.4621 + 1.4622 + // -moz-window-shadow: enum, inherit, initial 1.4623 + SetDiscrete(*aRuleData->ValueForWindowShadow(), 1.4624 + ui->mWindowShadow, canStoreInRuleTree, 1.4625 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.4626 + parentUI->mWindowShadow, 1.4627 + NS_STYLE_WINDOW_SHADOW_DEFAULT, 0, 0, 0, 0); 1.4628 + 1.4629 + COMPUTE_END_RESET(UIReset, ui) 1.4630 +} 1.4631 + 1.4632 +// Information about each transition or animation property that is 1.4633 +// constant. 1.4634 +struct TransitionPropInfo { 1.4635 + nsCSSProperty property; 1.4636 + // Location of the count of the property's computed value. 1.4637 + uint32_t nsStyleDisplay::* sdCount; 1.4638 +}; 1.4639 + 1.4640 +// Each property's index in this array must match its index in the 1.4641 +// mutable array |transitionPropData| below. 1.4642 +static const TransitionPropInfo transitionPropInfo[4] = { 1.4643 + { eCSSProperty_transition_delay, 1.4644 + &nsStyleDisplay::mTransitionDelayCount }, 1.4645 + { eCSSProperty_transition_duration, 1.4646 + &nsStyleDisplay::mTransitionDurationCount }, 1.4647 + { eCSSProperty_transition_property, 1.4648 + &nsStyleDisplay::mTransitionPropertyCount }, 1.4649 + { eCSSProperty_transition_timing_function, 1.4650 + &nsStyleDisplay::mTransitionTimingFunctionCount }, 1.4651 +}; 1.4652 + 1.4653 +// Each property's index in this array must match its index in the 1.4654 +// mutable array |animationPropData| below. 1.4655 +static const TransitionPropInfo animationPropInfo[8] = { 1.4656 + { eCSSProperty_animation_delay, 1.4657 + &nsStyleDisplay::mAnimationDelayCount }, 1.4658 + { eCSSProperty_animation_duration, 1.4659 + &nsStyleDisplay::mAnimationDurationCount }, 1.4660 + { eCSSProperty_animation_name, 1.4661 + &nsStyleDisplay::mAnimationNameCount }, 1.4662 + { eCSSProperty_animation_timing_function, 1.4663 + &nsStyleDisplay::mAnimationTimingFunctionCount }, 1.4664 + { eCSSProperty_animation_direction, 1.4665 + &nsStyleDisplay::mAnimationDirectionCount }, 1.4666 + { eCSSProperty_animation_fill_mode, 1.4667 + &nsStyleDisplay::mAnimationFillModeCount }, 1.4668 + { eCSSProperty_animation_play_state, 1.4669 + &nsStyleDisplay::mAnimationPlayStateCount }, 1.4670 + { eCSSProperty_animation_iteration_count, 1.4671 + &nsStyleDisplay::mAnimationIterationCountCount }, 1.4672 +}; 1.4673 + 1.4674 +// Information about each transition or animation property that changes 1.4675 +// during ComputeDisplayData. 1.4676 +struct TransitionPropData { 1.4677 + const nsCSSValueList *list; 1.4678 + nsCSSUnit unit; 1.4679 + uint32_t num; 1.4680 +}; 1.4681 + 1.4682 +static uint32_t 1.4683 +CountTransitionProps(const TransitionPropInfo* aInfo, 1.4684 + TransitionPropData* aData, 1.4685 + size_t aLength, 1.4686 + nsStyleDisplay* aDisplay, 1.4687 + const nsStyleDisplay* aParentDisplay, 1.4688 + const nsRuleData* aRuleData, 1.4689 + bool& aCanStoreInRuleTree) 1.4690 +{ 1.4691 + // The four transition properties or eight animation properties are 1.4692 + // stored in nsCSSDisplay in a single array for all properties. The 1.4693 + // number of transitions is equal to the number of items in the 1.4694 + // longest property's value. Properties that have fewer values than 1.4695 + // the longest are filled in by repeating the list. However, this 1.4696 + // repetition does not extend the computed value of that particular 1.4697 + // property (for purposes of inheritance, or, in our code, for when 1.4698 + // other properties are overridden by a more specific rule). 1.4699 + 1.4700 + // But actually, since the spec isn't clear yet, we'll fully compute 1.4701 + // all of them (so we can switch easily later), but only care about 1.4702 + // the ones up to the number of items for 'transition-property', per 1.4703 + // http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html . 1.4704 + 1.4705 + // Transitions are difficult to handle correctly because of this. For 1.4706 + // example, we need to handle scenarios such as: 1.4707 + // * a more general rule specifies transition-property: a, b, c; 1.4708 + // * a more specific rule overrides as transition-property: d; 1.4709 + // 1.4710 + // If only the general rule applied, we would fill in the extra 1.4711 + // properties (duration, delay, etc) with initial values to create 3 1.4712 + // fully-specified transitions. But when the more specific rule 1.4713 + // applies, we should only create a single transition. In order to do 1.4714 + // this we need to remember which properties were explicitly specified 1.4715 + // and which ones were just filled in with initial values to get a 1.4716 + // fully-specified transition, which we do by remembering the number 1.4717 + // of values for each property. 1.4718 + 1.4719 + uint32_t numTransitions = 0; 1.4720 + for (size_t i = 0; i < aLength; ++i) { 1.4721 + const TransitionPropInfo& info = aInfo[i]; 1.4722 + TransitionPropData& data = aData[i]; 1.4723 + 1.4724 + // cache whether any of the properties are specified as 'inherit' so 1.4725 + // we can use it below 1.4726 + 1.4727 + const nsCSSValue& value = *aRuleData->ValueFor(info.property); 1.4728 + data.unit = value.GetUnit(); 1.4729 + data.list = (value.GetUnit() == eCSSUnit_List || 1.4730 + value.GetUnit() == eCSSUnit_ListDep) 1.4731 + ? value.GetListValue() : nullptr; 1.4732 + 1.4733 + // General algorithm to determine how many total transitions we need 1.4734 + // to build. For each property: 1.4735 + // - if there is no value specified in for the property in 1.4736 + // displayData, use the values from the start struct, but only if 1.4737 + // they were explicitly specified 1.4738 + // - if there is a value specified for the property in displayData: 1.4739 + // - if the value is 'inherit', count the number of values for 1.4740 + // that property are specified by the parent, but only those 1.4741 + // that were explicitly specified 1.4742 + // - otherwise, count the number of values specified in displayData 1.4743 + 1.4744 + 1.4745 + // calculate number of elements 1.4746 + if (data.unit == eCSSUnit_Inherit) { 1.4747 + data.num = aParentDisplay->*(info.sdCount); 1.4748 + aCanStoreInRuleTree = false; 1.4749 + } else if (data.list) { 1.4750 + data.num = ListLength(data.list); 1.4751 + } else { 1.4752 + data.num = aDisplay->*(info.sdCount); 1.4753 + } 1.4754 + if (data.num > numTransitions) 1.4755 + numTransitions = data.num; 1.4756 + } 1.4757 + 1.4758 + return numTransitions; 1.4759 +} 1.4760 + 1.4761 +static void 1.4762 +ComputeTimingFunction(const nsCSSValue& aValue, nsTimingFunction& aResult) 1.4763 +{ 1.4764 + switch (aValue.GetUnit()) { 1.4765 + case eCSSUnit_Enumerated: 1.4766 + aResult = nsTimingFunction(aValue.GetIntValue()); 1.4767 + break; 1.4768 + case eCSSUnit_Cubic_Bezier: 1.4769 + { 1.4770 + nsCSSValue::Array* array = aValue.GetArrayValue(); 1.4771 + NS_ASSERTION(array && array->Count() == 4, 1.4772 + "Need 4 control points"); 1.4773 + aResult = nsTimingFunction(array->Item(0).GetFloatValue(), 1.4774 + array->Item(1).GetFloatValue(), 1.4775 + array->Item(2).GetFloatValue(), 1.4776 + array->Item(3).GetFloatValue()); 1.4777 + } 1.4778 + break; 1.4779 + case eCSSUnit_Steps: 1.4780 + { 1.4781 + nsCSSValue::Array* array = aValue.GetArrayValue(); 1.4782 + NS_ASSERTION(array && array->Count() == 2, 1.4783 + "Need 2 items"); 1.4784 + NS_ASSERTION(array->Item(0).GetUnit() == eCSSUnit_Integer, 1.4785 + "unexpected first value"); 1.4786 + NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Enumerated && 1.4787 + (array->Item(1).GetIntValue() == 1.4788 + NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START || 1.4789 + array->Item(1).GetIntValue() == 1.4790 + NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END), 1.4791 + "unexpected second value"); 1.4792 + nsTimingFunction::Type type = 1.4793 + (array->Item(1).GetIntValue() == 1.4794 + NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END) 1.4795 + ? nsTimingFunction::StepEnd : nsTimingFunction::StepStart; 1.4796 + aResult = nsTimingFunction(type, array->Item(0).GetIntValue()); 1.4797 + } 1.4798 + break; 1.4799 + default: 1.4800 + NS_NOTREACHED("Invalid transition property unit"); 1.4801 + } 1.4802 +} 1.4803 + 1.4804 +const void* 1.4805 +nsRuleNode::ComputeDisplayData(void* aStartStruct, 1.4806 + const nsRuleData* aRuleData, 1.4807 + nsStyleContext* aContext, 1.4808 + nsRuleNode* aHighestNode, 1.4809 + const RuleDetail aRuleDetail, 1.4810 + const bool aCanStoreInRuleTree) 1.4811 +{ 1.4812 + COMPUTE_START_RESET(Display, (), display, parentDisplay) 1.4813 + 1.4814 + // We may have ended up with aStartStruct's values of mDisplay and 1.4815 + // mFloats, but those may not be correct if our style data overrides 1.4816 + // its position or float properties. Reset to mOriginalDisplay and 1.4817 + // mOriginalFloats; it if turns out we still need the display/floats 1.4818 + // adjustments we'll do them below. 1.4819 + display->mDisplay = display->mOriginalDisplay; 1.4820 + display->mFloats = display->mOriginalFloats; 1.4821 + 1.4822 + // Each property's index in this array must match its index in the 1.4823 + // const array |transitionPropInfo| above. 1.4824 + TransitionPropData transitionPropData[4]; 1.4825 + TransitionPropData& delay = transitionPropData[0]; 1.4826 + TransitionPropData& duration = transitionPropData[1]; 1.4827 + TransitionPropData& property = transitionPropData[2]; 1.4828 + TransitionPropData& timingFunction = transitionPropData[3]; 1.4829 + 1.4830 +#define FOR_ALL_TRANSITION_PROPS(var_) \ 1.4831 + for (uint32_t var_ = 0; var_ < 4; ++var_) 1.4832 + 1.4833 + // CSS Transitions 1.4834 + uint32_t numTransitions = 1.4835 + CountTransitionProps(transitionPropInfo, transitionPropData, 1.4836 + ArrayLength(transitionPropData), 1.4837 + display, parentDisplay, aRuleData, 1.4838 + canStoreInRuleTree); 1.4839 + 1.4840 + display->mTransitions.SetLength(numTransitions); 1.4841 + 1.4842 + FOR_ALL_TRANSITION_PROPS(p) { 1.4843 + const TransitionPropInfo& i = transitionPropInfo[p]; 1.4844 + TransitionPropData& d = transitionPropData[p]; 1.4845 + 1.4846 + display->*(i.sdCount) = d.num; 1.4847 + } 1.4848 + 1.4849 + // Fill in the transitions we just allocated with the appropriate values. 1.4850 + for (uint32_t i = 0; i < numTransitions; ++i) { 1.4851 + nsTransition *transition = &display->mTransitions[i]; 1.4852 + 1.4853 + if (i >= delay.num) { 1.4854 + transition->SetDelay(display->mTransitions[i % delay.num].GetDelay()); 1.4855 + } else if (delay.unit == eCSSUnit_Inherit) { 1.4856 + // FIXME (Bug 522599) (for all transition properties): write a test that 1.4857 + // detects when this was wrong for i >= delay.num if parent had 1.4858 + // count for this property not equal to length 1.4859 + NS_ABORT_IF_FALSE(i < parentDisplay->mTransitionDelayCount, 1.4860 + "delay.num computed incorrectly"); 1.4861 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.4862 + "should have made canStoreInRuleTree false above"); 1.4863 + transition->SetDelay(parentDisplay->mTransitions[i].GetDelay()); 1.4864 + } else if (delay.unit == eCSSUnit_Initial || 1.4865 + delay.unit == eCSSUnit_Unset) { 1.4866 + transition->SetDelay(0.0); 1.4867 + } else if (delay.list) { 1.4868 + switch (delay.list->mValue.GetUnit()) { 1.4869 + case eCSSUnit_Seconds: 1.4870 + transition->SetDelay(PR_MSEC_PER_SEC * 1.4871 + delay.list->mValue.GetFloatValue()); 1.4872 + break; 1.4873 + case eCSSUnit_Milliseconds: 1.4874 + transition->SetDelay(delay.list->mValue.GetFloatValue()); 1.4875 + break; 1.4876 + default: 1.4877 + NS_NOTREACHED("Invalid delay unit"); 1.4878 + } 1.4879 + } 1.4880 + 1.4881 + if (i >= duration.num) { 1.4882 + transition->SetDuration( 1.4883 + display->mTransitions[i % duration.num].GetDuration()); 1.4884 + } else if (duration.unit == eCSSUnit_Inherit) { 1.4885 + NS_ABORT_IF_FALSE(i < parentDisplay->mTransitionDurationCount, 1.4886 + "duration.num computed incorrectly"); 1.4887 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.4888 + "should have made canStoreInRuleTree false above"); 1.4889 + transition->SetDuration(parentDisplay->mTransitions[i].GetDuration()); 1.4890 + } else if (duration.unit == eCSSUnit_Initial || 1.4891 + duration.unit == eCSSUnit_Unset) { 1.4892 + transition->SetDuration(0.0); 1.4893 + } else if (duration.list) { 1.4894 + switch (duration.list->mValue.GetUnit()) { 1.4895 + case eCSSUnit_Seconds: 1.4896 + transition->SetDuration(PR_MSEC_PER_SEC * 1.4897 + duration.list->mValue.GetFloatValue()); 1.4898 + break; 1.4899 + case eCSSUnit_Milliseconds: 1.4900 + transition->SetDuration(duration.list->mValue.GetFloatValue()); 1.4901 + break; 1.4902 + default: 1.4903 + NS_NOTREACHED("Invalid duration unit"); 1.4904 + } 1.4905 + } 1.4906 + 1.4907 + if (i >= property.num) { 1.4908 + transition->CopyPropertyFrom(display->mTransitions[i % property.num]); 1.4909 + } else if (property.unit == eCSSUnit_Inherit) { 1.4910 + NS_ABORT_IF_FALSE(i < parentDisplay->mTransitionPropertyCount, 1.4911 + "property.num computed incorrectly"); 1.4912 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.4913 + "should have made canStoreInRuleTree false above"); 1.4914 + transition->CopyPropertyFrom(parentDisplay->mTransitions[i]); 1.4915 + } else if (property.unit == eCSSUnit_Initial || 1.4916 + property.unit == eCSSUnit_Unset) { 1.4917 + transition->SetProperty(eCSSPropertyExtra_all_properties); 1.4918 + } else if (property.unit == eCSSUnit_None) { 1.4919 + transition->SetProperty(eCSSPropertyExtra_no_properties); 1.4920 + } else if (property.list) { 1.4921 + const nsCSSValue &val = property.list->mValue; 1.4922 + 1.4923 + if (val.GetUnit() == eCSSUnit_Ident) { 1.4924 + nsDependentString 1.4925 + propertyStr(property.list->mValue.GetStringBufferValue()); 1.4926 + nsCSSProperty prop = 1.4927 + nsCSSProps::LookupProperty(propertyStr, 1.4928 + nsCSSProps::eEnabledForAllContent); 1.4929 + if (prop == eCSSProperty_UNKNOWN) { 1.4930 + transition->SetUnknownProperty(propertyStr); 1.4931 + } else { 1.4932 + transition->SetProperty(prop); 1.4933 + } 1.4934 + } else { 1.4935 + NS_ABORT_IF_FALSE(val.GetUnit() == eCSSUnit_All, 1.4936 + nsPrintfCString("Invalid transition property unit %d", 1.4937 + val.GetUnit()).get()); 1.4938 + transition->SetProperty(eCSSPropertyExtra_all_properties); 1.4939 + } 1.4940 + } 1.4941 + 1.4942 + if (i >= timingFunction.num) { 1.4943 + transition->SetTimingFunction( 1.4944 + display->mTransitions[i % timingFunction.num].GetTimingFunction()); 1.4945 + } else if (timingFunction.unit == eCSSUnit_Inherit) { 1.4946 + NS_ABORT_IF_FALSE(i < parentDisplay->mTransitionTimingFunctionCount, 1.4947 + "timingFunction.num computed incorrectly"); 1.4948 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.4949 + "should have made canStoreInRuleTree false above"); 1.4950 + transition->SetTimingFunction( 1.4951 + parentDisplay->mTransitions[i].GetTimingFunction()); 1.4952 + } else if (timingFunction.unit == eCSSUnit_Initial || 1.4953 + timingFunction.unit == eCSSUnit_Unset) { 1.4954 + transition->SetTimingFunction( 1.4955 + nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)); 1.4956 + } else if (timingFunction.list) { 1.4957 + ComputeTimingFunction(timingFunction.list->mValue, 1.4958 + transition->TimingFunctionSlot()); 1.4959 + } 1.4960 + 1.4961 + FOR_ALL_TRANSITION_PROPS(p) { 1.4962 + const TransitionPropInfo& info = transitionPropInfo[p]; 1.4963 + TransitionPropData& d = transitionPropData[p]; 1.4964 + 1.4965 + // if we're at the end of the list, start at the beginning and repeat 1.4966 + // until we're out of transitions to populate 1.4967 + if (d.list) { 1.4968 + d.list = d.list->mNext ? d.list->mNext : 1.4969 + aRuleData->ValueFor(info.property)->GetListValue(); 1.4970 + } 1.4971 + } 1.4972 + } 1.4973 + 1.4974 + // Each property's index in this array must match its index in the 1.4975 + // const array |animationPropInfo| above. 1.4976 + TransitionPropData animationPropData[8]; 1.4977 + TransitionPropData& animDelay = animationPropData[0]; 1.4978 + TransitionPropData& animDuration = animationPropData[1]; 1.4979 + TransitionPropData& animName = animationPropData[2]; 1.4980 + TransitionPropData& animTimingFunction = animationPropData[3]; 1.4981 + TransitionPropData& animDirection = animationPropData[4]; 1.4982 + TransitionPropData& animFillMode = animationPropData[5]; 1.4983 + TransitionPropData& animPlayState = animationPropData[6]; 1.4984 + TransitionPropData& animIterationCount = animationPropData[7]; 1.4985 + 1.4986 +#define FOR_ALL_ANIMATION_PROPS(var_) \ 1.4987 + for (uint32_t var_ = 0; var_ < 8; ++var_) 1.4988 + 1.4989 + // CSS Animations. 1.4990 + 1.4991 + uint32_t numAnimations = 1.4992 + CountTransitionProps(animationPropInfo, animationPropData, 1.4993 + ArrayLength(animationPropData), 1.4994 + display, parentDisplay, aRuleData, 1.4995 + canStoreInRuleTree); 1.4996 + 1.4997 + display->mAnimations.SetLength(numAnimations); 1.4998 + 1.4999 + FOR_ALL_ANIMATION_PROPS(p) { 1.5000 + const TransitionPropInfo& i = animationPropInfo[p]; 1.5001 + TransitionPropData& d = animationPropData[p]; 1.5002 + 1.5003 + display->*(i.sdCount) = d.num; 1.5004 + } 1.5005 + 1.5006 + // Fill in the animations we just allocated with the appropriate values. 1.5007 + for (uint32_t i = 0; i < numAnimations; ++i) { 1.5008 + nsAnimation *animation = &display->mAnimations[i]; 1.5009 + 1.5010 + if (i >= animDelay.num) { 1.5011 + animation->SetDelay(display->mAnimations[i % animDelay.num].GetDelay()); 1.5012 + } else if (animDelay.unit == eCSSUnit_Inherit) { 1.5013 + // FIXME (Bug 522599) (for all animation properties): write a test that 1.5014 + // detects when this was wrong for i >= animDelay.num if parent had 1.5015 + // count for this property not equal to length 1.5016 + NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationDelayCount, 1.5017 + "animDelay.num computed incorrectly"); 1.5018 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.5019 + "should have made canStoreInRuleTree false above"); 1.5020 + animation->SetDelay(parentDisplay->mAnimations[i].GetDelay()); 1.5021 + } else if (animDelay.unit == eCSSUnit_Initial || 1.5022 + animDelay.unit == eCSSUnit_Unset) { 1.5023 + animation->SetDelay(0.0); 1.5024 + } else if (animDelay.list) { 1.5025 + switch (animDelay.list->mValue.GetUnit()) { 1.5026 + case eCSSUnit_Seconds: 1.5027 + animation->SetDelay(PR_MSEC_PER_SEC * 1.5028 + animDelay.list->mValue.GetFloatValue()); 1.5029 + break; 1.5030 + case eCSSUnit_Milliseconds: 1.5031 + animation->SetDelay(animDelay.list->mValue.GetFloatValue()); 1.5032 + break; 1.5033 + default: 1.5034 + NS_NOTREACHED("Invalid delay unit"); 1.5035 + } 1.5036 + } 1.5037 + 1.5038 + if (i >= animDuration.num) { 1.5039 + animation->SetDuration( 1.5040 + display->mAnimations[i % animDuration.num].GetDuration()); 1.5041 + } else if (animDuration.unit == eCSSUnit_Inherit) { 1.5042 + NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationDurationCount, 1.5043 + "animDuration.num computed incorrectly"); 1.5044 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.5045 + "should have made canStoreInRuleTree false above"); 1.5046 + animation->SetDuration(parentDisplay->mAnimations[i].GetDuration()); 1.5047 + } else if (animDuration.unit == eCSSUnit_Initial || 1.5048 + animDuration.unit == eCSSUnit_Unset) { 1.5049 + animation->SetDuration(0.0); 1.5050 + } else if (animDuration.list) { 1.5051 + switch (animDuration.list->mValue.GetUnit()) { 1.5052 + case eCSSUnit_Seconds: 1.5053 + animation->SetDuration(PR_MSEC_PER_SEC * 1.5054 + animDuration.list->mValue.GetFloatValue()); 1.5055 + break; 1.5056 + case eCSSUnit_Milliseconds: 1.5057 + animation->SetDuration(animDuration.list->mValue.GetFloatValue()); 1.5058 + break; 1.5059 + default: 1.5060 + NS_NOTREACHED("Invalid duration unit"); 1.5061 + } 1.5062 + } 1.5063 + 1.5064 + if (i >= animName.num) { 1.5065 + animation->SetName(display->mAnimations[i % animName.num].GetName()); 1.5066 + } else if (animName.unit == eCSSUnit_Inherit) { 1.5067 + NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationNameCount, 1.5068 + "animName.num computed incorrectly"); 1.5069 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.5070 + "should have made canStoreInRuleTree false above"); 1.5071 + animation->SetName(parentDisplay->mAnimations[i].GetName()); 1.5072 + } else if (animName.unit == eCSSUnit_Initial || 1.5073 + animName.unit == eCSSUnit_Unset) { 1.5074 + animation->SetName(EmptyString()); 1.5075 + } else if (animName.list) { 1.5076 + switch (animName.list->mValue.GetUnit()) { 1.5077 + case eCSSUnit_Ident: { 1.5078 + nsDependentString 1.5079 + nameStr(animName.list->mValue.GetStringBufferValue()); 1.5080 + animation->SetName(nameStr); 1.5081 + break; 1.5082 + } 1.5083 + case eCSSUnit_None: { 1.5084 + animation->SetName(EmptyString()); 1.5085 + break; 1.5086 + } 1.5087 + default: 1.5088 + NS_ABORT_IF_FALSE(false, 1.5089 + nsPrintfCString("Invalid animation-name unit %d", 1.5090 + animName.list->mValue.GetUnit()).get()); 1.5091 + } 1.5092 + } 1.5093 + 1.5094 + if (i >= animTimingFunction.num) { 1.5095 + animation->SetTimingFunction( 1.5096 + display->mAnimations[i % animTimingFunction.num].GetTimingFunction()); 1.5097 + } else if (animTimingFunction.unit == eCSSUnit_Inherit) { 1.5098 + NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationTimingFunctionCount, 1.5099 + "animTimingFunction.num computed incorrectly"); 1.5100 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.5101 + "should have made canStoreInRuleTree false above"); 1.5102 + animation->SetTimingFunction( 1.5103 + parentDisplay->mAnimations[i].GetTimingFunction()); 1.5104 + } else if (animTimingFunction.unit == eCSSUnit_Initial || 1.5105 + animTimingFunction.unit == eCSSUnit_Unset) { 1.5106 + animation->SetTimingFunction( 1.5107 + nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)); 1.5108 + } else if (animTimingFunction.list) { 1.5109 + ComputeTimingFunction(animTimingFunction.list->mValue, 1.5110 + animation->TimingFunctionSlot()); 1.5111 + } 1.5112 + 1.5113 + if (i >= animDirection.num) { 1.5114 + animation->SetDirection(display->mAnimations[i % animDirection.num].GetDirection()); 1.5115 + } else if (animDirection.unit == eCSSUnit_Inherit) { 1.5116 + NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationDirectionCount, 1.5117 + "animDirection.num computed incorrectly"); 1.5118 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.5119 + "should have made canStoreInRuleTree false above"); 1.5120 + animation->SetDirection(parentDisplay->mAnimations[i].GetDirection()); 1.5121 + } else if (animDirection.unit == eCSSUnit_Initial || 1.5122 + animDirection.unit == eCSSUnit_Unset) { 1.5123 + animation->SetDirection(NS_STYLE_ANIMATION_DIRECTION_NORMAL); 1.5124 + } else if (animDirection.list) { 1.5125 + NS_ABORT_IF_FALSE(animDirection.list->mValue.GetUnit() == eCSSUnit_Enumerated, 1.5126 + nsPrintfCString("Invalid animation-direction unit %d", 1.5127 + animDirection.list->mValue.GetUnit()).get()); 1.5128 + 1.5129 + animation->SetDirection(animDirection.list->mValue.GetIntValue()); 1.5130 + } 1.5131 + 1.5132 + if (i >= animFillMode.num) { 1.5133 + animation->SetFillMode(display->mAnimations[i % animFillMode.num].GetFillMode()); 1.5134 + } else if (animFillMode.unit == eCSSUnit_Inherit) { 1.5135 + NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationFillModeCount, 1.5136 + "animFillMode.num computed incorrectly"); 1.5137 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.5138 + "should have made canStoreInRuleTree false above"); 1.5139 + animation->SetFillMode(parentDisplay->mAnimations[i].GetFillMode()); 1.5140 + } else if (animFillMode.unit == eCSSUnit_Initial || 1.5141 + animFillMode.unit == eCSSUnit_Unset) { 1.5142 + animation->SetFillMode(NS_STYLE_ANIMATION_FILL_MODE_NONE); 1.5143 + } else if (animFillMode.list) { 1.5144 + NS_ABORT_IF_FALSE(animFillMode.list->mValue.GetUnit() == eCSSUnit_Enumerated, 1.5145 + nsPrintfCString("Invalid animation-fill-mode unit %d", 1.5146 + animFillMode.list->mValue.GetUnit()).get()); 1.5147 + 1.5148 + animation->SetFillMode(animFillMode.list->mValue.GetIntValue()); 1.5149 + } 1.5150 + 1.5151 + if (i >= animPlayState.num) { 1.5152 + animation->SetPlayState(display->mAnimations[i % animPlayState.num].GetPlayState()); 1.5153 + } else if (animPlayState.unit == eCSSUnit_Inherit) { 1.5154 + NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationPlayStateCount, 1.5155 + "animPlayState.num computed incorrectly"); 1.5156 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.5157 + "should have made canStoreInRuleTree false above"); 1.5158 + animation->SetPlayState(parentDisplay->mAnimations[i].GetPlayState()); 1.5159 + } else if (animPlayState.unit == eCSSUnit_Initial || 1.5160 + animPlayState.unit == eCSSUnit_Unset) { 1.5161 + animation->SetPlayState(NS_STYLE_ANIMATION_PLAY_STATE_RUNNING); 1.5162 + } else if (animPlayState.list) { 1.5163 + NS_ABORT_IF_FALSE(animPlayState.list->mValue.GetUnit() == eCSSUnit_Enumerated, 1.5164 + nsPrintfCString("Invalid animation-play-state unit %d", 1.5165 + animPlayState.list->mValue.GetUnit()).get()); 1.5166 + 1.5167 + animation->SetPlayState(animPlayState.list->mValue.GetIntValue()); 1.5168 + } 1.5169 + 1.5170 + if (i >= animIterationCount.num) { 1.5171 + animation->SetIterationCount(display->mAnimations[i % animIterationCount.num].GetIterationCount()); 1.5172 + } else if (animIterationCount.unit == eCSSUnit_Inherit) { 1.5173 + NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationIterationCountCount, 1.5174 + "animIterationCount.num computed incorrectly"); 1.5175 + NS_ABORT_IF_FALSE(!canStoreInRuleTree, 1.5176 + "should have made canStoreInRuleTree false above"); 1.5177 + animation->SetIterationCount(parentDisplay->mAnimations[i].GetIterationCount()); 1.5178 + } else if (animIterationCount.unit == eCSSUnit_Initial || 1.5179 + animIterationCount.unit == eCSSUnit_Unset) { 1.5180 + animation->SetIterationCount(1.0f); 1.5181 + } else if (animIterationCount.list) { 1.5182 + switch (animIterationCount.list->mValue.GetUnit()) { 1.5183 + case eCSSUnit_Enumerated: 1.5184 + NS_ABORT_IF_FALSE(animIterationCount.list->mValue.GetIntValue() == 1.5185 + NS_STYLE_ANIMATION_ITERATION_COUNT_INFINITE, 1.5186 + "unexpected value"); 1.5187 + animation->SetIterationCount(NS_IEEEPositiveInfinity()); 1.5188 + break; 1.5189 + case eCSSUnit_Number: 1.5190 + animation->SetIterationCount( 1.5191 + animIterationCount.list->mValue.GetFloatValue()); 1.5192 + break; 1.5193 + default: 1.5194 + NS_ABORT_IF_FALSE(false, 1.5195 + "unexpected animation-iteration-count unit"); 1.5196 + } 1.5197 + } 1.5198 + 1.5199 + FOR_ALL_ANIMATION_PROPS(p) { 1.5200 + const TransitionPropInfo& info = animationPropInfo[p]; 1.5201 + TransitionPropData& d = animationPropData[p]; 1.5202 + 1.5203 + // if we're at the end of the list, start at the beginning and repeat 1.5204 + // until we're out of animations to populate 1.5205 + if (d.list) { 1.5206 + d.list = d.list->mNext ? d.list->mNext : 1.5207 + aRuleData->ValueFor(info.property)->GetListValue(); 1.5208 + } 1.5209 + } 1.5210 + } 1.5211 + 1.5212 + // opacity: factor, inherit, initial 1.5213 + SetFactor(*aRuleData->ValueForOpacity(), display->mOpacity, canStoreInRuleTree, 1.5214 + parentDisplay->mOpacity, 1.0f, 1.5215 + SETFCT_OPACITY | SETFCT_UNSET_INITIAL); 1.5216 + 1.5217 + // display: enum, inherit, initial 1.5218 + SetDiscrete(*aRuleData->ValueForDisplay(), display->mDisplay, canStoreInRuleTree, 1.5219 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5220 + parentDisplay->mDisplay, 1.5221 + NS_STYLE_DISPLAY_INLINE, 0, 0, 0, 0); 1.5222 + 1.5223 + // mix-blend-mode: enum, inherit, initial 1.5224 + SetDiscrete(*aRuleData->ValueForMixBlendMode(), display->mMixBlendMode, 1.5225 + canStoreInRuleTree, 1.5226 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5227 + parentDisplay->mMixBlendMode, NS_STYLE_BLEND_NORMAL, 1.5228 + 0, 0, 0, 0); 1.5229 + 1.5230 + // Backup original display value for calculation of a hypothetical 1.5231 + // box (CSS2 10.6.4/10.6.5), in addition to getting our style data right later. 1.5232 + // See nsHTMLReflowState::CalculateHypotheticalBox 1.5233 + display->mOriginalDisplay = display->mDisplay; 1.5234 + 1.5235 + // appearance: enum, inherit, initial 1.5236 + SetDiscrete(*aRuleData->ValueForAppearance(), 1.5237 + display->mAppearance, canStoreInRuleTree, 1.5238 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5239 + parentDisplay->mAppearance, 1.5240 + NS_THEME_NONE, 0, 0, 0, 0); 1.5241 + 1.5242 + // binding: url, none, inherit 1.5243 + const nsCSSValue* bindingValue = aRuleData->ValueForBinding(); 1.5244 + if (eCSSUnit_URL == bindingValue->GetUnit()) { 1.5245 + mozilla::css::URLValue* url = bindingValue->GetURLStructValue(); 1.5246 + NS_ASSERTION(url, "What's going on here?"); 1.5247 + 1.5248 + if (MOZ_LIKELY(url->GetURI())) { 1.5249 + display->mBinding = url; 1.5250 + } else { 1.5251 + display->mBinding = nullptr; 1.5252 + } 1.5253 + } 1.5254 + else if (eCSSUnit_None == bindingValue->GetUnit() || 1.5255 + eCSSUnit_Initial == bindingValue->GetUnit() || 1.5256 + eCSSUnit_Unset == bindingValue->GetUnit()) { 1.5257 + display->mBinding = nullptr; 1.5258 + } 1.5259 + else if (eCSSUnit_Inherit == bindingValue->GetUnit()) { 1.5260 + canStoreInRuleTree = false; 1.5261 + display->mBinding = parentDisplay->mBinding; 1.5262 + } 1.5263 + 1.5264 + // position: enum, inherit, initial 1.5265 + SetDiscrete(*aRuleData->ValueForPosition(), display->mPosition, canStoreInRuleTree, 1.5266 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5267 + parentDisplay->mPosition, 1.5268 + NS_STYLE_POSITION_STATIC, 0, 0, 0, 0); 1.5269 + 1.5270 + // clear: enum, inherit, initial 1.5271 + SetDiscrete(*aRuleData->ValueForClear(), display->mBreakType, canStoreInRuleTree, 1.5272 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5273 + parentDisplay->mBreakType, 1.5274 + NS_STYLE_CLEAR_NONE, 0, 0, 0, 0); 1.5275 + 1.5276 + // temp fix for bug 24000 1.5277 + // Map 'auto' and 'avoid' to false, and 'always', 'left', and 1.5278 + // 'right' to true. 1.5279 + // "A conforming user agent may interpret the values 'left' and 1.5280 + // 'right' as 'always'." - CSS2.1, section 13.3.1 1.5281 + const nsCSSValue* breakBeforeValue = aRuleData->ValueForPageBreakBefore(); 1.5282 + if (eCSSUnit_Enumerated == breakBeforeValue->GetUnit()) { 1.5283 + display->mBreakBefore = 1.5284 + (NS_STYLE_PAGE_BREAK_AVOID != breakBeforeValue->GetIntValue() && 1.5285 + NS_STYLE_PAGE_BREAK_AUTO != breakBeforeValue->GetIntValue()); 1.5286 + } 1.5287 + else if (eCSSUnit_Initial == breakBeforeValue->GetUnit() || 1.5288 + eCSSUnit_Unset == breakBeforeValue->GetUnit()) { 1.5289 + display->mBreakBefore = false; 1.5290 + } 1.5291 + else if (eCSSUnit_Inherit == breakBeforeValue->GetUnit()) { 1.5292 + canStoreInRuleTree = false; 1.5293 + display->mBreakBefore = parentDisplay->mBreakBefore; 1.5294 + } 1.5295 + 1.5296 + const nsCSSValue* breakAfterValue = aRuleData->ValueForPageBreakAfter(); 1.5297 + if (eCSSUnit_Enumerated == breakAfterValue->GetUnit()) { 1.5298 + display->mBreakAfter = 1.5299 + (NS_STYLE_PAGE_BREAK_AVOID != breakAfterValue->GetIntValue() && 1.5300 + NS_STYLE_PAGE_BREAK_AUTO != breakAfterValue->GetIntValue()); 1.5301 + } 1.5302 + else if (eCSSUnit_Initial == breakAfterValue->GetUnit() || 1.5303 + eCSSUnit_Unset == breakAfterValue->GetUnit()) { 1.5304 + display->mBreakAfter = false; 1.5305 + } 1.5306 + else if (eCSSUnit_Inherit == breakAfterValue->GetUnit()) { 1.5307 + canStoreInRuleTree = false; 1.5308 + display->mBreakAfter = parentDisplay->mBreakAfter; 1.5309 + } 1.5310 + // end temp fix 1.5311 + 1.5312 + // page-break-inside: enum, inherit, initial 1.5313 + SetDiscrete(*aRuleData->ValueForPageBreakInside(), 1.5314 + display->mBreakInside, canStoreInRuleTree, 1.5315 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5316 + parentDisplay->mBreakInside, 1.5317 + NS_STYLE_PAGE_BREAK_AUTO, 0, 0, 0, 0); 1.5318 + 1.5319 + // touch-action: none, auto, enum, inherit, initial 1.5320 + SetDiscrete(*aRuleData->ValueForTouchAction(), display->mTouchAction, 1.5321 + canStoreInRuleTree, 1.5322 + SETDSC_ENUMERATED | SETDSC_AUTO | SETDSC_NONE | 1.5323 + SETDSC_UNSET_INITIAL, 1.5324 + parentDisplay->mTouchAction, 1.5325 + NS_STYLE_TOUCH_ACTION_AUTO, 1.5326 + NS_STYLE_TOUCH_ACTION_AUTO, 1.5327 + NS_STYLE_TOUCH_ACTION_NONE, 0, 0); 1.5328 + 1.5329 + // float: enum, inherit, initial 1.5330 + SetDiscrete(*aRuleData->ValueForFloat(), 1.5331 + display->mFloats, canStoreInRuleTree, 1.5332 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5333 + parentDisplay->mFloats, 1.5334 + NS_STYLE_FLOAT_NONE, 0, 0, 0, 0); 1.5335 + // Save mFloats in mOriginalFloats in case we need it later 1.5336 + display->mOriginalFloats = display->mFloats; 1.5337 + 1.5338 + // overflow-x: enum, inherit, initial 1.5339 + SetDiscrete(*aRuleData->ValueForOverflowX(), 1.5340 + display->mOverflowX, canStoreInRuleTree, 1.5341 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5342 + parentDisplay->mOverflowX, 1.5343 + NS_STYLE_OVERFLOW_VISIBLE, 0, 0, 0, 0); 1.5344 + 1.5345 + // overflow-y: enum, inherit, initial 1.5346 + SetDiscrete(*aRuleData->ValueForOverflowY(), 1.5347 + display->mOverflowY, canStoreInRuleTree, 1.5348 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5349 + parentDisplay->mOverflowY, 1.5350 + NS_STYLE_OVERFLOW_VISIBLE, 0, 0, 0, 0); 1.5351 + 1.5352 + // CSS3 overflow-x and overflow-y require some fixup as well in some 1.5353 + // cases. NS_STYLE_OVERFLOW_VISIBLE and NS_STYLE_OVERFLOW_CLIP are 1.5354 + // meaningful only when used in both dimensions. 1.5355 + if (display->mOverflowX != display->mOverflowY && 1.5356 + (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE || 1.5357 + display->mOverflowX == NS_STYLE_OVERFLOW_CLIP || 1.5358 + display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE || 1.5359 + display->mOverflowY == NS_STYLE_OVERFLOW_CLIP)) { 1.5360 + // We can't store in the rule tree since a more specific rule might 1.5361 + // change these conditions. 1.5362 + canStoreInRuleTree = false; 1.5363 + 1.5364 + // NS_STYLE_OVERFLOW_CLIP is a deprecated value, so if it's specified 1.5365 + // in only one dimension, convert it to NS_STYLE_OVERFLOW_HIDDEN. 1.5366 + if (display->mOverflowX == NS_STYLE_OVERFLOW_CLIP) 1.5367 + display->mOverflowX = NS_STYLE_OVERFLOW_HIDDEN; 1.5368 + if (display->mOverflowY == NS_STYLE_OVERFLOW_CLIP) 1.5369 + display->mOverflowY = NS_STYLE_OVERFLOW_HIDDEN; 1.5370 + 1.5371 + // If 'visible' is specified but doesn't match the other dimension, it 1.5372 + // turns into 'auto'. 1.5373 + if (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE) 1.5374 + display->mOverflowX = NS_STYLE_OVERFLOW_AUTO; 1.5375 + if (display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE) 1.5376 + display->mOverflowY = NS_STYLE_OVERFLOW_AUTO; 1.5377 + } 1.5378 + 1.5379 + SetDiscrete(*aRuleData->ValueForOverflowClipBox(), display->mOverflowClipBox, 1.5380 + canStoreInRuleTree, 1.5381 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5382 + parentDisplay->mOverflowClipBox, 1.5383 + NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX, 0, 0, 0, 0); 1.5384 + 1.5385 + SetDiscrete(*aRuleData->ValueForResize(), display->mResize, canStoreInRuleTree, 1.5386 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5387 + parentDisplay->mResize, 1.5388 + NS_STYLE_RESIZE_NONE, 0, 0, 0, 0); 1.5389 + 1.5390 + // clip property: length, auto, inherit 1.5391 + const nsCSSValue* clipValue = aRuleData->ValueForClip(); 1.5392 + switch (clipValue->GetUnit()) { 1.5393 + case eCSSUnit_Inherit: 1.5394 + canStoreInRuleTree = false; 1.5395 + display->mClipFlags = parentDisplay->mClipFlags; 1.5396 + display->mClip = parentDisplay->mClip; 1.5397 + break; 1.5398 + 1.5399 + case eCSSUnit_Initial: 1.5400 + case eCSSUnit_Unset: 1.5401 + case eCSSUnit_Auto: 1.5402 + display->mClipFlags = NS_STYLE_CLIP_AUTO; 1.5403 + display->mClip.SetRect(0,0,0,0); 1.5404 + break; 1.5405 + 1.5406 + case eCSSUnit_Null: 1.5407 + break; 1.5408 + 1.5409 + case eCSSUnit_Rect: { 1.5410 + const nsCSSRect& clipRect = clipValue->GetRectValue(); 1.5411 + 1.5412 + display->mClipFlags = NS_STYLE_CLIP_RECT; 1.5413 + 1.5414 + if (clipRect.mTop.GetUnit() == eCSSUnit_Auto) { 1.5415 + display->mClip.y = 0; 1.5416 + display->mClipFlags |= NS_STYLE_CLIP_TOP_AUTO; 1.5417 + } 1.5418 + else if (clipRect.mTop.IsLengthUnit()) { 1.5419 + display->mClip.y = CalcLength(clipRect.mTop, aContext, 1.5420 + mPresContext, canStoreInRuleTree); 1.5421 + } 1.5422 + 1.5423 + if (clipRect.mBottom.GetUnit() == eCSSUnit_Auto) { 1.5424 + // Setting to NS_MAXSIZE for the 'auto' case ensures that 1.5425 + // the clip rect is nonempty. It is important that mClip be 1.5426 + // nonempty if the actual clip rect could be nonempty. 1.5427 + display->mClip.height = NS_MAXSIZE; 1.5428 + display->mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO; 1.5429 + } 1.5430 + else if (clipRect.mBottom.IsLengthUnit()) { 1.5431 + display->mClip.height = CalcLength(clipRect.mBottom, aContext, 1.5432 + mPresContext, canStoreInRuleTree) - 1.5433 + display->mClip.y; 1.5434 + } 1.5435 + 1.5436 + if (clipRect.mLeft.GetUnit() == eCSSUnit_Auto) { 1.5437 + display->mClip.x = 0; 1.5438 + display->mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO; 1.5439 + } 1.5440 + else if (clipRect.mLeft.IsLengthUnit()) { 1.5441 + display->mClip.x = CalcLength(clipRect.mLeft, aContext, 1.5442 + mPresContext, canStoreInRuleTree); 1.5443 + } 1.5444 + 1.5445 + if (clipRect.mRight.GetUnit() == eCSSUnit_Auto) { 1.5446 + // Setting to NS_MAXSIZE for the 'auto' case ensures that 1.5447 + // the clip rect is nonempty. It is important that mClip be 1.5448 + // nonempty if the actual clip rect could be nonempty. 1.5449 + display->mClip.width = NS_MAXSIZE; 1.5450 + display->mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO; 1.5451 + } 1.5452 + else if (clipRect.mRight.IsLengthUnit()) { 1.5453 + display->mClip.width = CalcLength(clipRect.mRight, aContext, 1.5454 + mPresContext, canStoreInRuleTree) - 1.5455 + display->mClip.x; 1.5456 + } 1.5457 + break; 1.5458 + } 1.5459 + 1.5460 + default: 1.5461 + NS_ABORT_IF_FALSE(false, "unrecognized clip unit"); 1.5462 + } 1.5463 + 1.5464 + if (display->mDisplay != NS_STYLE_DISPLAY_NONE) { 1.5465 + // CSS2 9.7 specifies display type corrections dealing with 'float' 1.5466 + // and 'position'. Since generated content can't be floated or 1.5467 + // positioned, we can deal with it here. 1.5468 + 1.5469 + if (nsCSSPseudoElements::firstLetter == aContext->GetPseudo()) { 1.5470 + // a non-floating first-letter must be inline 1.5471 + // XXX this fix can go away once bug 103189 is fixed correctly 1.5472 + // Note that we reset mOriginalDisplay to enforce the invariant that it equals mDisplay if we're not positioned or floating. 1.5473 + display->mOriginalDisplay = display->mDisplay = NS_STYLE_DISPLAY_INLINE; 1.5474 + 1.5475 + // We can't cache the data in the rule tree since if a more specific 1.5476 + // rule has 'float: left' we'll end up with the wrong 'display' 1.5477 + // property. 1.5478 + canStoreInRuleTree = false; 1.5479 + } 1.5480 + 1.5481 + if (display->IsAbsolutelyPositionedStyle()) { 1.5482 + // 1) if position is 'absolute' or 'fixed' then display must be 1.5483 + // block-level and float must be 'none' 1.5484 + EnsureBlockDisplay(display->mDisplay); 1.5485 + display->mFloats = NS_STYLE_FLOAT_NONE; 1.5486 + 1.5487 + // Note that it's OK to cache this struct in the ruletree 1.5488 + // because it's fine as-is for any style context that points to 1.5489 + // it directly, and any use of it as aStartStruct (e.g. if a 1.5490 + // more specific rule sets "position: static") will use 1.5491 + // mOriginalDisplay and mOriginalFloats, which we have carefully 1.5492 + // not changed. 1.5493 + } else if (display->mFloats != NS_STYLE_FLOAT_NONE) { 1.5494 + // 2) if float is not none, and display is not none, then we must 1.5495 + // set a block-level 'display' type per CSS2.1 section 9.7. 1.5496 + EnsureBlockDisplay(display->mDisplay); 1.5497 + 1.5498 + // Note that it's OK to cache this struct in the ruletree 1.5499 + // because it's fine as-is for any style context that points to 1.5500 + // it directly, and any use of it as aStartStruct (e.g. if a 1.5501 + // more specific rule sets "float: none") will use 1.5502 + // mOriginalDisplay, which we have carefully not changed. 1.5503 + } 1.5504 + 1.5505 + } 1.5506 + 1.5507 + /* Convert the nsCSSValueList into an nsTArray<nsTransformFunction *>. */ 1.5508 + const nsCSSValue* transformValue = aRuleData->ValueForTransform(); 1.5509 + switch (transformValue->GetUnit()) { 1.5510 + case eCSSUnit_Null: 1.5511 + break; 1.5512 + 1.5513 + case eCSSUnit_Initial: 1.5514 + case eCSSUnit_Unset: 1.5515 + case eCSSUnit_None: 1.5516 + display->mSpecifiedTransform = nullptr; 1.5517 + break; 1.5518 + 1.5519 + case eCSSUnit_Inherit: 1.5520 + display->mSpecifiedTransform = parentDisplay->mSpecifiedTransform; 1.5521 + canStoreInRuleTree = false; 1.5522 + break; 1.5523 + 1.5524 + case eCSSUnit_SharedList: { 1.5525 + nsCSSValueSharedList* list = transformValue->GetSharedListValue(); 1.5526 + nsCSSValueList* head = list->mHead; 1.5527 + MOZ_ASSERT(head, "transform list must have at least one item"); 1.5528 + // can get a _None in here from transform animation 1.5529 + if (head->mValue.GetUnit() == eCSSUnit_None) { 1.5530 + NS_ABORT_IF_FALSE(head->mNext == nullptr, "none must be alone"); 1.5531 + display->mSpecifiedTransform = nullptr; 1.5532 + } else { 1.5533 + display->mSpecifiedTransform = list; 1.5534 + } 1.5535 + break; 1.5536 + } 1.5537 + 1.5538 + default: 1.5539 + NS_ABORT_IF_FALSE(false, "unrecognized transform unit"); 1.5540 + } 1.5541 + 1.5542 + /* Convert the nsCSSValueList into a will-change bitfield for fast lookup */ 1.5543 + const nsCSSValue* willChangeValue = aRuleData->ValueForWillChange(); 1.5544 + switch (willChangeValue->GetUnit()) { 1.5545 + case eCSSUnit_Null: 1.5546 + break; 1.5547 + 1.5548 + case eCSSUnit_List: 1.5549 + case eCSSUnit_ListDep: { 1.5550 + display->mWillChange.Clear(); 1.5551 + display->mWillChangeBitField = 0; 1.5552 + for (const nsCSSValueList* item = willChangeValue->GetListValue(); 1.5553 + item; item = item->mNext) 1.5554 + { 1.5555 + if (item->mValue.UnitHasStringValue()) { 1.5556 + nsAutoString buffer; 1.5557 + item->mValue.GetStringValue(buffer); 1.5558 + display->mWillChange.AppendElement(buffer); 1.5559 + 1.5560 + if (buffer.EqualsLiteral("transform")) { 1.5561 + display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_TRANSFORM; 1.5562 + } 1.5563 + if (buffer.EqualsLiteral("opacity")) { 1.5564 + display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_OPACITY; 1.5565 + } 1.5566 + if (buffer.EqualsLiteral("scroll-position")) { 1.5567 + display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_SCROLL; 1.5568 + } 1.5569 + 1.5570 + nsCSSProperty prop = 1.5571 + nsCSSProps::LookupProperty(buffer, 1.5572 + nsCSSProps::eEnabledForAllContent); 1.5573 + if (prop != eCSSProperty_UNKNOWN && 1.5574 + nsCSSProps::PropHasFlags(prop, 1.5575 + CSS_PROPERTY_CREATES_STACKING_CONTEXT)) 1.5576 + { 1.5577 + display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_STACKING_CONTEXT; 1.5578 + } 1.5579 + } 1.5580 + } 1.5581 + break; 1.5582 + } 1.5583 + 1.5584 + case eCSSUnit_Inherit: 1.5585 + display->mWillChange = parentDisplay->mWillChange; 1.5586 + display->mWillChangeBitField = parentDisplay->mWillChangeBitField; 1.5587 + canStoreInRuleTree = false; 1.5588 + break; 1.5589 + 1.5590 + case eCSSUnit_Initial: 1.5591 + case eCSSUnit_Unset: 1.5592 + case eCSSUnit_Auto: 1.5593 + display->mWillChange.Clear(); 1.5594 + display->mWillChangeBitField = 0; 1.5595 + break; 1.5596 + 1.5597 + default: 1.5598 + MOZ_ASSERT(false, "unrecognized will-change unit"); 1.5599 + } 1.5600 + 1.5601 + /* Convert -moz-transform-origin. */ 1.5602 + const nsCSSValue* transformOriginValue = 1.5603 + aRuleData->ValueForTransformOrigin(); 1.5604 + if (transformOriginValue->GetUnit() != eCSSUnit_Null) { 1.5605 + const nsCSSValue& valX = 1.5606 + transformOriginValue->GetUnit() == eCSSUnit_Triplet ? 1.5607 + transformOriginValue->GetTripletValue().mXValue : *transformOriginValue; 1.5608 + const nsCSSValue& valY = 1.5609 + transformOriginValue->GetUnit() == eCSSUnit_Triplet ? 1.5610 + transformOriginValue->GetTripletValue().mYValue : *transformOriginValue; 1.5611 + const nsCSSValue& valZ = 1.5612 + transformOriginValue->GetUnit() == eCSSUnit_Triplet ? 1.5613 + transformOriginValue->GetTripletValue().mZValue : *transformOriginValue; 1.5614 + 1.5615 + mozilla::DebugOnly<bool> cX = 1.5616 + SetCoord(valX, display->mTransformOrigin[0], 1.5617 + parentDisplay->mTransformOrigin[0], 1.5618 + SETCOORD_LPH | SETCOORD_INITIAL_HALF | 1.5619 + SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC | 1.5620 + SETCOORD_UNSET_INITIAL, 1.5621 + aContext, mPresContext, canStoreInRuleTree); 1.5622 + 1.5623 + mozilla::DebugOnly<bool> cY = 1.5624 + SetCoord(valY, display->mTransformOrigin[1], 1.5625 + parentDisplay->mTransformOrigin[1], 1.5626 + SETCOORD_LPH | SETCOORD_INITIAL_HALF | 1.5627 + SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC | 1.5628 + SETCOORD_UNSET_INITIAL, 1.5629 + aContext, mPresContext, canStoreInRuleTree); 1.5630 + 1.5631 + if (valZ.GetUnit() == eCSSUnit_Null) { 1.5632 + // Null for the z component means a 0 translation, not 1.5633 + // unspecified, as we have already checked the triplet 1.5634 + // value for Null. 1.5635 + display->mTransformOrigin[2].SetCoordValue(0); 1.5636 + } else { 1.5637 + mozilla::DebugOnly<bool> cZ = 1.5638 + SetCoord(valZ, display->mTransformOrigin[2], 1.5639 + parentDisplay->mTransformOrigin[2], 1.5640 + SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC | 1.5641 + SETCOORD_UNSET_INITIAL, 1.5642 + aContext, mPresContext, canStoreInRuleTree); 1.5643 + NS_ABORT_IF_FALSE(cY == cZ, "changed one but not the other"); 1.5644 + } 1.5645 + NS_ABORT_IF_FALSE(cX == cY, "changed one but not the other"); 1.5646 + NS_ASSERTION(cX, "Malformed -moz-transform-origin parse!"); 1.5647 + } 1.5648 + 1.5649 + const nsCSSValue* perspectiveOriginValue = 1.5650 + aRuleData->ValueForPerspectiveOrigin(); 1.5651 + if (perspectiveOriginValue->GetUnit() != eCSSUnit_Null) { 1.5652 + mozilla::DebugOnly<bool> result = 1.5653 + SetPairCoords(*perspectiveOriginValue, 1.5654 + display->mPerspectiveOrigin[0], 1.5655 + display->mPerspectiveOrigin[1], 1.5656 + parentDisplay->mPerspectiveOrigin[0], 1.5657 + parentDisplay->mPerspectiveOrigin[1], 1.5658 + SETCOORD_LPH | SETCOORD_INITIAL_HALF | 1.5659 + SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC | 1.5660 + SETCOORD_UNSET_INITIAL, 1.5661 + aContext, mPresContext, canStoreInRuleTree); 1.5662 + NS_ASSERTION(result, "Malformed -moz-perspective-origin parse!"); 1.5663 + } 1.5664 + 1.5665 + SetCoord(*aRuleData->ValueForPerspective(), 1.5666 + display->mChildPerspective, parentDisplay->mChildPerspective, 1.5667 + SETCOORD_LAH | SETCOORD_INITIAL_NONE | SETCOORD_NONE | 1.5668 + SETCOORD_UNSET_INITIAL, 1.5669 + aContext, mPresContext, canStoreInRuleTree); 1.5670 + 1.5671 + SetDiscrete(*aRuleData->ValueForBackfaceVisibility(), 1.5672 + display->mBackfaceVisibility, canStoreInRuleTree, 1.5673 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5674 + parentDisplay->mBackfaceVisibility, 1.5675 + NS_STYLE_BACKFACE_VISIBILITY_VISIBLE, 0, 0, 0, 0); 1.5676 + 1.5677 + // transform-style: enum, inherit, initial 1.5678 + SetDiscrete(*aRuleData->ValueForTransformStyle(), 1.5679 + display->mTransformStyle, canStoreInRuleTree, 1.5680 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5681 + parentDisplay->mTransformStyle, 1.5682 + NS_STYLE_TRANSFORM_STYLE_FLAT, 0, 0, 0, 0); 1.5683 + 1.5684 + // orient: enum, inherit, initial 1.5685 + SetDiscrete(*aRuleData->ValueForOrient(), 1.5686 + display->mOrient, canStoreInRuleTree, 1.5687 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.5688 + parentDisplay->mOrient, 1.5689 + NS_STYLE_ORIENT_AUTO, 0, 0, 0, 0); 1.5690 + 1.5691 + COMPUTE_END_RESET(Display, display) 1.5692 +} 1.5693 + 1.5694 +const void* 1.5695 +nsRuleNode::ComputeVisibilityData(void* aStartStruct, 1.5696 + const nsRuleData* aRuleData, 1.5697 + nsStyleContext* aContext, 1.5698 + nsRuleNode* aHighestNode, 1.5699 + const RuleDetail aRuleDetail, 1.5700 + const bool aCanStoreInRuleTree) 1.5701 +{ 1.5702 + COMPUTE_START_INHERITED(Visibility, (mPresContext), 1.5703 + visibility, parentVisibility) 1.5704 + 1.5705 + // IMPORTANT: No properties in this struct have lengths in them. We 1.5706 + // depend on this since CalcLengthWith can call StyleVisibility() 1.5707 + // to get the language for resolving fonts! 1.5708 + 1.5709 + // direction: enum, inherit, initial 1.5710 + SetDiscrete(*aRuleData->ValueForDirection(), visibility->mDirection, 1.5711 + canStoreInRuleTree, 1.5712 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.5713 + parentVisibility->mDirection, 1.5714 + (GET_BIDI_OPTION_DIRECTION(mPresContext->GetBidi()) 1.5715 + == IBMBIDI_TEXTDIRECTION_RTL) 1.5716 + ? NS_STYLE_DIRECTION_RTL : NS_STYLE_DIRECTION_LTR, 1.5717 + 0, 0, 0, 0); 1.5718 + 1.5719 + // visibility: enum, inherit, initial 1.5720 + SetDiscrete(*aRuleData->ValueForVisibility(), visibility->mVisible, 1.5721 + canStoreInRuleTree, 1.5722 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.5723 + parentVisibility->mVisible, 1.5724 + NS_STYLE_VISIBILITY_VISIBLE, 0, 0, 0, 0); 1.5725 + 1.5726 + // pointer-events: enum, inherit, initial 1.5727 + SetDiscrete(*aRuleData->ValueForPointerEvents(), visibility->mPointerEvents, 1.5728 + canStoreInRuleTree, 1.5729 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.5730 + parentVisibility->mPointerEvents, 1.5731 + NS_STYLE_POINTER_EVENTS_AUTO, 0, 0, 0, 0); 1.5732 + 1.5733 + // writing-mode: enum, inherit, initial 1.5734 + SetDiscrete(*aRuleData->ValueForWritingMode(), visibility->mWritingMode, 1.5735 + canStoreInRuleTree, 1.5736 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.5737 + parentVisibility->mWritingMode, 1.5738 + NS_STYLE_WRITING_MODE_HORIZONTAL_TB, 0, 0, 0, 0); 1.5739 + 1.5740 + // image-orientation: enum, inherit, initial 1.5741 + const nsCSSValue* orientation = aRuleData->ValueForImageOrientation(); 1.5742 + if (orientation->GetUnit() == eCSSUnit_Inherit || 1.5743 + orientation->GetUnit() == eCSSUnit_Unset) { 1.5744 + canStoreInRuleTree = false; 1.5745 + visibility->mImageOrientation = parentVisibility->mImageOrientation; 1.5746 + } else if (orientation->GetUnit() == eCSSUnit_Initial) { 1.5747 + visibility->mImageOrientation = nsStyleImageOrientation(); 1.5748 + } else if (orientation->IsAngularUnit()) { 1.5749 + double angle = orientation->GetAngleValueInRadians(); 1.5750 + visibility->mImageOrientation = 1.5751 + nsStyleImageOrientation::CreateAsAngleAndFlip(angle, false); 1.5752 + } else if (orientation->GetUnit() == eCSSUnit_Array) { 1.5753 + const nsCSSValue::Array* array = orientation->GetArrayValue(); 1.5754 + MOZ_ASSERT(array->Item(0).IsAngularUnit(), 1.5755 + "First image-orientation value is not an angle"); 1.5756 + MOZ_ASSERT(array->Item(1).GetUnit() == eCSSUnit_Enumerated && 1.5757 + array->Item(1).GetIntValue() == NS_STYLE_IMAGE_ORIENTATION_FLIP, 1.5758 + "Second image-orientation value is not 'flip'"); 1.5759 + double angle = array->Item(0).GetAngleValueInRadians(); 1.5760 + visibility->mImageOrientation = 1.5761 + nsStyleImageOrientation::CreateAsAngleAndFlip(angle, true); 1.5762 + 1.5763 + } else if (orientation->GetUnit() == eCSSUnit_Enumerated) { 1.5764 + switch (orientation->GetIntValue()) { 1.5765 + case NS_STYLE_IMAGE_ORIENTATION_FLIP: 1.5766 + visibility->mImageOrientation = nsStyleImageOrientation::CreateAsFlip(); 1.5767 + break; 1.5768 + case NS_STYLE_IMAGE_ORIENTATION_FROM_IMAGE: 1.5769 + visibility->mImageOrientation = nsStyleImageOrientation::CreateAsFromImage(); 1.5770 + break; 1.5771 + default: 1.5772 + NS_NOTREACHED("Invalid image-orientation enumerated value"); 1.5773 + } 1.5774 + } else { 1.5775 + MOZ_ASSERT(orientation->GetUnit() == eCSSUnit_Null, "Should be null unit"); 1.5776 + } 1.5777 + 1.5778 + COMPUTE_END_INHERITED(Visibility, visibility) 1.5779 +} 1.5780 + 1.5781 +const void* 1.5782 +nsRuleNode::ComputeColorData(void* aStartStruct, 1.5783 + const nsRuleData* aRuleData, 1.5784 + nsStyleContext* aContext, 1.5785 + nsRuleNode* aHighestNode, 1.5786 + const RuleDetail aRuleDetail, 1.5787 + const bool aCanStoreInRuleTree) 1.5788 +{ 1.5789 + COMPUTE_START_INHERITED(Color, (mPresContext), color, parentColor) 1.5790 + 1.5791 + // color: color, string, inherit 1.5792 + // Special case for currentColor. According to CSS3, setting color to 'currentColor' 1.5793 + // should behave as if it is inherited 1.5794 + const nsCSSValue* colorValue = aRuleData->ValueForColor(); 1.5795 + if ((colorValue->GetUnit() == eCSSUnit_EnumColor && 1.5796 + colorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) || 1.5797 + colorValue->GetUnit() == eCSSUnit_Unset) { 1.5798 + color->mColor = parentColor->mColor; 1.5799 + canStoreInRuleTree = false; 1.5800 + } 1.5801 + else if (colorValue->GetUnit() == eCSSUnit_Initial) { 1.5802 + color->mColor = mPresContext->DefaultColor(); 1.5803 + } 1.5804 + else { 1.5805 + SetColor(*colorValue, parentColor->mColor, mPresContext, aContext, 1.5806 + color->mColor, canStoreInRuleTree); 1.5807 + } 1.5808 + 1.5809 + COMPUTE_END_INHERITED(Color, color) 1.5810 +} 1.5811 + 1.5812 +// information about how to compute values for background-* properties 1.5813 +template <class SpecifiedValueItem, class ComputedValueItem> 1.5814 +struct BackgroundItemComputer { 1.5815 +}; 1.5816 + 1.5817 +template <> 1.5818 +struct BackgroundItemComputer<nsCSSValueList, uint8_t> 1.5819 +{ 1.5820 + static void ComputeValue(nsStyleContext* aStyleContext, 1.5821 + const nsCSSValueList* aSpecifiedValue, 1.5822 + uint8_t& aComputedValue, 1.5823 + bool& aCanStoreInRuleTree) 1.5824 + { 1.5825 + SetDiscrete(aSpecifiedValue->mValue, aComputedValue, aCanStoreInRuleTree, 1.5826 + SETDSC_ENUMERATED, uint8_t(0), 0, 0, 0, 0, 0); 1.5827 + } 1.5828 +}; 1.5829 + 1.5830 +template <> 1.5831 +struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Repeat> 1.5832 +{ 1.5833 + static void ComputeValue(nsStyleContext* aStyleContext, 1.5834 + const nsCSSValuePairList* aSpecifiedValue, 1.5835 + nsStyleBackground::Repeat& aComputedValue, 1.5836 + bool& aCanStoreInRuleTree) 1.5837 + { 1.5838 + NS_ASSERTION(aSpecifiedValue->mXValue.GetUnit() == eCSSUnit_Enumerated && 1.5839 + (aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Enumerated || 1.5840 + aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Null), 1.5841 + "Invalid unit"); 1.5842 + 1.5843 + bool hasContraction = true; 1.5844 + uint8_t value = aSpecifiedValue->mXValue.GetIntValue(); 1.5845 + switch (value) { 1.5846 + case NS_STYLE_BG_REPEAT_REPEAT_X: 1.5847 + aComputedValue.mXRepeat = NS_STYLE_BG_REPEAT_REPEAT; 1.5848 + aComputedValue.mYRepeat = NS_STYLE_BG_REPEAT_NO_REPEAT; 1.5849 + break; 1.5850 + case NS_STYLE_BG_REPEAT_REPEAT_Y: 1.5851 + aComputedValue.mXRepeat = NS_STYLE_BG_REPEAT_NO_REPEAT; 1.5852 + aComputedValue.mYRepeat = NS_STYLE_BG_REPEAT_REPEAT; 1.5853 + break; 1.5854 + default: 1.5855 + aComputedValue.mXRepeat = value; 1.5856 + hasContraction = false; 1.5857 + break; 1.5858 + } 1.5859 + 1.5860 + if (hasContraction) { 1.5861 + NS_ASSERTION(aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Null, 1.5862 + "Invalid unit."); 1.5863 + return; 1.5864 + } 1.5865 + 1.5866 + switch (aSpecifiedValue->mYValue.GetUnit()) { 1.5867 + case eCSSUnit_Null: 1.5868 + aComputedValue.mYRepeat = aComputedValue.mXRepeat; 1.5869 + break; 1.5870 + case eCSSUnit_Enumerated: 1.5871 + value = aSpecifiedValue->mYValue.GetIntValue(); 1.5872 + NS_ASSERTION(value == NS_STYLE_BG_REPEAT_NO_REPEAT || 1.5873 + value == NS_STYLE_BG_REPEAT_REPEAT, "Unexpected value"); 1.5874 + aComputedValue.mYRepeat = value; 1.5875 + break; 1.5876 + default: 1.5877 + NS_NOTREACHED("Unexpected CSS value"); 1.5878 + break; 1.5879 + } 1.5880 + } 1.5881 +}; 1.5882 + 1.5883 +template <> 1.5884 +struct BackgroundItemComputer<nsCSSValueList, nsStyleImage> 1.5885 +{ 1.5886 + static void ComputeValue(nsStyleContext* aStyleContext, 1.5887 + const nsCSSValueList* aSpecifiedValue, 1.5888 + nsStyleImage& aComputedValue, 1.5889 + bool& aCanStoreInRuleTree) 1.5890 + { 1.5891 + SetStyleImage(aStyleContext, aSpecifiedValue->mValue, aComputedValue, 1.5892 + aCanStoreInRuleTree); 1.5893 + } 1.5894 +}; 1.5895 + 1.5896 +/* Helper function for 1.5897 + * BackgroundItemComputer<nsCSSValue, nsStyleBackground::Position> 1.5898 + * It computes a single PositionCoord from an nsCSSValue object 1.5899 + * (contained in a list). 1.5900 + */ 1.5901 +typedef nsStyleBackground::Position::PositionCoord PositionCoord; 1.5902 +static void 1.5903 +ComputeBackgroundPositionCoord(nsStyleContext* aStyleContext, 1.5904 + const nsCSSValue& aEdge, 1.5905 + const nsCSSValue& aOffset, 1.5906 + PositionCoord* aResult, 1.5907 + bool& aCanStoreInRuleTree) 1.5908 +{ 1.5909 + if (eCSSUnit_Percent == aOffset.GetUnit()) { 1.5910 + aResult->mLength = 0; 1.5911 + aResult->mPercent = aOffset.GetPercentValue(); 1.5912 + aResult->mHasPercent = true; 1.5913 + } else if (aOffset.IsLengthUnit()) { 1.5914 + aResult->mLength = CalcLength(aOffset, aStyleContext, 1.5915 + aStyleContext->PresContext(), 1.5916 + aCanStoreInRuleTree); 1.5917 + aResult->mPercent = 0.0f; 1.5918 + aResult->mHasPercent = false; 1.5919 + } else if (aOffset.IsCalcUnit()) { 1.5920 + LengthPercentPairCalcOps ops(aStyleContext, 1.5921 + aStyleContext->PresContext(), 1.5922 + aCanStoreInRuleTree); 1.5923 + nsRuleNode::ComputedCalc vals = ComputeCalc(aOffset, ops); 1.5924 + aResult->mLength = vals.mLength; 1.5925 + aResult->mPercent = vals.mPercent; 1.5926 + aResult->mHasPercent = ops.mHasPercent; 1.5927 + } else { 1.5928 + aResult->mLength = 0; 1.5929 + aResult->mPercent = 0.0f; 1.5930 + aResult->mHasPercent = false; 1.5931 + NS_ASSERTION(aOffset.GetUnit() == eCSSUnit_Null, "unexpected unit"); 1.5932 + } 1.5933 + 1.5934 + if (eCSSUnit_Enumerated == aEdge.GetUnit()) { 1.5935 + int sign; 1.5936 + if (aEdge.GetIntValue() & (NS_STYLE_BG_POSITION_BOTTOM | 1.5937 + NS_STYLE_BG_POSITION_RIGHT)) { 1.5938 + sign = -1; 1.5939 + } else { 1.5940 + sign = 1; 1.5941 + } 1.5942 + aResult->mPercent = GetFloatFromBoxPosition(aEdge.GetIntValue()) + 1.5943 + sign * aResult->mPercent; 1.5944 + aResult->mLength = sign * aResult->mLength; 1.5945 + aResult->mHasPercent = true; 1.5946 + } else { 1.5947 + NS_ASSERTION(eCSSUnit_Null == aEdge.GetUnit(), "unexpected unit"); 1.5948 + } 1.5949 +} 1.5950 + 1.5951 +template <> 1.5952 +struct BackgroundItemComputer<nsCSSValueList, nsStyleBackground::Position> 1.5953 +{ 1.5954 + static void ComputeValue(nsStyleContext* aStyleContext, 1.5955 + const nsCSSValueList* aSpecifiedValue, 1.5956 + nsStyleBackground::Position& aComputedValue, 1.5957 + bool& aCanStoreInRuleTree) 1.5958 + { 1.5959 + NS_ASSERTION(aSpecifiedValue->mValue.GetUnit() == eCSSUnit_Array, "bg-position not an array"); 1.5960 + 1.5961 + nsRefPtr<nsCSSValue::Array> bgPositionArray = 1.5962 + aSpecifiedValue->mValue.GetArrayValue(); 1.5963 + const nsCSSValue &xEdge = bgPositionArray->Item(0); 1.5964 + const nsCSSValue &xOffset = bgPositionArray->Item(1); 1.5965 + const nsCSSValue &yEdge = bgPositionArray->Item(2); 1.5966 + const nsCSSValue &yOffset = bgPositionArray->Item(3); 1.5967 + 1.5968 + NS_ASSERTION((eCSSUnit_Enumerated == xEdge.GetUnit() || 1.5969 + eCSSUnit_Null == xEdge.GetUnit()) && 1.5970 + (eCSSUnit_Enumerated == yEdge.GetUnit() || 1.5971 + eCSSUnit_Null == yEdge.GetUnit()) && 1.5972 + eCSSUnit_Enumerated != xOffset.GetUnit() && 1.5973 + eCSSUnit_Enumerated != yOffset.GetUnit(), 1.5974 + "Invalid background position"); 1.5975 + 1.5976 + ComputeBackgroundPositionCoord(aStyleContext, xEdge, xOffset, 1.5977 + &aComputedValue.mXPosition, 1.5978 + aCanStoreInRuleTree); 1.5979 + 1.5980 + ComputeBackgroundPositionCoord(aStyleContext, yEdge, yOffset, 1.5981 + &aComputedValue.mYPosition, 1.5982 + aCanStoreInRuleTree); 1.5983 + } 1.5984 +}; 1.5985 + 1.5986 + 1.5987 +struct BackgroundSizeAxis { 1.5988 + nsCSSValue nsCSSValuePairList::* specified; 1.5989 + nsStyleBackground::Size::Dimension nsStyleBackground::Size::* result; 1.5990 + uint8_t nsStyleBackground::Size::* type; 1.5991 +}; 1.5992 + 1.5993 +static const BackgroundSizeAxis gBGSizeAxes[] = { 1.5994 + { &nsCSSValuePairList::mXValue, 1.5995 + &nsStyleBackground::Size::mWidth, 1.5996 + &nsStyleBackground::Size::mWidthType }, 1.5997 + { &nsCSSValuePairList::mYValue, 1.5998 + &nsStyleBackground::Size::mHeight, 1.5999 + &nsStyleBackground::Size::mHeightType } 1.6000 +}; 1.6001 + 1.6002 +template <> 1.6003 +struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Size> 1.6004 +{ 1.6005 + static void ComputeValue(nsStyleContext* aStyleContext, 1.6006 + const nsCSSValuePairList* aSpecifiedValue, 1.6007 + nsStyleBackground::Size& aComputedValue, 1.6008 + bool& aCanStoreInRuleTree) 1.6009 + { 1.6010 + nsStyleBackground::Size &size = aComputedValue; 1.6011 + for (const BackgroundSizeAxis *axis = gBGSizeAxes, 1.6012 + *axis_end = ArrayEnd(gBGSizeAxes); 1.6013 + axis < axis_end; ++axis) { 1.6014 + const nsCSSValue &specified = aSpecifiedValue->*(axis->specified); 1.6015 + if (eCSSUnit_Auto == specified.GetUnit()) { 1.6016 + size.*(axis->type) = nsStyleBackground::Size::eAuto; 1.6017 + } 1.6018 + else if (eCSSUnit_Enumerated == specified.GetUnit()) { 1.6019 + static_assert(nsStyleBackground::Size::eContain == 1.6020 + NS_STYLE_BG_SIZE_CONTAIN && 1.6021 + nsStyleBackground::Size::eCover == 1.6022 + NS_STYLE_BG_SIZE_COVER, 1.6023 + "background size constants out of sync"); 1.6024 + NS_ABORT_IF_FALSE(specified.GetIntValue() == NS_STYLE_BG_SIZE_CONTAIN || 1.6025 + specified.GetIntValue() == NS_STYLE_BG_SIZE_COVER, 1.6026 + "invalid enumerated value for size coordinate"); 1.6027 + size.*(axis->type) = specified.GetIntValue(); 1.6028 + } 1.6029 + else if (eCSSUnit_Null == specified.GetUnit()) { 1.6030 + NS_ABORT_IF_FALSE(axis == gBGSizeAxes + 1, 1.6031 + "null allowed only as height value, and only " 1.6032 + "for contain/cover/initial/inherit"); 1.6033 +#ifdef DEBUG 1.6034 + { 1.6035 + const nsCSSValue &widthValue = aSpecifiedValue->mXValue; 1.6036 + NS_ABORT_IF_FALSE(widthValue.GetUnit() != eCSSUnit_Inherit && 1.6037 + widthValue.GetUnit() != eCSSUnit_Initial && 1.6038 + widthValue.GetUnit() != eCSSUnit_Unset, 1.6039 + "initial/inherit/unset should already have been handled"); 1.6040 + NS_ABORT_IF_FALSE(widthValue.GetUnit() == eCSSUnit_Enumerated && 1.6041 + (widthValue.GetIntValue() == NS_STYLE_BG_SIZE_CONTAIN || 1.6042 + widthValue.GetIntValue() == NS_STYLE_BG_SIZE_COVER), 1.6043 + "null height value not corresponding to allowable " 1.6044 + "non-null width value"); 1.6045 + } 1.6046 +#endif 1.6047 + size.*(axis->type) = size.mWidthType; 1.6048 + } 1.6049 + else if (eCSSUnit_Percent == specified.GetUnit()) { 1.6050 + (size.*(axis->result)).mLength = 0; 1.6051 + (size.*(axis->result)).mPercent = specified.GetPercentValue(); 1.6052 + (size.*(axis->result)).mHasPercent = true; 1.6053 + size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage; 1.6054 + } 1.6055 + else if (specified.IsLengthUnit()) { 1.6056 + (size.*(axis->result)).mLength = 1.6057 + CalcLength(specified, aStyleContext, aStyleContext->PresContext(), 1.6058 + aCanStoreInRuleTree); 1.6059 + (size.*(axis->result)).mPercent = 0.0f; 1.6060 + (size.*(axis->result)).mHasPercent = false; 1.6061 + size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage; 1.6062 + } else { 1.6063 + NS_ABORT_IF_FALSE(specified.IsCalcUnit(), "unexpected unit"); 1.6064 + LengthPercentPairCalcOps ops(aStyleContext, 1.6065 + aStyleContext->PresContext(), 1.6066 + aCanStoreInRuleTree); 1.6067 + nsRuleNode::ComputedCalc vals = ComputeCalc(specified, ops); 1.6068 + (size.*(axis->result)).mLength = vals.mLength; 1.6069 + (size.*(axis->result)).mPercent = vals.mPercent; 1.6070 + (size.*(axis->result)).mHasPercent = ops.mHasPercent; 1.6071 + size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage; 1.6072 + } 1.6073 + } 1.6074 + 1.6075 + NS_ABORT_IF_FALSE(size.mWidthType < nsStyleBackground::Size::eDimensionType_COUNT, 1.6076 + "bad width type"); 1.6077 + NS_ABORT_IF_FALSE(size.mHeightType < nsStyleBackground::Size::eDimensionType_COUNT, 1.6078 + "bad height type"); 1.6079 + NS_ABORT_IF_FALSE((size.mWidthType != nsStyleBackground::Size::eContain && 1.6080 + size.mWidthType != nsStyleBackground::Size::eCover) || 1.6081 + size.mWidthType == size.mHeightType, 1.6082 + "contain/cover apply to both dimensions or to neither"); 1.6083 + } 1.6084 +}; 1.6085 + 1.6086 +template <class ComputedValueItem> 1.6087 +static void 1.6088 +SetBackgroundList(nsStyleContext* aStyleContext, 1.6089 + const nsCSSValue& aValue, 1.6090 + nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers, 1.6091 + const nsAutoTArray<nsStyleBackground::Layer, 1> &aParentLayers, 1.6092 + ComputedValueItem nsStyleBackground::Layer::* aResultLocation, 1.6093 + ComputedValueItem aInitialValue, 1.6094 + uint32_t aParentItemCount, 1.6095 + uint32_t& aItemCount, 1.6096 + uint32_t& aMaxItemCount, 1.6097 + bool& aRebuild, 1.6098 + bool& aCanStoreInRuleTree) 1.6099 +{ 1.6100 + switch (aValue.GetUnit()) { 1.6101 + case eCSSUnit_Null: 1.6102 + break; 1.6103 + 1.6104 + case eCSSUnit_Inherit: 1.6105 + aRebuild = true; 1.6106 + aCanStoreInRuleTree = false; 1.6107 + aLayers.EnsureLengthAtLeast(aParentItemCount); 1.6108 + aItemCount = aParentItemCount; 1.6109 + for (uint32_t i = 0; i < aParentItemCount; ++i) { 1.6110 + aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation; 1.6111 + } 1.6112 + break; 1.6113 + 1.6114 + case eCSSUnit_Initial: 1.6115 + case eCSSUnit_Unset: 1.6116 + aRebuild = true; 1.6117 + aItemCount = 1; 1.6118 + aLayers[0].*aResultLocation = aInitialValue; 1.6119 + break; 1.6120 + 1.6121 + case eCSSUnit_List: 1.6122 + case eCSSUnit_ListDep: { 1.6123 + aRebuild = true; 1.6124 + aItemCount = 0; 1.6125 + const nsCSSValueList* item = aValue.GetListValue(); 1.6126 + do { 1.6127 + NS_ASSERTION(item->mValue.GetUnit() != eCSSUnit_Null && 1.6128 + item->mValue.GetUnit() != eCSSUnit_Inherit && 1.6129 + item->mValue.GetUnit() != eCSSUnit_Initial && 1.6130 + item->mValue.GetUnit() != eCSSUnit_Unset, 1.6131 + "unexpected unit"); 1.6132 + ++aItemCount; 1.6133 + aLayers.EnsureLengthAtLeast(aItemCount); 1.6134 + BackgroundItemComputer<nsCSSValueList, ComputedValueItem> 1.6135 + ::ComputeValue(aStyleContext, item, 1.6136 + aLayers[aItemCount-1].*aResultLocation, 1.6137 + aCanStoreInRuleTree); 1.6138 + item = item->mNext; 1.6139 + } while (item); 1.6140 + break; 1.6141 + } 1.6142 + 1.6143 + default: 1.6144 + NS_ABORT_IF_FALSE(false, 1.6145 + nsPrintfCString("unexpected unit %d", 1.6146 + aValue.GetUnit()).get()); 1.6147 + } 1.6148 + 1.6149 + if (aItemCount > aMaxItemCount) 1.6150 + aMaxItemCount = aItemCount; 1.6151 +} 1.6152 + 1.6153 +template <class ComputedValueItem> 1.6154 +static void 1.6155 +SetBackgroundPairList(nsStyleContext* aStyleContext, 1.6156 + const nsCSSValue& aValue, 1.6157 + nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers, 1.6158 + const nsAutoTArray<nsStyleBackground::Layer, 1> 1.6159 + &aParentLayers, 1.6160 + ComputedValueItem nsStyleBackground::Layer::* 1.6161 + aResultLocation, 1.6162 + ComputedValueItem aInitialValue, 1.6163 + uint32_t aParentItemCount, 1.6164 + uint32_t& aItemCount, 1.6165 + uint32_t& aMaxItemCount, 1.6166 + bool& aRebuild, 1.6167 + bool& aCanStoreInRuleTree) 1.6168 +{ 1.6169 + switch (aValue.GetUnit()) { 1.6170 + case eCSSUnit_Null: 1.6171 + break; 1.6172 + 1.6173 + case eCSSUnit_Inherit: 1.6174 + aRebuild = true; 1.6175 + aCanStoreInRuleTree = false; 1.6176 + aLayers.EnsureLengthAtLeast(aParentItemCount); 1.6177 + aItemCount = aParentItemCount; 1.6178 + for (uint32_t i = 0; i < aParentItemCount; ++i) { 1.6179 + aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation; 1.6180 + } 1.6181 + break; 1.6182 + 1.6183 + case eCSSUnit_Initial: 1.6184 + case eCSSUnit_Unset: 1.6185 + aRebuild = true; 1.6186 + aItemCount = 1; 1.6187 + aLayers[0].*aResultLocation = aInitialValue; 1.6188 + break; 1.6189 + 1.6190 + case eCSSUnit_PairList: 1.6191 + case eCSSUnit_PairListDep: { 1.6192 + aRebuild = true; 1.6193 + aItemCount = 0; 1.6194 + const nsCSSValuePairList* item = aValue.GetPairListValue(); 1.6195 + do { 1.6196 + NS_ASSERTION(item->mXValue.GetUnit() != eCSSUnit_Inherit && 1.6197 + item->mXValue.GetUnit() != eCSSUnit_Initial && 1.6198 + item->mXValue.GetUnit() != eCSSUnit_Unset && 1.6199 + item->mYValue.GetUnit() != eCSSUnit_Inherit && 1.6200 + item->mYValue.GetUnit() != eCSSUnit_Initial && 1.6201 + item->mYValue.GetUnit() != eCSSUnit_Unset, 1.6202 + "unexpected unit"); 1.6203 + ++aItemCount; 1.6204 + aLayers.EnsureLengthAtLeast(aItemCount); 1.6205 + BackgroundItemComputer<nsCSSValuePairList, ComputedValueItem> 1.6206 + ::ComputeValue(aStyleContext, item, 1.6207 + aLayers[aItemCount-1].*aResultLocation, 1.6208 + aCanStoreInRuleTree); 1.6209 + item = item->mNext; 1.6210 + } while (item); 1.6211 + break; 1.6212 + } 1.6213 + 1.6214 + default: 1.6215 + NS_ABORT_IF_FALSE(false, 1.6216 + nsPrintfCString("unexpected unit %d", 1.6217 + aValue.GetUnit()).get()); 1.6218 + } 1.6219 + 1.6220 + if (aItemCount > aMaxItemCount) 1.6221 + aMaxItemCount = aItemCount; 1.6222 +} 1.6223 + 1.6224 +template <class ComputedValueItem> 1.6225 +static void 1.6226 +FillBackgroundList(nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers, 1.6227 + ComputedValueItem nsStyleBackground::Layer::* aResultLocation, 1.6228 + uint32_t aItemCount, uint32_t aFillCount) 1.6229 +{ 1.6230 + NS_PRECONDITION(aFillCount <= aLayers.Length(), "unexpected array length"); 1.6231 + for (uint32_t sourceLayer = 0, destLayer = aItemCount; 1.6232 + destLayer < aFillCount; 1.6233 + ++sourceLayer, ++destLayer) { 1.6234 + aLayers[destLayer].*aResultLocation = 1.6235 + aLayers[sourceLayer].*aResultLocation; 1.6236 + } 1.6237 +} 1.6238 + 1.6239 +const void* 1.6240 +nsRuleNode::ComputeBackgroundData(void* aStartStruct, 1.6241 + const nsRuleData* aRuleData, 1.6242 + nsStyleContext* aContext, 1.6243 + nsRuleNode* aHighestNode, 1.6244 + const RuleDetail aRuleDetail, 1.6245 + const bool aCanStoreInRuleTree) 1.6246 +{ 1.6247 + COMPUTE_START_RESET(Background, (), bg, parentBG) 1.6248 + 1.6249 + // background-color: color, string, inherit 1.6250 + const nsCSSValue* backColorValue = aRuleData->ValueForBackgroundColor(); 1.6251 + if (eCSSUnit_Initial == backColorValue->GetUnit() || 1.6252 + eCSSUnit_Unset == backColorValue->GetUnit()) { 1.6253 + bg->mBackgroundColor = NS_RGBA(0, 0, 0, 0); 1.6254 + } else if (!SetColor(*backColorValue, parentBG->mBackgroundColor, 1.6255 + mPresContext, aContext, bg->mBackgroundColor, 1.6256 + canStoreInRuleTree)) { 1.6257 + NS_ASSERTION(eCSSUnit_Null == backColorValue->GetUnit(), 1.6258 + "unexpected color unit"); 1.6259 + } 1.6260 + 1.6261 + uint32_t maxItemCount = 1; 1.6262 + bool rebuild = false; 1.6263 + 1.6264 + // background-image: url (stored as image), none, inherit [list] 1.6265 + nsStyleImage initialImage; 1.6266 + SetBackgroundList(aContext, *aRuleData->ValueForBackgroundImage(), 1.6267 + bg->mLayers, 1.6268 + parentBG->mLayers, &nsStyleBackground::Layer::mImage, 1.6269 + initialImage, parentBG->mImageCount, bg->mImageCount, 1.6270 + maxItemCount, rebuild, canStoreInRuleTree); 1.6271 + 1.6272 + // background-repeat: enum, inherit, initial [pair list] 1.6273 + nsStyleBackground::Repeat initialRepeat; 1.6274 + initialRepeat.SetInitialValues(); 1.6275 + SetBackgroundPairList(aContext, *aRuleData->ValueForBackgroundRepeat(), 1.6276 + bg->mLayers, 1.6277 + parentBG->mLayers, &nsStyleBackground::Layer::mRepeat, 1.6278 + initialRepeat, parentBG->mRepeatCount, 1.6279 + bg->mRepeatCount, maxItemCount, rebuild, 1.6280 + canStoreInRuleTree); 1.6281 + 1.6282 + // background-attachment: enum, inherit, initial [list] 1.6283 + SetBackgroundList(aContext, *aRuleData->ValueForBackgroundAttachment(), 1.6284 + bg->mLayers, parentBG->mLayers, 1.6285 + &nsStyleBackground::Layer::mAttachment, 1.6286 + uint8_t(NS_STYLE_BG_ATTACHMENT_SCROLL), 1.6287 + parentBG->mAttachmentCount, 1.6288 + bg->mAttachmentCount, maxItemCount, rebuild, 1.6289 + canStoreInRuleTree); 1.6290 + 1.6291 + // background-clip: enum, inherit, initial [list] 1.6292 + SetBackgroundList(aContext, *aRuleData->ValueForBackgroundClip(), 1.6293 + bg->mLayers, 1.6294 + parentBG->mLayers, &nsStyleBackground::Layer::mClip, 1.6295 + uint8_t(NS_STYLE_BG_CLIP_BORDER), parentBG->mClipCount, 1.6296 + bg->mClipCount, maxItemCount, rebuild, canStoreInRuleTree); 1.6297 + 1.6298 + // background-inline-policy: enum, inherit, initial 1.6299 + SetDiscrete(*aRuleData->ValueForBackgroundInlinePolicy(), 1.6300 + bg->mBackgroundInlinePolicy, 1.6301 + canStoreInRuleTree, 1.6302 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.6303 + parentBG->mBackgroundInlinePolicy, 1.6304 + NS_STYLE_BG_INLINE_POLICY_CONTINUOUS, 0, 0, 0, 0); 1.6305 + 1.6306 + // background-blend-mode: enum, inherit, initial [list] 1.6307 + SetBackgroundList(aContext, *aRuleData->ValueForBackgroundBlendMode(), 1.6308 + bg->mLayers, 1.6309 + parentBG->mLayers, &nsStyleBackground::Layer::mBlendMode, 1.6310 + uint8_t(NS_STYLE_BLEND_NORMAL), parentBG->mBlendModeCount, 1.6311 + bg->mBlendModeCount, maxItemCount, rebuild, 1.6312 + canStoreInRuleTree); 1.6313 + 1.6314 + // background-origin: enum, inherit, initial [list] 1.6315 + SetBackgroundList(aContext, *aRuleData->ValueForBackgroundOrigin(), 1.6316 + bg->mLayers, 1.6317 + parentBG->mLayers, &nsStyleBackground::Layer::mOrigin, 1.6318 + uint8_t(NS_STYLE_BG_ORIGIN_PADDING), parentBG->mOriginCount, 1.6319 + bg->mOriginCount, maxItemCount, rebuild, 1.6320 + canStoreInRuleTree); 1.6321 + 1.6322 + // background-position: enum, length, percent (flags), inherit [pair list] 1.6323 + nsStyleBackground::Position initialPosition; 1.6324 + initialPosition.SetInitialValues(); 1.6325 + SetBackgroundList(aContext, *aRuleData->ValueForBackgroundPosition(), 1.6326 + bg->mLayers, 1.6327 + parentBG->mLayers, &nsStyleBackground::Layer::mPosition, 1.6328 + initialPosition, parentBG->mPositionCount, 1.6329 + bg->mPositionCount, maxItemCount, rebuild, 1.6330 + canStoreInRuleTree); 1.6331 + 1.6332 + // background-size: enum, length, auto, inherit, initial [pair list] 1.6333 + nsStyleBackground::Size initialSize; 1.6334 + initialSize.SetInitialValues(); 1.6335 + SetBackgroundPairList(aContext, *aRuleData->ValueForBackgroundSize(), 1.6336 + bg->mLayers, 1.6337 + parentBG->mLayers, &nsStyleBackground::Layer::mSize, 1.6338 + initialSize, parentBG->mSizeCount, 1.6339 + bg->mSizeCount, maxItemCount, rebuild, 1.6340 + canStoreInRuleTree); 1.6341 + 1.6342 + if (rebuild) { 1.6343 + // Delete any extra items. We need to keep layers in which any 1.6344 + // property was specified. 1.6345 + bg->mLayers.TruncateLength(maxItemCount); 1.6346 + 1.6347 + uint32_t fillCount = bg->mImageCount; 1.6348 + FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mImage, 1.6349 + bg->mImageCount, fillCount); 1.6350 + FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mRepeat, 1.6351 + bg->mRepeatCount, fillCount); 1.6352 + FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mAttachment, 1.6353 + bg->mAttachmentCount, fillCount); 1.6354 + FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mClip, 1.6355 + bg->mClipCount, fillCount); 1.6356 + FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mBlendMode, 1.6357 + bg->mBlendModeCount, fillCount); 1.6358 + FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mOrigin, 1.6359 + bg->mOriginCount, fillCount); 1.6360 + FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mPosition, 1.6361 + bg->mPositionCount, fillCount); 1.6362 + FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mSize, 1.6363 + bg->mSizeCount, fillCount); 1.6364 + } 1.6365 + 1.6366 + // Now that the dust has settled, register the images with the document 1.6367 + for (uint32_t i = 0; i < bg->mImageCount; ++i) 1.6368 + bg->mLayers[i].TrackImages(aContext->PresContext()); 1.6369 + 1.6370 + COMPUTE_END_RESET(Background, bg) 1.6371 +} 1.6372 + 1.6373 +const void* 1.6374 +nsRuleNode::ComputeMarginData(void* aStartStruct, 1.6375 + const nsRuleData* aRuleData, 1.6376 + nsStyleContext* aContext, 1.6377 + nsRuleNode* aHighestNode, 1.6378 + const RuleDetail aRuleDetail, 1.6379 + const bool aCanStoreInRuleTree) 1.6380 +{ 1.6381 + COMPUTE_START_RESET(Margin, (), margin, parentMargin) 1.6382 + 1.6383 + // margin: length, percent, auto, inherit 1.6384 + nsStyleCoord coord; 1.6385 + nsCSSRect ourMargin; 1.6386 + ourMargin.mTop = *aRuleData->ValueForMarginTop(); 1.6387 + ourMargin.mRight = *aRuleData->ValueForMarginRightValue(); 1.6388 + ourMargin.mBottom = *aRuleData->ValueForMarginBottom(); 1.6389 + ourMargin.mLeft = *aRuleData->ValueForMarginLeftValue(); 1.6390 + AdjustLogicalBoxProp(aContext, 1.6391 + *aRuleData->ValueForMarginLeftLTRSource(), 1.6392 + *aRuleData->ValueForMarginLeftRTLSource(), 1.6393 + *aRuleData->ValueForMarginStartValue(), 1.6394 + *aRuleData->ValueForMarginEndValue(), 1.6395 + NS_SIDE_LEFT, ourMargin, canStoreInRuleTree); 1.6396 + AdjustLogicalBoxProp(aContext, 1.6397 + *aRuleData->ValueForMarginRightLTRSource(), 1.6398 + *aRuleData->ValueForMarginRightRTLSource(), 1.6399 + *aRuleData->ValueForMarginEndValue(), 1.6400 + *aRuleData->ValueForMarginStartValue(), 1.6401 + NS_SIDE_RIGHT, ourMargin, canStoreInRuleTree); 1.6402 + NS_FOR_CSS_SIDES(side) { 1.6403 + nsStyleCoord parentCoord = parentMargin->mMargin.Get(side); 1.6404 + if (SetCoord(ourMargin.*(nsCSSRect::sides[side]), 1.6405 + coord, parentCoord, 1.6406 + SETCOORD_LPAH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC | 1.6407 + SETCOORD_UNSET_INITIAL, 1.6408 + aContext, mPresContext, canStoreInRuleTree)) { 1.6409 + margin->mMargin.Set(side, coord); 1.6410 + } 1.6411 + } 1.6412 + 1.6413 + margin->RecalcData(); 1.6414 + COMPUTE_END_RESET(Margin, margin) 1.6415 +} 1.6416 + 1.6417 +static void 1.6418 +SetBorderImageRect(const nsCSSValue& aValue, 1.6419 + /** outparam */ nsCSSRect& aRect) 1.6420 +{ 1.6421 + switch (aValue.GetUnit()) { 1.6422 + case eCSSUnit_Null: 1.6423 + aRect.Reset(); 1.6424 + break; 1.6425 + case eCSSUnit_Rect: 1.6426 + aRect = aValue.GetRectValue(); 1.6427 + break; 1.6428 + case eCSSUnit_Inherit: 1.6429 + case eCSSUnit_Initial: 1.6430 + case eCSSUnit_Unset: 1.6431 + aRect.SetAllSidesTo(aValue); 1.6432 + break; 1.6433 + default: 1.6434 + NS_ASSERTION(false, "Unexpected border image value for rect."); 1.6435 + } 1.6436 +} 1.6437 + 1.6438 +static void 1.6439 +SetBorderImagePair(const nsCSSValue& aValue, 1.6440 + /** outparam */ nsCSSValuePair& aPair) 1.6441 +{ 1.6442 + switch (aValue.GetUnit()) { 1.6443 + case eCSSUnit_Null: 1.6444 + aPair.Reset(); 1.6445 + break; 1.6446 + case eCSSUnit_Pair: 1.6447 + aPair = aValue.GetPairValue(); 1.6448 + break; 1.6449 + case eCSSUnit_Inherit: 1.6450 + case eCSSUnit_Initial: 1.6451 + case eCSSUnit_Unset: 1.6452 + aPair.SetBothValuesTo(aValue); 1.6453 + break; 1.6454 + default: 1.6455 + NS_ASSERTION(false, "Unexpected border image value for pair."); 1.6456 + } 1.6457 +} 1.6458 + 1.6459 +static void 1.6460 +SetBorderImageSlice(const nsCSSValue& aValue, 1.6461 + /** outparam */ nsCSSValue& aSlice, 1.6462 + /** outparam */ nsCSSValue& aFill) 1.6463 +{ 1.6464 + const nsCSSValueList* valueList; 1.6465 + switch (aValue.GetUnit()) { 1.6466 + case eCSSUnit_Null: 1.6467 + aSlice.Reset(); 1.6468 + aFill.Reset(); 1.6469 + break; 1.6470 + case eCSSUnit_List: 1.6471 + // Get slice dimensions. 1.6472 + valueList = aValue.GetListValue(); 1.6473 + aSlice = valueList->mValue; 1.6474 + 1.6475 + // Get "fill" keyword. 1.6476 + valueList = valueList->mNext; 1.6477 + if (valueList) { 1.6478 + aFill = valueList->mValue; 1.6479 + } else { 1.6480 + aFill.SetInitialValue(); 1.6481 + } 1.6482 + break; 1.6483 + case eCSSUnit_Inherit: 1.6484 + case eCSSUnit_Initial: 1.6485 + case eCSSUnit_Unset: 1.6486 + aSlice = aValue; 1.6487 + aFill = aValue; 1.6488 + break; 1.6489 + default: 1.6490 + NS_ASSERTION(false, "Unexpected border image value for pair."); 1.6491 + } 1.6492 +} 1.6493 + 1.6494 +const void* 1.6495 +nsRuleNode::ComputeBorderData(void* aStartStruct, 1.6496 + const nsRuleData* aRuleData, 1.6497 + nsStyleContext* aContext, 1.6498 + nsRuleNode* aHighestNode, 1.6499 + const RuleDetail aRuleDetail, 1.6500 + const bool aCanStoreInRuleTree) 1.6501 +{ 1.6502 + COMPUTE_START_RESET(Border, (mPresContext), border, parentBorder) 1.6503 + 1.6504 + // box-shadow: none, list, inherit, initial 1.6505 + const nsCSSValue* boxShadowValue = aRuleData->ValueForBoxShadow(); 1.6506 + switch (boxShadowValue->GetUnit()) { 1.6507 + case eCSSUnit_Null: 1.6508 + break; 1.6509 + 1.6510 + case eCSSUnit_Initial: 1.6511 + case eCSSUnit_Unset: 1.6512 + case eCSSUnit_None: 1.6513 + border->mBoxShadow = nullptr; 1.6514 + break; 1.6515 + 1.6516 + case eCSSUnit_Inherit: 1.6517 + border->mBoxShadow = parentBorder->mBoxShadow; 1.6518 + canStoreInRuleTree = false; 1.6519 + break; 1.6520 + 1.6521 + case eCSSUnit_List: 1.6522 + case eCSSUnit_ListDep: 1.6523 + border->mBoxShadow = GetShadowData(boxShadowValue->GetListValue(), 1.6524 + aContext, true, canStoreInRuleTree); 1.6525 + break; 1.6526 + 1.6527 + default: 1.6528 + NS_ABORT_IF_FALSE(false, 1.6529 + nsPrintfCString("unrecognized shadow unit %d", 1.6530 + boxShadowValue->GetUnit()).get()); 1.6531 + } 1.6532 + 1.6533 + // border-width, border-*-width: length, enum, inherit 1.6534 + nsStyleCoord coord; 1.6535 + nsCSSRect ourBorderWidth; 1.6536 + ourBorderWidth.mTop = *aRuleData->ValueForBorderTopWidth(); 1.6537 + ourBorderWidth.mRight = *aRuleData->ValueForBorderRightWidthValue(); 1.6538 + ourBorderWidth.mBottom = *aRuleData->ValueForBorderBottomWidth(); 1.6539 + ourBorderWidth.mLeft = *aRuleData->ValueForBorderLeftWidthValue(); 1.6540 + AdjustLogicalBoxProp(aContext, 1.6541 + *aRuleData->ValueForBorderLeftWidthLTRSource(), 1.6542 + *aRuleData->ValueForBorderLeftWidthRTLSource(), 1.6543 + *aRuleData->ValueForBorderStartWidthValue(), 1.6544 + *aRuleData->ValueForBorderEndWidthValue(), 1.6545 + NS_SIDE_LEFT, ourBorderWidth, canStoreInRuleTree); 1.6546 + AdjustLogicalBoxProp(aContext, 1.6547 + *aRuleData->ValueForBorderRightWidthLTRSource(), 1.6548 + *aRuleData->ValueForBorderRightWidthRTLSource(), 1.6549 + *aRuleData->ValueForBorderEndWidthValue(), 1.6550 + *aRuleData->ValueForBorderStartWidthValue(), 1.6551 + NS_SIDE_RIGHT, ourBorderWidth, canStoreInRuleTree); 1.6552 + { // scope for compilers with broken |for| loop scoping 1.6553 + NS_FOR_CSS_SIDES(side) { 1.6554 + const nsCSSValue &value = ourBorderWidth.*(nsCSSRect::sides[side]); 1.6555 + NS_ASSERTION(eCSSUnit_Percent != value.GetUnit(), 1.6556 + "Percentage borders not implemented yet " 1.6557 + "If implementing, make sure to fix all consumers of " 1.6558 + "nsStyleBorder, the IsPercentageAwareChild method, " 1.6559 + "the nsAbsoluteContainingBlock::FrameDependsOnContainer " 1.6560 + "method, the " 1.6561 + "nsLineLayout::IsPercentageAwareReplacedElement method " 1.6562 + "and probably some other places"); 1.6563 + if (eCSSUnit_Enumerated == value.GetUnit()) { 1.6564 + NS_ASSERTION(value.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN || 1.6565 + value.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM || 1.6566 + value.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK, 1.6567 + "Unexpected enum value"); 1.6568 + border->SetBorderWidth(side, 1.6569 + (mPresContext->GetBorderWidthTable())[value.GetIntValue()]); 1.6570 + } 1.6571 + // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT 1.6572 + else if (SetCoord(value, coord, nsStyleCoord(), 1.6573 + SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY, 1.6574 + aContext, mPresContext, canStoreInRuleTree)) { 1.6575 + NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit"); 1.6576 + // clamp negative calc() to 0. 1.6577 + border->SetBorderWidth(side, std::max(coord.GetCoordValue(), 0)); 1.6578 + } 1.6579 + else if (eCSSUnit_Inherit == value.GetUnit()) { 1.6580 + canStoreInRuleTree = false; 1.6581 + border->SetBorderWidth(side, 1.6582 + parentBorder->GetComputedBorder().Side(side)); 1.6583 + } 1.6584 + else if (eCSSUnit_Initial == value.GetUnit() || 1.6585 + eCSSUnit_Unset == value.GetUnit()) { 1.6586 + border->SetBorderWidth(side, 1.6587 + (mPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]); 1.6588 + } 1.6589 + else { 1.6590 + NS_ASSERTION(eCSSUnit_Null == value.GetUnit(), 1.6591 + "missing case handling border width"); 1.6592 + } 1.6593 + } 1.6594 + } 1.6595 + 1.6596 + // border-style, border-*-style: enum, inherit 1.6597 + nsCSSRect ourBorderStyle; 1.6598 + ourBorderStyle.mTop = *aRuleData->ValueForBorderTopStyle(); 1.6599 + ourBorderStyle.mRight = *aRuleData->ValueForBorderRightStyleValue(); 1.6600 + ourBorderStyle.mBottom = *aRuleData->ValueForBorderBottomStyle(); 1.6601 + ourBorderStyle.mLeft = *aRuleData->ValueForBorderLeftStyleValue(); 1.6602 + AdjustLogicalBoxProp(aContext, 1.6603 + *aRuleData->ValueForBorderLeftStyleLTRSource(), 1.6604 + *aRuleData->ValueForBorderLeftStyleRTLSource(), 1.6605 + *aRuleData->ValueForBorderStartStyleValue(), 1.6606 + *aRuleData->ValueForBorderEndStyleValue(), 1.6607 + NS_SIDE_LEFT, ourBorderStyle, canStoreInRuleTree); 1.6608 + AdjustLogicalBoxProp(aContext, 1.6609 + *aRuleData->ValueForBorderRightStyleLTRSource(), 1.6610 + *aRuleData->ValueForBorderRightStyleRTLSource(), 1.6611 + *aRuleData->ValueForBorderEndStyleValue(), 1.6612 + *aRuleData->ValueForBorderStartStyleValue(), 1.6613 + NS_SIDE_RIGHT, ourBorderStyle, canStoreInRuleTree); 1.6614 + { // scope for compilers with broken |for| loop scoping 1.6615 + NS_FOR_CSS_SIDES(side) { 1.6616 + const nsCSSValue &value = ourBorderStyle.*(nsCSSRect::sides[side]); 1.6617 + nsCSSUnit unit = value.GetUnit(); 1.6618 + NS_ABORT_IF_FALSE(eCSSUnit_None != unit, 1.6619 + "'none' should be handled as enumerated value"); 1.6620 + if (eCSSUnit_Enumerated == unit) { 1.6621 + border->SetBorderStyle(side, value.GetIntValue()); 1.6622 + } 1.6623 + else if (eCSSUnit_Initial == unit || 1.6624 + eCSSUnit_Unset == unit) { 1.6625 + border->SetBorderStyle(side, NS_STYLE_BORDER_STYLE_NONE); 1.6626 + } 1.6627 + else if (eCSSUnit_Inherit == unit) { 1.6628 + canStoreInRuleTree = false; 1.6629 + border->SetBorderStyle(side, parentBorder->GetBorderStyle(side)); 1.6630 + } 1.6631 + } 1.6632 + } 1.6633 + 1.6634 + // -moz-border-*-colors: color, string, enum, none, inherit/initial 1.6635 + nscolor borderColor; 1.6636 + nscolor unused = NS_RGB(0,0,0); 1.6637 + 1.6638 + static const nsCSSProperty borderColorsProps[] = { 1.6639 + eCSSProperty_border_top_colors, 1.6640 + eCSSProperty_border_right_colors, 1.6641 + eCSSProperty_border_bottom_colors, 1.6642 + eCSSProperty_border_left_colors 1.6643 + }; 1.6644 + 1.6645 + NS_FOR_CSS_SIDES(side) { 1.6646 + const nsCSSValue& value = *aRuleData->ValueFor(borderColorsProps[side]); 1.6647 + switch (value.GetUnit()) { 1.6648 + case eCSSUnit_Null: 1.6649 + break; 1.6650 + 1.6651 + case eCSSUnit_Initial: 1.6652 + case eCSSUnit_Unset: 1.6653 + case eCSSUnit_None: 1.6654 + border->ClearBorderColors(side); 1.6655 + break; 1.6656 + 1.6657 + case eCSSUnit_Inherit: { 1.6658 + canStoreInRuleTree = false; 1.6659 + border->ClearBorderColors(side); 1.6660 + if (parentContext) { 1.6661 + nsBorderColors *parentColors; 1.6662 + parentBorder->GetCompositeColors(side, &parentColors); 1.6663 + if (parentColors) { 1.6664 + border->EnsureBorderColors(); 1.6665 + border->mBorderColors[side] = parentColors->Clone(); 1.6666 + } 1.6667 + } 1.6668 + break; 1.6669 + } 1.6670 + 1.6671 + case eCSSUnit_List: 1.6672 + case eCSSUnit_ListDep: { 1.6673 + // Some composite border color information has been specified for this 1.6674 + // border side. 1.6675 + border->EnsureBorderColors(); 1.6676 + border->ClearBorderColors(side); 1.6677 + const nsCSSValueList* list = value.GetListValue(); 1.6678 + while (list) { 1.6679 + if (SetColor(list->mValue, unused, mPresContext, 1.6680 + aContext, borderColor, canStoreInRuleTree)) 1.6681 + border->AppendBorderColor(side, borderColor); 1.6682 + else { 1.6683 + NS_NOTREACHED("unexpected item in -moz-border-*-colors list"); 1.6684 + } 1.6685 + list = list->mNext; 1.6686 + } 1.6687 + break; 1.6688 + } 1.6689 + 1.6690 + default: 1.6691 + NS_ABORT_IF_FALSE(false, "unrecognized border color unit"); 1.6692 + } 1.6693 + } 1.6694 + 1.6695 + // border-color, border-*-color: color, string, enum, inherit 1.6696 + bool foreground; 1.6697 + nsCSSRect ourBorderColor; 1.6698 + ourBorderColor.mTop = *aRuleData->ValueForBorderTopColor(); 1.6699 + ourBorderColor.mRight = *aRuleData->ValueForBorderRightColorValue(); 1.6700 + ourBorderColor.mBottom = *aRuleData->ValueForBorderBottomColor(); 1.6701 + ourBorderColor.mLeft = *aRuleData->ValueForBorderLeftColorValue(); 1.6702 + AdjustLogicalBoxProp(aContext, 1.6703 + *aRuleData->ValueForBorderLeftColorLTRSource(), 1.6704 + *aRuleData->ValueForBorderLeftColorRTLSource(), 1.6705 + *aRuleData->ValueForBorderStartColorValue(), 1.6706 + *aRuleData->ValueForBorderEndColorValue(), 1.6707 + NS_SIDE_LEFT, ourBorderColor, canStoreInRuleTree); 1.6708 + AdjustLogicalBoxProp(aContext, 1.6709 + *aRuleData->ValueForBorderRightColorLTRSource(), 1.6710 + *aRuleData->ValueForBorderRightColorRTLSource(), 1.6711 + *aRuleData->ValueForBorderEndColorValue(), 1.6712 + *aRuleData->ValueForBorderStartColorValue(), 1.6713 + NS_SIDE_RIGHT, ourBorderColor, canStoreInRuleTree); 1.6714 + { // scope for compilers with broken |for| loop scoping 1.6715 + NS_FOR_CSS_SIDES(side) { 1.6716 + const nsCSSValue &value = ourBorderColor.*(nsCSSRect::sides[side]); 1.6717 + if (eCSSUnit_Inherit == value.GetUnit()) { 1.6718 + canStoreInRuleTree = false; 1.6719 + if (parentContext) { 1.6720 + parentBorder->GetBorderColor(side, borderColor, foreground); 1.6721 + if (foreground) { 1.6722 + // We want to inherit the color from the parent, not use the 1.6723 + // color on the element where this chunk of style data will be 1.6724 + // used. We can ensure that the data for the parent are fully 1.6725 + // computed (unlike for the element where this will be used, for 1.6726 + // which the color could be specified on a more specific rule). 1.6727 + border->SetBorderColor(side, parentContext->StyleColor()->mColor); 1.6728 + } else 1.6729 + border->SetBorderColor(side, borderColor); 1.6730 + } else { 1.6731 + // We're the root 1.6732 + border->SetBorderToForeground(side); 1.6733 + } 1.6734 + } 1.6735 + else if (SetColor(value, unused, mPresContext, aContext, borderColor, 1.6736 + canStoreInRuleTree)) { 1.6737 + border->SetBorderColor(side, borderColor); 1.6738 + } 1.6739 + else if (eCSSUnit_Enumerated == value.GetUnit()) { 1.6740 + switch (value.GetIntValue()) { 1.6741 + case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR: 1.6742 + border->SetBorderToForeground(side); 1.6743 + break; 1.6744 + default: 1.6745 + NS_NOTREACHED("Unexpected enumerated color"); 1.6746 + break; 1.6747 + } 1.6748 + } 1.6749 + else if (eCSSUnit_Initial == value.GetUnit() || 1.6750 + eCSSUnit_Unset == value.GetUnit()) { 1.6751 + border->SetBorderToForeground(side); 1.6752 + } 1.6753 + } 1.6754 + } 1.6755 + 1.6756 + // border-radius: length, percent, inherit 1.6757 + { 1.6758 + const nsCSSProperty* subprops = 1.6759 + nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius); 1.6760 + NS_FOR_CSS_FULL_CORNERS(corner) { 1.6761 + int cx = NS_FULL_TO_HALF_CORNER(corner, false); 1.6762 + int cy = NS_FULL_TO_HALF_CORNER(corner, true); 1.6763 + const nsCSSValue& radius = *aRuleData->ValueFor(subprops[corner]); 1.6764 + nsStyleCoord parentX = parentBorder->mBorderRadius.Get(cx); 1.6765 + nsStyleCoord parentY = parentBorder->mBorderRadius.Get(cy); 1.6766 + nsStyleCoord coordX, coordY; 1.6767 + 1.6768 + if (SetPairCoords(radius, coordX, coordY, parentX, parentY, 1.6769 + SETCOORD_LPH | SETCOORD_INITIAL_ZERO | 1.6770 + SETCOORD_STORE_CALC | SETCOORD_UNSET_INITIAL, 1.6771 + aContext, mPresContext, canStoreInRuleTree)) { 1.6772 + border->mBorderRadius.Set(cx, coordX); 1.6773 + border->mBorderRadius.Set(cy, coordY); 1.6774 + } 1.6775 + } 1.6776 + } 1.6777 + 1.6778 + // float-edge: enum, inherit, initial 1.6779 + SetDiscrete(*aRuleData->ValueForFloatEdge(), 1.6780 + border->mFloatEdge, canStoreInRuleTree, 1.6781 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.6782 + parentBorder->mFloatEdge, 1.6783 + NS_STYLE_FLOAT_EDGE_CONTENT, 0, 0, 0, 0); 1.6784 + 1.6785 + // border-image-source 1.6786 + const nsCSSValue* borderImageSource = aRuleData->ValueForBorderImageSource(); 1.6787 + if (borderImageSource->GetUnit() == eCSSUnit_Inherit) { 1.6788 + canStoreInRuleTree = false; 1.6789 + border->mBorderImageSource = parentBorder->mBorderImageSource; 1.6790 + } else { 1.6791 + SetStyleImage(aContext, 1.6792 + *borderImageSource, 1.6793 + border->mBorderImageSource, 1.6794 + canStoreInRuleTree); 1.6795 + } 1.6796 + 1.6797 + nsCSSValue borderImageSliceValue; 1.6798 + nsCSSValue borderImageSliceFill; 1.6799 + SetBorderImageSlice(*aRuleData->ValueForBorderImageSlice(), 1.6800 + borderImageSliceValue, borderImageSliceFill); 1.6801 + 1.6802 + // border-image-slice: fill 1.6803 + SetDiscrete(borderImageSliceFill, 1.6804 + border->mBorderImageFill, 1.6805 + canStoreInRuleTree, 1.6806 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.6807 + parentBorder->mBorderImageFill, 1.6808 + NS_STYLE_BORDER_IMAGE_SLICE_NOFILL, 0, 0, 0, 0); 1.6809 + 1.6810 + nsCSSRect borderImageSlice; 1.6811 + SetBorderImageRect(borderImageSliceValue, borderImageSlice); 1.6812 + 1.6813 + nsCSSRect borderImageWidth; 1.6814 + SetBorderImageRect(*aRuleData->ValueForBorderImageWidth(), 1.6815 + borderImageWidth); 1.6816 + 1.6817 + nsCSSRect borderImageOutset; 1.6818 + SetBorderImageRect(*aRuleData->ValueForBorderImageOutset(), 1.6819 + borderImageOutset); 1.6820 + 1.6821 + NS_FOR_CSS_SIDES (side) { 1.6822 + // border-image-slice 1.6823 + if (SetCoord(borderImageSlice.*(nsCSSRect::sides[side]), coord, 1.6824 + parentBorder->mBorderImageSlice.Get(side), 1.6825 + SETCOORD_FACTOR | SETCOORD_PERCENT | 1.6826 + SETCOORD_INHERIT | SETCOORD_INITIAL_HUNDRED_PCT | 1.6827 + SETCOORD_UNSET_INITIAL, 1.6828 + aContext, mPresContext, canStoreInRuleTree)) { 1.6829 + border->mBorderImageSlice.Set(side, coord); 1.6830 + } 1.6831 + 1.6832 + // border-image-width 1.6833 + // 'auto' here means "same as slice" 1.6834 + if (SetCoord(borderImageWidth.*(nsCSSRect::sides[side]), coord, 1.6835 + parentBorder->mBorderImageWidth.Get(side), 1.6836 + SETCOORD_LPAH | SETCOORD_FACTOR | SETCOORD_INITIAL_FACTOR_ONE | 1.6837 + SETCOORD_UNSET_INITIAL, 1.6838 + aContext, mPresContext, canStoreInRuleTree)) { 1.6839 + border->mBorderImageWidth.Set(side, coord); 1.6840 + } 1.6841 + 1.6842 + // border-image-outset 1.6843 + if (SetCoord(borderImageOutset.*(nsCSSRect::sides[side]), coord, 1.6844 + parentBorder->mBorderImageOutset.Get(side), 1.6845 + SETCOORD_LENGTH | SETCOORD_FACTOR | 1.6846 + SETCOORD_INHERIT | SETCOORD_INITIAL_FACTOR_ZERO | 1.6847 + SETCOORD_UNSET_INITIAL, 1.6848 + aContext, mPresContext, canStoreInRuleTree)) { 1.6849 + border->mBorderImageOutset.Set(side, coord); 1.6850 + } 1.6851 + } 1.6852 + 1.6853 + // border-image-repeat 1.6854 + nsCSSValuePair borderImageRepeat; 1.6855 + SetBorderImagePair(*aRuleData->ValueForBorderImageRepeat(), 1.6856 + borderImageRepeat); 1.6857 + 1.6858 + SetDiscrete(borderImageRepeat.mXValue, 1.6859 + border->mBorderImageRepeatH, 1.6860 + canStoreInRuleTree, 1.6861 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.6862 + parentBorder->mBorderImageRepeatH, 1.6863 + NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH, 0, 0, 0, 0); 1.6864 + 1.6865 + SetDiscrete(borderImageRepeat.mYValue, 1.6866 + border->mBorderImageRepeatV, 1.6867 + canStoreInRuleTree, 1.6868 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.6869 + parentBorder->mBorderImageRepeatV, 1.6870 + NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH, 0, 0, 0, 0); 1.6871 + 1.6872 + border->TrackImage(aContext->PresContext()); 1.6873 + 1.6874 + COMPUTE_END_RESET(Border, border) 1.6875 +} 1.6876 + 1.6877 +const void* 1.6878 +nsRuleNode::ComputePaddingData(void* aStartStruct, 1.6879 + const nsRuleData* aRuleData, 1.6880 + nsStyleContext* aContext, 1.6881 + nsRuleNode* aHighestNode, 1.6882 + const RuleDetail aRuleDetail, 1.6883 + const bool aCanStoreInRuleTree) 1.6884 +{ 1.6885 + COMPUTE_START_RESET(Padding, (), padding, parentPadding) 1.6886 + 1.6887 + // padding: length, percent, inherit 1.6888 + nsStyleCoord coord; 1.6889 + nsCSSRect ourPadding; 1.6890 + ourPadding.mTop = *aRuleData->ValueForPaddingTop(); 1.6891 + ourPadding.mRight = *aRuleData->ValueForPaddingRightValue(); 1.6892 + ourPadding.mBottom = *aRuleData->ValueForPaddingBottom(); 1.6893 + ourPadding.mLeft = *aRuleData->ValueForPaddingLeftValue(); 1.6894 + AdjustLogicalBoxProp(aContext, 1.6895 + *aRuleData->ValueForPaddingLeftLTRSource(), 1.6896 + *aRuleData->ValueForPaddingLeftRTLSource(), 1.6897 + *aRuleData->ValueForPaddingStartValue(), 1.6898 + *aRuleData->ValueForPaddingEndValue(), 1.6899 + NS_SIDE_LEFT, ourPadding, canStoreInRuleTree); 1.6900 + AdjustLogicalBoxProp(aContext, 1.6901 + *aRuleData->ValueForPaddingRightLTRSource(), 1.6902 + *aRuleData->ValueForPaddingRightRTLSource(), 1.6903 + *aRuleData->ValueForPaddingEndValue(), 1.6904 + *aRuleData->ValueForPaddingStartValue(), 1.6905 + NS_SIDE_RIGHT, ourPadding, canStoreInRuleTree); 1.6906 + NS_FOR_CSS_SIDES(side) { 1.6907 + nsStyleCoord parentCoord = parentPadding->mPadding.Get(side); 1.6908 + if (SetCoord(ourPadding.*(nsCSSRect::sides[side]), 1.6909 + coord, parentCoord, 1.6910 + SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC | 1.6911 + SETCOORD_UNSET_INITIAL, 1.6912 + aContext, mPresContext, canStoreInRuleTree)) { 1.6913 + padding->mPadding.Set(side, coord); 1.6914 + } 1.6915 + } 1.6916 + 1.6917 + padding->RecalcData(); 1.6918 + COMPUTE_END_RESET(Padding, padding) 1.6919 +} 1.6920 + 1.6921 +const void* 1.6922 +nsRuleNode::ComputeOutlineData(void* aStartStruct, 1.6923 + const nsRuleData* aRuleData, 1.6924 + nsStyleContext* aContext, 1.6925 + nsRuleNode* aHighestNode, 1.6926 + const RuleDetail aRuleDetail, 1.6927 + const bool aCanStoreInRuleTree) 1.6928 +{ 1.6929 + COMPUTE_START_RESET(Outline, (mPresContext), outline, parentOutline) 1.6930 + 1.6931 + // outline-width: length, enum, inherit 1.6932 + const nsCSSValue* outlineWidthValue = aRuleData->ValueForOutlineWidth(); 1.6933 + if (eCSSUnit_Initial == outlineWidthValue->GetUnit() || 1.6934 + eCSSUnit_Unset == outlineWidthValue->GetUnit()) { 1.6935 + outline->mOutlineWidth = 1.6936 + nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated); 1.6937 + } 1.6938 + else { 1.6939 + SetCoord(*outlineWidthValue, outline->mOutlineWidth, 1.6940 + parentOutline->mOutlineWidth, 1.6941 + SETCOORD_LEH | SETCOORD_CALC_LENGTH_ONLY, aContext, 1.6942 + mPresContext, canStoreInRuleTree); 1.6943 + } 1.6944 + 1.6945 + // outline-offset: length, inherit 1.6946 + nsStyleCoord tempCoord; 1.6947 + const nsCSSValue* outlineOffsetValue = aRuleData->ValueForOutlineOffset(); 1.6948 + if (SetCoord(*outlineOffsetValue, tempCoord, 1.6949 + nsStyleCoord(parentOutline->mOutlineOffset, 1.6950 + nsStyleCoord::CoordConstructor), 1.6951 + SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_CALC_LENGTH_ONLY | 1.6952 + SETCOORD_UNSET_INITIAL, 1.6953 + aContext, mPresContext, canStoreInRuleTree)) { 1.6954 + outline->mOutlineOffset = tempCoord.GetCoordValue(); 1.6955 + } else { 1.6956 + NS_ASSERTION(outlineOffsetValue->GetUnit() == eCSSUnit_Null, 1.6957 + "unexpected unit"); 1.6958 + } 1.6959 + 1.6960 + // outline-color: color, string, enum, inherit 1.6961 + nscolor outlineColor; 1.6962 + nscolor unused = NS_RGB(0,0,0); 1.6963 + const nsCSSValue* outlineColorValue = aRuleData->ValueForOutlineColor(); 1.6964 + if (eCSSUnit_Inherit == outlineColorValue->GetUnit()) { 1.6965 + canStoreInRuleTree = false; 1.6966 + if (parentContext) { 1.6967 + if (parentOutline->GetOutlineColor(outlineColor)) 1.6968 + outline->SetOutlineColor(outlineColor); 1.6969 + else { 1.6970 + // We want to inherit the color from the parent, not use the 1.6971 + // color on the element where this chunk of style data will be 1.6972 + // used. We can ensure that the data for the parent are fully 1.6973 + // computed (unlike for the element where this will be used, for 1.6974 + // which the color could be specified on a more specific rule). 1.6975 + outline->SetOutlineColor(parentContext->StyleColor()->mColor); 1.6976 + } 1.6977 + } else { 1.6978 + outline->SetOutlineInitialColor(); 1.6979 + } 1.6980 + } 1.6981 + else if (SetColor(*outlineColorValue, unused, mPresContext, 1.6982 + aContext, outlineColor, canStoreInRuleTree)) 1.6983 + outline->SetOutlineColor(outlineColor); 1.6984 + else if (eCSSUnit_Enumerated == outlineColorValue->GetUnit() || 1.6985 + eCSSUnit_Initial == outlineColorValue->GetUnit() || 1.6986 + eCSSUnit_Unset == outlineColorValue->GetUnit()) { 1.6987 + outline->SetOutlineInitialColor(); 1.6988 + } 1.6989 + 1.6990 + // -moz-outline-radius: length, percent, inherit 1.6991 + { 1.6992 + const nsCSSProperty* subprops = 1.6993 + nsCSSProps::SubpropertyEntryFor(eCSSProperty__moz_outline_radius); 1.6994 + NS_FOR_CSS_FULL_CORNERS(corner) { 1.6995 + int cx = NS_FULL_TO_HALF_CORNER(corner, false); 1.6996 + int cy = NS_FULL_TO_HALF_CORNER(corner, true); 1.6997 + const nsCSSValue& radius = *aRuleData->ValueFor(subprops[corner]); 1.6998 + nsStyleCoord parentX = parentOutline->mOutlineRadius.Get(cx); 1.6999 + nsStyleCoord parentY = parentOutline->mOutlineRadius.Get(cy); 1.7000 + nsStyleCoord coordX, coordY; 1.7001 + 1.7002 + if (SetPairCoords(radius, coordX, coordY, parentX, parentY, 1.7003 + SETCOORD_LPH | SETCOORD_INITIAL_ZERO | 1.7004 + SETCOORD_STORE_CALC | SETCOORD_UNSET_INITIAL, 1.7005 + aContext, mPresContext, canStoreInRuleTree)) { 1.7006 + outline->mOutlineRadius.Set(cx, coordX); 1.7007 + outline->mOutlineRadius.Set(cy, coordY); 1.7008 + } 1.7009 + } 1.7010 + } 1.7011 + 1.7012 + // outline-style: enum, inherit, initial 1.7013 + // cannot use SetDiscrete because of SetOutlineStyle 1.7014 + const nsCSSValue* outlineStyleValue = aRuleData->ValueForOutlineStyle(); 1.7015 + nsCSSUnit unit = outlineStyleValue->GetUnit(); 1.7016 + NS_ABORT_IF_FALSE(eCSSUnit_None != unit && eCSSUnit_Auto != unit, 1.7017 + "'none' and 'auto' should be handled as enumerated values"); 1.7018 + if (eCSSUnit_Enumerated == unit) { 1.7019 + outline->SetOutlineStyle(outlineStyleValue->GetIntValue()); 1.7020 + } else if (eCSSUnit_Initial == unit || 1.7021 + eCSSUnit_Unset == unit) { 1.7022 + outline->SetOutlineStyle(NS_STYLE_BORDER_STYLE_NONE); 1.7023 + } else if (eCSSUnit_Inherit == unit) { 1.7024 + canStoreInRuleTree = false; 1.7025 + outline->SetOutlineStyle(parentOutline->GetOutlineStyle()); 1.7026 + } 1.7027 + 1.7028 + outline->RecalcData(mPresContext); 1.7029 + COMPUTE_END_RESET(Outline, outline) 1.7030 +} 1.7031 + 1.7032 +const void* 1.7033 +nsRuleNode::ComputeListData(void* aStartStruct, 1.7034 + const nsRuleData* aRuleData, 1.7035 + nsStyleContext* aContext, 1.7036 + nsRuleNode* aHighestNode, 1.7037 + const RuleDetail aRuleDetail, 1.7038 + const bool aCanStoreInRuleTree) 1.7039 +{ 1.7040 + COMPUTE_START_INHERITED(List, (), list, parentList) 1.7041 + 1.7042 + // list-style-type: enum, inherit, initial 1.7043 + SetDiscrete(*aRuleData->ValueForListStyleType(), 1.7044 + list->mListStyleType, canStoreInRuleTree, 1.7045 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.7046 + parentList->mListStyleType, 1.7047 + NS_STYLE_LIST_STYLE_DISC, 0, 0, 0, 0); 1.7048 + 1.7049 + // list-style-image: url, none, inherit 1.7050 + const nsCSSValue* imageValue = aRuleData->ValueForListStyleImage(); 1.7051 + if (eCSSUnit_Image == imageValue->GetUnit()) { 1.7052 + NS_SET_IMAGE_REQUEST_WITH_DOC(list->SetListStyleImage, 1.7053 + aContext, 1.7054 + imageValue->GetImageValue) 1.7055 + } 1.7056 + else if (eCSSUnit_None == imageValue->GetUnit() || 1.7057 + eCSSUnit_Initial == imageValue->GetUnit()) { 1.7058 + list->SetListStyleImage(nullptr); 1.7059 + } 1.7060 + else if (eCSSUnit_Inherit == imageValue->GetUnit() || 1.7061 + eCSSUnit_Unset == imageValue->GetUnit()) { 1.7062 + canStoreInRuleTree = false; 1.7063 + NS_SET_IMAGE_REQUEST(list->SetListStyleImage, 1.7064 + aContext, 1.7065 + parentList->GetListStyleImage()) 1.7066 + } 1.7067 + 1.7068 + // list-style-position: enum, inherit, initial 1.7069 + SetDiscrete(*aRuleData->ValueForListStylePosition(), 1.7070 + list->mListStylePosition, canStoreInRuleTree, 1.7071 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.7072 + parentList->mListStylePosition, 1.7073 + NS_STYLE_LIST_STYLE_POSITION_OUTSIDE, 0, 0, 0, 0); 1.7074 + 1.7075 + // image region property: length, auto, inherit 1.7076 + const nsCSSValue* imageRegionValue = aRuleData->ValueForImageRegion(); 1.7077 + switch (imageRegionValue->GetUnit()) { 1.7078 + case eCSSUnit_Inherit: 1.7079 + case eCSSUnit_Unset: 1.7080 + canStoreInRuleTree = false; 1.7081 + list->mImageRegion = parentList->mImageRegion; 1.7082 + break; 1.7083 + 1.7084 + case eCSSUnit_Initial: 1.7085 + case eCSSUnit_Auto: 1.7086 + list->mImageRegion.SetRect(0,0,0,0); 1.7087 + break; 1.7088 + 1.7089 + case eCSSUnit_Null: 1.7090 + break; 1.7091 + 1.7092 + case eCSSUnit_Rect: { 1.7093 + const nsCSSRect& rgnRect = imageRegionValue->GetRectValue(); 1.7094 + 1.7095 + if (rgnRect.mTop.GetUnit() == eCSSUnit_Auto) 1.7096 + list->mImageRegion.y = 0; 1.7097 + else if (rgnRect.mTop.IsLengthUnit()) 1.7098 + list->mImageRegion.y = 1.7099 + CalcLength(rgnRect.mTop, aContext, mPresContext, canStoreInRuleTree); 1.7100 + 1.7101 + if (rgnRect.mBottom.GetUnit() == eCSSUnit_Auto) 1.7102 + list->mImageRegion.height = 0; 1.7103 + else if (rgnRect.mBottom.IsLengthUnit()) 1.7104 + list->mImageRegion.height = 1.7105 + CalcLength(rgnRect.mBottom, aContext, mPresContext, 1.7106 + canStoreInRuleTree) - list->mImageRegion.y; 1.7107 + 1.7108 + if (rgnRect.mLeft.GetUnit() == eCSSUnit_Auto) 1.7109 + list->mImageRegion.x = 0; 1.7110 + else if (rgnRect.mLeft.IsLengthUnit()) 1.7111 + list->mImageRegion.x = 1.7112 + CalcLength(rgnRect.mLeft, aContext, mPresContext, canStoreInRuleTree); 1.7113 + 1.7114 + if (rgnRect.mRight.GetUnit() == eCSSUnit_Auto) 1.7115 + list->mImageRegion.width = 0; 1.7116 + else if (rgnRect.mRight.IsLengthUnit()) 1.7117 + list->mImageRegion.width = 1.7118 + CalcLength(rgnRect.mRight, aContext, mPresContext, 1.7119 + canStoreInRuleTree) - list->mImageRegion.x; 1.7120 + break; 1.7121 + } 1.7122 + 1.7123 + default: 1.7124 + NS_ABORT_IF_FALSE(false, "unrecognized image-region unit"); 1.7125 + } 1.7126 + 1.7127 + COMPUTE_END_INHERITED(List, list) 1.7128 +} 1.7129 + 1.7130 +static void 1.7131 +SetGridTrackBreadth(const nsCSSValue& aValue, 1.7132 + nsStyleCoord& aResult, 1.7133 + nsStyleContext* aStyleContext, 1.7134 + nsPresContext* aPresContext, 1.7135 + bool& aCanStoreInRuleTree) 1.7136 +{ 1.7137 + nsCSSUnit unit = aValue.GetUnit(); 1.7138 + if (unit == eCSSUnit_FlexFraction) { 1.7139 + aResult.SetFlexFractionValue(aValue.GetFloatValue()); 1.7140 + } else { 1.7141 + MOZ_ASSERT(unit != eCSSUnit_Inherit && unit != eCSSUnit_Unset, 1.7142 + "Unexpected value that would use dummyParentCoord"); 1.7143 + const nsStyleCoord dummyParentCoord; 1.7144 + SetCoord(aValue, aResult, dummyParentCoord, 1.7145 + SETCOORD_LPE | SETCOORD_STORE_CALC, 1.7146 + aStyleContext, aPresContext, aCanStoreInRuleTree); 1.7147 + } 1.7148 +} 1.7149 + 1.7150 +static void 1.7151 +SetGridTrackSize(const nsCSSValue& aValue, 1.7152 + nsStyleCoord& aResultMin, 1.7153 + nsStyleCoord& aResultMax, 1.7154 + nsStyleContext* aStyleContext, 1.7155 + nsPresContext* aPresContext, 1.7156 + bool& aCanStoreInRuleTree) 1.7157 +{ 1.7158 + if (aValue.GetUnit() == eCSSUnit_Function) { 1.7159 + // A minmax() function. 1.7160 + nsCSSValue::Array* func = aValue.GetArrayValue(); 1.7161 + NS_ASSERTION(func->Item(0).GetKeywordValue() == eCSSKeyword_minmax, 1.7162 + "Expected minmax(), got another function name"); 1.7163 + SetGridTrackBreadth(func->Item(1), aResultMin, 1.7164 + aStyleContext, aPresContext, aCanStoreInRuleTree); 1.7165 + SetGridTrackBreadth(func->Item(2), aResultMax, 1.7166 + aStyleContext, aPresContext, aCanStoreInRuleTree); 1.7167 + } else if (aValue.GetUnit() == eCSSUnit_Auto) { 1.7168 + // 'auto' computes to 'minmax(min-content, max-content)' 1.7169 + aResultMin.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT, 1.7170 + eStyleUnit_Enumerated); 1.7171 + aResultMax.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT, 1.7172 + eStyleUnit_Enumerated); 1.7173 + } else { 1.7174 + // A single <track-breadth>, 1.7175 + // specifies identical min and max sizing functions. 1.7176 + SetGridTrackBreadth(aValue, aResultMin, 1.7177 + aStyleContext, aPresContext, aCanStoreInRuleTree); 1.7178 + aResultMax = aResultMin; 1.7179 + } 1.7180 +} 1.7181 + 1.7182 +static void 1.7183 +SetGridAutoColumnsRows(const nsCSSValue& aValue, 1.7184 + nsStyleCoord& aResultMin, 1.7185 + nsStyleCoord& aResultMax, 1.7186 + const nsStyleCoord& aParentValueMin, 1.7187 + const nsStyleCoord& aParentValueMax, 1.7188 + nsStyleContext* aStyleContext, 1.7189 + nsPresContext* aPresContext, 1.7190 + bool& aCanStoreInRuleTree) 1.7191 + 1.7192 +{ 1.7193 + switch (aValue.GetUnit()) { 1.7194 + case eCSSUnit_Null: 1.7195 + break; 1.7196 + 1.7197 + case eCSSUnit_Inherit: 1.7198 + aCanStoreInRuleTree = false; 1.7199 + aResultMin = aParentValueMin; 1.7200 + aResultMax = aParentValueMax; 1.7201 + break; 1.7202 + 1.7203 + case eCSSUnit_Initial: 1.7204 + case eCSSUnit_Unset: 1.7205 + // The initial value is 'auto', 1.7206 + // which computes to 'minmax(min-content, max-content)'. 1.7207 + // (Explicitly-specified 'auto' values are handled in SetGridTrackSize.) 1.7208 + aResultMin.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT, 1.7209 + eStyleUnit_Enumerated); 1.7210 + aResultMax.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT, 1.7211 + eStyleUnit_Enumerated); 1.7212 + break; 1.7213 + 1.7214 + default: 1.7215 + SetGridTrackSize(aValue, aResultMin, aResultMax, 1.7216 + aStyleContext, aPresContext, aCanStoreInRuleTree); 1.7217 + } 1.7218 +} 1.7219 + 1.7220 +static void 1.7221 +AppendGridLineNames(const nsCSSValue& aValue, 1.7222 + nsStyleGridTemplate& aResult) 1.7223 +{ 1.7224 + // Compute a <line-names> value 1.7225 + nsTArray<nsString>* nameList = aResult.mLineNameLists.AppendElement(); 1.7226 + // Null unit means empty list, nothing more to do. 1.7227 + if (aValue.GetUnit() != eCSSUnit_Null) { 1.7228 + const nsCSSValueList* item = aValue.GetListValue(); 1.7229 + do { 1.7230 + nsString* name = nameList->AppendElement(); 1.7231 + item->mValue.GetStringValue(*name); 1.7232 + item = item->mNext; 1.7233 + } while (item); 1.7234 + } 1.7235 +} 1.7236 + 1.7237 +static void 1.7238 +SetGridTrackList(const nsCSSValue& aValue, 1.7239 + nsStyleGridTemplate& aResult, 1.7240 + const nsStyleGridTemplate& aParentValue, 1.7241 + nsStyleContext* aStyleContext, 1.7242 + nsPresContext* aPresContext, 1.7243 + bool& aCanStoreInRuleTree) 1.7244 + 1.7245 +{ 1.7246 + switch (aValue.GetUnit()) { 1.7247 + case eCSSUnit_Null: 1.7248 + break; 1.7249 + 1.7250 + case eCSSUnit_Inherit: 1.7251 + aCanStoreInRuleTree = false; 1.7252 + aResult.mIsSubgrid = aParentValue.mIsSubgrid; 1.7253 + aResult.mLineNameLists = aParentValue.mLineNameLists; 1.7254 + aResult.mMinTrackSizingFunctions = aParentValue.mMinTrackSizingFunctions; 1.7255 + aResult.mMaxTrackSizingFunctions = aParentValue.mMaxTrackSizingFunctions; 1.7256 + break; 1.7257 + 1.7258 + case eCSSUnit_Initial: 1.7259 + case eCSSUnit_Unset: 1.7260 + case eCSSUnit_None: 1.7261 + aResult.mIsSubgrid = false; 1.7262 + aResult.mLineNameLists.Clear(); 1.7263 + aResult.mMinTrackSizingFunctions.Clear(); 1.7264 + aResult.mMaxTrackSizingFunctions.Clear(); 1.7265 + break; 1.7266 + 1.7267 + default: 1.7268 + aResult.mLineNameLists.Clear(); 1.7269 + aResult.mMinTrackSizingFunctions.Clear(); 1.7270 + aResult.mMaxTrackSizingFunctions.Clear(); 1.7271 + const nsCSSValueList* item = aValue.GetListValue(); 1.7272 + if (item->mValue.GetUnit() == eCSSUnit_Enumerated && 1.7273 + item->mValue.GetIntValue() == NS_STYLE_GRID_TEMPLATE_SUBGRID) { 1.7274 + // subgrid <line-name-list>? 1.7275 + aResult.mIsSubgrid = true; 1.7276 + item = item->mNext; 1.7277 + while (item) { 1.7278 + AppendGridLineNames(item->mValue, aResult); 1.7279 + item = item->mNext; 1.7280 + } 1.7281 + } else { 1.7282 + // <track-list> 1.7283 + // The list is expected to have odd number of items, at least 3 1.7284 + // starting with a <line-names> (sub list of identifiers), 1.7285 + // and alternating between that and <track-size>. 1.7286 + aResult.mIsSubgrid = false; 1.7287 + for (;;) { 1.7288 + AppendGridLineNames(item->mValue, aResult); 1.7289 + item = item->mNext; 1.7290 + 1.7291 + if (!item) { 1.7292 + break; 1.7293 + } 1.7294 + 1.7295 + nsStyleCoord& min = *aResult.mMinTrackSizingFunctions.AppendElement(); 1.7296 + nsStyleCoord& max = *aResult.mMaxTrackSizingFunctions.AppendElement(); 1.7297 + SetGridTrackSize(item->mValue, min, max, 1.7298 + aStyleContext, aPresContext, aCanStoreInRuleTree); 1.7299 + 1.7300 + item = item->mNext; 1.7301 + MOZ_ASSERT(item, "Expected a eCSSUnit_List of odd length"); 1.7302 + } 1.7303 + MOZ_ASSERT(!aResult.mMinTrackSizingFunctions.IsEmpty() && 1.7304 + aResult.mMinTrackSizingFunctions.Length() == 1.7305 + aResult.mMaxTrackSizingFunctions.Length() && 1.7306 + aResult.mMinTrackSizingFunctions.Length() + 1 == 1.7307 + aResult.mLineNameLists.Length(), 1.7308 + "Inconstistent array lengths for nsStyleGridTemplate"); 1.7309 + } 1.7310 + } 1.7311 +} 1.7312 + 1.7313 +static void 1.7314 +SetGridTemplateAreas(const nsCSSValue& aValue, 1.7315 + nsRefPtr<css::GridTemplateAreasValue>* aResult, 1.7316 + css::GridTemplateAreasValue* aParentValue, 1.7317 + bool& aCanStoreInRuleTree) 1.7318 +{ 1.7319 + switch (aValue.GetUnit()) { 1.7320 + case eCSSUnit_Null: 1.7321 + break; 1.7322 + 1.7323 + case eCSSUnit_Inherit: 1.7324 + aCanStoreInRuleTree = false; 1.7325 + *aResult = aParentValue; 1.7326 + break; 1.7327 + 1.7328 + case eCSSUnit_Initial: 1.7329 + case eCSSUnit_Unset: 1.7330 + case eCSSUnit_None: 1.7331 + *aResult = nullptr; 1.7332 + break; 1.7333 + 1.7334 + default: 1.7335 + *aResult = aValue.GetGridTemplateAreas(); 1.7336 + } 1.7337 +} 1.7338 + 1.7339 +static void 1.7340 +SetGridLine(const nsCSSValue& aValue, 1.7341 + nsStyleGridLine& aResult, 1.7342 + const nsStyleGridLine& aParentValue, 1.7343 + bool& aCanStoreInRuleTree) 1.7344 + 1.7345 +{ 1.7346 + switch (aValue.GetUnit()) { 1.7347 + case eCSSUnit_Null: 1.7348 + break; 1.7349 + 1.7350 + case eCSSUnit_Inherit: 1.7351 + aCanStoreInRuleTree = false; 1.7352 + aResult = aParentValue; 1.7353 + break; 1.7354 + 1.7355 + case eCSSUnit_Initial: 1.7356 + case eCSSUnit_Unset: 1.7357 + case eCSSUnit_Auto: 1.7358 + aResult.SetAuto(); 1.7359 + break; 1.7360 + 1.7361 + default: 1.7362 + aResult.SetAuto(); // Reset any existing value. 1.7363 + const nsCSSValueList* item = aValue.GetListValue(); 1.7364 + do { 1.7365 + if (item->mValue.GetUnit() == eCSSUnit_Enumerated) { 1.7366 + aResult.mHasSpan = true; 1.7367 + } else if (item->mValue.GetUnit() == eCSSUnit_Integer) { 1.7368 + aResult.mInteger = item->mValue.GetIntValue(); 1.7369 + } else if (item->mValue.GetUnit() == eCSSUnit_Ident) { 1.7370 + item->mValue.GetStringValue(aResult.mLineName); 1.7371 + } else { 1.7372 + NS_ASSERTION(false, "Unexpected unit"); 1.7373 + } 1.7374 + item = item->mNext; 1.7375 + } while (item); 1.7376 + MOZ_ASSERT(!aResult.IsAuto(), 1.7377 + "should have set something away from default value"); 1.7378 + } 1.7379 +} 1.7380 + 1.7381 +const void* 1.7382 +nsRuleNode::ComputePositionData(void* aStartStruct, 1.7383 + const nsRuleData* aRuleData, 1.7384 + nsStyleContext* aContext, 1.7385 + nsRuleNode* aHighestNode, 1.7386 + const RuleDetail aRuleDetail, 1.7387 + const bool aCanStoreInRuleTree) 1.7388 +{ 1.7389 + COMPUTE_START_RESET(Position, (), pos, parentPos) 1.7390 + 1.7391 + // box offsets: length, percent, calc, auto, inherit 1.7392 + static const nsCSSProperty offsetProps[] = { 1.7393 + eCSSProperty_top, 1.7394 + eCSSProperty_right, 1.7395 + eCSSProperty_bottom, 1.7396 + eCSSProperty_left 1.7397 + }; 1.7398 + nsStyleCoord coord; 1.7399 + NS_FOR_CSS_SIDES(side) { 1.7400 + nsStyleCoord parentCoord = parentPos->mOffset.Get(side); 1.7401 + if (SetCoord(*aRuleData->ValueFor(offsetProps[side]), 1.7402 + coord, parentCoord, 1.7403 + SETCOORD_LPAH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC | 1.7404 + SETCOORD_UNSET_INITIAL, 1.7405 + aContext, mPresContext, canStoreInRuleTree)) { 1.7406 + pos->mOffset.Set(side, coord); 1.7407 + } 1.7408 + } 1.7409 + 1.7410 + SetCoord(*aRuleData->ValueForWidth(), pos->mWidth, parentPos->mWidth, 1.7411 + SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC | 1.7412 + SETCOORD_UNSET_INITIAL, 1.7413 + aContext, mPresContext, canStoreInRuleTree); 1.7414 + SetCoord(*aRuleData->ValueForMinWidth(), pos->mMinWidth, parentPos->mMinWidth, 1.7415 + SETCOORD_LPEH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC | 1.7416 + SETCOORD_UNSET_INITIAL, 1.7417 + aContext, mPresContext, canStoreInRuleTree); 1.7418 + SetCoord(*aRuleData->ValueForMaxWidth(), pos->mMaxWidth, parentPos->mMaxWidth, 1.7419 + SETCOORD_LPOEH | SETCOORD_INITIAL_NONE | SETCOORD_STORE_CALC | 1.7420 + SETCOORD_UNSET_INITIAL, 1.7421 + aContext, mPresContext, canStoreInRuleTree); 1.7422 + 1.7423 + SetCoord(*aRuleData->ValueForHeight(), pos->mHeight, parentPos->mHeight, 1.7424 + SETCOORD_LPAH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC | 1.7425 + SETCOORD_UNSET_INITIAL, 1.7426 + aContext, mPresContext, canStoreInRuleTree); 1.7427 + SetCoord(*aRuleData->ValueForMinHeight(), pos->mMinHeight, parentPos->mMinHeight, 1.7428 + SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC | 1.7429 + SETCOORD_UNSET_INITIAL, 1.7430 + aContext, mPresContext, canStoreInRuleTree); 1.7431 + SetCoord(*aRuleData->ValueForMaxHeight(), pos->mMaxHeight, parentPos->mMaxHeight, 1.7432 + SETCOORD_LPOH | SETCOORD_INITIAL_NONE | SETCOORD_STORE_CALC | 1.7433 + SETCOORD_UNSET_INITIAL, 1.7434 + aContext, mPresContext, canStoreInRuleTree); 1.7435 + 1.7436 + // box-sizing: enum, inherit, initial 1.7437 + SetDiscrete(*aRuleData->ValueForBoxSizing(), 1.7438 + pos->mBoxSizing, canStoreInRuleTree, 1.7439 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.7440 + parentPos->mBoxSizing, 1.7441 + NS_STYLE_BOX_SIZING_CONTENT, 0, 0, 0, 0); 1.7442 + 1.7443 + // align-content: enum, inherit, initial 1.7444 + SetDiscrete(*aRuleData->ValueForAlignContent(), 1.7445 + pos->mAlignContent, canStoreInRuleTree, 1.7446 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.7447 + parentPos->mAlignContent, 1.7448 + NS_STYLE_ALIGN_CONTENT_STRETCH, 0, 0, 0, 0); 1.7449 + 1.7450 + // align-items: enum, inherit, initial 1.7451 + SetDiscrete(*aRuleData->ValueForAlignItems(), 1.7452 + pos->mAlignItems, canStoreInRuleTree, 1.7453 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.7454 + parentPos->mAlignItems, 1.7455 + NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE, 0, 0, 0, 0); 1.7456 + 1.7457 + // align-self: enum, inherit, initial 1.7458 + // NOTE: align-self's initial value is the special keyword "auto", which is 1.7459 + // supposed to compute to our parent's computed value of "align-items". So 1.7460 + // technically, "auto" itself is never a valid computed value for align-self, 1.7461 + // since it always computes to something else. Despite that, we do actually 1.7462 + // store "auto" in nsStylePosition::mAlignSelf, as NS_STYLE_ALIGN_SELF_AUTO 1.7463 + // (and then resolve it as-necessary). We do this because "auto" is the 1.7464 + // initial value for this property, so if we were to actually resolve it in 1.7465 + // nsStylePosition, we'd never be able to share any nsStylePosition structs 1.7466 + // in the rule tree, since their mAlignSelf values would depend on the parent 1.7467 + // style, by default. 1.7468 + if (aRuleData->ValueForAlignSelf()->GetUnit() == eCSSUnit_Inherit) { 1.7469 + // Special handling for "align-self: inherit", in case we're inheriting 1.7470 + // "align-self: auto", in which case we need to resolve the parent's "auto" 1.7471 + // and inherit that resolved value. 1.7472 + uint8_t inheritedAlignSelf = parentPos->mAlignSelf; 1.7473 + if (inheritedAlignSelf == NS_STYLE_ALIGN_SELF_AUTO) { 1.7474 + if (!parentContext) { 1.7475 + // We're the root node. Nothing to inherit from --> just use default 1.7476 + // value. 1.7477 + inheritedAlignSelf = NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE; 1.7478 + } else { 1.7479 + // Our parent's "auto" value should resolve to our grandparent's value 1.7480 + // for "align-items". So, that's what we're supposed to inherit. 1.7481 + nsStyleContext* grandparentContext = parentContext->GetParent(); 1.7482 + if (!grandparentContext) { 1.7483 + // No grandparent --> our parent is the root node, so its 1.7484 + // "align-self: auto" computes to the default "align-items" value: 1.7485 + inheritedAlignSelf = NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE; 1.7486 + } else { 1.7487 + // Normal case -- we have a grandparent. 1.7488 + // Its "align-items" value is what we should end up inheriting. 1.7489 + const nsStylePosition* grandparentPos = 1.7490 + grandparentContext->StylePosition(); 1.7491 + inheritedAlignSelf = grandparentPos->mAlignItems; 1.7492 + } 1.7493 + } 1.7494 + } 1.7495 + 1.7496 + pos->mAlignSelf = inheritedAlignSelf; 1.7497 + canStoreInRuleTree = false; 1.7498 + } else { 1.7499 + SetDiscrete(*aRuleData->ValueForAlignSelf(), 1.7500 + pos->mAlignSelf, canStoreInRuleTree, 1.7501 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.7502 + parentPos->mAlignSelf, // (unused -- we handled inherit above) 1.7503 + NS_STYLE_ALIGN_SELF_AUTO, // initial == auto 1.7504 + 0, 0, 0, 0); 1.7505 + } 1.7506 + 1.7507 + // flex-basis: auto, length, percent, enum, calc, inherit, initial 1.7508 + // (Note: The flags here should match those used for 'width' property above.) 1.7509 + SetCoord(*aRuleData->ValueForFlexBasis(), pos->mFlexBasis, parentPos->mFlexBasis, 1.7510 + SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC | 1.7511 + SETCOORD_UNSET_INITIAL, 1.7512 + aContext, mPresContext, canStoreInRuleTree); 1.7513 + 1.7514 + // flex-direction: enum, inherit, initial 1.7515 + SetDiscrete(*aRuleData->ValueForFlexDirection(), 1.7516 + pos->mFlexDirection, canStoreInRuleTree, 1.7517 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.7518 + parentPos->mFlexDirection, 1.7519 + NS_STYLE_FLEX_DIRECTION_ROW, 0, 0, 0, 0); 1.7520 + 1.7521 + // flex-grow: float, inherit, initial 1.7522 + SetFactor(*aRuleData->ValueForFlexGrow(), 1.7523 + pos->mFlexGrow, canStoreInRuleTree, 1.7524 + parentPos->mFlexGrow, 0.0f, 1.7525 + SETFCT_UNSET_INITIAL); 1.7526 + 1.7527 + // flex-shrink: float, inherit, initial 1.7528 + SetFactor(*aRuleData->ValueForFlexShrink(), 1.7529 + pos->mFlexShrink, canStoreInRuleTree, 1.7530 + parentPos->mFlexShrink, 1.0f, 1.7531 + SETFCT_UNSET_INITIAL); 1.7532 + 1.7533 + // flex-wrap: enum, inherit, initial 1.7534 + SetDiscrete(*aRuleData->ValueForFlexWrap(), 1.7535 + pos->mFlexWrap, canStoreInRuleTree, 1.7536 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.7537 + parentPos->mFlexWrap, 1.7538 + NS_STYLE_FLEX_WRAP_NOWRAP, 0, 0, 0, 0); 1.7539 + 1.7540 + // order: integer, inherit, initial 1.7541 + SetDiscrete(*aRuleData->ValueForOrder(), 1.7542 + pos->mOrder, canStoreInRuleTree, 1.7543 + SETDSC_INTEGER | SETDSC_UNSET_INITIAL, 1.7544 + parentPos->mOrder, 1.7545 + NS_STYLE_ORDER_INITIAL, 0, 0, 0, 0); 1.7546 + 1.7547 + // justify-content: enum, inherit, initial 1.7548 + SetDiscrete(*aRuleData->ValueForJustifyContent(), 1.7549 + pos->mJustifyContent, canStoreInRuleTree, 1.7550 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.7551 + parentPos->mJustifyContent, 1.7552 + NS_STYLE_JUSTIFY_CONTENT_FLEX_START, 0, 0, 0, 0); 1.7553 + 1.7554 + // grid-auto-flow 1.7555 + const nsCSSValue& gridAutoFlow = *aRuleData->ValueForGridAutoFlow(); 1.7556 + switch (gridAutoFlow.GetUnit()) { 1.7557 + case eCSSUnit_Null: 1.7558 + break; 1.7559 + case eCSSUnit_Inherit: 1.7560 + canStoreInRuleTree = false; 1.7561 + pos->mGridAutoFlow = parentPos->mGridAutoFlow; 1.7562 + break; 1.7563 + case eCSSUnit_Initial: 1.7564 + case eCSSUnit_Unset: 1.7565 + pos->mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_NONE; 1.7566 + break; 1.7567 + default: 1.7568 + NS_ASSERTION(gridAutoFlow.GetUnit() == eCSSUnit_Enumerated, 1.7569 + "Unexpected unit"); 1.7570 + pos->mGridAutoFlow = gridAutoFlow.GetIntValue(); 1.7571 + } 1.7572 + 1.7573 + // grid-auto-columns 1.7574 + SetGridAutoColumnsRows(*aRuleData->ValueForGridAutoColumns(), 1.7575 + pos->mGridAutoColumnsMin, 1.7576 + pos->mGridAutoColumnsMax, 1.7577 + parentPos->mGridAutoColumnsMin, 1.7578 + parentPos->mGridAutoColumnsMax, 1.7579 + aContext, mPresContext, canStoreInRuleTree); 1.7580 + 1.7581 + // grid-auto-rows 1.7582 + SetGridAutoColumnsRows(*aRuleData->ValueForGridAutoRows(), 1.7583 + pos->mGridAutoRowsMin, 1.7584 + pos->mGridAutoRowsMax, 1.7585 + parentPos->mGridAutoRowsMin, 1.7586 + parentPos->mGridAutoRowsMax, 1.7587 + aContext, mPresContext, canStoreInRuleTree); 1.7588 + 1.7589 + // grid-template-columns 1.7590 + SetGridTrackList(*aRuleData->ValueForGridTemplateColumns(), 1.7591 + pos->mGridTemplateColumns, parentPos->mGridTemplateColumns, 1.7592 + aContext, mPresContext, canStoreInRuleTree); 1.7593 + 1.7594 + // grid-template-rows 1.7595 + SetGridTrackList(*aRuleData->ValueForGridTemplateRows(), 1.7596 + pos->mGridTemplateRows, parentPos->mGridTemplateRows, 1.7597 + aContext, mPresContext, canStoreInRuleTree); 1.7598 + 1.7599 + // grid-tempate-areas 1.7600 + SetGridTemplateAreas(*aRuleData->ValueForGridTemplateAreas(), 1.7601 + &pos->mGridTemplateAreas, 1.7602 + parentPos->mGridTemplateAreas, 1.7603 + canStoreInRuleTree); 1.7604 + 1.7605 + // grid-auto-position 1.7606 + const nsCSSValue& gridAutoPosition = *aRuleData->ValueForGridAutoPosition(); 1.7607 + switch (gridAutoPosition.GetUnit()) { 1.7608 + case eCSSUnit_Null: 1.7609 + break; 1.7610 + case eCSSUnit_Inherit: 1.7611 + canStoreInRuleTree = false; 1.7612 + pos->mGridAutoPositionColumn = parentPos->mGridAutoPositionColumn; 1.7613 + pos->mGridAutoPositionRow = parentPos->mGridAutoPositionRow; 1.7614 + break; 1.7615 + case eCSSUnit_Initial: 1.7616 + case eCSSUnit_Unset: 1.7617 + // '1 / 1' 1.7618 + pos->mGridAutoPositionColumn.SetToInteger(1); 1.7619 + pos->mGridAutoPositionRow.SetToInteger(1); 1.7620 + break; 1.7621 + default: 1.7622 + SetGridLine(gridAutoPosition.GetPairValue().mXValue, 1.7623 + pos->mGridAutoPositionColumn, 1.7624 + parentPos->mGridAutoPositionColumn, 1.7625 + canStoreInRuleTree); 1.7626 + SetGridLine(gridAutoPosition.GetPairValue().mYValue, 1.7627 + pos->mGridAutoPositionRow, 1.7628 + parentPos->mGridAutoPositionRow, 1.7629 + canStoreInRuleTree); 1.7630 + } 1.7631 + 1.7632 + // grid-column-start 1.7633 + SetGridLine(*aRuleData->ValueForGridColumnStart(), 1.7634 + pos->mGridColumnStart, 1.7635 + parentPos->mGridColumnStart, 1.7636 + canStoreInRuleTree); 1.7637 + 1.7638 + // grid-column-end 1.7639 + SetGridLine(*aRuleData->ValueForGridColumnEnd(), 1.7640 + pos->mGridColumnEnd, 1.7641 + parentPos->mGridColumnEnd, 1.7642 + canStoreInRuleTree); 1.7643 + 1.7644 + // grid-row-start 1.7645 + SetGridLine(*aRuleData->ValueForGridRowStart(), 1.7646 + pos->mGridRowStart, 1.7647 + parentPos->mGridRowStart, 1.7648 + canStoreInRuleTree); 1.7649 + 1.7650 + // grid-row-end 1.7651 + SetGridLine(*aRuleData->ValueForGridRowEnd(), 1.7652 + pos->mGridRowEnd, 1.7653 + parentPos->mGridRowEnd, 1.7654 + canStoreInRuleTree); 1.7655 + 1.7656 + // z-index 1.7657 + const nsCSSValue* zIndexValue = aRuleData->ValueForZIndex(); 1.7658 + if (! SetCoord(*zIndexValue, pos->mZIndex, parentPos->mZIndex, 1.7659 + SETCOORD_IA | SETCOORD_INITIAL_AUTO | SETCOORD_UNSET_INITIAL, 1.7660 + aContext, nullptr, canStoreInRuleTree)) { 1.7661 + if (eCSSUnit_Inherit == zIndexValue->GetUnit()) { 1.7662 + // handle inherit, because it's ok to inherit 'auto' here 1.7663 + canStoreInRuleTree = false; 1.7664 + pos->mZIndex = parentPos->mZIndex; 1.7665 + } 1.7666 + } 1.7667 + 1.7668 + COMPUTE_END_RESET(Position, pos) 1.7669 +} 1.7670 + 1.7671 +const void* 1.7672 +nsRuleNode::ComputeTableData(void* aStartStruct, 1.7673 + const nsRuleData* aRuleData, 1.7674 + nsStyleContext* aContext, 1.7675 + nsRuleNode* aHighestNode, 1.7676 + const RuleDetail aRuleDetail, 1.7677 + const bool aCanStoreInRuleTree) 1.7678 +{ 1.7679 + COMPUTE_START_RESET(Table, (), table, parentTable) 1.7680 + 1.7681 + // table-layout: enum, inherit, initial 1.7682 + SetDiscrete(*aRuleData->ValueForTableLayout(), 1.7683 + table->mLayoutStrategy, canStoreInRuleTree, 1.7684 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.7685 + parentTable->mLayoutStrategy, 1.7686 + NS_STYLE_TABLE_LAYOUT_AUTO, 0, 0, 0, 0); 1.7687 + 1.7688 + // span: pixels (not a real CSS prop) 1.7689 + const nsCSSValue* spanValue = aRuleData->ValueForSpan(); 1.7690 + if (eCSSUnit_Enumerated == spanValue->GetUnit() || 1.7691 + eCSSUnit_Integer == spanValue->GetUnit()) 1.7692 + table->mSpan = spanValue->GetIntValue(); 1.7693 + 1.7694 + COMPUTE_END_RESET(Table, table) 1.7695 +} 1.7696 + 1.7697 +const void* 1.7698 +nsRuleNode::ComputeTableBorderData(void* aStartStruct, 1.7699 + const nsRuleData* aRuleData, 1.7700 + nsStyleContext* aContext, 1.7701 + nsRuleNode* aHighestNode, 1.7702 + const RuleDetail aRuleDetail, 1.7703 + const bool aCanStoreInRuleTree) 1.7704 +{ 1.7705 + COMPUTE_START_INHERITED(TableBorder, (mPresContext), table, parentTable) 1.7706 + 1.7707 + // border-collapse: enum, inherit, initial 1.7708 + SetDiscrete(*aRuleData->ValueForBorderCollapse(), table->mBorderCollapse, 1.7709 + canStoreInRuleTree, 1.7710 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.7711 + parentTable->mBorderCollapse, 1.7712 + NS_STYLE_BORDER_SEPARATE, 0, 0, 0, 0); 1.7713 + 1.7714 + const nsCSSValue* borderSpacingValue = aRuleData->ValueForBorderSpacing(); 1.7715 + if (borderSpacingValue->GetUnit() != eCSSUnit_Null) { 1.7716 + // border-spacing-x/y: length, inherit 1.7717 + nsStyleCoord parentX(parentTable->mBorderSpacingX, 1.7718 + nsStyleCoord::CoordConstructor); 1.7719 + nsStyleCoord parentY(parentTable->mBorderSpacingY, 1.7720 + nsStyleCoord::CoordConstructor); 1.7721 + nsStyleCoord coordX, coordY; 1.7722 + 1.7723 +#ifdef DEBUG 1.7724 + bool result = 1.7725 +#endif 1.7726 + SetPairCoords(*borderSpacingValue, 1.7727 + coordX, coordY, parentX, parentY, 1.7728 + SETCOORD_LH | SETCOORD_INITIAL_ZERO | 1.7729 + SETCOORD_CALC_LENGTH_ONLY | 1.7730 + SETCOORD_CALC_CLAMP_NONNEGATIVE | SETCOORD_UNSET_INHERIT, 1.7731 + aContext, mPresContext, canStoreInRuleTree); 1.7732 + NS_ASSERTION(result, "malformed table border value"); 1.7733 + table->mBorderSpacingX = coordX.GetCoordValue(); 1.7734 + table->mBorderSpacingY = coordY.GetCoordValue(); 1.7735 + } 1.7736 + 1.7737 + // caption-side: enum, inherit, initial 1.7738 + SetDiscrete(*aRuleData->ValueForCaptionSide(), 1.7739 + table->mCaptionSide, canStoreInRuleTree, 1.7740 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.7741 + parentTable->mCaptionSide, 1.7742 + NS_STYLE_CAPTION_SIDE_TOP, 0, 0, 0, 0); 1.7743 + 1.7744 + // empty-cells: enum, inherit, initial 1.7745 + SetDiscrete(*aRuleData->ValueForEmptyCells(), 1.7746 + table->mEmptyCells, canStoreInRuleTree, 1.7747 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.7748 + parentTable->mEmptyCells, 1.7749 + (mPresContext->CompatibilityMode() == eCompatibility_NavQuirks) 1.7750 + ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND 1.7751 + : NS_STYLE_TABLE_EMPTY_CELLS_SHOW, 1.7752 + 0, 0, 0, 0); 1.7753 + 1.7754 + COMPUTE_END_INHERITED(TableBorder, table) 1.7755 +} 1.7756 + 1.7757 +const void* 1.7758 +nsRuleNode::ComputeContentData(void* aStartStruct, 1.7759 + const nsRuleData* aRuleData, 1.7760 + nsStyleContext* aContext, 1.7761 + nsRuleNode* aHighestNode, 1.7762 + const RuleDetail aRuleDetail, 1.7763 + const bool aCanStoreInRuleTree) 1.7764 +{ 1.7765 + uint32_t count; 1.7766 + nsAutoString buffer; 1.7767 + 1.7768 + COMPUTE_START_RESET(Content, (), content, parentContent) 1.7769 + 1.7770 + // content: [string, url, counter, attr, enum]+, normal, none, inherit 1.7771 + const nsCSSValue* contentValue = aRuleData->ValueForContent(); 1.7772 + switch (contentValue->GetUnit()) { 1.7773 + case eCSSUnit_Null: 1.7774 + break; 1.7775 + 1.7776 + case eCSSUnit_Normal: 1.7777 + case eCSSUnit_None: 1.7778 + case eCSSUnit_Initial: 1.7779 + case eCSSUnit_Unset: 1.7780 + // "normal", "none", "initial" and "unset" all mean no content 1.7781 + content->AllocateContents(0); 1.7782 + break; 1.7783 + 1.7784 + case eCSSUnit_Inherit: 1.7785 + canStoreInRuleTree = false; 1.7786 + count = parentContent->ContentCount(); 1.7787 + if (NS_SUCCEEDED(content->AllocateContents(count))) { 1.7788 + while (0 < count--) { 1.7789 + content->ContentAt(count) = parentContent->ContentAt(count); 1.7790 + } 1.7791 + } 1.7792 + break; 1.7793 + 1.7794 + case eCSSUnit_Enumerated: { 1.7795 + NS_ABORT_IF_FALSE(contentValue->GetIntValue() == 1.7796 + NS_STYLE_CONTENT_ALT_CONTENT, 1.7797 + "unrecognized solitary content keyword"); 1.7798 + content->AllocateContents(1); 1.7799 + nsStyleContentData& data = content->ContentAt(0); 1.7800 + data.mType = eStyleContentType_AltContent; 1.7801 + data.mContent.mString = nullptr; 1.7802 + break; 1.7803 + } 1.7804 + 1.7805 + case eCSSUnit_List: 1.7806 + case eCSSUnit_ListDep: { 1.7807 + const nsCSSValueList* contentValueList = contentValue->GetListValue(); 1.7808 + count = 0; 1.7809 + while (contentValueList) { 1.7810 + count++; 1.7811 + contentValueList = contentValueList->mNext; 1.7812 + } 1.7813 + if (NS_SUCCEEDED(content->AllocateContents(count))) { 1.7814 + const nsAutoString nullStr; 1.7815 + count = 0; 1.7816 + contentValueList = contentValue->GetListValue(); 1.7817 + while (contentValueList) { 1.7818 + const nsCSSValue& value = contentValueList->mValue; 1.7819 + nsCSSUnit unit = value.GetUnit(); 1.7820 + nsStyleContentType type; 1.7821 + nsStyleContentData &data = content->ContentAt(count++); 1.7822 + switch (unit) { 1.7823 + case eCSSUnit_String: type = eStyleContentType_String; break; 1.7824 + case eCSSUnit_Image: type = eStyleContentType_Image; break; 1.7825 + case eCSSUnit_Attr: type = eStyleContentType_Attr; break; 1.7826 + case eCSSUnit_Counter: type = eStyleContentType_Counter; break; 1.7827 + case eCSSUnit_Counters: type = eStyleContentType_Counters; break; 1.7828 + case eCSSUnit_Enumerated: 1.7829 + switch (value.GetIntValue()) { 1.7830 + case NS_STYLE_CONTENT_OPEN_QUOTE: 1.7831 + type = eStyleContentType_OpenQuote; break; 1.7832 + case NS_STYLE_CONTENT_CLOSE_QUOTE: 1.7833 + type = eStyleContentType_CloseQuote; break; 1.7834 + case NS_STYLE_CONTENT_NO_OPEN_QUOTE: 1.7835 + type = eStyleContentType_NoOpenQuote; break; 1.7836 + case NS_STYLE_CONTENT_NO_CLOSE_QUOTE: 1.7837 + type = eStyleContentType_NoCloseQuote; break; 1.7838 + default: 1.7839 + NS_ERROR("bad content value"); 1.7840 + type = eStyleContentType_Uninitialized; 1.7841 + } 1.7842 + break; 1.7843 + default: 1.7844 + NS_ERROR("bad content type"); 1.7845 + type = eStyleContentType_Uninitialized; 1.7846 + } 1.7847 + data.mType = type; 1.7848 + if (type == eStyleContentType_Image) { 1.7849 + NS_SET_IMAGE_REQUEST_WITH_DOC(data.SetImage, 1.7850 + aContext, 1.7851 + value.GetImageValue); 1.7852 + } 1.7853 + else if (type <= eStyleContentType_Attr) { 1.7854 + value.GetStringValue(buffer); 1.7855 + data.mContent.mString = NS_strdup(buffer.get()); 1.7856 + } 1.7857 + else if (type <= eStyleContentType_Counters) { 1.7858 + data.mContent.mCounters = value.GetArrayValue(); 1.7859 + data.mContent.mCounters->AddRef(); 1.7860 + } 1.7861 + else { 1.7862 + data.mContent.mString = nullptr; 1.7863 + } 1.7864 + contentValueList = contentValueList->mNext; 1.7865 + } 1.7866 + } 1.7867 + break; 1.7868 + } 1.7869 + 1.7870 + default: 1.7871 + NS_ABORT_IF_FALSE(false, 1.7872 + nsPrintfCString("unrecognized content unit %d", 1.7873 + contentValue->GetUnit()).get()); 1.7874 + } 1.7875 + 1.7876 + // counter-increment: [string [int]]+, none, inherit 1.7877 + const nsCSSValue* counterIncrementValue = 1.7878 + aRuleData->ValueForCounterIncrement(); 1.7879 + switch (counterIncrementValue->GetUnit()) { 1.7880 + case eCSSUnit_Null: 1.7881 + break; 1.7882 + 1.7883 + case eCSSUnit_None: 1.7884 + case eCSSUnit_Initial: 1.7885 + case eCSSUnit_Unset: 1.7886 + content->AllocateCounterIncrements(0); 1.7887 + break; 1.7888 + 1.7889 + case eCSSUnit_Inherit: 1.7890 + canStoreInRuleTree = false; 1.7891 + count = parentContent->CounterIncrementCount(); 1.7892 + if (NS_SUCCEEDED(content->AllocateCounterIncrements(count))) { 1.7893 + while (0 < count--) { 1.7894 + const nsStyleCounterData *data = 1.7895 + parentContent->GetCounterIncrementAt(count); 1.7896 + content->SetCounterIncrementAt(count, data->mCounter, data->mValue); 1.7897 + } 1.7898 + } 1.7899 + break; 1.7900 + 1.7901 + case eCSSUnit_PairList: 1.7902 + case eCSSUnit_PairListDep: { 1.7903 + const nsCSSValuePairList* ourIncrement = 1.7904 + counterIncrementValue->GetPairListValue(); 1.7905 + NS_ABORT_IF_FALSE(ourIncrement->mXValue.GetUnit() == eCSSUnit_Ident, 1.7906 + "unexpected value unit"); 1.7907 + count = ListLength(ourIncrement); 1.7908 + if (NS_FAILED(content->AllocateCounterIncrements(count))) { 1.7909 + break; 1.7910 + } 1.7911 + 1.7912 + count = 0; 1.7913 + for (const nsCSSValuePairList* p = ourIncrement; p; p = p->mNext, count++) { 1.7914 + int32_t increment; 1.7915 + if (p->mYValue.GetUnit() == eCSSUnit_Integer) { 1.7916 + increment = p->mYValue.GetIntValue(); 1.7917 + } else { 1.7918 + increment = 1; 1.7919 + } 1.7920 + p->mXValue.GetStringValue(buffer); 1.7921 + content->SetCounterIncrementAt(count, buffer, increment); 1.7922 + } 1.7923 + break; 1.7924 + } 1.7925 + 1.7926 + default: 1.7927 + NS_ABORT_IF_FALSE(false, "unexpected value unit"); 1.7928 + } 1.7929 + 1.7930 + // counter-reset: [string [int]]+, none, inherit 1.7931 + const nsCSSValue* counterResetValue = aRuleData->ValueForCounterReset(); 1.7932 + switch (counterResetValue->GetUnit()) { 1.7933 + case eCSSUnit_Null: 1.7934 + break; 1.7935 + 1.7936 + case eCSSUnit_None: 1.7937 + case eCSSUnit_Initial: 1.7938 + case eCSSUnit_Unset: 1.7939 + content->AllocateCounterResets(0); 1.7940 + break; 1.7941 + 1.7942 + case eCSSUnit_Inherit: 1.7943 + canStoreInRuleTree = false; 1.7944 + count = parentContent->CounterResetCount(); 1.7945 + if (NS_SUCCEEDED(content->AllocateCounterResets(count))) { 1.7946 + while (0 < count--) { 1.7947 + const nsStyleCounterData *data = 1.7948 + parentContent->GetCounterResetAt(count); 1.7949 + content->SetCounterResetAt(count, data->mCounter, data->mValue); 1.7950 + } 1.7951 + } 1.7952 + break; 1.7953 + 1.7954 + case eCSSUnit_PairList: 1.7955 + case eCSSUnit_PairListDep: { 1.7956 + const nsCSSValuePairList* ourReset = 1.7957 + counterResetValue->GetPairListValue(); 1.7958 + NS_ABORT_IF_FALSE(ourReset->mXValue.GetUnit() == eCSSUnit_Ident, 1.7959 + "unexpected value unit"); 1.7960 + count = ListLength(ourReset); 1.7961 + if (NS_FAILED(content->AllocateCounterResets(count))) { 1.7962 + break; 1.7963 + } 1.7964 + 1.7965 + count = 0; 1.7966 + for (const nsCSSValuePairList* p = ourReset; p; p = p->mNext, count++) { 1.7967 + int32_t reset; 1.7968 + if (p->mYValue.GetUnit() == eCSSUnit_Integer) { 1.7969 + reset = p->mYValue.GetIntValue(); 1.7970 + } else { 1.7971 + reset = 0; 1.7972 + } 1.7973 + p->mXValue.GetStringValue(buffer); 1.7974 + content->SetCounterResetAt(count, buffer, reset); 1.7975 + } 1.7976 + break; 1.7977 + } 1.7978 + 1.7979 + default: 1.7980 + NS_ABORT_IF_FALSE(false, "unexpected value unit"); 1.7981 + } 1.7982 + 1.7983 + // marker-offset: length, auto, inherit 1.7984 + SetCoord(*aRuleData->ValueForMarkerOffset(), content->mMarkerOffset, parentContent->mMarkerOffset, 1.7985 + SETCOORD_LH | SETCOORD_AUTO | SETCOORD_INITIAL_AUTO | 1.7986 + SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INITIAL, 1.7987 + aContext, mPresContext, canStoreInRuleTree); 1.7988 + 1.7989 + // If we ended up with an image, track it. 1.7990 + for (uint32_t i = 0; i < content->ContentCount(); ++i) { 1.7991 + if ((content->ContentAt(i).mType == eStyleContentType_Image) && 1.7992 + content->ContentAt(i).mContent.mImage) { 1.7993 + content->ContentAt(i).TrackImage(aContext->PresContext()); 1.7994 + } 1.7995 + } 1.7996 + 1.7997 + COMPUTE_END_RESET(Content, content) 1.7998 +} 1.7999 + 1.8000 +const void* 1.8001 +nsRuleNode::ComputeQuotesData(void* aStartStruct, 1.8002 + const nsRuleData* aRuleData, 1.8003 + nsStyleContext* aContext, 1.8004 + nsRuleNode* aHighestNode, 1.8005 + const RuleDetail aRuleDetail, 1.8006 + const bool aCanStoreInRuleTree) 1.8007 +{ 1.8008 + COMPUTE_START_INHERITED(Quotes, (), quotes, parentQuotes) 1.8009 + 1.8010 + // quotes: inherit, initial, none, [string string]+ 1.8011 + const nsCSSValue* quotesValue = aRuleData->ValueForQuotes(); 1.8012 + switch (quotesValue->GetUnit()) { 1.8013 + case eCSSUnit_Null: 1.8014 + break; 1.8015 + case eCSSUnit_Inherit: 1.8016 + case eCSSUnit_Unset: 1.8017 + canStoreInRuleTree = false; 1.8018 + quotes->CopyFrom(*parentQuotes); 1.8019 + break; 1.8020 + case eCSSUnit_Initial: 1.8021 + quotes->SetInitial(); 1.8022 + break; 1.8023 + case eCSSUnit_None: 1.8024 + quotes->AllocateQuotes(0); 1.8025 + break; 1.8026 + case eCSSUnit_PairList: 1.8027 + case eCSSUnit_PairListDep: { 1.8028 + const nsCSSValuePairList* ourQuotes 1.8029 + = quotesValue->GetPairListValue(); 1.8030 + nsAutoString buffer; 1.8031 + nsAutoString closeBuffer; 1.8032 + uint32_t count = ListLength(ourQuotes); 1.8033 + if (NS_FAILED(quotes->AllocateQuotes(count))) { 1.8034 + break; 1.8035 + } 1.8036 + count = 0; 1.8037 + while (ourQuotes) { 1.8038 + NS_ABORT_IF_FALSE(ourQuotes->mXValue.GetUnit() == eCSSUnit_String && 1.8039 + ourQuotes->mYValue.GetUnit() == eCSSUnit_String, 1.8040 + "improper list contents for quotes"); 1.8041 + ourQuotes->mXValue.GetStringValue(buffer); 1.8042 + ourQuotes->mYValue.GetStringValue(closeBuffer); 1.8043 + quotes->SetQuotesAt(count++, buffer, closeBuffer); 1.8044 + ourQuotes = ourQuotes->mNext; 1.8045 + } 1.8046 + break; 1.8047 + } 1.8048 + default: 1.8049 + NS_ABORT_IF_FALSE(false, "unexpected value unit"); 1.8050 + } 1.8051 + 1.8052 + COMPUTE_END_INHERITED(Quotes, quotes) 1.8053 +} 1.8054 + 1.8055 +const void* 1.8056 +nsRuleNode::ComputeXULData(void* aStartStruct, 1.8057 + const nsRuleData* aRuleData, 1.8058 + nsStyleContext* aContext, 1.8059 + nsRuleNode* aHighestNode, 1.8060 + const RuleDetail aRuleDetail, 1.8061 + const bool aCanStoreInRuleTree) 1.8062 +{ 1.8063 + COMPUTE_START_RESET(XUL, (), xul, parentXUL) 1.8064 + 1.8065 + // box-align: enum, inherit, initial 1.8066 + SetDiscrete(*aRuleData->ValueForBoxAlign(), 1.8067 + xul->mBoxAlign, canStoreInRuleTree, 1.8068 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.8069 + parentXUL->mBoxAlign, 1.8070 + NS_STYLE_BOX_ALIGN_STRETCH, 0, 0, 0, 0); 1.8071 + 1.8072 + // box-direction: enum, inherit, initial 1.8073 + SetDiscrete(*aRuleData->ValueForBoxDirection(), 1.8074 + xul->mBoxDirection, canStoreInRuleTree, 1.8075 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.8076 + parentXUL->mBoxDirection, 1.8077 + NS_STYLE_BOX_DIRECTION_NORMAL, 0, 0, 0, 0); 1.8078 + 1.8079 + // box-flex: factor, inherit 1.8080 + SetFactor(*aRuleData->ValueForBoxFlex(), 1.8081 + xul->mBoxFlex, canStoreInRuleTree, 1.8082 + parentXUL->mBoxFlex, 0.0f, 1.8083 + SETFCT_UNSET_INITIAL); 1.8084 + 1.8085 + // box-orient: enum, inherit, initial 1.8086 + SetDiscrete(*aRuleData->ValueForBoxOrient(), 1.8087 + xul->mBoxOrient, canStoreInRuleTree, 1.8088 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.8089 + parentXUL->mBoxOrient, 1.8090 + NS_STYLE_BOX_ORIENT_HORIZONTAL, 0, 0, 0, 0); 1.8091 + 1.8092 + // box-pack: enum, inherit, initial 1.8093 + SetDiscrete(*aRuleData->ValueForBoxPack(), 1.8094 + xul->mBoxPack, canStoreInRuleTree, 1.8095 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.8096 + parentXUL->mBoxPack, 1.8097 + NS_STYLE_BOX_PACK_START, 0, 0, 0, 0); 1.8098 + 1.8099 + // box-ordinal-group: integer, inherit, initial 1.8100 + SetDiscrete(*aRuleData->ValueForBoxOrdinalGroup(), 1.8101 + xul->mBoxOrdinal, canStoreInRuleTree, 1.8102 + SETDSC_INTEGER | SETDSC_UNSET_INITIAL, 1.8103 + parentXUL->mBoxOrdinal, 1, 1.8104 + 0, 0, 0, 0); 1.8105 + 1.8106 + const nsCSSValue* stackSizingValue = aRuleData->ValueForStackSizing(); 1.8107 + if (eCSSUnit_Inherit == stackSizingValue->GetUnit()) { 1.8108 + canStoreInRuleTree = false; 1.8109 + xul->mStretchStack = parentXUL->mStretchStack; 1.8110 + } else if (eCSSUnit_Initial == stackSizingValue->GetUnit() || 1.8111 + eCSSUnit_Unset == stackSizingValue->GetUnit()) { 1.8112 + xul->mStretchStack = true; 1.8113 + } else if (eCSSUnit_Enumerated == stackSizingValue->GetUnit()) { 1.8114 + xul->mStretchStack = stackSizingValue->GetIntValue() == 1.8115 + NS_STYLE_STACK_SIZING_STRETCH_TO_FIT; 1.8116 + } 1.8117 + 1.8118 + COMPUTE_END_RESET(XUL, xul) 1.8119 +} 1.8120 + 1.8121 +const void* 1.8122 +nsRuleNode::ComputeColumnData(void* aStartStruct, 1.8123 + const nsRuleData* aRuleData, 1.8124 + nsStyleContext* aContext, 1.8125 + nsRuleNode* aHighestNode, 1.8126 + const RuleDetail aRuleDetail, 1.8127 + const bool aCanStoreInRuleTree) 1.8128 +{ 1.8129 + COMPUTE_START_RESET(Column, (mPresContext), column, parent) 1.8130 + 1.8131 + // column-width: length, auto, inherit 1.8132 + SetCoord(*aRuleData->ValueForColumnWidth(), 1.8133 + column->mColumnWidth, parent->mColumnWidth, 1.8134 + SETCOORD_LAH | SETCOORD_INITIAL_AUTO | 1.8135 + SETCOORD_CALC_LENGTH_ONLY | SETCOORD_CALC_CLAMP_NONNEGATIVE | 1.8136 + SETCOORD_UNSET_INITIAL, 1.8137 + aContext, mPresContext, canStoreInRuleTree); 1.8138 + 1.8139 + // column-gap: length, inherit, normal 1.8140 + SetCoord(*aRuleData->ValueForColumnGap(), 1.8141 + column->mColumnGap, parent->mColumnGap, 1.8142 + SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL | 1.8143 + SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INITIAL, 1.8144 + aContext, mPresContext, canStoreInRuleTree); 1.8145 + // clamp negative calc() to 0 1.8146 + if (column->mColumnGap.GetUnit() == eStyleUnit_Coord) { 1.8147 + column->mColumnGap.SetCoordValue( 1.8148 + std::max(column->mColumnGap.GetCoordValue(), 0)); 1.8149 + } 1.8150 + 1.8151 + // column-count: auto, integer, inherit 1.8152 + const nsCSSValue* columnCountValue = aRuleData->ValueForColumnCount(); 1.8153 + if (eCSSUnit_Auto == columnCountValue->GetUnit() || 1.8154 + eCSSUnit_Initial == columnCountValue->GetUnit() || 1.8155 + eCSSUnit_Unset == columnCountValue->GetUnit()) { 1.8156 + column->mColumnCount = NS_STYLE_COLUMN_COUNT_AUTO; 1.8157 + } else if (eCSSUnit_Integer == columnCountValue->GetUnit()) { 1.8158 + column->mColumnCount = columnCountValue->GetIntValue(); 1.8159 + // Max kMaxColumnCount columns - wallpaper for bug 345583. 1.8160 + column->mColumnCount = std::min(column->mColumnCount, 1.8161 + nsStyleColumn::kMaxColumnCount); 1.8162 + } else if (eCSSUnit_Inherit == columnCountValue->GetUnit()) { 1.8163 + canStoreInRuleTree = false; 1.8164 + column->mColumnCount = parent->mColumnCount; 1.8165 + } 1.8166 + 1.8167 + // column-rule-width: length, enum, inherit 1.8168 + const nsCSSValue& widthValue = *aRuleData->ValueForColumnRuleWidth(); 1.8169 + if (eCSSUnit_Initial == widthValue.GetUnit() || 1.8170 + eCSSUnit_Unset == widthValue.GetUnit()) { 1.8171 + column->SetColumnRuleWidth( 1.8172 + (mPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]); 1.8173 + } 1.8174 + else if (eCSSUnit_Enumerated == widthValue.GetUnit()) { 1.8175 + NS_ASSERTION(widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN || 1.8176 + widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM || 1.8177 + widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK, 1.8178 + "Unexpected enum value"); 1.8179 + column->SetColumnRuleWidth( 1.8180 + (mPresContext->GetBorderWidthTable())[widthValue.GetIntValue()]); 1.8181 + } 1.8182 + else if (eCSSUnit_Inherit == widthValue.GetUnit()) { 1.8183 + column->SetColumnRuleWidth(parent->GetComputedColumnRuleWidth()); 1.8184 + canStoreInRuleTree = false; 1.8185 + } 1.8186 + else if (widthValue.IsLengthUnit() || widthValue.IsCalcUnit()) { 1.8187 + nscoord len = 1.8188 + CalcLength(widthValue, aContext, mPresContext, canStoreInRuleTree); 1.8189 + if (len < 0) { 1.8190 + // FIXME: This is untested (by test_value_storage.html) for 1.8191 + // column-rule-width since it gets covered up by the border 1.8192 + // rounding code. 1.8193 + NS_ASSERTION(widthValue.IsCalcUnit(), 1.8194 + "parser should have rejected negative length"); 1.8195 + len = 0; 1.8196 + } 1.8197 + column->SetColumnRuleWidth(len); 1.8198 + } 1.8199 + 1.8200 + // column-rule-style: enum, inherit 1.8201 + const nsCSSValue& styleValue = *aRuleData->ValueForColumnRuleStyle(); 1.8202 + NS_ABORT_IF_FALSE(eCSSUnit_None != styleValue.GetUnit(), 1.8203 + "'none' should be handled as enumerated value"); 1.8204 + if (eCSSUnit_Enumerated == styleValue.GetUnit()) { 1.8205 + column->mColumnRuleStyle = styleValue.GetIntValue(); 1.8206 + } 1.8207 + else if (eCSSUnit_Initial == styleValue.GetUnit() || 1.8208 + eCSSUnit_Unset == styleValue.GetUnit()) { 1.8209 + column->mColumnRuleStyle = NS_STYLE_BORDER_STYLE_NONE; 1.8210 + } 1.8211 + else if (eCSSUnit_Inherit == styleValue.GetUnit()) { 1.8212 + canStoreInRuleTree = false; 1.8213 + column->mColumnRuleStyle = parent->mColumnRuleStyle; 1.8214 + } 1.8215 + 1.8216 + // column-rule-color: color, inherit 1.8217 + const nsCSSValue& colorValue = *aRuleData->ValueForColumnRuleColor(); 1.8218 + if (eCSSUnit_Inherit == colorValue.GetUnit()) { 1.8219 + canStoreInRuleTree = false; 1.8220 + column->mColumnRuleColorIsForeground = false; 1.8221 + if (parent->mColumnRuleColorIsForeground) { 1.8222 + if (parentContext) { 1.8223 + column->mColumnRuleColor = parentContext->StyleColor()->mColor; 1.8224 + } else { 1.8225 + nsStyleColor defaultColumnRuleColor(mPresContext); 1.8226 + column->mColumnRuleColor = defaultColumnRuleColor.mColor; 1.8227 + } 1.8228 + } else { 1.8229 + column->mColumnRuleColor = parent->mColumnRuleColor; 1.8230 + } 1.8231 + } 1.8232 + else if (eCSSUnit_Initial == colorValue.GetUnit() || 1.8233 + eCSSUnit_Unset == colorValue.GetUnit() || 1.8234 + eCSSUnit_Enumerated == colorValue.GetUnit()) { 1.8235 + column->mColumnRuleColorIsForeground = true; 1.8236 + } 1.8237 + else if (SetColor(colorValue, 0, mPresContext, aContext, 1.8238 + column->mColumnRuleColor, canStoreInRuleTree)) { 1.8239 + column->mColumnRuleColorIsForeground = false; 1.8240 + } 1.8241 + 1.8242 + // column-fill: enum 1.8243 + SetDiscrete(*aRuleData->ValueForColumnFill(), 1.8244 + column->mColumnFill, canStoreInRuleTree, 1.8245 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.8246 + parent->mColumnFill, 1.8247 + NS_STYLE_COLUMN_FILL_BALANCE, 1.8248 + 0, 0, 0, 0); 1.8249 + 1.8250 + COMPUTE_END_RESET(Column, column) 1.8251 +} 1.8252 + 1.8253 +static void 1.8254 +SetSVGPaint(const nsCSSValue& aValue, const nsStyleSVGPaint& parentPaint, 1.8255 + nsPresContext* aPresContext, nsStyleContext *aContext, 1.8256 + nsStyleSVGPaint& aResult, nsStyleSVGPaintType aInitialPaintType, 1.8257 + bool& aCanStoreInRuleTree) 1.8258 +{ 1.8259 + nscolor color; 1.8260 + 1.8261 + if (aValue.GetUnit() == eCSSUnit_Inherit || 1.8262 + aValue.GetUnit() == eCSSUnit_Unset) { 1.8263 + aResult = parentPaint; 1.8264 + aCanStoreInRuleTree = false; 1.8265 + } else if (aValue.GetUnit() == eCSSUnit_None) { 1.8266 + aResult.SetType(eStyleSVGPaintType_None); 1.8267 + } else if (aValue.GetUnit() == eCSSUnit_Initial) { 1.8268 + aResult.SetType(aInitialPaintType); 1.8269 + aResult.mPaint.mColor = NS_RGB(0, 0, 0); 1.8270 + aResult.mFallbackColor = NS_RGB(0, 0, 0); 1.8271 + } else if (SetColor(aValue, NS_RGB(0, 0, 0), aPresContext, aContext, 1.8272 + color, aCanStoreInRuleTree)) { 1.8273 + aResult.SetType(eStyleSVGPaintType_Color); 1.8274 + aResult.mPaint.mColor = color; 1.8275 + } else if (aValue.GetUnit() == eCSSUnit_Pair) { 1.8276 + const nsCSSValuePair& pair = aValue.GetPairValue(); 1.8277 + 1.8278 + if (pair.mXValue.GetUnit() == eCSSUnit_URL) { 1.8279 + aResult.SetType(eStyleSVGPaintType_Server); 1.8280 + aResult.mPaint.mPaintServer = pair.mXValue.GetURLValue(); 1.8281 + NS_IF_ADDREF(aResult.mPaint.mPaintServer); 1.8282 + } else if (pair.mXValue.GetUnit() == eCSSUnit_Enumerated) { 1.8283 + 1.8284 + switch (pair.mXValue.GetIntValue()) { 1.8285 + case NS_COLOR_CONTEXT_FILL: 1.8286 + aResult.SetType(eStyleSVGPaintType_ContextFill); 1.8287 + break; 1.8288 + case NS_COLOR_CONTEXT_STROKE: 1.8289 + aResult.SetType(eStyleSVGPaintType_ContextStroke); 1.8290 + break; 1.8291 + default: 1.8292 + NS_NOTREACHED("unknown keyword as paint server value"); 1.8293 + } 1.8294 + 1.8295 + } else { 1.8296 + NS_NOTREACHED("malformed paint server value"); 1.8297 + } 1.8298 + 1.8299 + if (pair.mYValue.GetUnit() == eCSSUnit_None) { 1.8300 + aResult.mFallbackColor = NS_RGBA(0, 0, 0, 0); 1.8301 + } else { 1.8302 + NS_ABORT_IF_FALSE(pair.mYValue.GetUnit() != eCSSUnit_Inherit, 1.8303 + "cannot inherit fallback colour"); 1.8304 + SetColor(pair.mYValue, NS_RGB(0, 0, 0), aPresContext, aContext, 1.8305 + aResult.mFallbackColor, aCanStoreInRuleTree); 1.8306 + } 1.8307 + } else { 1.8308 + NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Null, 1.8309 + "malformed paint server value"); 1.8310 + } 1.8311 +} 1.8312 + 1.8313 +static void 1.8314 +SetSVGOpacity(const nsCSSValue& aValue, 1.8315 + float& aOpacityField, nsStyleSVGOpacitySource& aOpacityTypeField, 1.8316 + bool& aCanStoreInRuleTree, 1.8317 + float aParentOpacity, nsStyleSVGOpacitySource aParentOpacityType) 1.8318 +{ 1.8319 + if (eCSSUnit_Enumerated == aValue.GetUnit()) { 1.8320 + switch (aValue.GetIntValue()) { 1.8321 + case NS_STYLE_CONTEXT_FILL_OPACITY: 1.8322 + aOpacityTypeField = eStyleSVGOpacitySource_ContextFillOpacity; 1.8323 + break; 1.8324 + case NS_STYLE_CONTEXT_STROKE_OPACITY: 1.8325 + aOpacityTypeField = eStyleSVGOpacitySource_ContextStrokeOpacity; 1.8326 + break; 1.8327 + default: 1.8328 + NS_NOTREACHED("SetSVGOpacity: Unknown keyword"); 1.8329 + } 1.8330 + // Fall back on fully opaque 1.8331 + aOpacityField = 1.0f; 1.8332 + } else if (eCSSUnit_Inherit == aValue.GetUnit() || 1.8333 + eCSSUnit_Unset == aValue.GetUnit()) { 1.8334 + aCanStoreInRuleTree = false; 1.8335 + aOpacityField = aParentOpacity; 1.8336 + aOpacityTypeField = aParentOpacityType; 1.8337 + } else if (eCSSUnit_Null != aValue.GetUnit()) { 1.8338 + SetFactor(aValue, aOpacityField, aCanStoreInRuleTree, 1.8339 + aParentOpacity, 1.0f, SETFCT_OPACITY); 1.8340 + aOpacityTypeField = eStyleSVGOpacitySource_Normal; 1.8341 + } 1.8342 +} 1.8343 + 1.8344 +const void* 1.8345 +nsRuleNode::ComputeSVGData(void* aStartStruct, 1.8346 + const nsRuleData* aRuleData, 1.8347 + nsStyleContext* aContext, 1.8348 + nsRuleNode* aHighestNode, 1.8349 + const RuleDetail aRuleDetail, 1.8350 + const bool aCanStoreInRuleTree) 1.8351 +{ 1.8352 + COMPUTE_START_INHERITED(SVG, (), svg, parentSVG) 1.8353 + 1.8354 + // clip-rule: enum, inherit, initial 1.8355 + SetDiscrete(*aRuleData->ValueForClipRule(), 1.8356 + svg->mClipRule, canStoreInRuleTree, 1.8357 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.8358 + parentSVG->mClipRule, 1.8359 + NS_STYLE_FILL_RULE_NONZERO, 0, 0, 0, 0); 1.8360 + 1.8361 + // color-interpolation: enum, inherit, initial 1.8362 + SetDiscrete(*aRuleData->ValueForColorInterpolation(), 1.8363 + svg->mColorInterpolation, canStoreInRuleTree, 1.8364 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.8365 + parentSVG->mColorInterpolation, 1.8366 + NS_STYLE_COLOR_INTERPOLATION_SRGB, 0, 0, 0, 0); 1.8367 + 1.8368 + // color-interpolation-filters: enum, inherit, initial 1.8369 + SetDiscrete(*aRuleData->ValueForColorInterpolationFilters(), 1.8370 + svg->mColorInterpolationFilters, canStoreInRuleTree, 1.8371 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.8372 + parentSVG->mColorInterpolationFilters, 1.8373 + NS_STYLE_COLOR_INTERPOLATION_LINEARRGB, 0, 0, 0, 0); 1.8374 + 1.8375 + // fill: 1.8376 + SetSVGPaint(*aRuleData->ValueForFill(), 1.8377 + parentSVG->mFill, mPresContext, aContext, 1.8378 + svg->mFill, eStyleSVGPaintType_Color, canStoreInRuleTree); 1.8379 + 1.8380 + // fill-opacity: factor, inherit, initial, 1.8381 + // context-fill-opacity, context-stroke-opacity 1.8382 + nsStyleSVGOpacitySource contextFillOpacity = svg->mFillOpacitySource; 1.8383 + SetSVGOpacity(*aRuleData->ValueForFillOpacity(), 1.8384 + svg->mFillOpacity, contextFillOpacity, canStoreInRuleTree, 1.8385 + parentSVG->mFillOpacity, parentSVG->mFillOpacitySource); 1.8386 + svg->mFillOpacitySource = contextFillOpacity; 1.8387 + 1.8388 + // fill-rule: enum, inherit, initial 1.8389 + SetDiscrete(*aRuleData->ValueForFillRule(), 1.8390 + svg->mFillRule, canStoreInRuleTree, 1.8391 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.8392 + parentSVG->mFillRule, 1.8393 + NS_STYLE_FILL_RULE_NONZERO, 0, 0, 0, 0); 1.8394 + 1.8395 + // image-rendering: enum, inherit 1.8396 + SetDiscrete(*aRuleData->ValueForImageRendering(), 1.8397 + svg->mImageRendering, canStoreInRuleTree, 1.8398 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.8399 + parentSVG->mImageRendering, 1.8400 + NS_STYLE_IMAGE_RENDERING_AUTO, 0, 0, 0, 0); 1.8401 + 1.8402 + // marker-end: url, none, inherit 1.8403 + const nsCSSValue* markerEndValue = aRuleData->ValueForMarkerEnd(); 1.8404 + if (eCSSUnit_URL == markerEndValue->GetUnit()) { 1.8405 + svg->mMarkerEnd = markerEndValue->GetURLValue(); 1.8406 + } else if (eCSSUnit_None == markerEndValue->GetUnit() || 1.8407 + eCSSUnit_Initial == markerEndValue->GetUnit()) { 1.8408 + svg->mMarkerEnd = nullptr; 1.8409 + } else if (eCSSUnit_Inherit == markerEndValue->GetUnit() || 1.8410 + eCSSUnit_Unset == markerEndValue->GetUnit()) { 1.8411 + canStoreInRuleTree = false; 1.8412 + svg->mMarkerEnd = parentSVG->mMarkerEnd; 1.8413 + } 1.8414 + 1.8415 + // marker-mid: url, none, inherit 1.8416 + const nsCSSValue* markerMidValue = aRuleData->ValueForMarkerMid(); 1.8417 + if (eCSSUnit_URL == markerMidValue->GetUnit()) { 1.8418 + svg->mMarkerMid = markerMidValue->GetURLValue(); 1.8419 + } else if (eCSSUnit_None == markerMidValue->GetUnit() || 1.8420 + eCSSUnit_Initial == markerMidValue->GetUnit()) { 1.8421 + svg->mMarkerMid = nullptr; 1.8422 + } else if (eCSSUnit_Inherit == markerMidValue->GetUnit() || 1.8423 + eCSSUnit_Unset == markerMidValue->GetUnit()) { 1.8424 + canStoreInRuleTree = false; 1.8425 + svg->mMarkerMid = parentSVG->mMarkerMid; 1.8426 + } 1.8427 + 1.8428 + // marker-start: url, none, inherit 1.8429 + const nsCSSValue* markerStartValue = aRuleData->ValueForMarkerStart(); 1.8430 + if (eCSSUnit_URL == markerStartValue->GetUnit()) { 1.8431 + svg->mMarkerStart = markerStartValue->GetURLValue(); 1.8432 + } else if (eCSSUnit_None == markerStartValue->GetUnit() || 1.8433 + eCSSUnit_Initial == markerStartValue->GetUnit()) { 1.8434 + svg->mMarkerStart = nullptr; 1.8435 + } else if (eCSSUnit_Inherit == markerStartValue->GetUnit() || 1.8436 + eCSSUnit_Unset == markerStartValue->GetUnit()) { 1.8437 + canStoreInRuleTree = false; 1.8438 + svg->mMarkerStart = parentSVG->mMarkerStart; 1.8439 + } 1.8440 + 1.8441 + // paint-order: enum (bit field), inherit, initial 1.8442 + const nsCSSValue* paintOrderValue = aRuleData->ValueForPaintOrder(); 1.8443 + switch (paintOrderValue->GetUnit()) { 1.8444 + case eCSSUnit_Null: 1.8445 + break; 1.8446 + 1.8447 + case eCSSUnit_Enumerated: 1.8448 + static_assert 1.8449 + (NS_STYLE_PAINT_ORDER_BITWIDTH * NS_STYLE_PAINT_ORDER_LAST_VALUE <= 8, 1.8450 + "SVGStyleStruct::mPaintOrder not big enough"); 1.8451 + svg->mPaintOrder = static_cast<uint8_t>(paintOrderValue->GetIntValue()); 1.8452 + break; 1.8453 + 1.8454 + case eCSSUnit_Inherit: 1.8455 + case eCSSUnit_Unset: 1.8456 + canStoreInRuleTree = false; 1.8457 + svg->mPaintOrder = parentSVG->mPaintOrder; 1.8458 + break; 1.8459 + 1.8460 + case eCSSUnit_Initial: 1.8461 + svg->mPaintOrder = NS_STYLE_PAINT_ORDER_NORMAL; 1.8462 + break; 1.8463 + 1.8464 + default: 1.8465 + NS_NOTREACHED("unexpected unit"); 1.8466 + } 1.8467 + 1.8468 + // shape-rendering: enum, inherit 1.8469 + SetDiscrete(*aRuleData->ValueForShapeRendering(), 1.8470 + svg->mShapeRendering, canStoreInRuleTree, 1.8471 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.8472 + parentSVG->mShapeRendering, 1.8473 + NS_STYLE_SHAPE_RENDERING_AUTO, 0, 0, 0, 0); 1.8474 + 1.8475 + // stroke: 1.8476 + SetSVGPaint(*aRuleData->ValueForStroke(), 1.8477 + parentSVG->mStroke, mPresContext, aContext, 1.8478 + svg->mStroke, eStyleSVGPaintType_None, canStoreInRuleTree); 1.8479 + 1.8480 + // stroke-dasharray: <dasharray>, none, inherit, context-value 1.8481 + const nsCSSValue* strokeDasharrayValue = aRuleData->ValueForStrokeDasharray(); 1.8482 + switch (strokeDasharrayValue->GetUnit()) { 1.8483 + case eCSSUnit_Null: 1.8484 + break; 1.8485 + 1.8486 + case eCSSUnit_Inherit: 1.8487 + case eCSSUnit_Unset: 1.8488 + canStoreInRuleTree = false; 1.8489 + svg->mStrokeDasharrayFromObject = parentSVG->mStrokeDasharrayFromObject; 1.8490 + // only do the copy if weren't already set up by the copy constructor 1.8491 + // FIXME Bug 389408: This is broken when aStartStruct is non-null! 1.8492 + if (!svg->mStrokeDasharray) { 1.8493 + svg->mStrokeDasharrayLength = parentSVG->mStrokeDasharrayLength; 1.8494 + if (svg->mStrokeDasharrayLength) { 1.8495 + svg->mStrokeDasharray = new nsStyleCoord[svg->mStrokeDasharrayLength]; 1.8496 + if (svg->mStrokeDasharray) 1.8497 + memcpy(svg->mStrokeDasharray, 1.8498 + parentSVG->mStrokeDasharray, 1.8499 + svg->mStrokeDasharrayLength * sizeof(nsStyleCoord)); 1.8500 + else 1.8501 + svg->mStrokeDasharrayLength = 0; 1.8502 + } 1.8503 + } 1.8504 + break; 1.8505 + 1.8506 + case eCSSUnit_Enumerated: 1.8507 + NS_ABORT_IF_FALSE(strokeDasharrayValue->GetIntValue() == 1.8508 + NS_STYLE_STROKE_PROP_CONTEXT_VALUE, 1.8509 + "Unknown keyword for stroke-dasharray"); 1.8510 + svg->mStrokeDasharrayFromObject = true; 1.8511 + delete [] svg->mStrokeDasharray; 1.8512 + svg->mStrokeDasharray = nullptr; 1.8513 + svg->mStrokeDasharrayLength = 0; 1.8514 + break; 1.8515 + 1.8516 + case eCSSUnit_Initial: 1.8517 + case eCSSUnit_None: 1.8518 + svg->mStrokeDasharrayFromObject = false; 1.8519 + delete [] svg->mStrokeDasharray; 1.8520 + svg->mStrokeDasharray = nullptr; 1.8521 + svg->mStrokeDasharrayLength = 0; 1.8522 + break; 1.8523 + 1.8524 + case eCSSUnit_List: 1.8525 + case eCSSUnit_ListDep: { 1.8526 + svg->mStrokeDasharrayFromObject = false; 1.8527 + delete [] svg->mStrokeDasharray; 1.8528 + svg->mStrokeDasharray = nullptr; 1.8529 + svg->mStrokeDasharrayLength = 0; 1.8530 + 1.8531 + // count number of values 1.8532 + const nsCSSValueList *value = strokeDasharrayValue->GetListValue(); 1.8533 + svg->mStrokeDasharrayLength = ListLength(value); 1.8534 + 1.8535 + NS_ASSERTION(svg->mStrokeDasharrayLength != 0, "no dasharray items"); 1.8536 + 1.8537 + svg->mStrokeDasharray = new nsStyleCoord[svg->mStrokeDasharrayLength]; 1.8538 + 1.8539 + if (svg->mStrokeDasharray) { 1.8540 + uint32_t i = 0; 1.8541 + while (nullptr != value) { 1.8542 + SetCoord(value->mValue, 1.8543 + svg->mStrokeDasharray[i++], nsStyleCoord(), 1.8544 + SETCOORD_LP | SETCOORD_FACTOR, 1.8545 + aContext, mPresContext, canStoreInRuleTree); 1.8546 + value = value->mNext; 1.8547 + } 1.8548 + } else { 1.8549 + svg->mStrokeDasharrayLength = 0; 1.8550 + } 1.8551 + break; 1.8552 + } 1.8553 + 1.8554 + default: 1.8555 + NS_ABORT_IF_FALSE(false, "unrecognized dasharray unit"); 1.8556 + } 1.8557 + 1.8558 + // stroke-dashoffset: <dashoffset>, inherit 1.8559 + const nsCSSValue *strokeDashoffsetValue = 1.8560 + aRuleData->ValueForStrokeDashoffset(); 1.8561 + svg->mStrokeDashoffsetFromObject = 1.8562 + strokeDashoffsetValue->GetUnit() == eCSSUnit_Enumerated && 1.8563 + strokeDashoffsetValue->GetIntValue() == NS_STYLE_STROKE_PROP_CONTEXT_VALUE; 1.8564 + if (svg->mStrokeDashoffsetFromObject) { 1.8565 + svg->mStrokeDashoffset.SetCoordValue(0); 1.8566 + } else { 1.8567 + SetCoord(*aRuleData->ValueForStrokeDashoffset(), 1.8568 + svg->mStrokeDashoffset, parentSVG->mStrokeDashoffset, 1.8569 + SETCOORD_LPH | SETCOORD_FACTOR | SETCOORD_INITIAL_ZERO | 1.8570 + SETCOORD_UNSET_INHERIT, 1.8571 + aContext, mPresContext, canStoreInRuleTree); 1.8572 + } 1.8573 + 1.8574 + // stroke-linecap: enum, inherit, initial 1.8575 + SetDiscrete(*aRuleData->ValueForStrokeLinecap(), 1.8576 + svg->mStrokeLinecap, canStoreInRuleTree, 1.8577 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.8578 + parentSVG->mStrokeLinecap, 1.8579 + NS_STYLE_STROKE_LINECAP_BUTT, 0, 0, 0, 0); 1.8580 + 1.8581 + // stroke-linejoin: enum, inherit, initial 1.8582 + SetDiscrete(*aRuleData->ValueForStrokeLinejoin(), 1.8583 + svg->mStrokeLinejoin, canStoreInRuleTree, 1.8584 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.8585 + parentSVG->mStrokeLinejoin, 1.8586 + NS_STYLE_STROKE_LINEJOIN_MITER, 0, 0, 0, 0); 1.8587 + 1.8588 + // stroke-miterlimit: <miterlimit>, inherit 1.8589 + SetFactor(*aRuleData->ValueForStrokeMiterlimit(), 1.8590 + svg->mStrokeMiterlimit, 1.8591 + canStoreInRuleTree, 1.8592 + parentSVG->mStrokeMiterlimit, 4.0f, 1.8593 + SETFCT_UNSET_INHERIT); 1.8594 + 1.8595 + // stroke-opacity: 1.8596 + nsStyleSVGOpacitySource contextStrokeOpacity = svg->mStrokeOpacitySource; 1.8597 + SetSVGOpacity(*aRuleData->ValueForStrokeOpacity(), 1.8598 + svg->mStrokeOpacity, contextStrokeOpacity, canStoreInRuleTree, 1.8599 + parentSVG->mStrokeOpacity, parentSVG->mStrokeOpacitySource); 1.8600 + svg->mStrokeOpacitySource = contextStrokeOpacity; 1.8601 + 1.8602 + // stroke-width: 1.8603 + const nsCSSValue* strokeWidthValue = aRuleData->ValueForStrokeWidth(); 1.8604 + switch (strokeWidthValue->GetUnit()) { 1.8605 + case eCSSUnit_Enumerated: 1.8606 + NS_ABORT_IF_FALSE(strokeWidthValue->GetIntValue() == 1.8607 + NS_STYLE_STROKE_PROP_CONTEXT_VALUE, 1.8608 + "Unrecognized keyword for stroke-width"); 1.8609 + svg->mStrokeWidthFromObject = true; 1.8610 + svg->mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1)); 1.8611 + break; 1.8612 + 1.8613 + case eCSSUnit_Initial: 1.8614 + svg->mStrokeWidthFromObject = false; 1.8615 + svg->mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1)); 1.8616 + break; 1.8617 + 1.8618 + default: 1.8619 + svg->mStrokeWidthFromObject = false; 1.8620 + SetCoord(*strokeWidthValue, 1.8621 + svg->mStrokeWidth, parentSVG->mStrokeWidth, 1.8622 + SETCOORD_LPH | SETCOORD_FACTOR | SETCOORD_UNSET_INHERIT, 1.8623 + aContext, mPresContext, canStoreInRuleTree); 1.8624 + } 1.8625 + 1.8626 + // text-anchor: enum, inherit, initial 1.8627 + SetDiscrete(*aRuleData->ValueForTextAnchor(), 1.8628 + svg->mTextAnchor, canStoreInRuleTree, 1.8629 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.8630 + parentSVG->mTextAnchor, 1.8631 + NS_STYLE_TEXT_ANCHOR_START, 0, 0, 0, 0); 1.8632 + 1.8633 + // text-rendering: enum, inherit, initial 1.8634 + SetDiscrete(*aRuleData->ValueForTextRendering(), 1.8635 + svg->mTextRendering, canStoreInRuleTree, 1.8636 + SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, 1.8637 + parentSVG->mTextRendering, 1.8638 + NS_STYLE_TEXT_RENDERING_AUTO, 0, 0, 0, 0); 1.8639 + 1.8640 + COMPUTE_END_INHERITED(SVG, svg) 1.8641 +} 1.8642 + 1.8643 +// Returns true if the nsStyleFilter was successfully set using the nsCSSValue. 1.8644 +bool 1.8645 +nsRuleNode::SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter, 1.8646 + const nsCSSValue& aValue, 1.8647 + nsStyleContext* aStyleContext, 1.8648 + nsPresContext* aPresContext, 1.8649 + bool& aCanStoreInRuleTree) 1.8650 +{ 1.8651 + nsCSSUnit unit = aValue.GetUnit(); 1.8652 + if (unit == eCSSUnit_URL) { 1.8653 + nsIURI* url = aValue.GetURLValue(); 1.8654 + if (!url) 1.8655 + return false; 1.8656 + aStyleFilter->SetURL(url); 1.8657 + return true; 1.8658 + } 1.8659 + 1.8660 + NS_ABORT_IF_FALSE(unit == eCSSUnit_Function, "expected a filter function"); 1.8661 + 1.8662 + nsCSSValue::Array* filterFunction = aValue.GetArrayValue(); 1.8663 + nsCSSKeyword functionName = 1.8664 + (nsCSSKeyword)filterFunction->Item(0).GetIntValue(); 1.8665 + 1.8666 + int32_t type; 1.8667 + DebugOnly<bool> foundKeyword = 1.8668 + nsCSSProps::FindKeyword(functionName, 1.8669 + nsCSSProps::kFilterFunctionKTable, 1.8670 + type); 1.8671 + NS_ABORT_IF_FALSE(foundKeyword, "unknown filter type"); 1.8672 + if (type == NS_STYLE_FILTER_DROP_SHADOW) { 1.8673 + nsRefPtr<nsCSSShadowArray> shadowArray = GetShadowData( 1.8674 + filterFunction->Item(1).GetListValue(), 1.8675 + aStyleContext, 1.8676 + false, 1.8677 + aCanStoreInRuleTree); 1.8678 + aStyleFilter->SetDropShadow(shadowArray); 1.8679 + return true; 1.8680 + } 1.8681 + 1.8682 + int32_t mask = SETCOORD_PERCENT | SETCOORD_FACTOR; 1.8683 + if (type == NS_STYLE_FILTER_BLUR) { 1.8684 + mask = SETCOORD_LENGTH | SETCOORD_STORE_CALC; 1.8685 + } else if (type == NS_STYLE_FILTER_HUE_ROTATE) { 1.8686 + mask = SETCOORD_ANGLE; 1.8687 + } 1.8688 + 1.8689 + NS_ABORT_IF_FALSE(filterFunction->Count() == 2, 1.8690 + "all filter functions should have " 1.8691 + "exactly one argument"); 1.8692 + 1.8693 + nsCSSValue& arg = filterFunction->Item(1); 1.8694 + nsStyleCoord filterParameter; 1.8695 + DebugOnly<bool> didSetCoord = SetCoord(arg, filterParameter, 1.8696 + nsStyleCoord(), mask, 1.8697 + aStyleContext, aPresContext, 1.8698 + aCanStoreInRuleTree); 1.8699 + aStyleFilter->SetFilterParameter(filterParameter, type); 1.8700 + NS_ABORT_IF_FALSE(didSetCoord, "unexpected unit"); 1.8701 + return true; 1.8702 +} 1.8703 + 1.8704 +const void* 1.8705 +nsRuleNode::ComputeSVGResetData(void* aStartStruct, 1.8706 + const nsRuleData* aRuleData, 1.8707 + nsStyleContext* aContext, 1.8708 + nsRuleNode* aHighestNode, 1.8709 + const RuleDetail aRuleDetail, 1.8710 + const bool aCanStoreInRuleTree) 1.8711 +{ 1.8712 + COMPUTE_START_RESET(SVGReset, (), svgReset, parentSVGReset) 1.8713 + 1.8714 + // stop-color: 1.8715 + const nsCSSValue* stopColorValue = aRuleData->ValueForStopColor(); 1.8716 + if (eCSSUnit_Initial == stopColorValue->GetUnit() || 1.8717 + eCSSUnit_Unset == stopColorValue->GetUnit()) { 1.8718 + svgReset->mStopColor = NS_RGB(0, 0, 0); 1.8719 + } else { 1.8720 + SetColor(*stopColorValue, parentSVGReset->mStopColor, 1.8721 + mPresContext, aContext, svgReset->mStopColor, canStoreInRuleTree); 1.8722 + } 1.8723 + 1.8724 + // flood-color: 1.8725 + const nsCSSValue* floodColorValue = aRuleData->ValueForFloodColor(); 1.8726 + if (eCSSUnit_Initial == floodColorValue->GetUnit() || 1.8727 + eCSSUnit_Unset == floodColorValue->GetUnit()) { 1.8728 + svgReset->mFloodColor = NS_RGB(0, 0, 0); 1.8729 + } else { 1.8730 + SetColor(*floodColorValue, parentSVGReset->mFloodColor, 1.8731 + mPresContext, aContext, svgReset->mFloodColor, canStoreInRuleTree); 1.8732 + } 1.8733 + 1.8734 + // lighting-color: 1.8735 + const nsCSSValue* lightingColorValue = aRuleData->ValueForLightingColor(); 1.8736 + if (eCSSUnit_Initial == lightingColorValue->GetUnit() || 1.8737 + eCSSUnit_Unset == lightingColorValue->GetUnit()) { 1.8738 + svgReset->mLightingColor = NS_RGB(255, 255, 255); 1.8739 + } else { 1.8740 + SetColor(*lightingColorValue, parentSVGReset->mLightingColor, 1.8741 + mPresContext, aContext, svgReset->mLightingColor, 1.8742 + canStoreInRuleTree); 1.8743 + } 1.8744 + 1.8745 + // clip-path: url, none, inherit 1.8746 + const nsCSSValue* clipPathValue = aRuleData->ValueForClipPath(); 1.8747 + if (eCSSUnit_URL == clipPathValue->GetUnit()) { 1.8748 + svgReset->mClipPath = clipPathValue->GetURLValue(); 1.8749 + } else if (eCSSUnit_None == clipPathValue->GetUnit() || 1.8750 + eCSSUnit_Initial == clipPathValue->GetUnit() || 1.8751 + eCSSUnit_Unset == clipPathValue->GetUnit()) { 1.8752 + svgReset->mClipPath = nullptr; 1.8753 + } else if (eCSSUnit_Inherit == clipPathValue->GetUnit()) { 1.8754 + canStoreInRuleTree = false; 1.8755 + svgReset->mClipPath = parentSVGReset->mClipPath; 1.8756 + } 1.8757 + 1.8758 + // stop-opacity: 1.8759 + SetFactor(*aRuleData->ValueForStopOpacity(), 1.8760 + svgReset->mStopOpacity, canStoreInRuleTree, 1.8761 + parentSVGReset->mStopOpacity, 1.0f, 1.8762 + SETFCT_OPACITY | SETFCT_UNSET_INITIAL); 1.8763 + 1.8764 + // flood-opacity: 1.8765 + SetFactor(*aRuleData->ValueForFloodOpacity(), 1.8766 + svgReset->mFloodOpacity, canStoreInRuleTree, 1.8767 + parentSVGReset->mFloodOpacity, 1.0f, 1.8768 + SETFCT_OPACITY | SETFCT_UNSET_INITIAL); 1.8769 + 1.8770 + // dominant-baseline: enum, inherit, initial 1.8771 + SetDiscrete(*aRuleData->ValueForDominantBaseline(), 1.8772 + svgReset->mDominantBaseline, 1.8773 + canStoreInRuleTree, 1.8774 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.8775 + parentSVGReset->mDominantBaseline, 1.8776 + NS_STYLE_DOMINANT_BASELINE_AUTO, 0, 0, 0, 0); 1.8777 + 1.8778 + // vector-effect: enum, inherit, initial 1.8779 + SetDiscrete(*aRuleData->ValueForVectorEffect(), 1.8780 + svgReset->mVectorEffect, 1.8781 + canStoreInRuleTree, 1.8782 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.8783 + parentSVGReset->mVectorEffect, 1.8784 + NS_STYLE_VECTOR_EFFECT_NONE, 0, 0, 0, 0); 1.8785 + 1.8786 + // filter: url, none, inherit 1.8787 + const nsCSSValue* filterValue = aRuleData->ValueForFilter(); 1.8788 + switch (filterValue->GetUnit()) { 1.8789 + case eCSSUnit_Null: 1.8790 + break; 1.8791 + case eCSSUnit_None: 1.8792 + case eCSSUnit_Initial: 1.8793 + case eCSSUnit_Unset: 1.8794 + svgReset->mFilters.Clear(); 1.8795 + break; 1.8796 + case eCSSUnit_Inherit: 1.8797 + canStoreInRuleTree = false; 1.8798 + svgReset->mFilters = parentSVGReset->mFilters; 1.8799 + break; 1.8800 + case eCSSUnit_List: 1.8801 + case eCSSUnit_ListDep: { 1.8802 + svgReset->mFilters.Clear(); 1.8803 + const nsCSSValueList* cur = filterValue->GetListValue(); 1.8804 + while (cur) { 1.8805 + nsStyleFilter styleFilter; 1.8806 + if (!SetStyleFilterToCSSValue(&styleFilter, cur->mValue, aContext, 1.8807 + mPresContext, canStoreInRuleTree)) { 1.8808 + svgReset->mFilters.Clear(); 1.8809 + break; 1.8810 + } 1.8811 + NS_ABORT_IF_FALSE(styleFilter.GetType() != NS_STYLE_FILTER_NONE, 1.8812 + "filter should be set"); 1.8813 + svgReset->mFilters.AppendElement(styleFilter); 1.8814 + cur = cur->mNext; 1.8815 + } 1.8816 + break; 1.8817 + } 1.8818 + default: 1.8819 + NS_NOTREACHED("unexpected unit"); 1.8820 + } 1.8821 + 1.8822 + // mask: url, none, inherit 1.8823 + const nsCSSValue* maskValue = aRuleData->ValueForMask(); 1.8824 + if (eCSSUnit_URL == maskValue->GetUnit()) { 1.8825 + svgReset->mMask = maskValue->GetURLValue(); 1.8826 + } else if (eCSSUnit_None == maskValue->GetUnit() || 1.8827 + eCSSUnit_Initial == maskValue->GetUnit() || 1.8828 + eCSSUnit_Unset == maskValue->GetUnit()) { 1.8829 + svgReset->mMask = nullptr; 1.8830 + } else if (eCSSUnit_Inherit == maskValue->GetUnit()) { 1.8831 + canStoreInRuleTree = false; 1.8832 + svgReset->mMask = parentSVGReset->mMask; 1.8833 + } 1.8834 + 1.8835 + // mask-type: enum, inherit, initial 1.8836 + SetDiscrete(*aRuleData->ValueForMaskType(), 1.8837 + svgReset->mMaskType, 1.8838 + canStoreInRuleTree, 1.8839 + SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, 1.8840 + parentSVGReset->mMaskType, 1.8841 + NS_STYLE_MASK_TYPE_LUMINANCE, 0, 0, 0, 0); 1.8842 + 1.8843 + COMPUTE_END_RESET(SVGReset, svgReset) 1.8844 +} 1.8845 + 1.8846 +const void* 1.8847 +nsRuleNode::ComputeVariablesData(void* aStartStruct, 1.8848 + const nsRuleData* aRuleData, 1.8849 + nsStyleContext* aContext, 1.8850 + nsRuleNode* aHighestNode, 1.8851 + const RuleDetail aRuleDetail, 1.8852 + const bool aCanStoreInRuleTree) 1.8853 +{ 1.8854 + COMPUTE_START_INHERITED(Variables, (), variables, parentVariables) 1.8855 + 1.8856 + MOZ_ASSERT(aRuleData->mVariables, 1.8857 + "shouldn't be in ComputeVariablesData if there were no variable " 1.8858 + "declarations specified"); 1.8859 + 1.8860 + CSSVariableResolver resolver(&variables->mVariables); 1.8861 + resolver.Resolve(&parentVariables->mVariables, 1.8862 + aRuleData->mVariables); 1.8863 + canStoreInRuleTree = false; 1.8864 + 1.8865 + COMPUTE_END_INHERITED(Variables, variables) 1.8866 +} 1.8867 + 1.8868 +const void* 1.8869 +nsRuleNode::GetStyleData(nsStyleStructID aSID, 1.8870 + nsStyleContext* aContext, 1.8871 + bool aComputeData) 1.8872 +{ 1.8873 + NS_ASSERTION(IsUsedDirectly(), 1.8874 + "if we ever call this on rule nodes that aren't used " 1.8875 + "directly, we should adjust handling of mDependentBits " 1.8876 + "in some way."); 1.8877 + 1.8878 + const void *data; 1.8879 + data = mStyleData.GetStyleData(aSID); 1.8880 + if (MOZ_LIKELY(data != nullptr)) 1.8881 + return data; // We have a fully specified struct. Just return it. 1.8882 + 1.8883 + if (MOZ_UNLIKELY(!aComputeData)) 1.8884 + return nullptr; 1.8885 + 1.8886 + // Nothing is cached. We'll have to delve further and examine our rules. 1.8887 + data = WalkRuleTree(aSID, aContext); 1.8888 + 1.8889 + NS_ABORT_IF_FALSE(data, "should have aborted on out-of-memory"); 1.8890 + return data; 1.8891 +} 1.8892 + 1.8893 +// See comments above in GetStyleData for an explanation of what the 1.8894 +// code below does. 1.8895 +#define STYLE_STRUCT(name_, checkdata_cb_) \ 1.8896 +const nsStyle##name_* \ 1.8897 +nsRuleNode::GetStyle##name_(nsStyleContext* aContext, bool aComputeData) \ 1.8898 +{ \ 1.8899 + NS_ASSERTION(IsUsedDirectly(), \ 1.8900 + "if we ever call this on rule nodes that aren't used " \ 1.8901 + "directly, we should adjust handling of mDependentBits " \ 1.8902 + "in some way."); \ 1.8903 + \ 1.8904 + const nsStyle##name_ *data; \ 1.8905 + data = mStyleData.GetStyle##name_(); \ 1.8906 + if (MOZ_LIKELY(data != nullptr)) \ 1.8907 + return data; \ 1.8908 + \ 1.8909 + if (MOZ_UNLIKELY(!aComputeData)) \ 1.8910 + return nullptr; \ 1.8911 + \ 1.8912 + data = static_cast<const nsStyle##name_ *> \ 1.8913 + (WalkRuleTree(eStyleStruct_##name_, aContext)); \ 1.8914 + \ 1.8915 + NS_ABORT_IF_FALSE(data, "should have aborted on out-of-memory"); \ 1.8916 + return data; \ 1.8917 +} 1.8918 +#include "nsStyleStructList.h" 1.8919 +#undef STYLE_STRUCT 1.8920 + 1.8921 +void 1.8922 +nsRuleNode::Mark() 1.8923 +{ 1.8924 + for (nsRuleNode *node = this; 1.8925 + node && !(node->mDependentBits & NS_RULE_NODE_GC_MARK); 1.8926 + node = node->mParent) 1.8927 + node->mDependentBits |= NS_RULE_NODE_GC_MARK; 1.8928 +} 1.8929 + 1.8930 +static PLDHashOperator 1.8931 +SweepRuleNodeChildren(PLDHashTable *table, PLDHashEntryHdr *hdr, 1.8932 + uint32_t number, void *arg) 1.8933 +{ 1.8934 + ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(hdr); 1.8935 + if (entry->mRuleNode->Sweep()) 1.8936 + return PL_DHASH_REMOVE; // implies NEXT, unless |ed with STOP 1.8937 + return PL_DHASH_NEXT; 1.8938 +} 1.8939 + 1.8940 +bool 1.8941 +nsRuleNode::Sweep() 1.8942 +{ 1.8943 + // If we're not marked, then we have to delete ourself. 1.8944 + // However, we never allow the root node to GC itself, because nsStyleSet 1.8945 + // wants to hold onto the root node and not worry about re-creating a 1.8946 + // rule walker if the root node is deleted. 1.8947 + if (!(mDependentBits & NS_RULE_NODE_GC_MARK) && 1.8948 + // Skip this only if we're the *current* root and not an old one. 1.8949 + !(IsRoot() && mPresContext->StyleSet()->GetRuleTree() == this)) { 1.8950 + Destroy(); 1.8951 + return true; 1.8952 + } 1.8953 + 1.8954 + // Clear our mark, for the next time around. 1.8955 + mDependentBits &= ~NS_RULE_NODE_GC_MARK; 1.8956 + 1.8957 + // Call sweep on the children, since some may not be marked, and 1.8958 + // remove any deleted children from the child lists. 1.8959 + if (HaveChildren()) { 1.8960 + uint32_t childrenDestroyed; 1.8961 + if (ChildrenAreHashed()) { 1.8962 + PLDHashTable *children = ChildrenHash(); 1.8963 + uint32_t oldChildCount = children->entryCount; 1.8964 + PL_DHashTableEnumerate(children, SweepRuleNodeChildren, nullptr); 1.8965 + childrenDestroyed = children->entryCount - oldChildCount; 1.8966 + } else { 1.8967 + childrenDestroyed = 0; 1.8968 + for (nsRuleNode **children = ChildrenListPtr(); *children; ) { 1.8969 + nsRuleNode *next = (*children)->mNextSibling; 1.8970 + if ((*children)->Sweep()) { 1.8971 + // This rule node was destroyed, so implicitly advance by 1.8972 + // making *children point to the next entry. 1.8973 + *children = next; 1.8974 + ++childrenDestroyed; 1.8975 + } else { 1.8976 + // Advance. 1.8977 + children = &(*children)->mNextSibling; 1.8978 + } 1.8979 + } 1.8980 + } 1.8981 + mRefCnt -= childrenDestroyed; 1.8982 + NS_POSTCONDITION(IsRoot() || mRefCnt > 0, 1.8983 + "We didn't get swept, so we'd better have style contexts " 1.8984 + "pointing to us or to one of our descendants, which means " 1.8985 + "we'd better have a nonzero mRefCnt here!"); 1.8986 + } 1.8987 + return false; 1.8988 +} 1.8989 + 1.8990 +/* static */ bool 1.8991 +nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext, 1.8992 + uint32_t ruleTypeMask, 1.8993 + bool aAuthorColorsAllowed) 1.8994 +{ 1.8995 + uint32_t inheritBits = 0; 1.8996 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) 1.8997 + inheritBits |= NS_STYLE_INHERIT_BIT(Background); 1.8998 + 1.8999 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) 1.9000 + inheritBits |= NS_STYLE_INHERIT_BIT(Border); 1.9001 + 1.9002 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) 1.9003 + inheritBits |= NS_STYLE_INHERIT_BIT(Padding); 1.9004 + 1.9005 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) 1.9006 + inheritBits |= NS_STYLE_INHERIT_BIT(Text); 1.9007 + 1.9008 + // properties in the SIDS, whether or not we care about them 1.9009 + size_t nprops = 0, 1.9010 + backgroundOffset, borderOffset, paddingOffset, textShadowOffset; 1.9011 + 1.9012 + // We put the reset properties the start of the nsCSSValue array.... 1.9013 + 1.9014 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) { 1.9015 + backgroundOffset = nprops; 1.9016 + nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Background); 1.9017 + } 1.9018 + 1.9019 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) { 1.9020 + borderOffset = nprops; 1.9021 + nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Border); 1.9022 + } 1.9023 + 1.9024 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) { 1.9025 + paddingOffset = nprops; 1.9026 + nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Padding); 1.9027 + } 1.9028 + 1.9029 + // ...and the inherited properties at the end of the array. 1.9030 + size_t inheritedOffset = nprops; 1.9031 + 1.9032 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) { 1.9033 + textShadowOffset = nprops; 1.9034 + nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Text); 1.9035 + } 1.9036 + 1.9037 + void* dataStorage = alloca(nprops * sizeof(nsCSSValue)); 1.9038 + AutoCSSValueArray dataArray(dataStorage, nprops); 1.9039 + 1.9040 + /* We're relying on the use of |aStyleContext| not mutating it! */ 1.9041 + nsRuleData ruleData(inheritBits, dataArray.get(), 1.9042 + aStyleContext->PresContext(), aStyleContext); 1.9043 + 1.9044 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) { 1.9045 + ruleData.mValueOffsets[eStyleStruct_Background] = backgroundOffset; 1.9046 + } 1.9047 + 1.9048 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) { 1.9049 + ruleData.mValueOffsets[eStyleStruct_Border] = borderOffset; 1.9050 + } 1.9051 + 1.9052 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) { 1.9053 + ruleData.mValueOffsets[eStyleStruct_Padding] = paddingOffset; 1.9054 + } 1.9055 + 1.9056 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) { 1.9057 + ruleData.mValueOffsets[eStyleStruct_Text] = textShadowOffset; 1.9058 + } 1.9059 + 1.9060 + static const nsCSSProperty backgroundValues[] = { 1.9061 + eCSSProperty_background_color, 1.9062 + eCSSProperty_background_image, 1.9063 + }; 1.9064 + 1.9065 + static const nsCSSProperty borderValues[] = { 1.9066 + eCSSProperty_border_top_color, 1.9067 + eCSSProperty_border_top_style, 1.9068 + eCSSProperty_border_top_width, 1.9069 + eCSSProperty_border_right_color_value, 1.9070 + eCSSProperty_border_right_style_value, 1.9071 + eCSSProperty_border_right_width_value, 1.9072 + eCSSProperty_border_bottom_color, 1.9073 + eCSSProperty_border_bottom_style, 1.9074 + eCSSProperty_border_bottom_width, 1.9075 + eCSSProperty_border_left_color_value, 1.9076 + eCSSProperty_border_left_style_value, 1.9077 + eCSSProperty_border_left_width_value, 1.9078 + eCSSProperty_border_start_color_value, 1.9079 + eCSSProperty_border_start_style_value, 1.9080 + eCSSProperty_border_start_width_value, 1.9081 + eCSSProperty_border_end_color_value, 1.9082 + eCSSProperty_border_end_style_value, 1.9083 + eCSSProperty_border_end_width_value, 1.9084 + eCSSProperty_border_top_left_radius, 1.9085 + eCSSProperty_border_top_right_radius, 1.9086 + eCSSProperty_border_bottom_right_radius, 1.9087 + eCSSProperty_border_bottom_left_radius, 1.9088 + }; 1.9089 + 1.9090 + static const nsCSSProperty paddingValues[] = { 1.9091 + eCSSProperty_padding_top, 1.9092 + eCSSProperty_padding_right_value, 1.9093 + eCSSProperty_padding_bottom, 1.9094 + eCSSProperty_padding_left_value, 1.9095 + eCSSProperty_padding_start_value, 1.9096 + eCSSProperty_padding_end_value, 1.9097 + }; 1.9098 + 1.9099 + static const nsCSSProperty textShadowValues[] = { 1.9100 + eCSSProperty_text_shadow 1.9101 + }; 1.9102 + 1.9103 + // Number of properties we care about 1.9104 + size_t nValues = 0; 1.9105 + 1.9106 + nsCSSValue* values[MOZ_ARRAY_LENGTH(backgroundValues) + 1.9107 + MOZ_ARRAY_LENGTH(borderValues) + 1.9108 + MOZ_ARRAY_LENGTH(paddingValues) + 1.9109 + MOZ_ARRAY_LENGTH(textShadowValues)]; 1.9110 + 1.9111 + nsCSSProperty properties[MOZ_ARRAY_LENGTH(backgroundValues) + 1.9112 + MOZ_ARRAY_LENGTH(borderValues) + 1.9113 + MOZ_ARRAY_LENGTH(paddingValues) + 1.9114 + MOZ_ARRAY_LENGTH(textShadowValues)]; 1.9115 + 1.9116 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) { 1.9117 + for (uint32_t i = 0, i_end = ArrayLength(backgroundValues); 1.9118 + i < i_end; ++i) { 1.9119 + properties[nValues] = backgroundValues[i]; 1.9120 + values[nValues++] = ruleData.ValueFor(backgroundValues[i]); 1.9121 + } 1.9122 + } 1.9123 + 1.9124 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) { 1.9125 + for (uint32_t i = 0, i_end = ArrayLength(borderValues); 1.9126 + i < i_end; ++i) { 1.9127 + properties[nValues] = borderValues[i]; 1.9128 + values[nValues++] = ruleData.ValueFor(borderValues[i]); 1.9129 + } 1.9130 + } 1.9131 + 1.9132 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) { 1.9133 + for (uint32_t i = 0, i_end = ArrayLength(paddingValues); 1.9134 + i < i_end; ++i) { 1.9135 + properties[nValues] = paddingValues[i]; 1.9136 + values[nValues++] = ruleData.ValueFor(paddingValues[i]); 1.9137 + } 1.9138 + } 1.9139 + 1.9140 + if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) { 1.9141 + for (uint32_t i = 0, i_end = ArrayLength(textShadowValues); 1.9142 + i < i_end; ++i) { 1.9143 + properties[nValues] = textShadowValues[i]; 1.9144 + values[nValues++] = ruleData.ValueFor(textShadowValues[i]); 1.9145 + } 1.9146 + } 1.9147 + 1.9148 + nsStyleContext* styleContext = aStyleContext; 1.9149 + 1.9150 + // We need to be careful not to count styles covered up by user-important or 1.9151 + // UA-important declarations. But we do want to catch explicit inherit 1.9152 + // styling in those and check our parent style context to see whether we have 1.9153 + // user styling for those properties. Note that we don't care here about 1.9154 + // inheritance due to lack of a specified value, since all the properties we 1.9155 + // care about are reset properties. 1.9156 + bool haveExplicitUAInherit; 1.9157 + do { 1.9158 + haveExplicitUAInherit = false; 1.9159 + for (nsRuleNode* ruleNode = styleContext->RuleNode(); ruleNode; 1.9160 + ruleNode = ruleNode->GetParent()) { 1.9161 + nsIStyleRule *rule = ruleNode->GetRule(); 1.9162 + if (rule) { 1.9163 + ruleData.mLevel = ruleNode->GetLevel(); 1.9164 + ruleData.mIsImportantRule = ruleNode->IsImportantRule(); 1.9165 + 1.9166 + rule->MapRuleInfoInto(&ruleData); 1.9167 + 1.9168 + if (ruleData.mLevel == nsStyleSet::eAgentSheet || 1.9169 + ruleData.mLevel == nsStyleSet::eUserSheet) { 1.9170 + // This is a rule whose effect we want to ignore, so if any of 1.9171 + // the properties we care about were set, set them to the dummy 1.9172 + // value that they'll never otherwise get. 1.9173 + for (uint32_t i = 0; i < nValues; ++i) { 1.9174 + nsCSSUnit unit = values[i]->GetUnit(); 1.9175 + if (unit != eCSSUnit_Null && 1.9176 + unit != eCSSUnit_Dummy && 1.9177 + unit != eCSSUnit_DummyInherit) { 1.9178 + if (unit == eCSSUnit_Inherit || 1.9179 + (i >= inheritedOffset && unit == eCSSUnit_Unset)) { 1.9180 + haveExplicitUAInherit = true; 1.9181 + values[i]->SetDummyInheritValue(); 1.9182 + } else { 1.9183 + values[i]->SetDummyValue(); 1.9184 + } 1.9185 + } 1.9186 + } 1.9187 + } else { 1.9188 + // If any of the values we care about was set by the above rule, 1.9189 + // we have author style. 1.9190 + for (uint32_t i = 0; i < nValues; ++i) { 1.9191 + if (values[i]->GetUnit() != eCSSUnit_Null && 1.9192 + values[i]->GetUnit() != eCSSUnit_Dummy && // see above 1.9193 + values[i]->GetUnit() != eCSSUnit_DummyInherit) { 1.9194 + // If author colors are not allowed, only claim to have 1.9195 + // author-specified rules if we're looking at a non-color 1.9196 + // property or if we're looking at the background color and it's 1.9197 + // set to transparent. Anything else should get set to a dummy 1.9198 + // value instead. 1.9199 + if (aAuthorColorsAllowed || 1.9200 + !nsCSSProps::PropHasFlags(properties[i], 1.9201 + CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) || 1.9202 + (properties[i] == eCSSProperty_background_color && 1.9203 + !values[i]->IsNonTransparentColor())) { 1.9204 + return true; 1.9205 + } 1.9206 + 1.9207 + values[i]->SetDummyValue(); 1.9208 + } 1.9209 + } 1.9210 + } 1.9211 + } 1.9212 + } 1.9213 + 1.9214 + if (haveExplicitUAInherit) { 1.9215 + // reset all the eCSSUnit_Null values to eCSSUnit_Dummy (since they're 1.9216 + // not styled by the author, or by anyone else), and then reset all the 1.9217 + // eCSSUnit_DummyInherit values to eCSSUnit_Null (so we will be able to 1.9218 + // detect them being styled by the author) and move up to our parent 1.9219 + // style context. 1.9220 + for (uint32_t i = 0; i < nValues; ++i) 1.9221 + if (values[i]->GetUnit() == eCSSUnit_Null) 1.9222 + values[i]->SetDummyValue(); 1.9223 + for (uint32_t i = 0; i < nValues; ++i) 1.9224 + if (values[i]->GetUnit() == eCSSUnit_DummyInherit) 1.9225 + values[i]->Reset(); 1.9226 + styleContext = styleContext->GetParent(); 1.9227 + } 1.9228 + } while (haveExplicitUAInherit && styleContext); 1.9229 + 1.9230 + return false; 1.9231 +} 1.9232 + 1.9233 +/* static */ 1.9234 +bool 1.9235 +nsRuleNode::ComputeColor(const nsCSSValue& aValue, nsPresContext* aPresContext, 1.9236 + nsStyleContext* aStyleContext, nscolor& aResult) 1.9237 +{ 1.9238 + MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Inherit, 1.9239 + "aValue shouldn't have eCSSUnit_Inherit"); 1.9240 + MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Initial, 1.9241 + "aValue shouldn't have eCSSUnit_Initial"); 1.9242 + MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Unset, 1.9243 + "aValue shouldn't have eCSSUnit_Unset"); 1.9244 + 1.9245 + bool canStoreInRuleTree; 1.9246 + bool ok = SetColor(aValue, NS_RGB(0, 0, 0), aPresContext, aStyleContext, 1.9247 + aResult, canStoreInRuleTree); 1.9248 + MOZ_ASSERT(ok || !(aPresContext && aStyleContext)); 1.9249 + return ok; 1.9250 +}