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