Moved mask to Style and mask related drawing to ValueViewer.

Used the same mask also for TextStyles.
To keep the text selectable (since the mask is now also used for containsPoint), the future sight cost masks needed to be updated.

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@1183 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2008-08-30 23:49:12 +00:00
parent a183ecc9a6
commit a2af3211a4
28 changed files with 105 additions and 214 deletions
+9 -6
View File
@@ -118,6 +118,7 @@ IMPLEMENT_REFLECTION(Style) {
REFLECT(bottom);
REFLECT(angle);
REFLECT(visible);
REFLECT(mask);
}
void init_object(const FieldP& field, StyleP& style) {
@@ -135,15 +136,16 @@ inline bool is_setw(const Scriptable<double>& x) {
}
int Style::update(Context& ctx) {
bool changed =
left .update(ctx)
int changed =
( left .update(ctx)
| width .update(ctx)
| right .update(ctx)
| top .update(ctx)
| height .update(ctx)
| bottom .update(ctx)
| angle .update(ctx)
| visible.update(ctx);
| angle .update(ctx) ) * CHANGE_SIZE
| visible.update(ctx) * CHANGE_OTHER
| mask .update(ctx) * CHANGE_MASK;
// determine automatic_side and attachment of rotation point
if (automatic_side == AUTO_UNKNOWN) {
if (!is_set (right)) automatic_side = (AutomaticSide)(automatic_side | AUTO_RIGHT);
@@ -154,7 +156,7 @@ int Style::update(Context& ctx) {
else if (!is_setw(height)) automatic_side = (AutomaticSide)(automatic_side | AUTO_HEIGHT);
else if (!is_set (top)) automatic_side = (AutomaticSide)(automatic_side | AUTO_TOP);
else automatic_side = (AutomaticSide)(automatic_side | AUTO_TB);
changed = true;
changed |= CHANGE_SIZE;
}
if (!changed) return CHANGE_NONE;
// update the automatic_side
@@ -181,7 +183,7 @@ int Style::update(Context& ctx) {
if (width < 0) width = -width;
if (height < 0) height = -height;
// done
return CHANGE_OTHER;
return changed;
}
bool Style::isVisible() const {
@@ -214,6 +216,7 @@ void Style::checkContentDependencies(Context& ctx, const Dependency& dep) const
right .initDependencies(ctx,dep);
bottom .initDependencies(ctx,dep);
visible.initDependencies(ctx,dep);
mask .initDependencies(ctx,dep);
}
void Style::markDependencyMember(const String& name, const Dependency& dep) const {
+14 -9
View File
@@ -16,6 +16,7 @@
#include <util/rotation.hpp>
#include <script/scriptable.hpp>
#include <script/dependency.hpp>
#include <script/image.hpp>
DECLARE_POINTER_TYPE(Field);
DECLARE_POINTER_TYPE(Style);
@@ -94,13 +95,16 @@ class Style : public IntrusivePtrVirtualBase {
Style(const FieldP&);
virtual ~Style();
const FieldP fieldP; ///< Field this style is for, should have the right type!
int z_index; ///< Stacking of values of this field, higher = on top
Scriptable<double> left, top; ///< Position of this field
Scriptable<double> width, height; ///< Position of this field
Scriptable<double> right, bottom; ///< Position of this field
Scriptable<int> angle; ///< Rotation of the box
Scriptable<bool> visible; ///< Is this field visible?
const FieldP fieldP; ///< Field this style is for, should have the right type!
int z_index; ///< Stacking of values of this field, higher = on top
Scriptable<double> left, top; ///< Position of this field
Scriptable<double> width, height; ///< Position of this field
Scriptable<double> right, bottom; ///< Position of this field
Scriptable<int> angle; ///< Rotation of the box
Scriptable<bool> visible; ///< Is this field visible?
CachedScriptableMask mask; ///< Mask image
enum AutomaticSide {
AUTO_UNKNOWN = 0x00,
AUTO_LEFT = 0x01, AUTO_WIDTH = 0x02, AUTO_RIGHT = 0x04, AUTO_LR = 0x08,
@@ -166,8 +170,9 @@ class Style : public IntrusivePtrVirtualBase {
enum StyleChange
{ CHANGE_NONE = 0x00 // nothing changed
, CHANGE_OTHER = 0x01 // some other change (note: result of casting from bool)
, CHANGE_DEFAULT = 0x02 // only the 'default' state is affected
, CHANGE_MASK = 0x04 // a mask image changed, must be reloaded
, CHANGE_SIZE = 0x02 // size/angle changed
, CHANGE_DEFAULT = 0x04 // only the 'default' state is affected
, CHANGE_MASK = 0x08 // a mask image changed, must be reloaded
, CHANGE_ALREADY_PREPARED = 0x80 // hint that the change was the result of a content property change, viewers are already prepared
};
+2 -4
View File
@@ -213,9 +213,8 @@ void ChoiceStyle::initImage() {
int ChoiceStyle::update(Context& ctx) {
// Don't update the choice images, leave that to invalidate()
int change = Style ::update(ctx)
| font .update(ctx) * CHANGE_OTHER
| mask .update(ctx) * CHANGE_MASK;
int change = Style::update(ctx)
| font .update(ctx) * CHANGE_OTHER;
if (!choice_images_initialized) {
// we only want to do this once because it is rather slow, other updates are handled by dependencies
choice_images_initialized = true;
@@ -283,7 +282,6 @@ IMPLEMENT_REFLECTION(ChoiceStyle) {
REFLECT_BASE(Style);
REFLECT(popup_style);
REFLECT(render_style);
REFLECT(mask);
REFLECT(combine);
REFLECT(alignment);
REFLECT(font);
-1
View File
@@ -146,7 +146,6 @@ class ChoiceStyle : public Style {
CachedScriptableImage image; ///< Image to draw (when RENDER_IMAGE)
map<String,ScriptableImage> choice_images; ///< Images for the various choices (when RENDER_IMAGE)
bool choice_images_initialized;
CachedScriptableMask mask; ///< Mask image
ImageCombine combine; ///< Combining mode for drawing the images
Alignment alignment; ///< Alignment of images
wxImageList* thumbnails; ///< Thumbnails for the choices
+1 -3
View File
@@ -62,13 +62,11 @@ IMPLEMENT_REFLECTION(ColorStyle) {
REFLECT(right_width);
REFLECT(top_width);
REFLECT(bottom_width);
REFLECT(mask);
REFLECT(combine);
}
int ColorStyle::update(Context& ctx) {
return Style::update(ctx)
| mask.update(ctx) * CHANGE_MASK;
return Style::update(ctx);
}
// ----------------------------------------------------------------------------- : ColorValue
+6 -7
View File
@@ -57,13 +57,12 @@ class ColorStyle : public Style {
ColorStyle(const ColorFieldP& field);
DECLARE_STYLE_TYPE(Color);
double radius; ///< Radius of round corners
double left_width; ///< Width of the colored region on the left side
double right_width; ///< Width of the colored region on the right side
double top_width; ///< Width of the colored region on the top side
double bottom_width; ///< Width of the colored region on the bottom side
CachedScriptableMask mask; ///< Mask image
ImageCombine combine; ///< How to combine image with the background
double radius; ///< Radius of round corners
double left_width; ///< Width of the colored region on the left side
double right_width; ///< Width of the colored region on the right side
double top_width; ///< Width of the colored region on the top side
double bottom_width; ///< Width of the colored region on the bottom side
ImageCombine combine; ///< How to combine image with the background
virtual int update(Context&);
};
-2
View File
@@ -23,13 +23,11 @@ IMPLEMENT_REFLECTION(ImageField) {
IMPLEMENT_REFLECTION(ImageStyle) {
REFLECT_BASE(Style);
REFLECT(mask);
REFLECT_N("default", default_image);
}
int ImageStyle::update(Context& ctx) {
return Style ::update(ctx)
| mask .update(ctx) * CHANGE_MASK
| default_image.update(ctx) * CHANGE_DEFAULT;
}
+1 -2
View File
@@ -35,8 +35,7 @@ class ImageStyle : public Style {
inline ImageStyle(const ImageFieldP& field) : Style(field) {}
DECLARE_STYLE_TYPE(Image);
CachedScriptableMask mask; ///< Mask image
ScriptableImage default_image; ///< Placeholder
ScriptableImage default_image; ///< Placeholder
virtual int update(Context&);
};
-1
View File
@@ -111,7 +111,6 @@ IMPLEMENT_REFLECTION(TextStyle) {
REFLECT(line_height_hard_max);
REFLECT(line_height_line_max);
REFLECT(paragraph_height);
REFLECT_N("mask", mask_filename);
REFLECT(direction);
reflect_content(tag, *this);
}
-2
View File
@@ -67,8 +67,6 @@ class TextStyle : public Style {
double line_height_hard_max; ///< Maximum line height
double line_height_line_max; ///< Maximum line height
double paragraph_height; ///< Fixed height of paragraphs
String mask_filename; ///< Filename of the mask
AlphaMask mask; ///< Mask to fit the text to (may be null)
Direction direction; ///< In what direction is text layed out?
// information from text rendering
double content_width, content_height; ///< Size of the rendered text
+16 -7
View File
@@ -60,12 +60,21 @@ void AlphaMask::setAlpha(Bitmap& bmp) 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;
if (alpha) {
return alpha[x + y * size.x] >= 20;
} else {
return true;
}
}
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));
if (p.x < 0 || p.y < 0 || p.x >= resize.width || p.y >= resize.height) return false;
if (alpha) {
int x = (int)(p.x * size.x / resize.width);
int y = (int)(p.y * size.y / resize.height);
return alpha[x + y * size.x] >= 20;
} else {
return true;
}
}
/// Do the points form a (counter??)clockwise angle?
@@ -141,7 +150,7 @@ void AlphaMask::loadRowSizes() const {
lefts[y] = size.x;
rights[y] = 0;
for (int x = 0 ; x < size.x ; ++x) {
if (alpha[y * size.x + x] > 64) { // white enough
if (alpha[y * size.x + x] >= 128) { // white enough
rights[y] = x;
if (x < lefts[y]) lefts[y] = x;
}
@@ -155,7 +164,7 @@ double AlphaMask::rowLeft (double y, const RealSize& resize) const {
// no mask, or outside it
return 0;
}
return lefts[(int)(y * resize.height / size.y)] * resize.width / size.x;
return lefts[(int)(y * size.y / resize.height)] * resize.width / size.x;
}
double AlphaMask::rowRight(double y, const RealSize& resize) const {
@@ -164,5 +173,5 @@ double AlphaMask::rowRight(double y, const RealSize& resize) const {
// no mask, or outside it
return resize.width;
}
return rights[(int)(y * resize.height / size.y)] * resize.width / size.x;
return rights[(int)(y * size.y / resize.height)] * resize.width / size.x;
}
+2 -2
View File
@@ -661,10 +661,10 @@ bool TextViewer::prepareLinesScale(RotatedDC& dc, const vector<CharInfo>& chars,
}
double TextViewer::lineLeft(RotatedDC& dc, const TextStyle& style, double y) const {
return style.mask.rowLeft(y, dc.getInternalSize()) + style.padding_left;
return style.mask.getFromCache().rowLeft(y, dc.getInternalSize()) + style.padding_left;
}
double TextViewer::lineRight(RotatedDC& dc, const TextStyle& style, double y) const {
return style.mask.rowRight(y, dc.getInternalSize()) - style.padding_right;
return style.mask.getFromCache().rowRight(y, dc.getInternalSize()) - style.padding_right;
}
+1 -31
View File
@@ -22,46 +22,16 @@ bool ChoiceValueViewer::prepare(RotatedDC& dc) {
return prepare_choice_viewer(dc, *this, style(), value().value());
}
void ChoiceValueViewer::draw(RotatedDC& dc) {
int w = max(0,(int)dc.trX(style().width)), h = max(0,(int)dc.trY(style().height));
const AlphaMask& alpha_mask = getMask(w,h);
drawFieldBorder(dc, alpha_mask);
drawFieldBorder(dc);
if (style().render_style & RENDER_HIDDEN) return;
draw_choice_viewer(dc, *this, style(), value().value());
}
void ChoiceValueViewer::drawFieldBorder(RotatedDC& dc, const AlphaMask& alpha_mask) {
if (!alpha_mask.isLoaded()) {
ValueViewer::drawFieldBorder(dc);
} else if (setFieldBorderPen(dc)) {
dc.SetBrush(*wxTRANSPARENT_BRUSH);
vector<wxPoint> points;
alpha_mask.convexHull(points);
if (points.size() < 3) return;
FOR_EACH(p, points) p = dc.trPixelNoZoom(RealPoint(p.x,p.y));
dc.getDC().DrawPolygon((int)points.size(), &points[0]);
}
}
bool ChoiceValueViewer::containsPoint(const RealPoint& p) const {
// check against mask
return getMask(0,0).isOpaque(p, style().getSize());
}
void ChoiceValueViewer::onStyleChange(int changes) {
if (changes & CHANGE_MASK) style().image.clearCache();
ValueViewer::onStyleChange(changes);
}
const AlphaMask& ChoiceValueViewer::getMask(int w, int h) const {
GeneratedImage::Options opts;
opts.package = &viewer.getStylePackage();
opts.local_package = &viewer.getLocalPackage();
opts.angle = 0;
opts.width = w;
opts.height = h;
return style().mask.get(opts);
}
// ----------------------------------------------------------------------------- : Generic draw/prepare
bool prepare_choice_viewer(RotatedDC& dc, ValueViewer& viewer, ChoiceStyle& style, const String& value) {
-9
View File
@@ -23,19 +23,10 @@ class ChoiceValueViewer : public ValueViewer {
virtual bool prepare(RotatedDC& dc);
virtual void draw(RotatedDC& dc);
virtual void onStyleChange(int);
virtual bool containsPoint(const RealPoint& p) const;
private:
/// Draws a border around the field
void drawFieldBorder(RotatedDC& dc, const AlphaMask& alpha_mask);
/// Load the AlphaMask for this field
const AlphaMask& getMask(int w, int h) const;
};
bool prepare_choice_viewer(RotatedDC& dc, ValueViewer& viewer, ChoiceStyle& style, const String& value);
void draw_choice_viewer(RotatedDC& dc, ValueViewer& viewer, ChoiceStyle& style, const String& value);
const AlphaMask& get_mask(RotatedDC& dc, ValueViewer& viewer, ChoiceStyle& style, int w, int h);
// ----------------------------------------------------------------------------- : EOF
#endif
+3 -27
View File
@@ -44,8 +44,7 @@ void ColorValueViewer::draw(RotatedDC& dc) {
dc.DrawText(color_name, RealPoint(43, 3));
} else {
// is there a mask?
int w = max(0,(int)dc.trX(style().width)), h = max(0,(int)dc.trY(style().height));
const AlphaMask& alpha_mask = getMask(w,h);
const AlphaMask& alpha_mask = getMask(dc);
if (alpha_mask.isLoaded()) {
dc.DrawImage(alpha_mask.colorImage(value().value()), RealPoint(0,0), style().combine);
} else {
@@ -66,26 +65,13 @@ void ColorValueViewer::draw(RotatedDC& dc) {
dc.DrawRoundedRectangle(style().getInternalRect(), style().radius);
if (clip) dc.getDC().DestroyClippingRegion();
}
drawFieldBorder(dc, alpha_mask);
}
}
void ColorValueViewer::drawFieldBorder(RotatedDC& dc, const AlphaMask& alpha_mask) {
if (!alpha_mask.isLoaded()) {
ValueViewer::drawFieldBorder(dc);
} else if (setFieldBorderPen(dc)) {
dc.SetBrush(*wxTRANSPARENT_BRUSH);
vector<wxPoint> points;
alpha_mask.convexHull(points);
if (points.size() < 3) return;
FOR_EACH(p, points) p = dc.trPixelNoZoom(RealPoint(p.x,p.y));
dc.getDC().DrawPolygon((int)points.size(), &points[0]);
drawFieldBorder(dc);
}
}
bool ColorValueViewer::containsPoint(const RealPoint& p) const {
// check against mask
const AlphaMask& alpha_mask = getMask(0,0);
const AlphaMask& alpha_mask = getMask();
if (alpha_mask.isLoaded()) {
// check against mask
return alpha_mask.isOpaque(p, style().getSize());
@@ -98,13 +84,3 @@ bool ColorValueViewer::containsPoint(const RealPoint& p) const {
|| top < style().top_width || bottom < style().bottom_width; // inside vertical border
}
}
const AlphaMask& ColorValueViewer::getMask(int w, int h) const {
GeneratedImage::Options opts;
opts.package = &viewer.getStylePackage();
opts.local_package = &viewer.getLocalPackage();
opts.angle = 0;
opts.width = w;
opts.height = h;
return style().mask.get(opts);
}
-6
View File
@@ -24,12 +24,6 @@ class ColorValueViewer : public ValueViewer {
virtual void draw(RotatedDC& dc);
virtual bool containsPoint(const RealPoint& p) const;
private:
/// Draws a border around the field
void drawFieldBorder(RotatedDC& dc, const AlphaMask& alpha_mask);
/// Load the AlphaMask for this field
const AlphaMask& getMask(int w, int h) const;
};
// ----------------------------------------------------------------------------- : EOF
+1 -29
View File
@@ -74,31 +74,13 @@ void ImageValueViewer::draw(RotatedDC& dc) {
}
}
// border
drawFieldBorder(dc, alpha_mask);
drawFieldBorder(dc);
// draw image, if any
if (bitmap.Ok()) {
dc.DrawPreRotatedBitmap(bitmap, dc.getInternalRect());
}
}
void ImageValueViewer::drawFieldBorder(RotatedDC& dc, const AlphaMask& alpha_mask) {
if (!alpha_mask.isLoaded()) {
ValueViewer::drawFieldBorder(dc);
} else if (setFieldBorderPen(dc)) {
dc.SetBrush(*wxTRANSPARENT_BRUSH);
vector<wxPoint> points;
alpha_mask.convexHull(points);
if (points.size() < 3) return;
FOR_EACH(p, points) p = dc.trPixelNoZoom(RealPoint(p.x,p.y));
dc.getDC().DrawPolygon((int)points.size(), &points[0]);
}
}
bool ImageValueViewer::containsPoint(const RealPoint& p) const {
// check against mask
return getMask(0,0).isOpaque(p, style().getSize());
}
void ImageValueViewer::onValueChange() {
bitmap = Bitmap();
}
@@ -111,16 +93,6 @@ void ImageValueViewer::onStyleChange(int changes) {
ValueViewer::onStyleChange(changes);
}
const AlphaMask& ImageValueViewer::getMask(int w, int h) const {
GeneratedImage::Options opts;
opts.package = &viewer.getStylePackage();
opts.local_package = &viewer.getLocalPackage();
opts.angle = 0;
opts.width = w;
opts.height = h;
return style().mask.get(opts);
}
// is an image very light?
bool very_light(const Image& image) {
int w = image.GetWidth(), h = image.GetHeight();
-9
View File
@@ -23,9 +23,6 @@ class ImageValueViewer : public ValueViewer {
DECLARE_VALUE_VIEWER(Image) : ValueViewer(parent,style) {}
virtual void draw(RotatedDC& dc);
virtual bool containsPoint(const RealPoint& p) const;
virtual void onValueChange();
virtual void onStyleChange(int);
@@ -37,12 +34,6 @@ class ImageValueViewer : public ValueViewer {
/// Generate a placeholder image
static Bitmap imagePlaceholder(const Rotation& rot, UInt w, UInt h, const Image& background, bool editing);
/// Draws a border around the field
void drawFieldBorder(RotatedDC& dc, const AlphaMask& alpha_mask);
/// Load the AlphaMask for this field
const AlphaMask& getMask(int w, int h) const;
};
// ----------------------------------------------------------------------------- : EOF
+1 -31
View File
@@ -25,9 +25,7 @@ bool MultipleChoiceValueViewer::prepare(RotatedDC& dc) {
}
void MultipleChoiceValueViewer::draw(RotatedDC& dc) {
int w = max(0,(int)dc.trX(style().width)), h = max(0,(int)dc.trY(style().height));
const AlphaMask& alpha_mask = getMask(w,h);
drawFieldBorder(dc, alpha_mask);
drawFieldBorder(dc);
if (style().render_style & RENDER_HIDDEN) return;
RealPoint pos = align_in_rect(style().alignment, RealSize(0,0), style().getInternalRect());
// selected choices
@@ -86,35 +84,7 @@ void MultipleChoiceValueViewer::drawChoice(RotatedDC& dc, RealPoint& pos, const
pos = move_in_direction(style().direction, pos, size, style().spacing);
}
void MultipleChoiceValueViewer::drawFieldBorder(RotatedDC& dc, const AlphaMask& alpha_mask) {
if (!alpha_mask.isLoaded()) {
ValueViewer::drawFieldBorder(dc);
} else if (setFieldBorderPen(dc)) {
dc.SetBrush(*wxTRANSPARENT_BRUSH);
vector<wxPoint> points;
alpha_mask.convexHull(points);
if (points.size() < 3) return;
FOR_EACH(p, points) p = dc.trPixelNoZoom(RealPoint(p.x,p.y));
dc.getDC().DrawPolygon((int)points.size(), &points[0]);
}
}
bool MultipleChoiceValueViewer::containsPoint(const RealPoint& p) const {
// check against mask
return getMask(0,0).isOpaque(p, style().getSize());
}
void MultipleChoiceValueViewer::onStyleChange(int changes) {
if (changes & CHANGE_MASK) style().image.clearCache();
ValueViewer::onStyleChange(changes);
}
const AlphaMask& MultipleChoiceValueViewer::getMask(int w, int h) const {
GeneratedImage::Options opts;
opts.package = &viewer.getStylePackage();
opts.local_package = &viewer.getLocalPackage();
opts.angle = 0;
opts.width = w;
opts.height = h;
return style().mask.get(opts);
}
-5
View File
@@ -23,15 +23,10 @@ class MultipleChoiceValueViewer : public ValueViewer {
virtual bool prepare(RotatedDC& dc);
virtual void draw(RotatedDC& dc);
virtual void onStyleChange(int);
virtual bool containsPoint(const RealPoint& p) const;
protected:
double item_height; ///< Height of a single item, or 0 if non uniform
private:
void drawChoice(RotatedDC& dc, RealPoint& pos, const String& choice, bool active = true);
/// Draws a border around the field
void drawFieldBorder(RotatedDC& dc, const AlphaMask& alpha_mask);
/// Load the AlphaMask for this field
const AlphaMask& getMask(int w, int h) const;
};
// ----------------------------------------------------------------------------- : EOF
+1 -8
View File
@@ -15,14 +15,7 @@
IMPLEMENT_VALUE_VIEWER(Text);
bool TextValueViewer::prepare(RotatedDC& dc) {
if (!style().mask_filename.empty() && !style().mask.isLoaded()) {
// load contour mask
Image image;
InputStreamP image_file = getStylePackage().openIn(style().mask_filename);
if (image.LoadFile(*image_file)) {
style().mask.load(image);
}
}
getMask(dc); // ensure alpha/contour mask is loaded
return v.prepare(dc, value().value(), style(), viewer.getContext());
}
+24 -5
View File
@@ -10,6 +10,8 @@
#include <render/value/viewer.hpp>
#include <render/card/viewer.hpp>
DECLARE_TYPEOF_COLLECTION(wxPoint);
// ----------------------------------------------------------------------------- : ValueViewer
ValueViewer::ValueViewer(DataViewer& parent, const StyleP& style)
@@ -27,10 +29,7 @@ void ValueViewer::setValue(const ValueP& value) {
}
bool ValueViewer::containsPoint(const RealPoint& p) const {
return p.x >= 0
&& p.y >= 0
&& p.x < styleP->width
&& p.y < styleP->height;
return getMask().isOpaque(p, styleP->getSize());
}
RealRect ValueViewer::boundingBox() const {
return styleP->getExternalRect().grow(1);
@@ -54,10 +53,30 @@ bool ValueViewer::setFieldBorderPen(RotatedDC& dc) {
void ValueViewer::drawFieldBorder(RotatedDC& dc) {
if (setFieldBorderPen(dc)) {
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawRectangle(dc.getInternalRect().grow(dc.trInvS(1)));
const AlphaMask& alpha_mask = getMask(dc);
if (alpha_mask.isLoaded()) {
// from mask
vector<wxPoint> points;
alpha_mask.convexHull(points);
if (points.size() < 3) return;
FOR_EACH(p, points) p = dc.trPixelNoZoom(RealPoint(p.x,p.y));
dc.getDC().DrawPolygon((int)points.size(), &points[0]);
} else {
// simple rectangle
dc.DrawRectangle(dc.getInternalRect().grow(dc.trInvS(1)));
}
}
}
const AlphaMask& ValueViewer::getMask(int w, int h) const {
GeneratedImage::Options opts(w, h, &getStylePackage(), &getLocalPackage());
return styleP->mask.get(opts);
}
const AlphaMask& ValueViewer::getMask(const Rotation& rot) const {
return getMask((int)rot.trX(styleP->width), (int)rot.trY(styleP->height));
}
void ValueViewer::redraw() {
viewer.redraw(*this);
}
+4
View File
@@ -83,6 +83,10 @@ class ValueViewer : public StyleListener {
/// Redraw this viewer
void redraw();
/// Load the AlphaMask for this field, scaled but not rotated
const AlphaMask& getMask(int w = 0, int h = 0) const;
const AlphaMask& getMask(const Rotation& rot) const;
public:
/// Should this viewer render using a platform native look?
bool nativeLook() const;
+1 -1
View File
@@ -211,7 +211,7 @@ const AlphaMask& CachedScriptableMask::get(const GeneratedImage::Options& img_op
getNoCache(img_options,mask);
return mask;
}
void CachedScriptableMask::getNoCache(const GeneratedImage::Options& img_options, AlphaMask& other_mask) {
void CachedScriptableMask::getNoCache(const GeneratedImage::Options& img_options, AlphaMask& other_mask) const {
if (script.isBlank()) {
other_mask.clear();
} else {
+12 -2
View File
@@ -117,12 +117,22 @@ class CachedScriptableMask {
/// Update the script, returns true if the value has changed
bool update(Context& ctx);
inline void initDependencies(Context& ctx, const Dependency& dep) const {
script.initDependencies(ctx, dep);
}
/// Get the alpha mask; with the given options
/** if img_options.width == 0 and the mask is already loaded, just returns it. */
/** if img_options.width == 0 and the mask is already loaded, just returns it.
* Returns a reference, so calling again might change earlier results.
*/
const AlphaMask& get(const GeneratedImage::Options& img_options);
/// Get a mask that is not cached
void getNoCache(const GeneratedImage::Options& img_options, AlphaMask& mask);
void getNoCache(const GeneratedImage::Options& img_options, AlphaMask& mask) const;
/// Get the mask directly from the cache, without updating
/** Should only be used after get() was called before, otherwise an old mask might be returned */
inline const AlphaMask& getFromCache() const { return mask; }
private:
ScriptableImage script;