mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Added functions for blurring and scaling images and changing the alpha value
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@494 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -34,6 +34,12 @@ SymbolVariation::SymbolVariation()
|
||||
{}
|
||||
SymbolVariation::~SymbolVariation() {}
|
||||
|
||||
bool SymbolVariation::operator == (const SymbolVariation& that) const {
|
||||
return name == that.name
|
||||
&& border_radius == that.border_radius
|
||||
&& *filter == *that.filter;
|
||||
}
|
||||
|
||||
IMPLEMENT_REFLECTION_NO_SCRIPT(SymbolVariation) {
|
||||
REFLECT(name);
|
||||
REFLECT(border_radius);
|
||||
|
||||
@@ -54,6 +54,9 @@ class SymbolVariation : public IntrusivePtrBase<SymbolVariation> {
|
||||
String name; ///< Name of this variation
|
||||
SymbolFilterP filter; ///< Filter to color the symbol
|
||||
double border_radius; ///< Border radius for the symbol
|
||||
|
||||
bool operator == (const SymbolVariation&) const;
|
||||
|
||||
DECLARE_REFLECTION();
|
||||
};
|
||||
|
||||
|
||||
@@ -86,3 +86,13 @@ void set_alpha(Image& img, const Image& img_alpha) {
|
||||
im[i] = (im[i] * al[i*3]) / 255;
|
||||
}
|
||||
}
|
||||
|
||||
void set_alpha(Image& img, double alpha) {
|
||||
if (!img.HasAlpha()) img.InitAlpha();
|
||||
Byte b_alpha = alpha * 255;
|
||||
Byte *im = img.GetAlpha();
|
||||
UInt size = img.GetWidth() * img.GetHeight();
|
||||
for (UInt i = 0 ; i < size ; ++i) {
|
||||
im[i] = (im[i] * b_alpha) / 255;
|
||||
}
|
||||
}
|
||||
|
||||
+157
-1
@@ -152,6 +152,20 @@ bool SetMaskImage::operator == (const GeneratedImage& that) const {
|
||||
&& *mask == *that2->mask;
|
||||
}
|
||||
|
||||
Image SetAlphaImage::generate(const Options& opt) const {
|
||||
Image img = image->generate(opt);
|
||||
set_alpha(img, alpha);
|
||||
return img;
|
||||
}
|
||||
ImageCombine SetAlphaImage::combine() const {
|
||||
return image->combine();
|
||||
}
|
||||
bool SetAlphaImage::operator == (const GeneratedImage& that) const {
|
||||
const SetAlphaImage* that2 = dynamic_cast<const SetAlphaImage*>(&that);
|
||||
return that2 && *image == *that2->image
|
||||
&& alpha == that2->alpha;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : SetCombineImage
|
||||
|
||||
Image SetCombineImage::generate(const Options& opt) const {
|
||||
@@ -166,6 +180,146 @@ bool SetCombineImage::operator == (const GeneratedImage& that) const {
|
||||
&& image_combine == that2->image_combine;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : EnlargeImage
|
||||
|
||||
Image EnlargeImage::generate(const Options& opt) const {
|
||||
// generate 'sub' image
|
||||
Options sub_opt
|
||||
( opt.width * (border_size < 0.5 ? 1 - 2 * border_size : 0)
|
||||
, opt.height * (border_size < 0.5 ? 1 - 2 * border_size : 0)
|
||||
, opt.package
|
||||
, opt.local_package
|
||||
, opt.preserve_aspect);
|
||||
Image img = image->generate(sub_opt);
|
||||
// size of generated image
|
||||
int w = img.GetWidth(), h = img.GetHeight(); // original image size
|
||||
int dw = w * border_size, dh = h * border_size; // delta
|
||||
int w2 = w + dw + dw, h2 = h + dh + dh; // new image size
|
||||
Image larger(w2,h2);
|
||||
larger.InitAlpha();
|
||||
memset(larger.GetAlpha(),0,w2*h2); // blank
|
||||
// copy to sub-part of larger image
|
||||
Byte* data1 = img.GetData(), *data2 = larger.GetData();
|
||||
for (int y = 0 ; y < h ; ++y) {
|
||||
memcpy(data2 + 3*(dw + (y+dh)*w2), data1 + 3*y*w, 3*w); // copy a line
|
||||
}
|
||||
if (img.HasAlpha()) {
|
||||
data1 = img.GetAlpha(), data2 = larger.GetAlpha();
|
||||
for (int y = 0 ; y < h ; ++y) {
|
||||
memcpy(data2 + dw + (y+dh)*w2, data1 + y*w, w); // copy a line
|
||||
}
|
||||
}
|
||||
// done
|
||||
return larger;
|
||||
}
|
||||
ImageCombine EnlargeImage::combine() const {
|
||||
return image->combine();
|
||||
}
|
||||
bool EnlargeImage::operator == (const GeneratedImage& that) const {
|
||||
const EnlargeImage* that2 = dynamic_cast<const EnlargeImage*>(&that);
|
||||
return that2 && *image == *that2->image
|
||||
&& border_size == that2->border_size;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : DropShadowImage
|
||||
|
||||
/// Preform a gaussian blur, from the image in of w*h bytes to out
|
||||
/** out is scaled some scaling, this is the return value */
|
||||
UInt gaussian_blur(Byte* in, UInt* out, int w, int h, double radius) {
|
||||
// blur horizontally
|
||||
UInt* blur_x = new UInt[w*h]; // scaled by total_x, so in [0..255*total_x]
|
||||
memset(blur_x, 0, w*h*sizeof(UInt));
|
||||
UInt total_x = 0;
|
||||
{
|
||||
double sigma = radius * w;
|
||||
double mult = (1 << 8) / (sqrt(2 * M_PI) * sigma);
|
||||
double sigsqr2 = 1 / (2 * sigma * sigma);
|
||||
int range = min(w, (int)(3*sigma));
|
||||
for (int d = -range ; d <= range ; ++d) {
|
||||
UInt factor = (int)( mult * exp(-d * d * sigsqr2) );
|
||||
total_x += factor;
|
||||
if (factor > 0) {
|
||||
int x_start = max(0, -d), x_end = min(w, w-d);
|
||||
for (int y = 0 ; y < h ; ++y) {
|
||||
for (int x = x_start ; x < x_end ; ++x) {
|
||||
blur_x[x + y*w] += in[x + d + y*w] * factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// blur vertically
|
||||
memset(out, 0, w*h*sizeof(UInt));
|
||||
UInt total_y = 0;
|
||||
{
|
||||
double sigma = radius * h;
|
||||
double mult = (1 << 8) / (sqrt(2 * M_PI) * sigma);
|
||||
double sigsqr2 = 1 / (2 * sigma * sigma);
|
||||
int range = min(h, (int)(3*sigma));
|
||||
for (int d = -range ; d <= range ; ++d) {
|
||||
UInt factor = (UInt)( mult * exp(-d * d * sigsqr2) );
|
||||
total_y += factor;
|
||||
if (factor > 0) {
|
||||
int y_start = max(0, -d), y_end = min(h, h-d);
|
||||
for (int y = y_start ; y < y_end ; ++y) {
|
||||
for (int x = 0 ; x < w ; ++x) {
|
||||
out[x + y*w] += blur_x[x + (d + y)*w] * factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] blur_x;
|
||||
return total_x * total_y;
|
||||
}
|
||||
|
||||
Image DropShadowImage::generate(const Options& opt) const {
|
||||
// sub image
|
||||
Image img = image->generate(opt);
|
||||
if (!img.HasAlpha()) {
|
||||
// no alpha, there is nothing we can do
|
||||
return img;
|
||||
}
|
||||
int w = img.GetWidth(), h = img.GetHeight();
|
||||
Byte* alpha = img.GetAlpha();
|
||||
// blur
|
||||
UInt* shadow = new UInt[w*h];
|
||||
UInt total = 255 * gaussian_blur(alpha, shadow, w, h, shadow_blur_radius);
|
||||
// combine
|
||||
Byte* data = img.GetData();
|
||||
int dw = w * offset_x, dh = h * offset_y;
|
||||
int x_start = max(0, dw), y_start = max(0, dh);
|
||||
int x_end = min(w, w+dw), y_end = min(h, h+dh);
|
||||
int delta = dw + w * dh;
|
||||
int sa = (int)(shadow_alpha * (1 << 16));
|
||||
for (int y = y_start ; y < y_end ; ++y) {
|
||||
for (int x = x_start ; x < x_end ; ++x) {
|
||||
int p = x + y * w; // pixel we are working on
|
||||
int a = alpha[p];
|
||||
int shad = ((((255 - a)*sa)>>16) * shadow[p - delta]) / total; // amount of shadow to add
|
||||
int factor = max(1, a + shad); // divide by this
|
||||
data[3 * p ] = (a * data[3 * p ] + shad * shadow_color.Red() ) / factor;
|
||||
data[3 * p + 1] = (a * data[3 * p + 1] + shad * shadow_color.Green()) / factor;
|
||||
data[3 * p + 2] = (a * data[3 * p + 2] + shad * shadow_color.Blue() ) / factor;
|
||||
alpha[p] = a + shad;
|
||||
}
|
||||
}
|
||||
//memset(data,0,3*w*h);
|
||||
// cleanup
|
||||
delete[] shadow;
|
||||
return img;
|
||||
}
|
||||
ImageCombine DropShadowImage::combine() const {
|
||||
return image->combine();
|
||||
}
|
||||
bool DropShadowImage::operator == (const GeneratedImage& that) const {
|
||||
const DropShadowImage* that2 = dynamic_cast<const DropShadowImage*>(&that);
|
||||
return that2 && *image == *that2->image
|
||||
&& offset_x == that2->offset_x && offset_y == that2->offset_y
|
||||
&& shadow_alpha == that2->shadow_alpha && shadow_blur_radius == that2->shadow_blur_radius
|
||||
&& shadow_color == that2->shadow_color;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : PackagedImage
|
||||
|
||||
Image PackagedImage::generate(const Options& opt) const {
|
||||
@@ -223,7 +377,9 @@ bool SymbolToImage::operator == (const GeneratedImage& that) const {
|
||||
const SymbolToImage* that2 = dynamic_cast<const SymbolToImage*>(&that);
|
||||
return that2 && filename == that2->filename
|
||||
&& age == that2->age
|
||||
&& variation == that2->variation;
|
||||
&& (variation == that2->variation ||
|
||||
*variation == *that2->variation // custom variation
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : ImageValueToImage
|
||||
|
||||
@@ -129,6 +129,20 @@ class SetMaskImage : public GeneratedImage {
|
||||
GeneratedImageP image, mask;
|
||||
};
|
||||
|
||||
/// Change the alpha channel of an image
|
||||
class SetAlphaImage : public GeneratedImage {
|
||||
public:
|
||||
inline SetAlphaImage(const GeneratedImageP& image, double alpha)
|
||||
: image(image), alpha(alpha)
|
||||
{}
|
||||
virtual Image generate(const Options& opt) const;
|
||||
virtual ImageCombine combine() const;
|
||||
virtual bool operator == (const GeneratedImage& that) const;
|
||||
private:
|
||||
GeneratedImageP image;
|
||||
double alpha;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : SetCombineImage
|
||||
|
||||
/// Change the combine mode
|
||||
@@ -145,6 +159,42 @@ class SetCombineImage : public GeneratedImage {
|
||||
ImageCombine image_combine;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EnlargeImage
|
||||
|
||||
/// Enlarge an image by adding a border around it
|
||||
class EnlargeImage : public GeneratedImage {
|
||||
public:
|
||||
inline EnlargeImage(const GeneratedImageP& image, double border_size)
|
||||
: image(image), border_size(abs(border_size))
|
||||
{}
|
||||
virtual Image generate(const Options& opt) const;
|
||||
virtual ImageCombine combine() const;
|
||||
virtual bool operator == (const GeneratedImage& that) const;
|
||||
private:
|
||||
GeneratedImageP image;
|
||||
double border_size;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : DropShadowImage
|
||||
|
||||
/// Add a drop shadow to an image
|
||||
class DropShadowImage : public GeneratedImage {
|
||||
public:
|
||||
inline DropShadowImage(const GeneratedImageP& image, double offset_x, double offset_y, double shadow_alpha, double shadow_blur_radius, Color shadow_color)
|
||||
: image(image), offset_x(offset_x), offset_y(offset_y)
|
||||
, shadow_alpha(shadow_alpha), shadow_blur_radius(shadow_blur_radius), shadow_color(shadow_color)
|
||||
{}
|
||||
virtual Image generate(const Options& opt) const;
|
||||
virtual ImageCombine combine() const;
|
||||
virtual bool operator == (const GeneratedImage& that) const;
|
||||
private:
|
||||
GeneratedImageP image;
|
||||
double offset_x, offset_y;
|
||||
double shadow_alpha;
|
||||
double shadow_blur_radius;
|
||||
Color shadow_color;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : PackagedImage
|
||||
|
||||
/// Load an image from a file in a package
|
||||
|
||||
@@ -123,6 +123,8 @@ void draw_combine_image(DC& dc, UInt x, UInt y, const Image& img, ImageCombine c
|
||||
|
||||
/// Use the red channel of img_alpha as alpha channel for img
|
||||
void set_alpha(Image& img, const Image& img_alpha);
|
||||
/// Set the transparency of img
|
||||
void set_alpha(Image& img, double alpha);
|
||||
|
||||
/// An alpha mask is an alpha channel that can be copied to another image
|
||||
/** It is created by treating black in the source image as transparent and white (red) as opaque
|
||||
|
||||
@@ -86,6 +86,12 @@ AColor SolidFillSymbolFilter::color(double x, double y, SymbolSet point) const {
|
||||
else return AColor(0,0,0,0);
|
||||
}
|
||||
|
||||
bool SolidFillSymbolFilter::operator == (const SymbolFilter& that) const {
|
||||
const SolidFillSymbolFilter* that2 = dynamic_cast<const SolidFillSymbolFilter*>(&that);
|
||||
return that2 && fill_color == that2->fill_color
|
||||
&& border_color == that2->border_color;
|
||||
}
|
||||
|
||||
IMPLEMENT_REFLECTION(SolidFillSymbolFilter) {
|
||||
REFLECT_BASE(SymbolFilter);
|
||||
REFLECT(fill_color);
|
||||
@@ -101,6 +107,13 @@ AColor GradientSymbolFilter::color(double x, double y, SymbolSet point, const T*
|
||||
else return AColor(0,0,0,0);
|
||||
}
|
||||
|
||||
bool GradientSymbolFilter::equal(const GradientSymbolFilter& that) const {
|
||||
return fill_color_1 == that.fill_color_1
|
||||
&& fill_color_2 == that.fill_color_2
|
||||
&& border_color_1 == that.border_color_1
|
||||
&& border_color_2 == that.border_color_2;
|
||||
}
|
||||
|
||||
IMPLEMENT_REFLECTION(GradientSymbolFilter) {
|
||||
REFLECT_BASE(SymbolFilter);
|
||||
REFLECT(fill_color_1);
|
||||
@@ -120,6 +133,14 @@ LinearGradientSymbolFilter::LinearGradientSymbolFilter()
|
||||
: center_x(0.5), center_y(0.5)
|
||||
, end_x(1), end_y(1)
|
||||
{}
|
||||
LinearGradientSymbolFilter::LinearGradientSymbolFilter
|
||||
( const Color& fill_color_1, const Color& border_color_1
|
||||
, const Color& fill_color_2, const Color& border_color_2
|
||||
, double center_x, double center_y, double end_x, double end_y)
|
||||
: GradientSymbolFilter(fill_color_1, border_color_1, fill_color_2, border_color_2)
|
||||
, center_x(center_x), center_y(center_y)
|
||||
, end_x(end_x), end_y(end_y)
|
||||
{}
|
||||
|
||||
AColor LinearGradientSymbolFilter::color(double x, double y, SymbolSet point) const {
|
||||
len = sqr(end_x - center_x) + sqr(end_y - center_y);
|
||||
@@ -132,6 +153,13 @@ double LinearGradientSymbolFilter::t(double x, double y) const {
|
||||
return min(1.,max(0.,t));
|
||||
}
|
||||
|
||||
bool LinearGradientSymbolFilter::operator == (const SymbolFilter& that) const {
|
||||
const LinearGradientSymbolFilter* that2 = dynamic_cast<const LinearGradientSymbolFilter*>(&that);
|
||||
return that2 && equal(*that2)
|
||||
&& center_x == that2->center_x && end_x == that2->end_x
|
||||
&& center_y == that2->center_y && end_y == that2->end_y;
|
||||
}
|
||||
|
||||
IMPLEMENT_REFLECTION(LinearGradientSymbolFilter) {
|
||||
REFLECT_BASE(GradientSymbolFilter);
|
||||
REFLECT(center_x); REFLECT(center_y);
|
||||
@@ -149,3 +177,8 @@ AColor RadialGradientSymbolFilter::color(double x, double y, SymbolSet point) co
|
||||
double RadialGradientSymbolFilter::t(double x, double y) const {
|
||||
return sqrt( (sqr(x - 0.5) + sqr(y - 0.5)) * 2);
|
||||
}
|
||||
|
||||
bool RadialGradientSymbolFilter::operator == (const SymbolFilter& that) const {
|
||||
const RadialGradientSymbolFilter* that2 = dynamic_cast<const RadialGradientSymbolFilter*>(&that);
|
||||
return that2 && equal(*that2);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ class SymbolFilter : public IntrusivePtrVirtualBase {
|
||||
virtual AColor color(double x, double y, SymbolSet point) const = 0;
|
||||
/// Name of this fill type
|
||||
virtual String fillType() const = 0;
|
||||
/// Comparision
|
||||
virtual bool operator == (const SymbolFilter& that) const = 0;
|
||||
|
||||
DECLARE_REFLECTION_VIRTUAL();
|
||||
};
|
||||
@@ -66,8 +68,13 @@ intrusive_ptr<SymbolFilter> read_new<SymbolFilter>(Reader& reader);
|
||||
/// Symbol filter that returns solid colors
|
||||
class SolidFillSymbolFilter : public SymbolFilter {
|
||||
public:
|
||||
inline SolidFillSymbolFilter() {}
|
||||
inline SolidFillSymbolFilter(Color fill_color, Color border_color)
|
||||
: fill_color(fill_color), border_color(border_color)
|
||||
{}
|
||||
virtual AColor color(double x, double y, SymbolSet point) const;
|
||||
virtual String fillType() const;
|
||||
virtual bool operator == (const SymbolFilter& that) const;
|
||||
private:
|
||||
Color fill_color, border_color;
|
||||
DECLARE_REFLECTION();
|
||||
@@ -75,11 +82,18 @@ class SolidFillSymbolFilter : public SymbolFilter {
|
||||
|
||||
/// Symbol filter that returns some gradient
|
||||
class GradientSymbolFilter : public SymbolFilter {
|
||||
public:
|
||||
inline GradientSymbolFilter() {}
|
||||
inline GradientSymbolFilter(const Color& fill_color_1, const Color& border_color_1, const Color& fill_color_2, const Color& border_color_2)
|
||||
: fill_color_1(fill_color_1), border_color_1(border_color_1)
|
||||
, fill_color_2(fill_color_2), border_color_2(border_color_2)
|
||||
{}
|
||||
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;
|
||||
bool equal(const GradientSymbolFilter& that) const;
|
||||
|
||||
DECLARE_REFLECTION();
|
||||
};
|
||||
@@ -88,9 +102,12 @@ class GradientSymbolFilter : public SymbolFilter {
|
||||
class LinearGradientSymbolFilter : public GradientSymbolFilter {
|
||||
public:
|
||||
LinearGradientSymbolFilter();
|
||||
LinearGradientSymbolFilter(const Color& fill_color_1, const Color& border_color_1, const Color& fill_color_2, const Color& border_color_2
|
||||
,double center_x, double center_y, double end_x, double end_y);
|
||||
|
||||
virtual AColor color(double x, double y, SymbolSet point) const;
|
||||
virtual String fillType() const;
|
||||
virtual bool operator == (const SymbolFilter& that) const;
|
||||
|
||||
/// return time on the gradient, used by GradientSymbolFilter::color
|
||||
inline double t(double x, double y) const;
|
||||
@@ -105,8 +122,14 @@ class LinearGradientSymbolFilter : public GradientSymbolFilter {
|
||||
/// Symbol filter that returns a radial gradient
|
||||
class RadialGradientSymbolFilter : public GradientSymbolFilter {
|
||||
public:
|
||||
inline RadialGradientSymbolFilter() {}
|
||||
inline RadialGradientSymbolFilter(const Color& fill_color_1, const Color& border_color_1, const Color& fill_color_2, const Color& border_color_2)
|
||||
: GradientSymbolFilter(fill_color_1, border_color_1, fill_color_2, border_color_2)
|
||||
{}
|
||||
|
||||
virtual AColor color(double x, double y, SymbolSet point) const;
|
||||
virtual String fillType() const;
|
||||
virtual bool operator == (const SymbolFilter& that) const;
|
||||
|
||||
/// return time on the gradient, used by GradientSymbolFilter::color
|
||||
inline double t(double x, double y) const;
|
||||
|
||||
@@ -180,7 +180,7 @@ void SymbolViewer::drawSymbolPart(const SymbolPart& part, DC* border, DC* interi
|
||||
segment_subdivide(*part.getPoint((int)i), *part.getPoint((int)i+1), rotation, points);
|
||||
}
|
||||
// draw border
|
||||
if (border) {
|
||||
if (border && border_radius > 0) {
|
||||
// white/black or, if directB white/green
|
||||
border->SetBrush(Color(borderCol, (directB && borderCol == 0 ? 128 : borderCol), borderCol));
|
||||
border->SetPen(wxPen(*wxWHITE, (int) rotation.trS(border_radius)));
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <data/symbol.hpp>
|
||||
#include <data/field/symbol.hpp>
|
||||
#include <gfx/generated_image.hpp>
|
||||
#include <render/symbol/filter.hpp>
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(SymbolVariationP);
|
||||
|
||||
@@ -61,6 +62,12 @@ SCRIPT_FUNCTION(set_mask) {
|
||||
return new_intrusive2<SetMaskImage>(image, mask);
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(set_alpha) {
|
||||
SCRIPT_PARAM(GeneratedImageP, input);
|
||||
SCRIPT_PARAM(double, alpha);
|
||||
return new_intrusive2<SetAlphaImage>(input, alpha);
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(set_combine) {
|
||||
SCRIPT_PARAM(String, combine);
|
||||
SCRIPT_PARAM(GeneratedImageP, input);
|
||||
@@ -71,24 +78,72 @@ SCRIPT_FUNCTION(set_combine) {
|
||||
return new_intrusive2<SetCombineImage>(input, image_combine);
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(enlarge) {
|
||||
SCRIPT_PARAM(GeneratedImageP, input);
|
||||
SCRIPT_PARAM_N(double, _("border size"), border_size);
|
||||
return new_intrusive2<EnlargeImage>(input, border_size);
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(drop_shadow) {
|
||||
SCRIPT_PARAM(GeneratedImageP, input);
|
||||
SCRIPT_OPTIONAL_PARAM_N_(double, _("offset x"), offset_x);
|
||||
SCRIPT_OPTIONAL_PARAM_N_(double, _("offset y"), offset_y);
|
||||
SCRIPT_OPTIONAL_PARAM_N_(double, _("alpha"), alpha);
|
||||
SCRIPT_OPTIONAL_PARAM_N_(double, _("blur radius"), blur_radius);
|
||||
SCRIPT_OPTIONAL_PARAM_N_(Color, _("color"), color);
|
||||
return new_intrusive6<DropShadowImage>(input, offset_x, offset_y, alpha, blur_radius, color);
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(symbol_variation) {
|
||||
// find symbol
|
||||
SCRIPT_PARAM(ValueP, symbol);
|
||||
SymbolValueP value = dynamic_pointer_cast<SymbolValue>(symbol);
|
||||
SCRIPT_PARAM(String, variation);
|
||||
// find style
|
||||
SCRIPT_PARAM(Set*, set);
|
||||
SCRIPT_OPTIONAL_PARAM_(CardP, card);
|
||||
SymbolStyleP style = dynamic_pointer_cast<SymbolStyle>(set->stylesheetForP(card)->styleFor(value->fieldP));
|
||||
if (!style) throw InternalError(_("Symbol value has a style of the wrong type"));
|
||||
// find variation
|
||||
FOR_EACH(v, style->variations) {
|
||||
if (v->name == variation) {
|
||||
// found it
|
||||
return new_intrusive3<SymbolToImage>(value->filename, value->last_update, v);
|
||||
SCRIPT_OPTIONAL_PARAM(String, variation) {
|
||||
// find style
|
||||
SCRIPT_PARAM(Set*, set);
|
||||
SCRIPT_OPTIONAL_PARAM_(CardP, card);
|
||||
SymbolStyleP style = dynamic_pointer_cast<SymbolStyle>(set->stylesheetForP(card)->styleFor(value->fieldP));
|
||||
if (!style) throw InternalError(_("Symbol value has a style of the wrong type"));
|
||||
// find variation
|
||||
FOR_EACH(v, style->variations) {
|
||||
if (v->name == variation) {
|
||||
// found it
|
||||
return new_intrusive3<SymbolToImage>(value->filename, value->last_update, v);
|
||||
}
|
||||
}
|
||||
throw ScriptError(_("Variation of symbol not found ('") + variation + _("')"));
|
||||
} else {
|
||||
// custom variation
|
||||
SCRIPT_PARAM_N(double, _("border radius"), border_radius);
|
||||
SCRIPT_OPTIONAL_PARAM_N_(String, _("fill type"), fill_type);
|
||||
SymbolVariationP var(new SymbolVariation);
|
||||
var->border_radius = border_radius;
|
||||
if (fill_type == _("solid") || fill_type.empty()) {
|
||||
SCRIPT_PARAM_N(Color, _("fill color"), fill_color);
|
||||
SCRIPT_PARAM_N(Color, _("border color"), border_color);
|
||||
var->filter = new_intrusive2<SolidFillSymbolFilter>(fill_color, border_color);
|
||||
} else if (fill_type == _("linear gradient")) {
|
||||
SCRIPT_PARAM_N(Color, _("fill color 1"), fill_color_1);
|
||||
SCRIPT_PARAM_N(Color, _("border color 1"), border_color_1);
|
||||
SCRIPT_PARAM_N(Color, _("fill color 2"), fill_color_2);
|
||||
SCRIPT_PARAM_N(Color, _("border color 2"), border_color_2);
|
||||
SCRIPT_PARAM_N(double, _("center x"), center_x);
|
||||
SCRIPT_PARAM_N(double, _("center y"), center_y);
|
||||
SCRIPT_PARAM_N(double, _("end x"), end_x);
|
||||
SCRIPT_PARAM_N(double, _("end y"), end_y);
|
||||
var->filter = new_intrusive8<LinearGradientSymbolFilter>(fill_color_1, border_color_1, fill_color_2, border_color_2
|
||||
,center_x, center_y, end_x, end_y);
|
||||
} else if (fill_type == _("radial gradient")) {
|
||||
SCRIPT_PARAM_N(Color, _("fill color 1"), fill_color_1);
|
||||
SCRIPT_PARAM_N(Color, _("border color 1"), border_color_1);
|
||||
SCRIPT_PARAM_N(Color, _("fill color 2"), fill_color_2);
|
||||
SCRIPT_PARAM_N(Color, _("border color 2"), border_color_2);
|
||||
var->filter = new_intrusive4<RadialGradientSymbolFilter>(fill_color_1, border_color_1, fill_color_2, border_color_2);
|
||||
} else {
|
||||
throw ScriptError(_("Unknown fill type for symbol_variation: ") + fill_type);
|
||||
}
|
||||
return new_intrusive3<SymbolToImage>(value->filename, value->last_update, var);
|
||||
}
|
||||
throw ScriptError(_("Variation of symbol not found ('") + variation + _("')"));
|
||||
}
|
||||
|
||||
SCRIPT_FUNCTION(built_in_image) {
|
||||
@@ -103,7 +158,10 @@ void init_script_image_functions(Context& ctx) {
|
||||
ctx.setVariable(_("masked blend"), script_masked_blend);
|
||||
ctx.setVariable(_("combine blend"), script_combine_blend);
|
||||
ctx.setVariable(_("set mask"), script_set_mask);
|
||||
ctx.setVariable(_("set alpha"), script_set_alpha);
|
||||
ctx.setVariable(_("set combine"), script_set_combine);
|
||||
ctx.setVariable(_("enlarge"), script_enlarge);
|
||||
ctx.setVariable(_("drop shadow"), script_drop_shadow);
|
||||
ctx.setVariable(_("symbol variation"), script_symbol_variation);
|
||||
ctx.setVariable(_("built in image"), script_built_in_image);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,10 @@ GeneratedImageP image_from_script(const ScriptValueP& value) {
|
||||
// ----------------------------------------------------------------------------- : ScriptableImage
|
||||
|
||||
Image ScriptableImage::generate(const GeneratedImage::Options& options, bool cache) const {
|
||||
if (cached.Ok() && cached.GetWidth() == options.width && cached.GetHeight() == options.height) {
|
||||
if (cached.Ok() && (cached.GetWidth() == options.width && cached.GetHeight() == options.height
|
||||
|| (options.preserve_aspect == ASPECT_FIT && // only one dimension has to fit
|
||||
(cached.GetWidth() == options.width || cached.GetHeight() == options.height)
|
||||
))) {
|
||||
// cached, so we are done
|
||||
return cached;
|
||||
}
|
||||
|
||||
@@ -274,6 +274,7 @@ template <> inline String from_script<String> (const ScriptValueP& va
|
||||
template <> inline int from_script<int> (const ScriptValueP& value) { return *value; }
|
||||
template <> inline double from_script<double> (const ScriptValueP& value) { return *value; }
|
||||
template <> inline bool from_script<bool> (const ScriptValueP& value) { return *value; }
|
||||
template <> inline Color from_script<Color> (const ScriptValueP& value) { return *value; }
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user