// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Contains the input used by filter_proto_converter to create a valid flattened
// skia image filter. These messages were made using CreateProc and flatten
// methods in mind so that a valid flattenable is produced. Many of the enums
// here are copied from skia. Most of the messages are straightforward, but
// there are a few things worth noting here. First is that many fields can be
// written to the flattenable output as-is (such as the fields x,y and z in
// Point3). And sometimes entire messages such as Point3 are written
// as-is. These Message and fields can be what we call "autovisited". For fields
// it means that they can be handled by the WriteFields method in
// filter_proto_converter.cc. For messages it means they can be handled by
// WriteFields and the generic Visit function (void Converter::Visit(const
// Message& msg)) and do not need their own specific code. In this file, we will
// put a comment "Autovisit:" before fields or messages that can be autovisited.
// A second thing to know is the parent and child pattern we use here. In many
// cases we need to specify one type of some kind of skia flattenable, like one
// ColorFilter. To do this we create a message $CONCEPT + "Child" (eg
// ColorFilterChild) that contains oneof these subtypes. In many cases these
// subtypes (or children) will share things in common with each other. To avoid
// re-implementing the same thing dozens of times, we give these children a
// field called parent, that when Visited handles this common functionality. One
// important exception to this general pattern is the LightParent message which
// contains its own children, rather than the usual practice (which is the other
// way around). That was done because the order in which the common
// functionality must be done is different than in other cases (here it must
// happen after the child functionality is handled, not before as in the other
// cases). Finally, the last thing to know is because protobuf doesn't have a
// good way to specify an array of a certain length so this functionality is
// implemented by defining a message containing required fields representing
// each element in the array (eg OverdrawColorFilter).

syntax = "proto2";

package skia_image_filter_proto_converter;

// Used for testcases.
message Input {
  required ImageFilterChild image_filter = 1;
  required uint64 rng_seed = 2;
}

// No content when flattened.
message LumaColorFilter {}

message OverdrawColorFilter {
  // Autovisit:
  required uint32 val1 = 1;
  required uint32 val2 = 2;
  required uint32 val3 = 3;
  required uint32 val4 = 4;
  required uint32 val5 = 5;
  required uint32 val6 = 6;
}

message ColorFilterChild {
  oneof children {
    ModeColorFilter mode_color_filter = 1;
    ColorMatrixFilterRowMajor255 color_matrix_filter_row_major_255 = 2;
    ComposeColorFilter compose_color_filter = 3;
    SRGBGammaColorFilter srgb_gamma_color_filter = 4;
    HighContrast_Filter high_contrast__filter = 5;
    LumaColorFilter luma_color_filter = 6;
    OverdrawColorFilter overdraw_color_filter = 7;
    Table_ColorFilter table__color_filter = 8;
    ToSRGBColorFilter to_srgb_color_filter = 9;
  }
}

message TransferFn {
  required Named named = 1;
  required float a = 2;
  required float b = 3;
  required float c = 4;
  required float d = 5;
  required float e = 6;
  required float f = 7;
  required float g = 8;
  required ThreeByFour three_by_four = 9;
}

enum Named {
  kSRGB_Named = 0;
  kAdobeRGB_Named = 1;
  kSRGBLinear_Named = 2;
  kSRGB_NonLinearBlending_Named = 3;
}

message ColorSpace_XYZ {
  enum GammaNamed {
    kLinear_SkGammaNamed = 0;
    kSRGB_SkGammaNamed = 1;
    k2Dot2Curve_SkGammaNamed = 2;
  }
  required GammaNamed gamma_named = 1;
  required ThreeByFour three_by_four = 2;
}

message ColorSpaceNamed {
  enum ColorSpaceNamedEnum {
    kAdobeRGB_Named = 1;
    kSRGBLinear_Named = 2;
  }
  required ColorSpaceNamedEnum named = 1;
  required GammaNamed gamma_named = 2;
}

message ColorSpaceChild {
  oneof data {
    ICC icc = 1;
    TransferFn transfer_fn = 2;
    ColorSpace_XYZ color_space__xyz = 3;
  }
  required ColorSpaceNamed named = 4;
}

message ToSRGBColorFilter {
  required ColorSpaceChild color_space = 1;
}

message ColorTable {
  required float val1 = 1;
  required float val2 = 2;
  required float val3 = 3;
  required float val4 = 4;
  required float val5 = 5;
  required float val6 = 6;
  required float val7 = 7;
  required float val8 = 8;
  required float val9 = 9;
  required float val10 = 10;
  required float val11 = 11;
  required float val12 = 12;
  required float val13 = 13;
  required float val14 = 14;
  required float val15 = 15;
  required float val16 = 16;
  required float val17 = 17;
  required float val18 = 18;
  required float val19 = 19;
  required float val20 = 20;
  required float val21 = 21;
  required float val22 = 22;
  required float val23 = 23;
  required float val24 = 24;
  required float val25 = 25;
  required float val26 = 26;
  required float val27 = 27;
  required float val28 = 28;
  required float val29 = 29;
  required float val30 = 30;
  required float val31 = 31;
  required float val32 = 32;
  required float val33 = 33;
  required float val34 = 34;
  required float val35 = 35;
  required float val36 = 36;
  required float val37 = 37;
  required float val38 = 38;
  required float val39 = 39;
  required float val40 = 40;
  required float val41 = 41;
  required float val42 = 42;
  required float val43 = 43;
  required float val44 = 44;
  required float val45 = 45;
  required float val46 = 46;
  required float val47 = 47;
  required float val48 = 48;
  required float val49 = 49;
  required float val50 = 50;
  required float val51 = 51;
  required float val52 = 52;
  required float val53 = 53;
  required float val54 = 54;
  required float val55 = 55;
  required float val56 = 56;
  required float val57 = 57;
  required float val58 = 58;
  required float val59 = 59;
  required float val60 = 60;
  required float val61 = 61;
  required float val62 = 62;
  required float val63 = 63;
  required float val64 = 64;
}

