mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Implemented printing (finally)
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@272 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
+133
-30
@@ -10,9 +10,12 @@
|
||||
#include <gui/card_select_window.hpp>
|
||||
#include <gui/util.hpp>
|
||||
#include <data/set.hpp>
|
||||
#include <data/stylesheet.hpp>
|
||||
#include <render/card/viewer.hpp>
|
||||
#include <wx/print.h>
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(CardP);
|
||||
DECLARE_POINTER_TYPE(PageLayout);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Buffering DC
|
||||
|
||||
@@ -31,7 +34,7 @@ DECLARE_TYPEOF_COLLECTION(CardP);
|
||||
*/
|
||||
class TextBufferDC : public wxMemoryDC {
|
||||
public:
|
||||
TextBufferDC(UInt width, UInt height);
|
||||
TextBufferDC(int width, int height);
|
||||
|
||||
virtual void DoDrawText(const String& str, int x, int y);
|
||||
virtual void DoDrawRotatedText(const String& str, int x, int y, double angle);
|
||||
@@ -47,9 +50,10 @@ class TextBufferDC : public wxMemoryDC {
|
||||
int x, y;
|
||||
String text;
|
||||
double angle;
|
||||
double user_scale_x, user_scale_y;
|
||||
|
||||
TextDraw(wxFont font, Color color, int x, int y, String text, double angle = 0)
|
||||
: font(font), color(color), x(x), y(y), text(text), angle(angle)
|
||||
TextDraw(wxFont font, Color color, double user_scale_x, double user_scale_y, int x, int y, String text, double angle = 0)
|
||||
: font(font), color(color), user_scale_x(user_scale_x), user_scale_y(user_scale_y), x(x), y(y), text(text), angle(angle)
|
||||
{}
|
||||
};
|
||||
public:
|
||||
@@ -59,7 +63,7 @@ class TextBufferDC : public wxMemoryDC {
|
||||
Bitmap buffer;
|
||||
};
|
||||
|
||||
TextBufferDC::TextBufferDC(UInt width, UInt height)
|
||||
TextBufferDC::TextBufferDC(int width, int height)
|
||||
: buffer(width, height, 32)
|
||||
{
|
||||
SelectObject(buffer);
|
||||
@@ -67,10 +71,14 @@ TextBufferDC::TextBufferDC(UInt width, UInt height)
|
||||
clearDC(*this,*wxWHITE_BRUSH);
|
||||
}
|
||||
void TextBufferDC::DoDrawText(const String& str, int x, int y) {
|
||||
text.push_back( new_shared5<TextDraw>(GetFont(), GetTextForeground(), x, y, str) );
|
||||
double usx,usy;
|
||||
GetUserScale(&usx, &usy);
|
||||
text.push_back( new_shared7<TextDraw>(GetFont(), GetTextForeground(), usx, usy, x, y, str) );
|
||||
}
|
||||
void TextBufferDC::DoDrawRotatedText(const String& str, int x, int y, double angle) {
|
||||
text.push_back( new_shared6<TextDraw>(GetFont(), GetTextForeground(), x, y, str, angle) );
|
||||
double usx,usy;
|
||||
GetUserScale(&usx, &usy);
|
||||
text.push_back( new_shared8<TextDraw>(GetFont(), GetTextForeground(), usx, usy, x, y, str, angle) );
|
||||
}
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(TextBufferDC::TextDrawP);
|
||||
@@ -79,6 +87,9 @@ void TextBufferDC::drawToDevice(DC& dc, int x, int y) {
|
||||
SelectObject(wxNullBitmap);
|
||||
dc.DrawBitmap(buffer, x, y);
|
||||
FOR_EACH(t, text) {
|
||||
double usx,usy;
|
||||
dc.GetUserScale(&usx, &usy);
|
||||
dc.SetUserScale(usx * t->user_scale_x, usx * t->user_scale_y);
|
||||
dc.SetFont (t->font);
|
||||
dc.SetTextForeground(t->color);
|
||||
if (t->angle) {
|
||||
@@ -86,45 +97,139 @@ void TextBufferDC::drawToDevice(DC& dc, int x, int y) {
|
||||
} else {
|
||||
dc.DrawText(t->text, t->x + x, t->y + y);
|
||||
}
|
||||
dc.SetUserScale(usx, usy);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Layout
|
||||
|
||||
/// Layout of a page of cards
|
||||
class PageLayout {
|
||||
public:
|
||||
RealSize card_size; ///< Size of a card
|
||||
RealSize card_space; ///< Spacing between cards
|
||||
double margin_left, margin_right, margin_top, margin_bottom; ///< Page margins
|
||||
int rows, cols; ///< Number of rows/columns of cards
|
||||
bool landscape; ///< Are cards rotated to landscape orientation?
|
||||
};
|
||||
PageLayout::PageLayout()
|
||||
: margin_left(0), margin_right(0), margin_top(0), margin_bottom(0)
|
||||
, rows(0), cols(0), card_landscape(false)
|
||||
{}
|
||||
|
||||
PageLayout::PageLayout(const StyleSheet& stylesheet, const RealSize& page_size)
|
||||
: page_size(page_size)
|
||||
, margin_left(0), margin_right(0), margin_top(0), margin_bottom(0)
|
||||
{
|
||||
card_size.width = stylesheet.card_width * 25.4 / stylesheet.card_dpi;
|
||||
card_size.height = stylesheet.card_height * 25.4 / stylesheet.card_dpi;
|
||||
card_landscape = card_size.width > card_size.height;
|
||||
cols = floor(page_size.width / card_size.width);
|
||||
rows = floor(page_size.height / card_size.height);
|
||||
// distribute whitespace evenly
|
||||
margin_left = margin_right = card_spacing.width = (page_size.width - (cols * card_size.width )) / (cols + 1);
|
||||
margin_top = margin_bottom = card_spacing.height = (page_size.height - (rows * card_size.height)) / (rows + 1);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Printout
|
||||
|
||||
/// A printout object specifying how to print a specified set of cards
|
||||
class CardsPrintout : wxPrintout {
|
||||
class CardsPrintout : public wxPrintout {
|
||||
public:
|
||||
CardsPrintout(const SetP& set, const vector<CardP>& cards);
|
||||
/// Determine card size, cards per row
|
||||
void OnPreparePrinting();
|
||||
/// Number of pages, and something else I don't understand...
|
||||
void GetPageInfo(int* pageMin, int* pageMax, int* pageFrom, int* pageTo);
|
||||
virtual void GetPageInfo(int* pageMin, int* pageMax, int* pageFrom, int* pageTo);
|
||||
/// Again, 'number of pages', strange wx interface
|
||||
bool HasPage(int page);
|
||||
virtual bool HasPage(int page);
|
||||
/// Determine the layout
|
||||
virtual void OnPreparePrinting();
|
||||
/// Print a page
|
||||
bool OnPrintPage(int page);
|
||||
virtual bool OnPrintPage(int page);
|
||||
|
||||
private:
|
||||
PageLayout layout;
|
||||
PageLayoutP layout;
|
||||
SetP set;
|
||||
vector<CardP> cards; ///< Cards to print
|
||||
DataViewer viewer;
|
||||
double scale_x, scale_y; // priter pixel per mm
|
||||
|
||||
inline int pageCount() {
|
||||
return ((int)cards.size() + layout->cardsPerPage() - 1) / layout->cardsPerPage();
|
||||
}
|
||||
|
||||
/// Draw a card, that is card_nr on this page, find the postion by asking the layout
|
||||
void drawCard(DC& dc, const CardP& card, size_t card_nr);
|
||||
/// Draw a card at the specified coordinates
|
||||
void drawCard(DC& dc, const CardP& card, double x, double y, int rotation = 0);
|
||||
void drawCard(DC& dc, const CardP& card, int card_nr);
|
||||
};
|
||||
|
||||
CardsPrintout::CardsPrintout(const SetP& set, const vector<CardP>& cards)
|
||||
: set(set), cards(cards)
|
||||
{
|
||||
viewer.setSet(set);
|
||||
}
|
||||
|
||||
void CardsPrintout::GetPageInfo(int* page_min, int* page_max, int* page_from, int* page_to) {
|
||||
*page_from = *page_min = 1;
|
||||
*page_to = *page_max = pageCount();
|
||||
}
|
||||
|
||||
bool CardsPrintout::HasPage(int page) {
|
||||
return page <= pageCount(); // page number is 1 based
|
||||
}
|
||||
|
||||
void CardsPrintout::OnPreparePrinting() {
|
||||
int pw_mm, ph_mm;
|
||||
GetPageSizeMM(&pw_mm, &ph_mm);
|
||||
if (!layout) {
|
||||
layout = new_shared2<PageLayout>(*set->stylesheet, RealSize(pw_mm, ph_mm));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CardsPrintout::OnPrintPage(int page) {
|
||||
DC& dc = *GetDC();
|
||||
// scale factors
|
||||
int pw_mm, ph_mm;
|
||||
GetPageSizeMM(&pw_mm, &ph_mm);
|
||||
int pw_px, ph_px;
|
||||
dc.GetSize(&pw_px, &ph_px);
|
||||
scale_x = (double)pw_px / pw_mm;
|
||||
scale_y = (double)ph_px / ph_mm;
|
||||
// print the cards that belong on this page
|
||||
int start = (page - 1) * layout->cardsPerPage();
|
||||
int end = min((int)cards.size(), start + layout->cardsPerPage());
|
||||
for (int i = start ; i < end ; ++i) {
|
||||
drawCard(dc, cards[i], i - start);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CardsPrintout::drawCard(DC& dc, const CardP& card, int card_nr) {
|
||||
// determine position
|
||||
int col = card_nr % layout->cols;
|
||||
int row = card_nr / layout->cols;
|
||||
RealPoint pos( layout->margin_left + (layout->card_size.width + layout->card_spacing.width) * col
|
||||
, layout->margin_top + (layout->card_size.height + layout->card_spacing.height) * row);
|
||||
// determine rotation
|
||||
StyleSheet& stylesheet = *set->stylesheetFor(card);
|
||||
int rotation = 0;
|
||||
if ((stylesheet.card_width > stylesheet.card_height) != layout->card_landscape) {
|
||||
rotation = 90 - rotation;
|
||||
}
|
||||
/*
|
||||
// size of this particular card (in mm)
|
||||
RealSize card_size( stylesheet.card_width * 25.4 / stylesheet.card_dpi
|
||||
, stylesheet.card_height * 25.4 / stylesheet.card_dpi);
|
||||
if (rotation == 90) swap(card_size.width, card_size.height);
|
||||
// adjust card size, to center card in the available space (from layout->card_size)?
|
||||
// TODO
|
||||
*/
|
||||
|
||||
// create buffers
|
||||
int w = stylesheet.card_width, h = stylesheet.card_height; // in pixels
|
||||
if (rotation == 90) swap(w,h);
|
||||
TextBufferDC bufferDC(w,h);
|
||||
RotatedDC rdc(bufferDC, rotation, RealRect(0,0,w,h), 1.0, QUALITY_SUB_PIXEL);
|
||||
// render card to dc
|
||||
viewer.setCard(card);
|
||||
viewer.draw(rdc, *wxWHITE);
|
||||
// render buffer to device
|
||||
double px_per_mm = stylesheet.card_dpi / 25.4;
|
||||
dc.SetUserScale(scale_x / px_per_mm, scale_y / px_per_mm);
|
||||
dc.SetDeviceOrigin(scale_x * pos.x, scale_y * pos.y);
|
||||
bufferDC.drawToDevice(dc, 0, 0); // adjust for scaling
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : PrintWindow
|
||||
|
||||
void print_preview(Window* parent, const SetP& set) {
|
||||
@@ -137,8 +242,8 @@ void print_preview(Window* parent, const SetP& set) {
|
||||
FOR_EACH(c, set->cards) {
|
||||
if (wnd.isSelected(c)) selected.push_back(c);
|
||||
}
|
||||
/* // Show the print preview
|
||||
wxPreviewFrame frame = new wxPreviewFrame(
|
||||
// Show the print preview
|
||||
wxPreviewFrame* frame = new wxPreviewFrame(
|
||||
new wxPrintPreview(
|
||||
new CardsPrintout(set, selected),
|
||||
new CardsPrintout(set, selected)
|
||||
@@ -146,7 +251,6 @@ void print_preview(Window* parent, const SetP& set) {
|
||||
frame->Initialize();
|
||||
frame->Maximize(true);
|
||||
frame->Show();
|
||||
*/
|
||||
}
|
||||
|
||||
void print_set(Window* parent, const SetP& set) {
|
||||
@@ -159,9 +263,8 @@ void print_set(Window* parent, const SetP& set) {
|
||||
FOR_EACH(c, set->cards) {
|
||||
if (wnd.isSelected(c)) selected.push_back(c);
|
||||
}
|
||||
/* // Print the cards
|
||||
// Print the cards
|
||||
wxPrinter p;
|
||||
CardsPrintout pout(set, selected);
|
||||
p.Print(parent, &pout, true);
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -10,8 +10,11 @@
|
||||
// ----------------------------------------------------------------------------- : Includes
|
||||
|
||||
#include <util/prec.hpp>
|
||||
#include <util/reflect.hpp>
|
||||
#include <util/real_point.hpp>
|
||||
|
||||
DECLARE_POINTER_TYPE(Set);
|
||||
class StyleSheet;
|
||||
|
||||
// ----------------------------------------------------------------------------- : Printing
|
||||
|
||||
@@ -21,5 +24,27 @@ void print_preview(Window* parent, const SetP& set);
|
||||
/// Print the given set
|
||||
void print_set(Window* parent, const SetP& set);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Layout
|
||||
|
||||
/// Layout of a page of cards
|
||||
class PageLayout {
|
||||
public:
|
||||
PageLayout();
|
||||
PageLayout(const StyleSheet& stylesheet, const RealSize& page_size);
|
||||
|
||||
RealSize page_size; ///< Size of a page (in millimetres)
|
||||
RealSize card_size; ///< Size of a card (in millimetres)
|
||||
RealSize card_spacing; ///< Spacing between cards (in millimetres)
|
||||
double margin_left, margin_right, margin_top, margin_bottom; ///< Page margins (in millimetres)
|
||||
int rows, cols; ///< Number of rows/columns of cards
|
||||
bool card_landscape; ///< Are cards rotated to landscape orientation?
|
||||
|
||||
/// The number of cards per page
|
||||
inline int cardsPerPage() const { return rows * cols; }
|
||||
|
||||
private:
|
||||
DECLARE_REFLECTION();
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
#endif
|
||||
|
||||
@@ -75,6 +75,16 @@ template <typename T, typename A0, typename A1, typename A2, typename A3, typena
|
||||
inline shared_ptr<T> new_shared7(const A0& a0, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) {
|
||||
return shared_ptr<T>(new T(a0, a1, a2, a3, a4, a5, a6));
|
||||
}
|
||||
/// Allocate a new shared-pointed object, given eight arguments to pass to the ctor of T
|
||||
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
|
||||
inline shared_ptr<T> new_shared8(const A0& a0, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7) {
|
||||
return shared_ptr<T>(new T(a0, a1, a2, a3, a4, a5, a6, a7));
|
||||
}
|
||||
/// Allocate a new shared-pointed object, given nine arguments to pass to the ctor of T
|
||||
template <typename T, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
|
||||
inline shared_ptr<T> new_shared9(const A0& a0, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6, const A7& a7, const A8& a8) {
|
||||
return shared_ptr<T>(new T(a0, a1, a2, a3, a4, a5, a6, a7, a8));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : Intrusive pointers
|
||||
|
||||
|
||||
Reference in New Issue
Block a user