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