message Table_ColorFilter {
  optional ColorTable table_a = 1;
  optional ColorTable table_r = 2;
  optional ColorTable table_g = 3;
  optional ColorTable table_b = 4;
}

// See SkHighContrastFilter.cpp
message HighContrast_Filter {
  enum InvertStyle {
    kNoInvert = 0;
    kInvertBrightness = 1;
    kInvertLightness = 2;
  }

  required bool grayscale = 1;
  required InvertStyle invert_style = 2;
  // Autovisit up to here
  required float contrast = 3;
}

// Autovisit:
message SRGBGammaColorFilter {
  enum Direction {
    kLinearToSRGB = 0;
    kSRGBToLinear = 1;
  }
  required Direction direction = 1;
}

message ComposeColorFilter {
  required ColorFilterChild outer = 1;
  required ColorFilterChild inner = 2;
}

message ColorFilterMatrix {
  // Autovisit:
  required float val1 = 1;
  required float val2 = 2;
  required float val3 = 3;
  required float val4 = 4;
  required float val5 = 5;
  required float val6 = 6;
  required float val7 = 7;
  required float val8 = 8;
  required float val9 = 9;
  required float val10 = 10;
  required float val11 = 11;
  required float val12 = 12;
  required float val13 = 13;
  required float val14 = 14;
  required float val15 = 15;
  required float val16 = 16;
  required float val17 = 17;
  required float val18 = 18;
  required float val19 = 19;
  required float val20 = 20;
}

// See SkColorMatrixFilterRowMajor255.cpp (https://goo.gl/qwF8DK)
message ColorMatrixFilterRowMajor255 {
  // Autovisit:
  required ColorFilterMatrix color_filter_matrix = 1;
}

message ModeColorFilter {
  required uint32 color = 1;
  required BlendMode mode = 2;
}

message Rectangle {
  required float left = 1;
  required float top = 2;
  required float right = 3;
  required float bottom = 4;
}

message IRect {
  required int32 left = 1;
  required int32 top = 2;
  required int32 right = 3;
  required int32 bottom = 4;
}

message CropRectangle {
  required Rectangle rectangle = 1;
  required uint32 flags = 2;
}

message PictureInfo {
  // TODO(metzman): Figure out how to keep this up to date.
  enum Version {
    V0 = 56;
    V1 = 57;
    V2 = 58;
    V3 = 59;
    kRemoveHeaderFlags_Version = 60;
    V4 = 61;
  }

  required Version version = 1;
  required Rectangle rectangle = 2;
  required uint32 flags = 3;
}

message PictureData {
  // SkPictureData.cpp (https://goo.gl/hDnKjz)
  repeated PictureTagChild tags = 1;
  required ReaderPictureTag reader_tag = 2;
}

enum BlendMode {
  kClear = 0;
  kSrc = 1;
  kDst = 2;
  // TODO(metzman): Uncomment this when bug 786133 is fixed.
  // kSrcOver = 3;
  kDstOver = 4;
  kSrcIn = 5;
  kDstIn = 6;
  kSrcOut = 7;
  kDstOut = 8;
  kSrcATop = 9;
  kDstATop = 10;
  kXor = 11;
  kPlus = 12;
  kModulate = 13;
  kScreenAndLastCoeffMode = 14;
  kOverlay = 15;
  kDarken = 16;
  kLighten = 17;
  kColorDodge = 18;
  kColorBurn = 19;
  kHardLight = 20;
  kSoftLight = 21;
  kDifference = 22;
  kExclusion = 23;
  kLastSeparableModeAndMultiply = 24;
  kHue = 25;
  kSaturation = 26;
  kColor = 27;
  kLuminosity = 28;
}

message Paint {
  required float text_size = 1;
  required float text_scale_x = 2;
  required float text_skew_x = 3;
  required float stroke_width = 4;
  required float stroke_miter = 5;
  required uint32 color = 6;
  // Autovisit up to here

  enum TextEncoding {
    kUTF8_TextEncoding = 0;
    kUTF16_TextEncoding = 1;
    kUTF32_TextEncoding = 2;
    kGlyphID_TextEncoding = 3;
  }

  enum Style {
    kFill_Style = 0;
    kStroke_Style = 1;
    kStrokeAndFill_Style = 2;  // no longer needed/used
  }

  enum StrokeCap {
    kButt_Cap = 0;
    kRound_Cap = 1;
    kSquare_Cap = 2;
  }

  enum StrokeJoin {
    kMiter_Join = 0;
    kRound_Join = 1;
    kBevel_Join = 2;
  }

  required StrokeCap stroke_cap = 7;
  required StrokeJoin stroke_join = 8;
  required Style style = 9;
  required TextEncoding text_encoding = 10;
  required BlendMode blend_mode = 11;
  optional PaintEffects effects = 12;

  enum PaintFlags {
    kAntiAlias_Flag = 0x01;
    kDither_Flag = 0x04;
    kFakeBoldText_Flag = 0x20;
    kLinearText_Flag = 0x40;
    kSubpixelText_Flag = 0x80;
    kDevKernText_Flag = 0x100;
    kLCDRenderText_Flag = 0x200;
    kEmbeddedBitmapText_Flag = 0x400;
    kAutoHinting_Flag = 0x800;
    kVerticalText_Flag = 0x1000;
    kGenA8FromLCD_Flag = 0x2000;
    kAllFlags = 0xFFFF;
  }

  enum Hinting {
    kNo_Hinting = 0;
    kSlight_Hinting = 1;
    kNormal_Hinting = 2;
    kFull_Hinting = 3;
  }

  enum Align {
    kLeft_Align = 0;
    kCenter_Align = 1;
    kRight_Align = 2;
  }

  // Stuff that gets packed into flags.
  required PaintFlags flags = 13;
  required Hinting hinting = 14;
  required Align align = 15;
  required FilterQuality filter_quality = 16;
}

message Point {
  required float x = 1;
  required float y = 2;
}

