PhoenixInkscape  0.8.0
Batch convert SVG to PNG with Inkscape
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1/***************************************
2 Auteur : Pierre Aubert
3 Mail : pierre.aubert@lapp.in2p3.fr
4 Licence : CeCILL-C
5****************************************/
6
7#include "convertToString.h"
8#include "PPath.h"
9#include "OptionParser.h"
10#include "pxml_utils.h"
11
12#include "pinkscape_slide.h"
13
15
17OptionParser createOptionParser(){
18 OptionParser parser(true, __PROGRAM_VERSION__);
19 parser.setExampleLongOption("phoenix_inkscapesplitter --input=file.svg --output=output/dir/");
20 parser.setExampleShortOption("phoenix_inkscapesplitter -i file1.svg file1.svg fileN.svg -o output/dir/");
21
22 parser.addOption("input", "i", OptionType::FILENAME, true, "list of input files to be treated");
23
24 PString defaultOutputDir(".");
25 parser.addOption("output", "o", defaultOutputDir, "Output directory");
26
27 return parser;
28}
29
31struct PLayer{
33 long unsigned int begin;
35 long unsigned int end;
37 PString command;
38};
39
41typedef std::vector<PLayer> PVecLayer;
42
44typedef std::vector<long unsigned int> PSlide;
45
47typedef std::vector<PSlide > PVecSlide;
48
50
53PString getInkscapeLabel(const PXml & layerXml){
54 PString attr("");
55 PXmlAttr attrXml;
56 if(pxml_getAttrIfExist(attrXml, layerXml, "inkscape:label")){
57 attr = attrXml.getValue();
58 }
59 return attr;
60}
61
63
66void createVectorSlide(PVecLayer & vecLayerSlide, const PVecXml & vecLayer){
67 long unsigned int i(0lu);
68 for(PVecXml::const_iterator itLayer(vecLayer.begin()); itLayer != vecLayer.end(); ++itLayer){
69 PString inkscapeLabel(getInkscapeLabel(*itLayer));
70 std::cout << "\tlayer '" << inkscapeLabel << "'";
71 PVecString listNb(inkscapeLabel.split('-'));
72 long unsigned int begin(0lu), end(0lu);
73 bool isBeginDefined(false), isEndDefine(false);
74 PString command("");
75 for(PVecString::iterator it(listNb.begin()); it != listNb.end(); ++it){
76 if(it->isNumber()){
77 if(isBeginDefined){
78 end = atol(it->c_str());
79 isEndDefine = true;
80 }else{
81 begin = atol(it->c_str());
82 isBeginDefined = true;
83 }
84 }else{
85 if(*it == "N" && isBeginDefined){
86 command = "UntilEnd";
87 std::cout << "\t=> until end";
88 }
89
90 }
91 }
92 std::cout << std::endl;
93 if(!isBeginDefined && !isEndDefine){
94 begin = i;
95 end = i;
96 }
97 PLayer layer;
98 layer.command = command;
99 layer.begin = begin;
100 if(isEndDefine){layer.end = end;}
101 else{layer.end = begin;}
102 vecLayerSlide.push_back(layer);
103 }
104}
105
107
111void createSlideWithLayer(PSlide & slide, const PVecLayer & vecLayerSlide, long unsigned int index){
112 long unsigned int i(0lu);
113 for(PVecLayer::const_iterator it(vecLayerSlide.begin()); it != vecLayerSlide.end(); ++it){
114 if(index >= it->begin && index <= it->end){
115 slide.push_back(i);
116 }
117 ++i;
118 }
119}
120
122
125void createVecSlide(PVecSlide & vecSlide, PVecLayer & vecLayerSlide){
126 if(vecLayerSlide.size() == 0lu){return;}
127 PVecLayer::iterator it(vecLayerSlide.begin());
128 long unsigned int minSlide(it->begin), maxSlide(it->end);
129 ++it;
130 while(it != vecLayerSlide.end()){
131 if(it->begin < minSlide){minSlide = it->begin;}
132 if(it->end > maxSlide){maxSlide = it->end;}
133 ++it;
134 }
135 for(PVecLayer::iterator itCmd(vecLayerSlide.begin()); itCmd != vecLayerSlide.end(); ++itCmd){
136 if(itCmd->command == "UntilEnd"){
137 itCmd->end = maxSlide;
138 }
139 }
140 for(long unsigned int i(minSlide); i < maxSlide + 1lu; ++i){
141 PSlide slide;
142 createSlideWithLayer(slide, vecLayerSlide, i);
143 vecSlide.push_back(slide);
144 }
145}
146
148
151PString getSlideNumber(long unsigned int i){
152 if(i < 10lu){
153 return "0" + valueToString(i);
154 }else{
155 return valueToString(i);
156 }
157}
158
160
166bool saveSlides(POutoutMode & outputMode, const PPath & baseOutputName,
167 const PVecSlide & vecSlides, const PVecXml & vecLayerXml, const PXml & lighRoot)
168{
169 long unsigned int i(0lu);
170 for(PVecSlide::const_iterator itSlide(vecSlides.begin()); itSlide != vecSlides.end(); ++itSlide){
171 PXml tmpRoot(lighRoot);
172 tmpRoot.setName("");
173 PXml * svgPtr = pxml_getChildPtr(tmpRoot, "svg");
174 const PSlide & slide = *itSlide;
175 for(PSlide::const_iterator it(slide.begin()); it != slide.end(); ++it){
176// We need to suppress attribute : style="display:none"
177 PXml tmpLayer(vecLayerXml[*it]);
178 pxml_setAttr(tmpLayer, "style", "display:inline");
179 svgPtr->getVecChild().push_back(tmpLayer); //We add the corresponding layer
180 }
181 //Save svg file
182 PPath outputSlide(PPath("./") + baseOutputName + PPath("_") + getSlideNumber(i) + PPath(".svg"));
183 //Get the svg content
184 PString slideContent(pxml_baliseStr(tmpRoot, true));
185 //Check if the svg is already saved
186 if(pinkscape_isSlideKnown(outputMode, outputSlide, slideContent)){
187 continue;
188 }
189 //If not, save the svg into png image
190 if(!outputSlide.saveFileContent(slideContent)){
191 std::cerr << "saveSlides : can't save svg file '"<<outputSlide<<"'" << std::endl;
192 return false;
193 }
194 //Call inkscape to make png file
195 PPath outputSlidePng(baseOutputName + PPath("_") + getSlideNumber(i) + PPath(".png"));
196// PString command("inkscape --without-gui -e "+outputSlidePng+" "+outputSlide);
197 PString command(PString("convert ") + outputSlide + PString(" ") + outputSlidePng);
198// PString command("inkscape --batch-process -o "+outputSlidePng+" "+outputSlide); //for Inkscape 1.1.2 (0a00cf5339, 2022-02-04)
199
200 if(system(command.c_str()) != 0){
201 std::cerr << "saveSlides : can't create png file with command '"<<command<<"'" << std::endl;
202 return false;
203 }
204 //Removing the temporary svg files
205 command = PString("rm ") + outputSlide;
206 if(system(command.c_str()) != 0){
207 std::cerr << "saveSlides : can't remove temporary svg file with command '"<<command<<"'" << std::endl;
208 return false;
209 }
210 ++i;
211 }
212 return true;
213}
214
216
219bool processFileSvg(const PPath & inputFile){
220 if(inputFile == ""){return false;}
221 PXml root;
222 if(!pxml_parserFile(root, inputFile)){
223 std::cerr << "processFileSvg : can't load file '"<<inputFile<<"'" << std::endl;
224 return false;
225 }
226// cout << "processFileSvg : root nbChild : " << root.getVecChild().size() << endl;
227// PVecXml & vecChild = root.getVecChild();
228// for(PVecXml::iterator it(vecChild.begin()); it != vecChild.end(); ++it){
229// cout << "processFileSvg : '" << it->getName() << "'" << endl;
230// }
231 PXml svgBalise;
232 if(!pxml_getChildIfExist(svgBalise, root, "svg")){
233 std::cerr << "processFileSvg : can't find 'svg' balise in root" << std::endl;
234 return false;
235 }
236
237// PVecXml & vecChildSvg = svgBalise.getVecChild();
238// for(PVecXml::iterator it(vecChildSvg.begin()); it != vecChildSvg.end(); ++it){
239// cout << "processFileSvg : svg '" << it->getName() << "'" << endl;
240// }
241
242 PVecXml vecLayer;
243 if(!pxml_getVecChildIfExist(vecLayer, svgBalise, "g")){
244 std::cerr << "processFileSvg : can't find 'g' balise in svg" << std::endl;
245 return false;
246 }
247 long unsigned int nbCalque(vecLayer.size());
248 std::cout << "processFileSvg : get " << nbCalque << " layer";
249 if(nbCalque > 1lu){std::cout << "s";}
250 std::cout << std::endl;
251
252 PVecLayer vecLayerSlide;
253 createVectorSlide(vecLayerSlide, vecLayer);
254 if(vecLayerSlide.size() == 0lu){
255 std::cerr << "processFileSvg : no layer defined with -begin-end synthax" << std::endl;
256 return false;
257 }
258 PVecSlide vecSlides;
259 createVecSlide(vecSlides, vecLayerSlide);
260
261 PXml lighRoot(root);
262 PXml * svgPtr = pxml_getChildPtr(lighRoot, "svg");
263 PXml svgNoLayer(pxml_eraseVecChild(*svgPtr, "g"));
264 *svgPtr = svgNoLayer;
265
266 POutoutMode outputMode;
267 PString baseOutputSlideName(inputFile.getFileName().eraseExtension());
268 pinkscape_loadSlideMap(outputMode.mapSlide, baseOutputSlideName);
269 bool b = saveSlides(outputMode, baseOutputSlideName, vecSlides, vecLayer, lighRoot);
270 pinkscape_saveSlideMap(outputMode.mapSlide, baseOutputSlideName);
271 return b;
272}
273
275
278int processFiles(const std::vector<PPath> & listInputFile){
279 if(listInputFile.size() == 0lu){
280 std::cerr << "processFiles : no input file" << std::endl;
281 return -1;
282 }
283 bool b(true);
284 for(std::vector<PPath>::const_iterator it(listInputFile.begin()); it != listInputFile.end() && b; ++it){
285 b &= processFileSvg(*it);
286 }
287 return 1 - b;
288}
289
290int main(int argc, char** argv){
291 OptionParser parser = createOptionParser();
292 parser.parseArgument(argc, argv);
293
294 const OptionMode & defaultMode = parser.getDefaultMode();
295 std::vector<PPath> listInputFile;
296 defaultMode.getValue(listInputFile, "input");
297
298 return processFiles(listInputFile);
299}
300
301
std::vector< PSlide > PVecSlide
Define the layer in slide.
Definition main.cpp:47
std::vector< PLayer > PVecLayer
Vector of layer.
Definition main.cpp:41
PString getInkscapeLabel(const PXml &layerXml)
Get the inkscape label of current PXml.
Definition main.cpp:53
void createVecSlide(PVecSlide &vecSlide, PVecLayer &vecLayerSlide)
Create the vector of slides.
Definition main.cpp:125
int main(int argc, char **argv)
Definition main.cpp:290
void createSlideWithLayer(PSlide &slide, const PVecLayer &vecLayerSlide, long unsigned int index)
Create the slide to be generated.
Definition main.cpp:111
int processFiles(const std::vector< PPath > &listInputFile)
Process all the input files.
Definition main.cpp:278
bool saveSlides(POutoutMode &outputMode, const PPath &baseOutputName, const PVecSlide &vecSlides, const PVecXml &vecLayerXml, const PXml &lighRoot)
Save the slides.
Definition main.cpp:166
void createVectorSlide(PVecLayer &vecLayerSlide, const PVecXml &vecLayer)
Create the vector of slide layer.
Definition main.cpp:66
OptionParser createOptionParser()
Create the OptionParser of this program.
Definition main.cpp:17
bool processFileSvg(const PPath &inputFile)
Process all the input files.
Definition main.cpp:219
PString getSlideNumber(long unsigned int i)
Convert the slide index into string.
Definition main.cpp:151
std::vector< long unsigned int > PSlide
Slide composed of layer.
Definition main.cpp:44
void pinkscape_loadSlideMap(PMapSlide &mapFormula, const PPath &baseOutputName)
Load the map file of all the formulae if it exists.
void pinkscape_saveSlideMap(const PMapSlide &mapFormula, const PPath &baseOutputName)
Save the map file of the formulae to avoid extra latex call.
bool pinkscape_isSlideKnown(POutoutMode &outputMode, const PPath &outputSlide, const PString &slideContent)
Check if the slide we are going to save was already saved (with the same content) or not.
Get the begin and end slide for current layer.
Definition main.cpp:31
long unsigned int end
Last slide where the layer has to be printed.
Definition main.cpp:35
long unsigned int begin
first slide where the layer has to be printed
Definition main.cpp:33
PString command
Extra command.
Definition main.cpp:37
Output mode of the html backend.
PMapSlide mapSlide
Map of the formula which are already saved as png files.