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