]> git.lyx.org Git - lyx.git/blob - src/frontends/gtk/GPainter.C
Joao latest bits
[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  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12 #include <gtkmm.h>
13
14 #include "GPainter.h"
15 #include "debug.h"
16 #include "GWorkArea.h"
17 #include "lyxrc.h"
18 #include "encoding.h"
19 #include "language.h"
20 #include "LColor.h"
21 #include "xftFontLoader.h"
22 #include "xformsImage.h"
23 #include "frontends/font_metrics.h"
24 #include "codeConvert.h"
25
26 #include "support/lstrings.h"
27
28 #include <boost/scoped_array.hpp>
29
30 #include <X11/Xft/Xft.h>
31
32 #include <cmath>
33
34 using std::string;
35
36
37 GPainter::GPainter(GWorkArea & xwa)
38         : Painter(), owner_(xwa)
39 {
40 }
41
42
43 int GPainter::paperWidth() const
44 {
45         return owner_.workWidth();
46 }
47
48
49 int GPainter::paperHeight() const
50 {
51         return owner_.workHeight();
52 }
53
54
55 void GPainter::setForeground(Glib::RefPtr<Gdk::GC> gc, LColor_color clr)
56 {
57         Gdk::Color * gclr = owner_.getColorHandler().getGdkColor(clr);
58         gc->set_foreground(*gclr);
59 }
60
61
62 void GPainter::setLineParam(Glib::RefPtr<Gdk::GC> gc,
63                             line_style ls, line_width lw)
64 {
65         int width;
66         Gdk::LineStyle style;
67         switch (lw) {
68         case Painter::line_thin:
69                 width = 0;
70                 break;
71         case Painter::line_thick:
72                 width = 2;
73                 break;
74         }
75
76         switch (ls) {
77         case Painter::line_solid:
78                 style = Gdk::LINE_SOLID;
79                 break;
80         case Painter::line_onoffdash:
81                 style = Gdk::LINE_ON_OFF_DASH;
82                 break;
83         }
84         gc->set_line_attributes(width, style,
85                                 Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER);
86 }
87
88
89 Painter & GPainter::point(int x, int y, LColor_color c)
90 {
91         setForeground(owner_.getGC(), c);
92         owner_.getPixmap()->draw_point(owner_.getGC(), x, y);
93         return *this;
94 }
95
96
97 Painter & GPainter::line(int x1, int y1,
98         int x2, int y2,
99         LColor_color col,
100         line_style ls,
101         line_width lw)
102 {
103         setForeground(owner_.getGC(), col);
104         setLineParam(owner_.getGC(), ls, lw);
105         owner_.getPixmap()->draw_line(owner_.getGC(), x1, y1, x2, y2);
106         return *this;
107 }
108
109
110 Painter & GPainter::lines(int const * xp, int const * yp,
111         int np,
112         LColor_color col,
113         line_style ls,
114         line_width lw)
115 {
116         setForeground(owner_.getGC(), col);
117         setLineParam(owner_.getGC(), ls, lw);
118         std::vector<Gdk::Point> points(np);
119
120         for (int i = 0; i < np; ++i) {
121                 points[i].set_x(xp[i]);
122                 points[i].set_y(yp[i]);
123         }
124         owner_.getPixmap()->draw_lines(owner_.getGC(), points);
125         return *this;
126 }
127
128
129 Painter & GPainter::rectangle(int x, int y,
130         int w, int h,
131         LColor_color col,
132         line_style ls,
133         line_width lw)
134 {
135         setForeground(owner_.getGC(), col);
136         setLineParam(owner_.getGC(), ls, lw);
137         owner_.getPixmap()->draw_rectangle(owner_.getGC(), false, x, y, w, h);
138         return *this;
139 }
140
141
142 Painter & GPainter::fillRectangle(int x, int y,
143         int w, int h,
144         LColor_color col)
145 {
146         setForeground(owner_.getGC(), col);
147         owner_.getPixmap()->draw_rectangle(owner_.getGC(), true, x, y, w, h);
148         return *this;
149 }
150
151
152 Painter & GPainter::fillPolygon(int const * xp, int const * yp,
153         int np, LColor_color col)
154 {
155         setForeground(owner_.getGC(), col);
156         std::vector<Gdk::Point> points(np);
157
158         for (int i = 0; i < np; ++i) {
159                 points[i].set_x(xp[i]);
160                 points[i].set_y(yp[i]);
161         }
162         owner_.getPixmap()->draw_polygon(owner_.getGC(), true, points);
163         return *this;
164 }
165
166
167 Painter & GPainter::arc(int x, int y,
168         unsigned int w, unsigned int h,
169         int a1, int a2, LColor_color col)
170 {
171         setForeground(owner_.getGC(), col);
172         owner_.getPixmap()->draw_arc(owner_.getGC(),
173                                      false, x, y, w, h, a1, a2);
174         return *this;
175 }
176
177
178 Painter & GPainter::image(int x, int y,
179         int w, int h,
180         lyx::graphics::Image const & i)
181 {
182         lyx::graphics::xformsImage const & image =
183                 static_cast<lyx::graphics::xformsImage const &>(i);
184         Pixmap pixmap = GDK_PIXMAP_XID(owner_.getPixmap()->gobj());
185         GC gc = GDK_GC_XGC(owner_.getGC()->gobj());
186         XCopyArea(owner_.getDisplay(), image.getPixmap(), pixmap,
187                   gc, 0, 0, w, h, x, y);
188         return *this;
189 }
190
191
192 Painter & GPainter::text(int x, int y,
193         std::string const & s, LyXFont const & f)
194 {
195         size_t size = s.length() + 1;
196         wchar_t * wcs = (wchar_t *) alloca(size * sizeof(wchar_t));
197         size = mbstowcs(wcs, s.c_str(), size);
198         return text(x, y, wcs, size, f);
199 }
200
201
202 Painter & GPainter::text(int x, int y,
203         char c, LyXFont const & f)
204 {
205         char s[2] = { c, '\0' };
206         return text(x, y, s, 1, f);
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 namespace font_metrics
218 {
219
220 int width(wchar_t const *s, size_t n, LyXFont const & f);
221
222 }
223
224
225 Painter & GPainter::text(int x, int y, wchar_t const * s, int ls,
226                       LyXFont const & f)
227 {
228         XftFont * font = getXftFont(f);
229         XftColor * xftClr = owner_.getColorHandler().
230                 getXftColor(f.realColor());
231 //      getXftColor(f.realColor());
232         XftDraw * draw = owner_.getXftDraw();
233         if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
234                 XftDrawString32(draw, xftClr, font, x, y,
235                                 wcsToXftChar32StrFast(s), ls);
236         } else {
237                 LyXFont smallfont(f);
238                 smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
239                 XftFont * fontS = getXftFont(smallfont);
240                 wchar_t c;
241                 int tmpx = x;
242                 for(int i = 0; i < ls; ++i) {
243                         c = lyx::support::uppercase(s[i]);
244                         if(c != s[i]) {
245                                 XftDrawString32(draw, xftClr, fontS, tmpx, y,
246                                                 wcsToXftChar32StrFast(&c), 1);
247                                 tmpx += font_metrics::width(c, smallfont);
248                         } else {
249                                 XftDrawString32(draw, xftClr, font, tmpx, y,
250                                                 wcsToXftChar32StrFast(&c), 1);
251                                 tmpx += font_metrics::width(c, f);
252                         }
253                 }
254         }
255         if (f.underbar() == LyXFont::ON)
256                 underline(f, x, y, font_metrics::width(s, ls, f));
257         return *this;
258 }
259
260
261 Painter & GPainter::text(int x, int y,
262         char const * s, size_t ls,
263         LyXFont const & f)
264 {
265         boost::scoped_array<wchar_t> wcs(new wchar_t[ls + 1]);
266         size_t len;
267         if (fontLoader.isSpecial(f)) {
268                 unsigned char const * us =
269                         reinterpret_cast<unsigned char const *>(s);
270                 len = ls;
271                 std::copy(us, us + ls, wcs.get());
272         } else
273                 len = mbstowcs(wcs.get(), s, ls + 1);
274         return text(x, y, wcs.get(), len, f);
275 }