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