message PathEffectChild {
  oneof children {
    PairPathEffect pair_path_effect = 1;
    Path2DPathEffect path_2d_path_effect = 2;
    Line2DPathEffect line_2d_path_effect = 3;
    CornerPathEffect corner_path_effect = 4;
    DashImpl dash_impl = 5;
    DiscretePathEffect discrete_path_effect = 6;
    Path1DPathEffect path_1d_path_effect = 7;
  }
}

// Autovisit:
message CornerPathEffect {
  // 0 is a very bad choice for radius, so make field optional with a default of
  // 1.
  optional float radius = 1 [default = 1];
}

message Path2DPathEffect {
  required Matrix matrix = 1;
  required Path path = 2;
}

message Line2DPathEffect {
  required Matrix matrix = 1;
  required float width = 2;
}

message DashImpl {
  required float phase = 1;
  required float interval_1 = 2;
  required float interval_2 = 3;
  repeated float intervals = 4;
}

// Autovisit:
message DiscretePathEffect {
  required float seg_length = 1;
  required float perterb = 2;
  required uint32 seed_assist = 3;
}

message Path1DPathEffect {
  enum Style {
    kTranslate_Style = 0;
    kRotate_Style = 1;
    kMorph_Style = 2;
  }
  required float advance = 1;
  required Path path = 2;
  required float initial_offset = 3;
  required Style style = 4;
}

message Path {
  enum Convexity {
    kUnknown_Convexity = 0;
    kConvex_Convexity = 1;
    kConcave_Convexity = 2;
  }
  enum FirstDirection {
    kCW_FirstDirection = 0;
    kCCW_FirstDirection = 1;
    kUnknown_FirstDirection = 2;
  }
  enum SerializationVersion {
    kPathPrivFirstDirection_Version = 1;
    kPathPrivLastMoveToIndex_Version = 2;
    kPathPrivTypeEnumVersion = 3;
  }

  required Convexity convexity = 1;
  required uint32 fill_type = 2;  // Should be 8 bytes
  required FirstDirection first_direction = 3;
  required bool is_volatile = 4;
  required SerializationVersion serialized_version = 5;
  required int32 last_move_to_index = 6;
  required PathRef path_ref = 7;
}

message ValidVerb {
  enum Value {
    kMove_Verb = 0;
    kLine_Verb = 1;
    kQuad_Verb = 2;
    kConic_Verb = 3;
    kCubic_Verb = 4;
    kClose_Verb = 5;
    // We don't actually want kDone_Verb.
  }
  required Value value = 1;
  required Point point1 = 2;
  required Point point2 = 3;
  required Point point3 = 4;
  required float conic_weight = 5;
}

message PathRef {
  repeated ValidVerb verbs = 1;
  required bool is_finite = 2;
  required uint32 segment_mask = 3;
  required ValidVerb first_verb = 4;
}

message PairPathEffect {
  enum Type {
    SUM = 1;
    COMPOSE = 2;
  }
  required Type type = 1;
  required PathEffectChild path_effect_1 = 2;
  required PathEffectChild path_effect_2 = 3;
}

message ShaderChild {
  oneof children {
    ColorShader color_shader = 1;
    Color4Shader color_4_shader = 2;
    ColorFilterShader color_filter_shader = 3;
    ComposeShader compose_shader = 4;
    EmptyShader empty_shader = 5;
    ImageShader image_shader = 6;
    PictureShader picture_shader = 7;
    PerlinNoiseShaderImpl perlin_noise_shader_impl = 8;
    LocalMatrixShader local_matrix_shader = 9;
    LinearGradient linear_gradient = 10;
    RadialGradient radial_gradient = 11;
    SweepGradient sweep_gradient = 12;
    TwoPointConicalGradient two_point_conical_gradient = 13;
  }
}

message TwoPointConicalGradient {
  required GradientParent parent = 1;
  // Autovisit:
  required Point center1 = 2;
  required Point center2 = 3;
  required float radius1 = 4;
  required float radius2 = 5;
}

message SweepGradient {
  required GradientParent parent = 1;
  // Autovisit:
  required Point center = 2;
  // TODO(metzman): Handle case when buffer.fVersion >=
  // kTileInfoInSweepGradient_Version or fVersion != 0.
  required float bias = 3;
  required float scale = 4;
}

message RadialGradient {
  required GradientParent parent = 1;
  // Autovisit:
  required Point center = 2;
  required float radius = 3;
}

message Color4f {
  // Autovisit:
  required float r = 1;
  required float g = 2;
  required float b = 3;
  required float a = 4;
}

// Note that this cannot be named "Descriptor" since that name is used by
// protobuf's reflection methods
message GradientDescriptor {
  optional ColorSpaceChild color_space = 1;
  optional float pos = 2;
  optional Matrix local_matrix = 3;
  required TileMode tile_mode = 4;
  required uint32 grad_flags = 5;  // <= UINT8_MAX
  repeated Color4f colors = 6;
}

// Contained by children
message GradientParent {
  required GradientDescriptor gradient_descriptor = 1;
}

message LinearGradient {
  required GradientParent parent = 1;
  // Autovisit:
  required Point start = 2;
  required Point end = 3;
}

message LocalMatrixShader {
  required Matrix matrix = 1;
  required ShaderChild proxy_shader = 2;
}

// Autovisit:
message PerlinNoiseShaderImpl {
  enum Type {
    kFractalNoise_Type = 0;
    kTurbulence_Type = 1;
    kImprovedNoise_Type = 2;
  }
  required Type type = 1;
  required float base_frequency_x = 2;
  required float base_frequency_y = 3;
  required int32 octaves = 4;
  required float seed = 5;
  required int32 height = 6;
  required int32 width = 7;
}

message PictureShader {
  required Matrix matrix = 1;
  // Autovisit:
  required TileMode tmx = 2;
  required TileMode tmy = 3;
  required Rectangle rect = 4;
}

enum TileMode {
  kClamp_TileMode = 0;
  kRepeat_TileMode = 1;
  kMirror_TileMode = 2;
}

// Autovisit:
message ImageShader {
  required TileMode tile_mode_x = 1;
  required TileMode tile_mode_y = 2;
  required Matrix matrix = 3;
  required Image image = 4;
}

