/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SKSL_CONSTRUCTOR #define SKSL_CONSTRUCTOR #include "include/core/SkSpan.h" #include "src/sksl/SkSLIRGenerator.h" #include "src/sksl/ir/SkSLExpression.h" namespace SkSL { /** * Base class representing a constructor with unknown arguments. */ class AnyConstructor : public Expression { public: AnyConstructor(int offset, Kind kind, const Type* type) : INHERITED(offset, kind, type) {} virtual SkSpan> argumentSpan() = 0; virtual SkSpan> argumentSpan() const = 0; bool hasProperty(Property property) const override { for (const std::unique_ptr& arg : this->argumentSpan()) { if (arg->hasProperty(property)) { return true; } } return false; } String description() const override { String result = this->type().description() + "("; const char* separator = ""; for (const std::unique_ptr& arg : this->argumentSpan()) { result += separator; result += arg->description(); separator = ", "; } result += ")"; return result; } const Type& componentType() const { return this->type().componentType(); } bool isCompileTimeConstant() const override { for (const std::unique_ptr& arg : this->argumentSpan()) { if (!arg->isCompileTimeConstant()) { return false; } } return true; } bool isConstantOrUniform() const override { for (const std::unique_ptr& arg : this->argumentSpan()) { if (!arg->isConstantOrUniform()) { return false; } } return true; } const Expression* getConstantSubexpression(int n) const override; ComparisonResult compareConstant(const Expression& other) const override; private: std::unique_ptr fArgument; using INHERITED = Expression; }; /** * Base class representing a constructor that takes a single argument. */ class SingleArgumentConstructor : public AnyConstructor { public: SingleArgumentConstructor(int offset, Kind kind, const Type* type, std::unique_ptr argument) : INHERITED(offset, kind, type) , fArgument(std::move(argument)) {} std::unique_ptr& argument() { return fArgument; } const std::unique_ptr& argument() const { return fArgument; } SkSpan> argumentSpan() final { return {&fArgument, 1}; } SkSpan> argumentSpan() const final { return {&fArgument, 1}; } private: std::unique_ptr fArgument; using INHERITED = AnyConstructor; }; /** * Base class representing a constructor that takes an array of arguments. */ class MultiArgumentConstructor : public AnyConstructor { public: MultiArgumentConstructor(int offset, Kind kind, const Type* type, ExpressionArray arguments) : INHERITED(offset, kind, type) , fArguments(std::move(arguments)) {} ExpressionArray& arguments() { return fArguments; } const ExpressionArray& arguments() const { return fArguments; } ExpressionArray cloneArguments() const { ExpressionArray clonedArgs; clonedArgs.reserve_back(this->arguments().size()); for (const std::unique_ptr& arg: this->arguments()) { clonedArgs.push_back(arg->clone()); } return clonedArgs; } SkSpan> argumentSpan() final { return {&fArguments.front(), fArguments.size()}; } SkSpan> argumentSpan() const final { return {&fArguments.front(), fArguments.size()}; } private: ExpressionArray fArguments; using INHERITED = AnyConstructor; }; /** * Converts any GLSL constructor, such as `float2(x, y)` or `mat3x3(otherMat)` or `int[2](0, i)`, to * an SkSL expression. * * Vector constructors must always consist of either exactly 1 scalar, or a collection of vectors * and scalars totaling exactly the right number of scalar components. * * Matrix constructors must always consist of either exactly 1 scalar, exactly 1 matrix, or a * collection of vectors and scalars totaling exactly the right number of scalar components. * * Array constructors must always contain the proper number of array elements (matching the Type). */ namespace Constructor { // Creates, typechecks and simplifies constructor expressions. Reports errors via the // ErrorReporter. This can return null on error, so be careful. There are several different // Constructor expression types; this class chooses the proper one based on context, e.g. // `ConstructorCompound`, `ConstructorScalarCast`, or `ConstructorMatrixResize`. std::unique_ptr Convert(const Context& context, int offset, const Type& type, ExpressionArray args); }; } // namespace SkSL #endif