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