message ImageInfo {
  enum AlphaType {
    kUnknown_SkAlphaType = 0;
    kOpaque_SkAlphaType = 1;
    kPremul_SkAlphaType = 2;
    kUnpremul_SkAlphaType = 3;
  }

  enum ColorType {
    kUnknown_Stored_SkColorType = 0;
    kAlpha_8_Stored_SkColorType = 1;
    kRGB_565_Stored_SkColorType = 2;
    kARGB_4444_Stored_SkColorType = 3;
    kRGBA_8888_Stored_SkColorType = 4;
    kBGRA_8888_Stored_SkColorType = 5;
    kIndex_8_Stored_SkColorType_DEPRECATED = 6;
    kGray_8_Stored_SkColorType = 7;
    kRGBA_F16_Stored_SkColorType = 8;
  }

  required int32 width = 1;
  required int32 height = 2;
  required AlphaType alpha_type = 3;
  required ColorType color_type = 4;
  required ColorSpaceChild color_space = 5;
}

message ImageData {
  repeated uint32 data = 1;
}

// TODO(metzman): Finish implementing using ImageInfo.
message Image {
  // Must be non-negative.
  required int32 width = 1;
  required int32 height = 2;
  required ImageData data = 3;
  // Must be nonnegative.
  required int32 origin_x = 4;
  required int32 origin_y = 5;
}

// Autovisit:
message EmptyShader {}

message ComposeShader {
  required ShaderChild dst = 1;
  required ShaderChild src = 2;
  // Autovisit:
  required BlendMode mode = 3;
  required float lerp_t = 4;
}

message ColorFilterShader {
  required ShaderChild shader = 1;
  required ColorFilterChild filter = 2;
}

message Color4Shader {
  required uint32 color = 1;
}

// Autovisit:
message ColorShader {
  required uint32 color = 1;
}

message LooperChild {
  required LayerDrawLooper layer_draw_looper = 1;
}

message LayerDrawLooper {
  repeated LayerInfo layer_infos = 1;
}

message LayerInfo {
  required int32 paint_bits = 1;
  required BlendMode color_mode = 2;
  required Point point = 3;
  required bool post_translate = 4;
  // Autovisit up to here
  required Paint paint = 5;
}

message MaskFilterChild {
  oneof children {
    BlurMaskFilter blur_mask_filter_impl = 1;
    EmbossMaskFilter emboss_mask_filter = 2;
  }
}

message EmbossMaskFilterLight {
  required float direction_x = 1;
  required float direction_y = 2;
  required float direction_z = 3;
  required uint32 ambient = 4;
  required uint32 specular = 5;
}

message EmbossMaskFilter {
  required EmbossMaskFilterLight light = 1;
  required float blur_sigma = 2;
}

enum BlurStyle {
  kNormal_SkBlurStyle = 0;
  kSolid_SkBlurStyle = 1;
  kOuter_SkBlurStyle = 2;
  kInner_SkBlurStyle = 3;
}

// Copied from https://goo.gl/Yy5Euw
enum BlurFlags {
  kNone_BlurFlag = 0x00;
  kIgnoreTransform_BlurFlag = 0x01;
  kHighQuality_BlurFlag = 0x02;
  kAll_BlurFlag = 0x03;
}

message BlurMaskFilter {
  required float sigma = 1;
  required BlurStyle style = 2;
  required BlurFlags flags = 3;
  required Rectangle occluder = 4;
}

message PaintEffects {
  optional PathEffectChild path_effect = 1;
  optional ShaderChild shader = 2;
  optional MaskFilterChild mask_filter = 3;
  optional ColorFilterChild color_filter = 4;
  optional LooperChild looper = 5;
  optional ImageFilterChild image_filter = 6;
}

message RecordingData {
  repeated Paint paints = 1;
}

message PaintImageFilter {
  required ImageFilterParent image_filter_parent = 1;
  required Paint paint = 2;
}

message PictureTagChild {
  oneof children {
    PaintPictureTag paint = 1;
    PathPictureTag path = 2;
    Image image = 3;
    Vertices vertices = 4;
    TextBlob text_blob = 5;
  }
}

message TextBlob {
  required Rectangle bounds = 1;
  enum GlyphPositioning {
    kDefault_Positioning = 0;
    kHorizontal_Positioning = 1;
    kFull_Positioning = 2;
  }
  required GlyphPositioning glyph_positioning = 2;
  required bool extended = 3;
  required Point offset = 4;
  required Paint paint = 5;
  required GlyphAndPosAndCluster glyph_pos_cluster_1 = 6;
  required GlyphAndPosAndCluster glyph_pos_cluster_2 = 7;
  repeated GlyphAndPosAndCluster glyph_pos_clusters = 8;
  repeated uint32 text = 9;
}

message GlyphAndPosAndCluster {
  required uint32 glyph = 1;
  required float position_1 = 2;
  required float position_2 = 3;
  required uint32 cluster = 4;
}

message Vertices {
  enum VertexMode {
    kTriangles_VertexMode = 0;
    kTriangleStrip_VertexMode = 1;
    kTriangleFan_VertexMode = 2;
  }
  required VertexMode mode = 1;
  required bool has_texs = 2;
  required bool has_colors = 3;
  repeated VertexTexColor vertex_text_colors = 4;
  repeated uint32 indices = 5;
}

message VertexTexColor {
  required Point vertex = 1;
  required Point tex = 2;
  required Point color = 3;
}

message ReaderPictureTag {
  required uint32 first_bytes = 1;
  repeated uint32 later_bytes = 2;
}

message PaintPictureTag {
  required Paint paint = 1;
}

message PathPictureTag {
  required Path path = 1;
}

message Picture {
  required PictureInfo info = 1;
  optional PictureData data = 2;
}

