2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * * Redistributions of source code must retain the above copyright
5 * notice, this list of conditions and the following disclaimer.
6 * * Redistributions in binary form must reproduce the above
7 * copyright notice, this list of conditions and the following disclaimer
8 * in the documentation and/or other materials provided with the
10 * * Neither the name of Google Inc. nor the names of its
11 * contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "core/css/resolver/StyleBuilderConverter.h"
30 #include "core/css/BasicShapeFunctions.h"
31 #include "core/css/CSSFontFeatureValue.h"
32 #include "core/css/CSSFunctionValue.h"
33 #include "core/css/CSSGridLineNamesValue.h"
34 #include "core/css/CSSPrimitiveValueMappings.h"
35 #include "core/css/CSSReflectValue.h"
36 #include "core/css/CSSShadowValue.h"
37 #include "core/css/Pair.h"
38 #include "core/css/Rect.h"
39 #include "core/svg/SVGURIReference.h"
45 static GridLength convertGridTrackBreadth(const StyleResolverState& state, CSSPrimitiveValue* primitiveValue)
47 if (primitiveValue->getValueID() == CSSValueMinContent)
48 return Length(MinContent);
50 if (primitiveValue->getValueID() == CSSValueMaxContent)
51 return Length(MaxContent);
54 if (primitiveValue->isFlex())
55 return GridLength(primitiveValue->getDoubleValue());
57 return primitiveValue->convertToLength<FixedConversion | PercentConversion | AutoConversion>(state.cssToLengthConversionData());
62 PassRefPtr<StyleReflection> StyleBuilderConverter::convertBoxReflect(StyleResolverState& state, CSSValue* value)
64 if (value->isPrimitiveValue()) {
65 ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
66 return RenderStyle::initialBoxReflect();
69 CSSReflectValue* reflectValue = toCSSReflectValue(value);
70 RefPtr<StyleReflection> reflection = StyleReflection::create();
71 reflection->setDirection(*reflectValue->direction());
72 if (reflectValue->offset())
73 reflection->setOffset(reflectValue->offset()->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData()));
75 mask.setMaskDefaults();
76 state.styleMap().mapNinePieceImage(state.style(), CSSPropertyWebkitBoxReflect, reflectValue->mask(), mask);
77 reflection->setMask(mask);
79 return reflection.release();
82 Color StyleBuilderConverter::convertColor(StyleResolverState& state, CSSValue* value, bool forVisitedLink)
84 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
85 return state.document().textLinkColors().colorFromPrimitiveValue(primitiveValue, state.style()->color(), forVisitedLink);
88 AtomicString StyleBuilderConverter::convertFragmentIdentifier(StyleResolverState& state, CSSValue* value)
90 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
91 if (primitiveValue->isURI())
92 return SVGURIReference::fragmentIdentifierFromIRIString(primitiveValue->getStringValue(), state.element()->treeScope());
96 LengthBox StyleBuilderConverter::convertClip(StyleResolverState& state, CSSValue* value)
98 Rect* rect = toCSSPrimitiveValue(value)->getRectValue();
100 return LengthBox(convertLengthOrAuto(state, rect->top()),
101 convertLengthOrAuto(state, rect->right()),
102 convertLengthOrAuto(state, rect->bottom()),
103 convertLengthOrAuto(state, rect->left()));
106 static FontDescription::GenericFamilyType convertGenericFamily(CSSValueID valueID)
109 case CSSValueWebkitBody:
110 return FontDescription::StandardFamily;
112 return FontDescription::SerifFamily;
113 case CSSValueSansSerif:
114 return FontDescription::SansSerifFamily;
115 case CSSValueCursive:
116 return FontDescription::CursiveFamily;
117 case CSSValueFantasy:
118 return FontDescription::FantasyFamily;
119 case CSSValueMonospace:
120 return FontDescription::MonospaceFamily;
121 case CSSValueWebkitPictograph:
122 return FontDescription::PictographFamily;
124 return FontDescription::NoFamily;
128 static bool convertFontFamilyName(StyleResolverState& state, CSSPrimitiveValue* primitiveValue,
129 FontDescription::GenericFamilyType& genericFamily, AtomicString& familyName)
131 if (primitiveValue->isString()) {
132 genericFamily = FontDescription::NoFamily;
133 familyName = AtomicString(primitiveValue->getStringValue());
134 } else if (state.document().settings()) {
135 genericFamily = convertGenericFamily(primitiveValue->getValueID());
136 familyName = state.fontBuilder().genericFontFamilyName(genericFamily);
139 return !familyName.isEmpty();
142 FontDescription::FamilyDescription StyleBuilderConverter::convertFontFamily(StyleResolverState& state, CSSValue* value)
144 ASSERT(value->isValueList());
146 FontDescription::FamilyDescription desc(FontDescription::NoFamily);
147 FontFamily* currFamily = nullptr;
149 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
150 CSSValue* item = i.value();
151 if (!item->isPrimitiveValue())
154 FontDescription::GenericFamilyType genericFamily = FontDescription::NoFamily;
155 AtomicString familyName;
157 if (!convertFontFamilyName(state, toCSSPrimitiveValue(item), genericFamily, familyName))
161 currFamily = &desc.family;
163 RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
164 currFamily->appendFamily(newFamily);
165 currFamily = newFamily.get();
168 currFamily->setFamily(familyName);
170 if (genericFamily != FontDescription::NoFamily)
171 desc.genericFamily = genericFamily;
177 PassRefPtr<FontFeatureSettings> StyleBuilderConverter::convertFontFeatureSettings(StyleResolverState& state, CSSValue* value)
179 if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueNormal)
180 return FontBuilder::initialFeatureSettings();
182 CSSValueList* list = toCSSValueList(value);
183 RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
184 int len = list->length();
185 for (int i = 0; i < len; ++i) {
186 CSSFontFeatureValue* feature = toCSSFontFeatureValue(list->item(i));
187 settings->append(FontFeature(feature->tag(), feature->value()));
192 class RedirectSetHasViewportUnits {
194 RedirectSetHasViewportUnits(RenderStyle* from, RenderStyle* to)
195 : m_from(from), m_to(to), m_hadViewportUnits(from->hasViewportUnits())
197 from->setHasViewportUnits(false);
199 ~RedirectSetHasViewportUnits()
201 m_to->setHasViewportUnits(m_from->hasViewportUnits());
202 m_from->setHasViewportUnits(m_hadViewportUnits);
207 bool m_hadViewportUnits;
210 static float computeFontSize(StyleResolverState& state, CSSPrimitiveValue* primitiveValue, const FontDescription::Size& parentSize)
212 RedirectSetHasViewportUnits redirect(state.parentStyle(), state.style());
214 CSSToLengthConversionData conversionData(state.parentStyle(), state.rootElementStyle(), state.document().renderView(), 1.0f, true);
215 if (primitiveValue->isLength())
216 return primitiveValue->computeLength<float>(conversionData);
217 if (primitiveValue->isCalculatedPercentageWithLength())
218 return primitiveValue->cssCalcValue()->toCalcValue(conversionData)->evaluate(parentSize.value);
220 ASSERT_NOT_REACHED();
224 FontDescription::Size StyleBuilderConverter::convertFontSize(StyleResolverState& state, CSSValue* value)
226 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
228 FontDescription::Size parentSize(0, 0.0f, false);
230 // FIXME: Find out when parentStyle could be 0?
231 if (state.parentStyle())
232 parentSize = state.parentFontDescription().size();
234 if (CSSValueID valueID = primitiveValue->getValueID()) {
236 case CSSValueXxSmall:
242 case CSSValueXxLarge:
243 case CSSValueWebkitXxxLarge:
244 return FontDescription::Size(FontSize::keywordSize(valueID), 0.0f, false);
246 return FontDescription::largerSize(parentSize);
247 case CSSValueSmaller:
248 return FontDescription::smallerSize(parentSize);
250 ASSERT_NOT_REACHED();
251 return FontBuilder::initialSize();
255 bool parentIsAbsoluteSize = state.parentFontDescription().isAbsoluteSize();
257 if (primitiveValue->isPercentage())
258 return FontDescription::Size(0, (primitiveValue->getFloatValue() * parentSize.value / 100.0f), parentIsAbsoluteSize);
260 return FontDescription::Size(0, computeFontSize(state, primitiveValue, parentSize), parentIsAbsoluteSize || !primitiveValue->isFontRelativeLength());
263 FontWeight StyleBuilderConverter::convertFontWeight(StyleResolverState& state, CSSValue* value)
265 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
266 switch (primitiveValue->getValueID()) {
268 return FontDescription::bolderWeight(state.parentStyle()->fontDescription().weight());
269 case CSSValueLighter:
270 return FontDescription::lighterWeight(state.parentStyle()->fontDescription().weight());
272 return *primitiveValue;
276 FontDescription::VariantLigatures StyleBuilderConverter::convertFontVariantLigatures(StyleResolverState&, CSSValue* value)
278 if (value->isValueList()) {
279 FontDescription::VariantLigatures ligatures;
280 CSSValueList* valueList = toCSSValueList(value);
281 for (size_t i = 0; i < valueList->length(); ++i) {
282 CSSValue* item = valueList->item(i);
283 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(item);
284 switch (primitiveValue->getValueID()) {
285 case CSSValueNoCommonLigatures:
286 ligatures.common = FontDescription::DisabledLigaturesState;
288 case CSSValueCommonLigatures:
289 ligatures.common = FontDescription::EnabledLigaturesState;
291 case CSSValueNoDiscretionaryLigatures:
292 ligatures.discretionary = FontDescription::DisabledLigaturesState;
294 case CSSValueDiscretionaryLigatures:
295 ligatures.discretionary = FontDescription::EnabledLigaturesState;
297 case CSSValueNoHistoricalLigatures:
298 ligatures.historical = FontDescription::DisabledLigaturesState;
300 case CSSValueHistoricalLigatures:
301 ligatures.historical = FontDescription::EnabledLigaturesState;
303 case CSSValueNoContextual:
304 ligatures.contextual = FontDescription::DisabledLigaturesState;
306 case CSSValueContextual:
307 ligatures.contextual = FontDescription::EnabledLigaturesState;
310 ASSERT_NOT_REACHED();
317 ASSERT_WITH_SECURITY_IMPLICATION(value->isPrimitiveValue());
318 ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNormal);
319 return FontDescription::VariantLigatures();
322 EGlyphOrientation StyleBuilderConverter::convertGlyphOrientation(StyleResolverState&, CSSValue* value)
324 if (!value->isPrimitiveValue())
327 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
328 if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_DEG)
331 float angle = fabsf(fmodf(primitiveValue->getFloatValue(), 360.0f));
333 if (angle <= 45.0f || angle > 315.0f)
335 if (angle > 45.0f && angle <= 135.0f)
337 if (angle > 135.0f && angle <= 225.0f)
342 GridAutoFlow StyleBuilderConverter::convertGridAutoFlow(StyleResolverState&, CSSValue* value)
344 CSSValueList* list = toCSSValueList(value);
346 ASSERT(list->length() >= 1);
347 CSSPrimitiveValue* first = toCSSPrimitiveValue(list->item(0));
348 CSSPrimitiveValue* second = list->length() == 2 ? toCSSPrimitiveValue(list->item(1)) : nullptr;
350 switch (first->getValueID()) {
353 if (second->getValueID() == CSSValueDense)
354 return AutoFlowRowDense;
355 return AutoFlowStackRow;
360 if (second->getValueID() == CSSValueDense)
361 return AutoFlowColumnDense;
362 return AutoFlowStackColumn;
364 return AutoFlowColumn;
366 if (second && second->getValueID() == CSSValueColumn)
367 return AutoFlowColumnDense;
368 return AutoFlowRowDense;
370 if (second && second->getValueID() == CSSValueColumn)
371 return AutoFlowStackColumn;
372 return AutoFlowStackRow;
374 ASSERT_NOT_REACHED();
375 return RenderStyle::initialGridAutoFlow();
379 GridPosition StyleBuilderConverter::convertGridPosition(StyleResolverState&, CSSValue* value)
381 // We accept the specification's grammar:
382 // 'auto' | [ <integer> || <custom-ident> ] | [ span && [ <integer> || <custom-ident> ] ] | <custom-ident>
384 GridPosition position;
386 if (value->isPrimitiveValue()) {
387 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
388 // We translate <custom-ident> to <string> during parsing as it
389 // makes handling it more simple.
390 if (primitiveValue->isString()) {
391 position.setNamedGridArea(primitiveValue->getStringValue());
395 ASSERT(primitiveValue->getValueID() == CSSValueAuto);
399 CSSValueList* values = toCSSValueList(value);
400 ASSERT(values->length());
402 bool isSpanPosition = false;
403 // The specification makes the <integer> optional, in which case it default to '1'.
404 int gridLineNumber = 1;
407 CSSValueListIterator it = values;
408 CSSPrimitiveValue* currentValue = toCSSPrimitiveValue(it.value());
409 if (currentValue->getValueID() == CSSValueSpan) {
410 isSpanPosition = true;
412 currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0;
415 if (currentValue && currentValue->isNumber()) {
416 gridLineNumber = currentValue->getIntValue();
418 currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0;
421 if (currentValue && currentValue->isString()) {
422 gridLineName = currentValue->getStringValue();
426 ASSERT(!it.hasMore());
428 position.setSpanPosition(gridLineNumber, gridLineName);
430 position.setExplicitPosition(gridLineNumber, gridLineName);
435 GridTrackSize StyleBuilderConverter::convertGridTrackSize(StyleResolverState& state, CSSValue* value)
437 if (value->isPrimitiveValue())
438 return GridTrackSize(convertGridTrackBreadth(state, toCSSPrimitiveValue(value)));
440 CSSFunctionValue* minmaxFunction = toCSSFunctionValue(value);
441 CSSValueList* arguments = minmaxFunction->arguments();
442 ASSERT_WITH_SECURITY_IMPLICATION(arguments->length() == 2);
443 GridLength minTrackBreadth(convertGridTrackBreadth(state, toCSSPrimitiveValue(arguments->item(0))));
444 GridLength maxTrackBreadth(convertGridTrackBreadth(state, toCSSPrimitiveValue(arguments->item(1))));
445 return GridTrackSize(minTrackBreadth, maxTrackBreadth);
448 bool StyleBuilderConverter::convertGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSizes, NamedGridLinesMap& namedGridLines, OrderedNamedGridLines& orderedNamedGridLines, StyleResolverState& state)
451 if (value->isPrimitiveValue()) {
452 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
453 return primitiveValue->getValueID() == CSSValueNone;
456 if (!value->isValueList())
459 size_t currentNamedGridLine = 0;
460 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
461 CSSValue* currValue = i.value();
462 if (currValue->isGridLineNamesValue()) {
463 CSSGridLineNamesValue* lineNamesValue = toCSSGridLineNamesValue(currValue);
464 for (CSSValueListIterator j = lineNamesValue; j.hasMore(); j.advance()) {
465 String namedGridLine = toCSSPrimitiveValue(j.value())->getStringValue();
466 NamedGridLinesMap::AddResult result = namedGridLines.add(namedGridLine, Vector<size_t>());
467 result.storedValue->value.append(currentNamedGridLine);
468 OrderedNamedGridLines::AddResult orderedInsertionResult = orderedNamedGridLines.add(currentNamedGridLine, Vector<String>());
469 orderedInsertionResult.storedValue->value.append(namedGridLine);
474 ++currentNamedGridLine;
475 trackSizes.append(convertGridTrackSize(state, currValue));
478 // The parser should have rejected any <track-list> without any <track-size> as
479 // this is not conformant to the syntax.
480 ASSERT(!trackSizes.isEmpty());
484 void StyleBuilderConverter::createImplicitNamedGridLinesFromGridArea(const NamedGridAreaMap& namedGridAreas, NamedGridLinesMap& namedGridLines, GridTrackSizingDirection direction)
486 for (const auto& namedGridAreaEntry : namedGridAreas) {
487 GridSpan areaSpan = direction == ForRows ? namedGridAreaEntry.value.rows : namedGridAreaEntry.value.columns;
489 NamedGridLinesMap::AddResult startResult = namedGridLines.add(namedGridAreaEntry.key + "-start", Vector<size_t>());
490 startResult.storedValue->value.append(areaSpan.resolvedInitialPosition.toInt());
491 std::sort(startResult.storedValue->value.begin(), startResult.storedValue->value.end());
494 NamedGridLinesMap::AddResult endResult = namedGridLines.add(namedGridAreaEntry.key + "-end", Vector<size_t>());
495 endResult.storedValue->value.append(areaSpan.resolvedFinalPosition.toInt() + 1);
496 std::sort(endResult.storedValue->value.begin(), endResult.storedValue->value.end());
501 Length StyleBuilderConverter::convertLength(StyleResolverState& state, CSSValue* value)
503 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
504 Length result = primitiveValue->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData());
505 result.setQuirk(primitiveValue->isQuirkValue());
509 Length StyleBuilderConverter::convertLengthOrAuto(StyleResolverState& state, CSSValue* value)
511 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
512 Length result = primitiveValue->convertToLength<FixedConversion | PercentConversion | AutoConversion>(state.cssToLengthConversionData());
513 result.setQuirk(primitiveValue->isQuirkValue());
517 Length StyleBuilderConverter::convertLengthSizing(StyleResolverState& state, CSSValue* value)
519 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
520 switch (primitiveValue->getValueID()) {
521 case CSSValueInvalid:
522 return convertLength(state, value);
523 case CSSValueIntrinsic:
524 return Length(Intrinsic);
525 case CSSValueMinIntrinsic:
526 return Length(MinIntrinsic);
527 case CSSValueWebkitMinContent:
528 return Length(MinContent);
529 case CSSValueWebkitMaxContent:
530 return Length(MaxContent);
531 case CSSValueWebkitFillAvailable:
532 return Length(FillAvailable);
533 case CSSValueWebkitFitContent:
534 return Length(FitContent);
538 ASSERT_NOT_REACHED();
543 Length StyleBuilderConverter::convertLengthMaxSizing(StyleResolverState& state, CSSValue* value)
545 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
546 if (primitiveValue->getValueID() == CSSValueNone)
547 return Length(MaxSizeNone);
548 return convertLengthSizing(state, value);
551 LengthPoint StyleBuilderConverter::convertLengthPoint(StyleResolverState& state, CSSValue* value)
553 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
554 Pair* pair = primitiveValue->getPairValue();
555 Length x = pair->first()->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData());
556 Length y = pair->second()->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData());
557 return LengthPoint(x, y);
560 LineBoxContain StyleBuilderConverter::convertLineBoxContain(StyleResolverState&, CSSValue* value)
562 if (value->isPrimitiveValue()) {
563 ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
564 return LineBoxContainNone;
567 return toCSSLineBoxContainValue(value)->value();
570 float StyleBuilderConverter::convertNumberOrPercentage(StyleResolverState& state, CSSValue* value)
572 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
573 ASSERT(primitiveValue->isNumber() || primitiveValue->isPercentage());
574 if (primitiveValue->isNumber())
575 return primitiveValue->getFloatValue();
576 return primitiveValue->getFloatValue() / 100.0f;
579 static float convertPerspectiveLength(StyleResolverState& state, CSSPrimitiveValue* primitiveValue)
581 return std::max(primitiveValue->computeLength<float>(state.cssToLengthConversionData()), 0.0f);
584 float StyleBuilderConverter::convertPerspective(StyleResolverState& state, CSSValue* value)
586 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
588 if (primitiveValue->getValueID() == CSSValueNone)
589 return RenderStyle::initialPerspective();
591 // CSSPropertyWebkitPerspective accepts unitless numbers.
592 if (primitiveValue->isNumber()) {
593 RefPtrWillBeRawPtr<CSSPrimitiveValue> px = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX);
594 return convertPerspectiveLength(state, px.get());
597 return convertPerspectiveLength(state, primitiveValue);
600 template <CSSValueID cssValueFor0, CSSValueID cssValueFor100>
601 static Length convertOriginLength(StyleResolverState& state, CSSPrimitiveValue* primitiveValue)
603 if (primitiveValue->isValueID()) {
604 switch (primitiveValue->getValueID()) {
606 return Length(0, Percent);
608 return Length(100, Percent);
610 return Length(50, Percent);
612 ASSERT_NOT_REACHED();
616 return StyleBuilderConverter::convertLength(state, primitiveValue);
619 LengthPoint StyleBuilderConverter::convertPerspectiveOrigin(StyleResolverState& state, CSSValue* value)
621 CSSValueList* list = toCSSValueList(value);
622 ASSERT(list->length() == 2);
624 CSSPrimitiveValue* primitiveValueX = toCSSPrimitiveValue(list->item(0));
625 CSSPrimitiveValue* primitiveValueY = toCSSPrimitiveValue(list->item(1));
628 convertOriginLength<CSSValueLeft, CSSValueRight>(state, primitiveValueX),
629 convertOriginLength<CSSValueTop, CSSValueBottom>(state, primitiveValueY)
633 EPaintOrder StyleBuilderConverter::convertPaintOrder(StyleResolverState&, CSSValue* cssPaintOrder)
635 if (cssPaintOrder->isValueList()) {
637 const CSSValueList& list = *toCSSValueList(cssPaintOrder);
638 for (size_t i = 0; i < list.length(); ++i) {
639 EPaintOrderType paintOrderType = PT_NONE;
640 switch (toCSSPrimitiveValue(list.item(i))->getValueID()) {
642 paintOrderType = PT_FILL;
645 paintOrderType = PT_STROKE;
647 case CSSValueMarkers:
648 paintOrderType = PT_MARKERS;
651 ASSERT_NOT_REACHED();
655 paintOrder |= (paintOrderType << kPaintOrderBitwidth*i);
657 return (EPaintOrder)paintOrder;
663 PassRefPtr<QuotesData> StyleBuilderConverter::convertQuotes(StyleResolverState&, CSSValue* value)
665 if (value->isValueList()) {
666 CSSValueList* list = toCSSValueList(value);
667 RefPtr<QuotesData> quotes = QuotesData::create();
668 for (size_t i = 0; i < list->length(); i += 2) {
669 CSSValue* first = list->item(i);
670 CSSValue* second = list->item(i + 1);
671 String startQuote = toCSSPrimitiveValue(first)->getStringValue();
672 String endQuote = toCSSPrimitiveValue(second)->getStringValue();
673 quotes->addPair(std::make_pair(startQuote, endQuote));
675 return quotes.release();
677 // FIXME: We should assert we're a primitive value with valueID = CSSValueNone
678 return QuotesData::create();
681 LengthSize StyleBuilderConverter::convertRadius(StyleResolverState& state, CSSValue* value)
683 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
684 Pair* pair = primitiveValue->getPairValue();
685 Length radiusWidth = pair->first()->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData());
686 Length radiusHeight = pair->second()->convertToLength<FixedConversion | PercentConversion>(state.cssToLengthConversionData());
687 float width = radiusWidth.value();
688 float height = radiusHeight.value();
689 ASSERT(width >= 0 && height >= 0);
690 if (width <= 0 || height <= 0)
691 return LengthSize(Length(0, Fixed), Length(0, Fixed));
692 return LengthSize(radiusWidth, radiusHeight);
695 PassRefPtr<ShadowList> StyleBuilderConverter::convertShadow(StyleResolverState& state, CSSValue* value)
697 if (value->isPrimitiveValue()) {
698 ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
699 return PassRefPtr<ShadowList>();
702 const CSSValueList* valueList = toCSSValueList(value);
703 size_t shadowCount = valueList->length();
704 ShadowDataVector shadows;
705 for (size_t i = 0; i < shadowCount; ++i) {
706 const CSSShadowValue* item = toCSSShadowValue(valueList->item(i));
707 float x = item->x->computeLength<float>(state.cssToLengthConversionData());
708 float y = item->y->computeLength<float>(state.cssToLengthConversionData());
709 float blur = item->blur ? item->blur->computeLength<float>(state.cssToLengthConversionData()) : 0;
710 float spread = item->spread ? item->spread->computeLength<float>(state.cssToLengthConversionData()) : 0;
711 ShadowStyle shadowStyle = item->style && item->style->getValueID() == CSSValueInset ? Inset : Normal;
714 color = convertColor(state, item->color.get());
716 color = state.style()->color();
717 shadows.append(ShadowData(FloatPoint(x, y), blur, spread, shadowStyle, color));
719 return ShadowList::adopt(shadows);
722 PassRefPtr<ShapeValue> StyleBuilderConverter::convertShapeValue(StyleResolverState& state, CSSValue* value)
724 if (value->isPrimitiveValue()) {
725 ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
729 if (value->isImageValue() || value->isImageGeneratorValue() || value->isImageSetValue())
730 return ShapeValue::createImageValue(state.styleImage(CSSPropertyShapeOutside, value));
732 RefPtr<BasicShape> shape;
733 CSSBoxType cssBox = BoxMissing;
734 CSSValueList* valueList = toCSSValueList(value);
735 for (unsigned i = 0; i < valueList->length(); ++i) {
736 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(valueList->item(i));
737 if (primitiveValue->isShape())
738 shape = basicShapeForValue(state, primitiveValue->getShapeValue());
740 cssBox = CSSBoxType(*primitiveValue);
744 return ShapeValue::createShapeValue(shape.release(), cssBox);
746 ASSERT(cssBox != BoxMissing);
747 return ShapeValue::createBoxShapeValue(cssBox);
750 float StyleBuilderConverter::convertSpacing(StyleResolverState& state, CSSValue* value)
752 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
753 if (primitiveValue->getValueID() == CSSValueNormal)
755 return primitiveValue->computeLength<float>(state.cssToLengthConversionData());
758 PassRefPtr<SVGLengthList> StyleBuilderConverter::convertStrokeDasharray(StyleResolverState&, CSSValue* value)
760 if (!value->isValueList()) {
761 return SVGRenderStyle::initialStrokeDashArray();
764 CSSValueList* dashes = toCSSValueList(value);
766 RefPtr<SVGLengthList> array = SVGLengthList::create();
767 size_t length = dashes->length();
768 for (size_t i = 0; i < length; ++i) {
769 CSSValue* currValue = dashes->item(i);
770 if (!currValue->isPrimitiveValue())
773 CSSPrimitiveValue* dash = toCSSPrimitiveValue(dashes->item(i));
774 array->append(SVGLength::fromCSSPrimitiveValue(dash));
777 return array.release();
780 StyleColor StyleBuilderConverter::convertStyleColor(StyleResolverState& state, CSSValue* value, bool forVisitedLink)
782 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
783 if (primitiveValue->getValueID() == CSSValueCurrentcolor)
784 return StyleColor::currentColor();
785 return state.document().textLinkColors().colorFromPrimitiveValue(primitiveValue, Color(), forVisitedLink);
788 Color StyleBuilderConverter::convertSVGColor(StyleResolverState& state, CSSValue* value)
790 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
791 if (primitiveValue->isRGBColor())
792 return primitiveValue->getRGBA32Value();
793 ASSERT(primitiveValue->getValueID() == CSSValueCurrentcolor);
794 return state.style()->color();
797 PassRefPtr<SVGLength> StyleBuilderConverter::convertSVGLength(StyleResolverState&, CSSValue* value)
799 return SVGLength::fromCSSPrimitiveValue(toCSSPrimitiveValue(value));
802 float StyleBuilderConverter::convertTextStrokeWidth(StyleResolverState& state, CSSValue* value)
804 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
805 if (primitiveValue->getValueID()) {
806 float multiplier = convertLineWidth<float>(state, value);
807 return CSSPrimitiveValue::create(multiplier / 48, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(state.cssToLengthConversionData());
809 return primitiveValue->computeLength<float>(state.cssToLengthConversionData());
812 TransformOrigin StyleBuilderConverter::convertTransformOrigin(StyleResolverState& state, CSSValue* value)
814 CSSValueList* list = toCSSValueList(value);
815 ASSERT(list->length() == 3);
817 CSSPrimitiveValue* primitiveValueX = toCSSPrimitiveValue(list->item(0));
818 CSSPrimitiveValue* primitiveValueY = toCSSPrimitiveValue(list->item(1));
819 CSSPrimitiveValue* primitiveValueZ = toCSSPrimitiveValue(list->item(2));
821 return TransformOrigin(
822 convertOriginLength<CSSValueLeft, CSSValueRight>(state, primitiveValueX),
823 convertOriginLength<CSSValueTop, CSSValueBottom>(state, primitiveValueY),
824 StyleBuilderConverter::convertComputedLength<float>(state, primitiveValueZ)