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
8 // JLH = James L. Hammons <jlhamm@acm.org>
11 // --- ---------- -----------------------------------------------------------
12 // JLH 05/28/2010 Added this text. :-)
15 #include "rs_filtercxf.h"
21 //#include "rs_regexp.h"
23 #include "rs_utility.h"
24 #include "rs_system.h"
27 * Default constructor.
29 RS_FilterCXF::RS_FilterCXF(): RS_FilterInterface()
31 RS_DEBUG->print("Setting up CXF filter...");
33 addImportFormat(RS2::FormatCXF);
34 addExportFormat(RS2::FormatCXF);
37 RS_FilterCXF::~RS_FilterCXF()
42 * Implementation of the method used for RS_Import to communicate
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.
49 bool RS_FilterCXF::fileImport(RS_Graphic & g, const QString & file, RS2::FormatType /*type*/)
51 RS_DEBUG->print("CXF Filter: importing file '%s'...", file.toLatin1().data());
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();
63 RS_DEBUG->print(RS_Debug::D_WARNING, "Cannot open CXF file '%s'.", file.toLatin1().data());
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);
73 if (!font.getEncoding().isEmpty())
74 g.addVariable("Encoding", font.getEncoding(), 0);
76 RS_BlockList * letterList = font.getLetterList();
78 for(uint i=0; i<font.countLetters(); ++i)
80 RS_Block* ch = font.letterAt(i);
83 uCode.setNum(ch->getName().at(0).unicode(), 16);
85 while (uCode.length() < 4)
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)));
92 g.addBlock(ch, false);
96 g.addBlockNotification();
102 * Implementation of the method used for RS_Export to communicate
105 * @param file Full path to the CXF file that will be written.
107 bool RS_FilterCXF::fileExport(RS_Graphic & g, const QString & file, RS2::FormatType /*type*/)
109 RS_DEBUG->print("CXF Filter: exporting file '%s'...", file.toLatin1().data());
111 // crashes under windoze xp:
112 //std::ofstream fout;
114 RS_DEBUG->print("RS_FilterCXF::fileExport: open");
115 //fout.open((const char*)file.local8Bit());
118 if ((fp = fopen((const char *)file.toLocal8Bit(), "wt")) != NULL)
120 RS_DEBUG->print("RS_FilterCXF::fileExport: open: OK");
121 RS_DEBUG->print("RS_FilterCXF::fileExport: 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());
128 RS_DEBUG->print("001");
129 QString ns = g.getVariableString("Names", "");
133 QStringList names = ns.split(',');
134 RS_DEBUG->print("002");
136 for(QStringList::Iterator it=names.begin(); it!=names.end(); ++it)
138 fprintf(fp, "# Name: %s\n", (const char*)((*it).toLocal8Bit()));
142 RS_DEBUG->print("003");
144 QString es = g.getVariableString("Encoding", "");
147 fprintf(fp, "# Encoding: %s\n", (const char *)es.toLocal8Bit());
149 RS_DEBUG->print("004a");
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));
155 QString sa = g.getVariableString("Authors", "");
156 RS_DEBUG->print("authors: %s", (const char *)sa.toLocal8Bit());
160 QStringList authors = sa.split(',');
161 RS_DEBUG->print("006");
162 RS_DEBUG->print("count: %d", authors.count());
166 for(QStringList::Iterator it2=authors.begin(); it2!=authors.end(); ++it2)
168 RS_DEBUG->print("006a");
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";
179 RS_DEBUG->print("007");
182 RS_DEBUG->print("RS_FilterCXF::fileExport: header: OK");
184 RS_DEBUG->print("008");
185 // iterate through blocks (=letters of font)
186 for(uint i=0; i<g.countBlocks(); ++i)
188 RS_Block * blk = g.blockAt(i);
190 RS_DEBUG->print("block: %d", i);
191 RS_DEBUG->print("001");
195 RS_DEBUG->print("002");
196 RS_DEBUG->print("002a: %s", (const char *)(blk->getName().toLocal8Bit()));
198 fprintf(fp, "\n%s\n", (const char *)(blk->getName().toLocal8Bit()));
200 // iterate through entities of this letter:
201 for(RS_Entity * e=blk->firstEntity(RS2::ResolveAll); e!=NULL;
202 e=blk->nextEntity(RS2::ResolveAll))
206 RS_DEBUG->print("004");
209 if (e->rtti() == RS2::EntityLine)
211 RS_Line * l = (RS_Line *)e;
213 fprintf(fp, "L %f,%f,%f,%f\n", l->getStartpoint().x, l->getStartpoint().y,
214 l->getEndpoint().x, l->getEndpoint().y);
217 else if (e->rtti() == RS2::EntityArc)
219 RS_Arc * a = (RS_Arc *)e;
221 if (!a->isReversed())
230 fprintf(fp, "%f,%f,%f,%f,%f\n", a->getCenter().x, a->getCenter().y,
231 a->getRadius(), a->getAngle1() * ARAD, a->getAngle2() * ARAD);
233 // Ignore entities other than arcs / lines
239 RS_DEBUG->print("005");
241 RS_DEBUG->print("006");
243 RS_DEBUG->print("007");
248 RS_DEBUG->print("CXF Filter: exporting file: OK");
253 RS_DEBUG->print("CXF Filter: exporting file failed");
260 * Streams a double value to the given stream cutting away trailing 0's.
262 * @param value A double value. e.g. 2.700000
264 void RS_FilterCXF::stream(std::ofstream & fs, double value)
266 fs << (const char *)RS_Utility::doubleToString(value).toAscii().data();