Commit 9c773fe5 authored by twanvl's avatar twanvl

implemented SymbolFilter

parent 2a871a35
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <data/field/symbol.hpp> #include <data/field/symbol.hpp>
#include <render/symbol/filter.hpp>
// ----------------------------------------------------------------------------- : SymbolField // ----------------------------------------------------------------------------- : SymbolField
...@@ -35,7 +36,7 @@ SymbolStyle::Variation::Variation() ...@@ -35,7 +36,7 @@ SymbolStyle::Variation::Variation()
IMPLEMENT_REFLECTION(SymbolStyle::Variation) { IMPLEMENT_REFLECTION(SymbolStyle::Variation) {
REFLECT(name); REFLECT(name);
REFLECT(border_radius); REFLECT(border_radius);
//REFLECT_NAMELESS(filter); REFLECT_NAMELESS(filter);
} }
// ----------------------------------------------------------------------------- : SymbolValue // ----------------------------------------------------------------------------- : SymbolValue
......
...@@ -109,5 +109,8 @@ inline int bot(int x) { return max(0, x); } ///< bottom range check for color ...@@ -109,5 +109,8 @@ inline int bot(int x) { return max(0, x); } ///< bottom range check for color
inline int top(int x) { return min(255, x); } ///< top range check for color values inline int top(int x) { return min(255, x); } ///< top range check for color values
inline int col(int x) { return top(bot(x)); } ///< top and bottom range check for color values inline int col(int x) { return top(bot(x)); } ///< top and bottom range check for color values
/// Linear interpolation between colors
Color lerp(const Color& a, const Color& b, double t);
// ----------------------------------------------------------------------------- : EOF // ----------------------------------------------------------------------------- : EOF
#endif #endif
...@@ -112,6 +112,7 @@ void GalleryList::onKeyDown(wxKeyEvent& ev) { ...@@ -112,6 +112,7 @@ void GalleryList::onKeyDown(wxKeyEvent& ev) {
} }
// Linear interpolation between colors // Linear interpolation between colors
// MOVE ME, declared in gfx.hpp
Color lerp(const Color& a, const Color& b, double t) { Color lerp(const Color& a, const Color& b, double t) {
return Color(a.Red() + (b.Red() - a.Red() ) * t, return Color(a.Red() + (b.Red() - a.Red() ) * t,
a.Green() + (b.Green() - a.Green()) * t, a.Green() + (b.Green() - a.Green()) * t,
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#include <util/prec.hpp> #include <util/prec.hpp>
#include <data/symbol.hpp> #include <data/symbol.hpp>
#include <gui/symbol/viewer.hpp> #include <render/symbol/viewer.hpp>
class SymbolWindow; class SymbolWindow;
DECLARE_POINTER_TYPE(SymbolEditorBase); DECLARE_POINTER_TYPE(SymbolEditorBase);
......
...@@ -508,24 +508,6 @@ ...@@ -508,24 +508,6 @@
<File <File
RelativePath=".\gui\symbol\select_editor.hpp"> RelativePath=".\gui\symbol\select_editor.hpp">
</File> </File>
<File
RelativePath=".\gui\symbol\viewer.cpp">
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release Unicode|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)1.obj"/>
</FileConfiguration>
</File>
<File
RelativePath=".\gui\symbol\viewer.hpp">
</File>
<File <File
RelativePath=".\gui\symbol\window.cpp"> RelativePath=".\gui\symbol\window.cpp">
<FileConfiguration <FileConfiguration
...@@ -1464,6 +1446,46 @@ ...@@ -1464,6 +1446,46 @@
RelativePath=".\render\card\viewer.hpp"> RelativePath=".\render\card\viewer.hpp">
</File> </File>
</Filter> </Filter>
<Filter
Name="symbol"
Filter="">
<File
RelativePath=".\render\symbol\filter.cpp">
</File>
<File
RelativePath=".\render\symbol\filter.hpp">
</File>
<File
RelativePath=".\render\symbol\viewer.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)3.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)3.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Debug Unicode|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)3.obj"/>
</FileConfiguration>
<FileConfiguration
Name="Release Unicode|Win32">
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)/$(InputName)3.obj"/>
</FileConfiguration>
</File>
<File
RelativePath=".\render\symbol\viewer.hpp">
</File>
</Filter>
</Filter> </Filter>
<File <File
RelativePath=".\code_template.cpp"> RelativePath=".\code_template.cpp">
......
//+----------------------------------------------------------------------------+
//| 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);
}
//+----------------------------------------------------------------------------+
//| 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 @@ ...@@ -6,14 +6,14 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <gui/symbol/viewer.hpp> #include <render/symbol/viewer.hpp>
DECLARE_TYPEOF_COLLECTION(SymbolPartP); DECLARE_TYPEOF_COLLECTION(SymbolPartP);
// ----------------------------------------------------------------------------- : Constructor // ----------------------------------------------------------------------------- : Constructor
SymbolViewer::SymbolViewer(const SymbolP& symbol, double borderRadius) SymbolViewer::SymbolViewer(const SymbolP& symbol, double border_radius)
: borderRadius(borderRadius) : border_radius(border_radius)
, rotation(0, RealRect(0,0,500,500)) , rotation(0, RealRect(0,0,500,500))
{ {
setSymbol(symbol); setSymbol(symbol);
...@@ -176,7 +176,7 @@ void SymbolViewer::drawSymbolPart(const SymbolPart& part, DC* border, DC* interi ...@@ -176,7 +176,7 @@ void SymbolViewer::drawSymbolPart(const SymbolPart& part, DC* border, DC* interi
// white/black // white/black
border->SetBrush(Color(borderCol, borderCol, borderCol)); 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]); border->DrawPolygon((int)points.size(), &points[0]);
} }
// draw interior // draw interior
...@@ -186,38 +186,3 @@ void SymbolViewer::drawSymbolPart(const SymbolPart& part, DC* border, DC* interi ...@@ -186,38 +186,3 @@ void SymbolViewer::drawSymbolPart(const SymbolPart& part, DC* border, DC* interi
interior->DrawPolygon((int)points.size(), &points[0]); 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);
}
*/
\ No newline at end of file
...@@ -14,6 +14,11 @@ ...@@ -14,6 +14,11 @@
#include <data/symbol.hpp> #include <data/symbol.hpp>
#include <gfx/bezier.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 // ----------------------------------------------------------------------------- : Symbol Viewer
enum HighlightStyle { enum HighlightStyle {
...@@ -25,10 +30,10 @@ enum HighlightStyle { ...@@ -25,10 +30,10 @@ enum HighlightStyle {
class SymbolViewer : public SymbolView { class SymbolViewer : public SymbolView {
public: public:
// --------------------------------------------------- : Data // --------------------------------------------------- : Data
SymbolViewer(const SymbolP& symbol, double borderRadius = 0.05); SymbolViewer(const SymbolP& symbol, double border_radius = 0.05);
// drawing // drawing
double borderRadius; double border_radius;
// --------------------------------------------------- : Point translation // --------------------------------------------------- : Point translation
......
...@@ -55,6 +55,7 @@ Context& ScriptManager::getContext(const StyleSheetP& stylesheet) { ...@@ -55,6 +55,7 @@ Context& ScriptManager::getContext(const StyleSheetP& stylesheet) {
ctx->setVariable(_("set"), new_intrusive1<ScriptObject<Set*> >(&set)); ctx->setVariable(_("set"), new_intrusive1<ScriptObject<Set*> >(&set));
ctx->setVariable(_("game"), toScript(set.game)); ctx->setVariable(_("game"), toScript(set.game));
ctx->setVariable(_("stylesheet"), toScript(stylesheet)); ctx->setVariable(_("stylesheet"), toScript(stylesheet));
ctx->setVariable(_("card"), set.cards.empty() ? script_nil : toScript(set.cards.front())); // dummy value
//ctx->setVariable(_("styling"), toScript(set->extraStyleData(style))); //ctx->setVariable(_("styling"), toScript(set->extraStyleData(style)));
try { try {
// perform init scripts // perform init scripts
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment