]> Shamusworld >> Repos - architektonas/blob - src/base/rs_filtercxf.cpp
Initial import
[architektonas] / src / base / rs_filtercxf.cpp
1 // rs_filtercxf.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // (C) 2010 Underground Software
7 //
8 // JLH = James L. Hammons <jlhamm@acm.org>
9 //
10 // Who  When        What
11 // ---  ----------  -----------------------------------------------------------
12 // JLH  05/28/2010  Added this text. :-)
13 //
14
15 #include "rs_filtercxf.h"
16
17 #include <iostream>
18 #include <fstream>
19 #include <QtCore>
20
21 //#include "rs_regexp.h"
22 #include "rs_font.h"
23 #include "rs_utility.h"
24 #include "rs_system.h"
25
26 /**
27  * Default constructor.
28  */
29 RS_FilterCXF::RS_FilterCXF(): RS_FilterInterface()
30 {
31     RS_DEBUG->print("Setting up CXF filter...");
32
33     addImportFormat(RS2::FormatCXF);
34     addExportFormat(RS2::FormatCXF);
35 }
36
37 RS_FilterCXF::~RS_FilterCXF()
38 {
39 }
40
41 /**
42  * Implementation of the method used for RS_Import to communicate
43  * with this filter.
44  *
45  * @param g The graphic in which the entities from the file
46  * will be created or the graphics from which the entities are
47  * taken to be stored in a file.
48  */
49 bool RS_FilterCXF::fileImport(RS_Graphic & g, const QString & file, RS2::FormatType /*type*/)
50 {
51         RS_DEBUG->print("CXF Filter: importing file '%s'...", file.toLatin1().data());
52
53         //this->graphic = &g;
54         bool success = false;
55
56         // Load font file as we normally do, but the font doesn't own the
57         //  letters (we'll add them to the graphic instead. Hence 'false').
58         RS_Font font(file, false);
59         success = font.loadFont();
60
61         if (success == false)
62         {
63                 RS_DEBUG->print(RS_Debug::D_WARNING, "Cannot open CXF file '%s'.", file.toLatin1().data());
64                 return false;
65         }
66
67         g.addVariable("Names", font.getNames().join(","), 0);
68         g.addVariable("LetterSpacing", font.getLetterSpacing(), 0);
69         g.addVariable("WordSpacing", font.getWordSpacing(), 0);
70         g.addVariable("LineSpacingFactor", font.getLineSpacingFactor(), 0);
71         g.addVariable("Authors", font.getAuthors().join(","), 0);
72
73         if (!font.getEncoding().isEmpty())
74                 g.addVariable("Encoding", font.getEncoding(), 0);
75
76         RS_BlockList * letterList = font.getLetterList();
77
78         for(uint i=0; i<font.countLetters(); ++i)
79         {
80                 RS_Block* ch = font.letterAt(i);
81
82                 QString uCode;
83                 uCode.setNum(ch->getName().at(0).unicode(), 16);
84
85                 while (uCode.length() < 4)
86                         uCode="0"+uCode;
87
88                 //ch->setName("[" + uCode + "] " + ch->getName());
89                 //letterList->rename(ch, QString("[%1]").arg(ch->getName()));
90                 letterList->rename(ch, QString("[%1] %2").arg(uCode).arg(ch->getName().at(0)));
91
92                 g.addBlock(ch, false);
93                 ch->reparent(&g);
94         }
95
96         g.addBlockNotification();
97
98         return true;
99 }
100
101 /**
102  * Implementation of the method used for RS_Export to communicate
103  * with this filter.
104  *
105  * @param file Full path to the CXF file that will be written.
106  */
107 bool RS_FilterCXF::fileExport(RS_Graphic & g, const QString & file, RS2::FormatType /*type*/)
108 {
109         RS_DEBUG->print("CXF Filter: exporting file '%s'...", file.toLatin1().data());
110
111         // crashes under windoze xp:
112         //std::ofstream fout;
113
114         RS_DEBUG->print("RS_FilterCXF::fileExport: open");
115         //fout.open((const char*)file.local8Bit());
116         FILE * fp;
117
118         if ((fp = fopen((const char *)file.toLocal8Bit(), "wt")) != NULL)
119         {
120                 RS_DEBUG->print("RS_FilterCXF::fileExport: open: OK");
121                 RS_DEBUG->print("RS_FilterCXF::fileExport: header");
122
123                 // header:
124                 fprintf(fp, "# Format:            QCad II Font\n");
125                 fprintf(fp, "# Creator:           %s\n", (const char *)RS_SYSTEM->getAppName().toLocal8Bit());
126                 fprintf(fp, "# Version:           %s\n", (const char *)RS_SYSTEM->getAppVersion().toLocal8Bit());
127
128                 RS_DEBUG->print("001");
129                 QString ns = g.getVariableString("Names", "");
130
131                 if (!ns.isEmpty())
132                 {
133                         QStringList names = ns.split(',');
134                         RS_DEBUG->print("002");
135
136                         for(QStringList::Iterator it=names.begin(); it!=names.end(); ++it)
137                         {
138                                 fprintf(fp, "# Name:              %s\n", (const char*)((*it).toLocal8Bit()));
139                         }
140                 }
141
142                 RS_DEBUG->print("003");
143
144                 QString es = g.getVariableString("Encoding", "");
145
146                 if (!es.isEmpty())
147                         fprintf(fp, "# Encoding:          %s\n", (const char *)es.toLocal8Bit());
148
149                 RS_DEBUG->print("004a");
150
151                 fprintf(fp, "# LetterSpacing:     %f\n", g.getVariableDouble("LetterSpacing", 3.0));
152                 fprintf(fp, "# WordSpacing:       %f\n", g.getVariableDouble("WordSpacing", 6.75));
153                 fprintf(fp, "# LineSpacingFactor: %f\n", g.getVariableDouble("LineSpacingFactor", 1.0));
154
155                 QString sa = g.getVariableString("Authors", "");
156                 RS_DEBUG->print("authors: %s", (const char *)sa.toLocal8Bit());
157
158                 if (!sa.isEmpty())
159                 {
160                         QStringList authors = sa.split(',');
161                         RS_DEBUG->print("006");
162                         RS_DEBUG->print("count: %d", authors.count());
163
164                         QString a;
165
166                         for(QStringList::Iterator it2=authors.begin(); it2!=authors.end(); ++it2)
167                         {
168                                 RS_DEBUG->print("006a");
169                                 a = QString(*it2);
170                                 RS_DEBUG->print("006b");
171                                 RS_DEBUG->print("string is: %s", a.toAscii().data());
172                                 RS_DEBUG->print("006b0");
173                                 fprintf(fp, "# Author:            ");
174                                 RS_DEBUG->print("006b1");
175                                 fprintf(fp, "%s\n", a.toAscii().data());
176                                 //fout << "# Author:            " << a.ascii() << "\n";
177                         }
178
179                         RS_DEBUG->print("007");
180                 }
181
182                 RS_DEBUG->print("RS_FilterCXF::fileExport: header: OK");
183
184                 RS_DEBUG->print("008");
185                 // iterate through blocks (=letters of font)
186                 for(uint i=0; i<g.countBlocks(); ++i)
187                 {
188                         RS_Block * blk = g.blockAt(i);
189
190                         RS_DEBUG->print("block: %d", i);
191                         RS_DEBUG->print("001");
192
193                         if (blk != NULL)
194                         {
195                                 RS_DEBUG->print("002");
196                                 RS_DEBUG->print("002a: %s", (const char *)(blk->getName().toLocal8Bit()));
197
198                                 fprintf(fp, "\n%s\n", (const char *)(blk->getName().toLocal8Bit()));
199
200                                 // iterate through entities of this letter:
201                                 for(RS_Entity * e=blk->firstEntity(RS2::ResolveAll); e!=NULL;
202                                         e=blk->nextEntity(RS2::ResolveAll))
203                                 {
204                                         if (!e->isUndone())
205                                         {
206                                                 RS_DEBUG->print("004");
207
208                                                 // lines:
209                                                 if (e->rtti() == RS2::EntityLine)
210                                                 {
211                                                         RS_Line * l = (RS_Line *)e;
212
213                                                         fprintf(fp, "L %f,%f,%f,%f\n", l->getStartpoint().x, l->getStartpoint().y,
214                                                                 l->getEndpoint().x, l->getEndpoint().y);
215                                                 }
216                                                 // arcs:
217                                                 else if (e->rtti() == RS2::EntityArc)
218                                                 {
219                                                         RS_Arc * a = (RS_Arc *)e;
220
221                                                         if (!a->isReversed())
222                                                         {
223                                                                 fprintf(fp, "A ");
224                                                         }
225                                                         else
226                                                         {
227                                                                 fprintf(fp, "AR ");
228                                                         }
229
230                                                         fprintf(fp, "%f,%f,%f,%f,%f\n", a->getCenter().x, a->getCenter().y,
231                                                                 a->getRadius(), a->getAngle1() * ARAD, a->getAngle2() * ARAD);
232                                                 }
233                                                 // Ignore entities other than arcs / lines
234                                                 else
235                                                 {
236                                                 }
237                                         }
238
239                                         RS_DEBUG->print("005");
240                                 }
241                                 RS_DEBUG->print("006");
242                         }
243                         RS_DEBUG->print("007");
244                 }
245
246                 //fout.close();
247                 fclose(fp);
248                 RS_DEBUG->print("CXF Filter: exporting file: OK");
249                 return true;
250         }
251         else
252         {
253                 RS_DEBUG->print("CXF Filter: exporting file failed");
254         }
255
256         return false;
257 }
258
259 /**
260  * Streams a double value to the given stream cutting away trailing 0's.
261  *
262  * @param value A double value. e.g. 2.700000
263  */
264 void RS_FilterCXF::stream(std::ofstream & fs, double value)
265 {
266     fs << (const char *)RS_Utility::doubleToString(value).toAscii().data();
267 }