1 #include "export_pdf.hpp"
2 #include "canvas_pdf.hpp"
3 #include <podofo/podofo.h>
4 #include "util/util.hpp"
5 #include "board/board.hpp"
6 #include "export_pdf_util.hpp"
7 
8 namespace horizon {
9 
cb_nop(std::string,double)10 static void cb_nop(std::string, double)
11 {
12 }
13 
export_pdf(const class Board & brd,const class PDFExportSettings & settings,std::function<void (std::string,double)> cb)14 void export_pdf(const class Board &brd, const class PDFExportSettings &settings,
15                 std::function<void(std::string, double)> cb)
16 {
17     if (!cb)
18         cb = &cb_nop;
19     cb("Initializing", 0);
20 
21     PoDoFo::PdfStreamedDocument document(settings.output_filename.c_str());
22     PoDoFo::PdfPainterMM painter;
23     auto info = document.GetInfo();
24     info->SetCreator("horizon EDA");
25     info->SetProducer("horizon EDA");
26 
27 
28     auto font = document.CreateFont("Helvetica");
29 
30     PDFExportSettings my_settings(settings);
31     my_settings.include_text = false; // need to work out text placement
32     CanvasPDF ca(painter, *font, my_settings);
33 
34     cb("Exporting Board", 0);
35     int64_t border_width = 1_mm;
36     auto bbox = brd.get_bbox();
37     auto width = bbox.second.x - bbox.first.x + border_width * 2;
38     auto height = bbox.second.y - bbox.first.y + border_width * 2;
39 
40     auto page = document.CreatePage(PoDoFo::PdfRect(0, 0, to_pt(width), to_pt(height)));
41     painter.SetPage(page);
42     painter.SetLineCapStyle(PoDoFo::ePdfLineCapStyle_Round);
43     painter.SetFont(font);
44     painter.SetColor(0, 0, 0);
45     painter.SetTextRenderingMode(PoDoFo::ePdfTextRenderingMode_Invisible);
46     if (settings.mirror) {
47         painter.SetTransformationMatrix(-1, 0, 0, 1, to_pt(bbox.second.x + border_width),
48                                         to_pt(-bbox.first.y + border_width));
49     }
50     else {
51         painter.SetTransformationMatrix(1, 0, 0, 1, to_pt(-bbox.first.x + border_width),
52                                         to_pt(-bbox.first.y + border_width));
53     }
54     ca.layer_filter = true;
55     ca.use_layer_colors = true;
56 
57     std::vector<int> layers_sorted;
58     for (const auto &it : settings.layers) {
59         if (it.second.enabled) {
60             layers_sorted.push_back(it.first);
61             ca.set_layer_color(it.first, it.second.color);
62         }
63     }
64     std::sort(layers_sorted.begin(), layers_sorted.end());
65     if (settings.reverse_layers)
66         std::reverse(layers_sorted.begin(), layers_sorted.end());
67 
68     for (const auto &[uu, pic] : brd.pictures) {
69         if (!pic.on_top)
70             render_picture(document, painter, pic);
71     }
72 
73     unsigned int i_layer = 0;
74     for (int layer : layers_sorted) {
75         ca.clear();
76         ca.current_layer = layer;
77         ca.fill = settings.layers.at(layer).mode == PDFExportSettings::Layer::Mode::FILL;
78         cb("Exporting layer " + format_m_of_n(i_layer, layers_sorted.size()), ((double)i_layer) / layers_sorted.size());
79         ca.update(brd);
80         i_layer++;
81     }
82 
83     for (const auto &[uu, pic] : brd.pictures) {
84         if (pic.on_top)
85             render_picture(document, painter, pic);
86     }
87 
88     painter.FinishPage();
89 
90     document.Close();
91 }
92 } // namespace horizon
93