]> git.lyx.org Git - features.git/blob - src/FontList.cpp
Fix scons and src/FontList.cpp for the addition of FontList.h|cpp
[features.git] / src / FontList.cpp
1 /**
2  * \file FontList.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup
7  * \author Lars Gullik Bjønnes
8  * \author Jean-Marc Lasgouttes
9  * \author Angus Leeming
10  * \author John Levon
11  * \author André Pönitz
12  * \author Dekel Tsur
13  * \author Jürgen Vigna
14  * \author Abdelrazak Younes
15  *
16  * Full author contact details are available in file CREDITS.
17  */
18
19 #include <config.h>
20
21 #include "FontList.h"
22
23 #include <boost/next_prior.hpp>
24
25 #include <algorithm>
26
27 using std::distance;
28 using std::endl;
29 using std::string;
30 using std::ostream;
31
32 namespace lyx {
33
34 namespace {
35
36 class matchFT
37 {
38 public:
39         /// used by lower_bound and upper_bound
40         int operator()(FontTable const & a, FontTable const & b) const {
41                 return a.pos() < b.pos();
42         }
43 };
44
45 } // anon namespace
46
47 FontList::iterator FontList::fontIterator(pos_type pos)
48 {
49         static Font dummy;
50         FontTable search_elem(pos, dummy);
51         return lower_bound(list_.begin(), list_.end(), search_elem,
52                 matchFT());
53 }
54
55
56 FontList::const_iterator FontList::fontIterator(pos_type pos) const
57 {
58         static Font dummy;
59         FontTable search_elem(pos, dummy);
60         return lower_bound(list_.begin(), list_.end(), search_elem,
61                 matchFT());
62 }
63
64
65 Font & FontList::get(pos_type pos)
66 {
67         iterator end = list_.end();
68         iterator it = fontIterator(pos);
69         if (it != end && it->pos() == pos)
70                 return it->font_;
71         static Font dummy;
72         return dummy;
73 }
74
75
76 void FontList::erase(pos_type pos)
77 {
78         // Erase entries in the tables.
79         iterator it = fontIterator(pos);
80         iterator beg = list_.begin();
81         if (it != list_.end() && it->pos() == pos
82                 && (pos == 0 
83                         || (it != beg && boost::prior(it)->pos() == pos - 1))) {
84
85                 // If it is a multi-character font
86                 // entry, we just make it smaller
87                 // (see update below), otherwise we
88                 // should delete it.
89                 unsigned int const i = it - beg;
90                 list_.erase(beg + i);
91                 it = beg + i;
92                 if (i > 0 && i < list_.size() &&
93                     list_[i - 1].font() == list_[i].font()) {
94                         list_.erase(beg + i - 1);
95                         it = beg + i - 1;
96                 }
97         }
98
99         // Update all other entries
100         iterator end = list_.end();
101         for (; it != end; ++it)
102                 it->pos(it->pos() - 1);
103 }
104
105 void FontList::increasePosAfterPos(pos_type pos)
106 {
107         List::iterator end = list_.end();
108         List::iterator it = fontIterator(pos);
109         for (; it != end; ++it)
110                 ++it->pos_;
111 }
112
113
114 void FontList::decreasePosAfterPos(pos_type pos)
115 {
116         List::iterator end = list_.end();
117         List::iterator it = fontIterator(pos);
118         for (; it != end; ++it)
119                 --it->pos_;
120 }
121
122
123 void FontList::set(pos_type pos, Font const & font)
124 {
125         // No need to simplify this because it will disappear
126         // in a new kernel. (Asger)
127         // Next search font table
128
129         iterator beg = list_.begin();
130         iterator it = beg;
131         iterator endit = list_.end();
132         for (; it != endit; ++it) {
133                 if (it->pos() >= pos)
134                         break;
135         }
136         size_t const i = distance(beg, it);
137         bool notfound = (it == endit);
138
139         if (!notfound && list_[i].font() == font)
140                 return;
141
142         bool begin = pos == 0 || notfound ||
143                 (i > 0 && list_[i - 1].pos() == pos - 1);
144         // Is position pos is a beginning of a font block?
145         bool end = !notfound && list_[i].pos() == pos;
146         // Is position pos is the end of a font block?
147         if (begin && end) { // A single char block
148                 if (i + 1 < list_.size() &&
149                     list_[i + 1].font() == font) {
150                         // Merge the singleton block with the next block
151                         list_.erase(list_.begin() + i);
152                         if (i > 0 && list_[i - 1].font() == font)
153                                 list_.erase(list_.begin() + i - 1);
154                 } else if (i > 0 && list_[i - 1].font() == font) {
155                         // Merge the singleton block with the previous block
156                         list_[i - 1].pos(pos);
157                         list_.erase(list_.begin() + i);
158                 } else
159                         list_[i].font(font);
160         } else if (begin) {
161                 if (i > 0 && list_[i - 1].font() == font)
162                         list_[i - 1].pos(pos);
163                 else
164                         list_.insert(list_.begin() + i,
165                                         FontTable(pos, font));
166         } else if (end) {
167                 list_[i].pos(pos - 1);
168                 if (!(i + 1 < list_.size() &&
169                       list_[i + 1].font() == font))
170                         list_.insert(list_.begin() + i + 1,
171                                         FontTable(pos, font));
172         } else { // The general case. The block is splitted into 3 blocks
173                 list_.insert(list_.begin() + i,
174                                 FontTable(pos - 1, list_[i].font()));
175                 list_.insert(list_.begin() + i + 1,
176                                 FontTable(pos, font));
177         }
178 }
179
180
181 Font_size FontList::highestInRange
182         (pos_type startpos, pos_type endpos, Font_size def_size) const
183 {
184         if (list_.empty())
185                 return def_size;
186
187         const_iterator end_it = list_.begin();
188         const_iterator const end = list_.end();
189         for (; end_it != end; ++end_it) {
190                 if (end_it->pos() >= endpos)
191                         break;
192         }
193
194         if (end_it != end)
195                 ++end_it;
196
197         FontList::const_iterator cit = list_.begin();
198         for (; cit != end; ++cit) {
199                 if (cit->pos() >= startpos)
200                         break;
201         }
202
203         Font::FONT_SIZE maxsize = Font::SIZE_TINY;
204         for (; cit != end_it; ++cit) {
205                 Font::FONT_SIZE size = cit->font().size();
206                 if (size == Font::INHERIT_SIZE)
207                         size = def_size;
208                 if (size > maxsize && size <= Font::SIZE_HUGER)
209                         maxsize = size;
210         }
211         return maxsize;
212 }
213
214 } // namespace lyx