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;
}
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;
}
CSSValueList* CSSVariablesDeclaration::getParsedVariable(const String& variableName)
{
    CSSValue* result = m_variablesMap.get(variableName).get();
    if (result->isValueList())
        return static_cast<CSSValueList*>(result);
    return 0;
}
Ejemplo n.º 4
0
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.
    CSSValue* family = properties.getPropertyCSSValue(CSSPropertyFontFamily);
    if (!family || (!family->isFontFamilyValue() && !family->isPrimitiveValue()))
        return nullptr;
    CSSValue* src = properties.getPropertyCSSValue(CSSPropertySrc);
    if (!src || !src->isValueList())
        return nullptr;

    FontFace* fontFace = new FontFace(document);

    if (fontFace->setFamilyValue(*family)
        && fontFace->setPropertyFromStyle(properties, CSSPropertyFontStyle)
        && fontFace->setPropertyFromStyle(properties, CSSPropertyFontWeight)
        && fontFace->setPropertyFromStyle(properties, CSSPropertyFontStretch)
        && fontFace->setPropertyFromStyle(properties, CSSPropertyUnicodeRange)
        && fontFace->setPropertyFromStyle(properties, CSSPropertyFontVariant)
        && fontFace->setPropertyFromStyle(properties, CSSPropertyFontFeatureSettings)
        && fontFace->setPropertyFromStyle(properties, CSSPropertyFontDisplay)
        && !fontFace->family().isEmpty()
        && fontFace->traits().bitfield()) {
        fontFace->initCSSFontFace(document, src);
        return fontFace;
    }
    return nullptr;
}
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));
}
Ejemplo n.º 6
0
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());
    }
}
Ejemplo n.º 7
0
FontFace* FontFace::create(ExecutionContext* context, const AtomicString& family, const String& source, const FontFaceDescriptors& descriptors)
{
    FontFace* fontFace = new FontFace(context, family, descriptors);

    CSSValue* src = parseCSSValue(toDocument(context), source, CSSPropertySrc);
    if (!src || !src->isValueList())
        fontFace->setError(DOMException::create(SyntaxError, "The source provided ('" + source + "') could not be parsed as a value list."));

    fontFace->initCSSFontFace(toDocument(context), src);
    return fontFace;
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
static bool computationallyIndependent(const CSSValue& value) {
  DCHECK(!value.isCSSWideKeyword());

  if (value.isVariableReferenceValue())
    return !toCSSVariableReferenceValue(value)
                .variableDataValue()
                ->needsVariableResolution();

  if (value.isValueList()) {
    for (const CSSValue* innerValue : toCSSValueList(value)) {
      if (!computationallyIndependent(*innerValue))
        return false;
    }
    return true;
  }

  if (value.isPrimitiveValue()) {
    const CSSPrimitiveValue& primitiveValue = toCSSPrimitiveValue(value);
    if (!primitiveValue.isLength() &&
        !primitiveValue.isCalculatedPercentageWithLength())
      return true;

    CSSPrimitiveValue::CSSLengthArray lengthArray;
    primitiveValue.accumulateLengthArray(lengthArray);
    for (size_t i = 0; i < lengthArray.values.size(); i++) {
      if (lengthArray.typeFlags.get(i) &&
          i != CSSPrimitiveValue::UnitTypePixels &&
          i != CSSPrimitiveValue::UnitTypePercentage)
        return false;
    }
    return true;
  }

  // TODO(timloh): Images and transform-function values can also contain
  // lengths.

  return true;
}
Ejemplo n.º 10
0
void RuleFeatureSet::updateInvalidationSetsForContentAttribute(const RuleData& ruleData)
{
    const StylePropertySet& propertySet = ruleData.rule()->properties();

    int propertyIndex = propertySet.findPropertyIndex(CSSPropertyContent);

    if (propertyIndex == -1)
        return;

    StylePropertySet::PropertyReference contentProperty = propertySet.propertyAt(propertyIndex);
    CSSValue* contentValue = contentProperty.value();

    if (!contentValue->isValueList())
        return;

    for (auto& item : toCSSValueList(*contentValue)) {
        if (!item->isFunctionValue())
            continue;
        CSSFunctionValue* functionValue = toCSSFunctionValue(item.get());
        if (functionValue->functionType() != CSSValueAttr)
            continue;
        ensureAttributeInvalidationSet(AtomicString(toCSSPrimitiveValue(functionValue->item(0))->getStringValue())).setInvalidatesSelf();
    }
}
Ejemplo n.º 11
0
TransformOperations TransformBuilder::createTransformOperations(
    const CSSValue& inValue,
    const CSSToLengthConversionData& conversionData) {
  TransformOperations operations;
  if (!inValue.isValueList()) {
    DCHECK_EQ(toCSSIdentifierValue(inValue).getValueID(), CSSValueNone);
    return operations;
  }

  float zoomFactor = conversionData.zoom();
  for (auto& value : toCSSValueList(inValue)) {
    const CSSFunctionValue* transformValue = toCSSFunctionValue(value.get());
    TransformOperation::OperationType transformType =
        getTransformOperationType(transformValue->functionType());

    const CSSPrimitiveValue& firstValue =
        toCSSPrimitiveValue(transformValue->item(0));

    switch (transformType) {
      case TransformOperation::Scale:
      case TransformOperation::ScaleX:
      case TransformOperation::ScaleY: {
        double sx = 1.0;
        double sy = 1.0;
        if (transformType == TransformOperation::ScaleY) {
          sy = firstValue.getDoubleValue();
        } else {
          sx = firstValue.getDoubleValue();
          if (transformType != TransformOperation::ScaleX) {
            if (transformValue->length() > 1) {
              const CSSPrimitiveValue& secondValue =
                  toCSSPrimitiveValue(transformValue->item(1));
              sy = secondValue.getDoubleValue();
            } else {
              sy = sx;
            }
          }
        }
        operations.operations().append(
            ScaleTransformOperation::create(sx, sy, 1.0, transformType));
        break;
      }
      case TransformOperation::ScaleZ:
      case TransformOperation::Scale3D: {
        double sx = 1.0;
        double sy = 1.0;
        double sz = 1.0;
        if (transformType == TransformOperation::ScaleZ) {
          sz = firstValue.getDoubleValue();
        } else {
          sx = firstValue.getDoubleValue();
          sy = toCSSPrimitiveValue(transformValue->item(1)).getDoubleValue();
          sz = toCSSPrimitiveValue(transformValue->item(2)).getDoubleValue();
        }
        operations.operations().append(
            ScaleTransformOperation::create(sx, sy, sz, transformType));
        break;
      }
      case TransformOperation::Translate:
      case TransformOperation::TranslateX:
      case TransformOperation::TranslateY: {
        Length tx = Length(0, Fixed);
        Length ty = Length(0, Fixed);
        if (transformType == TransformOperation::TranslateY)
          ty = convertToFloatLength(firstValue, conversionData);
        else {
          tx = convertToFloatLength(firstValue, conversionData);
          if (transformType != TransformOperation::TranslateX) {
            if (transformValue->length() > 1) {
              const CSSPrimitiveValue& secondValue =
                  toCSSPrimitiveValue(transformValue->item(1));
              ty = convertToFloatLength(secondValue, conversionData);
            }
          }
        }

        operations.operations().append(
            TranslateTransformOperation::create(tx, ty, 0, transformType));
        break;
      }
      case TransformOperation::TranslateZ:
      case TransformOperation::Translate3D: {
        Length tx = Length(0, Fixed);
        Length ty = Length(0, Fixed);
        double tz = 0;
        if (transformType == TransformOperation::TranslateZ) {
          tz = firstValue.computeLength<double>(conversionData);
        } else {
          tx = convertToFloatLength(firstValue, conversionData);
          ty = convertToFloatLength(
              toCSSPrimitiveValue(transformValue->item(1)), conversionData);
          tz = toCSSPrimitiveValue(transformValue->item(2))
                   .computeLength<double>(conversionData);
        }

        operations.operations().append(
            TranslateTransformOperation::create(tx, ty, tz, transformType));
        break;
      }
      case TransformOperation::RotateX:
      case TransformOperation::RotateY:
      case TransformOperation::RotateZ: {
        double angle = firstValue.computeDegrees();
        if (transformValue->length() == 1) {
          double x = transformType == TransformOperation::RotateX;
          double y = transformType == TransformOperation::RotateY;
          double z = transformType == TransformOperation::RotateZ;
          operations.operations().append(
              RotateTransformOperation::create(x, y, z, angle, transformType));
        } else {
          // For SVG 'transform' attributes we generate 3-argument rotate()
          // functions.
          DCHECK_EQ(transformValue->length(), 3u);
          const CSSPrimitiveValue& secondValue =
              toCSSPrimitiveValue(transformValue->item(1));
          const CSSPrimitiveValue& thirdValue =
              toCSSPrimitiveValue(transformValue->item(2));
          operations.operations().append(
              RotateAroundOriginTransformOperation::create(
                  angle, secondValue.computeLength<double>(conversionData),
                  thirdValue.computeLength<double>(conversionData)));
        }
        break;
      }
      case TransformOperation::Rotate3D: {
        const CSSPrimitiveValue& secondValue =
            toCSSPrimitiveValue(transformValue->item(1));
        const CSSPrimitiveValue& thirdValue =
            toCSSPrimitiveValue(transformValue->item(2));
        const 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, transformType));
        break;
      }
      case TransformOperation::Skew:
      case TransformOperation::SkewX:
      case TransformOperation::SkewY: {
        double angleX = 0;
        double angleY = 0;
        double angle = firstValue.computeDegrees();
        if (transformType == TransformOperation::SkewY)
          angleY = angle;
        else {
          angleX = angle;
          if (transformType == TransformOperation::Skew) {
            if (transformValue->length() > 1) {
              const CSSPrimitiveValue& secondValue =
                  toCSSPrimitiveValue(transformValue->item(1));
              angleY = secondValue.computeDegrees();
            }
          }
        }
        operations.operations().append(
            SkewTransformOperation::create(angleX, angleY, transformType));
        break;
      }
      case TransformOperation::Matrix: {
        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 =
            zoomFactor *
            toCSSPrimitiveValue(transformValue->item(4)).getDoubleValue();
        double f =
            zoomFactor *
            toCSSPrimitiveValue(transformValue->item(5)).getDoubleValue();
        operations.operations().append(
            MatrixTransformOperation::create(a, b, c, d, e, f));
        break;
      }
      case TransformOperation::Matrix3D: {
        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());
        matrix.zoom(zoomFactor);
        operations.operations().append(
            Matrix3DTransformOperation::create(matrix));
        break;
      }
      case TransformOperation::Perspective: {
        double p = firstValue.computeLength<double>(conversionData);
        ASSERT(p >= 0);
        operations.operations().append(
            PerspectiveTransformOperation::create(p));
        break;
      }
      default:
        ASSERT_NOT_REACHED();
        break;
    }
  }
  return operations;
}
static PassRefPtr<CustomFilterOperation> createCustomFilterOperationWithInlineSyntax(CSSFilterValue* filterValue, StyleResolverState& state)
{
    CSSValue* shadersValue = filterValue->itemWithoutBoundsCheck(0);
    ASSERT_WITH_SECURITY_IMPLICATION(shadersValue->isValueList());
    CSSValueList* shadersList = toCSSValueList(shadersValue);

    unsigned shadersListLength = shadersList->length();
    ASSERT(shadersListLength);

    CSSShaderValue* vertexShader = 0;
    CSSShaderValue* fragmentShader = 0;

    if (shadersList->itemWithoutBoundsCheck(0)->isShaderValue())
        vertexShader = toCSSShaderValue(shadersList->itemWithoutBoundsCheck(0));

    CustomFilterProgramType programType = ProgramTypeBlendsElementTexture;
    CustomFilterProgramMixSettings mixSettings;

    if (shadersListLength > 1) {
        CSSValue* fragmentShaderOrMixFunction = shadersList->itemWithoutBoundsCheck(1);
        if (fragmentShaderOrMixFunction->isMixFunctionValue()) {
            CSSMixFunctionValue* mixFunction = toCSSMixFunctionValue(fragmentShaderOrMixFunction);
            CSSValueListIterator iterator(mixFunction);

            ASSERT(mixFunction->length());
            if (iterator.value()->isShaderValue())
                fragmentShader = toCSSShaderValue(iterator.value());

            iterator.advance();

            ASSERT(mixFunction->length() <= 3);
            while (iterator.hasMore()) {
                CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value());
                if (CSSParser::isBlendMode(primitiveValue->getValueID()))
                    mixSettings.blendMode = *primitiveValue;
                else if (CSSParser::isCompositeOperator(primitiveValue->getValueID()))
                    mixSettings.compositeOperator = *primitiveValue;
                else
                    ASSERT_NOT_REACHED();
                iterator.advance();
            }
        } else {
            programType = ProgramTypeNoElementTexture;
            if (fragmentShaderOrMixFunction->isShaderValue())
                fragmentShader = toCSSShaderValue(fragmentShaderOrMixFunction);
        }
    }

    if (!vertexShader && !fragmentShader)
        return 0;

    unsigned meshRows = 1;
    unsigned meshColumns = 1;
    CustomFilterMeshType meshType = MeshTypeAttached;

    CSSValue* parametersValue = 0;

    if (filterValue->length() > 1) {
        CSSValueListIterator iterator(filterValue->itemWithoutBoundsCheck(1));

        // The second value might be the mesh box or the list of parameters:
        // If it starts with a number or any of the mesh-box identifiers it is
        // the mesh-box list, if not it means it is the parameters list.

        if (iterator.hasMore() && iterator.isPrimitiveValue()) {
            CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value());
            if (primitiveValue->isNumber()) {
                // If only one integer value is specified, it will set both
                // the rows and the columns.
                meshColumns = meshRows = primitiveValue->getIntValue();
                iterator.advance();

                // Try to match another number for the rows.
                if (iterator.hasMore() && iterator.isPrimitiveValue()) {
                    CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value());
                    if (primitiveValue->isNumber()) {
                        meshRows = primitiveValue->getIntValue();
                        iterator.advance();
                    }
                }
            }
        }

        if (iterator.hasMore() && iterator.isPrimitiveValue()) {
            CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value());
            if (primitiveValue->getValueID() == CSSValueDetached) {
                meshType = MeshTypeDetached;
                iterator.advance();
            }
        }

        if (!iterator.index()) {
            // If no value was consumed from the mesh value, then it is just a parameter list, meaning that we end up
            // having just two CSSListValues: list of shaders and list of parameters.
            ASSERT(filterValue->length() == 2);
            parametersValue = filterValue->itemWithoutBoundsCheck(1);
        }
    }

    if (filterValue->length() > 2 && !parametersValue)
        parametersValue = filterValue->itemWithoutBoundsCheck(2);

    CustomFilterParameterList parameterList;
    if (parametersValue && !parseCustomFilterParameterList(parametersValue, parameterList, state))
        return 0;

    RefPtr<CustomFilterProgram> program = createCustomFilterProgram(vertexShader, fragmentShader, programType, mixSettings, meshType, state);
    return CustomFilterOperation::create(program.release(), parameterList, meshRows, meshColumns, meshType);
}