void CSSToStyleMap::mapNinePieceImage(StyleResolverState& state, CSSPropertyID property, CSSValue* value, NinePieceImage& image) { // If we're not a value list, then we are "none" and don't need to alter the empty image at all. if (!value || !value->isValueList()) return; // Retrieve the border image value. CSSValueList* borderImage = toCSSValueList(value); // Set the image (this kicks off the load). CSSPropertyID imageProperty; if (property == CSSPropertyWebkitBorderImage) imageProperty = CSSPropertyBorderImageSource; else if (property == CSSPropertyWebkitMaskBoxImage) imageProperty = CSSPropertyWebkitMaskBoxImageSource; else imageProperty = property; for (unsigned i = 0 ; i < borderImage->length() ; ++i) { CSSValue* current = borderImage->item(i); if (current->isImageValue() || current->isImageGeneratorValue() || current->isImageSetValue()) image.setImage(state.styleImage(imageProperty, current)); else if (current->isBorderImageSliceValue()) mapNinePieceImageSlice(state, current, image); else if (current->isValueList()) { CSSValueList* slashList = toCSSValueList(current); size_t length = slashList->length(); // Map in the image slices. if (length && slashList->item(0)->isBorderImageSliceValue()) mapNinePieceImageSlice(state, slashList->item(0), image); // Map in the border slices. if (length > 1) image.setBorderSlices(mapNinePieceImageQuad(state, slashList->item(1))); // Map in the outset. if (length > 2) image.setOutset(mapNinePieceImageQuad(state, slashList->item(2))); } else if (current->isPrimitiveValue()) { // Set the appropriate rules for stretch/round/repeat of the slices. mapNinePieceImageRepeat(state, current, image); } } if (property == CSSPropertyWebkitBorderImage) { // We have to preserve the legacy behavior of -webkit-border-image and make the border slices // also set the border widths. We don't need to worry about percentages, since we don't even support // those on real borders yet. if (image.borderSlices().top().isLength() && image.borderSlices().top().length().isFixed()) state.style()->setBorderTopWidth(image.borderSlices().top().length().value()); if (image.borderSlices().right().isLength() && image.borderSlices().right().length().isFixed()) state.style()->setBorderRightWidth(image.borderSlices().right().length().value()); if (image.borderSlices().bottom().isLength() && image.borderSlices().bottom().length().isFixed()) state.style()->setBorderBottomWidth(image.borderSlices().bottom().length().value()); if (image.borderSlices().left().isLength() && image.borderSlices().left().length().isFixed()) state.style()->setBorderLeftWidth(image.borderSlices().left().length().value()); } }
PassRefPtr<CSSFontFace> FontFace::createCSSFontFace(Document* document) { RefPtr<CSSFontFace> cssFontFace = CSSFontFace::create(this); // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace. CSSValueList* srcList = toCSSValueList(m_src.get()); int srcLength = srcList->length(); bool foundSVGFont = false; for (int i = 0; i < srcLength; i++) { // An item in the list either specifies a string (local font name) or a URL (remote font to download). CSSFontFaceSrcValue* item = toCSSFontFaceSrcValue(srcList->itemWithoutBoundsCheck(i)); OwnPtr<CSSFontFaceSource> source; #if ENABLE(SVG_FONTS) foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement(); #endif if (!item->isLocal()) { Settings* settings = document ? document->frame() ? document->frame()->settings() : 0 : 0; bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled()); if (allowDownloading && item->isSupportedFormat() && document) { FontResource* fetched = item->fetch(document); if (fetched) { source = adoptPtr(new CSSFontFaceSource(item->resource(), fetched)); #if ENABLE(SVG_FONTS) if (foundSVGFont) source->setHasExternalSVGFont(true); #endif } } } else { source = adoptPtr(new CSSFontFaceSource(item->resource())); } if (source) { #if ENABLE(SVG_FONTS) source->setSVGFontFaceElement(item->svgFontFaceElement()); #endif cssFontFace->addSource(source.release()); } } if (CSSValueList* rangeList = toCSSValueList(m_unicodeRange.get())) { unsigned numRanges = rangeList->length(); for (unsigned i = 0; i < numRanges; i++) { CSSUnicodeRangeValue* range = toCSSUnicodeRangeValue(rangeList->itemWithoutBoundsCheck(i)); cssFontFace->ranges().add(range->from(), range->to()); } } return cssFontFace; }
bool ShadowStyleInterpolation::usesDefaultStyleInterpolation(const CSSValue& start, const CSSValue& end) { if (start.isValueList() && end.isValueList() && toCSSValueList(start).length() == toCSSValueList(end).length()) { const CSSValueList* startList = toCSSValueList(&start); const CSSValueList* endList = toCSSValueList(&end); for (size_t i = 0; i < toCSSValueList(start).length(); i++) { if (startList->item(i)->isShadowValue() && endList->item(i)->isShadowValue() && toCSSShadowValue(startList->item(i))->style != toCSSShadowValue(endList->item(i))->style) return true; } } return false; }
PassRefPtr<FilterStyleInterpolation::FilterListStyleInterpolation> FilterStyleInterpolation::maybeCreateList(const CSSValue& start, const CSSValue& end, CSSPropertyID property) { if (start.isCSSWideKeyword() || end.isCSSWideKeyword()) return nullptr; ASSERT(start.isValueList() || toCSSPrimitiveValue(start).getValueID() == CSSValueNone); ASSERT(end.isValueList() || toCSSPrimitiveValue(end).getValueID() == CSSValueNone); if (!start.isValueList() && !end.isValueList()) return nullptr; return maybeCreateFromList( start.isValueList() ? toCSSValueList(start) : *CSSValueList::createSpaceSeparated(), end.isValueList() ? toCSSValueList(end) : *CSSValueList::createSpaceSeparated(), property); }
PassRefPtr<CSSValue> CSSValue::cloneForCSSOM() const { switch (classType()) { case PrimitiveClass: return toCSSPrimitiveValue(this)->cloneForCSSOM(); case ValueListClass: return toCSSValueList(this)->cloneForCSSOM(); case ImageClass: case CursorImageClass: return toCSSImageValue(this)->cloneForCSSOM(); #if ENABLE(CSS_FILTERS) case WebKitCSSFilterClass: return toWebKitCSSFilterValue(this)->cloneForCSSOM(); #endif case WebKitCSSTransformClass: return toWebKitCSSTransformValue(this)->cloneForCSSOM(); #if ENABLE(CSS_IMAGE_SET) case ImageSetClass: return toCSSImageSetValue(this)->cloneForCSSOM(); #endif #if ENABLE(SVG) case SVGColorClass: return toSVGColor(this)->cloneForCSSOM(); case SVGPaintClass: return toSVGPaint(this)->cloneForCSSOM(); #endif default: ASSERT(!isSubtypeExposedToCSSOM()); return TextCloneCSSValue::create(classType(), cssText()); } }
InterpolationValue CSSTransformInterpolationType::maybeConvertValue( const CSSValue& value, const StyleResolverState& state, ConversionCheckers& conversionCheckers) const { if (value.isValueList()) { CSSLengthArray lengthArray; for (const CSSValue* item : toCSSValueList(value)) { const CSSFunctionValue& transformFunction = toCSSFunctionValue(*item); if (transformFunction.functionType() == CSSValueMatrix || transformFunction.functionType() == CSSValueMatrix3d) { lengthArray.typeFlags.set(CSSPrimitiveValue::UnitTypePixels); continue; } for (const CSSValue* argument : transformFunction) { const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(*argument); if (!primitiveValue.isLength()) continue; primitiveValue.accumulateLengthArray(lengthArray); } } std::unique_ptr<InterpolationType::ConversionChecker> lengthUnitsChecker = LengthUnitsChecker::maybeCreate(std::move(lengthArray), state); if (lengthUnitsChecker) conversionCheckers.append(std::move(lengthUnitsChecker)); } TransformOperations transform; TransformBuilder::createTransformOperations( value, state.cssToLengthConversionData(), transform); return convertTransform(std::move(transform)); }
bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSValue& value) { switch (value.cssValueType()) { case CSSValue::CSS_INHERIT: return true; case CSSValue::CSS_PRIMITIVE_VALUE: return interpolationRequiresStyleResolve(toCSSPrimitiveValue(value)); case CSSValue::CSS_VALUE_LIST: return interpolationRequiresStyleResolve(toCSSValueList(value)); case CSSValue::CSS_CUSTOM: if (value.isImageValue()) return interpolationRequiresStyleResolve(toCSSImageValue(value)); if (value.isShadowValue()) return interpolationRequiresStyleResolve(toCSSShadowValue(value)); if (value.isSVGDocumentValue()) return interpolationRequiresStyleResolve(toCSSSVGDocumentValue(value)); // FIXME: consider other custom types. return true; case CSSValue::CSS_INITIAL: // FIXME: should not require resolving styles for initial. return true; default: ASSERT_NOT_REACHED(); return true; } }
void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextEmphasisStyle(StyleResolverState& state, CSSValue* value) { if (value->isValueList()) { CSSValueList* list = toCSSValueList(value); ASSERT(list->length() == 2); for (unsigned i = 0; i < 2; ++i) { CSSPrimitiveValue* value = toCSSPrimitiveValue(list->item(i)); if (value->getValueID() == CSSValueFilled || value->getValueID() == CSSValueOpen) state.style()->setTextEmphasisFill(*value); else state.style()->setTextEmphasisMark(*value); } state.style()->setTextEmphasisCustomMark(nullAtom); return; } CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value); if (primitiveValue->isString()) { state.style()->setTextEmphasisFill(TextEmphasisFillFilled); state.style()->setTextEmphasisMark(TextEmphasisMarkCustom); state.style()->setTextEmphasisCustomMark(AtomicString(primitiveValue->getStringValue())); return; } state.style()->setTextEmphasisCustomMark(nullAtom); if (primitiveValue->getValueID() == CSSValueFilled || primitiveValue->getValueID() == CSSValueOpen) { state.style()->setTextEmphasisFill(*primitiveValue); state.style()->setTextEmphasisMark(TextEmphasisMarkAuto); } else { state.style()->setTextEmphasisFill(TextEmphasisFillFilled); state.style()->setTextEmphasisMark(*primitiveValue); } }
bool DeferredLegacyStyleInterpolation::interpolationRequiresStyleResolve(const CSSValue& value) { // FIXME: should not require resolving styles for inherit/initial/unset. if (value.isCSSWideKeyword()) return true; if (value.isBasicShapeCircleValue()) return interpolationRequiresStyleResolve(toCSSBasicShapeCircleValue(value)); if (value.isBasicShapeEllipseValue()) return interpolationRequiresStyleResolve(toCSSBasicShapeEllipseValue(value)); if (value.isBasicShapePolygonValue()) return interpolationRequiresStyleResolve(toCSSBasicShapePolygonValue(value)); if (value.isBasicShapeInsetValue()) return interpolationRequiresStyleResolve(toCSSBasicShapeInsetValue(value)); if (value.isPrimitiveValue()) return interpolationRequiresStyleResolve(toCSSPrimitiveValue(value)); if (value.isQuadValue()) return interpolationRequiresStyleResolve(toCSSQuadValue(value)); if (value.isValueList()) return interpolationRequiresStyleResolve(toCSSValueList(value)); if (value.isValuePair()) return interpolationRequiresStyleResolve(toCSSValuePair(value)); if (value.isImageValue()) return interpolationRequiresStyleResolve(toCSSImageValue(value)); if (value.isShadowValue()) return interpolationRequiresStyleResolve(toCSSShadowValue(value)); if (value.isSVGDocumentValue()) return interpolationRequiresStyleResolve(toCSSSVGDocumentValue(value)); // FIXME: consider other custom types. return true; }
InterpolationValue CSSFilterListInterpolationType::maybeConvertValue( const CSSValue& value, const StyleResolverState&, ConversionCheckers&) const { if (value.isIdentifierValue() && toCSSIdentifierValue(value).getValueID() == CSSValueNone) return InterpolationValue(InterpolableList::create(0), NonInterpolableList::create()); if (!value.isBaseValueList()) return nullptr; const CSSValueList& list = toCSSValueList(value); size_t length = list.length(); std::unique_ptr<InterpolableList> interpolableList = InterpolableList::create(length); Vector<RefPtr<NonInterpolableValue>> nonInterpolableValues(length); for (size_t i = 0; i < length; i++) { InterpolationValue itemResult = FilterInterpolationFunctions::maybeConvertCSSFilter(list.item(i)); if (!itemResult) return nullptr; interpolableList->set(i, std::move(itemResult.interpolableValue)); nonInterpolableValues[i] = itemResult.nonInterpolableValue.release(); } return InterpolationValue( std::move(interpolableList), NonInterpolableList::create(std::move(nonInterpolableValues))); }
TEST(CSSPropertyParserTest, GridTrackLimits) { struct { const CSSPropertyID propertyID; const char* input; const size_t output; } testCases[] = { {CSSPropertyGridTemplateColumns, "repeat(999999, 20px)", 999999}, {CSSPropertyGridTemplateRows, "repeat(999999, 20px)", 999999}, {CSSPropertyGridTemplateColumns, "repeat(1000000, 10%)", 1000000}, {CSSPropertyGridTemplateRows, "repeat(1000000, 10%)", 1000000}, {CSSPropertyGridTemplateColumns, "repeat(1000000, (first) min-content (last))", 1000000}, {CSSPropertyGridTemplateRows, "repeat(1000000, (first) min-content (last))", 1000000}, {CSSPropertyGridTemplateColumns, "repeat(1000001, auto)", 1000000}, {CSSPropertyGridTemplateRows, "repeat(1000001, auto)", 1000000}, {CSSPropertyGridTemplateColumns, "repeat(400000, 2em minmax(10px, max-content) 0.5fr)", 999999}, {CSSPropertyGridTemplateRows, "repeat(400000, 2em minmax(10px, max-content) 0.5fr)", 999999}, {CSSPropertyGridTemplateColumns, "repeat(600000, (first) 3vh 10% 2fr (nav) 10px auto 1fr 6em (last))", 999999}, {CSSPropertyGridTemplateRows, "repeat(600000, (first) 3vh 10% 2fr (nav) 10px auto 1fr 6em (last))", 999999}, {CSSPropertyGridTemplateColumns, "repeat(100000000000000000000, 10% 1fr)", 1000000}, {CSSPropertyGridTemplateRows, "repeat(100000000000000000000, 10% 1fr)", 1000000}, {CSSPropertyGridTemplateColumns, "repeat(100000000000000000000, 10% 5em 1fr auto auto 15px min-content)", 999999}, {CSSPropertyGridTemplateRows, "repeat(100000000000000000000, 10% 5em 1fr auto auto 15px min-content)", 999999}, }; for (unsigned i = 0; i < WTF_ARRAY_LENGTH(testCases); ++i) { RefPtrWillBeRawPtr<CSSValue> value = CSSParser::parseSingleValue(testCases[i].propertyID, testCases[i].input); ASSERT_TRUE(value); ASSERT_TRUE(value->isValueList()); EXPECT_EQ(computeNumberOfTracks(toCSSValueList(value.get())), testCases[i].output); } }
void FontFace::initCSSFontFace(Document* document, PassRefPtrWillBeRawPtr<CSSValue> src) { m_cssFontFace = createCSSFontFace(this, m_unicodeRange.get()); if (m_error) return; // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace. ASSERT(src); ASSERT(src->isValueList()); CSSValueList* srcList = toCSSValueList(src.get()); int srcLength = srcList->length(); for (int i = 0; i < srcLength; i++) { // An item in the list either specifies a string (local font name) or a URL (remote font to download). CSSFontFaceSrcValue* item = toCSSFontFaceSrcValue(srcList->item(i)); OwnPtrWillBeRawPtr<CSSFontFaceSource> source = nullptr; if (!item->isLocal()) { const Settings* settings = document ? document->settings() : nullptr; bool allowDownloading = settings && settings->downloadableBinaryFontsEnabled(); if (allowDownloading && item->isSupportedFormat() && document) { FontResource* fetched = item->fetch(document); if (fetched) { FontLoader* fontLoader = document->styleEngine().fontSelector()->fontLoader(); source = adoptPtrWillBeNoop(new RemoteFontFaceSource(fetched, fontLoader)); } } } else { source = adoptPtrWillBeNoop(new LocalFontFaceSource(item->resource())); } if (source) m_cssFontFace->addSource(source.release()); } }
void StyleBuilderFunctions::applyValueCSSPropertyMotionRotation(StyleResolverState& state, CSSValue* value) { float rotation = 0; MotionRotationType rotationType = MotionRotationFixed; ASSERT(value->isValueList()); CSSValueList* list = toCSSValueList(value); int len = list->length(); for (int i = 0; i < len; i++) { CSSValue* item = list->item(i); ASSERT(item->isPrimitiveValue()); CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(item); if (primitiveValue->getValueID() == CSSValueAuto) { rotationType = MotionRotationAuto; } else if (primitiveValue->getValueID() == CSSValueReverse) { rotationType = MotionRotationAuto; rotation += 180; } else { rotation += primitiveValue->computeDegrees(); } } state.style()->setMotionRotation(rotation); state.style()->setMotionRotationType(rotationType); }
PassRefPtr<ShadowList> StyleBuilderConverter::convertShadow(StyleResolverState& state, CSSValue* value) { if (value->isPrimitiveValue()) { ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone); return PassRefPtr<ShadowList>(); } const CSSValueList* valueList = toCSSValueList(value); size_t shadowCount = valueList->length(); ShadowDataVector shadows; for (size_t i = 0; i < shadowCount; ++i) { const CSSShadowValue* item = toCSSShadowValue(valueList->item(i)); float x = item->x->computeLength<float>(state.cssToLengthConversionData()); float y = item->y->computeLength<float>(state.cssToLengthConversionData()); float blur = item->blur ? item->blur->computeLength<float>(state.cssToLengthConversionData()) : 0; float spread = item->spread ? item->spread->computeLength<float>(state.cssToLengthConversionData()) : 0; ShadowStyle shadowStyle = item->style && item->style->getValueID() == CSSValueInset ? Inset : Normal; Color color; if (item->color) color = convertColor(state, item->color.get()); else color = state.style()->color(); shadows.append(ShadowData(FloatPoint(x, y), blur, spread, shadowStyle, color)); } return ShadowList::adopt(shadows); }
void FontBuilder::setFontVariantLigaturesValue(CSSValue* value) { FontDescriptionChangeScope scope(this); FontDescription::LigaturesState commonLigaturesState = FontDescription::NormalLigaturesState; FontDescription::LigaturesState discretionaryLigaturesState = FontDescription::NormalLigaturesState; FontDescription::LigaturesState historicalLigaturesState = FontDescription::NormalLigaturesState; FontDescription::LigaturesState contextualLigaturesState = FontDescription::NormalLigaturesState; if (value->isValueList()) { CSSValueList* valueList = toCSSValueList(value); for (size_t i = 0; i < valueList->length(); ++i) { CSSValue* item = valueList->itemWithoutBoundsCheck(i); ASSERT(item->isPrimitiveValue()); if (item->isPrimitiveValue()) { CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(item); switch (primitiveValue->getValueID()) { case CSSValueNoCommonLigatures: commonLigaturesState = FontDescription::DisabledLigaturesState; break; case CSSValueCommonLigatures: commonLigaturesState = FontDescription::EnabledLigaturesState; break; case CSSValueNoDiscretionaryLigatures: discretionaryLigaturesState = FontDescription::DisabledLigaturesState; break; case CSSValueDiscretionaryLigatures: discretionaryLigaturesState = FontDescription::EnabledLigaturesState; break; case CSSValueNoHistoricalLigatures: historicalLigaturesState = FontDescription::DisabledLigaturesState; break; case CSSValueHistoricalLigatures: historicalLigaturesState = FontDescription::EnabledLigaturesState; break; case CSSValueNoContextual: contextualLigaturesState = FontDescription::DisabledLigaturesState; break; case CSSValueContextual: contextualLigaturesState = FontDescription::EnabledLigaturesState; break; default: ASSERT_NOT_REACHED(); break; } } } } #if ASSERT_ENABLED else { ASSERT_WITH_SECURITY_IMPLICATION(value->isPrimitiveValue()); ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNormal); } #endif scope.fontDescription().setCommonLigaturesState(commonLigaturesState); scope.fontDescription().setDiscretionaryLigaturesState(discretionaryLigaturesState); scope.fontDescription().setHistoricalLigaturesState(historicalLigaturesState); scope.fontDescription().setContextualLigaturesState(contextualLigaturesState); }
PassRefPtr<FontFace> FontFace::create(Document* document, const StyleRuleFontFace* fontFaceRule) { const StylePropertySet& properties = fontFaceRule->properties(); // Obtain the font-family property and the src property. Both must be defined. RefPtrWillBeRawPtr<CSSValue> family = properties.getPropertyCSSValue(CSSPropertyFontFamily); if (!family || !family->isValueList()) return nullptr; RefPtrWillBeRawPtr<CSSValue> src = properties.getPropertyCSSValue(CSSPropertySrc); if (!src || !src->isValueList()) return nullptr; RefPtr<FontFace> fontFace = adoptRefWillBeRefCountedGarbageCollected<FontFace>(new FontFace()); if (fontFace->setFamilyValue(toCSSValueList(family.get())) && fontFace->setPropertyFromStyle(properties, CSSPropertyFontStyle) && fontFace->setPropertyFromStyle(properties, CSSPropertyFontWeight) && fontFace->setPropertyFromStyle(properties, CSSPropertyFontStretch) && fontFace->setPropertyFromStyle(properties, CSSPropertyUnicodeRange) && fontFace->setPropertyFromStyle(properties, CSSPropertyFontVariant) && fontFace->setPropertyFromStyle(properties, CSSPropertyWebkitFontFeatureSettings) && !fontFace->family().isEmpty() && fontFace->traits().mask()) { fontFace->initCSSFontFace(document, src); return fontFace.release(); } return nullptr; }
void FontFace::initCSSFontFace(Document* document, PassRefPtrWillBeRawPtr<CSSValue> src) { m_cssFontFace = createCSSFontFace(this, m_unicodeRange.get()); if (m_error) return; // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace. ASSERT(src); ASSERT(src->isValueList()); CSSValueList* srcList = toCSSValueList(src.get()); int srcLength = srcList->length(); bool foundSVGFont = false; for (int i = 0; i < srcLength; i++) { // An item in the list either specifies a string (local font name) or a URL (remote font to download). CSSFontFaceSrcValue* item = toCSSFontFaceSrcValue(srcList->item(i)); OwnPtrWillBeRawPtr<CSSFontFaceSource> source = nullptr; #if ENABLE(SVG_FONTS) foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement(); #endif if (!item->isLocal()) { Settings* settings = document ? document->frame() ? document->frame()->settings() : 0 : 0; bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled()); if (allowDownloading && item->isSupportedFormat() && document) { FontResource* fetched = item->fetch(document); if (fetched) { FontLoader* fontLoader = document->styleEngine()->fontSelector()->fontLoader(); #if ENABLE(SVG_FONTS) if (foundSVGFont) { source = adoptPtrWillBeNoop(new SVGRemoteFontFaceSource(item->resource(), fetched, fontLoader)); } else #endif { source = adoptPtrWillBeNoop(new RemoteFontFaceSource(fetched, fontLoader)); } } } } else { #if ENABLE(SVG_FONTS) if (item->svgFontFaceElement()) { RefPtrWillBeRawPtr<SVGFontFaceElement> fontfaceElement = item->svgFontFaceElement(); // SVGFontFaceSource assumes that it is the case where <font-face> element resides in the same document. // We put a RELEASE_ASSERT here as it will cause UAF if the assumption is false. RELEASE_ASSERT(fontfaceElement->inDocument()); RELEASE_ASSERT(fontfaceElement->document() == document); source = adoptPtrWillBeNoop(new SVGFontFaceSource(fontfaceElement.get())); } else #endif { source = adoptPtrWillBeNoop(new LocalFontFaceSource(item->resource())); } } if (source) m_cssFontFace->addSource(source.release()); } }
String CSSValue::cssText() const { if (m_isTextClone) { ASSERT(isCSSOMSafe()); return toTextCloneCSSValue(this)->cssText(); } ASSERT(!isCSSOMSafe() || isSubtypeExposedToCSSOM()); switch (classType()) { case AspectRatioClass: return toCSSAspectRatioValue(this)->customCSSText(); case BorderImageSliceClass: return toCSSBorderImageSliceValue(this)->customCSSText(); case FontClass: return toCSSFontValue(this)->customCSSText(); case FontFaceSrcClass: return toCSSFontFaceSrcValue(this)->customCSSText(); case FontFeatureClass: return toCSSFontFeatureValue(this)->customCSSText(); case FunctionClass: return toCSSFunctionValue(this)->customCSSText(); case LinearGradientClass: return toCSSLinearGradientValue(this)->customCSSText(); case RadialGradientClass: return toCSSRadialGradientValue(this)->customCSSText(); case CrossfadeClass: return toCSSCrossfadeValue(this)->customCSSText(); case ImageClass: return toCSSImageValue(this)->customCSSText(); case InheritedClass: return toCSSInheritedValue(this)->customCSSText(); case InitialClass: return toCSSInitialValue(this)->customCSSText(); case PrimitiveClass: return toCSSPrimitiveValue(this)->customCSSText(); case ShadowClass: return toCSSShadowValue(this)->customCSSText(); case CubicBezierTimingFunctionClass: return toCSSCubicBezierTimingFunctionValue(this)->customCSSText(); case StepsTimingFunctionClass: return toCSSStepsTimingFunctionValue(this)->customCSSText(); case UnicodeRangeClass: return toCSSUnicodeRangeValue(this)->customCSSText(); case ValueListClass: return toCSSValueList(this)->customCSSText(); case CSSTransformClass: return toCSSTransformValue(this)->customCSSText(); case LineBoxContainClass: return toCSSLineBoxContainValue(this)->customCSSText(); case CalculationClass: return toCSSCalcValue(this)->customCSSText(); case ImageSetClass: return toCSSImageSetValue(this)->customCSSText(); case CSSFilterClass: return toCSSFilterValue(this)->customCSSText(); } ASSERT_NOT_REACHED(); return String(); }
InterpolationValue CSSBasicShapeInterpolationType::maybeConvertValue(const CSSValue& value, const StyleResolverState&, ConversionCheckers&) const { if (!value.isBaseValueList()) return BasicShapeInterpolationFunctions::maybeConvertCSSValue(value); const CSSValueList& list = toCSSValueList(value); if (list.length() != 1) return nullptr; return BasicShapeInterpolationFunctions::maybeConvertCSSValue(*list.item(0)); }
InterpolationValue CSSLengthListInterpolationType::maybeConvertValue(const CSSValue& value, const StyleResolverState&, ConversionCheckers&) const { if (!value.isBaseValueList()) return nullptr; const CSSValueList& list = toCSSValueList(value); return ListInterpolationFunctions::createList(list.length(), [&list](size_t index) { return CSSLengthInterpolationType::maybeConvertCSSValue(*list.item(index)); }); }
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; }
String StylePropertySerializer::backgroundRepeatPropertyValue() const { RefPtr<CSSValue> repeatX = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundRepeatX); RefPtr<CSSValue> repeatY = m_propertySet.getPropertyCSSValue(CSSPropertyBackgroundRepeatY); if (!repeatX || !repeatY) return String(); if (repeatX->cssValueType() == repeatY->cssValueType() && (repeatX->cssValueType() == CSSValue::CSS_INITIAL || repeatX->cssValueType() == CSSValue::CSS_INHERIT)) { return repeatX->cssText(); } RefPtr<CSSValueList> repeatXList; if (repeatX->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) { repeatXList = CSSValueList::createCommaSeparated(); repeatXList->append(repeatX); } else if (repeatX->cssValueType() == CSSValue::CSS_VALUE_LIST) { repeatXList = toCSSValueList(repeatX.get()); } else { return String(); } RefPtr<CSSValueList> repeatYList; if (repeatY->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) { repeatYList = CSSValueList::createCommaSeparated(); repeatYList->append(repeatY); } else if (repeatY->cssValueType() == CSSValue::CSS_VALUE_LIST) { repeatYList = toCSSValueList(repeatY.get()); } else { return String(); } size_t shorthandLength = lowestCommonMultiple(repeatXList->length(), repeatYList->length()); StringBuilder builder; for (size_t i = 0; i < shorthandLength; ++i) { if (i) builder.appendLiteral(", "); appendBackgroundRepeatValue(builder, *repeatXList->item(i % repeatXList->length()), *repeatYList->item(i % repeatYList->length())); } return builder.toString(); }
void StyleBuilderFunctions::applyValueCSSPropertySize(StyleResolverState& state, CSSValue* value) { state.style()->resetPageSizeType(); FloatSize size; PageSizeType pageSizeType = PAGE_SIZE_AUTO; CSSValueList* list = toCSSValueList(value); if (list->length() == 2) { // <length>{2} | <page-size> <orientation> CSSPrimitiveValue* first = toCSSPrimitiveValue(list->item(0)); CSSPrimitiveValue* second = toCSSPrimitiveValue(list->item(1)); if (first->isLength()) { // <length>{2} size = FloatSize(first->computeLength<float>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0)), second->computeLength<float>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0))); } else { // <page-size> <orientation> size = getPageSizeFromName(first); ASSERT(second->getValueID() == CSSValueLandscape || second->getValueID() == CSSValuePortrait); if (second->getValueID() == CSSValueLandscape) size = size.transposedSize(); } pageSizeType = PAGE_SIZE_RESOLVED; } else { ASSERT(list->length() == 1); // <length> | auto | <page-size> | [ portrait | landscape] CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(list->item(0)); if (primitiveValue->isLength()) { // <length> pageSizeType = PAGE_SIZE_RESOLVED; float width = primitiveValue->computeLength<float>(state.cssToLengthConversionData().copyWithAdjustedZoom(1.0)); size = FloatSize(width, width); } else { switch (primitiveValue->getValueID()) { case CSSValueAuto: pageSizeType = PAGE_SIZE_AUTO; break; case CSSValuePortrait: pageSizeType = PAGE_SIZE_AUTO_PORTRAIT; break; case CSSValueLandscape: pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE; break; default: // <page-size> pageSizeType = PAGE_SIZE_RESOLVED; size = getPageSizeFromName(primitiveValue); } } } state.style()->setPageSizeType(pageSizeType); state.style()->setPageSize(size); }
PassRefPtr<TimingFunction> AnimationInputHelpers::parseTimingFunction(const String& string) { if (string.isEmpty()) return nullptr; RefPtrWillBeRawPtr<CSSValue> value = CSSParser::parseSingleValue(CSSPropertyTransitionTimingFunction, string); if (!value || value->isInitialValue() || value->isInheritedValue()) return nullptr; CSSValueList* valueList = toCSSValueList(value.get()); if (valueList->length() > 1) return nullptr; return CSSToStyleMap::mapAnimationTimingFunction(valueList->item(0), true); }
static CSSFontFace* createCSSFontFace(FontFace* fontFace, CSSValue* unicodeRange) { Vector<UnicodeRange> ranges; if (CSSValueList* rangeList = toCSSValueList(unicodeRange)) { unsigned numRanges = rangeList->length(); for (unsigned i = 0; i < numRanges; i++) { CSSUnicodeRangeValue* range = toCSSUnicodeRangeValue(rangeList->item(i)); ranges.append(UnicodeRange(range->from(), range->to())); } } return new CSSFontFace(fontFace, ranges); }
static PassOwnPtrWillBeRawPtr<CSSFontFace> createCSSFontFace(FontFace* fontFace, CSSValue* unicodeRange) { Vector<CSSFontFace::UnicodeRange> ranges; if (CSSValueList* rangeList = toCSSValueList(unicodeRange)) { unsigned numRanges = rangeList->length(); for (unsigned i = 0; i < numRanges; i++) { CSSUnicodeRangeValue* range = toCSSUnicodeRangeValue(rangeList->item(i)); ranges.append(CSSFontFace::UnicodeRange(range->from(), range->to())); } } return adoptPtrWillBeNoop(new CSSFontFace(fontFace, ranges)); }
v8::Handle<v8::Object> wrap(CSSValue* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { ASSERT(impl); if (impl->isTransformValue()) return wrap(toCSSTransformValue(impl), creationContext, isolate); if (impl->isFilterValue()) return wrap(toCSSFilterValue(impl), creationContext, isolate); if (impl->isValueList()) return wrap(toCSSValueList(impl), creationContext, isolate); if (impl->isPrimitiveValue()) return wrap(toCSSPrimitiveValue(impl), creationContext, isolate); return V8CSSValue::createWrapper(impl, creationContext, isolate); }
InterpolationValue CSSShadowListInterpolationType::maybeConvertValue(const CSSValue& value, const StyleResolverState&, ConversionCheckers&) const { if (value.isPrimitiveValue() && toCSSPrimitiveValue(value).getValueID() == CSSValueNone) return createNeutralValue(); if (!value.isBaseValueList()) return nullptr; const CSSValueList& valueList = toCSSValueList(value); return ListInterpolationFunctions::createList(valueList.length(), [&valueList](size_t index) { return ShadowInterpolationFunctions::maybeConvertCSSValue(valueList.item(index)); }); }
PassRefPtr<FontFeatureSettings> StyleBuilderConverter::convertFontFeatureSettings(StyleResolverState& state, CSSValue* value) { if (value->isPrimitiveValue() && toCSSPrimitiveValue(value)->getValueID() == CSSValueNormal) return FontBuilder::initialFeatureSettings(); CSSValueList* list = toCSSValueList(value); RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create(); int len = list->length(); for (int i = 0; i < len; ++i) { CSSFontFeatureValue* feature = toCSSFontFeatureValue(list->item(i)); settings->append(FontFeature(feature->tag(), feature->value())); } return settings; }
static void compareLengthLists(PassRefPtrWillBeRawPtr<CSSValueList> expectedList, PassRefPtrWillBeRawPtr<CSSValue> actualList) { ASSERT(actualList->isValueList()); for (size_t i = 0; i < 10; i++) { CSSValue* currentExpectedValue = expectedList->item(i); CSSValue* currentActualValue = toCSSValueList(*actualList).item(i); ASSERT(currentExpectedValue->isPrimitiveValue()); ASSERT(currentActualValue->isPrimitiveValue()); EXPECT_EQ(toCSSPrimitiveValue(currentExpectedValue)->getDoubleValue(), toCSSPrimitiveValue(currentActualValue)->getDoubleValue()); EXPECT_EQ(toCSSPrimitiveValue(currentExpectedValue)->getDoubleValue(), toCSSPrimitiveValue(currentActualValue)->getDoubleValue()); } }