New class CachedScriptableMask: like CachedScriptableImage, only containing an AlphaMask instead of an Image/Bitmap.

Use CachedScriptableMask for all masks.

TODO: This introduces some duplicate code in ValueViewers that could be fixed by moving mask to the Style base class.

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1182 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2008-08-30 21:51:38 +00:00
parent acb3493b59
commit a183ecc9a6
23 changed files with 306 additions and 159 deletions
+4 -2
View File
@@ -35,7 +35,7 @@ class GeneratedImage : public ScriptValue {
mutable int width, height; ///< Width to force the image to, or 0 to keep the width of the input
///< In that case, width and height will be later set to the actual size
double zoom; ///< Zoom factor to use, when witdth=height=0
double zoom; ///< Zoom factor to use, when width=height=0
int angle; ///< Angle to rotate image by afterwards
PreserveAspect preserve_aspect;
bool saturate;
@@ -55,9 +55,10 @@ class GeneratedImage : public ScriptValue {
/// Can this image be generated safely from another thread?
virtual bool threadSafe() const { return true; }
/// Is this image specific to the set (the local_package)?
virtual bool local() const { return false; }
/// Is this image blank?
virtual bool isBlank() const { return false; }
virtual ScriptType type() const;
virtual String typeName() const;
@@ -88,6 +89,7 @@ class BlankImage : public GeneratedImage {
public:
virtual Image generate(const Options&) const;
virtual bool operator == (const GeneratedImage& that) const;
virtual bool isBlank() const { return true; }
// Why is this not thread safe? What is GTK smoking?
#ifdef __WXGTK__
+5 -4
View File
@@ -167,8 +167,9 @@ class AlphaMask : public IntrusivePtrBase<AlphaMask> {
/// Apply the alpha mask to a bitmap
void setAlpha(Bitmap& b) const;
/// Is the given location fully transparent?
bool isTransparent(int x, int y) const;
/// Is the given location opaque (not fully transparent)? when the mask were stretched to size
bool isOpaque(const RealPoint& p, const RealSize& size) const;
bool isOpaque(int x, int y) const;
/// Determine a convex hull polygon *around* the mask
void convexHull(vector<wxPoint>& points) const;
@@ -178,9 +179,9 @@ class AlphaMask : public IntrusivePtrBase<AlphaMask> {
/// Returns the start of a row, when the mask were stretched to size
/** This is: the x coordinate of the first non-transparent pixel */
double rowLeft (double y, RealSize size) const;
double rowLeft (double y, const RealSize& size) const;
/// Returns the end of a row, when the mask were stretched to size
double rowRight(double y, RealSize size) const;
double rowRight(double y, const RealSize& size) const;
/// Does this mask have the given size?
inline bool hasSize(const wxSize& compare_size) const { return size == compare_size; }
+25 -18
View File
@@ -17,9 +17,13 @@ AlphaMask::AlphaMask(const Image& img) : alpha(nullptr), lefts(nullptr), rights(
load(img);
}
AlphaMask::~AlphaMask() {
delete[] alpha;
delete[] lefts;
delete[] rights;
clear();
}
void AlphaMask::clear() {
delete[] alpha; alpha = nullptr;
delete[] lefts; lefts = nullptr;
delete[] rights; rights = nullptr;
}
void AlphaMask::load(const Image& img) {
@@ -54,10 +58,14 @@ void AlphaMask::setAlpha(Bitmap& bmp) const {
bmp = Bitmap(img);
}
bool AlphaMask::isTransparent(int x, int y) const {
bool AlphaMask::isOpaque(int x, int y) const {
if (x < 0 || y < 0 || x >= size.x || y >= size.y) return false;
if (!alpha) return true;
return alpha[x + y * size.x] < 20;
return alpha[x + y * size.x] >= 20;
}
bool AlphaMask::isOpaque(const RealPoint& p, const RealSize& resize) const {
return isOpaque((int)(p.x * size.x / resize.width)
,(int)(p.y * size.y / resize.height));
}
/// Do the points form a (counter??)clockwise angle?
@@ -72,6 +80,10 @@ void make_convex(vector<wxPoint>& points) {
points.erase(points.end() - 2);
}
}
void add_convex_point(vector<wxPoint>& points, int x, int y) {
points.push_back(wxPoint(x,y));
make_convex(points);
}
void AlphaMask::convexHull(vector<wxPoint>& points) const {
if (!alpha) throw InternalError(_("AlphaMask::convexHull"));
@@ -84,36 +96,31 @@ void AlphaMask::convexHull(vector<wxPoint>& points) const {
miny = min(miny,y);
maxy = y;
if (y == miny) {
points.push_back(wxPoint(x-1,y-1));
add_convex_point(points, x-1, y-1);
}
points.push_back(wxPoint(x-1,y));
make_convex(points);
add_convex_point(points, x-1, y);
lastx = x;
break;
}
}
}
if (maxy == -1) return; // No image
points.push_back(wxPoint(lastx-1,maxy+1));
make_convex(points);
add_convex_point(points, lastx-1, maxy+1);
// Right side, bottom to top
for (int y = maxy ; y >= miny ; --y) {
for (int x = size.x - 1 ; x >= 0 ; --x) {
if (alpha[x + y * size.x] >= 20) {
// opaque pixel
if (y == maxy) {
points.push_back(wxPoint(x+1,y+1));
make_convex(points);
add_convex_point(points, x+1, y+1);
}
points.push_back(wxPoint(x+1,y));
make_convex(points);
add_convex_point(points, x+1, y);
lastx = x;
break;
}
}
}
points.push_back(wxPoint(lastx+1,miny-1));
make_convex(points);
add_convex_point(points, lastx+1, miny-1);
}
Image AlphaMask::colorImage(const Color& color) const {
@@ -142,7 +149,7 @@ void AlphaMask::loadRowSizes() const {
}
}
double AlphaMask::rowLeft (double y, RealSize resize) const {
double AlphaMask::rowLeft (double y, const RealSize& resize) const {
loadRowSizes();
if (!lefts || y < 0 || y >= resize.height) {
// no mask, or outside it
@@ -151,7 +158,7 @@ double AlphaMask::rowLeft (double y, RealSize resize) const {
return lefts[(int)(y * resize.height / size.y)] * resize.width / size.x;
}
double AlphaMask::rowRight(double y, RealSize resize) const {
double AlphaMask::rowRight(double y, const RealSize& resize) const {
loadRowSizes();
if (!rights || y < 0 || y >= resize.height) {
// no mask, or outside it