// Copied with comments from skia.
// Enums in C++ that don't have set values start at 0.
enum FilterQuality {
  // fastest but lowest quality, typically nearest-neighbor
  kNone_SkFilterQuality = 0;
  kLow_SkFilterQuality = 1;     // typically bilerp
  kMedium_SkFilterQuality = 2;  // typically bilerp + mipmaps for down-scaling
  // slowest but highest quality, typically bicubic or better
  kHigh_SkFilterQuality = 3;
}

message PictureImageFilter {
  enum PictureResolution {
    kDeviceSpace_PictureResolution = 0;
    kLocalSpace_PictureResolution = 1;
  }

  optional Picture picture = 1;
  required Rectangle crop_rectangle = 2;
  required PictureResolution resolution = 3;
}

message Matrix {
  required float val1 = 1;
  required float val2 = 2;
  required float val3 = 3;
  required float val4 = 4;
  required float val5 = 5;
  required float val6 = 6;
  required float val7 = 7;
  required float val8 = 8;
  required float val9 = 9;
}

message MatrixImageFilter {
  required ImageFilterParent image_filter_parent = 1;
  required Matrix transform = 2;
  required FilterQuality filter_quality = 3;
}

message ImageFilterChild {
  oneof children {
    PaintImageFilter paint_image_filter = 1;
    MatrixImageFilter matrix_image_filter = 2;
    SpecularLightingImageFilter specular_lighting_image_filter = 3;
    ArithmeticImageFilter arithmetic_image_filter = 4;
    AlphaThresholdFilterImpl alpha_threshold_filter_impl = 5;
    BlurImageFilterImpl blur_image_filter_impl = 6;
    ColorFilterImageFilter color_filter_image_filter = 7;
    ComposeImageFilter compose_image_filter = 8;
    DisplacementMapEffect displacement_map_effect = 9;
    DropShadowImageFilter drop_shadow_image_filter = 10;
    LocalMatrixImageFilter local_matrix_image_filter = 11;
    MagnifierImageFilter magnifier_image_filter = 13;
    MatrixConvolutionImageFilter matrix_convolution_image_filter = 14;
    MergeImageFilter merge_image_filter = 15;
    DilateImageFilter dilate_image_filter = 16;
    ErodeImageFilter erode_image_filter = 17;
    OffsetImageFilter offset_image_filter = 18;
    PictureImageFilter picture_image_filter = 19;
    TileImageFilter tile_image_filter = 20;
    XfermodeImageFilter_Base xfermode_image_filter__base = 21;
    XfermodeImageFilter xfermode_image_filter = 22;
    DiffuseLightingImageFilter diffuse_lighting_image_filter = 23;
    ImageSource image_source = 24;
  }
}

message DiffuseLightingImageFilter {
  required ImageFilterParent parent = 1;
  required LightParent light = 2;
  required float surface_scale = 3;
  required float kd = 4;
}

message XfermodeImageFilter {
  required ImageFilterParent parent = 1;
  required BlendMode mode = 2;
}

message XfermodeImageFilter_Base {
  required ImageFilterParent parent = 1;
  required BlendMode mode = 2;
}

message TileImageFilter {
  required ImageFilterParent parent = 1;
  required Rectangle src = 2;
  required Rectangle dst = 3;
}

message OffsetImageFilter {
  required ImageFilterParent parent = 1;
  required Point offset = 2;
}

message ErodeImageFilter {
  required ImageFilterParent parent = 1;
  required int32 width = 2;
  required int32 height = 3;
}

message DilateImageFilter {
  required ImageFilterParent parent = 1;
  required int32 width = 2;
  required int32 height = 3;
}

message MergeImageFilter {
  required ImageFilterParent parent = 1;
}

message MatrixConvolutionImageFilter {
  required ImageFilterParent parent = 1;
  required int32 width = 2;
  required int32 height = 3;
  // Since we can't specify a field of repeated bytes that is width*height, use
  // a kernel_seed to seed a RNG to get the number of bytes we need.
  required int64 kernel_seed = 4;
  required float gain = 5;
  required float bias = 6;
  required int32 offset_x = 7;
  required int32 offset_y = 8;
  required TileMode tile_mode = 9;
  required bool convolve_alpha = 10;
}

message MagnifierImageFilter {
  required ImageFilterParent parent = 1;
  required Rectangle src = 2;
  required float inset = 3;
}

message LocalMatrixImageFilter {
  required ImageFilterParent parent = 1;
  required Matrix matrix = 2;
}

message ImageSource {
  required FilterQuality filter_quality = 1;
  required Rectangle src = 2;
  required Rectangle dst = 3;
  // / Autovisit
  required Image image = 4;
}

message DropShadowImageFilter {
  enum ShadowMode {
    kDrawShadowAndForeground_ShadowMode = 0;
    kDrawShadowOnly_ShadowMode = 1;
    kDrawShadowOnly_ShadowMod = 2;
  }
  required ImageFilterParent parent = 1;
  // Autovisit:
  required float dx = 2;
  required float dy = 3;
  required float sigma_x = 4;
  required float sigma_y = 5;
  required uint32 color = 6;
  required ShadowMode shadow_mode = 7;
}

message DisplacementMapEffect {
  enum ChannelSelectorType {
    kUnknown_ChannelSelectorType = 0;
    kR_ChannelSelectorType = 1;
    kG_ChannelSelectorType = 2;
    kB_ChannelSelectorType = 3;
    kA_ChannelSelectorTyp = 4;
  }

  required ImageFilterParent parent = 1;
  // Autovisit:
  required ChannelSelectorType xsel = 2;
  required ChannelSelectorType ysel = 3;
  required float scale = 4;
}

message ComposeImageFilter {
  required ImageFilterParent parent = 1;
}

message ColorFilterImageFilter {
  required ImageFilterParent parent = 1;
  required ColorFilterChild color_filter = 2;
}

message BlurImageFilterImpl {
  required ImageFilterParent parent = 1;
  required float sigma_x = 2;
  required float sigma_y = 3;
  required TileMode mode = 4;
}

message AlphaThresholdFilterImpl {
  required ImageFilterParent parent = 1;
  required float inner = 2;
  required float outer = 3;
  required Region rgn = 4;
}

