Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / style / nsStyleContext.cpp
blob508e4cf9d329639d88ab5c78df3da2cde5aed539
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * David Hyatt <hyatt@netscape.com>
24 * Pierre Phaneuf <pp@ludusdesign.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 /* the interface (to internal code) for retrieving computed style data */
42 #include "nsStyleConsts.h"
43 #include "nsString.h"
44 #include "nsPresContext.h"
45 #include "nsIStyleRule.h"
46 #include "nsCRT.h"
48 #include "nsCOMPtr.h"
49 #include "nsStyleSet.h"
50 #include "nsIPresShell.h"
51 #include "prenv.h"
53 #include "nsRuleNode.h"
54 #include "nsStyleContext.h"
55 #include "imgIRequest.h"
57 #include "nsPrintfCString.h"
59 #ifdef DEBUG
60 // #define NOISY_DEBUG
61 #endif
63 //----------------------------------------------------------------------
66 nsStyleContext::nsStyleContext(nsStyleContext* aParent,
67 nsIAtom* aPseudoTag,
68 nsRuleNode* aRuleNode,
69 nsPresContext* aPresContext)
70 : mParent(aParent),
71 mChild(nsnull),
72 mEmptyChild(nsnull),
73 mPseudoTag(aPseudoTag),
74 mRuleNode(aRuleNode),
75 mBits(0),
76 mRefCnt(0)
78 mNextSibling = this;
79 mPrevSibling = this;
80 if (mParent) {
81 mParent->AddRef();
82 mParent->AddChild(this);
85 ApplyStyleFixups(aPresContext);
87 #define eStyleStruct_LastItem (nsStyleStructID_Length - 1)
88 NS_ASSERTION(NS_STYLE_INHERIT_MASK & NS_STYLE_INHERIT_BIT(LastItem),
89 "NS_STYLE_INHERIT_MASK must be bigger, and other bits shifted");
90 #undef eStyleStruct_LastItem
93 nsStyleContext::~nsStyleContext()
95 NS_ASSERTION((nsnull == mChild) && (nsnull == mEmptyChild), "destructing context with children");
97 nsPresContext *presContext = mRuleNode->GetPresContext();
99 presContext->PresShell()->StyleSet()->
100 NotifyStyleContextDestroyed(presContext, this);
102 if (mParent) {
103 mParent->RemoveChild(this);
104 mParent->Release();
107 // Free up our data structs.
108 if (mCachedStyleData.mResetData || mCachedStyleData.mInheritedData) {
109 mCachedStyleData.Destroy(mBits, presContext);
113 void nsStyleContext::AddChild(nsStyleContext* aChild)
115 NS_ASSERTION(aChild->mPrevSibling == aChild &&
116 aChild->mNextSibling == aChild,
117 "child already in a child list");
119 nsStyleContext **list = aChild->mRuleNode->IsRoot() ? &mEmptyChild : &mChild;
121 // Insert at the beginning of the list. See also FindChildWithRules.
122 if (*list) {
123 // Link into existing elements, if there are any.
124 aChild->mNextSibling = (*list);
125 aChild->mPrevSibling = (*list)->mPrevSibling;
126 (*list)->mPrevSibling->mNextSibling = aChild;
127 (*list)->mPrevSibling = aChild;
129 (*list) = aChild;
132 void nsStyleContext::RemoveChild(nsStyleContext* aChild)
134 NS_PRECONDITION(nsnull != aChild && this == aChild->mParent, "bad argument");
136 nsStyleContext **list = aChild->mRuleNode->IsRoot() ? &mEmptyChild : &mChild;
138 if (aChild->mPrevSibling != aChild) { // has siblings
139 if ((*list) == aChild) {
140 (*list) = (*list)->mNextSibling;
143 else {
144 NS_ASSERTION((*list) == aChild, "bad sibling pointers");
145 (*list) = nsnull;
148 aChild->mPrevSibling->mNextSibling = aChild->mNextSibling;
149 aChild->mNextSibling->mPrevSibling = aChild->mPrevSibling;
150 aChild->mNextSibling = aChild;
151 aChild->mPrevSibling = aChild;
154 already_AddRefed<nsStyleContext>
155 nsStyleContext::FindChildWithRules(const nsIAtom* aPseudoTag,
156 nsRuleNode* aRuleNode)
158 PRUint32 threshold = 10; // The # of siblings we're willing to examine
159 // before just giving this whole thing up.
161 nsStyleContext* result = nsnull;
162 nsStyleContext *list = aRuleNode->IsRoot() ? mEmptyChild : mChild;
164 if (list) {
165 nsStyleContext *child = list;
166 do {
167 if (child->mRuleNode == aRuleNode && child->mPseudoTag == aPseudoTag) {
168 result = child;
169 break;
171 child = child->mNextSibling;
172 threshold--;
173 if (threshold == 0)
174 break;
175 } while (child != list);
178 if (result) {
179 if (result != list) {
180 // Move result to the front of the list.
181 RemoveChild(result);
182 AddChild(result);
185 // Add reference for the caller.
186 result->AddRef();
189 return result;
193 PRBool nsStyleContext::Equals(const nsStyleContext* aOther) const
195 PRBool result = PR_TRUE;
196 const nsStyleContext* other = (nsStyleContext*)aOther;
198 if (other != this) {
199 if (mParent != other->mParent) {
200 result = PR_FALSE;
202 else if (mBits != other->mBits) {
203 result = PR_FALSE;
205 else if (mPseudoTag != other->mPseudoTag) {
206 result = PR_FALSE;
208 else if (mRuleNode != other->mRuleNode) {
209 result = PR_FALSE;
212 return result;
215 //=========================================================================================================
217 const void* nsStyleContext::GetStyleData(nsStyleStructID aSID)
219 const void* cachedData = mCachedStyleData.GetStyleData(aSID);
220 if (cachedData)
221 return cachedData; // We have computed data stored on this node in the context tree.
222 return mRuleNode->GetStyleData(aSID, this, PR_TRUE); // Our rule node will take care of it for us.
225 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
226 const nsStyle##name_ * nsStyleContext::GetStyle##name_ () \
228 const nsStyle##name_ * cachedData = mCachedStyleData.GetStyle##name_(); \
229 if (cachedData) \
230 return cachedData; /* We have computed data stored on this node */ \
231 /* in the context tree. */ \
232 /* Else our rule node will take care of it for us. */ \
233 return mRuleNode->GetStyle##name_(this, PR_TRUE); \
235 #include "nsStyleStructList.h"
236 #undef STYLE_STRUCT
238 const void* nsStyleContext::PeekStyleData(nsStyleStructID aSID)
240 const void* cachedData = mCachedStyleData.GetStyleData(aSID);
241 if (cachedData)
242 return cachedData; // We have computed data stored on this node in the context tree.
243 return mRuleNode->GetStyleData(aSID, this, PR_FALSE); // Our rule node will take care of it for us.
246 // This is an evil evil function, since it forces you to alloc your own separate copy of
247 // style data! Do not use this function unless you absolutely have to! You should avoid
248 // this at all costs! -dwh
249 void*
250 nsStyleContext::GetUniqueStyleData(const nsStyleStructID& aSID)
252 // If we already own the struct and no kids could depend on it, then
253 // just return it. (We leak in this case if there are kids -- and this
254 // function really shouldn't be called for style contexts that could
255 // have kids depending on the data. ClearStyleData would be OK, but
256 // this test for no mChild or mEmptyChild doesn't catch that case.)
257 const void *current = GetStyleData(aSID);
258 if (!mChild && !mEmptyChild &&
259 !(mBits & nsCachedStyleData::GetBitForSID(aSID)) &&
260 mCachedStyleData.GetStyleData(aSID))
261 return const_cast<void*>(current);
263 void* result;
264 nsPresContext *presContext = PresContext();
265 switch (aSID) {
267 #define UNIQUE_CASE(c_) \
268 case eStyleStruct_##c_: \
269 result = new (presContext) nsStyle##c_( \
270 * static_cast<const nsStyle##c_ *>(current)); \
271 break;
273 UNIQUE_CASE(Display)
274 UNIQUE_CASE(Background)
275 UNIQUE_CASE(Text)
276 UNIQUE_CASE(TextReset)
278 #undef UNIQUE_CASE
280 default:
281 NS_ERROR("Struct type not supported. Please find another way to do this if you can!\n");
282 return nsnull;
285 if (!result) {
286 NS_WARNING("Ran out of memory while trying to allocate memory for a unique style struct! "
287 "Returning the non-unique data.");
288 return const_cast<void*>(current);
291 SetStyle(aSID, result);
292 mBits &= ~nsCachedStyleData::GetBitForSID(aSID);
294 return result;
297 void
298 nsStyleContext::SetStyle(nsStyleStructID aSID, void* aStruct)
300 // This method should only be called from nsRuleNode! It is not a public
301 // method!
303 NS_ASSERTION(aSID >= 0 && aSID < nsStyleStructID_Length, "out of bounds");
305 // NOTE: nsCachedStyleData::GetStyleData works roughly the same way.
306 // See the comments there (in nsRuleNode.h) for more details about
307 // what this is doing and why.
309 const nsCachedStyleData::StyleStructInfo& info =
310 nsCachedStyleData::gInfo[aSID];
311 char* resetOrInheritSlot = reinterpret_cast<char*>(&mCachedStyleData) +
312 info.mCachedStyleDataOffset;
313 char* resetOrInherit = reinterpret_cast<char*>
314 (*reinterpret_cast<void**>(resetOrInheritSlot));
315 if (!resetOrInherit) {
316 nsPresContext *presContext = mRuleNode->GetPresContext();
317 if (mCachedStyleData.IsReset(aSID)) {
318 mCachedStyleData.mResetData = new (presContext) nsResetStyleData;
319 resetOrInherit = reinterpret_cast<char*>(mCachedStyleData.mResetData);
320 } else {
321 mCachedStyleData.mInheritedData =
322 new (presContext) nsInheritedStyleData;
323 resetOrInherit =
324 reinterpret_cast<char*>(mCachedStyleData.mInheritedData);
327 char* dataSlot = resetOrInherit + info.mInheritResetOffset;
328 *reinterpret_cast<void**>(dataSlot) = aStruct;
331 void
332 nsStyleContext::ApplyStyleFixups(nsPresContext* aPresContext)
334 // See if we have any text decorations.
335 // First see if our parent has text decorations. If our parent does, then we inherit the bit.
336 if (mParent && mParent->HasTextDecorations())
337 mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
338 else {
339 // We might have defined a decoration.
340 const nsStyleTextReset* text = GetStyleTextReset();
341 if (text->mTextDecoration != NS_STYLE_TEXT_DECORATION_NONE &&
342 text->mTextDecoration != NS_STYLE_TEXT_DECORATION_OVERRIDE_ALL)
343 mBits |= NS_STYLE_HAS_TEXT_DECORATIONS;
346 // Correct tables.
347 const nsStyleDisplay* disp = GetStyleDisplay();
348 if (disp->mDisplay == NS_STYLE_DISPLAY_TABLE) {
349 // -moz-center and -moz-right are used for HTML's alignment
350 // This is covering the <div align="right"><table>...</table></div> case.
351 // In this case, we don't want to inherit the text alignment into the table.
352 const nsStyleText* text = GetStyleText();
354 if (text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER ||
355 text->mTextAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT)
357 nsStyleText* uniqueText = (nsStyleText*)GetUniqueStyleData(eStyleStruct_Text);
358 uniqueText->mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
362 // CSS2.1 section 9.2.4 specifies fixups for the 'display' property of
363 // the root element. We can't implement them in nsRuleNode because we
364 // don't want to store all display structs that aren't 'block',
365 // 'inline', or 'table' in the style context tree on the off chance
366 // that the root element has its style reresolved later. So do them
367 // here if needed, by changing the style data, so that other code
368 // doesn't get confused by looking at the style data.
369 if (!mParent) {
370 if (disp->mDisplay != NS_STYLE_DISPLAY_NONE &&
371 disp->mDisplay != NS_STYLE_DISPLAY_BLOCK &&
372 disp->mDisplay != NS_STYLE_DISPLAY_TABLE) {
373 nsStyleDisplay *mutable_display = static_cast<nsStyleDisplay*>
374 (GetUniqueStyleData(eStyleStruct_Display));
375 if (mutable_display->mDisplay == NS_STYLE_DISPLAY_INLINE_TABLE)
376 mutable_display->mDisplay = NS_STYLE_DISPLAY_TABLE;
377 else
378 mutable_display->mDisplay = NS_STYLE_DISPLAY_BLOCK;
382 // Computer User Interface style, to trigger loads of cursors
383 GetStyleUserInterface();
386 nsChangeHint
387 nsStyleContext::CalcStyleDifference(nsStyleContext* aOther)
389 nsChangeHint hint = NS_STYLE_HINT_NONE;
390 NS_ENSURE_TRUE(aOther, hint);
391 // We must always ensure that we populate the structs on the new style
392 // context that are filled in on the old context, so that if we get
393 // two style changes in succession, the second of which causes a real
394 // style change, the PeekStyleData doesn't return null (implying that
395 // nobody ever looked at that struct's data). In other words, we
396 // can't skip later structs if we get a big change up front, because
397 // we could later get a small change in one of those structs that we
398 // don't want to miss.
400 // If our rule nodes are the same, then we are looking at the same
401 // style data. We know this because CalcStyleDifference is always
402 // called on two style contexts that point to the same element, so we
403 // know that our position in the style context tree is the same and
404 // our position in the rule node tree is also the same.
405 PRBool compare = mRuleNode != aOther->mRuleNode;
407 nsChangeHint maxHint = nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
408 nsChangeHint_UpdateCursor);
410 #define DO_STRUCT_DIFFERENCE(struct_) \
411 PR_BEGIN_MACRO \
412 NS_ASSERTION(NS_IsHintSubset(nsStyle##struct_::MaxDifference(), maxHint), \
413 "Struct placed in the wrong maxHint section"); \
414 const nsStyle##struct_* this##struct_ = \
415 static_cast<const nsStyle##struct_*>( \
416 PeekStyleData(eStyleStruct_##struct_)); \
417 if (this##struct_) { \
418 const nsStyle##struct_* other##struct_ = aOther->GetStyle##struct_(); \
419 if (compare && \
420 !NS_IsHintSubset(maxHint, hint) && \
421 this##struct_ != other##struct_) { \
422 NS_ASSERTION(NS_IsHintSubset( \
423 this##struct_->CalcDifference(*other##struct_), \
424 nsStyle##struct_::MaxDifference()), \
425 "CalcDifference() returned bigger hint than MaxDifference()"); \
426 NS_UpdateHint(hint, this##struct_->CalcDifference(*other##struct_)); \
429 PR_END_MACRO
431 // We begin by examining those style structs that are capable of
432 // causing the maximal difference, a FRAMECHANGE.
433 // FRAMECHANGE Structs: Display, XUL, Content, UserInterface,
434 // Visibility, Outline, TableBorder, Table, UIReset, Quotes
435 DO_STRUCT_DIFFERENCE(Display);
436 DO_STRUCT_DIFFERENCE(XUL);
437 DO_STRUCT_DIFFERENCE(Column);
438 DO_STRUCT_DIFFERENCE(Content);
439 DO_STRUCT_DIFFERENCE(UserInterface);
440 DO_STRUCT_DIFFERENCE(Visibility);
441 DO_STRUCT_DIFFERENCE(Outline);
442 DO_STRUCT_DIFFERENCE(TableBorder);
443 DO_STRUCT_DIFFERENCE(Table);
444 DO_STRUCT_DIFFERENCE(UIReset);
445 DO_STRUCT_DIFFERENCE(List);
446 // If the quotes implementation is ever going to change we might not need
447 // a framechange here and a reflow should be sufficient. See bug 35768.
448 DO_STRUCT_DIFFERENCE(Quotes);
450 #ifdef MOZ_SVG
451 maxHint = nsChangeHint(NS_STYLE_HINT_REFLOW | nsChangeHint_UpdateEffects);
452 DO_STRUCT_DIFFERENCE(SVGReset);
453 DO_STRUCT_DIFFERENCE(SVG);
454 #endif
456 // At this point, we know that the worst kind of damage we could do is
457 // a reflow.
458 maxHint = NS_STYLE_HINT_REFLOW;
460 // The following structs cause (as their maximal difference) a reflow
461 // to occur. REFLOW Structs: Font, Margin, Padding, Border, List,
462 // Position, Text, TextReset
463 DO_STRUCT_DIFFERENCE(Font);
464 DO_STRUCT_DIFFERENCE(Margin);
465 DO_STRUCT_DIFFERENCE(Padding);
466 DO_STRUCT_DIFFERENCE(Border);
467 DO_STRUCT_DIFFERENCE(Position);
468 DO_STRUCT_DIFFERENCE(Text);
469 DO_STRUCT_DIFFERENCE(TextReset);
471 // At this point, we know that the worst kind of damage we could do is
472 // a re-render (i.e., a VISUAL change).
473 maxHint = NS_STYLE_HINT_VISUAL;
475 // The following structs cause (as their maximal difference) a
476 // re-render to occur. VISUAL Structs: Color, Background
477 DO_STRUCT_DIFFERENCE(Color);
478 DO_STRUCT_DIFFERENCE(Background);
480 #undef DO_STRUCT_DIFFERENCE
482 return hint;
485 void
486 nsStyleContext::Mark()
488 // Mark our rule node.
489 mRuleNode->Mark();
491 // Mark our children (i.e., tell them to mark their rule nodes, etc.).
492 if (mChild) {
493 nsStyleContext* child = mChild;
494 do {
495 child->Mark();
496 child = child->mNextSibling;
497 } while (mChild != child);
500 if (mEmptyChild) {
501 nsStyleContext* child = mEmptyChild;
502 do {
503 child->Mark();
504 child = child->mNextSibling;
505 } while (mEmptyChild != child);
509 #ifdef DEBUG
511 class URICString : public nsCAutoString {
512 public:
513 URICString(nsIURI* aURI) {
514 if (aURI) {
515 aURI->GetSpec(*this);
516 } else {
517 Assign("[none]");
521 URICString(imgIRequest* aImageRequest) {
522 nsCOMPtr<nsIURI> uri;
523 if (aImageRequest) {
524 aImageRequest->GetURI(getter_AddRefs(uri));
526 if (uri) {
527 uri->GetSpec(*this);
528 } else {
529 Assign("[none]");
533 URICString(nsCSSValue::URL* aURI) {
534 if (aURI) {
535 NS_ASSERTION(aURI->mURI, "Must have URI here!");
536 aURI->mURI->GetSpec(*this);
537 } else {
538 Assign("[none]");
542 URICString& operator=(const URICString& aOther) {
543 Assign(aOther);
544 return *this;
548 void nsStyleContext::List(FILE* out, PRInt32 aIndent)
550 // Indent
551 PRInt32 ix;
552 for (ix = aIndent; --ix >= 0; ) fputs(" ", out);
553 fprintf(out, "%p(%d) parent=%p ",
554 (void*)this, mRefCnt, (void *)mParent);
555 if (mPseudoTag) {
556 nsAutoString buffer;
557 mPseudoTag->ToString(buffer);
558 fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out);
559 fputs(" ", out);
562 if (mRuleNode) {
563 fputs("{\n", out);
564 nsRuleNode* ruleNode = mRuleNode;
565 while (ruleNode) {
566 nsIStyleRule *styleRule = ruleNode->GetRule();
567 if (styleRule) {
568 styleRule->List(out, aIndent + 1);
570 ruleNode = ruleNode->GetParent();
572 for (ix = aIndent; --ix >= 0; ) fputs(" ", out);
573 fputs("}\n", out);
575 else {
576 fputs("{}\n", out);
579 if (nsnull != mChild) {
580 nsStyleContext* child = mChild;
581 do {
582 child->List(out, aIndent + 1);
583 child = child->mNextSibling;
584 } while (mChild != child);
586 if (nsnull != mEmptyChild) {
587 nsStyleContext* child = mEmptyChild;
588 do {
589 child->List(out, aIndent + 1);
590 child = child->mNextSibling;
591 } while (mEmptyChild != child);
595 static void IndentBy(FILE* out, PRInt32 aIndent) {
596 while (--aIndent >= 0) fputs(" ", out);
598 // virtual
599 void nsStyleContext::DumpRegressionData(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent)
601 nsAutoString str;
603 // FONT
604 IndentBy(out,aIndent);
605 const nsStyleFont* font = GetStyleFont();
606 fprintf(out, "<font %s %d %d %d />\n",
607 NS_ConvertUTF16toUTF8(font->mFont.name).get(),
608 font->mFont.size,
609 font->mSize,
610 font->mGenericID);
612 // COLOR
613 IndentBy(out,aIndent);
614 const nsStyleColor* color = GetStyleColor();
615 fprintf(out, "<color data=\"%ld\"/>\n",
616 (long)color->mColor);
618 // BACKGROUND
619 IndentBy(out,aIndent);
620 const nsStyleBackground* bg = GetStyleBackground();
621 fprintf(out, "<background data=\"%d %d %d %ld %ld %ld %s\"/>\n",
622 (int)bg->mBackgroundAttachment,
623 (int)bg->mBackgroundFlags,
624 (int)bg->mBackgroundRepeat,
625 (long)bg->mBackgroundColor,
626 // XXX These aren't initialized unless flags are set:
627 (long)bg->mBackgroundXPosition.mCoord, // potentially lossy on some platforms
628 (long)bg->mBackgroundYPosition.mCoord, // potentially lossy on some platforms
629 URICString(bg->mBackgroundImage).get());
631 // SPACING (ie. margin, padding, border, outline)
632 IndentBy(out,aIndent);
633 fprintf(out, "<spacing data=\"");
635 const nsStyleMargin* margin = GetStyleMargin();
636 margin->mMargin.ToString(str);
637 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
639 const nsStylePadding* padding = GetStylePadding();
640 padding->mPadding.ToString(str);
641 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
643 const nsStyleBorder* border = GetStyleBorder();
644 #ifdef NS_COORD_IS_FLOAT
645 const char format [] = "top: %ftw right: %ftw bottom: %ftw left: %ftw";
646 #else
647 const char format [] = "top: %dtw right: %dtw bottom: %dtw left: %dtw";
648 #endif
649 nsPrintfCString output(format,
650 border->GetActualBorderWidth(NS_SIDE_TOP),
651 border->GetActualBorderWidth(NS_SIDE_RIGHT),
652 border->GetActualBorderWidth(NS_SIDE_BOTTOM),
653 border->GetActualBorderWidth(NS_SIDE_LEFT));
654 fprintf(out, "%s ", output.get());
655 border->mBorderRadius.ToString(str);
656 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
658 const nsStyleOutline* outline = GetStyleOutline();
659 outline->mOutlineRadius.ToString(str);
660 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
661 outline->mOutlineWidth.ToString(str);
662 fprintf(out, "%s", NS_ConvertUTF16toUTF8(str).get());
663 fprintf(out, "%d", (int)border->mFloatEdge);
664 fprintf(out, "\" />\n");
666 // LIST
667 IndentBy(out,aIndent);
668 const nsStyleList* list = GetStyleList();
669 fprintf(out, "<list data=\"%d %d %s\" />\n",
670 (int)list->mListStyleType,
671 (int)list->mListStyleType,
672 URICString(list->mListStyleImage).get());
674 // POSITION
675 IndentBy(out,aIndent);
676 const nsStylePosition* pos = GetStylePosition();
677 fprintf(out, "<position data=\"");
678 pos->mOffset.ToString(str);
679 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
680 pos->mWidth.ToString(str);
681 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
682 pos->mMinWidth.ToString(str);
683 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
684 pos->mMaxWidth.ToString(str);
685 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
686 pos->mHeight.ToString(str);
687 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
688 pos->mMinHeight.ToString(str);
689 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
690 pos->mMaxHeight.ToString(str);
691 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
692 fprintf(out, "%d ", (int)pos->mBoxSizing);
693 pos->mZIndex.ToString(str);
694 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
695 fprintf(out, "\" />\n");
697 // TEXT
698 IndentBy(out,aIndent);
699 const nsStyleText* text = GetStyleText();
700 fprintf(out, "<text data=\"%d %d %d %d",
701 (int)text->mTextAlign,
702 (int)text->mTextTransform,
703 (int)text->mWhiteSpace,
704 (int)text->mWordWrap);
705 text->mLetterSpacing.ToString(str);
706 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
707 text->mLineHeight.ToString(str);
708 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
709 text->mTextIndent.ToString(str);
710 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
711 text->mWordSpacing.ToString(str);
712 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
713 fprintf(out, "\" />\n");
715 // TEXT RESET
716 IndentBy(out,aIndent);
717 const nsStyleTextReset* textReset = GetStyleTextReset();
718 fprintf(out, "<textreset data=\"%d ",
719 (int)textReset->mTextDecoration);
720 textReset->mVerticalAlign.ToString(str);
721 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
722 fprintf(out, "\" />\n");
724 // DISPLAY
725 IndentBy(out,aIndent);
726 const nsStyleDisplay* disp = GetStyleDisplay();
727 fprintf(out, "<display data=\"%d %d %f %d %d %d %d %d %d %d %ld %ld %ld %ld %s\" />\n",
728 (int)disp->mPosition,
729 (int)disp->mDisplay,
730 (float)disp->mOpacity,
731 (int)disp->mFloats,
732 (int)disp->mBreakType,
733 (int)disp->mBreakBefore,
734 (int)disp->mBreakAfter,
735 (int)disp->mOverflowX,
736 (int)disp->mOverflowY,
737 (int)disp->mClipFlags,
738 (long)disp->mClip.x,
739 (long)disp->mClip.y,
740 (long)disp->mClip.width,
741 (long)disp->mClip.height,
742 URICString(disp->mBinding).get()
745 // VISIBILITY
746 IndentBy(out,aIndent);
747 const nsStyleVisibility* vis = GetStyleVisibility();
748 fprintf(out, "<visibility data=\"%d %d\" />\n",
749 (int)vis->mDirection,
750 (int)vis->mVisible
753 // TABLE
754 IndentBy(out,aIndent);
755 const nsStyleTable* table = GetStyleTable();
756 fprintf(out, "<table data=\"%d %d %d ",
757 (int)table->mLayoutStrategy,
758 (int)table->mFrame,
759 (int)table->mRules);
760 fprintf(out, "%ld %ld ",
761 (long)table->mCols,
762 (long)table->mSpan);
763 fprintf(out, "\" />\n");
765 // TABLEBORDER
766 IndentBy(out,aIndent);
767 const nsStyleTableBorder* tableBorder = GetStyleTableBorder();
768 fprintf(out, "<tableborder data=\"%d %d %d %d %d ",
769 (int)tableBorder->mBorderCollapse,
770 (int)tableBorder->mBorderSpacingX,
771 (int)tableBorder->mBorderSpacingY,
772 (int)tableBorder->mCaptionSide,
773 (int)tableBorder->mEmptyCells);
774 fprintf(out, "\" />\n");
776 // CONTENT
777 IndentBy(out,aIndent);
778 const nsStyleContent* content = GetStyleContent();
779 fprintf(out, "<content data=\"%ld %ld %ld ",
780 (long)content->ContentCount(),
781 (long)content->CounterIncrementCount(),
782 (long)content->CounterResetCount());
783 // XXX: iterate over the content and counters...
784 content->mMarkerOffset.ToString(str);
785 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
786 fprintf(out, "\" />\n");
788 // QUOTES
789 IndentBy(out,aIndent);
790 const nsStyleQuotes* quotes = GetStyleQuotes();
791 fprintf(out, "<quotes data=\"%ld ",
792 (long)quotes->QuotesCount());
793 // XXX: iterate over the quotes...
794 fprintf(out, "\" />\n");
796 // UI
797 IndentBy(out,aIndent);
798 const nsStyleUserInterface* ui = GetStyleUserInterface();
799 fprintf(out, "<ui data=\"%d %d %d %d\" />\n",
800 (int)ui->mUserInput,
801 (int)ui->mUserModify,
802 (int)ui->mUserFocus,
803 (int)ui->mCursor);
805 // UIReset
806 IndentBy(out,aIndent);
807 const nsStyleUIReset* uiReset = GetStyleUIReset();
808 fprintf(out, "<uireset data=\"%d %d %d\" />\n",
809 (int)uiReset->mUserSelect,
810 (int)uiReset->mIMEMode,
811 (int)uiReset->mWindowShadow);
813 // Column
814 IndentBy(out,aIndent);
815 const nsStyleColumn* column = GetStyleColumn();
816 fprintf(out, "<column data=\"%d ",
817 (int)column->mColumnCount);
818 column->mColumnWidth.ToString(str);
819 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
820 column->mColumnGap.ToString(str);
821 fprintf(out, "%s ", NS_ConvertUTF16toUTF8(str).get());
822 fprintf(out, "%d %d %ld",
823 (int)column->GetComputedColumnRuleWidth(),
824 (int)column->mColumnRuleStyle,
825 (long)column->mColumnRuleColor);
826 fprintf(out, "\" />\n");
828 // XUL
829 IndentBy(out,aIndent);
830 const nsStyleXUL* xul = GetStyleXUL();
831 fprintf(out, "<xul data=\"%d %d %d %d %d %d",
832 (int)xul->mBoxAlign,
833 (int)xul->mBoxDirection,
834 (int)xul->mBoxFlex,
835 (int)xul->mBoxOrient,
836 (int)xul->mBoxPack,
837 (int)xul->mBoxOrdinal);
838 fprintf(out, "\" />\n");
840 #ifdef MOZ_SVG
841 // SVG
842 IndentBy(out,aIndent);
843 const nsStyleSVG* svg = GetStyleSVG();
844 fprintf(out, "<svg data=\"%d ",(int)svg->mFill.mType);
845 if (svg->mFill.mType == eStyleSVGPaintType_Server)
846 fprintf(out, "%s %ld ", URICString(svg->mFill.mPaint.mPaintServer).get(),
847 (long)svg->mFill.mFallbackColor);
848 else
849 fprintf(out, "%ld ", (long)svg->mFill.mPaint.mColor);
851 fprintf(out, "%d ", (int)svg->mStroke.mType);
852 if (svg->mStroke.mType == eStyleSVGPaintType_Server)
853 fprintf(out, "%s %ld ", URICString(svg->mStroke.mPaint.mPaintServer).get(),
854 (long)svg->mStroke.mFallbackColor);
855 else
856 fprintf(out, "%ld ", (long)svg->mStroke.mPaint.mColor);
858 fprintf(out, "%s %s %s ",
859 URICString(svg->mMarkerEnd).get(),
860 URICString(svg->mMarkerMid).get(),
861 URICString(svg->mMarkerStart).get());
863 for (PRUint32 i = 0; i < svg->mStrokeDasharrayLength; i++) {
864 svg->mStrokeDasharray[i].ToString(str);
865 fprintf(out,
866 "%s%c",
867 NS_ConvertUTF16toUTF8(str).get(),
868 (i == svg->mStrokeDasharrayLength) ? ' ' : ',');
871 svg->mStrokeDashoffset.ToString(str);
872 fprintf(out, "%f %s %f %f ",
873 svg->mFillOpacity,
874 NS_ConvertUTF16toUTF8(str).get(),
875 svg->mStrokeMiterlimit,
876 svg->mStrokeOpacity);
877 svg->mStrokeWidth.ToString(str);
878 fprintf(out, "%s %d %d %d %d %d %d %d %d %d %d %d\" />\n",
879 NS_ConvertUTF16toUTF8(str).get(),
880 (int)svg->mStrokeDasharrayLength,
881 (int)svg->mClipRule,
882 (int)svg->mColorInterpolation,
883 (int)svg->mColorInterpolationFilters,
884 (int)svg->mFillRule,
885 (int)svg->mPointerEvents,
886 (int)svg->mShapeRendering,
887 (int)svg->mStrokeLinecap,
888 (int)svg->mStrokeLinejoin,
889 (int)svg->mTextAnchor,
890 (int)svg->mTextRendering);
892 // SVGReset
893 IndentBy(out,aIndent);
894 const nsStyleSVGReset* svgReset = GetStyleSVGReset();
896 fprintf(out, "<svgreset data=\"%ld ", (long)svgReset->mStopColor);
898 fprintf(out, "%ld ", (long)svgReset->mFloodColor);
900 fprintf(out, "%ld ", (long)svgReset->mLightingColor);
902 fprintf(out, "%s %s %s %f %f %d\" />\n",
903 URICString(svgReset->mClipPath).get(),
904 URICString(svgReset->mFilter).get(),
905 URICString(svgReset->mMask).get(),
906 svgReset->mStopOpacity,
907 svgReset->mFloodOpacity,
908 (int)svgReset->mDominantBaseline);
909 #endif
910 //#insert new style structs here#
912 #endif
914 // Overloaded new operator. Initializes the memory to 0 and relies on an arena
915 // (which comes from the presShell) to perform the allocation.
916 void*
917 nsStyleContext::operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW
919 // Check the recycle list first.
920 return aPresContext->AllocateFromShell(sz);
923 // Overridden to prevent the global delete from being called, since the memory
924 // came out of an nsIArena instead of the global delete operator's heap.
925 void
926 nsStyleContext::Destroy()
928 // Get the pres context from our rule node.
929 nsCOMPtr<nsPresContext> presContext = mRuleNode->GetPresContext();
931 // Call our destructor.
932 this->~nsStyleContext();
934 // Don't let the memory be freed, since it will be recycled
935 // instead. Don't call the global operator delete.
936 presContext->FreeToShell(sizeof(nsStyleContext), this);
939 already_AddRefed<nsStyleContext>
940 NS_NewStyleContext(nsStyleContext* aParentContext,
941 nsIAtom* aPseudoTag,
942 nsRuleNode* aRuleNode,
943 nsPresContext* aPresContext)
945 nsStyleContext* context = new (aPresContext) nsStyleContext(aParentContext, aPseudoTag,
946 aRuleNode, aPresContext);
947 if (context)
948 context->AddRef();
949 return context;