This commit is contained in:
ebbit1q
2026-01-05 00:41:30 +01:00
committed by GitHub
parent 8c889cf0aa
commit 168f6abe51
+64 -59
View File
@@ -29,50 +29,50 @@ void PrintJob::init(const RealSize& page_size) {
layout_cards();
align_cards();
center_cards();
}
}
void PrintJob::measure_cards() {
void PrintJob::measure_cards() {
unordered_set<CardP> already_measured_cards;
FOR_EACH(card, cards) {
if (already_measured_cards.find(card) != already_measured_cards.end()) continue;
if (already_measured_cards.find(card) != already_measured_cards.end()) continue;
already_measured_cards.emplace(card);
card_layouts.push_back(measure_card(card));
CardP other_face = card->getLinkedOtherFace(cards);
card_layouts.push_back(measure_card(card));
CardP other_face = card->getLinkedOtherFace(cards);
if (other_face && already_measured_cards.find(other_face) == already_measured_cards.end()) {
already_measured_cards.emplace(other_face);
card_layouts.push_back(measure_card(other_face));
int index = card_layouts.size()-1;
card_layouts[index].other_face = index-1;
already_measured_cards.emplace(other_face);
card_layouts.push_back(measure_card(other_face));
int index = card_layouts.size()-1;
card_layouts[index].other_face = index-1;
card_layouts[index-1].other_face = index;
}
}
}
sorted_layouts = vector<CardLayout>(card_layouts);
std::sort(sorted_layouts.begin(), sorted_layouts.end());
}
PrintJob::CardLayout PrintJob::measure_card(const CardP& card) {
// initial measure
}
PrintJob::CardLayout PrintJob::measure_card(const CardP& card) {
// initial measure
const StyleSheet& stylesheet = set->stylesheetFor(card);
RealSize size_mm(stylesheet.card_width * 25.4 / stylesheet.card_dpi, stylesheet.card_height * 25.4 / stylesheet.card_dpi);
RealSize size_px(stylesheet.card_width, stylesheet.card_height);
// check if we need to rotate to align best to default card height
// check if we need to rotate to align best to default card height
Radians rotation = 0.0;
if (abs(size_mm.width - default_size_mm.height) < abs(size_mm.height - default_size_mm.height)) {
swap(size_mm.width, size_mm.height);
swap(size_px.width, size_px.height);
rotation = rad90;
}
}
// snap to default_size_mm if we are close
if (abs(size_mm.width - default_size_mm.width) < threshold_size.width) size_mm.width = default_size_mm.width;
if (abs(size_mm.height - default_size_mm.height) < threshold_size.height) size_mm.height = default_size_mm.height;
// add bleed
double bleed_size_px = 0.0;
if (!almost_equal(settings.print_bleed, 0.0)) {
// add bleed
double bleed_size_px = 0.0;
if (!almost_equal(settings.print_bleed, 0.0)) {
bleed_size_px = stylesheet.card_dpi * settings.print_bleed / 25.4;
size_mm = RealSize(size_mm.width + 2 * settings.print_bleed, size_mm.height + 2 * settings.print_bleed);
size_mm = RealSize(size_mm.width + 2 * settings.print_bleed, size_mm.height + 2 * settings.print_bleed);
size_px = RealSize(size_px.width + 2 * bleed_size_px, size_px.height + 2 * bleed_size_px);
}
return CardLayout(card, size_mm, size_px, bleed_size_px, rotation);
}
}
void PrintJob::layout_cards() {
page_layouts.push_back(vector<CardLayout>());
@@ -85,12 +85,12 @@ void PrintJob::layout_cards() {
if (layout.other_face >= 0) {
CardLayout& other_layout = card_layouts[layout.other_face];
if ( layout.size_mm.width + other_layout.size_mm.width + settings.print_spacing + row_width >= page_size.width) continue;
if (max(layout.size_mm.height, other_layout.size_mm.height) + row_top >= page_size.height) continue;
// the card and its other face fit
if (max(layout.size_mm.height, other_layout.size_mm.height) + row_top >= page_size.height) continue;
// the card and its other face fit
layout.pos.width = row_width;
layout.pos.height = row_top;
page_layouts[page_layouts.size()-1].push_back(layout);
already_laidout_cards.emplace(layout.card);
already_laidout_cards.emplace(layout.card);
other_layout.pos.width = row_width + layout.size_mm.width + settings.print_spacing;
other_layout.pos.height = row_top;
page_layouts[page_layouts.size()-1].push_back(other_layout);
@@ -99,8 +99,8 @@ void PrintJob::layout_cards() {
// move to next spot on the row
row_width += layout.size_mm.width + other_layout.size_mm.width + 2 * settings.print_spacing;
row_height = max(max(row_height, layout.size_mm.height + settings.print_spacing), other_layout.size_mm.height + settings.print_spacing);
}
else {
}
else {
if (layout.size_mm.width + row_width >= page_size.width) continue;
if (layout.size_mm.height + row_top >= page_size.height) continue;
// the card fits
@@ -111,7 +111,7 @@ void PrintJob::layout_cards() {
if (already_laidout_cards.size() >= card_layouts.size()) return;
// move to next spot on the row
row_width += layout.size_mm.width + settings.print_spacing;
row_height = max(row_height, layout.size_mm.height + settings.print_spacing);
row_height = max(row_height, layout.size_mm.height + settings.print_spacing);
}
goto continue_outer;
}
@@ -133,7 +133,7 @@ void PrintJob::layout_cards() {
row_width = row_height = 0.0;
continue_outer:;
}
}
}
void PrintJob::align_cards() {
// for each page
@@ -184,7 +184,7 @@ void PrintJob::align_cards() {
continue_outer:;
}
}
}
}
void PrintJob::center_cards() {
for (int p = 0; p < page_layouts.size(); ++p) {
@@ -281,36 +281,40 @@ bool CardsPrintout::OnPrintPage(int page) {
void CardsPrintout::drawCards(DC& dc, PrintJobP& job, int page) {
FOR_EACH(card_layout, job->page_layouts[page - 1]) {
drawCard(dc, card_layout);
}
}
dc.SetDeviceOrigin(0, 0);
}
void CardsPrintout::drawCard(DC& dc, PrintJob::CardLayout& card_layout) {
// upscale to printer dpi
RealPoint scale(printer_px_per_mm.width * card_layout.size_mm.width / card_layout.size_px.width,
printer_px_per_mm.height * card_layout.size_mm.height / card_layout.size_px.height);
int bleed = lround(card_layout.bleed_size_px * scale.x);
// upscale to printer dpi
RealPoint scale(printer_px_per_mm.width * card_layout.size_mm.width / card_layout.size_px.width,
printer_px_per_mm.height * card_layout.size_mm.height / card_layout.size_px.height);
int bleed = lround(card_layout.bleed_size_px * scale.x);
int width = lround(card_layout.size_px.width * scale.x), height = lround(card_layout.size_px.height * scale.y);
// render card to its own dc
wxBitmap buffer(width, height, 32);
wxMemoryDC bufferDC;
bufferDC.SelectObject(buffer);
clearDC(bufferDC,*wxWHITE_BRUSH);
RotatedDC rdc(bufferDC, card_layout.rot, RealRect(0, 0, card_layout.size_px.width, card_layout.size_px.height), scale.x, QUALITY_AA, ROTATION_ATTACH_TOP_LEFT);
RotatedDC rdc(bufferDC, card_layout.rot, RealRect(0, 0, card_layout.size_px.width, card_layout.size_px.height), scale.x, QUALITY_AA, ROTATION_ATTACH_TOP_LEFT);
if (is_rad90(card_layout.rot)) bufferDC.SetDeviceOrigin(bleed, height - width - 1 - bleed); // I don't understand why this is needed
else bufferDC.SetDeviceOrigin(bleed, bleed);
else bufferDC.SetDeviceOrigin(bleed, bleed);
viewer.setCard(card_layout.card);
viewer.draw(rdc, *wxWHITE);
viewer.draw(rdc, *wxWHITE);
bufferDC.SetDeviceOrigin(0,0);
/// add print bleed edge
if (bleed > 0) {
Image left_border = bufferDC.GetAsBitmap(&wxRect(bleed + 1, bleed, bleed, height - 2 * bleed)).ConvertToImage();
bufferDC.DrawBitmap(left_border.Mirror(true), 0, bleed);
Image right_border = bufferDC.GetAsBitmap(&wxRect(width - 2 * bleed - 1, bleed, bleed, height - 2 * bleed)).ConvertToImage();
bufferDC.DrawBitmap(right_border.Mirror(true), width - bleed - 1, bleed);
Image top_border = bufferDC.GetAsBitmap(&wxRect(0, bleed + 1, width, bleed)).ConvertToImage();
bufferDC.DrawBitmap(top_border.Mirror(false), 0, 0);
Image bottom_border = bufferDC.GetAsBitmap(&wxRect(0, height - 2 * bleed - 1, width, bleed)).ConvertToImage();
bufferDC.DrawBitmap(bottom_border.Mirror(false), 0, height - bleed - 1);
/// add print bleed edge
if (bleed > 0) {
auto left_rect = wxRect(bleed + 1, bleed, bleed, height - 2 * bleed);
Image left_border = bufferDC.GetAsBitmap(&left_rect).ConvertToImage();
bufferDC.DrawBitmap(left_border.Mirror(true), 0, bleed);
auto right_rect = wxRect(width - 2 * bleed - 1, bleed, bleed, height - 2 * bleed);
Image right_border = bufferDC.GetAsBitmap(&right_rect).ConvertToImage();
bufferDC.DrawBitmap(right_border.Mirror(true), width - bleed - 1, bleed);
auto top_rect = wxRect(0, bleed + 1, width, bleed);
Image top_border = bufferDC.GetAsBitmap(&top_rect).ConvertToImage();
bufferDC.DrawBitmap(top_border.Mirror(false), 0, 0);
auto bottom_rect = wxRect(0, height - 2 * bleed - 1, width, bleed);
Image bottom_border = bufferDC.GetAsBitmap(&bottom_rect).ConvertToImage();
bufferDC.DrawBitmap(bottom_border.Mirror(false), 0, height - bleed - 1);
}
// render card dc to page dc
bufferDC.SelectObject(wxNullBitmap);
@@ -322,11 +326,11 @@ void CardsPrintout::drawCutterLines(DC& dc, PrintJobP& job, int page) {
const vector<PrintJob::CardLayout>& page_layouts = job->page_layouts[page - 1];
const RealSize& page_margin = job->page_margins[page - 1];
int page_width, page_height;
GetPageSizeMM(&page_width, &page_height);
GetPageSizeMM(&page_width, &page_height);
wxPen pen(wxColour(0, 0, 0), 2, wxPENSTYLE_SOLID);
pen.SetQuality(wxPEN_QUALITY_HIGH);
dc.SetPen(pen);
// vertical
dc.SetPen(pen);
// vertical
int v_bleed = printer_px_per_mm.width * settings.print_bleed;
for (int i = 0; i < page_layouts.size(); ++i) {
double left_line = page_layouts[i].pos.width;
@@ -349,22 +353,22 @@ void CardsPrintout::drawCutterLines(DC& dc, PrintJobP& job, int page) {
}
}
}
if (draw_left_line) {
if (draw_left_line) {
int left = printer_px_per_mm.width * left_line;
dc.DrawLine(wxPoint(left + v_bleed, 0.0),
dc.DrawLine(wxPoint(left + v_bleed, 0.0),
wxPoint(left + v_bleed, printer_px_per_mm.height * CUTTER_LINE_SIZE_MM));
dc.DrawLine(wxPoint(left + v_bleed, printer_px_per_mm.height * page_height),
dc.DrawLine(wxPoint(left + v_bleed, printer_px_per_mm.height * page_height),
wxPoint(left + v_bleed, printer_px_per_mm.height * (page_height - CUTTER_LINE_SIZE_MM)));
}
if (draw_right_line) {
int right = printer_px_per_mm.width * right_line;
dc.DrawLine(wxPoint(right - v_bleed, 0.0),
dc.DrawLine(wxPoint(right - v_bleed, 0.0),
wxPoint(right - v_bleed, printer_px_per_mm.height * CUTTER_LINE_SIZE_MM));
dc.DrawLine(wxPoint(right - v_bleed, printer_px_per_mm.height * page_height),
dc.DrawLine(wxPoint(right - v_bleed, printer_px_per_mm.height * page_height),
wxPoint(right - v_bleed, printer_px_per_mm.height * (page_height - CUTTER_LINE_SIZE_MM)));
}
}
// horizontal
// horizontal
int h_bleed = printer_px_per_mm.height * settings.print_bleed;
for (int i = 0; i < page_layouts.size(); ++i) {
double top_line = page_layouts[i].pos.height;
@@ -389,16 +393,16 @@ void CardsPrintout::drawCutterLines(DC& dc, PrintJobP& job, int page) {
}
if (draw_top_line) {
int top = printer_px_per_mm.height * top_line;
dc.DrawLine(wxPoint(0.0, top + h_bleed),
dc.DrawLine(wxPoint(0.0, top + h_bleed),
wxPoint(printer_px_per_mm.width * CUTTER_LINE_SIZE_MM, top + h_bleed));
dc.DrawLine(wxPoint(printer_px_per_mm.width * page_width, top + h_bleed),
dc.DrawLine(wxPoint(printer_px_per_mm.width * page_width, top + h_bleed),
wxPoint(printer_px_per_mm.width * (page_width - CUTTER_LINE_SIZE_MM), top + h_bleed));
}
if (draw_bottom_line) {
int bottom = printer_px_per_mm.height * bottom_line;
dc.DrawLine(wxPoint(0.0, bottom - h_bleed),
dc.DrawLine(wxPoint(0.0, bottom - h_bleed),
wxPoint(printer_px_per_mm.width * CUTTER_LINE_SIZE_MM, bottom - h_bleed));
dc.DrawLine(wxPoint(printer_px_per_mm.width * page_width, bottom - h_bleed),
dc.DrawLine(wxPoint(printer_px_per_mm.width * page_width, bottom - h_bleed),
wxPoint(printer_px_per_mm.width * (page_width - CUTTER_LINE_SIZE_MM), bottom - h_bleed));
}
}
@@ -482,3 +486,4 @@ void print_preview(Window* parent, const SetP& set, const ExportCardSelectionCho
void print_set(Window* parent, const SetP& set, const ExportCardSelectionChoices& choices) {
print_set(parent, make_print_job(parent, set, choices));
}