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. :-)
18 #include "rs_fontchar.h"
20 #include "rs_system.h"
25 * @param owner true if the font owns the letters (blocks). Otherwise
26 * the letters will be deleted when the font is deleted.
28 RS_Font::RS_Font(const QString & fileName, bool owner): letterList(owner)
30 this->fileName = fileName;
35 lineSpacingFactor = 1.0;
38 /** @return the fileName of this font. */
39 QString RS_Font::getFileName() const
44 /** @return the encoding of this font. */
45 QString RS_Font::getEncoding() const
50 /** @return the alternative names of this font. */
51 const QStringList & RS_Font::getNames() const
56 /** @return the author(s) of this font. */
57 const QStringList & RS_Font::getAuthors() const
62 /** @return Default letter spacing for this font */
63 double RS_Font::getLetterSpacing()
68 /** @return Default word spacing for this font */
69 double RS_Font::getWordSpacing()
74 /** @return Default line spacing factor for this font */
75 double RS_Font::getLineSpacingFactor()
77 return lineSpacingFactor;
81 * Loads the font into memory.
83 * @retval true font was already loaded or is loaded now.
84 * @retval false font could not be loaded.
86 bool RS_Font::loadFont()
88 RS_DEBUG->print("RS_Font::loadFont");
95 // Search for the appropriate font if we have only the name of the font:
96 if (!fileName.toLower().contains(".cxf"))
98 QStringList fonts = RS_SYSTEM->getFontList();
101 for(QStringList::Iterator it=fonts.begin(); it!=fonts.end(); it++)
103 if (QFileInfo(*it).baseName().toLower() == fileName.toLower())
110 // We have the full path of the font:
114 // No font paths found:
117 RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Font::loadFont: No fonts available.");
124 if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
126 RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Font::loadFont: Cannot open font file: %s",
127 path.toLatin1().data());
132 RS_DEBUG->print("RS_Font::loadFont: Successfully opened font file: %s", path.toLatin1().data());
135 QTextStream ts(&file);
138 // Read line by line until we find a new letter:
139 //I think this is wrong... We're mixing classes here...
140 //AND THAT WAS THE PROBLEM!!!
141 // while (!file.atEnd())
144 line = ts.readLine();
145 //printf("\"%s\"\n", line.toAscii().data());
149 // Read font settings:
150 if (line.at(0) == '#')
153 // QStringList lst = QStringList::split(':', line.right(line.length() - 1));
154 QStringList lst = line.right(line.length() - 1).split(":");
155 QStringList::Iterator it3 = lst.begin();
157 // QString identifier = (*it3).stripWhiteSpace();
158 QString identifier = (*it3);
159 identifier = identifier.simplified().toLower();
161 // QString value = (*it3).stripWhiteSpace();
162 QString value = (*it3);
163 value = value.simplified().toLower();
165 QStringList list = line.right(line.length() - 1).split(":");
166 QString identifier = "", value = "";
168 if (list.size() >= 1)
169 identifier = list[0].simplified().toLower();
171 if (list.size() >= 2)
172 value = list[1].simplified();//.toLower();
174 //printf("--> identifier=\"%s\", value=\"%s\"\n", identifier.toAscii().data(), value.toAscii().data());
176 if (identifier == "letterspacing")
177 letterSpacing = value.toDouble();
178 else if (identifier == "wordspacing")
179 wordSpacing = value.toDouble();
180 else if (identifier == "linespacingfactor")
181 lineSpacingFactor = value.toDouble();
182 else if (identifier == "author")
183 authors.append(value);
184 else if (identifier == "name")
186 else if (identifier == "encoding")
188 ts.setCodec(QTextCodec::codecForName(value.toAscii()));
192 // Add another letter to this font:
193 else if (line.at(0) == '[')
199 QRegExp regexp("[0-9A-Fa-f]{4,4}");
200 // regexp.search(line);
201 regexp.indexIn(line);
202 QString cap = regexp.cap();
206 int uCode = cap.toInt(NULL, 16);
209 // read UTF8 (qcad 1 compatibility)
210 // else if (line.find(']') >= 3)
211 else if (line.indexOf(']') >= 3)
213 // int i = line.find(']');
214 int i = line.indexOf(']');
215 QString mid = line.mid(1, i - 1);
216 ch = QString::fromUtf8(mid.toLatin1()).at(0);
218 // read normal ascii character:
224 // create new letter:
225 RS_FontChar * letter = new RS_FontChar(NULL, ch, Vector(0.0, 0.0));
227 // Read entities of this letter:
228 line = ts.readLine();
230 while (!line.isEmpty())
232 QString coordsStr = line.right(line.length() - 2);
233 QStringList coords = coordsStr.split(",");
234 QStringList::Iterator it2 = coords.begin();
237 if (line.at(0) == 'L')
239 double x1 = (*it2++).toDouble();
240 double y1 = (*it2++).toDouble();
241 double x2 = (*it2++).toDouble();
242 double y2 = (*it2).toDouble();
244 RS_LineData ld(Vector(x1, y1), Vector(x2, y2));
245 RS_Line * line = new RS_Line(letter, ld);
246 line->setPen(RS_Pen(RS2::FlagInvalid));
247 line->setLayer(NULL);
248 letter->addEntity(line);
251 else if (line.at(0) == 'A')
253 double cx = (*it2++).toDouble();
254 double cy = (*it2++).toDouble();
255 double r = (*it2++).toDouble();
256 double a1 = (*it2++).toDouble() / ARAD;
257 double a2 = (*it2).toDouble() / ARAD;
258 bool reversed = (line.at(1) == 'R');
260 RS_ArcData ad(Vector(cx, cy), r, a1, a2, reversed);
261 RS_Arc * arc = new RS_Arc(letter, ad);
262 arc->setPen(RS_Pen(RS2::FlagInvalid));
264 letter->addEntity(arc);
267 line = ts.readLine();
270 letter->calculateBorders();
271 letterList.add(letter);
278 RS_DEBUG->print("RS_Font::loadFont OK");
283 // Wrappers for block list (letters) functions
284 RS_BlockList * RS_Font::getLetterList()
289 RS_Block * RS_Font::findLetter(const QString & name)
291 return letterList.find(name);
294 uint RS_Font::countLetters()
296 return letterList.count();
299 RS_Block * RS_Font::letterAt(uint i)
301 return letterList.at(i);
305 * Dumps the fonts data to stdout.
307 std::ostream & operator<<(std::ostream & os, const RS_Font & f)
309 os << " Font file name: " << f.getFileName().toLatin1().data() << "\n";
310 //<< (RS_BlockList&)f << "\n";