message Region {
  required IRect bounds = 1;
  // TODO(metzman): Properly implement complex regions.
}

message RegionComplex {
  required int32 y_span_count = 1;
  required int32 interval_count = 2;
  repeated int32 run_seed = 3;
}

message ArithmeticImageFilter {
  required ImageFilterParent parent = 1;

  // Ignored see SkXfermodeImageFilter_Base::LegacyArithmeticCreateProc.
  // Converter will write a mode even without a corresponding field.
  // required BlendMode mode = 2;

  // Autovisit:
  required float val1 = 2;
  required float val2 = 3;
  required float val3 = 4;
  required float val4 = 5;
  required bool enforce_pm_color = 6;
}

// Contained by children
message ImageFilterParent {
  required ImageFilterChild default_input = 1;
  repeated ImageFilterChild inputs = 2;
  required CropRectangle crop_rectangle = 3;
}

// Autovisit:
message Point3 {
  required float x = 1;
  required float y = 2;
  required float z = 3;
}

// Contains children
message LightParent {
  required Point3 color = 1;
  required LightChild light_child = 2;
}

// Autovisit:
message DistantLight {
  required Point3 direction = 1;
}

// Autovisit:
message PointLight {
  required Point3 location = 1;
}

// See SkLightingImageFilter.cpp
// Autovisit:
message SpotLight {
  required Point3 location = 1;
  required Point3 target = 2;
  required float specular_exponent = 3;
  required float cos_outer_cone_angle = 4;
  required float cos_inner_cone_angle = 5;
  required float cone_scale = 6;
  required Point3 s = 7;
}

message LightChild {
  oneof children {
    PointLight point_light = 1;
    SpotLight spot_light = 2;
  }
  required DistantLight distant_light = 3;
}

message SpecularLightingImageFilter {
  required ImageFilterParent image_filter_parent = 1;
  required LightParent light = 2;
  required float surface_scale = 3;
  required float ks = 4;
  required float shininess = 5;
}

enum GammaNamed {
  kLinear_SkGammaNamed = 0;
  kSRGB_SkGammaNamed = 1;
  k2Dot2Curve_SkGammaNamed = 2;
  kNonStandard_SkGammaNamed = 3;
}

message ThreeByFour {
  required float val1 = 1;
  required float val2 = 2;
  required float val3 = 3;
  required float val4 = 4;
  required float val5 = 5;
  required float val6 = 6;
  required float val7 = 7;
  required float val8 = 8;
  required float val9 = 9;
  required float val10 = 10;
  required float val11 = 11;
  required float val12 = 12;
}

enum ICCTag {
  kTAG_rXYZ = 0;
  kTAG_gXYZ = 1;
  kTAG_bXYZ = 2;
  kTAG_rTRC = 3;
  kTAG_gTRC = 4;
  kTAG_bTRC = 5;
  kTAG_kTRC = 6;
  kTAG_A2B0 = 7;
  kTAG_CurveType = 8;
  kTAG_ParaCurveType = 9;
  kTAG_TextType = 10;
}

// This contains a lot of commented out fields since they are in the actual
// struct this message represents, but are unused. We don't define them and
// WriteIgnoredFields is used to write them rather than wasting LPM's time
// setting them. However, we leave them here commented out for reference, and
// we don't use their numbers in case we use them in the future.
message ICC {
  enum Profile {
    Display_Profile = 0;
    Input_Profile = 1;
    Output_Profile = 2;
    ColorSpace_Profile = 3;
  }

  enum InputColorSpace {
    RGB_ColorSpace = 0;
    CMYK_ColorSpace = 1;
    Gray_ColorSpace = 2;
  }
  enum PCS {
    kXYZ_PCSSpace = 0;
    kLAB_PCSSpace = 1;
  }
  enum RenderingIntent {
    kPerceptual = 0;
    kRelative = 1;
    kSaturation = 2;
    kAbsolute = 3;
  }
  required Named named = 34;
  // required uint32 size = 1; // Always 132.
  // required uint32 cmm_type_ignored = 2;
  required uint32 version = 3;
  required Profile profile_class = 4;
  required InputColorSpace input_color_space = 5;
  required PCS pcs = 6;
  // required uint32 datetime_ignored_1 = 7;
  // required uint32 datetime_ignored_2 = 8;
  // required uint32 datetime_ignored_3 = 9;
  // Always SkSetFourByteTag('a', 'c', 's', 'p')
  // required uint32 signature = 10;
  // required uint32 platform_target_ignored = 11;
  // required uint32 flags_ignored = 12;
  // required uint32 device_manufacturer_ignored = 13;
  // required uint32 device_model_ignored = 14;
  // required uint32 device_attributes_ignored_1 = 15;
  // required uint32 device_attributes_ignored_2 = 16;
  required RenderingIntent rendering_intent = 17;
  required int32 illuminant_x = 18;
  required int32 illuminant_y = 19;
  required int32 illuminant_z = 20;

  // required uint32 creator_ignored = 21;
  // required uint32 profileid_ignored_1 = 22;
  // required uint32 profileid_ignored_2 = 23;
  // required uint32 profileid_ignored_3 = 24;
  // required uint32 profileid_ignored_4 = 25;
  // required uint32 reserved_ignored_1 = 26;
  // required uint32 reserved_ignored_2 = 27;
  // required uint32 reserved_ignored_3 = 28;
  // required uint32 reserved_ignored_4 = 29;
  // required uint32 reserved_ignored_5 = 30;
  // required uint32 reserved_ignored_6 = 31;
  // required uint32 reserved_ignored_7 = 32;

  // We'll use colorspaces instead
  required ICCColorSpace color_space = 33;
  // repeated Tag tags = 33;
}

message ICCColorSpace {
  oneof color_space {
    ICCXYZ xyz = 1;
    ICCGray gray = 2;
  }
  // Default.
  required ICCA2B0 a2b0 = 3;
}

message ICCXYZ {}

message ICCGray {}

