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