1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/doc/adding-style-props.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,479 @@ 1.4 +<!-- This Source Code Form is subject to the terms of the Mozilla Public 1.5 + - License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 1.7 + 1.8 +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head> 1.9 + <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1"> 1.10 + <meta name="author" content="Marc Attinasi"><title>Adding a new style property - layout cookbook</title></head> 1.11 + 1.12 +<body> 1.13 +<h1>Adding a new style property</h1> 1.14 +<blockquote> 1.15 + <h4>Document history:</h4> 1.16 + <ul> 1.17 + <li>03/21/2002: Marc Attinasi (attinasi@netscape.com) created document 1.18 +/ implementing -moz-force-broken-image-icon for bug <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=58646"> 1.19 +58646</a></li> 1.20 + <li> 1.21 + 6/18/2002: David Baron (dbaron@dbaron.org): corrected support 1.22 + for 'inherit' and 'initial' (didn't test with code, though), 1.23 + and explained what the final boolean in CheckPropertyData is for. 1.24 + </li> 1.25 + <li> 1.26 + 11/09/2002: Christopher Aillon (caillon@returnzero.com): updated 1.27 + nsCSSPropList.h macro description and added information about 1.28 + nsIDOMCSS2Properties.idl. 1.29 + </li> 1.30 + </ul> 1.31 + <p> 1.32 + <b>NOTE</b>: This document is still missing a few pieces. I need to 1.33 + add information on adding to <code>nsComputedDOMStyle</code>. 1.34 + </p> 1.35 + </blockquote> 1.36 + <h2>Overview</h2> 1.37 +When a new style property is needed there are many places in the code that 1.38 +need to be updated. This document outlines the procedure used to add a new 1.39 +property, in this case the property is a proprietary one called '-moz-force-broken-image-icons' 1.40 +and is used as a way for a stylesheet to force broken image icons to be displayed. 1.41 +This is all being done in the context of <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=58646"> 1.42 +bug 58646</a>. 1.43 + 1.44 + <h2>Analysis</h2> 1.45 +<p>Up front you have to decide some things about the new property:</p> 1.46 + 1.47 +<p><b>Questions:</b></p> 1.48 + <ol> 1.49 + <li>Is the property proprietary or specified by the CSS standard?</li> 1.50 + <li>Is the property inherited?</li> 1.51 + <li>What types of values can the property have?</li> 1.52 + <li>Does it logically fit with other existing properties?</li> 1.53 + <li>What is the impact to the layout of a page if that property changes?</li> 1.54 + <li>What do you want to name it?</li> 1.55 + </ol> 1.56 +<p><b>Answers:</b></p> 1.57 + <ol> 1.58 + <li>In our specific case, we want a property that is used internally, 1.59 +so it is a proprietary property.</li> 1.60 + <li>The property is to be used for images, which are leaf elements, so 1.61 +there is no need to inherit it.</li> 1.62 + <li>The property is used simply to force a broken image to be represented 1.63 +by an icon, so it only supports the values '0' and '1' as numerics. </li> 1.64 + <li>It is hard to see how this property fits logically in with other 1.65 +properties, but if we stretch our imaginations we could say that it is a 1.66 +sort of UI property.</li> 1.67 + <li>If this property changes, the image frame has to be recreated. This 1.68 +is because the decision about whether to display the icon or not will impact 1.69 +the decision to replace the image frame with an inline text frame for the 1.70 +ALT text, so if the ALT text inline is already made, there is no image frame 1.71 +left around to reflow or otherwise modify.</li> 1.72 + <li>Finally, the name will be '-moz-force-broken-image-icons' - that 1.73 +should be pretty self-describing (by convention we start proprietary property 1.74 +names with '-moz-').</li> 1.75 + </ol> 1.76 + <h2>Implementation</h2> 1.77 + 1.78 +<p>There are several places that need to be educated about a new style property. 1.79 +They are: 1.80 +</p> 1.81 + <ul> 1.82 + <li><a href="#CSSPropList">CSS Property Names and Hint Tables</a>: the new 1.83 +property name must be made formally know to the system</li> 1.84 + <li><a href="#CSSDeclaration">CSS Declaration</a>: the declaration must be 1.85 +able to hold the property and its value(s)</li> 1.86 + <li><a href="#Parser">CSS Parser</a>: the parser must be able to parse the 1.87 +property name, validate the values, and provide a declaration for the property 1.88 +and value</li> 1.89 + <li><a href="#StyleContext">Style Context</a>: the StyleContext must be able 1.90 +to hold the resolved value of the property, and provide a means to retrieve the 1.91 +property value. Additionally, the StyleContext has to know what kind of impact a 1.92 +change to this property causes.</li> 1.93 + <li><a href="#RuleNode">Rule Nodes</a>: the RuleNodes need to know how the 1.94 +property is inherited and how it is shared by other elements.</li> 1.95 + <li><a href="#DOM">DOM</a>: Your style should be accessible from the DOM so 1.96 +users may dynamically set/get its property value.</li> 1.97 + <li><a href="#Layout">Layout</a>: layout has to know what to do with the 1.98 +property, in other words, the meaning of the property.</li> 1.99 + </ul> 1.100 + <h3><a name="CSSPropList">CSS Property Name / Constants / Hints</a></h3> 1.101 + 1.102 +<p> 1.103 +First, add the new name to the property list in <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/public/nsCSSPropList.h"> 1.104 +nsCSSPropList.h</a> 1.105 + Insert the property in the list alphabetically, using the existing 1.106 +property names as a template. The format of the entry you will create is: 1.107 +</p> 1.108 + <pre>CSS_PROP(-moz-force-broken-image-icons, force_broken_image_icons, MozForceBrokenImageIcons, NS_STYLE_HINT_FRAMECHANGE) // bug 58646</pre> 1.109 + 1.110 +<p>The first value is the formal property name, in other words the property 1.111 +name as it is seen by the CSS parser.<br> 1.112 +The second value is the name of the property as it will appear internally.<br> 1.113 +The third value is the name of the DOM property used to access your style.<br> 1.114 +The last value indicates what must change when the value of the property 1.115 +changes. It should be an 1.116 +<a href="http://lxr.mozilla.org/seamonkey/source/content/shared/public/nsChangeHint.h">nsChangeHint</a>.</p> 1.117 + 1.118 +<p>If you need to introduce new constants for the values of the property, they 1.119 +must be added to <a href="http://lxr.mozilla.org/seamonkey/source/layout/base/public/nsStyleConsts.h"> 1.120 +nsStyleConsts.h</a> 1.121 + and to the appropriate keyword tables in <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/src/nsCSSProps.cpp"> 1.122 +nsCSSProps.cpp</a> 1.123 + (note: this cookbook does not do this since the new property does not require 1.124 +any new keywords for the property values). 1.125 + <h3><a name="CSSDeclaration">CSS Declaration</a></h3> 1.126 +Changes will need to be made to the structs and classes defined in <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSDeclaration.h"> 1.127 +nsCSSDeclaration.h </a> 1.128 +and <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSDeclaration.cpp"> 1.129 +nsCSSDeclaration.cpp</a> 1.130 + <br> 1.131 + <br> 1.132 +First, find the declaration of the struct that will hold the new property 1.133 +value (in the header file). For this example it is the struct <b>nsCSSUserInterface</b> 1.134 +. Modify the struct declaration to include a new data member for the new 1.135 +property, of the type CSSValue. Next, open the implementation file (the cpp) 1.136 +and modify the struct's constructors. <br> 1.137 + <br> 1.138 +Next, the <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSDeclaration.cpp#1410"> 1.139 +AppendValue</a> 1.140 + method must be updated to support your new property. The CSSParser will 1.141 +call this to build up a declaration. Find the portion of that method that 1.142 +deals with the other properties in the struct that you are adding your property 1.143 +to (or create a new section if you are creating a new style struct). For 1.144 +this example we will find the 'UserInterface' section and add our new property 1.145 + <a href="#AppendValueCase">there</a> 1.146 +.<br> 1.147 + <pre> // nsCSSUserInterface 1.148 + case eCSSProperty_user_input: 1.149 + case eCSSProperty_user_modify: 1.150 + case eCSSProperty_user_select: 1.151 + case eCSSProperty_key_equivalent: 1.152 + case eCSSProperty_user_focus: 1.153 + case eCSSProperty_resizer: 1.154 + case eCSSProperty_cursor: 1.155 + case eCSSProperty_force_broken_image_icons: { 1.156 + CSS_ENSURE(UserInterface) { 1.157 + switch (aProperty) { 1.158 + case eCSSProperty_user_input: theUserInterface->mUserInput = aValue; break; 1.159 + case eCSSProperty_user_modify: theUserInterface->mUserModify = aValue; break; 1.160 + case eCSSProperty_user_select: theUserInterface->mUserSelect = aValue; break; 1.161 + case eCSSProperty_key_equivalent: 1.162 + CSS_ENSURE_DATA(theUserInterface->mKeyEquivalent, nsCSSValueList) { 1.163 + theUserInterface->mKeyEquivalent->mValue = aValue; 1.164 + CSS_IF_DELETE(theUserInterface->mKeyEquivalent->mNext); 1.165 + } 1.166 + break; 1.167 + case eCSSProperty_user_focus: theUserInterface->mUserFocus = aValue; break; 1.168 + case eCSSProperty_resizer: theUserInterface->mResizer = aValue; break; 1.169 + case eCSSProperty_cursor: 1.170 + CSS_ENSURE_DATA(theUserInterface->mCursor, nsCSSValueList) { 1.171 + theUserInterface->mCursor->mValue = aValue; 1.172 + CSS_IF_DELETE(theUserInterface->mCursor->mNext); 1.173 + } 1.174 + break; 1.175 +<b> <a name="AppendValueCase"></a>case eCSSProperty_force_broken_image_icons: theUserInterface->mForceBrokenImageIcon = aValue; break; 1.176 +</b> 1.177 + CSS_BOGUS_DEFAULT; // make compiler happy 1.178 + } 1.179 + } 1.180 + break; 1.181 + } 1.182 + 1.183 +</pre> 1.184 +The GetValue method must be similarly <a href="#GetValueCase">modified</a> 1.185 +:<br> 1.186 + <pre> // nsCSSUserInterface 1.187 + case eCSSProperty_user_input: 1.188 + case eCSSProperty_user_modify: 1.189 + case eCSSProperty_user_select: 1.190 + case eCSSProperty_key_equivalent: 1.191 + case eCSSProperty_user_focus: 1.192 + case eCSSProperty_resizer: 1.193 + case eCSSProperty_cursor: 1.194 + case eCSSProperty_force_broken_image_icons: { 1.195 + CSS_VARONSTACK_GET(UserInterface); 1.196 + if (nullptr != theUserInterface) { 1.197 + switch (aProperty) { 1.198 + case eCSSProperty_user_input: aValue = theUserInterface->mUserInput; break; 1.199 + case eCSSProperty_user_modify: aValue = theUserInterface->mUserModify; break; 1.200 + case eCSSProperty_user_select: aValue = theUserInterface->mUserSelect; break; 1.201 + case eCSSProperty_key_equivalent: 1.202 + if (nullptr != theUserInterface->mKeyEquivalent) { 1.203 + aValue = theUserInterface->mKeyEquivalent->mValue; 1.204 + } 1.205 + break; 1.206 + case eCSSProperty_user_focus: aValue = theUserInterface->mUserFocus; break; 1.207 + case eCSSProperty_resizer: aValue = theUserInterface->mResizer; break; 1.208 + case eCSSProperty_cursor: 1.209 + if (nullptr != theUserInterface->mCursor) { 1.210 + aValue = theUserInterface->mCursor->mValue; 1.211 + } 1.212 + break; 1.213 +<b> <a name="GetValueCase"></a>case eCSSProperty_force_broken_image_icons: aValue = theUserInterface->mForceBrokenImageIcons; break; 1.214 +</b> 1.215 + CSS_BOGUS_DEFAULT; // make compiler happy 1.216 + } 1.217 + } 1.218 + else { 1.219 + aValue.Reset(); 1.220 + } 1.221 + break; 1.222 + } 1.223 + 1.224 +</pre> 1.225 +Finally <a href="#ListCase">modify </a> 1.226 +the 'List' method to output the property value.<br> 1.227 + <pre>void nsCSSUserInterface::List(FILE* out, int32_t aIndent) const 1.228 +{ 1.229 + for (int32_t index = aIndent; --index >= 0; ) fputs(" ", out); 1.230 + 1.231 + nsAutoString buffer; 1.232 + 1.233 + mUserInput.AppendToString(buffer, eCSSProperty_user_input); 1.234 + mUserModify.AppendToString(buffer, eCSSProperty_user_modify); 1.235 + mUserSelect.AppendToString(buffer, eCSSProperty_user_select); 1.236 + nsCSSValueList* keyEquiv = mKeyEquivalent; 1.237 + while (nullptr != keyEquiv) { 1.238 + keyEquiv->mValue.AppendToString(buffer, eCSSProperty_key_equivalent); 1.239 + keyEquiv= keyEquiv->mNext; 1.240 + } 1.241 + mUserFocus.AppendToString(buffer, eCSSProperty_user_focus); 1.242 + mResizer.AppendToString(buffer, eCSSProperty_resizer); 1.243 + 1.244 + nsCSSValueList* cursor = mCursor; 1.245 + while (nullptr != cursor) { 1.246 + cursor->mValue.AppendToString(buffer, eCSSProperty_cursor); 1.247 + cursor = cursor->mNext; 1.248 + } 1.249 + 1.250 + <b> <a name="ListCase"></a>mForceBrokenImageIcon.AppendToString(buffer,eCSSProperty_force_broken_image_icons);</b> 1.251 + 1.252 + fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out); 1.253 +} 1.254 + 1.255 +</pre> 1.256 + 1.257 + <h3><a name="Parser">CSS Parser</a></h3> 1.258 +Next, the CSSParser must be educated about this new property so that it can 1.259 +read in the formal declarations and build up the internal declarations that 1.260 +will be used to build the rules. If you are adding a simple property that 1.261 +takes a single value, you simply add your new property to the ParseSingleProperty 1.262 +method. If a more complex parsing is required you will have to write a new 1.263 +method to handle it, modeling it off of one of the existing parsing helper 1.264 +methods (see <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSParser.cpp#4151"> 1.265 +ParseBackground</a> 1.266 +, for and example). We are just adding a simple single-value property here.<br> 1.267 + <br> 1.268 +Open nsCSSParser.cpp and look for the method <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSParser.cpp#3580"> 1.269 +ParseSingleProperty</a> 1.270 +. This method is responsible for calling the relevant helper routine to parse 1.271 +the value(s). Find an existing property that is similar to the property you 1.272 +are adding. For our example we are adding a property that takes a numeric 1.273 +value so we will model it after the 'height' property and call ParsePositiveVariant. 1.274 +Add a new case for the new property and call the appropriate parser-helper 1.275 +and make a call to ParseVariant passing the <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSParser.cpp#2754"> 1.276 +variant flag</a> 1.277 + that makes sense for your property. In our case<br> 1.278 + <br> 1.279 + <pre> case eCSSProperty_force_broken_image_icons:</pre> 1.280 + <pre> return ParsePositiveVariant(aErrorCode, aValue, VARIANT_INTEGER, nullptr);</pre> 1.281 +This will parse the value as a positive integer value, which is what we want.<br> 1.282 + <br> 1.283 + <h3><a name="StyleContext">Style Context</a></h3> 1.284 +Having implemented support for the new property in the CSS Parser and CSS 1.285 +Declaration classes in the content module, it is now time to provide support 1.286 +for the new property in layout. The Style Context must be given a new data 1.287 +member corresponding to the declaration's new data member, so the computed 1.288 +value can be held for the layout objects to use.<br> 1.289 + <br> 1.290 +First look into <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/public/nsStyleStruct.h"> 1.291 +nsStyleStruct.h</a> 1.292 + to see the existing style strucs. Find the one that you want to store the 1.293 +data on. In this example, we want to put it on the nsStyleUserInterface struct, 1.294 +however there is also a class nsStyleUIReset that holds the non-inherited 1.295 +values, so we will use that one (remember, our property is not inherited). 1.296 +Add a <a href="#StyleContextMember">data member</a> 1.297 + to hold the value: 1.298 + <pre>struct nsStyleUIReset { 1.299 + nsStyleUIReset(void); 1.300 + nsStyleUIReset(const nsStyleUIReset& aOther); 1.301 + ~nsStyleUIReset(void); 1.302 + 1.303 + NS_DEFINE_STATIC_STYLESTRUCTID_ACCESSOR(eStyleStruct_UIReset) 1.304 + 1.305 + void* operator new(size_t sz, nsPresContext* aContext) { 1.306 + return aContext->AllocateFromShell(sz); 1.307 + } 1.308 + void Destroy(nsPresContext* aContext) { 1.309 + this->~nsStyleUIReset(); 1.310 + aContext->FreeToShell(sizeof(nsStyleUIReset), this); 1.311 + }; 1.312 + 1.313 + int32_t CalcDifference(const nsStyleUIReset& aOther) const; 1.314 + 1.315 + uint8_t mUserSelect; // [reset] (selection-style) 1.316 + PRUnichar mKeyEquivalent; // [reset] XXX what type should this be? 1.317 + uint8_t mResizer; // [reset] 1.318 + <b><a name="StyleContextMember"></a>uint8_t mForceBrokenImageIcon; // [reset] (0 if not forcing, otherwise forcing)</b> 1.319 +}; 1.320 +</pre> 1.321 +In the implementation file <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/src/nsStyleStruct.cpp"> 1.322 +nsStyleContext.cpp </a> 1.323 +add the new data member to the constructors of the style struct and the CalcDifference 1.324 +method, which must return the correct style-change hint when a change to 1.325 +your new property is detected. The constructor changes are obvious, but here 1.326 +is the CalcDifference change for our example:<br> 1.327 + <pre>int32_t nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const 1.328 +{ 1.329 + <b> if (mForceBrokenImageIcon == aOther.mForceBrokenImageIcon) {</b> 1.330 + if (mResizer == aOther.mResizer) { 1.331 + if (mUserSelect == aOther.mUserSelect) { 1.332 + if (mKeyEquivalent == aOther.mKeyEquivalent) { 1.333 + return NS_STYLE_HINT_NONE; 1.334 + } 1.335 + return NS_STYLE_HINT_CONTENT; 1.336 + } 1.337 + return NS_STYLE_HINT_VISUAL; 1.338 + } 1.339 + return NS_STYLE_HINT_VISUAL; 1.340 + } 1.341 + <b>return NS_STYLE_HINT_FRAMECHANGE; 1.342 +</b>} 1.343 +</pre> 1.344 + <h3>CSSStyleRule</h3> 1.345 +The nsCSSStyleRule must be updated to manage mapping the declaration to the 1.346 +style struct. In the file <a href="http://lxr.mozilla.org/seamonkey/source/content/html/style/src/nsCSSStyleRule.cpp"> 1.347 +nsCSSStyleRule.cpp</a> 1.348 +, locate the Declaration mapping function corresponding to the style struct 1.349 +you have added your property to. For example, we <a href="http://bugzilla.mozilla.org/MapUIForDeclChange"> 1.350 +update </a> 1.351 +MapUIForDeclaration:<br> 1.352 + <pre>static nsresult 1.353 +MapUIForDeclaration(nsCSSDeclaration* aDecl, const nsStyleStructID& aID, nsCSSUserInterface& aUI) 1.354 +{ 1.355 + if (!aDecl) 1.356 + return NS_OK; // The rule must have a declaration. 1.357 + 1.358 + nsCSSUserInterface* ourUI = (nsCSSUserInterface*)aDecl->GetData(kCSSUserInterfaceSID); 1.359 + if (!ourUI) 1.360 + return NS_OK; // We don't have any rules for UI. 1.361 + 1.362 + if (aID == eStyleStruct_UserInterface) { 1.363 + if (aUI.mUserFocus.GetUnit() == eCSSUnit_Null && ourUI->mUserFocus.GetUnit() != eCSSUnit_Null) 1.364 + aUI.mUserFocus = ourUI->mUserFocus; 1.365 + 1.366 + if (aUI.mUserInput.GetUnit() == eCSSUnit_Null && ourUI->mUserInput.GetUnit() != eCSSUnit_Null) 1.367 + aUI.mUserInput = ourUI->mUserInput; 1.368 + 1.369 + if (aUI.mUserModify.GetUnit() == eCSSUnit_Null && ourUI->mUserModify.GetUnit() != eCSSUnit_Null) 1.370 + aUI.mUserModify = ourUI->mUserModify; 1.371 + 1.372 + if (!aUI.mCursor && ourUI->mCursor) 1.373 + aUI.mCursor = ourUI->mCursor; 1.374 + 1.375 + 1.376 + } 1.377 + else if (aID == eStyleStruct_UIReset) { 1.378 + if (aUI.mUserSelect.GetUnit() == eCSSUnit_Null && ourUI->mUserSelect.GetUnit() != eCSSUnit_Null) 1.379 + aUI.mUserSelect = ourUI->mUserSelect; 1.380 + 1.381 + if (!aUI.mKeyEquivalent && ourUI->mKeyEquivalent) 1.382 + aUI.mKeyEquivalent = ourUI->mKeyEquivalent; 1.383 + 1.384 + if (aUI.mResizer.GetUnit() == eCSSUnit_Null && ourUI->mResizer.GetUnit() != eCSSUnit_Null) 1.385 + aUI.mResizer = ourUI->mResizer; 1.386 + <b> 1.387 + <a name="MapUIForDeclChange"></a>if (aUI.mForceBrokenImageIcon.GetUnit() == eCSSUnit_Null && ourUI->mForceBrokenImageIcon.GetUnit() == eCSSUnit_Integer) 1.388 + aUI.mForceBrokenImageIcon = ourUI->mForceBrokenImageIcon;</b> 1.389 + } 1.390 + 1.391 + return NS_OK; 1.392 + 1.393 +} 1.394 +</pre> 1.395 + <h3><a name="RuleNode">Rule Node</a></h3> 1.396 +Now we have to update the RuleNode code to know about the new property. First, 1.397 +locate the PropertyCheckData array for the data that you added the new property 1.398 +to. For this example, we add the following:<br> 1.399 + <pre>static const PropertyCheckData UIResetCheckProperties[] = { 1.400 + CHECKDATA_PROP(nsCSSUserInterface, mUserSelect, CHECKDATA_VALUE, PR_FALSE), 1.401 + CHECKDATA_PROP(nsCSSUserInterface, mResizer, CHECKDATA_VALUE, PR_FALSE), 1.402 + CHECKDATA_PROP(nsCSSUserInterface, mKeyEquivalent, CHECKDATA_VALUELIST, PR_FALSE) 1.403 + <b>CHECKDATA_PROP(nsCSSUserInterface, mForceBrokenImageIcon, CHECKDATA_VALUE, PR_FALSE)</b> 1.404 +}; 1.405 +</pre> 1.406 +The first two arguments correspond to the structure and data member from 1.407 +the CSSDeclaration, the third is the data type, the fourth indicates 1.408 +whether it is a coord value that uses an explicit inherit value on the 1.409 +style data struct that must be computed by layout.<br> 1.410 + <br> 1.411 +Next, we have to make sure the ComputeXXX method for the structure the property 1.412 +was added to is updated to mange the new value. In this example we need to 1.413 +modify the nsRuleNode::ComputeUIResetData method to handle the CSS Declaration 1.414 +to the style struct:<br> 1.415 + <pre> ... 1.416 + // resizer: auto, none, enum, inherit 1.417 + if (eCSSUnit_Enumerated == uiData.mResizer.GetUnit()) { 1.418 + ui->mResizer = uiData.mResizer.GetIntValue(); 1.419 + } 1.420 + else if (eCSSUnit_Auto == uiData.mResizer.GetUnit()) { 1.421 + ui->mResizer = NS_STYLE_RESIZER_AUTO; 1.422 + } 1.423 + else if (eCSSUnit_None == uiData.mResizer.GetUnit()) { 1.424 + ui->mResizer = NS_STYLE_RESIZER_NONE; 1.425 + } 1.426 + else if (eCSSUnit_Inherit == uiData.mResizer.GetUnit()) { 1.427 + inherited = PR_TRUE; 1.428 + ui->mResizer = parentUI->mResizer; 1.429 + } 1.430 + 1.431 + <b>// force-broken-image-icons: integer, inherit, initial 1.432 + if (eCSSUnit_Integer == uiData.mForceBrokenImageIcons.GetUnit()) { 1.433 + ui->mForceBrokenImageIcons = uiData.mForceBrokenImageIcons.GetIntValue(); 1.434 + } else if (eCSSUnit_Inherit == uiData.mForceBrokenImageIcons.GetUnit()) { 1.435 + inherited = PR_TRUE; 1.436 + ui->mForceBrokenImageIcons = parentUI->mForceBrokenImageIcons; 1.437 + } else if (eCSSUnit_Initial == uiData.mForceBrokenImageIcons.GetUnit()) { 1.438 + ui->mForceBrokenImageIcons = 0; 1.439 + }</b> 1.440 + 1.441 + if (inherited) 1.442 + // We inherited, and therefore can't be cached in the rule node. We have to be put right on the 1.443 + // style context. 1.444 + aContext->SetStyle(eStyleStruct_UIReset, *ui); 1.445 + else { 1.446 + // We were fully specified and can therefore be cached right on the rule node. 1.447 + if (!aHighestNode->mStyleData.mResetData) 1.448 + aHighestNode->mStyleData.mResetData = new (mPresContext) nsResetStyleData; 1.449 + aHighestNode->mStyleData.mResetData->mUIData = ui; 1.450 + // Propagate the bit down. 1.451 + PropagateDependentBit(NS_STYLE_INHERIT_UI_RESET, aHighestNode); 1.452 + } 1.453 + ... 1.454 +</pre> 1.455 + <h3><a name="DOM">DOM</a></h3> 1.456 +Users in scripts, or anywhere outside of layout/ or content/ may need to access 1.457 +the new property. This is done using the CSS OM, specifically 1.458 +<code>nsIDOMCSSStyleDeclaration</code> and <code>CSS2Properties</code>. 1.459 +By the magic of C++ pre-processing, the 1.460 +CSS2Properties bits will be implemented automatically when you 1.461 +<a href="#CSSPropList">add your property</a> to <a href="http://lxr.mozilla.org/seamonkey/source/content/shared/public/nsCSSPropList.h"> 1.462 +nsCSSPropList.h</a>. 1.463 + <h3><a name="Layout">Layout</a></h3> 1.464 +OK, finally the style system is supporting the new property. It is time to 1.465 +actually make use of it now.<br> 1.466 + <br> 1.467 +In layout, retrieve the styleStruct that has the new property from the frame's 1.468 +style context. Access the new property and get its value. It is that simple. 1.469 +For this example, it looks like this, in nsImageFrame:<br> 1.470 + <pre> PRBool forceIcon = PR_FALSE; 1.471 + 1.472 + if (StyleUIReset()->mForceBrokenImageIcon) { 1.473 + forceIcon = PR_TRUE; 1.474 + } 1.475 + 1.476 +</pre> 1.477 +Create some testcases with style rules that use the new property, make sure 1.478 +it is being parsed correctly. Test it in an external stylesheet and in inline 1.479 +style. Test that it is inherited correctly, or not inherited as appropriate 1.480 +to your property. Update this document with any further details, or correcting 1.481 +any errors.<br> 1.482 + </body></html>