message ICCA2B0 {
  oneof type {
    ICCA2B0Lut8 lut8 = 1;
    ICCA2B0Lut16 lut16 = 2;
  }
  // Default.
  required ICCA2B0AToB atob = 3;
}

enum Ignored { VALUE = 0; }

enum UInt8 {
  VAL0 = 0;
  VAL1 = 1;
  VAL2 = 2;
  VAL3 = 3;
  VAL4 = 4;
  VAL5 = 5;
  VAL6 = 6;
  VAL7 = 7;
  VAL8 = 8;
  VAL9 = 9;
  VAL10 = 10;
  VAL11 = 11;
  VAL12 = 12;
  VAL13 = 13;
  VAL14 = 14;
  VAL15 = 15;
  VAL16 = 16;
  VAL17 = 17;
  VAL18 = 18;
  VAL19 = 19;
  VAL20 = 20;
  VAL21 = 21;
  VAL22 = 22;
  VAL23 = 23;
  VAL24 = 24;
  VAL25 = 25;
  VAL26 = 26;
  VAL27 = 27;
  VAL28 = 28;
  VAL29 = 29;
  VAL30 = 30;
  VAL31 = 31;
  VAL32 = 32;
  VAL33 = 33;
  VAL34 = 34;
  VAL35 = 35;
  VAL36 = 36;
  VAL37 = 37;
  VAL38 = 38;
  VAL39 = 39;
  VAL40 = 40;
  VAL41 = 41;
  VAL42 = 42;
  VAL43 = 43;
  VAL44 = 44;
  VAL45 = 45;
  VAL46 = 46;
  VAL47 = 47;
  VAL48 = 48;
  VAL49 = 49;
  VAL50 = 50;
  VAL51 = 51;
  VAL52 = 52;
  VAL53 = 53;
  VAL54 = 54;
  VAL55 = 55;
  VAL56 = 56;
  VAL57 = 57;
  VAL58 = 58;
  VAL59 = 59;
  VAL60 = 60;
  VAL61 = 61;
  VAL62 = 62;
  VAL63 = 63;
  VAL64 = 64;
  VAL65 = 65;
  VAL66 = 66;
  VAL67 = 67;
  VAL68 = 68;
  VAL69 = 69;
  VAL70 = 70;
  VAL71 = 71;
  VAL72 = 72;
  VAL73 = 73;
  VAL74 = 74;
  VAL75 = 75;
  VAL76 = 76;
  VAL77 = 77;
  VAL78 = 78;
  VAL79 = 79;
  VAL80 = 80;
  VAL81 = 81;
  VAL82 = 82;
  VAL83 = 83;
  VAL84 = 84;
  VAL85 = 85;
  VAL86 = 86;
  VAL87 = 87;
  VAL88 = 88;
  VAL89 = 89;
  VAL90 = 90;
  VAL91 = 91;
  VAL92 = 92;
  VAL93 = 93;
  VAL94 = 94;
  VAL95 = 95;
  VAL96 = 96;
  VAL97 = 97;
  VAL98 = 98;
  VAL99 = 99;
  VAL100 = 100;
  VAL101 = 101;
  VAL102 = 102;
  VAL103 = 103;
  VAL104 = 104;
  VAL105 = 105;
  VAL106 = 106;
  VAL107 = 107;
  VAL108 = 108;
  VAL109 = 109;
  VAL110 = 110;
  VAL111 = 111;
  VAL112 = 112;
  VAL113 = 113;
  VAL114 = 114;
  VAL115 = 115;
  VAL116 = 116;
  VAL117 = 117;
  VAL118 = 118;
  VAL119 = 119;
  VAL120 = 120;
  VAL121 = 121;
  VAL122 = 122;
  VAL123 = 123;
  VAL124 = 124;
  VAL125 = 125;
  VAL126 = 126;
  VAL127 = 127;
  VAL128 = 128;
  VAL129 = 129;
  VAL130 = 130;
  VAL131 = 131;
  VAL132 = 132;
  VAL133 = 133;
  VAL134 = 134;
  VAL135 = 135;
  VAL136 = 136;
  VAL137 = 137;
  VAL138 = 138;
  VAL139 = 139;
  VAL140 = 140;
  VAL141 = 141;
  VAL142 = 142;
  VAL143 = 143;
  VAL144 = 144;
  VAL145 = 145;
  VAL146 = 146;
  VAL147 = 147;
  VAL148 = 148;
  VAL149 = 149;
  VAL150 = 150;
  VAL151 = 151;
  VAL152 = 152;
  VAL153 = 153;
  VAL154 = 154;
  VAL155 = 155;
  VAL156 = 156;
  VAL157 = 157;
  VAL158 = 158;
  VAL159 = 159;
  VAL160 = 160;
  VAL161 = 161;
  VAL162 = 162;
  VAL163 = 163;
  VAL164 = 164;
  VAL165 = 165;
  VAL166 = 166;
  VAL167 = 167;
  VAL168 = 168;
  VAL169 = 169;
  VAL170 = 170;
  VAL171 = 171;
  VAL172 = 172;
  VAL173 = 173;
  VAL174 = 174;
  VAL175 = 175;
  VAL176 = 176;
  VAL177 = 177;
  VAL178 = 178;
  VAL179 = 179;
  VAL180 = 180;
  VAL181 = 181;
  VAL182 = 182;
  VAL183 = 183;
  VAL184 = 184;
  VAL185 = 185;
  VAL186 = 186;
  VAL187 = 187;
  VAL188 = 188;
  VAL189 = 189;
  VAL190 = 190;
  VAL191 = 191;
  VAL192 = 192;
  VAL193 = 193;
  VAL194 = 194;
  VAL195 = 195;
  VAL196 = 196;
  VAL197 = 197;
  VAL198 = 198;
  VAL199 = 199;
  VAL200 = 200;
  VAL201 = 201;
  VAL202 = 202;
  VAL203 = 203;
  VAL204 = 204;
  VAL205 = 205;
  VAL206 = 206;
  VAL207 = 207;
  VAL208 = 208;
  VAL209 = 209;
  VAL210 = 210;
  VAL211 = 211;
  VAL212 = 212;
  VAL213 = 213;
  VAL214 = 214;
  VAL215 = 215;
  VAL216 = 216;
  VAL217 = 217;
  VAL218 = 218;
  VAL219 = 219;
  VAL220 = 220;
  VAL221 = 221;
  VAL222 = 222;
  VAL223 = 223;
  VAL224 = 224;
  VAL225 = 225;
  VAL226 = 226;
  VAL227 = 227;
  VAL228 = 228;
  VAL229 = 229;
  VAL230 = 230;
  VAL231 = 231;
  VAL232 = 232;
  VAL233 = 233;
  VAL234 = 234;
  VAL235 = 235;
  VAL236 = 236;
  VAL237 = 237;
  VAL238 = 238;
  VAL239 = 239;
  VAL240 = 240;
  VAL241 = 241;
  VAL242 = 242;
  VAL243 = 243;
  VAL244 = 244;
  VAL245 = 245;
  VAL246 = 246;
  VAL247 = 247;
  VAL248 = 248;
  VAL249 = 249;
  VAL250 = 250;
  VAL251 = 251;
  VAL252 = 252;
  VAL253 = 253;
  VAL254 = 254;
  VAL255 = 255;
}

