]> git.lyx.org Git - lyx.git/blob - src/frontends/gtk/GPainter.C
fontloader for gtk, probably not efficient
[lyx.git] / src / frontends / gtk / GPainter.C
1 /**
2  * \file GPainter.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Huang Ying
7  * \author John Spray
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 // Too hard to make concept checks work with this file
15 #ifdef _GLIBCXX_CONCEPT_CHECKS
16 #undef _GLIBCXX_CONCEPT_CHECKS
17 #endif
18 #ifdef _GLIBCPP_CONCEPT_CHECKS
19 #undef _GLIBCPP_CONCEPT_CHECKS
20 #endif
21
22 #include "GPainter.h"
23 #include "debug.h"
24 #include "GWorkArea.h"
25 #include "LyXGdkImage.h"
26 #include "lyxrc.h"
27 #include "encoding.h"
28 #include "language.h"
29 #include "LColor.h"
30 #include "xftFontLoader.h"
31
32 #include "frontends/Application.h"
33 #include "frontends/FontMetrics.h"
34
35 #include "support/lstrings.h"
36
37 #include <gtkmm.h>
38 #include <gdk/gdkx.h>
39
40 #include <X11/Xft/Xft.h>
41
42 #include <boost/scoped_array.hpp>
43
44 #include <cmath>
45
46 using std::string;
47
48 namespace lyx {
49 namespace frontend {
50
51 GPainter::GPainter(GWorkArea & xwa)
52         : Painter(), owner_(xwa), currentcolor_(LColor::magenta)
53 {
54 }
55
56
57 int GPainter::paperWidth() const
58 {
59         return owner_.workWidth();
60 }
61
62
63 int GPainter::paperHeight() const
64 {
65         return owner_.workHeight();
66 }
67
68
69 inline void GPainter::setForeground(LColor_color clr)
70 {
71         if (clr != currentcolor_) {
72                 gc_->set_foreground(*(colorhandler_->getGdkColor(clr)));
73                 currentcolor_ = clr;
74         }
75 }
76
77
78 void GPainter::start()
79 {
80         pixmap_ = owner_.getPixmap();
81         colorhandler_ = &(owner_.getColorHandler());
82         gc_ = owner_.getGC();
83         gc_->set_foreground(*(colorhandler_->getGdkColor(currentcolor_)));
84 }
85
86
87 inline void GPainter::setLineParam(line_style ls, line_width lw)
88 {
89         int width = 0;
90         switch (lw) {
91         case Painter::line_thin:
92                 width = 0;
93                 break;
94         case Painter::line_thick:
95                 width = 2;
96                 break;
97         }
98
99         Gdk::LineStyle style = Gdk::LINE_SOLID;
100         switch (ls) {
101         case Painter::line_solid:
102                 style = Gdk::LINE_SOLID;
103                 break;
104         case Painter::line_onoffdash:
105                 style = Gdk::LINE_ON_OFF_DASH;
106                 break;
107         }
108         gc_->set_line_attributes(width, style,
109                                 Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER);
110 }
111
112
113 void GPainter::point(int x, int y, LColor_color c)
114 {
115         setForeground(c);
116         pixmap_->draw_point(gc_, x, y);
117 }
118
119
120 void GPainter::line(int x1, int y1,
121         int x2, int y2,
122         LColor_color col,
123         line_style ls,
124         line_width lw)
125 {
126         setForeground(col);
127         setLineParam(ls, lw);
128         pixmap_->draw_line(gc_, x1, y1, x2, y2);
129 }
130
131
132 void GPainter::lines(int const * xp, int const * yp, int np,
133         LColor_color col,
134         line_style ls,
135         line_width lw)
136 {
137         setForeground(col);
138         setLineParam(ls, lw);
139         std::vector<Gdk::Point> points(np);
140
141         for (int i = 0; i < np; ++i) {
142                 points[i].set_x(xp[i]);
143                 points[i].set_y(yp[i]);
144         }
145         pixmap_->draw_lines(gc_, points);
146 }
147
148
149 void GPainter::rectangle(int x, int y, int w, int h,
150         LColor_color col,
151         line_style ls,
152         line_width lw)
153 {
154         setForeground(col);
155         setLineParam(ls, lw);
156         pixmap_->draw_rectangle(gc_, false, x, y, w, h);
157 }
158
159
160 void GPainter::fillRectangle(int x, int y, int w, int h,
161         LColor_color col)
162 {
163         setForeground(col);
164         pixmap_->draw_rectangle(gc_, true, x, y, w, h);
165 }
166
167
168 void GPainter::arc(int x, int y, unsigned int w, unsigned int h,
169         int a1, int a2, LColor_color col)
170 {
171         setForeground(col);
172         pixmap_->draw_arc(gc_,
173                                      false, x, y, w, h, a1, a2);
174 }
175
176
177 void GPainter::image(int x, int y, int w, int h,
178         graphics::Image const & i)
179 {
180         graphics::LyXGdkImage const & image =
181                 static_cast<graphics::LyXGdkImage const &>(i);
182         Glib::RefPtr<Gdk::Pixbuf> const & pixbuf = image.pixbuf();
183         Glib::RefPtr<Gdk::Pixmap> pixmap = pixmap_;
184
185         Glib::RefPtr<Gdk::GC> gc = gc_;
186         pixmap->draw_pixbuf (gc, pixbuf, 0, 0, x, y, w, h,
187                              Gdk::RGB_DITHER_NONE, 0, 0);
188 }
189
190 namespace {
191
192 inline XftFont * getXftFont(LyXFont const & f)
193 {
194         return fontLoader.load(f.family(), f.series(),
195                 f.realShape(), f.size());
196 }
197
198 } // anon namespace
199
200
201 int GPainter::text(int x, int y,
202                     char_type const * s, size_t ls,
203                     LyXFont const & f)
204 {
205         XftFont * font = getXftFont(f);
206         XftColor * xftClr = owner_.getColorHandler().
207                 getXftColor(f.realColor());
208         XftDraw * draw = owner_.getXftDraw();
209         int textwidth = 0;
210
211         if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
212                 XftDrawString32(draw,
213                                 xftClr,
214                                 font,
215                                 x, y,
216                                 reinterpret_cast<FcChar32 const *>(s),
217                                 ls);
218                 textwidth = theApp->fontLoader().metrics(f).width(s, ls);
219         } else {
220                 LyXFont smallfont(f);
221                 smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
222                 XftFont * fontS = getXftFont(smallfont);
223                 for (unsigned int i = 0; i < ls; ++i) {
224                         // Ok, this looks quite ugly...
225                         char_type c = gdk_keyval_to_unicode(gdk_keyval_to_upper(gdk_unicode_to_keyval(s[i])));
226                         if (c != s[i]) {
227                                 XftDrawString32(draw,
228                                                 xftClr,
229                                                 fontS,
230                                                 x + textwidth, y,
231                                                 reinterpret_cast<FcChar32 *>(&c),
232                                                 1);
233                                 textwidth += theApp->fontLoader().metrics(smallfont).width(c);
234                         } else {
235                                 XftDrawString32(draw,
236                                                 xftClr,
237                                                 font,
238                                                 x + textwidth, y,
239                                                 reinterpret_cast<FcChar32 *>(&c),
240                                                 1);
241                                 textwidth += theApp->fontLoader().metrics(f).width(c);
242                         }
243                 }
244         }
245         if (f.underbar() == LyXFont::ON)
246                 underline(f, x, y, textwidth);
247
248         return textwidth;
249 }
250
251
252 int GPainter::text(int x, int y, docstring const & s, LyXFont const & f)
253 {
254         return text (x, y, reinterpret_cast<char_type const *>(s.data()), s.size(), f);
255 }
256
257
258 int GPainter::text(int x, int y, char_type c, LyXFont const & f)
259 {
260         return text (x, y, &c, 1, f);
261 }
262
263
264 } // namespace frontend
265 } // namespace lyx