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"
22 #include "rs_utility.h"
23 #include "rs_system.h"
26 * Default constructor.
28 RS_FilterCXF::RS_FilterCXF(): RS_FilterInterface()
30 RS_DEBUG->print("Setting up CXF filter...");
32 addImportFormat(RS2::FormatCXF);
33 addExportFormat(RS2::FormatCXF);
36 RS_FilterCXF::~RS_FilterCXF()
41 * Implementation of the method used for RS_Import to communicate
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.
48 bool RS_FilterCXF::fileImport(Drawing & g, const QString & file, RS2::FormatType /*type*/)
50 RS_DEBUG->print("CXF Filter: importing file '%s'...", file.toLatin1().data());
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();
62 RS_DEBUG->print(RS_Debug::D_WARNING, "Cannot open CXF file '%s'.", file.toLatin1().data());
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);
72 if (!font.getEncoding().isEmpty())
73 g.addVariable("Encoding", font.getEncoding(), 0);
75 RS_BlockList * letterList = font.getLetterList();
77 for(uint i=0; i<font.countLetters(); i++)
79 RS_Block * ch = font.letterAt(i);
82 uCode.setNum(ch->getName().at(0).unicode(), 16);
84 while (uCode.length() < 4)
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)));
91 g.addBlock(ch, false);
95 g.addBlockNotification();
101 * Implementation of the method used for RS_Export to communicate
104 * @param file Full path to the CXF file that will be written.
106 bool RS_FilterCXF::fileExport(Drawing & g, const QString & file, RS2::FormatType /*type*/)
108 RS_DEBUG->print("CXF Filter: exporting file '%s'...", file.toAscii().data());
110 // crashes under windoze xp:
111 //std::ofstream fout;
113 RS_DEBUG->print("RS_FilterCXF::fileExport: open");
114 //fout.open((const char*)file.local8Bit());
117 if ((fp = fopen((const char *)file.toLocal8Bit(), "wt")) != NULL)
119 RS_DEBUG->print("RS_FilterCXF::fileExport: open: OK");
120 RS_DEBUG->print("RS_FilterCXF::fileExport: 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());
127 RS_DEBUG->print("001");
128 QString ns = g.getVariableString("Names", "");
132 QStringList names = ns.split(',');
133 RS_DEBUG->print("002");
135 for(QStringList::Iterator it=names.begin(); it!=names.end(); ++it)
137 fprintf(fp, "# Name: %s\n", (const char*)((*it).toLocal8Bit()));
141 RS_DEBUG->print("003");
143 QString es = g.getVariableString("Encoding", "");
146 fprintf(fp, "# Encoding: %s\n", (const char *)es.toLocal8Bit());
148 RS_DEBUG->print("004a");
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));
154 QString sa = g.getVariableString("Authors", "");
155 RS_DEBUG->print("authors: %s", (const char *)sa.toLocal8Bit());
159 QStringList authors = sa.split(',');
160 RS_DEBUG->print("006");
161 RS_DEBUG->print("count: %d", authors.count());
165 for(QStringList::Iterator it2=authors.begin(); it2!=authors.end(); ++it2)
167 RS_DEBUG->print("006a");
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";
178 RS_DEBUG->print("007");
181 RS_DEBUG->print("RS_FilterCXF::fileExport: header: OK");
183 RS_DEBUG->print("008");
184 // iterate through blocks (=letters of font)
185 for(uint i=0; i<g.countBlocks(); ++i)
187 RS_Block * blk = g.blockAt(i);
189 RS_DEBUG->print("block: %d", i);
190 RS_DEBUG->print("001");
194 RS_DEBUG->print("002");
195 RS_DEBUG->print("002a: %s", (const char *)(blk->getName().toLocal8Bit()));
197 fprintf(fp, "\n%s\n", (const char *)(blk->getName().toLocal8Bit()));
199 // iterate through entities of this letter:
200 for(RS_Entity * e=blk->firstEntity(RS2::ResolveAll); e!=NULL;
201 e=blk->nextEntity(RS2::ResolveAll))
205 RS_DEBUG->print("004");
208 if (e->rtti() == RS2::EntityLine)
210 RS_Line * l = (RS_Line *)e;
212 fprintf(fp, "L %f,%f,%f,%f\n", l->getStartpoint().x, l->getStartpoint().y,
213 l->getEndpoint().x, l->getEndpoint().y);
216 else if (e->rtti() == RS2::EntityArc)
218 RS_Arc * a = (RS_Arc *)e;
220 if (!a->isReversed())
229 fprintf(fp, "%f,%f,%f,%f,%f\n", a->getCenter().x, a->getCenter().y,
230 a->getRadius(), a->getAngle1() * ARAD, a->getAngle2() * ARAD);
232 // Ignore entities other than arcs / lines
238 RS_DEBUG->print("005");
240 RS_DEBUG->print("006");
242 RS_DEBUG->print("007");
247 RS_DEBUG->print("CXF Filter: exporting file: OK");
252 RS_DEBUG->print("CXF Filter: exporting file failed");
259 * Streams a double value to the given stream cutting away trailing 0's.
261 * @param value A double value. e.g. 2.700000
263 void RS_FilterCXF::stream(std::ofstream & fs, double value)
265 fs << (const char *)RS_Utility::doubleToString(value).toAscii().data();