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