Commit 1440ae5c authored by twanvl's avatar twanvl

implemented resampled text ("high quality")

parent efa7a856
...@@ -21,14 +21,20 @@ StatsDimension::StatsDimension(const Field& field) ...@@ -21,14 +21,20 @@ StatsDimension::StatsDimension(const Field& field)
, description (field.description) , description (field.description)
, icon_filename(field.icon_filename) , icon_filename(field.icon_filename)
{ {
// init script! // initialize script, card.{field_name}
Script& s = script.getScript();
s.addInstruction(I_GET_VAR, string_to_variable(_("card")));
s.addInstruction(I_MEMBER_C, field.name);
s.addInstruction(I_RET);
} }
IMPLEMENT_REFLECTION(StatsDimension) { IMPLEMENT_REFLECTION(StatsDimension) {
REFLECT(name); if (!automatic) {
REFLECT(description); REFLECT(name);
REFLECT_N("icon", icon_filename); REFLECT(description);
REFLECT(script); REFLECT_N("icon", icon_filename);
REFLECT(script);
}
} }
// ----------------------------------------------------------------------------- : Statistics category // ----------------------------------------------------------------------------- : Statistics category
...@@ -53,9 +59,11 @@ IMPLEMENT_REFLECTION_ENUM(GraphType) { ...@@ -53,9 +59,11 @@ IMPLEMENT_REFLECTION_ENUM(GraphType) {
} }
IMPLEMENT_REFLECTION(StatsCategory) { IMPLEMENT_REFLECTION(StatsCategory) {
REFLECT(name); if (!automatic) {
REFLECT(description); REFLECT(name);
REFLECT_N("icon", icon_filename); REFLECT(description);
REFLECT(type); REFLECT_N("icon", icon_filename);
REFLECT(dimensions); REFLECT(type);
REFLECT(dimensions);
}
} }
...@@ -210,19 +210,19 @@ void SymbolFont::drawWithText(RotatedDC& dc, Context& ctx, const RealRect& rect, ...@@ -210,19 +210,19 @@ void SymbolFont::drawWithText(RotatedDC& dc, Context& ctx, const RealRect& rect,
if (def) { if (def) {
Bitmap bmp = def->getBitmap(ctx, *this, dc.trS(font_size)); Bitmap bmp = def->getBitmap(ctx, *this, dc.trS(font_size));
// align symbol // align symbol
sym_rect.size = dc.trInvS(RealSize(bmp.GetWidth(), bmp.GetHeight())); sym_rect.size() = dc.trInvS(RealSize(bmp.GetWidth(), bmp.GetHeight()));
sym_rect.position = align_in_rect(align, sym_rect.size, rect); sym_rect.position() = align_in_rect(align, sym_rect.size(), rect);
// draw // draw
dc.DrawBitmap(bmp, sym_rect.position); dc.DrawBitmap(bmp, sym_rect.position());
} }
// 2. draw text // 2. draw text
if (!text_font) return; if (!text_font) return;
// subtract margins from size // subtract margins from size
sym_rect.position.x += text_margin_left; sym_rect.x += text_margin_left;
sym_rect.position.y += text_margin_top; sym_rect.y += text_margin_top;
sym_rect.size.width -= text_margin_left + text_margin_right; sym_rect.width -= text_margin_left + text_margin_right;
sym_rect.size.height -= text_margin_top + text_margin_bottom; sym_rect.height -= text_margin_top + text_margin_bottom;
// setup text, shrink it // setup text, shrink it
double size = text_font->size; // TODO : incorporate shrink factor? double size = text_font->size; // TODO : incorporate shrink factor?
RealSize ts; RealSize ts;
...@@ -230,7 +230,7 @@ void SymbolFont::drawWithText(RotatedDC& dc, Context& ctx, const RealRect& rect, ...@@ -230,7 +230,7 @@ void SymbolFont::drawWithText(RotatedDC& dc, Context& ctx, const RealRect& rect,
if (size <= 0) return; // text too small if (size <= 0) return; // text too small
dc.SetFont(text_font->font, size); dc.SetFont(text_font->font, size);
ts = dc.GetTextExtent(text); ts = dc.GetTextExtent(text);
if (ts.width <= sym_rect.size.width && ts.height <= sym_rect.size.height) { if (ts.width <= sym_rect.width && ts.height <= sym_rect.height) {
break; // text fits break; // text fits
} else { } else {
// text doesn't fit // text doesn't fit
......
...@@ -36,6 +36,16 @@ enum PreserveAspect ...@@ -36,6 +36,16 @@ enum PreserveAspect
/// Resample an image, but preserve the aspect ratio by adding a transparent border around the output if needed. /// Resample an image, but preserve the aspect ratio by adding a transparent border around the output if needed.
void resample_preserve_aspect(const Image& img_in, Image& img_out); void resample_preserve_aspect(const Image& img_in, Image& img_out);
/// Draw text by first drawing it using a larger font and then downsampling it
/** optionally rotated by an angle.
* rect = rectangle to draw in
* (wc,hc) = the corner where drawing should begin, (0,0) for top-left, (1,1) for bottom-right
*/
void draw_resampled_text(DC& dc, const RealRect& rect, int wc, int hc, int angle, const String& text);
// scaling factor to use when drawing resampled text
extern const int text_scaling;
// ----------------------------------------------------------------------------- : Image rotation // ----------------------------------------------------------------------------- : Image rotation
/// Rotates an image counter clockwise /// Rotates an image counter clockwise
......
//+----------------------------------------------------------------------------+
//| 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 <gfx/gfx.hpp>
#include <util/error.hpp>
#include <gui/util.hpp> // clearDC_black
// ----------------------------------------------------------------------------- : Resampled text
// scaling factor to use when drawing resampled text
const int text_scaling = 4;
// Fills an image with the specified color
void fill_image(Image& image, const Color& color) {
Byte* pos = image.GetData();
Byte* end = image.GetData() + image.GetWidth() * image.GetHeight() * 3;
while (pos != end) {
pos[0] = color.Red();
pos[1] = color.Green();
pos[2] = color.Blue();
pos += 3;
}
}
// Downsamples the red channel of the input image to the alpha channel of the output image
// img_in must be text_scaling times as large as img_out
void downsample_to_alpha(Image& img_in, Image& img_out) {
assert(img_in.GetWidth() == img_out.GetWidth() * text_scaling);
assert(img_in.GetHeight() == img_out.GetHeight() * text_scaling);
// scale in the x direction, this overwrites parts of the input image
Byte* in = img_in.GetData();
Byte* out = img_in.GetData();
int count = img_out.GetWidth() * img_in.GetHeight();
for (int i = 0 ; i < count ; ++i) {
int total = 0;
for (int j = 0 ; j < text_scaling ; ++j) {
total += in[3 * (j + text_scaling * i)];
}
out[i] = total / text_scaling;
}
// now scale in the y direction, and write to the output alpha
img_out.InitAlpha();
out = img_out.GetAlpha();
int line_size = img_out.GetWidth();
for (int y = 0 ; y < img_out.GetHeight() ; ++y) {
for (int x = 0 ; x < img_out.GetWidth() ; ++x) {
int total = 0;
for (int j = 0 ; j < text_scaling ; ++j) {
total += in[x + line_size * (j + text_scaling * y)];
}
out[x + line_size * y] = total / text_scaling;
}
}
}
// Draw text by first drawing it using a larger font and then downsampling it
// optionally rotated by an angle
// (w2,h2) = size of text
// (wc,hc) = the corner where drawing should begin, (0,0) for top-left, (1,1) for bottom-right
void draw_resampled_text(DC& dc, const RealRect& rect, int wc, int hc, int angle, const String& text) {
// enlarge slightly
int w = rect.width + 1, h = rect.height + 1;
// determine sub-pixel position
int xi = rect.x, yi = rect.y;
int xsub = text_scaling * (rect.x - xi), ysub = text_scaling * (rect.y - yi);
// draw text
Bitmap buffer(w * text_scaling, h * text_scaling, 24); // should be initialized to black
wxMemoryDC mdc;
mdc.SelectObject(buffer);
clearDC_black(mdc);
// now draw the text
mdc.SetFont(dc.GetFont());
mdc.SetTextForeground(*wxWHITE);
mdc.DrawRotatedText(text, wc * w * text_scaling + xsub, hc * h * text_scaling + ysub, angle);
// get image
mdc.SelectObject(wxNullBitmap);
Image img_large = buffer.ConvertToImage();
// step 2. sample down
Image img_small(w, h, false);
fill_image(img_small, dc.GetTextForeground());
downsample_to_alpha(img_large, img_small);
// step 3. draw to dc
dc.DrawBitmap(img_small, xi + wc * (rect.width - w), yi + hc * (rect.height - h));
}
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <gui/control/graph.hpp> #include <gui/control/graph.hpp>
#include <util/alignment.hpp>
#include <gfx/gfx.hpp> #include <gfx/gfx.hpp>
#include <wx/dcbuffer.h> #include <wx/dcbuffer.h>
...@@ -86,8 +87,11 @@ GraphData::GraphData(const GraphDataPre& d) ...@@ -86,8 +87,11 @@ GraphData::GraphData(const GraphDataPre& d)
// ----------------------------------------------------------------------------- : Graph1D // ----------------------------------------------------------------------------- : Graph1D
bool Graph1D::findItem(const RealPoint& pos, vector<int>& out) const { void Graph1D::draw(RotatedDC& dc, const vector<int>& current) const {
int i = findItem(pos); draw(dc, axis < current.size() ? current.at(axis) : -1);
}
bool Graph1D::findItem(const RealPoint& pos, const RealRect& rect, vector<int>& out) const {
int i = findItem(pos, rect);
if (i == -1) return false; if (i == -1) return false;
else { else {
out.clear(); out.clear();
...@@ -99,11 +103,86 @@ bool Graph1D::findItem(const RealPoint& pos, vector<int>& out) const { ...@@ -99,11 +103,86 @@ bool Graph1D::findItem(const RealPoint& pos, vector<int>& out) const {
// ----------------------------------------------------------------------------- : Bar Graph // ----------------------------------------------------------------------------- : Bar Graph
void BarGraph::draw(RotatedDC& dc) const { void BarGraph::draw(RotatedDC& dc, int current) const {
// TODO if (!data) return;
// Rectangle for bars
RealRect rect = dc.getInternalRect().move(15, 5, -20, -20);
// Bar sizes
GraphAxis& axis = axis_data();
int count = int(axis.groups.size());
double width_space = rect.width / count; // including spacing
double width = width_space / 5 * 4;
double space = width_space / 5;
double step_height = rect.height / axis.max; // multiplier for bar height
// Highlight current column
Color bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
Color fg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
if (current >= 0) {
double x = rect.x + width_space * current;
dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(lerp(bg, axis.groups[current].color, 0.25));
dc.DrawRectangle(RealRect(x + space / 2 - 5, rect.bottom() + 1 + 15,
width + 10, -step_height * axis.groups[current].size - 1.999 - 20));
dc.SetBrush(lerp(bg, axis.groups[current].color, 0.5));
dc.DrawRectangle(RealRect(x + space / 2 - 2, rect.bottom() + 1 + 2,
width + 4, -step_height * axis.groups[current].size - 1.999 - 4));
}
// How many labels and lines to draw?
dc.SetFont(*wxNORMAL_FONT);
UInt label_step = max(1.0, dc.GetCharHeight() / step_height);
// Draw backlines (horizontal) and value labels
dc.SetPen(lerp(bg, fg, 0.5));
for (UInt i = 0 ; i <= axis.max ; ++i) {
if (i % label_step == 0) {
int y = rect.bottom() - i * step_height;
dc.DrawLine(RealPoint(rect.left() - 2, y), RealPoint(rect.right(), y));
// draw label, aligned middle right
String label; label << i;
RealSize text_size = dc.GetTextExtent(label);
dc.DrawText(label, align_in_rect(ALIGN_MIDDLE_RIGHT, text_size, RealRect(rect.x - 4, y, 0, 0)));
}
}
// Draw axes
dc.SetPen(fg);
dc.DrawLine(rect.bottomLeft() - RealSize(2,0), rect.bottomRight());
dc.DrawLine(rect.topLeft(), rect.bottomLeft());
// Draw bars
double x = rect.x;
FOR_EACH_CONST(g, axis.groups) {
// draw bar
dc.SetBrush(g.color);
dc.DrawRectangle(RealRect(x + space / 2, rect.bottom() + 1, width, -step_height * g.size - 1.999));
// draw label, aligned bottom center
RealSize text_size = dc.GetTextExtent(g.name);
dc.SetClippingRegion(RealRect(x + 2, rect.bottom(), width_space - 4, text_size.height));
dc.DrawText(g.name, align_in_rect(ALIGN_TOP_CENTER, text_size, RealRect(x, rect.bottom() + 3, width_space, 0)));
dc.DestroyClippingRegion();
x += width_space;
}
} }
int BarGraph::findItem(const RealPoint& pos) const { int BarGraph::findItem(const RealPoint& pos, const RealRect& rect1) const {
return -1; // TODO if (!data) return -1;
// Rectangle for bars
RealRect rect = rect1.move(15, 5, -20, -20);
// Bar sizes
GraphAxis& axis = axis_data();
int count = int(axis.groups.size());
double width_space = rect.width / count; // including spacing
double space = width_space / 5;
// Find column in which this point could be located
int col = (pos.x - rect.x) / width_space;
double in_col = (pos.x - rect.x) - col * width_space;
if (in_col < space / 2 || // left
in_col > width_space - space / 2 || // right
pos.y > rect.bottom() || // below
pos.y < rect.top()) { // above
return -1;
}
if (col < 0 || (size_t)col >= axis_data().groups.size()) {
return -1;
} else {
return col;
}
} }
// ----------------------------------------------------------------------------- : Pie Graph // ----------------------------------------------------------------------------- : Pie Graph
...@@ -136,7 +215,7 @@ void GraphControl::onPaint(wxPaintEvent&) { ...@@ -136,7 +215,7 @@ void GraphControl::onPaint(wxPaintEvent&) {
rdc.SetPen(*wxTRANSPARENT_PEN); rdc.SetPen(*wxTRANSPARENT_PEN);
rdc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); rdc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
rdc.DrawRectangle(rdc.getInternalRect()); rdc.DrawRectangle(rdc.getInternalRect());
if (graph) graph->draw(rdc); if (graph) graph->draw(rdc, current_item);
} }
void GraphControl::onSize(wxSizeEvent&) { void GraphControl::onSize(wxSizeEvent&) {
...@@ -146,7 +225,9 @@ void GraphControl::onSize(wxSizeEvent&) { ...@@ -146,7 +225,9 @@ void GraphControl::onSize(wxSizeEvent&) {
void GraphControl::onMouseDown(wxMouseEvent& ev) { void GraphControl::onMouseDown(wxMouseEvent& ev) {
if (!graph) return; if (!graph) return;
wxSize cs = GetClientSize(); wxSize cs = GetClientSize();
graph->findItem(RealPoint((double)ev.GetX()/cs.GetWidth(), (double)ev.GetY()/cs.GetHeight()), current_item); if (graph->findItem(RealPoint(ev.GetX(), ev.GetY()), RealRect(RealPoint(0,0),cs), current_item)) {
Refresh(false);
}
} }
BEGIN_EVENT_TABLE(GraphControl, wxControl) BEGIN_EVENT_TABLE(GraphControl, wxControl)
......
...@@ -83,9 +83,9 @@ class GraphData { ...@@ -83,9 +83,9 @@ class GraphData {
class Graph { class Graph {
public: public:
/// Draw this graph, filling the internalRect() of the dc. /// Draw this graph, filling the internalRect() of the dc.
virtual void draw(RotatedDC& dc) const = 0; virtual void draw(RotatedDC& dc, const vector<int>& current) const = 0;
/// Find the item at the given position, position is normalized to [0..1) /// Find the item at the given position, the rectangle gives the screen size
virtual bool findItem(const RealPoint& pos, vector<int>& out) const { return false; } virtual bool findItem(const RealPoint& pos, const RealRect& rect, vector<int>& out) const { return false; }
/// Change the data /// Change the data
virtual void setData(const GraphDataP& d) { data = d; } virtual void setData(const GraphDataP& d) { data = d; }
...@@ -98,19 +98,22 @@ class Graph { ...@@ -98,19 +98,22 @@ class Graph {
class Graph1D : public Graph { class Graph1D : public Graph {
public: public:
inline Graph1D(size_t axis) : axis(axis) {} inline Graph1D(size_t axis) : axis(axis) {}
virtual bool findItem(const RealPoint& pos, vector<int>& out) const; virtual void draw(RotatedDC& dc, const vector<int>& current) const;
virtual bool findItem(const RealPoint& pos, const RealRect& rect, vector<int>& out) const;
protected: protected:
size_t axis; size_t axis;
/// Find an item, return the position along the axis, or -1 if not found /// Find an item, return the position along the axis, or -1 if not found
virtual int findItem(const RealPoint& pos) const = 0; virtual int findItem(const RealPoint& pos, const RealRect& rect) const = 0;
virtual void draw(RotatedDC& dc, int current) const = 0;
inline GraphAxis& axis_data() const { return *data->axes.at(axis); }
}; };
/// A bar graph /// A bar graph
class BarGraph : public Graph1D { class BarGraph : public Graph1D {
public: public:
inline BarGraph(size_t axis) : Graph1D(axis) {} inline BarGraph(size_t axis) : Graph1D(axis) {}
virtual void draw(RotatedDC& dc) const; virtual void draw(RotatedDC& dc, int current) const;
virtual int findItem(const RealPoint& pos) const; virtual int findItem(const RealPoint& pos, const RealRect& rect) const;
}; };
// TODO // TODO
...@@ -121,16 +124,16 @@ class BarGraph : public Graph1D { ...@@ -121,16 +124,16 @@ class BarGraph : public Graph1D {
class PieGraph : public Graph1D { class PieGraph : public Graph1D {
public: public:
inline PieGraph(size_t axis) : Graph1D(axis) {} inline PieGraph(size_t axis) : Graph1D(axis) {}
virtual void draw(RotatedDC& dc) const; virtual void draw(RotatedDC& dc, int current) const;
virtual int findItem(const RealPoint& pos) const; virtual int findItem(const RealPoint& pos, const RealRect& rect) const;
}; };
/// The legend, used for pie graphs /// The legend, used for pie graphs
class GraphLegend : public Graph1D { class GraphLegend : public Graph1D {
public: public:
inline GraphLegend(size_t axis) : Graph1D(axis) {} inline GraphLegend(size_t axis) : Graph1D(axis) {}
virtual void draw(RotatedDC& dc) const; virtual void draw(RotatedDC& dc, int current) const;
virtual int findItem(const RealPoint& pos) const; virtual int findItem(const RealPoint& pos, const RealRect& rect) const;
}; };
//class GraphTable { //class GraphTable {
......
...@@ -124,7 +124,7 @@ SetWindow::SetWindow(Window* parent, const SetP& set) ...@@ -124,7 +124,7 @@ SetWindow::SetWindow(Window* parent, const SetP& set)
addPanel(menuWindow, tabBar, new KeywordsPanel(this, wxID_ANY), 2, _("F8"), _("Keywords"), _("Keywords"), _("Define extra keywords for this set")); addPanel(menuWindow, tabBar, new KeywordsPanel(this, wxID_ANY), 2, _("F8"), _("Keywords"), _("Keywords"), _("Define extra keywords for this set"));
addPanel(menuWindow, tabBar, new StatsPanel (this, wxID_ANY), 3, _("F9"), _("Stats"), _("Statistics"), _("Show statistics about the cards in the set")); addPanel(menuWindow, tabBar, new StatsPanel (this, wxID_ANY), 3, _("F9"), _("Stats"), _("Statistics"), _("Show statistics about the cards in the set"));
// addPanel(*s, *menuWindow, *tabBar, new DraftPanel (&this, wxID_ANY), 4, _("F10")) // addPanel(*s, *menuWindow, *tabBar, new DraftPanel (&this, wxID_ANY), 4, _("F10"))
selectPanel(ID_WINDOW_MIN + 0); // select cards panel selectPanel(ID_WINDOW_MIN + 4); // select cards panel
// loose ends // loose ends
tabBar->Realize(); tabBar->Realize();
...@@ -141,6 +141,7 @@ SetWindow::SetWindow(Window* parent, const SetP& set) ...@@ -141,6 +141,7 @@ SetWindow::SetWindow(Window* parent, const SetP& set)
SetExtraStyle(wxWS_EX_PROCESS_UI_UPDATES); SetExtraStyle(wxWS_EX_PROCESS_UI_UPDATES);
setSet(set); setSet(set);
current_panel->Layout();
} }
SetWindow::~SetWindow() { SetWindow::~SetWindow() {
...@@ -203,25 +204,6 @@ void SetWindow::selectPanel(int id) { ...@@ -203,25 +204,6 @@ void SetWindow::selectPanel(int id) {
// ----------------------------------------------------------------------------- : Set actions // ----------------------------------------------------------------------------- : Set actions
void SetWindow::onBeforeChangeSet() {
// Make sure we don't own the set's scriptUpdater
// if (set->scriptUpdater != &scriptUpdater) {
// assert(!scriptUpdater.set);
// return;
// }
// We do own the set's scriptUpdater
// stop handling updates for the set
// do this first, so events get send, which stop worker threads
// scriptUpdater.setNullSet();
// another window should take over the scriptUpdating
// FOR_EACH(wnd, SetWindows) {
// if (wnd != &this && wnd->getSet() == set) {
// wnd->scriptUpdater.setSet(set);
// break;
// }
// }
}
void SetWindow::onChangeSet() { void SetWindow::onChangeSet() {
// make sure there is always at least one card // make sure there is always at least one card
// some things need this // some things need this
......
...@@ -76,8 +76,6 @@ class SetWindow : public wxFrame, public SetView { ...@@ -76,8 +76,6 @@ class SetWindow : public wxFrame, public SetView {
// --------------------------------------------------- : Action related // --------------------------------------------------- : Action related
protected: protected:
/// We want to respond to set changes
virtual void onBeforeChangeSet();
/// We want to respond to set changes /// We want to respond to set changes
virtual void onChangeSet(); virtual void onChangeSet();
/// Actions that change the set /// Actions that change the set
......
...@@ -40,6 +40,13 @@ void clearDC(DC& dc, const wxBrush& brush) { ...@@ -40,6 +40,13 @@ void clearDC(DC& dc, const wxBrush& brush) {
dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight()); dc.DrawRectangle(0, 0, size.GetWidth(), size.GetHeight());
} }
void clearDC_black(DC& dc) {
#if !BITMAPS_DEFAULT_BLACK
// On windows 9x it seems that bitmaps are not black by default
clearDC(dc, *wxBLACK_BRUSH);
#endif
}
void draw_checker(RotatedDC& dc, const RealRect& rect) { void draw_checker(RotatedDC& dc, const RealRect& rect) {
dc.SetPen(*wxTRANSPARENT_PEN); dc.SetPen(*wxTRANSPARENT_PEN);
dc.SetBrush(*wxWHITE_BRUSH); dc.SetBrush(*wxWHITE_BRUSH);
...@@ -47,13 +54,13 @@ void draw_checker(RotatedDC& dc, const RealRect& rect) { ...@@ -47,13 +54,13 @@ void draw_checker(RotatedDC& dc, const RealRect& rect) {
dc.SetBrush(Color(235,235,235)); dc.SetBrush(Color(235,235,235));
const double checker_size = 10; const double checker_size = 10;
int odd = 0; int odd = 0;
for (double y = 0 ; y < rect.size.height ; y += checker_size) { for (double y = 0 ; y < rect.height ; y += checker_size) {
for (double x = odd * checker_size ; x < rect.size.width ; x += checker_size * 2) { for (double x = odd * checker_size ; x < rect.width ; x += checker_size * 2) {
dc.DrawRectangle(RealRect( dc.DrawRectangle(RealRect(
rect.position.x + x, rect.x + x,
rect.position.y + y, rect.y + y,
min(checker_size, rect.size.width - x), min(checker_size, rect.width - x),
min(checker_size, rect.size.height - y) min(checker_size, rect.height - y)
)); ));
} }
odd = 1 - odd; odd = 1 - odd;
......
...@@ -26,7 +26,10 @@ int focused_control(const Window* window); ...@@ -26,7 +26,10 @@ int focused_control(const Window* window);
// ----------------------------------------------------------------------------- : DC related // ----------------------------------------------------------------------------- : DC related
/// Fill a DC with a single color /// Fill a DC with a single color
void clearDC(DC& dc, const wxBrush& brush = *wxBLACK_BRUSH); void clearDC(DC& dc, const wxBrush& brush);
/// Fill a newly allocated DC with black, if the platform doesn't do so automaticly
void clearDC_black(DC& dc);
/// Draw a checkerboard pattern /// Draw a checkerboard pattern
void draw_checker(RotatedDC& dc, const RealRect&); void draw_checker(RotatedDC& dc, const RealRect&);
......
...@@ -110,7 +110,7 @@ ...@@ -110,7 +110,7 @@
Name="VCCustomBuildTool"/> Name="VCCustomBuildTool"/>
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="rpcrt4.lib wsock32.lib comctl32.lib wxbase26.lib wxmsw26_core.lib wxjpeg.lib wxpng.lib wxtiff.lib wxzlib.lib" AdditionalDependencies="rpcrt4.lib wsock32.lib comctl32.lib wxbase26.lib wxmsw26_core.lib wxjpeg.lib wxpng.lib wxtiff.lib wxzlib.lib wxregex.lib"
OutputFile="$(OutDir)/mse.exe" OutputFile="$(OutDir)/mse.exe"
LinkIncremental="1" LinkIncremental="1"
SuppressStartupBanner="TRUE" SuppressStartupBanner="TRUE"
...@@ -250,7 +250,7 @@ ...@@ -250,7 +250,7 @@
Name="VCCustomBuildTool"/> Name="VCCustomBuildTool"/>
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="rpcrt4.lib wsock32.lib comctl32.lib wxbase26u.lib wxmsw26u_core.lib wxjpeg.lib wxpng.lib wxtiff.lib wxzlib.lib" AdditionalDependencies="rpcrt4.lib wsock32.lib comctl32.lib wxbase26u.lib wxmsw26u_core.lib wxjpeg.lib wxpng.lib wxtiff.lib wxzlib.lib wxregexu.lib"
OutputFile="$(OutDir)/mse.exe" OutputFile="$(OutDir)/mse.exe"
LinkIncremental="1" LinkIncremental="1"
SuppressStartupBanner="TRUE" SuppressStartupBanner="TRUE"
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
// ----------------------------------------------------------------------------- : Includes // ----------------------------------------------------------------------------- : Includes
#include <render/symbol/viewer.hpp> #include <render/symbol/viewer.hpp>
#include <gui/util.hpp> // clearDC_black
DECLARE_TYPEOF_COLLECTION(SymbolPartP); DECLARE_TYPEOF_COLLECTION(SymbolPartP);
...@@ -29,12 +30,7 @@ MemoryDCP getTempDC(DC& dc) { ...@@ -29,12 +30,7 @@ MemoryDCP getTempDC(DC& dc) {
Bitmap buffer(s.GetWidth(), s.GetHeight(), 1); Bitmap buffer(s.GetWidth(), s.GetHeight(), 1);
MemoryDCP newDC(new wxMemoryDC); MemoryDCP newDC(new wxMemoryDC);
newDC->SelectObject(buffer); newDC->SelectObject(buffer);
// On windows 9x it seems that bitmaps are not black by default clearDC_black(*newDC);
#if !BITMAPS_DEFAULT_BLACK
newDC->SetPen(*wxTRANSPARENT_PEN);
newDC->SetBrush(*wxBLACK_BRUSH);
newDC->DrawRectangle(0, 0, s.GetWidth(), s.GetHeight());
#endif
return newDC; return newDC;
} }
......
...@@ -20,8 +20,8 @@ void TextElements::draw(RotatedDC& dc, double scale, const RealRect& rect, const ...@@ -20,8 +20,8 @@ void TextElements::draw(RotatedDC& dc, double scale, const RealRect& rect, const
size_t end_ = min(end, e->end); size_t end_ = min(end, e->end);
if (start_ < end_) { if (start_ < end_) {
e->draw(dc, scale, e->draw(dc, scale,
RealRect(rect.position.x + xs[start_-start] - xs[0], rect.position.y, RealRect(rect.x + xs[start_-start] - xs[0], rect.y,
xs[end_-start] - xs[start_-start], rect.size.height), xs[end_-start] - xs[start_-start], rect.height),
xs + start_ - start, what, start_, end_); xs + start_ - start, what, start_, end_);
} }
if (end <= e->end) return; // nothing can be after this if (end <= e->end) return; // nothing can be after this
......
...@@ -27,11 +27,11 @@ void FontTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, co ...@@ -27,11 +27,11 @@ void FontTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, co
// draw shadow // draw shadow
if (font->hasShadow()) { if (font->hasShadow()) {
dc.SetTextForeground(font->shadow_color); dc.SetTextForeground(font->shadow_color);
dc.DrawText(text.substr(start, end - start), rect.position + font->shadow_displacement); dc.DrawText(text.substr(start, end - start), rect.position() + font->shadow_displacement);
} }
// draw // draw
dc.SetTextForeground(font->color); dc.SetTextForeground(font->color);
dc.DrawText(text.substr(start, end - start), rect.position); dc.DrawText(text.substr(start, end - start), rect.position());
// } // }
} }
......
...@@ -285,14 +285,22 @@ void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP& ...@@ -285,14 +285,22 @@ void instrBinary (BinaryInstructionType i, ScriptValueP& a, const ScriptValueP&
a = toScript((String)*a + (String)*b); a = toScript((String)*a + (String)*b);
} else if (at == SCRIPT_DOUBLE || bt == SCRIPT_DOUBLE) { } else if (at == SCRIPT_DOUBLE || bt == SCRIPT_DOUBLE) {
a = toScript((double)*a + (double)*b); a = toScript((double)*a + (double)*b);
} else { } else if (at == SCRIPT_INT || bt == SCRIPT_INT) {
a = toScript((int)*a + (int)*b); a = toScript((int)*a + (int)*b);
} else {
a = toScript((String)*a + (String)*b);
} }
break; break;
case I_SUB: OPERATOR_DI(-); case I_SUB: OPERATOR_DI(-);
case I_MUL: OPERATOR_DI(*); case I_MUL: OPERATOR_DI(*);
case I_DIV: OPERATOR_DI(/); case I_DIV: OPERATOR_DI(/);
case I_MOD: // fmod case I_MOD:
if (at == SCRIPT_DOUBLE || bt == SCRIPT_DOUBLE) {
a = toScript(fmod((double)*a, (double)*b));
} else {
a = toScript((int)*a % (int)*b);
}
break;
case I_AND: OPERATOR_I(&&); case I_AND: OPERATOR_I(&&);
case I_OR: OPERATOR_I(||); case I_OR: OPERATOR_I(||);
case I_EQ: OPERATOR_SDI(==); case I_EQ: OPERATOR_SDI(==);
......
...@@ -52,6 +52,10 @@ void OptionalScript::initDependencies(Context& ctx, const Dependency& dep) const ...@@ -52,6 +52,10 @@ void OptionalScript::initDependencies(Context& ctx, const Dependency& dep) const
} }
} }
Script& OptionalScript::getScript() {
if (!script) script = new_intrusive<Script>();
return *script;
}
// custom reflection, different for each type // custom reflection, different for each type
......
...@@ -73,6 +73,9 @@ class OptionalScript { ...@@ -73,6 +73,9 @@ class OptionalScript {
/// Initialize things this script depends on by adding dep to their list of dependent scripts /// Initialize things this script depends on by adding dep to their list of dependent scripts
void initDependencies(Context&, const Dependency& dep) const; void initDependencies(Context&, const Dependency& dep) const;
/// Get access to the script, be careful
Script& getScript();
protected: protected:
ScriptP script; ///< The script, may be null if there is no script ScriptP script; ///< The script, may be null if there is no script
String unparsed; ///< Unparsed script, for writing back to a file String unparsed; ///< Unparsed script, for writing back to a file
......
...@@ -26,8 +26,8 @@ double align_delta_y(Alignment align, double box_height, double obj_height) { ...@@ -26,8 +26,8 @@ double align_delta_y(Alignment align, double box_height, double obj_height) {
RealPoint align_in_rect(Alignment align, const RealSize& to_align, const RealRect& outer) { RealPoint align_in_rect(Alignment align, const RealSize& to_align, const RealRect& outer) {
return RealPoint( return RealPoint(
outer.position.x + align_delta_x(align, outer.size.width, to_align.width), outer.x + align_delta_x(align, outer.width, to_align.width),
outer.position.y + align_delta_y(align, outer.size.height, to_align.height) outer.y + align_delta_y(align, outer.height, to_align.height)
); );
} }
......
...@@ -33,8 +33,11 @@ enum Alignment ...@@ -33,8 +33,11 @@ enum Alignment
, ALIGN_STRETCH = 0x2000 , ALIGN_STRETCH = 0x2000
// common combinations // common combinations
, ALIGN_TOP_LEFT = ALIGN_TOP | ALIGN_LEFT , ALIGN_TOP_LEFT = ALIGN_TOP | ALIGN_LEFT
, ALIGN_TOP_CENTER = ALIGN_TOP | ALIGN_CENTER
, ALIGN_TOP_RIGHT = ALIGN_TOP | ALIGN_RIGHT
, ALIGN_MIDDLE_LEFT = ALIGN_MIDDLE | ALIGN_LEFT , ALIGN_MIDDLE_LEFT = ALIGN_MIDDLE | ALIGN_LEFT
, ALIGN_MIDDLE_CENTER = ALIGN_MIDDLE | ALIGN_CENTER , ALIGN_MIDDLE_CENTER = ALIGN_MIDDLE | ALIGN_CENTER
, ALIGN_MIDDLE_RIGHT = ALIGN_MIDDLE | ALIGN_RIGHT
}; };
......
...@@ -117,33 +117,51 @@ inline RealSize addDiagonal(const RealSize& a, const RealSize& b) { ...@@ -117,33 +117,51 @@ inline RealSize addDiagonal(const RealSize& a, const RealSize& b) {
// ----------------------------------------------------------------------------- : Rectangle using doubles // ----------------------------------------------------------------------------- : Rectangle using doubles
/// A rectangle (postion and size) using real (double) coordinats /// A rectangle (postion and size) using real (double) coordinats
class RealRect { class RealRect : private RealPoint, private RealSize {
public: public:
/// Position of the top left corner using RealPoint::x;
RealPoint position; using RealPoint::y;
/// Size of the rectangle using RealSize::width;
RealSize size; using RealSize::height;
inline RealRect(const wxRect& rect) inline RealRect(const wxRect& rect)
: position(rect.x, rect.y), size(rect.width, rect.height) : RealPoint(rect.x, rect.y), RealSize(rect.width, rect.height)
{} {}
inline RealRect(const RealPoint& position, const RealSize& size) inline RealRect(const RealPoint& position, const RealSize& size)
: position(position), size(size) : RealPoint(position), RealSize(size)
{} {}
inline RealRect(double x, double y, double w, double h) inline RealRect(double x, double y, double w, double h)
: position(x,y), size(w,h) : RealPoint(x,y), RealSize(w,h)
{} {}
inline operator wxRect() const { /// Position of the top left corner
return wxRect(position.x, position.y, size.width, size.height); inline RealPoint& position() { return *this; }
} inline const RealPoint& position() const { return *this; }
/// Size of the rectangle
inline RealSize& size() { return *this; }
inline const RealSize& size() const { return *this; }
inline double left() const { return x; }
inline double right() const { return x + width; }
inline double top() const { return y; }
inline double bottom() const { return y + height; }
inline RealPoint topLeft () const { return *this; }
inline RealPoint topRight () const { return RealPoint(x + width, y); }
inline RealPoint bottomLeft () const { return RealPoint(x, y + height); }
inline RealPoint bottomRight() const { return RealPoint(x + width, y + height); }
/// Return a rectangle that is amount larger to all sides /// Return a rectangle that is amount larger to all sides
inline RealRect grow(double amount) { inline RealRect grow(double amount) {
return RealRect(position.x - amount, position.y - amount, size.width + 2 * amount, size.height + 2 * amount); return RealRect(x - amount, y - amount, width + 2 * amount, height + 2 * amount);
} }
/// Move the coordinates by some amount /// Move the coordinates by some amount
inline RealRect move(double dx, double dy, double dw, double dh) { inline RealRect move(double dx, double dy, double dw, double dh) const {
return RealRect(position.x + dx, position.y + dy, size.width + dw, size.height + dh); return RealRect(x + dx, y + dy, width + dw, height + dh);
}
inline operator wxRect() const {
return wxRect(x, y, width, height);
} }
}; };
...@@ -160,9 +178,9 @@ class RealRect { ...@@ -160,9 +178,9 @@ class RealRect {
* +----+-------+ * +----+-------+
*/ */
inline RealRect split_left(RealRect& r, double w) { inline RealRect split_left(RealRect& r, double w) {
RealRect result(r.position.x, r.position.y, w, r.size.height); RealRect result(r.x, r.y, w, r.height);
r.size.width -= w; r.width -= w;
r.position.x += w; r.x += w;
return result; return result;
} }
/// Split a rectangle horizontally /// Split a rectangle horizontally
......
...@@ -19,8 +19,8 @@ int constrain_angle(int angle) { ...@@ -19,8 +19,8 @@ int constrain_angle(int angle) {
Rotation::Rotation(int angle, const RealRect& rect, double zoom) Rotation::Rotation(int angle, const RealRect& rect, double zoom)
: angle(constrain_angle(angle)) : angle(constrain_angle(angle))
, size(rect.size) , size(rect.size())
, origin(rect.position) , origin(rect.position())
, zoom(zoom) , zoom(zoom)
{ {
// set origin // set origin
...@@ -43,7 +43,7 @@ RealSize Rotation::tr(const RealSize& s) const { ...@@ -43,7 +43,7 @@ RealSize Rotation::tr(const RealSize& s) const {
} }
} }
RealRect Rotation::tr(const RealRect& r) const { RealRect Rotation::tr(const RealRect& r) const {
return RealRect(tr(r.position), tr(r.size)); return RealRect(tr(r.position()), tr(r.size()));
} }
RealSize Rotation::trNoNeg(const RealSize& s) const { RealSize Rotation::trNoNeg(const RealSize& s) const {
...@@ -54,12 +54,12 @@ RealSize Rotation::trNoNeg(const RealSize& s) const { ...@@ -54,12 +54,12 @@ RealSize Rotation::trNoNeg(const RealSize& s) const {
} }
} }
RealRect Rotation::trNoNeg(const RealRect& r) const { RealRect Rotation::trNoNeg(const RealRect& r) const {
RealSize s = (sideways() ? RealSize(r.size.height, r.size.width) : r.size) * zoom; RealSize s = (sideways() ? RealSize(r.height, r.width) : r.size()) * zoom;
return RealRect(tr(r.position) - RealSize(revX()?s.width:0, revY()?s.height:0), s); return RealRect(tr(r.position()) - RealSize(revX()?s.width:0, revY()?s.height:0), s);
} }
RealRect Rotation::trNoNegNoZoom(const RealRect& r) const { RealRect Rotation::trNoNegNoZoom(const RealRect& r) const {
RealSize s = sideways() ? RealSize(r.size.height, r.size.width) : r.size; RealSize s = sideways() ? RealSize(r.height, r.width) : r.size();
return RealRect(tr(r.position) - RealSize(revX()?s.width:0, revY()?s.height:0), s); return RealRect(tr(r.position()) - RealSize(revX()?s.width:0, revY()?s.height:0), s);
} }
...@@ -90,8 +90,8 @@ Rotater::Rotater(Rotation& rot, const Rotation& by) ...@@ -90,8 +90,8 @@ Rotater::Rotater(Rotation& rot, const Rotation& by)
RealRect new_ext = rot.trNoNeg(by.getExternalRect()); RealRect new_ext = rot.trNoNeg(by.getExternalRect());
rot.angle = constrain_angle(rot.angle + by.angle); rot.angle = constrain_angle(rot.angle + by.angle);
rot.zoom *= by.zoom; rot.zoom *= by.zoom;
rot.size = new_ext.size; rot.size = new_ext.size();
rot.origin = new_ext.position + RealSize(rot.revX() ? rot.size.width : 0, rot.revY() ? rot.size.height : 0); rot.origin = new_ext.position() + RealSize(rot.revX() ? rot.size.width : 0, rot.revY() ? rot.size.height : 0);
} }
Rotater::~Rotater() { Rotater::~Rotater() {
...@@ -107,26 +107,21 @@ RotatedDC::RotatedDC(DC& dc, int angle, const RealRect& rect, double zoom, bool ...@@ -107,26 +107,21 @@ RotatedDC::RotatedDC(DC& dc, int angle, const RealRect& rect, double zoom, bool
RotatedDC::RotatedDC(DC& dc, const Rotation& rotation, bool high_quality = false) RotatedDC::RotatedDC(DC& dc, const Rotation& rotation, bool high_quality = false)
: Rotation(rotation) : Rotation(rotation)
, dc(dc), high_quality(high_quality) , dc(dc), high_quality(high_quality&&false)
{} {}
// ----------------------------------------------------------------------------- : RotatedDC : Drawing // ----------------------------------------------------------------------------- : RotatedDC : Drawing
void RotatedDC::DrawText (const String& text, const RealPoint& pos) { void RotatedDC::DrawText (const String& text, const RealPoint& pos) {
if (text.empty()) return; if (text.empty()) return;
// if (high_quality) { if (high_quality) {
/* RealRect r(p, getTextExtent(text)); RealRect r(pos, GetTextExtent(text));
//dc.getTextExtent(text, &r.width, &r.height)
RealRect r_ext = trNoNeg(r); RealRect r_ext = trNoNeg(r);
drawResampledText( { draw_resampled_text(dc, r_ext, revX(), revY(), angle, text);
dc, r_ext.x, r_ext.y, r_ext.width, r_ext.height,
revX(), revY(),
angle, text);
}
} else { } else {
*/ RealPoint p_ext = tr(pos); RealPoint p_ext = tr(pos);
dc.DrawRotatedText(text, p_ext.x, p_ext.y, angle); dc.DrawRotatedText(text, p_ext.x, p_ext.y, angle);
// } }
} }
void RotatedDC::DrawBitmap(const Bitmap& bitmap, const RealPoint& pos) { void RotatedDC::DrawBitmap(const Bitmap& bitmap, const RealPoint& pos) {
...@@ -165,22 +160,30 @@ void RotatedDC::SetBrush(const wxBrush& brush) { dc.SetBrush(brush); } ...@@ -165,22 +160,30 @@ void RotatedDC::SetBrush(const wxBrush& brush) { dc.SetBrush(brush); }
void RotatedDC::SetTextForeground(const Color& color) { dc.SetTextForeground(color); } void RotatedDC::SetTextForeground(const Color& color) { dc.SetTextForeground(color); }
void RotatedDC::SetLogicalFunction(int function) { dc.SetLogicalFunction(function); } void RotatedDC::SetLogicalFunction(int function) { dc.SetLogicalFunction(function); }
void RotatedDC::SetFont(const wxFont& font) { SetFont(font, font.GetPointSize()); } void RotatedDC::SetFont(const wxFont& font) {
SetFont(font, font.GetPointSize());
}
void RotatedDC::SetFont(wxFont font, double size) { void RotatedDC::SetFont(wxFont font, double size) {
font.SetPointSize(trS(size)); font.SetPointSize(trS(size) * (high_quality ? text_scaling : 1));
dc.SetFont(font); dc.SetFont(font);
} }
double RotatedDC::getFontSizeStep() const { double RotatedDC::getFontSizeStep() const {
return 1; // TODO return 1. / (high_quality ? text_scaling : 1);
// return 1. / (high_quality ? text_scaling : 1);
} }
RealSize RotatedDC::GetTextExtent(const String& text) const { RealSize RotatedDC::GetTextExtent(const String& text) const {
int w, h; int w, h;
dc.GetTextExtent(text, &w, &h); dc.GetTextExtent(text, &w, &h);
return RealSize(w,h) / zoom; return RealSize(w,h) / zoom / (high_quality ? text_scaling : 1);
} }
double RotatedDC::GetCharHeight() const { double RotatedDC::GetCharHeight() const {
return dc.GetCharHeight() / zoom; return dc.GetCharHeight() / zoom / (high_quality ? text_scaling : 1);
}
void RotatedDC::SetClippingRegion(const RealRect& rect) {
dc.SetClippingRegion(trNoNeg(rect));
}
void RotatedDC::DestroyClippingRegion() {
dc.DestroyClippingRegion();
} }
...@@ -139,17 +139,20 @@ class RotatedDC : public Rotation { ...@@ -139,17 +139,20 @@ class RotatedDC : public Rotation {
void SetBrush(const wxBrush&); void SetBrush(const wxBrush&);
void SetTextForeground(const Color&); void SetTextForeground(const Color&);
void SetLogicalFunction(int function); void SetLogicalFunction(int function);
void SetFont(const wxFont& font); void SetFont(const wxFont& font);
/// Set the font, scales for zoom and high_quality /// Set the font, scales for zoom and high_quality
/** The font will get the given (internal) point size */ /** The font will get the given (internal) point size */
void SetFont(wxFont font, double size); void SetFont(wxFont font, double size);
/// Steps to use when decrementing font size /// Steps to use when decrementing font size
double getFontSizeStep() const; double getFontSizeStep() const;
RealSize GetTextExtent(const String& text) const; RealSize GetTextExtent(const String& text) const;
double GetCharHeight() const; double GetCharHeight() const;
void SetClippingRegion(const RealRect& rect);
void DestroyClippingRegion();
inline wxDC& getDC() { return dc; } inline wxDC& getDC() { return dc; }
private: private:
......
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