mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
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:
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
*/
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user