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