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