• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
3  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  */
21 
22 #include "config.h"
23 #include "RenderStyle.h"
24 
25 #include "CSSStyleSelector.h"
26 #include "CachedImage.h"
27 #include "CounterContent.h"
28 #include "FontSelector.h"
29 #include "RenderArena.h"
30 #include "RenderObject.h"
31 #include "StyleImage.h"
32 #include <wtf/StdLibExtras.h>
33 #include <algorithm>
34 
35 namespace WebCore {
36 
defaultStyle()37 inline RenderStyle* defaultStyle()
38 {
39     static RenderStyle* s_defaultStyle = RenderStyle::createDefaultStyle().releaseRef();
40     return s_defaultStyle;
41 }
42 
create()43 PassRefPtr<RenderStyle> RenderStyle::create()
44 {
45     return adoptRef(new RenderStyle());
46 }
47 
createDefaultStyle()48 PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
49 {
50     return adoptRef(new RenderStyle(true));
51 }
52 
clone(const RenderStyle * other)53 PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
54 {
55     return adoptRef(new RenderStyle(*other));
56 }
57 
RenderStyle()58 RenderStyle::RenderStyle()
59     : box(defaultStyle()->box)
60     , visual(defaultStyle()->visual)
61     , background(defaultStyle()->background)
62     , surround(defaultStyle()->surround)
63     , rareNonInheritedData(defaultStyle()->rareNonInheritedData)
64     , rareInheritedData(defaultStyle()->rareInheritedData)
65     , inherited(defaultStyle()->inherited)
66     , m_pseudoState(PseudoUnknown)
67     , m_affectedByAttributeSelectors(false)
68     , m_unique(false)
69     , m_affectedByEmpty(false)
70     , m_emptyState(false)
71     , m_childrenAffectedByFirstChildRules(false)
72     , m_childrenAffectedByLastChildRules(false)
73     , m_childrenAffectedByDirectAdjacentRules(false)
74     , m_childrenAffectedByForwardPositionalRules(false)
75     , m_childrenAffectedByBackwardPositionalRules(false)
76     , m_firstChildState(false)
77     , m_lastChildState(false)
78     , m_childIndex(0)
79 #if ENABLE(SVG)
80     , m_svgStyle(defaultStyle()->m_svgStyle)
81 #endif
82 {
83     setBitDefaults(); // Would it be faster to copy this from the default style?
84 }
85 
RenderStyle(bool)86 RenderStyle::RenderStyle(bool)
87     : m_pseudoState(PseudoUnknown)
88     , m_affectedByAttributeSelectors(false)
89     , m_unique(false)
90     , m_affectedByEmpty(false)
91     , m_emptyState(false)
92     , m_childrenAffectedByFirstChildRules(false)
93     , m_childrenAffectedByLastChildRules(false)
94     , m_childrenAffectedByDirectAdjacentRules(false)
95     , m_childrenAffectedByForwardPositionalRules(false)
96     , m_childrenAffectedByBackwardPositionalRules(false)
97     , m_firstChildState(false)
98     , m_lastChildState(false)
99     , m_childIndex(0)
100 {
101     setBitDefaults();
102 
103     box.init();
104     visual.init();
105     background.init();
106     surround.init();
107     rareNonInheritedData.init();
108     rareNonInheritedData.access()->flexibleBox.init();
109     rareNonInheritedData.access()->marquee.init();
110     rareNonInheritedData.access()->m_multiCol.init();
111     rareNonInheritedData.access()->m_transform.init();
112     rareInheritedData.init();
113     inherited.init();
114 
115 #if ENABLE(SVG)
116     m_svgStyle.init();
117 #endif
118 }
119 
RenderStyle(const RenderStyle & o)120 RenderStyle::RenderStyle(const RenderStyle& o)
121     : RefCounted<RenderStyle>()
122     , inherited_flags(o.inherited_flags)
123     , noninherited_flags(o.noninherited_flags)
124     , box(o.box)
125     , visual(o.visual)
126     , background(o.background)
127     , surround(o.surround)
128     , rareNonInheritedData(o.rareNonInheritedData)
129     , rareInheritedData(o.rareInheritedData)
130     , inherited(o.inherited)
131     , m_pseudoState(o.m_pseudoState)
132     , m_affectedByAttributeSelectors(false)
133     , m_unique(false)
134     , m_affectedByEmpty(false)
135     , m_emptyState(false)
136     , m_childrenAffectedByFirstChildRules(false)
137     , m_childrenAffectedByLastChildRules(false)
138     , m_childrenAffectedByDirectAdjacentRules(false)
139     , m_childrenAffectedByForwardPositionalRules(false)
140     , m_childrenAffectedByBackwardPositionalRules(false)
141     , m_firstChildState(false)
142     , m_lastChildState(false)
143     , m_childIndex(0)
144 #if ENABLE(SVG)
145     , m_svgStyle(o.m_svgStyle)
146 #endif
147 {
148 }
149 
inheritFrom(const RenderStyle * inheritParent)150 void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
151 {
152     rareInheritedData = inheritParent->rareInheritedData;
153     inherited = inheritParent->inherited;
154     inherited_flags = inheritParent->inherited_flags;
155 #if ENABLE(SVG)
156     if (m_svgStyle != inheritParent->m_svgStyle)
157         m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
158 #endif
159 }
160 
~RenderStyle()161 RenderStyle::~RenderStyle()
162 {
163 }
164 
operator ==(const RenderStyle & o) const165 bool RenderStyle::operator==(const RenderStyle& o) const
166 {
167     // compare everything except the pseudoStyle pointer
168     return inherited_flags == o.inherited_flags &&
169             noninherited_flags == o.noninherited_flags &&
170             box == o.box &&
171             visual == o.visual &&
172             background == o.background &&
173             surround == o.surround &&
174             rareNonInheritedData == o.rareNonInheritedData &&
175             rareInheritedData == o.rareInheritedData &&
176             inherited == o.inherited
177 #if ENABLE(SVG)
178             && m_svgStyle == o.m_svgStyle
179 #endif
180             ;
181 }
182 
isStyleAvailable() const183 bool RenderStyle::isStyleAvailable() const
184 {
185     return this != CSSStyleSelector::styleNotYetAvailable();
186 }
187 
pseudoBit(RenderStyle::PseudoId pseudo)188 static inline int pseudoBit(RenderStyle::PseudoId pseudo)
189 {
190     return 1 << (pseudo - 1);
191 }
192 
hasPseudoStyle(PseudoId pseudo) const193 bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
194 {
195     ASSERT(pseudo > NOPSEUDO);
196     ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
197     return pseudoBit(pseudo) & noninherited_flags._pseudoBits;
198 }
199 
setHasPseudoStyle(PseudoId pseudo)200 void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
201 {
202     ASSERT(pseudo > NOPSEUDO);
203     ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
204     noninherited_flags._pseudoBits |= pseudoBit(pseudo);
205 }
206 
getCachedPseudoStyle(PseudoId pid)207 RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid)
208 {
209     if (!m_cachedPseudoStyle || styleType() != NOPSEUDO)
210         return 0;
211     RenderStyle* ps = m_cachedPseudoStyle.get();
212     while (ps && ps->styleType() != pid)
213         ps = ps->m_cachedPseudoStyle.get();
214     return ps;
215 }
216 
addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)217 RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
218 {
219     if (!pseudo)
220         return 0;
221     pseudo->m_cachedPseudoStyle = m_cachedPseudoStyle;
222     m_cachedPseudoStyle = pseudo;
223     return m_cachedPseudoStyle.get();
224 }
225 
inheritedNotEqual(RenderStyle * other) const226 bool RenderStyle::inheritedNotEqual(RenderStyle* other) const
227 {
228     return inherited_flags != other->inherited_flags ||
229            inherited != other->inherited ||
230 #if ENABLE(SVG)
231            m_svgStyle->inheritedNotEqual(other->m_svgStyle.get()) ||
232 #endif
233            rareInheritedData != other->rareInheritedData;
234 }
235 
positionedObjectMoved(const LengthBox & a,const LengthBox & b)236 static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
237 {
238     // If any unit types are different, then we can't guarantee
239     // that this was just a movement.
240     if (a.left().type() != b.left().type() ||
241         a.right().type() != b.right().type() ||
242         a.top().type() != b.top().type() ||
243         a.bottom().type() != b.bottom().type())
244         return false;
245 
246     // Only one unit can be non-auto in the horizontal direction and
247     // in the vertical direction.  Otherwise the adjustment of values
248     // is changing the size of the box.
249     if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
250         return false;
251     if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
252         return false;
253 
254     // One of the units is fixed or percent in both directions and stayed
255     // that way in the new style.  Therefore all we are doing is moving.
256     return true;
257 }
258 
259 /*
260   compares two styles. The result gives an idea of the action that
261   needs to be taken when replacing the old style with a new one.
262 
263   CbLayout: The containing block of the object needs a relayout.
264   Layout: the RenderObject needs a relayout after the style change
265   Visible: The change is visible, but no relayout is needed
266   NonVisible: The object does need neither repaint nor relayout after
267        the change.
268 
269   ### TODO:
270   A lot can be optimised here based on the display type, lots of
271   optimisations are unimplemented, and currently result in the
272   worst case result causing a relayout of the containing block.
273 */
diff(const RenderStyle * other) const274 RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
275 {
276 #if ENABLE(SVG)
277     // This is horribly inefficient.  Eventually we'll have to integrate
278     // this more directly by calling: Diff svgDiff = svgStyle->diff(other)
279     // and then checking svgDiff and returning from the appropriate places below.
280     if (m_svgStyle != other->m_svgStyle)
281         return Layout;
282 #endif
283 
284     if (box->width != other->box->width ||
285         box->min_width != other->box->min_width ||
286         box->max_width != other->box->max_width ||
287         box->height != other->box->height ||
288         box->min_height != other->box->min_height ||
289         box->max_height != other->box->max_height)
290         return Layout;
291 
292     if (box->vertical_align != other->box->vertical_align || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
293         return Layout;
294 
295     if (box->boxSizing != other->box->boxSizing)
296         return Layout;
297 
298     if (surround->margin != other->surround->margin)
299         return Layout;
300 
301     if (surround->padding != other->surround->padding)
302         return Layout;
303 
304     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
305         if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance ||
306             rareNonInheritedData->marginTopCollapse != other->rareNonInheritedData->marginTopCollapse ||
307             rareNonInheritedData->marginBottomCollapse != other->rareNonInheritedData->marginBottomCollapse ||
308             rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp ||
309             rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
310             return Layout;
311 
312         if (rareNonInheritedData->flexibleBox.get() != other->rareNonInheritedData->flexibleBox.get() &&
313             *rareNonInheritedData->flexibleBox.get() != *other->rareNonInheritedData->flexibleBox.get())
314             return Layout;
315 
316         if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
317             return Layout;
318 
319         if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
320             return Layout;
321 
322         if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get() &&
323             *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
324             return Layout;
325 
326         if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get() &&
327             *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get())
328             return Layout;
329 
330 #if ENABLE(DASHBOARD_SUPPORT)
331         // If regions change, trigger a relayout to re-calc regions.
332         if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
333             return Layout;
334 #endif
335     }
336 
337     if (rareInheritedData.get() != other->rareInheritedData.get()) {
338         if (rareInheritedData->highlight != other->rareInheritedData->highlight ||
339             rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust ||
340             rareInheritedData->wordBreak != other->rareInheritedData->wordBreak ||
341             rareInheritedData->wordWrap != other->rareInheritedData->wordWrap ||
342             rareInheritedData->nbspMode != other->rareInheritedData->nbspMode ||
343             rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak ||
344             rareInheritedData->textSecurity != other->rareInheritedData->textSecurity)
345             return Layout;
346 
347         if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
348             return Layout;
349 
350         if (textStrokeWidth() != other->textStrokeWidth())
351             return Layout;
352     }
353 
354     if (inherited->indent != other->inherited->indent ||
355         inherited->line_height != other->inherited->line_height ||
356         inherited->list_style_image != other->inherited->list_style_image ||
357         inherited->font != other->inherited->font ||
358         inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing ||
359         inherited->vertical_border_spacing != other->inherited->vertical_border_spacing ||
360         inherited_flags._box_direction != other->inherited_flags._box_direction ||
361         inherited_flags._visuallyOrdered != other->inherited_flags._visuallyOrdered ||
362         inherited_flags._htmlHacks != other->inherited_flags._htmlHacks ||
363         noninherited_flags._position != other->noninherited_flags._position ||
364         noninherited_flags._floating != other->noninherited_flags._floating ||
365         noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
366         return Layout;
367 
368 
369     if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
370         if (inherited_flags._border_collapse != other->inherited_flags._border_collapse ||
371             inherited_flags._empty_cells != other->inherited_flags._empty_cells ||
372             inherited_flags._caption_side != other->inherited_flags._caption_side ||
373             noninherited_flags._table_layout != other->noninherited_flags._table_layout)
374             return Layout;
375 
376         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
377         // does not, so these style differences can be width differences.
378         if (inherited_flags._border_collapse &&
379             (borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE ||
380              borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN ||
381              borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE ||
382              borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN ||
383              borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE ||
384              borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN ||
385              borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE ||
386              borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN))
387             return Layout;
388     }
389 
390     if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
391         if (inherited_flags._list_style_type != other->inherited_flags._list_style_type ||
392             inherited_flags._list_style_position != other->inherited_flags._list_style_position)
393             return Layout;
394     }
395 
396     if (inherited_flags._text_align != other->inherited_flags._text_align ||
397         inherited_flags._text_transform != other->inherited_flags._text_transform ||
398         inherited_flags._direction != other->inherited_flags._direction ||
399         inherited_flags._white_space != other->inherited_flags._white_space ||
400         noninherited_flags._clear != other->noninherited_flags._clear)
401         return Layout;
402 
403     // Overflow returns a layout hint.
404     if (noninherited_flags._overflowX != other->noninherited_flags._overflowX ||
405         noninherited_flags._overflowY != other->noninherited_flags._overflowY)
406         return Layout;
407 
408     // If our border widths change, then we need to layout.  Other changes to borders
409     // only necessitate a repaint.
410     if (borderLeftWidth() != other->borderLeftWidth() ||
411         borderTopWidth() != other->borderTopWidth() ||
412         borderBottomWidth() != other->borderBottomWidth() ||
413         borderRightWidth() != other->borderRightWidth())
414         return Layout;
415 
416     // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
417     const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
418     const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
419     if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
420         return Layout;
421     if (visual->counterIncrement != other->visual->counterIncrement ||
422         visual->counterReset != other->visual->counterReset)
423         return Layout;
424 
425     if (inherited->m_effectiveZoom != other->inherited->m_effectiveZoom)
426         return Layout;
427 
428     // Make sure these left/top/right/bottom checks stay below all layout checks and above
429     // all visible checks.
430     if (position() != StaticPosition) {
431         if (surround->offset != other->surround->offset) {
432              // Optimize for the case where a positioned layer is moving but not changing size.
433             if (position() == AbsolutePosition && positionedObjectMoved(surround->offset, other->surround->offset))
434                 return LayoutPositionedMovementOnly;
435 
436             // FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we
437             // can stop doing a layout when relative positioned objects move.  In particular, we'll need
438             // to update scrolling positions and figure out how to do a repaint properly of the updated layer.
439             //if (other->position() == RelativePosition)
440             //    return RepaintLayer;
441             //else
442                 return Layout;
443         } else if (box->z_index != other->box->z_index || box->z_auto != other->box->z_auto ||
444                  visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
445             return RepaintLayer;
446     }
447 
448     if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity ||
449         rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask ||
450         rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
451         return RepaintLayer;
452 
453     if (inherited->color != other->inherited->color ||
454         inherited_flags._visibility != other->inherited_flags._visibility ||
455         inherited_flags._text_decorations != other->inherited_flags._text_decorations ||
456         inherited_flags._force_backgrounds_to_white != other->inherited_flags._force_backgrounds_to_white ||
457         surround->border != other->surround->border ||
458         *background.get() != *other->background.get() ||
459         visual->textDecoration != other->visual->textDecoration ||
460         rareInheritedData->userModify != other->rareInheritedData->userModify ||
461         rareInheritedData->userSelect != other->rareInheritedData->userSelect ||
462         rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag ||
463         rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit ||
464         rareInheritedData->textFillColor != other->rareInheritedData->textFillColor ||
465         rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor)
466         return Repaint;
467 
468     // Cursors are not checked, since they will be set appropriately in response to mouse events,
469     // so they don't need to cause any repaint or layout.
470 
471     // Animations don't need to be checked either.  We always set the new style on the RenderObject, so we will get a chance to fire off
472     // the resulting transition properly.
473     return Equal;
474 }
475 
setClip(Length top,Length right,Length bottom,Length left)476 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
477 {
478     StyleVisualData *data = visual.access();
479     data->clip.m_top = top;
480     data->clip.m_right = right;
481     data->clip.m_bottom = bottom;
482     data->clip.m_left = left;
483 }
484 
addCursor(CachedImage * image,const IntPoint & hotSpot)485 void RenderStyle::addCursor(CachedImage* image, const IntPoint& hotSpot)
486 {
487     CursorData data;
488     data.cursorImage = image;
489     data.hotSpot = hotSpot;
490     if (!inherited.access()->cursorData)
491         inherited.access()->cursorData = CursorList::create();
492     inherited.access()->cursorData->append(data);
493 }
494 
setCursorList(PassRefPtr<CursorList> other)495 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
496 {
497     inherited.access()->cursorData = other;
498 }
499 
clearCursorList()500 void RenderStyle::clearCursorList()
501 {
502     if (inherited->cursorData)
503         inherited.access()->cursorData = 0;
504 }
505 
contentDataEquivalent(const RenderStyle * otherStyle) const506 bool RenderStyle::contentDataEquivalent(const RenderStyle* otherStyle) const
507 {
508     ContentData* c1 = rareNonInheritedData->m_content.get();
509     ContentData* c2 = otherStyle->rareNonInheritedData->m_content.get();
510 
511     while (c1 && c2) {
512         if (c1->m_type != c2->m_type)
513             return false;
514 
515         switch (c1->m_type) {
516             case CONTENT_NONE:
517                 break;
518             case CONTENT_TEXT:
519                 if (!equal(c1->m_content.m_text, c2->m_content.m_text))
520                     return false;
521                 break;
522             case CONTENT_OBJECT:
523                 if (!StyleImage::imagesEquivalent(c1->m_content.m_image, c2->m_content.m_image))
524                     return false;
525                 break;
526             case CONTENT_COUNTER:
527                 if (*c1->m_content.m_counter != *c2->m_content.m_counter)
528                     return false;
529                 break;
530         }
531 
532         c1 = c1->m_next;
533         c2 = c2->m_next;
534     }
535 
536     return !c1 && !c2;
537 }
538 
clearContent()539 void RenderStyle::clearContent()
540 {
541     if (rareNonInheritedData->m_content)
542         rareNonInheritedData->m_content->clear();
543 }
544 
setContent(PassRefPtr<StyleImage> image,bool add)545 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
546 {
547     if (!image)
548         return; // The object is null. Nothing to do. Just bail.
549 
550     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
551     ContentData* lastContent = content.get();
552     while (lastContent && lastContent->m_next)
553         lastContent = lastContent->m_next;
554 
555     bool reuseContent = !add;
556     ContentData* newContentData;
557     if (reuseContent && content) {
558         content->clear();
559         newContentData = content.release();
560     } else
561         newContentData = new ContentData;
562 
563     if (lastContent && !reuseContent)
564         lastContent->m_next = newContentData;
565     else
566         content.set(newContentData);
567 
568     newContentData->m_content.m_image = image.releaseRef();
569     newContentData->m_type = CONTENT_OBJECT;
570 }
571 
setContent(StringImpl * s,bool add)572 void RenderStyle::setContent(StringImpl* s, bool add)
573 {
574     if (!s)
575         return; // The string is null. Nothing to do. Just bail.
576 
577     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
578     ContentData* lastContent = content.get();
579     while (lastContent && lastContent->m_next)
580         lastContent = lastContent->m_next;
581 
582     bool reuseContent = !add;
583     if (add && lastContent) {
584         if (lastContent->m_type == CONTENT_TEXT) {
585             // We can augment the existing string and share this ContentData node.
586             StringImpl* oldStr = lastContent->m_content.m_text;
587             String newStr = oldStr;
588             newStr.append(s);
589             newStr.impl()->ref();
590             oldStr->deref();
591             lastContent->m_content.m_text = newStr.impl();
592             return;
593         }
594     }
595 
596     ContentData* newContentData = 0;
597     if (reuseContent && content) {
598         content->clear();
599         newContentData = content.release();
600     } else
601         newContentData = new ContentData;
602 
603     if (lastContent && !reuseContent)
604         lastContent->m_next = newContentData;
605     else
606         content.set(newContentData);
607 
608     newContentData->m_content.m_text = s;
609     newContentData->m_content.m_text->ref();
610     newContentData->m_type = CONTENT_TEXT;
611 }
612 
setContent(CounterContent * c,bool add)613 void RenderStyle::setContent(CounterContent* c, bool add)
614 {
615     if (!c)
616         return;
617 
618     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
619     ContentData* lastContent = content.get();
620     while (lastContent && lastContent->m_next)
621         lastContent = lastContent->m_next;
622 
623     bool reuseContent = !add;
624     ContentData* newContentData = 0;
625     if (reuseContent && content) {
626         content->clear();
627         newContentData = content.release();
628     } else
629         newContentData = new ContentData;
630 
631     if (lastContent && !reuseContent)
632         lastContent->m_next = newContentData;
633     else
634         content.set(newContentData);
635 
636     newContentData->m_content.m_counter = c;
637     newContentData->m_type = CONTENT_COUNTER;
638 }
639 
applyTransform(TransformationMatrix & transform,const IntSize & borderBoxSize,bool includeTransformOrigin) const640 void RenderStyle::applyTransform(TransformationMatrix& transform, const IntSize& borderBoxSize, bool includeTransformOrigin) const
641 {
642     // transform-origin brackets the transform with translate operations.
643     // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
644     // in that case.
645     bool applyTransformOrigin = false;
646     unsigned s = rareNonInheritedData->m_transform->m_operations.operations().size();
647     unsigned i;
648     if (includeTransformOrigin) {
649         for (i = 0; i < s; i++) {
650             TransformOperation::OperationType type = rareNonInheritedData->m_transform->m_operations.operations()[i]->getOperationType();
651             if (type != TransformOperation::TRANSLATE_X &&
652                     type != TransformOperation::TRANSLATE_Y &&
653                     type != TransformOperation::TRANSLATE) {
654                 applyTransformOrigin = true;
655                 break;
656             }
657         }
658     }
659 
660     if (applyTransformOrigin)
661         transform.translate(transformOriginX().calcFloatValue(borderBoxSize.width()), transformOriginY().calcFloatValue(borderBoxSize.height()));
662 
663     for (i = 0; i < s; i++)
664         rareNonInheritedData->m_transform->m_operations.operations()[i]->apply(transform, borderBoxSize);
665 
666     if (applyTransformOrigin)
667         transform.translate(-transformOriginX().calcFloatValue(borderBoxSize.width()), -transformOriginY().calcFloatValue(borderBoxSize.height()));
668 }
669 
670 #if ENABLE(XBL)
addBindingURI(StringImpl * uri)671 void RenderStyle::addBindingURI(StringImpl* uri)
672 {
673     BindingURI* binding = new BindingURI(uri);
674     if (!bindingURIs())
675         SET_VAR(rareNonInheritedData, bindingURI, binding)
676     else
677         for (BindingURI* b = bindingURIs(); b; b = b->next()) {
678             if (!b->next())
679                 b->setNext(binding);
680         }
681 }
682 #endif
683 
setTextShadow(ShadowData * val,bool add)684 void RenderStyle::setTextShadow(ShadowData* val, bool add)
685 {
686     StyleRareInheritedData* rareData = rareInheritedData.access();
687     if (!add) {
688         delete rareData->textShadow;
689         rareData->textShadow = val;
690         return;
691     }
692 
693     val->next = rareData->textShadow;
694     rareData->textShadow = val;
695 }
696 
setBoxShadow(ShadowData * shadowData,bool add)697 void RenderStyle::setBoxShadow(ShadowData* shadowData, bool add)
698 {
699     StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
700     if (!add) {
701         rareData->m_boxShadow.set(shadowData);
702         return;
703     }
704 
705     shadowData->next = rareData->m_boxShadow.release();
706     rareData->m_boxShadow.set(shadowData);
707 }
708 
counterDirectives() const709 const CounterDirectiveMap* RenderStyle::counterDirectives() const
710 {
711     return rareNonInheritedData->m_counterDirectives.get();
712 }
713 
accessCounterDirectives()714 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
715 {
716     OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
717     if (!map)
718         map.set(new CounterDirectiveMap);
719     return *map.get();
720 }
721 
722 #if ENABLE(DASHBOARD_SUPPORT)
initialDashboardRegions()723 const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
724 {
725     DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
726     return emptyList;
727 }
728 
noneDashboardRegions()729 const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
730 {
731     DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
732     static bool noneListInitialized = false;
733 
734     if (!noneListInitialized) {
735         StyleDashboardRegion region;
736         region.label = "";
737         region.offset.m_top  = Length();
738         region.offset.m_right = Length();
739         region.offset.m_bottom = Length();
740         region.offset.m_left = Length();
741         region.type = StyleDashboardRegion::None;
742         noneList.append(region);
743         noneListInitialized = true;
744     }
745     return noneList;
746 }
747 #endif
748 
adjustAnimations()749 void RenderStyle::adjustAnimations()
750 {
751     AnimationList* animationList = rareNonInheritedData->m_animations.get();
752     if (!animationList)
753         return;
754 
755     // Get rid of empty animations and anything beyond them
756     for (size_t i = 0; i < animationList->size(); ++i) {
757         if (animationList->animation(i)->isEmpty()) {
758             animationList->resize(i);
759             break;
760         }
761     }
762 
763     if (animationList->isEmpty()) {
764         clearAnimations();
765         return;
766     }
767 
768     // Repeat patterns into layers that don't have some properties set.
769     animationList->fillUnsetProperties();
770 }
771 
adjustTransitions()772 void RenderStyle::adjustTransitions()
773 {
774     AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
775     if (!transitionList)
776         return;
777 
778     // Get rid of empty transitions and anything beyond them
779     for (size_t i = 0; i < transitionList->size(); ++i) {
780         if (transitionList->animation(i)->isEmpty()) {
781             transitionList->resize(i);
782             break;
783         }
784     }
785 
786     if (transitionList->isEmpty()) {
787         clearTransitions();
788         return;
789     }
790 
791     // Repeat patterns into layers that don't have some properties set.
792     transitionList->fillUnsetProperties();
793 
794     // Make sure there are no duplicate properties. This is an O(n^2) algorithm
795     // but the lists tend to be very short, so it is probably ok
796     for (size_t i = 0; i < transitionList->size(); ++i) {
797         for (size_t j = i+1; j < transitionList->size(); ++j) {
798             if (transitionList->animation(i)->property() == transitionList->animation(j)->property()) {
799                 // toss i
800                 transitionList->remove(i);
801                 j = i;
802             }
803         }
804     }
805 }
806 
accessAnimations()807 AnimationList* RenderStyle::accessAnimations()
808 {
809     if (!rareNonInheritedData.access()->m_animations)
810         rareNonInheritedData.access()->m_animations.set(new AnimationList());
811     return rareNonInheritedData->m_animations.get();
812 }
813 
accessTransitions()814 AnimationList* RenderStyle::accessTransitions()
815 {
816     if (!rareNonInheritedData.access()->m_transitions)
817         rareNonInheritedData.access()->m_transitions.set(new AnimationList());
818     return rareNonInheritedData->m_transitions.get();
819 }
820 
transitionForProperty(int property)821 const Animation* RenderStyle::transitionForProperty(int property)
822 {
823     if (transitions()) {
824         for (size_t i = 0; i < transitions()->size(); ++i) {
825             const Animation* p = transitions()->animation(i);
826             if (p->property() == cAnimateAll || p->property() == property) {
827                 return p;
828             }
829         }
830     }
831     return 0;
832 }
833 
setBlendedFontSize(int size)834 void RenderStyle::setBlendedFontSize(int size)
835 {
836     FontDescription desc(fontDescription());
837     desc.setSpecifiedSize(size);
838     desc.setComputedSize(size);
839     setFontDescription(desc);
840     font().update(font().fontSelector());
841 }
842 
843 } // namespace WebCore
844