Commit 6c89546e authored by twanvl's avatar twanvl

Implemented printing (finally)

parent 60441224
......@@ -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
......
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