2 * \file src/FontInfo.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Lars Gullik Bjønnes
7 * \author Jean-Marc Lasgouttes
8 * \author Angus Leeming
12 * Full author contact details are available in file CREDITS.
21 #include "support/debug.h"
22 #include "support/docstring.h"
23 #include "support/lstrings.h"
26 using namespace lyx::support
;
31 // Strings used to read and write .lyx format files
33 char const * LyXFamilyNames
[NUM_FAMILIES
+ 2 /* default & error */] =
34 { "roman", "sans", "typewriter", "symbol",
35 "cmr", "cmsy", "cmm", "cmex", "msa", "msb", "eufrak", "wasy", "esint",
38 char const * LyXSeriesNames
[4] =
39 { "medium", "bold", "default", "error" };
41 char const * LyXShapeNames
[6] =
42 { "up", "italic", "slanted", "smallcaps", "default", "error" };
44 char const * LyXSizeNames
[14] =
45 { "tiny", "scriptsize", "footnotesize", "small", "normal", "large",
46 "larger", "largest", "huge", "giant",
47 "increase", "decrease", "default", "error" };
49 char const * LyXMiscNames
[5] =
50 { "off", "on", "toggle", "default", "error" };
53 FontInfo
const sane_font(
68 FontInfo
const inherit_font(
83 FontInfo
const ignore_font(
104 /// Decreases font size_ by one
105 FontInfo
& FontInfo::decSize()
108 case FONT_SIZE_HUGER
: size_
= FONT_SIZE_HUGE
; break;
109 case FONT_SIZE_HUGE
: size_
= FONT_SIZE_LARGEST
; break;
110 case FONT_SIZE_LARGEST
: size_
= FONT_SIZE_LARGER
; break;
111 case FONT_SIZE_LARGER
: size_
= FONT_SIZE_LARGE
; break;
112 case FONT_SIZE_LARGE
: size_
= FONT_SIZE_NORMAL
; break;
113 case FONT_SIZE_NORMAL
: size_
= FONT_SIZE_SMALL
; break;
114 case FONT_SIZE_SMALL
: size_
= FONT_SIZE_FOOTNOTE
; break;
115 case FONT_SIZE_FOOTNOTE
: size_
= FONT_SIZE_SCRIPT
; break;
116 case FONT_SIZE_SCRIPT
: size_
= FONT_SIZE_TINY
; break;
117 case FONT_SIZE_TINY
: break;
118 case FONT_SIZE_INCREASE
:
119 LYXERR0("Can't FontInfo::decSize on FONT_SIZE_INCREASE");
121 case FONT_SIZE_DECREASE
:
122 LYXERR0("Can't FontInfo::decSize on FONT_SIZE_DECREASE");
124 case FONT_SIZE_INHERIT
:
125 LYXERR0("Can't FontInfo::decSize on FONT_SIZE_INHERIT");
127 case FONT_SIZE_IGNORE
:
128 LYXERR0("Can't FontInfo::decSize on FONT_SIZE_IGNORE");
135 /// Increases font size_ by one
136 FontInfo
& FontInfo::incSize()
139 case FONT_SIZE_HUGER
: break;
140 case FONT_SIZE_HUGE
: size_
= FONT_SIZE_HUGER
; break;
141 case FONT_SIZE_LARGEST
: size_
= FONT_SIZE_HUGE
; break;
142 case FONT_SIZE_LARGER
: size_
= FONT_SIZE_LARGEST
; break;
143 case FONT_SIZE_LARGE
: size_
= FONT_SIZE_LARGER
; break;
144 case FONT_SIZE_NORMAL
: size_
= FONT_SIZE_LARGE
; break;
145 case FONT_SIZE_SMALL
: size_
= FONT_SIZE_NORMAL
; break;
146 case FONT_SIZE_FOOTNOTE
: size_
= FONT_SIZE_SMALL
; break;
147 case FONT_SIZE_SCRIPT
: size_
= FONT_SIZE_FOOTNOTE
; break;
148 case FONT_SIZE_TINY
: size_
= FONT_SIZE_SCRIPT
; break;
149 case FONT_SIZE_INCREASE
:
150 LYXERR0("Can't FontInfo::incSize on FONT_SIZE_INCREASE");
152 case FONT_SIZE_DECREASE
:
153 LYXERR0("Can't FontInfo::incSize on FONT_SIZE_DECREASE");
155 case FONT_SIZE_INHERIT
:
156 LYXERR0("Can't FontInfo::incSize on FONT_SIZE_INHERIT");
158 case FONT_SIZE_IGNORE
:
159 LYXERR0("Can't FontInfo::incSize on FONT_SIZE_IGNORE");
166 /// Reduce font to fall back to template where possible
167 void FontInfo::reduce(FontInfo
const & tmplt
)
169 if (family_
== tmplt
.family_
)
170 family_
= INHERIT_FAMILY
;
171 if (series_
== tmplt
.series_
)
172 series_
= INHERIT_SERIES
;
173 if (shape_
== tmplt
.shape_
)
174 shape_
= INHERIT_SHAPE
;
175 if (size_
== tmplt
.size_
)
176 size_
= FONT_SIZE_INHERIT
;
177 if (emph_
== tmplt
.emph_
)
178 emph_
= FONT_INHERIT
;
179 if (underbar_
== tmplt
.underbar_
)
180 underbar_
= FONT_INHERIT
;
181 if (strikeout_
== tmplt
.strikeout_
)
182 strikeout_
= FONT_INHERIT
;
183 if (uuline_
== tmplt
.uuline_
)
184 uuline_
= FONT_INHERIT
;
185 if (uwave_
== tmplt
.uwave_
)
186 uwave_
= FONT_INHERIT
;
187 if (noun_
== tmplt
.noun_
)
188 noun_
= FONT_INHERIT
;
189 if (color_
== tmplt
.color_
)
190 color_
= Color_inherit
;
191 if (background_
== tmplt
.background_
)
192 background_
= Color_inherit
;
196 /// Realize font from a template
197 FontInfo
& FontInfo::realize(FontInfo
const & tmplt
)
199 if ((*this) == inherit_font
) {
204 if (family_
== INHERIT_FAMILY
)
205 family_
= tmplt
.family_
;
207 if (series_
== INHERIT_SERIES
)
208 series_
= tmplt
.series_
;
210 if (shape_
== INHERIT_SHAPE
)
211 shape_
= tmplt
.shape_
;
213 if (size_
== FONT_SIZE_INHERIT
)
216 if (emph_
== FONT_INHERIT
)
219 if (underbar_
== FONT_INHERIT
)
220 underbar_
= tmplt
.underbar_
;
222 if (strikeout_
== FONT_INHERIT
)
223 strikeout_
= tmplt
.strikeout_
;
225 if (uuline_
== FONT_INHERIT
)
226 uuline_
= tmplt
.uuline_
;
228 if (uwave_
== FONT_INHERIT
)
229 uwave_
= tmplt
.uwave_
;
231 if (noun_
== FONT_INHERIT
)
234 if (color_
== Color_inherit
)
235 color_
= tmplt
.color_
;
237 if (background_
== Color_inherit
)
238 background_
= tmplt
.background_
;
244 /// Updates a misc setting according to request
245 static FontState
setMisc(FontState newfont
,
248 if (newfont
== FONT_TOGGLE
) {
251 else if (org
== FONT_OFF
)
254 LYXERR0("Font::setMisc: Need state"
255 " FONT_ON or FONT_OFF to toggle. Setting to FONT_ON");
258 } else if (newfont
== FONT_IGNORE
)
264 /// Updates font settings according to request
265 void FontInfo::update(FontInfo
const & newfont
, bool toggleall
)
267 if (newfont
.family_
== family_
&& toggleall
)
268 setFamily(INHERIT_FAMILY
); // toggle 'back'
269 else if (newfont
.family_
!= IGNORE_FAMILY
)
270 setFamily(newfont
.family_
);
271 // else it's IGNORE_SHAPE
273 // "Old" behaviour: "Setting" bold will toggle bold on/off.
274 switch (newfont
.series_
) {
277 if (series_
== BOLD_SERIES
&& toggleall
)
278 setSeries(MEDIUM_SERIES
);
280 setSeries(BOLD_SERIES
);
284 setSeries(newfont
.series_
);
290 if (newfont
.shape_
== shape_
&& toggleall
)
291 shape_
= INHERIT_SHAPE
; // toggle 'back'
292 else if (newfont
.shape_
!= IGNORE_SHAPE
)
293 shape_
= newfont
.shape_
;
294 // else it's IGNORE_SHAPE
296 if (newfont
.size_
!= FONT_SIZE_IGNORE
) {
297 if (newfont
.size_
== FONT_SIZE_INCREASE
)
299 else if (newfont
.size_
== FONT_SIZE_DECREASE
)
302 size_
= newfont
.size_
;
305 setEmph(setMisc(newfont
.emph_
, emph_
));
306 setUnderbar(setMisc(newfont
.underbar_
, underbar_
));
307 setStrikeout(setMisc(newfont
.strikeout_
, strikeout_
));
308 setUuline(setMisc(newfont
.uuline_
, uuline_
));
309 setUwave(setMisc(newfont
.uwave_
, uwave_
));
310 setNoun(setMisc(newfont
.noun_
, noun_
));
311 setNumber(setMisc(newfont
.number_
, number_
));
313 if (newfont
.color_
== color_
&& toggleall
)
314 setColor(Color_inherit
); // toggle 'back'
315 else if (newfont
.color_
!= Color_ignore
)
316 setColor(newfont
.color_
);
318 if (newfont
.background_
== background_
&& toggleall
)
319 setBackground(Color_inherit
); // toggle 'back'
320 else if (newfont
.background_
!= Color_ignore
)
321 setBackground(newfont
.background_
);
324 /// Is font resolved?
325 bool FontInfo::resolved() const
327 return (family_
!= INHERIT_FAMILY
&& series_
!= INHERIT_SERIES
328 && shape_
!= INHERIT_SHAPE
&& size_
!= FONT_SIZE_INHERIT
329 && emph_
!= FONT_INHERIT
&& underbar_
!= FONT_INHERIT
330 && uuline_
!= FONT_INHERIT
&& uwave_
!= FONT_INHERIT
331 && strikeout_
!= FONT_INHERIT
&& noun_
!= FONT_INHERIT
332 && color_
!= Color_inherit
333 && background_
!= Color_inherit
);
337 Color
FontInfo::realColor() const
339 if (paint_color_
!= Color_none
)
341 if (color_
== Color_none
)
342 return Color_foreground
;
349 void appendSep(string
& s1
, string
const & s2
) {
352 s1
+= s1
.empty() ? "" : "\n";
357 string
makeCSSTag(string
const & key
, string
const & val
)
359 return key
+ ": " + val
+ ";";
363 string
getFamilyCSS(FontFamily
const & f
)
370 case TYPEWRITER_FAMILY
:
390 string
getSeriesCSS(FontSeries
const & s
)
405 string
getShapeCSS(FontShape
const & s
)
407 string fs
= "normal";
408 string fv
= "normal";
410 case UP_SHAPE
: break;
411 case ITALIC_SHAPE
: fs
= "italic"; break;
412 case SLANTED_SHAPE
: fs
= "oblique"; break;
413 case SMALLCAPS_SHAPE
: fv
= "small-caps"; break;
416 fs
= ""; fv
= ""; break;
420 appendSep(retval
, makeCSSTag("font-style", fs
));
422 appendSep(retval
, makeCSSTag("font-variant", fv
));
427 string
getSizeCSS(FontSize
const & s
)
432 case FONT_SIZE_SCRIPT
:
434 case FONT_SIZE_FOOTNOTE
:
435 case FONT_SIZE_SMALL
:
437 case FONT_SIZE_NORMAL
:
439 case FONT_SIZE_LARGE
:
441 case FONT_SIZE_LARGER
:
442 case FONT_SIZE_LARGEST
:
445 case FONT_SIZE_HUGER
:
447 case FONT_SIZE_INCREASE
:
449 case FONT_SIZE_DECREASE
:
451 case FONT_SIZE_IGNORE
:
452 case FONT_SIZE_INHERIT
:
458 } // namespace anonymous
461 // FIXME This does not yet handle color
462 docstring
FontInfo::asCSS() const
465 string tmp
= getFamilyCSS(family_
);
467 appendSep(retval
, makeCSSTag("font-family", tmp
));
468 tmp
= getSeriesCSS(series_
);
470 appendSep(retval
, makeCSSTag("font-weight", tmp
));
471 appendSep(retval
, getShapeCSS(shape_
));
472 tmp
= getSizeCSS(size_
);
474 appendSep(retval
, makeCSSTag("font-size", tmp
));
475 return from_ascii(retval
);
479 // Set family according to lyx format string
480 void setLyXFamily(string
const & fam
, FontInfo
& f
)
482 string
const s
= ascii_lowercase(fam
);
485 while (LyXFamilyNames
[i
] != s
&&
486 LyXFamilyNames
[i
] != string("error"))
488 if (s
== LyXFamilyNames
[i
])
489 f
.setFamily(FontFamily(i
));
491 LYXERR0("Unknown family `" << s
<< '\'');
495 // Set series according to lyx format string
496 void setLyXSeries(string
const & ser
, FontInfo
& f
)
498 string
const s
= ascii_lowercase(ser
);
501 while (LyXSeriesNames
[i
] != s
&&
502 LyXSeriesNames
[i
] != string("error")) ++i
;
503 if (s
== LyXSeriesNames
[i
]) {
504 f
.setSeries(FontSeries(i
));
506 LYXERR0("Unknown series `" << s
<< '\'');
510 // Set shape according to lyx format string
511 void setLyXShape(string
const & sha
, FontInfo
& f
)
513 string
const s
= ascii_lowercase(sha
);
516 while (LyXShapeNames
[i
] != s
&& LyXShapeNames
[i
] != string("error"))
518 if (s
== LyXShapeNames
[i
])
519 f
.setShape(FontShape(i
));
521 LYXERR0("Unknown shape `" << s
<< '\'');
525 // Set size according to lyx format string
526 void setLyXSize(string
const & siz
, FontInfo
& f
)
528 string
const s
= ascii_lowercase(siz
);
530 while (LyXSizeNames
[i
] != s
&& LyXSizeNames
[i
] != string("error"))
532 if (s
== LyXSizeNames
[i
]) {
533 f
.setSize(FontSize(i
));
535 LYXERR0("Unknown size `" << s
<< '\'');
539 // Set size according to lyx format string
540 FontState
setLyXMisc(string
const & siz
)
542 string
const s
= ascii_lowercase(siz
);
544 while (LyXMiscNames
[i
] != s
&&
545 LyXMiscNames
[i
] != string("error")) ++i
;
546 if (s
== LyXMiscNames
[i
])
548 LYXERR0("Unknown misc flag `" << s
<< '\'');
553 /// Sets color after LyX text format
554 void setLyXColor(string
const & col
, FontInfo
& f
)
556 f
.setColor(lcolor
.getFromLyXName(col
));
560 // Read a font definition from given file in lyx format
562 FontInfo
lyxRead(Lexer
& lex
, FontInfo
const & fi
)
566 bool finished
= false;
567 while (!finished
&& lex
.isOK() && !error
) {
569 string
const tok
= ascii_lowercase(lex
.getString());
573 } else if (tok
== "endfont") {
575 } else if (tok
== "family") {
577 string
const ttok
= lex
.getString();
578 setLyXFamily(ttok
, f
);
579 } else if (tok
== "series") {
581 string
const ttok
= lex
.getString();
582 setLyXSeries(ttok
, f
);
583 } else if (tok
== "shape") {
585 string
const ttok
= lex
.getString();
586 setLyXShape(ttok
, f
);
587 } else if (tok
== "size") {
589 string
const ttok
= lex
.getString();
591 } else if (tok
== "misc") {
593 string
const ttok
= ascii_lowercase(lex
.getString());
595 if (ttok
== "no_bar") {
596 f
.setUnderbar(FONT_OFF
);
597 } else if (ttok
== "no_strikeout") {
598 f
.setStrikeout(FONT_OFF
);
599 } else if (ttok
== "no_uuline") {
600 f
.setUuline(FONT_OFF
);
601 } else if (ttok
== "no_uwave") {
602 f
.setUwave(FONT_OFF
);
603 } else if (ttok
== "no_emph") {
605 } else if (ttok
== "no_noun") {
607 } else if (ttok
== "emph") {
609 } else if (ttok
== "underbar") {
610 f
.setUnderbar(FONT_ON
);
611 } else if (ttok
== "strikeout") {
612 f
.setStrikeout(FONT_ON
);
613 } else if (ttok
== "uuline") {
614 f
.setUuline(FONT_ON
);
615 } else if (ttok
== "uwave") {
617 } else if (ttok
== "noun") {
620 lex
.printError("Illegal misc type");
622 } else if (tok
== "color") {
624 string
const ttok
= lex
.getString();
625 setLyXColor(ttok
, f
);
627 lex
.printError("Unknown tag");