diff --git a/data/ch-s.mse-locale/locale b/data/ch-s.mse-locale/locale index f24d2685..867b6ac6 100644 --- a/data/ch-s.mse-locale/locale +++ b/data/ch-s.mse-locale/locale @@ -728,6 +728,8 @@ label: #TODO: Localize section put space between cards: Put space between cards? spacing print: Spacing between cards in millimeters + #TODO: Localize + bleed print: Print bleed margin in millimeters cutter lines print: Add cutter guide lines? cutter lines all: All cutter lines no intersect: If they don't intersect a card diff --git a/data/ch-t.mse-locale/locale b/data/ch-t.mse-locale/locale index 410f7eaf..29daf5e8 100644 --- a/data/ch-t.mse-locale/locale +++ b/data/ch-t.mse-locale/locale @@ -726,6 +726,8 @@ label: #TODO: Localize section put space between cards: Put space between cards? spacing print: Spacing between cards in millimeters + #TODO: Localize + bleed print: Print bleed margin in millimeters cutter lines print: Add cutter guide lines? cutter lines all: All cutter lines no intersect: If they don't intersect a card diff --git a/data/da.mse-locale/locale b/data/da.mse-locale/locale index 4d4cd093..aad4e9b3 100644 --- a/data/da.mse-locale/locale +++ b/data/da.mse-locale/locale @@ -744,6 +744,8 @@ label: #TODO: Localize section put space between cards: Put space between cards? spacing print: Spacing between cards in millimeters + #TODO: Localize + bleed print: Print bleed margin in millimeters cutter lines print: Add cutter guide lines? cutter lines all: All cutter lines no intersect: If they don't intersect a card diff --git a/data/de.mse-locale/locale b/data/de.mse-locale/locale index f9c8b1b5..9ab511fc 100644 --- a/data/de.mse-locale/locale +++ b/data/de.mse-locale/locale @@ -694,6 +694,7 @@ label: # print dialog put space between cards: Soll zwischen den Karten ein Leerzeichen eingefügt werden? spacing print: Kartenabstand in Millimetern + bleed print: Beschnittzugabe in Millimetern cutter lines print: Schnittlinien hinzufügen? cutter lines all: Alle cutter lines no intersect: Wenn sie keine Karte schneiden @@ -747,8 +748,8 @@ button: Viewer-Rotationseinstellung beim Exportieren verwenden bleed export: - Fügen Sie einen einfachen - Druckbeschnittrand hinzu. + Grobe Beschnittzugabe + hinzufügen notes export: Kartennotizen in Bildmetadaten exportieren diff --git a/data/en.mse-locale/locale b/data/en.mse-locale/locale index 0e49efd3..62c6cff0 100644 --- a/data/en.mse-locale/locale +++ b/data/en.mse-locale/locale @@ -696,6 +696,7 @@ label: # print dialog put space between cards: Put space between cards? spacing print: Spacing between cards in millimeters + bleed print: Print bleed margin in millimeters cutter lines print: Add cutter guide lines? cutter lines all: All cutter lines no intersect: If they don't intersect a card diff --git a/data/es.mse-locale/locale b/data/es.mse-locale/locale index f389319f..7c0b6e94 100644 --- a/data/es.mse-locale/locale +++ b/data/es.mse-locale/locale @@ -729,6 +729,8 @@ label: #TODO: Localize section put space between cards: Put space between cards? spacing print: Spacing between cards in millimeters + #TODO: Localize + bleed print: Print bleed margin in millimeters cutter lines print: Add cutter guide lines? cutter lines all: All cutter lines no intersect: If they don't intersect a card diff --git a/data/fr.mse-locale/locale b/data/fr.mse-locale/locale index c20f2100..4f581866 100644 --- a/data/fr.mse-locale/locale +++ b/data/fr.mse-locale/locale @@ -694,7 +694,8 @@ label: # print dialog put space between cards: Ajouter un espace entre les cartes? - spacing print: Espace entre les cartes en millimetres + spacing print: Espace entre les cartes en millimètres + bleed print: Marge de fond perdu en millimètres cutter lines print: Ajouter des lignes de découpe? cutter lines all: Toutes cutter lines no intersect: Si elles n'intersectent pas de carte diff --git a/data/it.mse-locale/locale b/data/it.mse-locale/locale index 3b34506a..92cf6ef9 100644 --- a/data/it.mse-locale/locale +++ b/data/it.mse-locale/locale @@ -695,6 +695,7 @@ label: # print dialog put space between cards: Inserire uno spazio tra le carte? spacing print: Spaziatura tra le carte in millimetri + bleed print: Margine di abbondanza in millimetri cutter lines print: Aggiungere linee di taglio? cutter lines all: Tutte cutter lines no intersect: Se non intersecano una carta @@ -749,7 +750,7 @@ button: visualizzatore durante l'esportazione bleed export: Aggiungere un margine - grezzo di stampa + di abbondanza grezzo notes export: Esporta note della carta all'interno dei metadati dell'immagine diff --git a/data/jp.mse-locale/locale b/data/jp.mse-locale/locale index 24c66937..1f79d2a2 100644 --- a/data/jp.mse-locale/locale +++ b/data/jp.mse-locale/locale @@ -728,6 +728,8 @@ label: #TODO: Localize section put space between cards: Put space between cards? spacing print: Spacing between cards in millimeters + #TODO: Localize + bleed print: Print bleed margin in millimeters cutter lines print: Add cutter guide lines? cutter lines all: All cutter lines no intersect: If they don't intersect a card diff --git a/data/ko.mse-locale/locale b/data/ko.mse-locale/locale index 38cfcc4b..217d732f 100644 --- a/data/ko.mse-locale/locale +++ b/data/ko.mse-locale/locale @@ -734,6 +734,8 @@ label: #TODO: Localize section put space between cards: Put space between cards? spacing print: Spacing between cards in millimeters + #TODO: Localize + bleed print: Print bleed margin in millimeters cutter lines print: Add cutter guide lines? cutter lines all: All cutter lines no intersect: If they don't intersect a card diff --git a/data/pl.mse-locale/locale b/data/pl.mse-locale/locale index 900c7767..1a0369f1 100644 --- a/data/pl.mse-locale/locale +++ b/data/pl.mse-locale/locale @@ -778,6 +778,8 @@ label: #TODO: Localize section put space between cards: Put space between cards? spacing print: Spacing between cards in millimeters + #TODO: Localize + bleed print: Print bleed margin in millimeters cutter lines print: Add cutter guide lines? cutter lines all: All cutter lines no intersect: If they don't intersect a card diff --git a/data/pt-br.mse-locale/locale b/data/pt-br.mse-locale/locale index d3093955..6cf6064e 100644 --- a/data/pt-br.mse-locale/locale +++ b/data/pt-br.mse-locale/locale @@ -696,6 +696,7 @@ label: # print dialog put space between cards: Colocar um espaço entre os Cards? spacing print: Espaçamento entre Cards em milímetros + bleed print: Margem de sangria de impressão em milímetros cutter lines print: Adicionar linhas de corte? cutter lines all: Todas cutter lines no intersect: Se não cruzarem um cartão diff --git a/data/ru.mse-locale/locale b/data/ru.mse-locale/locale index d2717a24..600ed4bf 100644 --- a/data/ru.mse-locale/locale +++ b/data/ru.mse-locale/locale @@ -768,6 +768,8 @@ label: #TODO: Localize section put space between cards: Put space between cards? spacing print: Spacing between cards in millimeters + #TODO: Localize + bleed print: Print bleed margin in millimeters cutter lines print: Add cutter guide lines? cutter lines all: All cutter lines no intersect: If they don't intersect a card diff --git a/src/data/format/image.cpp b/src/data/format/image.cpp index b5dbd9c7..d12c3243 100644 --- a/src/data/format/image.cpp +++ b/src/data/format/image.cpp @@ -55,9 +55,10 @@ Image export_image(const SetP& set, const CardP& card, const bool write_metadata /// rotate img = rotate_image(img, angle_radians); - int width = img.GetWidth(), height = img.GetHeight(); /// add print bleed edge + int width = img.GetWidth(), height = img.GetHeight(); + bleed = max(0, min(width-1, min(height-1, bleed))); if (size.width < bleed + 2 || size.height < bleed + 2) { queue_message(MESSAGE_ERROR, _("Image too small to add bleed edge")); } @@ -200,7 +201,7 @@ Image export_image( const SetP& set, const vector& cards, Byte* pixels = global_img.GetData(); Byte* alpha = global_img.GetAlpha(); // fill with transparent - for (UInt i = 0; i < global_width*global_height; ++i) { + for (int i = 0; i < global_width*global_height; ++i) { pixels[3 * i + 0] = 0; pixels[3 * i + 1] = 0; pixels[3 * i + 2] = 0; diff --git a/src/data/settings.cpp b/src/data/settings.cpp index 1e181cbe..ce4b3efc 100644 --- a/src/data/settings.cpp +++ b/src/data/settings.cpp @@ -197,6 +197,7 @@ Settings::Settings() , symbol_grid (true) , symbol_grid_snap (false) , print_spacing (0.33) + , print_bleed (0.0) , print_cutter_lines (CUTTER_ALL) , dark_mode_type (DARKMODE_SYSTEM) , import_scale_selection (0) @@ -334,6 +335,7 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(Settings) { REFLECT(symbol_grid_snap); REFLECT(default_game); REFLECT(print_spacing); + REFLECT(print_bleed); REFLECT(print_cutter_lines); REFLECT(dark_mode_type); REFLECT(apprentice_location); diff --git a/src/data/settings.hpp b/src/data/settings.hpp index 6116ca63..024645bb 100644 --- a/src/data/settings.hpp +++ b/src/data/settings.hpp @@ -209,6 +209,7 @@ public: // --------------------------------------------------- : Printing double print_spacing; + double print_bleed; CutterLinesType print_cutter_lines; // --------------------------------------------------- : Dark Mode diff --git a/src/gfx/generated_image.cpp b/src/gfx/generated_image.cpp index c7fc33e7..c8c4aa8b 100644 --- a/src/gfx/generated_image.cpp +++ b/src/gfx/generated_image.cpp @@ -326,13 +326,15 @@ Image BleedEdgedImage::generate(const Options& opt) { // create enlarged image Image base_img = base_image->generate(opt); int w = base_img.GetWidth(), h = base_img.GetHeight(); - if (w <= 4 || h <= 4) { + if (w <= 3 || h <= 3) { queue_message(MESSAGE_ERROR, _("Image too small to add bleed edge")); return base_img; } bool is_landscape = w > h; int dw = int(w * (horizontal_size > 0.0 ? horizontal_size : is_landscape ? 0.037 : 0.048)); - int dh = int(h * (vertical_size > 0.0 ? vertical_size : is_landscape ? 0.048 : 0.037)); + int dh = int(h * (vertical_size > 0.0 ? vertical_size : is_landscape ? 0.048 : 0.037)); + dw = min(w-1, max(0, dw)); + dh = min(h-1, max(0, dh)); if (dw <= 0 && dh <= 0) { return base_img; } diff --git a/src/gui/preferences_window.cpp b/src/gui/preferences_window.cpp index c82bba1d..f427582b 100644 --- a/src/gui/preferences_window.cpp +++ b/src/gui/preferences_window.cpp @@ -301,7 +301,7 @@ TransfersPreferencesPage::TransfersPreferencesPage(Window* parent) : Preferences export_scale->Append(String::Format(_("%d%%"), i)); } int default_export_scale = settings.default_stylesheet_settings.export_scale_selection(); - if (default_export_scale < 0 || default_export_scale > export_scale->GetCount() - 1) default_export_scale = 0; + if (default_export_scale < 0 || default_export_scale > (int)export_scale->GetCount() - 1) default_export_scale = 0; export_scale->SetSelection(default_export_scale); internal_image_extension->SetValue(settings.internal_image_extension); diff --git a/src/gui/print_window.cpp b/src/gui/print_window.cpp index bf321d71..98007fa3 100644 --- a/src/gui/print_window.cpp +++ b/src/gui/print_window.cpp @@ -50,19 +50,28 @@ void PrintJob::measure_cards() { std::sort(sorted_layouts.begin(), sorted_layouts.end()); } 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 Radians rotation = 0.0; - bool rotated = abs(size_mm.width - default_size_mm.height) < abs(size_mm.height - default_size_mm.height); // try to align best to default card height - if (rotated) { + 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; - } - if (abs(size_mm.width - default_size_mm.width) < threshold_size.width) size_mm.width = default_size_mm.width; // snap to default_size_mm if we are close + } + // 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; - return CardLayout(card, size_mm, size_px, rotation); + // 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_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() { @@ -223,6 +232,7 @@ private: /// Draw cutter lines in the page margins, corresponding to the edges of cards void drawCutterLines(DC& dc, PrintJobP& job, int page); + static constexpr double CUTTER_LINE_SIZE_MM = 8.0; /// Draw cards according to their CardLayout info void drawCards (DC& dc, PrintJobP& job, int page); void drawCard (DC& dc, PrintJob::CardLayout& card_layout); @@ -263,8 +273,8 @@ bool CardsPrintout::OnPrintPage(int page) { // scale factor (pixels per mm) printer_px_per_mm = RealSize((double)page_width_px / page_width_mm, (double)page_height_px / page_height_mm); // print the cards that belong on this page - drawCards(dc, job, page); if (settings.print_cutter_lines != CUTTER_NONE) drawCutterLines(dc, job, page); + drawCards(dc, job, page); return true; } @@ -273,22 +283,37 @@ void CardsPrintout::drawCards(DC& dc, PrintJobP& job, int page) { drawCard(dc, card_layout); } dc.SetDeviceOrigin(0, 0); - //dc.SetUserScale(printer_px_per_mm.width, printer_px_per_mm.height); } void CardsPrintout::drawCard(DC& dc, PrintJob::CardLayout& card_layout) { // upscale to printer dpi - double card_px_per_mm_width = card_layout.size_px.width / card_layout.size_mm.width; - double scale = printer_px_per_mm.width / card_px_per_mm_width; + 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(card_layout.size_px.width * scale, card_layout.size_px.height * scale, 32); + 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, 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); viewer.setCard(card_layout.card); - viewer.draw(rdc, *wxWHITE); - bufferDC.SelectObject(wxNullBitmap); + 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); + } // render card dc to page dc + bufferDC.SelectObject(wxNullBitmap); dc.SetDeviceOrigin(int(printer_px_per_mm.width * card_layout.pos.width), int(printer_px_per_mm.height * card_layout.pos.height)); dc.DrawBitmap(buffer, 0, 0); } @@ -297,82 +322,85 @@ void CardsPrintout::drawCutterLines(DC& dc, PrintJobP& job, int page) { const vector& 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); - - double vertical_line_size = min(10.0, page_margin.height - 3.0); - if (vertical_line_size > 0.0) { - for (int i = 0; i < page_layouts.size(); ++i) { - double left_line = page_layouts[i].pos.width; - double right_line = left_line + page_layouts[i].size_mm.width; - bool draw_left_line = true; - bool draw_right_line = true; - if (settings.print_cutter_lines == CUTTER_NO_INTERSECTION) { - // check if another card is in the way of this cutter line - for (int j = 0; j < page_layouts.size(); ++j) { - if (i == j) continue; - double other_left_line = page_layouts[j].pos.width; - double other_right_line = other_left_line + page_layouts[j].size_mm.width; - if (draw_left_line && left_line - other_left_line > job->threshold_bottom && other_right_line - left_line > job->threshold_bottom) { - draw_left_line = false; - if (!draw_right_line) break; - } - if (draw_right_line && right_line - other_left_line > job->threshold_bottom && other_right_line - right_line > job->threshold_bottom) { - draw_right_line = false; - if (!draw_left_line) break; - } + GetPageSizeMM(&page_width, &page_height); + wxPen pen(wxColour(0, 0, 0), 2, wxPENSTYLE_SOLID); + pen.SetQuality(wxPEN_QUALITY_HIGH); + 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; + double right_line = left_line + page_layouts[i].size_mm.width; + bool draw_left_line = true; + bool draw_right_line = true; + if (settings.print_cutter_lines == CUTTER_NO_INTERSECTION) { + // check if another card is in the way of this cutter line + for (int j = 0; j < page_layouts.size(); ++j) { + if (i == j) continue; + double other_left_line = page_layouts[j].pos.width; + double other_right_line = other_left_line + page_layouts[j].size_mm.width; + if (draw_left_line && left_line - other_left_line > job->threshold_bottom && other_right_line - left_line > job->threshold_bottom) { + draw_left_line = false; + if (!draw_right_line) break; + } + if (draw_right_line && right_line - other_left_line > job->threshold_bottom && other_right_line - right_line > job->threshold_bottom) { + draw_right_line = false; + if (!draw_left_line) break; } } - if (draw_left_line) { - int left = printer_px_per_mm.width * left_line; - dc.DrawLine(wxPoint(left, 0.0), wxPoint(left, printer_px_per_mm.height * vertical_line_size)); - dc.DrawLine(wxPoint(left, printer_px_per_mm.height * page_height), wxPoint(left, printer_px_per_mm.height * (page_height - vertical_line_size))); - } - if (draw_right_line) { - int right = printer_px_per_mm.width * right_line; - dc.DrawLine(wxPoint(right, 0.0), wxPoint(right, printer_px_per_mm.height * vertical_line_size)); - dc.DrawLine(wxPoint(right, printer_px_per_mm.height * page_height), wxPoint(right, printer_px_per_mm.height * (page_height - vertical_line_size))); - } } - } else { - queue_message(MESSAGE_WARNING, _ERROR_("v margin too small for cutter")); + if (draw_left_line) { + int left = printer_px_per_mm.width * left_line; + 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), + 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), + 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), + wxPoint(right - v_bleed, printer_px_per_mm.height * (page_height - CUTTER_LINE_SIZE_MM))); + } } - - double horizontal_line_size = min(10.0, page_margin.width - 3.0); - if (horizontal_line_size > 0.0) { - for (int i = 0; i < page_layouts.size(); ++i) { - double top_line = page_layouts[i].pos.height; - double bottom_line = top_line + page_layouts[i].size_mm.height; - bool draw_top_line = true; - bool draw_bottom_line = true; - if (settings.print_cutter_lines == CUTTER_NO_INTERSECTION) { - // check if another card is in the way of this cutter line - for (int j = 0; j < page_layouts.size(); ++j) { - if (i == j) continue; - double other_top_line = page_layouts[j].pos.height; - double other_bottom_line = other_top_line + page_layouts[j].size_mm.height; - if (draw_top_line && top_line - other_top_line > job->threshold_bottom && other_bottom_line - top_line > job->threshold_bottom) { - draw_top_line = false; - if (!draw_bottom_line) break; - } - if (draw_bottom_line && bottom_line - other_top_line > job->threshold_bottom && other_bottom_line - bottom_line > job->threshold_bottom) { - draw_bottom_line = false; - if (!draw_top_line) break; - } + // 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; + double bottom_line = top_line + page_layouts[i].size_mm.height; + bool draw_top_line = true; + bool draw_bottom_line = true; + if (settings.print_cutter_lines == CUTTER_NO_INTERSECTION) { + // check if another card is in the way of this cutter line + for (int j = 0; j < page_layouts.size(); ++j) { + if (i == j) continue; + double other_top_line = page_layouts[j].pos.height; + double other_bottom_line = other_top_line + page_layouts[j].size_mm.height; + if (draw_top_line && top_line - other_top_line > job->threshold_bottom && other_bottom_line - top_line > job->threshold_bottom) { + draw_top_line = false; + if (!draw_bottom_line) break; + } + if (draw_bottom_line && bottom_line - other_top_line > job->threshold_bottom && other_bottom_line - bottom_line > job->threshold_bottom) { + draw_bottom_line = false; + if (!draw_top_line) break; } } - if (draw_top_line) { - int top = printer_px_per_mm.height * top_line; - dc.DrawLine(wxPoint(0.0, top), wxPoint(printer_px_per_mm.width * horizontal_line_size, top)); - dc.DrawLine(wxPoint(printer_px_per_mm.width * page_width, top), wxPoint(printer_px_per_mm.width * (page_width - horizontal_line_size), top)); - } - if (draw_bottom_line) { - int bottom = printer_px_per_mm.height * bottom_line; - dc.DrawLine(wxPoint(0.0, bottom), wxPoint(printer_px_per_mm.width * horizontal_line_size, bottom)); - dc.DrawLine(wxPoint(printer_px_per_mm.width * page_width, bottom), wxPoint(printer_px_per_mm.width * (page_width - horizontal_line_size), bottom)); - } } - } else { - queue_message(MESSAGE_WARNING, _ERROR_("h margin too small for cutter")); + if (draw_top_line) { + int top = printer_px_per_mm.height * top_line; + 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), + 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), + 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), + wxPoint(printer_px_per_mm.width * (page_width - CUTTER_LINE_SIZE_MM), bottom - h_bleed)); + } } } @@ -382,11 +410,11 @@ PrintJobP make_print_job(Window* parent, const SetP& set, const ExportCardSelect // Let the user choose cards and spacing // controls ExportWindowBase wnd(parent, _TITLE_("select cards print"), set, choices); - wxFloatingPointValidator validator(2, NULL, wxNUM_VAL_ZERO_AS_BLANK); - validator.SetRange(0, 100); - wxTextCtrl* space = new wxTextCtrl(&wnd, wxID_ANY, _(""), wxDefaultPosition, wxDefaultSize, 0L, validator); - space->SetValue(wxString::Format(wxT("%lf"), settings.print_spacing)); - wxChoice* cutter = new wxChoice(&wnd, wxID_ANY); + wxFloatingPointValidator validator(2, NULL); + validator.SetRange(0.0, 10.0); + wxTextCtrl* space = new wxTextCtrl(&wnd, wxID_ANY, wxString::Format(wxT("%.2f"), settings.print_spacing), wxDefaultPosition, wxDefaultSize, 0L, validator); + wxTextCtrl* bleed = new wxTextCtrl(&wnd, wxID_ANY, wxString::Format(wxT("%.2f"), settings.print_bleed), wxDefaultPosition, wxDefaultSize, 0L, validator); + wxChoice* cutter = new wxChoice(&wnd, wxID_ANY); cutter->Clear(); cutter->Append(_LABEL_("cutter lines all")); cutter->Append(_LABEL_("cutter lines no intersect")); @@ -400,6 +428,8 @@ PrintJobP make_print_job(Window* parent, const SetP& set, const ExportCardSelect wxSizer* s4 = new wxStaticBoxSizer(wxVERTICAL, &wnd, _TITLE_("settings")); s4->Add(new wxStaticText(&wnd, -1, _LABEL_("spacing print")), 0, wxALL, 8); s4->Add(space, 0, wxALL & ~wxTOP, 8); + s4->Add(new wxStaticText(&wnd, -1, _LABEL_("bleed print")), 0, wxALL, 8); + s4->Add(bleed, 0, wxALL & ~wxTOP, 8); s4->Add(new wxStaticText(&wnd, -1, _LABEL_("cutter lines print")), 0, wxALL, 8); s4->Add(cutter, 0, wxALL & ~wxTOP, 8); s2->Add(s4, 1, wxEXPAND | (wxALL & ~wxLEFT), 8); @@ -416,6 +446,9 @@ PrintJobP make_print_job(Window* parent, const SetP& set, const ExportCardSelect String spacing = space->GetValue(); if (spacing.empty()) spacing = _("0"); spacing.ToDouble(&settings.print_spacing); + String bleeding = bleed->GetValue(); + if (bleeding.empty()) bleeding = _("0"); + bleeding.ToDouble(&settings.print_bleed); settings.print_cutter_lines = (CutterLinesType)cutter->GetSelection(); PrintJobP job = make_intrusive(set, wnd.getSelection()); return job; diff --git a/src/gui/print_window.hpp b/src/gui/print_window.hpp index dd768b16..d05ce398 100644 --- a/src/gui/print_window.hpp +++ b/src/gui/print_window.hpp @@ -29,12 +29,12 @@ public: threshold_top = 0.75 * default_size_mm.width; threshold_bottom = 0.1; - threshold_size = RealSize(0.05 * default_size_mm.width, 0.05 * default_size_mm.height); + threshold_size = RealSize(0.03 * default_size_mm.width, 0.03 * default_size_mm.height); } SetP set; vector cards; ///< Cards selected by the user for print - RealSize default_size_mm; ///< Size of a card with the default stylesheet in millimetres + RealSize default_size_mm; ///< Size of a card with the default stylesheet in millimetres, without bleed // align cards that are at most this far appart in millimeters double threshold_top; @@ -44,8 +44,8 @@ public: RealSize threshold_size; struct CardLayout { - CardLayout(const CardP& card, const RealSize& size_mm, const RealSize& size_px, const Radians& rotation) - : card(card), size_mm(size_mm), size_px(size_px), rot(rotation), other_face(-1) {} + CardLayout(const CardP& card, const RealSize& size_mm, const RealSize& size_px, double bleed_size_px, Radians rotation) + : card(card), size_mm(size_mm), size_px(size_px), bleed_size_px(bleed_size_px), rot(rotation), other_face(-1) {} bool operator<(const CardLayout& that) const { return size_mm.width > that.size_mm.width; // put the widest cards first @@ -53,7 +53,8 @@ public: CardP card; RealSize size_mm; - RealSize size_px; + RealSize size_px; + double bleed_size_px; Radians rot; RealSize pos; int other_face; diff --git a/src/util/rotation.hpp b/src/util/rotation.hpp index 15e14c27..e97e02d1 100644 --- a/src/util/rotation.hpp +++ b/src/util/rotation.hpp @@ -32,7 +32,7 @@ public: /** with the given rectangle of external coordinates and a given rotation angle and zoom factor. * if is_internal then the rect gives the internal coordinates, its origin should be (0,0) */ - Rotation(Radians angle = 0, const RealRect& rect = RealRect(0,0,0,0), double zoom = 1.0, double strectch = 1.0, RotationFlags flags = ROTATION_NORMAL); + Rotation(Radians angle = 0, const RealRect& rect = RealRect(0,0,0,0), double zoom = 1.0, double stretch = 1.0, RotationFlags flags = ROTATION_NORMAL); /// Change the zoom factor inline void setZoom(double z) { zoomX = zoomY = z; }