{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "title": "WhimTex clipboard brush JSON, version 1",
  "description": "1 MiB UTF-8 JSON maximum. Replaces the current brush, not document layers. HLSL is compiled on the GPU: trust the source. Texture URL downloads require confirmation. Runtime validates shader syntax and gradient ordering.",
  "oneOf": [
    {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "format": {
          "const": "whimtex.brush"
        },
        "version": {
          "const": 1
        },
        "name": {
          "type": "string",
          "maxLength": 4096
        },
        "settings": {
          "$ref": "#/$defs/settings"
        },
        "source": {
          "const": "Standard"
        },
        "url": {
          "type": "string",
          "maxLength": 4096,
          "pattern": "^https?://[^\\s]+$"
        }
      },
      "required": [
        "format",
        "version",
        "source"
      ]
    },
    {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "format": {
          "const": "whimtex.brush"
        },
        "version": {
          "const": 1
        },
        "name": {
          "type": "string",
          "maxLength": 4096
        },
        "settings": {
          "$ref": "#/$defs/settings"
        },
        "source": {
          "const": "HLSL"
        },
        "code": {
          "type": "string",
          "minLength": 1,
          "maxLength": 65536
        },
        "resolution": {
          "type": "integer",
          "minimum": 32,
          "maximum": 2048
        }
      },
      "required": [
        "format",
        "version",
        "source",
        "code"
      ]
    }
  ],
  "$defs": {
    "settings": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "size": {
          "type": "number",
          "minimum": 1,
          "maximum": 4096
        },
        "hardness": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "spacing": {
          "type": "number",
          "minimum": 0.01,
          "maximum": 4
        },
        "opacity": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "flow": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "scatter": {
          "type": "number",
          "minimum": 0,
          "maximum": 4
        },
        "scatterBias": {
          "type": "number",
          "minimum": -1,
          "maximum": 1
        },
        "sizeJitter": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "angleJitter": {
          "type": "number",
          "minimum": 0,
          "maximum": 180
        },
        "angleOffset": {
          "type": "number",
          "minimum": -180,
          "maximum": 180
        },
        "flipX": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "flipY": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "rotationMode": {
          "type": "string",
          "enum": [
            "Fixed",
            "StrokeDirection"
          ]
        },
        "randomAlgorithm": {
          "type": "string",
          "enum": [
            "Random",
            "Sobol"
          ]
        },
        "tipChannel": {
          "type": "string",
          "enum": [
            "Alpha",
            "Luminance",
            "InvertedLuminance",
            "Color"
          ]
        },
        "tipSdf": {
          "type": "boolean"
        },
        "mode": {
          "type": "string",
          "enum": [
            "Hardness",
            "Gradient"
          ]
        },
        "tipGradient": {
          "$ref": "#/$defs/gradient"
        },
        "tintGradient": {
          "$ref": "#/$defs/gradient"
        },
        "blend": {
          "type": "string",
          "enum": [
            "Normal",
            "Multiply",
            "Add",
            "Subtract",
            "Divide",
            "Screen",
            "Overlay",
            "Darken",
            "Lighten",
            "Dodge",
            "Burn",
            "LinearDodge",
            "LinearBurn",
            "LinearLight",
            "LinearLightAddSub",
            "VividLight",
            "PinLight",
            "HardMix",
            "HardLight",
            "SoftLight",
            "Difference",
            "Exclusion",
            "Negation"
          ]
        },
        "blendApplication": {
          "type": "string",
          "enum": [
            "Stroke",
            "Stamp"
          ]
        },
        "seed": {
          "type": "integer",
          "minimum": 1,
          "maximum": 2147483647
        }
      },
      "required": []
    },
    "gradient": {
      "oneOf": [
        {
          "$ref": "#/$defs/gradientStops"
        },
        {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "colors": {
              "$ref": "#/$defs/gradientStops"
            },
            "alphas": {
              "type": "array",
              "minItems": 1,
              "maxItems": 64,
              "items": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "time": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                  },
                  "alpha": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1
                  },
                  "midpoint": {
                    "type": "number",
                    "minimum": 0.01,
                    "maximum": 0.99
                  }
                },
                "required": [
                  "time",
                  "alpha"
                ]
              }
            },
            "mode": {
              "type": "string",
              "enum": [
                "Classic",
                "Linear",
                "Perceptual",
                "Fixed"
              ]
            },
            "smoothness": {
              "type": "number",
              "minimum": 0,
              "maximum": 1
            },
            "colorSpace": {
              "type": "string",
              "enum": [
                "Gamma",
                "Linear"
              ]
            }
          },
          "required": [
            "colors"
          ]
        }
      ]
    },
    "gradientStops": {
      "type": "array",
      "minItems": 1,
      "maxItems": 64,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "time": {
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "color": {
            "type": "array",
            "prefixItems": [
              {
                "type": "number",
                "minimum": -107,
                "maximum": 107
              },
              {
                "type": "number",
                "minimum": -107,
                "maximum": 107
              },
              {
                "type": "number",
                "minimum": -107,
                "maximum": 107
              },
              {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              }
            ],
            "items": false,
            "minItems": 4,
            "maxItems": 4
          },
          "midpoint": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 0.99
          },
          "alphaMidpoint": {
            "type": "number",
            "minimum": 0.01,
            "maximum": 0.99
          }
        },
        "required": [
          "time",
          "color"
        ]
      },
      "description": "Stops must have strictly increasing times."
    }
  }
}
