/* | |

* 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 SkNormalSource_DEFINED | |

#define SkNormalSource_DEFINED | |

#include "SkFlattenable.h" | |

#include "SkShader.h" | |

class SkMatrix; | |

struct SkPoint3; | |

#if SK_SUPPORT_GPU | |

class GrFragmentProcessor; | |

#endif | |

/** Abstract class that generates or reads in normals for use by SkLightingShader. | |

*/ | |

class SK_API SkNormalSource : public SkFlattenable { | |

public: | |

virtual ~SkNormalSource() override; | |

#if SK_SUPPORT_GPU | |

/** Returns a fragment processor that takes no input and outputs a normal (already rotated) | |

as its output color. To be used as a child fragment processor. | |

*/ | |

virtual sk_sp<GrFragmentProcessor> asFragmentProcessor(const SkShader::AsFPArgs&) const = 0; | |

#endif | |

class Provider { | |

public: | |

virtual ~Provider() {} | |

/** Called for each span of the object being drawn on the CPU. Your subclass should set | |

the appropriate normals that correspond to the specified device coordinates. | |

*/ | |

virtual void fillScanLine(int x, int y, SkPoint3 output[], int count) const = 0; | |

}; | |

/** Returns an instance of 'Provider' that provides normals for the CPU pipeline. The | |

necessary data will be initialized in place at 'storage'. | |

*/ | |

virtual Provider* asProvider(const SkShader::ContextRec&, void* storage) const = 0; | |

/** Amount of memory needed to store a provider object and its dependencies. | |

*/ | |

virtual size_t providerSize(const SkShader::ContextRec&) const = 0; | |

/** Returns a normal source that provides normals sourced from the the normal map argument. | |

@param map a shader that outputs the normal map | |

@param ctm the current canvas' total matrix, used to rotate normals when necessary. | |

nullptr will be returned if 'map' is null | |

The normal map is currently assumed to be an 8888 image where the normal at a texel | |

is retrieved by: | |

N.x = R-127; | |

N.y = G-127; | |

N.z = B-127; | |

N.normalize(); | |

The +Z axis is thus encoded in RGB as (127, 127, 255) while the -Z axis is | |

(127, 127, 0). | |

*/ | |

static sk_sp<SkNormalSource> MakeFromNormalMap(sk_sp<SkShader> map, const SkMatrix& ctm); | |

/** Returns a normal source that provides straight-up normals only <0, 0, 1>. | |

*/ | |

static sk_sp<SkNormalSource> MakeFlat(); | |

/** This enum specifies the shape of the bevel. All bevels output <0, 0, 1> as the surface | |

* normal for any point more than 'width' away from any edge. | |

* | |

* Mathematical details: | |

* For the purpose of describing the shape of the bevel, we define 'w' to be the given width of | |

* the bevel, and 'h' to be the given height. We will assume the shape is rotated such that the | |

* point being shaded as well as the closest point in the shape's edge to that point are in the | |

* x-axis, and the shape is translated so that the aforementioned point in the edge is at | |

* coordinates (w, 0, 0) and the end of the bevel is at (0, 0, h). | |

* | |

*/ | |

enum class BevelType { | |

/* This bevel simulates a surface that is slanted from the shape's edges inwards, linearly. | |

* | |

* Mathematical details: | |

* This bevel follows a straight line from (w, 0, 0) to (0, 0, h). | |

*/ | |

kLinear, | |

/* This bevel simulates a surface that rounds off at the shape's edges, smoothly becoming | |

* perpendicular to the x-y plane. | |

* | |

* Mathematical details: | |

* This bevel follows the only quadratic bezier curve whose start point is at (w, 0, 0), | |

* control point is at (w, 0, h), and end point is at (0, 0, h). | |

*/ | |

kRoundedOut, | |

/* This bevel simulates a surface that sharply becomes perpendicular to the x-y plane when | |

* at 'width' units from the nearest edge, and then rounds off towards the shape's | |

* edge, smoothly becoming parallel to the x-y plane. | |

* | |

* Mathematical details: | |

* This bevel follows the only quadratic bezier curve whose start point is at (w, 0, 0), | |

* control point is at (0, 0, 0), and end point is at (0, 0, h). | |

*/ | |

kRoundedIn | |

}; | |

/** Returns a normal source that generates a bevel for the shape being drawn. Currently this is | |

not implemented on CPU rendering. On GPU this currently only works for anti-aliased circles | |

and rectangles. | |

@param type the type of bevel to add. | |

@param width the width of the bevel, in source space. Must be positive. | |

@param height the height of the plateau, in source space. Can be positive, negative, | |

or zero. A negative height means the simulated bevels slope downwards. | |

*/ | |

static sk_sp<SkNormalSource> MakeBevel(BevelType, SkScalar width, SkScalar height); | |

SK_DEFINE_FLATTENABLE_TYPE(SkNormalSource) | |

SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() | |

}; | |

#endif |