Logo ROOT   6.12/07
Reference Guide
XLFDParser.mm
Go to the documentation of this file.
1 // @(#)root/graf2d:$Id$
2 // Author: Timur Pocheptsov 2/03/2012
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2012, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //#define NDEBUG
13 
14 #include <stdexcept>
15 #include <sstream>
16 #include <cassert>
17 #include <cctype>
18 
19 #include "XLFDParser.h"
20 #include "TError.h"
21 
22 //
23 // I did not find any formal description of what XLFD name can be.
24 // The first version of this code was quite strict - it expected all
25 // components to be in place, digits must be digits. But after using
26 // ROOT's GUI for some time, I noticed that ROOT can use font name like
27 // *, "fixed", "-*-" or something like this. In this case I have to set
28 // some "default" or "wildcard" names.
29 //
30 
31 namespace ROOT {
32 namespace MacOSX {
33 namespace X11 {
34 
35 namespace {
36 
37 typedef std::string::size_type size_type;
38 
39 //______________________________________________________________________________
40 template<class T>
41 void StringToInt(const std::string &str, const std::string &componentName, T &num)
42 {
43  for (size_type i = 0, e = str.length(); i < e; ++i) {
44  const char symbol = str[i];
45  if (!std::isdigit(symbol))
46  throw std::runtime_error("bad symbol while converting component " + componentName + " into number");
47  }
48 
49  std::istringstream in(str);
50  in>>num;
51 }
52 
53 //______________________________________________________________________________
54 size_type GetXLFDNameComponentAsString(const std::string &name, const std::string & componentName,
55  size_type pos, std::string &component)
56 {
57  const size_type length = name.length();
58  if (pos + 1 >= length)
59  throw std::runtime_error("Unexpected end of name while parsing " + componentName);
60 
61  //Starting symbol must be '-'.
62  if (name[pos] != '-')
63  throw std::runtime_error("Component " + componentName + " must start from '-'");
64 
65  const size_type start = ++pos;
66  ++pos;
67  while (pos < length && name[pos] != '-')
68  ++pos;
69 
70  if (pos - start)
71  component = name.substr(start, pos - start);
72  else
73  component = "";
74 
75  return pos;
76 }
77 
78 
79 //______________________________________________________________________________
80 template<class T>
81 size_type GetXLFDNameComponentAsInteger(const std::string &name,
82  const std::string &componentName,
83  size_type pos, T &component)
84 {
85  std::string num;
86  pos = GetXLFDNameComponentAsString(name, componentName, pos, num);
87  StringToInt(num, componentName, component);
88 
89  return pos;
90 }
91 
92 
93 //______________________________________________________________________________
94 size_type ParseFoundry(const std::string &name, size_type pos, XLFDName &/*dst*/)
95 {
96  //Ignore foundry.
97  std::string dummy;
98  return GetXLFDNameComponentAsString(name, "foundry", pos, dummy);
99 }
100 
101 
102 //______________________________________________________________________________
103 size_type ParseFamilyName(const std::string &name, size_type pos, XLFDName &dst)
104 {
105  const size_type tokenEnd = GetXLFDNameComponentAsString(name, "family name", pos, dst.fFamilyName);
106 
107  //This is a "special case": ROOT uses it's own symbol.ttf, but
108  //I can not use it to render text in a GUI, and also I can not use
109  //Apple's system symbol font - it can not encode all symbols ROOT wants.
110  if (dst.fFamilyName == "symbol")
111  dst.fFamilyName = "helvetica";
112 
113  return tokenEnd;
114 }
115 
116 
117 //______________________________________________________________________________
118 size_type ParseWeight(const std::string &name, size_type pos, XLFDName &dst)
119 {
120  //Weight can be an integer, can be a word, can be a combination of a word
121  //and integer.
122  std::string weight;
123  pos = GetXLFDNameComponentAsString(name, "weight", pos, weight);
124 
125  if (weight == "*")
126  dst.fWeight = kFWAny;
127  else if (weight == "bold")
128  dst.fWeight = kFWBold;
129  else
130  dst.fWeight = kFWMedium;
131 
132  return pos;
133 }
134 
135 
136 //______________________________________________________________________________
137 size_type ParseSlant(const std::string &name, size_type pos, XLFDName &dst)
138 {
139  //Slant can be regular or italic now.
140  std::string slant;
141  pos = GetXLFDNameComponentAsString(name, "slant", pos, slant);
142 
143  //Can be 'r', 'R', 'i', 'I', 'o', 'O', '*'.
144  if (slant == "*")
145  dst.fSlant = kFSAny;
146  else if (slant == "i" || slant == "I" || slant == "o" || slant == "O")
147  dst.fSlant = kFSItalic;
148  else
149  dst.fSlant = kFSRegular;
150 
151  return pos;
152 }
153 
154 //______________________________________________________________________________
155 size_type ParseSetwidth(const std::string &name, size_type pos, XLFDName &/*dst*/)
156 {
157  //Setwidth is ignored now.
158  std::string dummy;
159  return GetXLFDNameComponentAsString(name, "setwidth", pos, dummy);
160 }
161 
162 //______________________________________________________________________________
163 size_type ParseAddstyle(const std::string &name, size_type pos, XLFDName &/*dst*/)
164 {
165  //Ignored at the moment.
166  std::string dummy;
167  return GetXLFDNameComponentAsString(name, "addstyle", pos, dummy);
168 }
169 
170 //______________________________________________________________________________
171 size_type ParsePixelSize(const std::string &name, size_type pos, XLFDName &dst)
172 {
173  //First, try to parse as string. It can be '*' == 'any size'.
174  //In the first version it was more strict - throwing and exception.
175  std::string dummy;
176 
177  size_type endOfSize = GetXLFDNameComponentAsString(name, "pixel size", pos, dummy);
178  if (dummy == "*") {
179  //Aha, ignore size.
180  dst.fPixelSize = 0;
181  return endOfSize;
182  }
183 
184  const size_type pos1 = GetXLFDNameComponentAsInteger(name, "pixel size", pos, dst.fPixelSize);
185  if (dst.fPixelSize < 12)
186  dst.fPixelSize = 12;
187  //Real size in pixel?
188  return pos1;//GetXLFDNameComponentAsInteger(name, "pixel size", pos, dst.fPixelSize);
189 }
190 
191 //______________________________________________________________________________
192 size_type ParsePointSize(const std::string &name, size_type pos, XLFDName &/*dst*/)
193 {
194  //Ignored at the moment.
195  std::string dummy;
196  return GetXLFDNameComponentAsString(name, "point size", pos, dummy);
197 }
198 
199 
200 //______________________________________________________________________________
201 size_type ParseHoriz(const std::string &name, size_type pos, XLFDName &/*dst*/)
202 {
203  //Ignored at the moment.
204  std::string dummy;
205  return GetXLFDNameComponentAsString(name, "horizontal", pos, dummy);
206 }
207 
208 
209 //______________________________________________________________________________
210 size_type ParseVert(const std::string &name, size_type pos, XLFDName &/*dst*/)
211 {
212  //Ignored at the moment.
213  std::string dummy;
214  return GetXLFDNameComponentAsString(name, "vertical", pos, dummy);
215 }
216 
217 
218 //______________________________________________________________________________
219 size_type ParseSpacing(const std::string &name, size_type pos, XLFDName &/*dst*/)
220 {
221  //Ignored at the moment.
222  std::string dummy;
223  return GetXLFDNameComponentAsString(name, "spacing", pos, dummy);
224 }
225 
226 
227 //______________________________________________________________________________
228 size_type ParseAvgwidth(const std::string &name, size_type pos, XLFDName &/*dst*/)
229 {
230  //Ignored at the moment.
231  std::string dummy;
232  return GetXLFDNameComponentAsString(name, "average width", pos, dummy);
233 }
234 
235 
236 //______________________________________________________________________________
237 size_type ParseRgstry(const std::string &name, size_type pos, XLFDName &dst)
238 {
239  return GetXLFDNameComponentAsString(name, "language", pos, dst.fRgstry);
240 }
241 
242 
243 //______________________________________________________________________________
244 size_type ParseEncoding(const std::string &name, size_type pos, XLFDName &dst)
245 {
246  return GetXLFDNameComponentAsString(name, "encoding", pos, dst.fRgstry);
247 }
248 
249 }//Anonymous namespace.
250 
251 //______________________________________________________________________________
253  : fWeight(kFWAny),
254  fSlant(kFSAny),
255  fPixelSize(0)
256 {
257 }
258 
259 //______________________________________________________________________________
260 bool ParseXLFDName(const std::string &xlfdName, XLFDName &dst)
261 {
262  const size_type nameLength = xlfdName.length();
263 
264  assert(nameLength && "XLFD name is a string with a zero length");
265 
266  if (!nameLength) {
267  ::Warning("ROOT::MacOSX::X11::ParseXLFDName: ", "XLFD name is a string with a zero length");
268  return false;
269  }
270 
271  try {
272  if (xlfdName == "fixed" || xlfdName == "*") {
273  //Is this correct XLFD name???? Who knows. Replace it.
274  dst.fFamilyName = "LucidaGrande";
275  dst.fPixelSize = 12;
276  } else {
277  size_type pos = ParseFoundry(xlfdName, 0, dst);
278  if (pos + 1 < nameLength)
279  pos = ParseFamilyName(xlfdName, pos, dst);
280 
281  if (pos + 1 < nameLength)
282  pos = ParseWeight(xlfdName, pos, dst);
283  else
284  dst.fWeight = kFWMedium;
285 
286  if (pos + 1 < nameLength)
287  pos = ParseSlant(xlfdName, pos, dst);
288  else
289  dst.fSlant = kFSRegular;
290 
291  if (pos + 1 < nameLength)
292  pos = ParseSetwidth(xlfdName, pos, dst);
293  if (pos + 1 < nameLength)
294  pos = ParseAddstyle(xlfdName, pos, dst);
295  if (pos + 1 < nameLength)
296  pos = ParsePixelSize(xlfdName, pos, dst);
297  if (pos + 1 < nameLength)
298  pos = ParsePointSize(xlfdName, pos, dst);
299  if (pos + 1 < nameLength)
300  pos = ParseHoriz(xlfdName, pos, dst);
301  if (pos + 1 < nameLength)
302  pos = ParseVert(xlfdName, pos, dst);
303  if (pos + 1 < nameLength)
304  pos = ParseSpacing(xlfdName, pos, dst);
305  if (pos + 1 < nameLength)
306  pos = ParseAvgwidth(xlfdName, pos, dst);
307  if (pos + 1 < nameLength)
308  pos = ParseRgstry(xlfdName, pos, dst);
309  if (pos + 1 < nameLength)
310  pos = ParseEncoding(xlfdName, pos, dst);
311  }
312 
313  return true;
314  } catch (const std::exception &e) {
315  ::Error("ROOT::MacOSX::Quartz::ParseXLFDName", "Failed to parse XLFD name - %s", e.what());
316  return false;
317  }
318 }
319 
320 }//X11
321 }//MacOSX
322 }//ROOT
bool ParseXLFDName(const std::string &xlfdName, XLFDName &dst)
Definition: XLFDParser.mm:260
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
double T(double x)
Definition: ChebyshevPol.h:34
void Warning(const char *location, const char *msgfmt,...)
static RooMathCoreReg dummy
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
char name[80]
Definition: TGX11.cxx:109
void Error(ErrorHandler_t func, int code, const char *va_(fmt),...)
Write error message and call a handler, if required.