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
10 // JLH = James L. Hammons <jlhamm@acm.org>
13 // --- ---------- -----------------------------------------------------------
14 // JLH 05/28/2010 Added this text. :-)
21 #include "mathextra.h"
27 * @param owner true if the font owns the letters (blocks). Otherwise
28 * the letters will be deleted when the font is deleted.
30 Font::Font(const QString & fn, bool owner): letterList(owner), fileName(fn),
31 encoding(""), loaded(false), letterSpacing(3.0), wordSpacing(6.75),
32 lineSpacingFactor(1.0)
36 /** @return the fileName of this font. */
37 QString Font::getFileName() const
42 /** @return the encoding of this font. */
43 QString Font::getEncoding() const
48 /** @return the alternative names of this font. */
49 const QStringList & Font::getNames() const
54 /** @return the author(s) of this font. */
55 const QStringList & Font::getAuthors() const
60 /** @return Default letter spacing for this font */
61 double Font::getLetterSpacing()
66 /** @return Default word spacing for this font */
67 double Font::getWordSpacing()
72 /** @return Default line spacing factor for this font */
73 double Font::getLineSpacingFactor()
75 return lineSpacingFactor;
79 * Loads the font into memory.
81 * @retval true font was already loaded or is loaded now.
82 * @retval false font could not be loaded.
86 DEBUG->print("Font::loadFont");
93 // Search for the appropriate font if we have only the name of the font:
94 if (!fileName.toLower().contains(".cxf"))
96 QStringList fonts = SYSTEM->getFontList();
99 for(QStringList::Iterator it=fonts.begin(); it!=fonts.end(); it++)
101 if (QFileInfo(*it).baseName().toLower() == fileName.toLower())
108 // We have the full path of the font:
112 // No font paths found:
115 DEBUG->print(Debug::D_WARNING, "Font::loadFont: No fonts available.");
122 if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
124 DEBUG->print(Debug::D_WARNING, "Font::loadFont: Cannot open font file: %s",
125 path.toAscii().data());
129 DEBUG->print("Font::loadFont: Successfully opened font file: %s", path.toAscii().data());
131 QTextStream ts(&file);
133 // Read line by line until we find a new letter:
134 //I think this is wrong... We're mixing classes here...
135 //AND THAT WAS THE PROBLEM!!!
136 // while (!file.atEnd())
139 QString line = ts.readLine();
144 // Read font settings:
145 if (line.at(0) == '#')
146 ParseIdentifier(ts, line);
147 // Add another letter to this font:
148 else if (line.at(0) == '[')
149 ParseCharacter(ts, line);
154 DEBUG->print("Font::loadFont OK");
159 void Font::ParseIdentifier(QTextStream & ts, QString line)
161 QStringList list = line.mid(1).split(":");
162 QString identifier = "", value = "";
164 if (list.size() >= 1)
165 identifier = list[0].simplified().toLower();
167 if (list.size() >= 2)
168 value = list[1].simplified();
170 if (identifier == "letterspacing")
171 letterSpacing = value.toDouble();
172 else if (identifier == "wordspacing")
173 wordSpacing = value.toDouble();
174 else if (identifier == "linespacingfactor")
175 lineSpacingFactor = value.toDouble();
176 else if (identifier == "author")
177 authors.append(value);
178 else if (identifier == "name")
180 else if (identifier == "encoding")
182 ts.setCodec(QTextCodec::codecForName(value.toAscii()));
187 void Font::ParseCharacter(QTextStream & ts, QString line)
189 // Unicode character:
193 QRegExp regexp("[0-9A-Fa-f]{4,4}");
194 regexp.indexIn(line);
195 QString cap = regexp.cap();
199 int uCode = cap.toInt(NULL, 16);
202 // Read UTF8 (QCad 1 compatibility)
203 else if (line.indexOf(']') >= 3)
205 int i = line.indexOf(']');
206 QString mid = line.mid(1, i - 1);
207 ch = QString::fromUtf8(mid.toAscii()).at(0);
209 // Read normal ascii character:
215 // Create new letter:
216 FontChar * letter = new FontChar(NULL, ch, Vector(0.0, 0.0));
217 // Read entities of this letter:
218 line = ts.readLine();
220 while (!line.isEmpty())
222 QStringList coords = line.mid(2).split(",");
223 QStringList::Iterator it2 = coords.begin();
225 if (line.at(0) == 'L') // Line
227 double x1 = (*it2++).toDouble();
228 double y1 = (*it2++).toDouble();
229 double x2 = (*it2++).toDouble();
230 double y2 = (*it2).toDouble();
232 LineData ld(Vector(x1, y1), Vector(x2, y2));
233 Line * line = new Line(letter, ld);
234 line->setPen(Pen(RS2::FlagInvalid));
235 line->setLayer(NULL);
236 letter->addEntity(line);
238 else if (line.at(0) == 'A') // Arc
240 double cx = (*it2++).toDouble();
241 double cy = (*it2++).toDouble();
242 double r = (*it2++).toDouble();
243 double a1 = (*it2++).toDouble() / ARAD;
244 double a2 = (*it2).toDouble() / ARAD;
245 bool reversed = (line.at(1) == 'R');
247 ArcData ad(Vector(cx, cy), r, a1, a2, reversed);
248 Arc * arc = new Arc(letter, ad);
249 arc->setPen(Pen(RS2::FlagInvalid));
251 letter->addEntity(arc);
254 line = ts.readLine();
257 letter->calculateBorders();
258 letterList.add(letter);
261 // Wrappers for block list (letters) functions
262 BlockList * Font::getLetterList()
267 Block * Font::findLetter(const QString & name)
269 return letterList.find(name);
272 uint Font::countLetters()
274 return letterList.count();
277 Block * Font::letterAt(uint i)
279 return letterList.at(i);
283 * Dumps the fonts data to stdout.
285 std::ostream & operator<<(std::ostream & os, const Font & f)
287 os << " Font file name: " << f.getFileName().toLatin1().data() << "\n";
288 //<< (BlockList&)f << "\n";