bool StyleBuilderConverter::convertGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSizes, NamedGridLinesMap& namedGridLines, OrderedNamedGridLines& orderedNamedGridLines, StyleResolverState& state) { // Handle 'none'. if (value->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); return primitiveValue->getValueID() == CSSValueNone; } if (!value->isValueList()) return false; size_t currentNamedGridLine = 0; for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { CSSValue* currValue = i.value(); if (currValue->isGridLineNamesValue()) { CSSGridLineNamesValue* lineNamesValue = toCSSGridLineNamesValue(currValue); for (CSSValueListIterator j = lineNamesValue; j.hasMore(); j.advance()) { String namedGridLine = toCSSPrimitiveValue(j.value())->getStringValue(); NamedGridLinesMap::AddResult result = namedGridLines.add(namedGridLine, Vector<size_t>()); result.storedValue->value.append(currentNamedGridLine); OrderedNamedGridLines::AddResult orderedInsertionResult = orderedNamedGridLines.add(currentNamedGridLine, Vector<String>()); orderedInsertionResult.storedValue->value.append(namedGridLine); } continue; } ++currentNamedGridLine; trackSizes.append(convertGridTrackSize(state, currValue)); } // The parser should have rejected any <track-list> without any <track-size> as // this is not conformant to the syntax. ASSERT(!trackSizes.isEmpty()); return true; }
GridPosition StyleBuilderConverter::convertGridPosition(StyleResolverState&, CSSValue* value) { // We accept the specification's grammar: // 'auto' | [ <integer> || <custom-ident> ] | [ span && [ <integer> || <custom-ident> ] ] | <custom-ident> GridPosition position; if (value->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); // We translate <custom-ident> to <string> during parsing as it // makes handling it more simple. if (primitiveValue->isString()) { position.setNamedGridArea(primitiveValue->getStringValue()); return position; } ASSERT(primitiveValue->getValueID() == CSSValueAuto); return position; } CSSValueList* values = toCSSValueList(value); ASSERT(values->length()); bool isSpanPosition = false; // The specification makes the <integer> optional, in which case it default to '1'. int gridLineNumber = 1; String gridLineName; CSSValueListIterator it = values; CSSPrimitiveValue* currentValue = toCSSPrimitiveValue(it.value()); if (currentValue->getValueID() == CSSValueSpan) { isSpanPosition = true; it.advance(); currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0; } if (currentValue && currentValue->isNumber()) { gridLineNumber = currentValue->getIntValue(); it.advance(); currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0; } if (currentValue && currentValue->isString()) { gridLineName = currentValue->getStringValue(); it.advance(); } ASSERT(!it.hasMore()); if (isSpanPosition) position.setSpanPosition(gridLineNumber, gridLineName); else position.setExplicitPosition(gridLineNumber, gridLineName); return position; }
// FIXME: I am not convinced FontBuilder needs to know anything about CSSValues. void FontBuilder::setFontFamilyValue(CSSValue* value, float effectiveZoom) { FontDescriptionChangeScope scope(this); if (!value->isValueList()) return; FontFamily& firstFamily = scope.fontDescription().firstFamily(); FontFamily* currFamily = 0; // Before mapping in a new font-family property, we should reset the generic family. bool oldFamilyUsedFixedDefaultSize = scope.fontDescription().useFixedDefaultSize(); scope.fontDescription().setGenericFamily(FontDescription::NoFamily); for (CSSValueListIterator i = value; i.hasMore(); i.advance()) { CSSValue* item = i.value(); if (!item->isPrimitiveValue()) continue; CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item); AtomicString face; Settings* settings = m_document->settings(); if (contentValue->isString()) { face = contentValue->getStringValue(); } else if (settings) { switch (contentValue->getValueID()) { case CSSValueWebkitBody: face = settings->standardFontFamily(); break; case CSSValueSerif: face = FontFamilyNames::webkit_serif; scope.fontDescription().setGenericFamily(FontDescription::SerifFamily); break; case CSSValueSansSerif: face = FontFamilyNames::webkit_sans_serif; scope.fontDescription().setGenericFamily(FontDescription::SansSerifFamily); break; case CSSValueCursive: face = FontFamilyNames::webkit_cursive; scope.fontDescription().setGenericFamily(FontDescription::CursiveFamily); break; case CSSValueFantasy: face = FontFamilyNames::webkit_fantasy; scope.fontDescription().setGenericFamily(FontDescription::FantasyFamily); break; case CSSValueMonospace: face = FontFamilyNames::webkit_monospace; scope.fontDescription().setGenericFamily(FontDescription::MonospaceFamily); break; case CSSValueWebkitPictograph: face = FontFamilyNames::webkit_pictograph; scope.fontDescription().setGenericFamily(FontDescription::PictographFamily); break; default: break; } } if (!face.isEmpty()) { if (!currFamily) { // Filling in the first family. firstFamily.setFamily(face); firstFamily.appendFamily(0); // Remove any inherited family-fallback list. currFamily = &firstFamily; scope.fontDescription().setIsSpecifiedFont(scope.fontDescription().genericFamily() == FontDescription::NoFamily); } else { RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create(); newFamily->setFamily(face); currFamily->appendFamily(newFamily); currFamily = newFamily.get(); } } } // We can't call useFixedDefaultSize() until all new font families have been added // If currFamily is non-zero then we set at least one family on this description. if (!currFamily) return; if (scope.fontDescription().keywordSize() && scope.fontDescription().useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize) setSize(scope.fontDescription(), effectiveZoom, FontSize::fontSizeForKeyword(m_document, CSSValueXxSmall + scope.fontDescription().keywordSize() - 1, !oldFamilyUsedFixedDefaultSize)); }
bool TransformBuilder::createTransformOperations(CSSValue* inValue, RenderStyle* style, RenderStyle* rootStyle, TransformOperations& outOperations) { if (!inValue || !inValue->isValueList()) { outOperations.clear(); return false; } float zoomFactor = style ? style->effectiveZoom() : 1; TransformOperations operations; for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) { CSSValue* currValue = i.value(); if (!currValue->isCSSTransformValue()) continue; CSSTransformValue* transformValue = static_cast<CSSTransformValue*>(i.value()); if (!transformValue->length()) continue; bool haveNonPrimitiveValue = false; for (unsigned j = 0; j < transformValue->length(); ++j) { if (!transformValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) { haveNonPrimitiveValue = true; break; } } if (haveNonPrimitiveValue) continue; CSSPrimitiveValue* firstValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(0)); switch (transformValue->operationType()) { case CSSTransformValue::ScaleTransformOperation: case CSSTransformValue::ScaleXTransformOperation: case CSSTransformValue::ScaleYTransformOperation: { double sx = 1.0; double sy = 1.0; if (transformValue->operationType() == CSSTransformValue::ScaleYTransformOperation) sy = firstValue->getDoubleValue(); else { sx = firstValue->getDoubleValue(); if (transformValue->operationType() != CSSTransformValue::ScaleXTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); sy = secondValue->getDoubleValue(); } else sy = sx; } } operations.operations().append(ScaleTransformOperation::create(sx, sy, 1.0, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::ScaleZTransformOperation: case CSSTransformValue::Scale3DTransformOperation: { double sx = 1.0; double sy = 1.0; double sz = 1.0; if (transformValue->operationType() == CSSTransformValue::ScaleZTransformOperation) sz = firstValue->getDoubleValue(); else if (transformValue->operationType() == CSSTransformValue::ScaleYTransformOperation) sy = firstValue->getDoubleValue(); else { sx = firstValue->getDoubleValue(); if (transformValue->operationType() != CSSTransformValue::ScaleXTransformOperation) { if (transformValue->length() > 2) { CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2)); sz = thirdValue->getDoubleValue(); } if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); sy = secondValue->getDoubleValue(); } else sy = sx; } } operations.operations().append(ScaleTransformOperation::create(sx, sy, sz, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::TranslateTransformOperation: case CSSTransformValue::TranslateXTransformOperation: case CSSTransformValue::TranslateYTransformOperation: { Length tx = Length(0, Fixed); Length ty = Length(0, Fixed); if (transformValue->operationType() == CSSTransformValue::TranslateYTransformOperation) ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); else { tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); if (transformValue->operationType() != CSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor); } } } if (tx.isUndefined() || ty.isUndefined()) return false; operations.operations().append(TranslateTransformOperation::create(tx, ty, Length(0, Fixed), getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::TranslateZTransformOperation: case CSSTransformValue::Translate3DTransformOperation: { Length tx = Length(0, Fixed); Length ty = Length(0, Fixed); Length tz = Length(0, Fixed); if (transformValue->operationType() == CSSTransformValue::TranslateZTransformOperation) tz = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); else if (transformValue->operationType() == CSSTransformValue::TranslateYTransformOperation) ty = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); else { tx = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); if (transformValue->operationType() != CSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 2) { CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2)); tz = convertToFloatLength(thirdValue, style, rootStyle, zoomFactor); } if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); ty = convertToFloatLength(secondValue, style, rootStyle, zoomFactor); } } } if (tx.isUndefined() || ty.isUndefined() || tz.isUndefined()) return false; operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::RotateTransformOperation: { double angle = firstValue->computeDegrees(); operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::RotateXTransformOperation: case CSSTransformValue::RotateYTransformOperation: case CSSTransformValue::RotateZTransformOperation: { double x = 0; double y = 0; double z = 0; double angle = firstValue->computeDegrees(); if (transformValue->operationType() == CSSTransformValue::RotateXTransformOperation) x = 1; else if (transformValue->operationType() == CSSTransformValue::RotateYTransformOperation) y = 1; else z = 1; operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::Rotate3DTransformOperation: { if (transformValue->length() < 4) break; CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2)); CSSPrimitiveValue* fourthValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(3)); double x = firstValue->getDoubleValue(); double y = secondValue->getDoubleValue(); double z = thirdValue->getDoubleValue(); double angle = fourthValue->computeDegrees(); operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::SkewTransformOperation: case CSSTransformValue::SkewXTransformOperation: case CSSTransformValue::SkewYTransformOperation: { double angleX = 0; double angleY = 0; double angle = firstValue->computeDegrees(); if (transformValue->operationType() == CSSTransformValue::SkewYTransformOperation) angleY = angle; else { angleX = angle; if (transformValue->operationType() == CSSTransformValue::SkewTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1)); angleY = secondValue->computeDegrees(); } } } operations.operations().append(SkewTransformOperation::create(angleX, angleY, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::MatrixTransformOperation: { if (transformValue->length() < 6) break; double a = firstValue->getDoubleValue(); double b = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue(); double c = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue(); double d = toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue(); double e = zoomFactor * toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue(); double f = zoomFactor * toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue(); operations.operations().append(MatrixTransformOperation::create(a, b, c, d, e, f)); break; } case CSSTransformValue::Matrix3DTransformOperation: { if (transformValue->length() < 16) break; TransformationMatrix matrix(toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(0))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(1))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(2))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(3))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(4))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(5))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(6))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(7))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(8))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(9))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(10))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(11))->getDoubleValue(), zoomFactor * toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(12))->getDoubleValue(), zoomFactor * toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(13))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(14))->getDoubleValue(), toCSSPrimitiveValue(transformValue->itemWithoutBoundsCheck(15))->getDoubleValue()); operations.operations().append(Matrix3DTransformOperation::create(matrix)); break; } case CSSTransformValue::PerspectiveTransformOperation: { Length p = Length(0, Fixed); if (firstValue->isLength()) p = convertToFloatLength(firstValue, style, rootStyle, zoomFactor); else { // This is a quirk that should go away when 3d transforms are finalized. double val = firstValue->getDoubleValue(); p = val >= 0 ? Length(clampToPositiveInteger(val), Fixed) : Length(Undefined); } if (p.isUndefined()) return false; operations.operations().append(PerspectiveTransformOperation::create(p)); break; } case CSSTransformValue::UnknownTransformOperation: ASSERT_NOT_REACHED(); break; } } outOperations = operations; return true; }
bool FilterOperationResolver::createFilterOperations(CSSValue* inValue, const CSSToLengthConversionData& unadjustedConversionData, FilterOperations& outOperations, StyleResolverState& state) { ASSERT(outOperations.isEmpty()); if (!inValue) return false; if (inValue->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inValue); if (primitiveValue->getValueID() == CSSValueNone) return true; } if (!inValue->isValueList()) return false; float zoomFactor = unadjustedConversionData.zoom() * state.elementStyleResources().deviceScaleFactor(); const CSSToLengthConversionData& conversionData = unadjustedConversionData.copyWithAdjustedZoom(zoomFactor); FilterOperations operations; for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) { CSSValue* currValue = i.value(); if (!currValue->isFilterValue()) continue; CSSFilterValue* filterValue = toCSSFilterValue(i.value()); FilterOperation::OperationType operationType = filterOperationForType(filterValue->operationType()); if (operationType == FilterOperation::VALIDATED_CUSTOM) { // ValidatedCustomFilterOperation is not supposed to end up in the RenderStyle. ASSERT_NOT_REACHED(); continue; } if (operationType == FilterOperation::CUSTOM) { RefPtr<CustomFilterOperation> operation = createCustomFilterOperation(filterValue, state); if (!operation) return false; operations.operations().append(operation); continue; } if (operationType == FilterOperation::REFERENCE) { if (filterValue->length() != 1) continue; CSSValue* argument = filterValue->itemWithoutBoundsCheck(0); if (!argument->isSVGDocumentValue()) continue; CSSSVGDocumentValue* svgDocumentValue = toCSSSVGDocumentValue(argument); KURL url = state.document().completeURL(svgDocumentValue->url()); RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(svgDocumentValue->url(), url.fragmentIdentifier()); if (SVGURIReference::isExternalURIReference(svgDocumentValue->url(), state.document())) { if (!svgDocumentValue->loadRequested()) state.elementStyleResources().addPendingSVGDocument(operation.get(), svgDocumentValue); else if (svgDocumentValue->cachedSVGDocument()) ReferenceFilterBuilder::setDocumentResourceReference(operation.get(), adoptPtr(new DocumentResourceReference(svgDocumentValue->cachedSVGDocument()))); } operations.operations().append(operation); continue; } // Check that all parameters are primitive values, with the // exception of drop shadow which has a CSSShadowValue parameter. if (operationType != FilterOperation::DROP_SHADOW) { bool haveNonPrimitiveValue = false; for (unsigned j = 0; j < filterValue->length(); ++j) { if (!filterValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) { haveNonPrimitiveValue = true; break; } } if (haveNonPrimitiveValue) continue; } CSSPrimitiveValue* firstValue = filterValue->length() && filterValue->itemWithoutBoundsCheck(0)->isPrimitiveValue() ? toCSSPrimitiveValue(filterValue->itemWithoutBoundsCheck(0)) : 0; switch (filterValue->operationType()) { case CSSFilterValue::GrayscaleFilterOperation: case CSSFilterValue::SepiaFilterOperation: case CSSFilterValue::SaturateFilterOperation: { double amount = 1; if (filterValue->length() == 1) { amount = firstValue->getDoubleValue(); if (firstValue->isPercentage()) amount /= 100; } operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType)); break; } case CSSFilterValue::HueRotateFilterOperation: { double angle = 0; if (filterValue->length() == 1) angle = firstValue->computeDegrees(); operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType)); break; } case CSSFilterValue::InvertFilterOperation: case CSSFilterValue::BrightnessFilterOperation: case CSSFilterValue::ContrastFilterOperation: case CSSFilterValue::OpacityFilterOperation: { double amount = (filterValue->operationType() == CSSFilterValue::BrightnessFilterOperation) ? 0 : 1; if (filterValue->length() == 1) { amount = firstValue->getDoubleValue(); if (firstValue->isPercentage()) amount /= 100; } operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType)); break; } case CSSFilterValue::BlurFilterOperation: { Length stdDeviation = Length(0, Fixed); if (filterValue->length() >= 1) stdDeviation = firstValue->convertToLength<FixedConversion | PercentConversion>(conversionData); if (stdDeviation.isUndefined()) return false; operations.operations().append(BlurFilterOperation::create(stdDeviation)); break; } case CSSFilterValue::DropShadowFilterOperation: { if (filterValue->length() != 1) return false; CSSValue* cssValue = filterValue->itemWithoutBoundsCheck(0); if (!cssValue->isShadowValue()) continue; CSSShadowValue* item = toCSSShadowValue(cssValue); IntPoint location(item->x->computeLength<int>(conversionData), item->y->computeLength<int>(conversionData)); int blur = item->blur ? item->blur->computeLength<int>(conversionData) : 0; Color shadowColor; if (item->color) shadowColor = state.document().textLinkColors().colorFromPrimitiveValue(item->color.get(), state.style()->color()); operations.operations().append(DropShadowFilterOperation::create(location, blur, shadowColor.isValid() ? shadowColor : Color::transparent)); break; } case CSSFilterValue::UnknownFilterOperation: default: ASSERT_NOT_REACHED(); break; } } outOperations = operations; return true; }
bool TransformBuilder::createTransformOperations(CSSValue* inValue, const CSSToLengthConversionData& conversionData, TransformOperations& outOperations) { if (!inValue || !inValue->isValueList()) { outOperations.clear(); return false; } TransformOperations operations; for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) { CSSValue* currValue = i.value(); if (!currValue->isTransformValue()) continue; CSSTransformValue* transformValue = toCSSTransformValue(i.value()); if (!transformValue->length()) continue; bool haveNonPrimitiveValue = false; for (unsigned j = 0; j < transformValue->length(); ++j) { if (!transformValue->item(j)->isPrimitiveValue()) { haveNonPrimitiveValue = true; break; } } if (haveNonPrimitiveValue) continue; CSSPrimitiveValue* firstValue = toCSSPrimitiveValue(transformValue->item(0)); switch (transformValue->operationType()) { case CSSTransformValue::ScaleTransformOperation: case CSSTransformValue::ScaleXTransformOperation: case CSSTransformValue::ScaleYTransformOperation: { double sx = 1.0; double sy = 1.0; if (transformValue->operationType() == CSSTransformValue::ScaleYTransformOperation) sy = firstValue->getDoubleValue(); else { sx = firstValue->getDoubleValue(); if (transformValue->operationType() != CSSTransformValue::ScaleXTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); sy = secondValue->getDoubleValue(); } else sy = sx; } } operations.operations().append(ScaleTransformOperation::create(sx, sy, 1.0, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::ScaleZTransformOperation: case CSSTransformValue::Scale3DTransformOperation: { double sx = 1.0; double sy = 1.0; double sz = 1.0; if (transformValue->operationType() == CSSTransformValue::ScaleZTransformOperation) sz = firstValue->getDoubleValue(); else if (transformValue->operationType() == CSSTransformValue::ScaleYTransformOperation) sy = firstValue->getDoubleValue(); else { sx = firstValue->getDoubleValue(); if (transformValue->operationType() != CSSTransformValue::ScaleXTransformOperation) { if (transformValue->length() > 2) { CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->item(2)); sz = thirdValue->getDoubleValue(); } if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); sy = secondValue->getDoubleValue(); } else sy = sx; } } operations.operations().append(ScaleTransformOperation::create(sx, sy, sz, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::TranslateTransformOperation: case CSSTransformValue::TranslateXTransformOperation: case CSSTransformValue::TranslateYTransformOperation: { Length tx = Length(0, Fixed); Length ty = Length(0, Fixed); if (transformValue->operationType() == CSSTransformValue::TranslateYTransformOperation) ty = convertToFloatLength(firstValue, conversionData); else { tx = convertToFloatLength(firstValue, conversionData); if (transformValue->operationType() != CSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); ty = convertToFloatLength(secondValue, conversionData); } } } operations.operations().append(TranslateTransformOperation::create(tx, ty, 0, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::TranslateZTransformOperation: case CSSTransformValue::Translate3DTransformOperation: { Length tx = Length(0, Fixed); Length ty = Length(0, Fixed); double tz = 0; if (transformValue->operationType() == CSSTransformValue::TranslateZTransformOperation) tz = firstValue->computeLength<double>(conversionData); else if (transformValue->operationType() == CSSTransformValue::TranslateYTransformOperation) ty = convertToFloatLength(firstValue, conversionData); else { tx = convertToFloatLength(firstValue, conversionData); if (transformValue->operationType() != CSSTransformValue::TranslateXTransformOperation) { if (transformValue->length() > 2) { CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->item(2)); tz = thirdValue->computeLength<double>(conversionData); } if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); ty = convertToFloatLength(secondValue, conversionData); } } } operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::RotateTransformOperation: { double angle = firstValue->computeDegrees(); operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::RotateXTransformOperation: case CSSTransformValue::RotateYTransformOperation: case CSSTransformValue::RotateZTransformOperation: { double x = 0; double y = 0; double z = 0; double angle = firstValue->computeDegrees(); if (transformValue->operationType() == CSSTransformValue::RotateXTransformOperation) x = 1; else if (transformValue->operationType() == CSSTransformValue::RotateYTransformOperation) y = 1; else z = 1; operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::Rotate3DTransformOperation: { if (transformValue->length() < 4) break; CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); CSSPrimitiveValue* thirdValue = toCSSPrimitiveValue(transformValue->item(2)); CSSPrimitiveValue* fourthValue = toCSSPrimitiveValue(transformValue->item(3)); double x = firstValue->getDoubleValue(); double y = secondValue->getDoubleValue(); double z = thirdValue->getDoubleValue(); double angle = fourthValue->computeDegrees(); operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::SkewTransformOperation: case CSSTransformValue::SkewXTransformOperation: case CSSTransformValue::SkewYTransformOperation: { double angleX = 0; double angleY = 0; double angle = firstValue->computeDegrees(); if (transformValue->operationType() == CSSTransformValue::SkewYTransformOperation) angleY = angle; else { angleX = angle; if (transformValue->operationType() == CSSTransformValue::SkewTransformOperation) { if (transformValue->length() > 1) { CSSPrimitiveValue* secondValue = toCSSPrimitiveValue(transformValue->item(1)); angleY = secondValue->computeDegrees(); } } } operations.operations().append(SkewTransformOperation::create(angleX, angleY, getTransformOperationType(transformValue->operationType()))); break; } case CSSTransformValue::MatrixTransformOperation: { if (transformValue->length() < 6) break; double a = firstValue->getDoubleValue(); double b = toCSSPrimitiveValue(transformValue->item(1))->getDoubleValue(); double c = toCSSPrimitiveValue(transformValue->item(2))->getDoubleValue(); double d = toCSSPrimitiveValue(transformValue->item(3))->getDoubleValue(); double e = toCSSPrimitiveValue(transformValue->item(4))->getDoubleValue(); double f = toCSSPrimitiveValue(transformValue->item(5))->getDoubleValue(); operations.operations().append(MatrixTransformOperation::create(a, b, c, d, e, f)); break; } case CSSTransformValue::Matrix3DTransformOperation: { if (transformValue->length() < 16) break; TransformationMatrix matrix(toCSSPrimitiveValue(transformValue->item(0))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(1))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(2))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(3))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(4))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(5))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(6))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(7))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(8))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(9))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(10))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(11))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(12))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(13))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(14))->getDoubleValue(), toCSSPrimitiveValue(transformValue->item(15))->getDoubleValue()); operations.operations().append(Matrix3DTransformOperation::create(matrix)); break; } case CSSTransformValue::PerspectiveTransformOperation: { double p; if (firstValue->isLength()) p = firstValue->computeLength<double>(conversionData); else { // This is a quirk that should go away when 3d transforms are finalized. double val = firstValue->getDoubleValue(); if (val < 0) return false; p = clampToPositiveInteger(val); } operations.operations().append(PerspectiveTransformOperation::create(p)); break; } case CSSTransformValue::UnknownTransformOperation: ASSERT_NOT_REACHED(); break; } } outOperations = operations; return true; }