implemented SymbolFilter

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@70 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2006-10-31 17:58:29 +00:00
parent 5b56e8ee11
commit 2dd93a91fb
10 changed files with 305 additions and 61 deletions
+135
View File
@@ -0,0 +1,135 @@
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2006 Twan van Laarhoven |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
// ----------------------------------------------------------------------------- : Includes
#include <render/symbol/filter.hpp>
#include <gfx/gfx.hpp>
#include <util/error.hpp>
// ----------------------------------------------------------------------------- : Symbol filtering
void filter_symbol(Image& symbol, const SymbolFilter& filter) {
if (!symbol.HasAlpha()) symbol.InitAlpha();
Byte* data = symbol.GetData();
Byte* alpha = symbol.GetAlpha();
UInt width = symbol.GetWidth(), height = symbol.GetHeight();
for (UInt y = 0 ; y < width ; ++y) {
for (UInt x = 0 ; x < height ; ++x) {
// Determine set
// green -> border or outside
// green+red=white -> border
SymbolSet point = data[1] ? (data[0] ? SYMBOL_BORDER : SYMBOL_OUTSIDE) : SYMBOL_INSIDE;
// Call filter
AColor result = filter.color((double)x / width, (double)y / height, point);
// Store color
data[0] = result.Red();
data[2] = result.Green();
data[2] = result.Blue();
alpha[0] = result.alpha;
// next
data += 3;
alpha += 1;
}
}
}
// ----------------------------------------------------------------------------- : SymbolFilter
IMPLEMENT_REFLECTION(SymbolFilter) {
if (!tag.reading()) {
String fill_type = fillType();
REFLECT(fill_type);
}
}
template <> void GetMember::handle(const shared_ptr<SymbolFilter>& f) {
handle(*f);
}
template <>
shared_ptr<SymbolFilter> read_new<SymbolFilter>(Reader& reader) {
// there must be a fill type specified
String fill_type;
reader.handle(_("fill type"), fill_type);
if (fill_type == _("solid")) return new_shared<SolidFillSymbolFilter>();
else if (fill_type == _("linear gradient")) return new_shared<LinearGradientSymbolFilter>();
else if (fill_type == _("radial gradient")) return new_shared<RadialGradientSymbolFilter>();
else {
throw ParseError(_("Unsupported fill type: '") + fill_type + _("'"));
}
}
// ----------------------------------------------------------------------------- : SolidFillSymbolFilter
String SolidFillSymbolFilter::fillType() const { return _("solid"); }
AColor SolidFillSymbolFilter::color(double x, double y, SymbolSet point) const {
if (point == SYMBOL_INSIDE) return fill_color;
else if (point == SYMBOL_BORDER) return border_color;
else return AColor(0,0,0,0);
}
IMPLEMENT_REFLECTION(SolidFillSymbolFilter) {
REFLECT_BASE(SymbolFilter);
REFLECT(fill_color);
REFLECT(border_color);
}
// ----------------------------------------------------------------------------- : GradientSymbolFilter
template <typename T>
AColor GradientSymbolFilter::color(double x, double y, SymbolSet point, const T* t) const {
if (point == SYMBOL_INSIDE) return lerp(fill_color_1, fill_color_2, t->t(x,y));
else if (point == SYMBOL_BORDER) return lerp(border_color_1, border_color_2, t->t(x,y));
else return AColor(0,0,0,0);
}
IMPLEMENT_REFLECTION(GradientSymbolFilter) {
REFLECT_BASE(SymbolFilter);
REFLECT(fill_color_1);
REFLECT(fill_color_2);
REFLECT(border_color_1);
REFLECT(border_color_2);
}
// ----------------------------------------------------------------------------- : LinearGradientSymbolFilter
String LinearGradientSymbolFilter::fillType() const { return _("linear gradient"); }
LinearGradientSymbolFilter::LinearGradientSymbolFilter()
: center_x(0.5), center_y(0.5)
, end_x(1), end_y(1)
{}
AColor LinearGradientSymbolFilter::color(double x, double y, SymbolSet point) const {
return GradientSymbolFilter::color(x,y,point,this);
}
double LinearGradientSymbolFilter::t(double x, double y) const {
//return abs( int(x - center_x) * dirX + int(y - centerY) * dirY) * scale;
return 0; // todo
}
IMPLEMENT_REFLECTION(LinearGradientSymbolFilter) {
REFLECT_BASE(GradientSymbolFilter);
REFLECT(center_x); REFLECT(center_y);
REFLECT(end_x); REFLECT(end_y);
}
// ----------------------------------------------------------------------------- : RadialGradientSymbolFilter
String RadialGradientSymbolFilter::fillType() const { return _("radial gradient"); }
AColor RadialGradientSymbolFilter::color(double x, double y, SymbolSet point) const {
return GradientSymbolFilter::color(x,y,point,this);
}
// TODO: move to some general util header
inline double sqr(double x) { return x * x; }
double RadialGradientSymbolFilter::t(double x, double y) const {
return sqrt( (sqr(x - 0.5) + sqr(y - 0.5)) * 2);
}
+111
View File
@@ -0,0 +1,111 @@
//+----------------------------------------------------------------------------+
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
//| Copyright: (C) 2001 - 2006 Twan van Laarhoven |
//| License: GNU General Public License 2 or later (see file COPYING) |
//+----------------------------------------------------------------------------+
#ifndef HEADER_RENDER_SYMBOL_FILTER
#define HEADER_RENDER_SYMBOL_FILTER
// ----------------------------------------------------------------------------- : Includes
#include <util/prec.hpp>
#include <util/reflect.hpp>
class SymbolFilter;
// ----------------------------------------------------------------------------- : Color
/// Color with alpha channel
class AColor : public Color {
public:
int alpha; ///< The alpha value, in the range [0..255]
inline AColor(int r, int g, int b, int a = 255) : Color(r,g,b), alpha(a) {}
inline AColor(const Color& color, int a = 255) : Color(color), alpha(a) {}
};
// ----------------------------------------------------------------------------- : Symbol filtering
/// Filter a symbol-image.
/** Filtering means that each pixel will be determined by the specified function.
* The result is stored in the symbol parameter.
*/
void filter_symbol(Image& symbol, const SymbolFilter& filter);
/// Is a point inside a symbol?
enum SymbolSet
{ SYMBOL_INSIDE
, SYMBOL_BORDER
, SYMBOL_OUTSIDE
};
// ----------------------------------------------------------------------------- : SymbolFilter
/// Base class for symbol filters
class SymbolFilter {
public:
virtual ~SymbolFilter() {}
/// What color should the symbol have at location (x, y)?
/** x,y are in the range [0...1) */
virtual AColor color(double x, double y, SymbolSet point) const = 0;
/// Name of this fill type
virtual String fillType() const = 0;
DECLARE_REFLECTION_VIRTUAL();
};
template <>
shared_ptr<SymbolFilter> read_new<SymbolFilter>(Reader& reader);
// ----------------------------------------------------------------------------- : SymbolFilter types
/// Symbol filter that returns solid colors
class SolidFillSymbolFilter : public SymbolFilter {
public:
virtual AColor color(double x, double y, SymbolSet point) const;
virtual String fillType() const;
private:
Color fill_color, border_color;
DECLARE_REFLECTION();
};
/// Symbol filter that returns some gradient
class GradientSymbolFilter : public SymbolFilter {
protected:
Color fill_color_1, border_color_1;
Color fill_color_2, border_color_2;
template <typename T>
AColor color(double x, double y, SymbolSet point, const T* t) const;
DECLARE_REFLECTION();
};
/// Symbol filter that returns a linear gradient
class LinearGradientSymbolFilter : public GradientSymbolFilter {
public:
LinearGradientSymbolFilter();
virtual AColor color(double x, double y, SymbolSet point) const;
virtual String fillType() const;
/// return time on the gradient, used by GradientSymbolFilter::color
inline double t(double x, double y) const;
private:
double center_x, center_y;
double end_x, end_y;
DECLARE_REFLECTION();
};
/// Symbol filter that returns a radial gradient
class RadialGradientSymbolFilter : public GradientSymbolFilter {
public:
virtual AColor color(double x, double y, SymbolSet point) const;
virtual String fillType() const;
/// return time on the gradient, used by GradientSymbolFilter::color
inline double t(double x, double y) const;
};
// ----------------------------------------------------------------------------- : EOF
#endif
+4 -39
View File
@@ -6,14 +6,14 @@
// ----------------------------------------------------------------------------- : Includes
#include <gui/symbol/viewer.hpp>
#include <render/symbol/viewer.hpp>
DECLARE_TYPEOF_COLLECTION(SymbolPartP);
// ----------------------------------------------------------------------------- : Constructor
SymbolViewer::SymbolViewer(const SymbolP& symbol, double borderRadius)
: borderRadius(borderRadius)
SymbolViewer::SymbolViewer(const SymbolP& symbol, double border_radius)
: border_radius(border_radius)
, rotation(0, RealRect(0,0,500,500))
{
setSymbol(symbol);
@@ -176,7 +176,7 @@ void SymbolViewer::drawSymbolPart(const SymbolPart& part, DC* border, DC* interi
// white/black
border->SetBrush(Color(borderCol, borderCol, borderCol));
}
border->SetPen(wxPen(*wxWHITE, rotation.trS(borderRadius)));
border->SetPen(wxPen(*wxWHITE, rotation.trS(border_radius)));
border->DrawPolygon((int)points.size(), &points[0]);
}
// draw interior
@@ -186,38 +186,3 @@ void SymbolViewer::drawSymbolPart(const SymbolPart& part, DC* border, DC* interi
interior->DrawPolygon((int)points.size(), &points[0]);
}
}
/*
void SymbolViewer::calcBezierPoint(const ControlPointP& p0, const ControlPointP& p1, Point*& p_out, UInt count) {
BezierCurve c(*p0, *p1);
// add start point
*p_out = toDisplay(*p0);
++p_out;
// recursively calculate rest of curve
calcBezierOpt(c, *p0, *p1, 0.0f, 1.0f, p_out, count-1);
}
void SymbolViewer::calcBezierOpt(const BezierCurve& c, const Vector2D& p0, const Vector2D& p1, double t0, double t1, Point*& p_out, mutable UInt count) {
if (count <= 0) return;
double midtime = (t0+t1) * 0.5f;
Vector2D midpoint = c.pointAt(midtime);
Vector2D d0 = p0 - midpoint;
Vector2D d1 = midpoint - p1;
// Determine treshold for subdivision, greater angle -> subdivide
// greater size -> subdivide
double treshold = fabs( atan2(d0.x,d0.y) - atan2(d1.x,d1.y)) * (p0-p1).lengthSqr();
bool subdivide = treshold >= .0001;
// subdivide left
calcBezierOpt(c, p0, midpoint, t0, midtime, p_out, count/2);
// add midpoint
if (subdivide) {
*p_out = toDisplay(midpoint);
++p_out;
count -= 1;
}
// subdivide right
calcBezierOpt(c, midpoint, p1, midtime, t1, p_out, count/2);
}
*/
+7 -2
View File
@@ -14,6 +14,11 @@
#include <data/symbol.hpp>
#include <gfx/bezier.hpp>
// ----------------------------------------------------------------------------- : Simple rendering
/// Render a Symbol to an Image
Image render_symbol(const SymbolP& symbol, double border_radius = 0.05, int size = 100);
// ----------------------------------------------------------------------------- : Symbol Viewer
enum HighlightStyle {
@@ -25,10 +30,10 @@ enum HighlightStyle {
class SymbolViewer : public SymbolView {
public:
// --------------------------------------------------- : Data
SymbolViewer(const SymbolP& symbol, double borderRadius = 0.05);
SymbolViewer(const SymbolP& symbol, double border_radius = 0.05);
// drawing
double borderRadius;
double border_radius;
// --------------------------------------------------- : Point translation