enum InputChannels {
  ONE = 1;
  TWO = 2;
  THREE = 3;
}

enum OutputChannels {
  // Can't be named THREE or else it will conflict with THREE in InputChannels.
  // It doesn't matter, since we only use the numeric value on the converter
  // side.
  _THREE = 3;
}

message ICCA2B0AToB {
  required InputChannels input_channels = 1;
  required OutputChannels output_channels = 2;  // Must be 3
}

message ICCA2B0Lut16 {
  required ICCA2B0Lut8 lut8 = 1;

  // TODO(metzman): allow these to be specified rather than generated.
  // required uint32 in_table_entries = 2; // uint16_t
  // required uint32 out_table_entries = 3; // uint16_t
  required uint64 in_table_seed = 4;
  required uint64 out_table_seed = 5;
}

message ICCA2B0Lut8 {
  required Ignored ignored_byte_4 = 1;
  required Ignored ignored_byte_5 = 2;
  required Ignored ignored_byte_6 = 3;
  required Ignored ignored_byte_7 = 4;
  // Needs to agree with output_channels
  required OutputChannels input_channels = 5;
  required OutputChannels output_channels = 6;  // Must be 3
  required UInt8 clut_grid_points = 7;
  required Ignored ignored_byte_11 = 8;
  required Matrix matrix = 9;
  required OneChannelGammas input_gammas_1 = 10;
  required OneChannelGammas input_gammas_2 = 11;
  required OneChannelGammas input_gammas_3 = 12;
  required uint64 clut_bytes_seed = 13;
  required OutputGammas output_gammas = 14;
}

message OneChannelGammas {
  required int32 bytes_0_3 = 1;
  required int32 bytes_4_7 = 2;
  required int32 bytes_8_11 = 3;
  required int32 bytes_12_15 = 4;
  required int32 bytes_16_19 = 5;
  required int32 bytes_20_23 = 6;
  required int32 bytes_24_27 = 7;
  required int32 bytes_28_31 = 8;
  required int32 bytes_32_35 = 9;
  required int32 bytes_36_39 = 10;
  required int32 bytes_40_43 = 11;
  required int32 bytes_44_47 = 12;
  required int32 bytes_48_51 = 13;
  required int32 bytes_52_55 = 14;
  required int32 bytes_56_59 = 15;
  required int32 bytes_60_63 = 16;
  required int32 bytes_64_67 = 17;
  required int32 bytes_68_71 = 18;
  required int32 bytes_72_75 = 19;
  required int32 bytes_76_79 = 20;
  required int32 bytes_80_83 = 21;
  required int32 bytes_84_87 = 22;
  required int32 bytes_88_91 = 23;
  required int32 bytes_92_95 = 24;
  required int32 bytes_96_99 = 25;
  required int32 bytes_100_103 = 26;
  required int32 bytes_104_107 = 27;
  required int32 bytes_108_111 = 28;
  required int32 bytes_112_115 = 29;
  required int32 bytes_116_119 = 30;
  required int32 bytes_120_123 = 31;
  required int32 bytes_124_127 = 32;
  required int32 bytes_128_131 = 33;
  required int32 bytes_132_135 = 34;
  required int32 bytes_136_139 = 35;
  required int32 bytes_140_143 = 36;
  required int32 bytes_144_147 = 37;
  required int32 bytes_148_151 = 38;
  required int32 bytes_152_155 = 39;
  required int32 bytes_156_159 = 40;
  required int32 bytes_160_163 = 41;
  required int32 bytes_164_167 = 42;
  required int32 bytes_168_171 = 43;
  required int32 bytes_172_175 = 44;
  required int32 bytes_176_179 = 45;
  required int32 bytes_180_183 = 46;
  required int32 bytes_184_187 = 47;
  required int32 bytes_188_191 = 48;
  required int32 bytes_192_195 = 49;
  required int32 bytes_196_199 = 50;
  required int32 bytes_200_203 = 51;
  required int32 bytes_204_207 = 52;
  required int32 bytes_208_211 = 53;
  required int32 bytes_212_215 = 54;
  required int32 bytes_216_219 = 55;
  required int32 bytes_220_223 = 56;
  required int32 bytes_224_227 = 57;
  required int32 bytes_228_231 = 58;
  required int32 bytes_232_235 = 59;
  required int32 bytes_236_239 = 60;
  required int32 bytes_240_243 = 61;
  required int32 bytes_244_247 = 62;
  required int32 bytes_248_251 = 63;
  required int32 bytes_252_255 = 64;
}

// Since output gammas are 3 times the size of input gammas, make
message OutputGammas {
  required OneChannelGammas bytes_0_255 = 1;
  required OneChannelGammas bytes_255_511 = 2;
  required OneChannelGammas bytes_512_768 = 3;
}
