]> www.fi.muni.cz Git - evince.git/blob - dvi/painter.cc
2dc57e2c46abae2f8b48e2eb478d2fb3b0cd90b0
[evince.git] / dvi / painter.cc
1 #include "painter.hh"
2 #include "dl-dvi-fontdefinition.hh"
3
4 using DviLib::DviFontdefinition;
5 using DviLib::DviFontMap;
6 using DviLib::AbstractCharacter;
7
8 // paint a bitmap
9 void
10 DviPainter::paint_bitmap (const unsigned char *data,
11                           uint width, uint height, 
12                           int hoffset, int voffset)
13 {
14     GdkPixbuf *pixbuf = 
15         gdk_pixbuf_new_from_data (data,
16                                   GDK_COLORSPACE_RGB, 
17                                   TRUE,        // has_alpha,
18                                   8,
19                                   width,
20                                   height,
21                                   width * 4,  // rowstride
22                                   NULL,     // destroy_fn
23                                   NULL);    // destroy_fn_data
24     
25     uint x = dvi_to_pixels (current_frame->h);
26     uint y = dvi_to_pixels (current_frame->v);
27     
28     gdk_pixbuf_render_to_drawable (pixbuf,
29                                    pixmap,
30                                    gc,
31                                    0, 0,
32                                    x-hoffset,
33                                    y-voffset,
34                                    //y+(height - voffset),
35                                    width,
36                                    height,
37                                    GDK_RGB_DITHER_NONE,
38                                    0, 0);
39 }
40
41 // typeset ch, move w
42 void 
43 DviPainter::set_char (int ch)
44 {
45     AbstractCharacter *character = current_frame->font->get_char (ch);
46     character->paint (* this);
47     
48     int tfm_width = character->get_tfm_width ();
49     int at_size = current_frame->font->get_at_size ();
50     int dvi_width = tfm_to_dvi (tfm_width, at_size);
51     
52     current_frame->h += dvi_width;
53 }
54
55 // typeset ch, don't move
56 void 
57 DviPainter::put_char (int ch)
58 {
59     AbstractCharacter *character = current_frame->font->get_char (ch);
60     character->paint (* this);
61 }
62
63 void 
64 // rule, move (height, width)
65 DviPainter::set_rule (int height, 
66                       int width)
67 {
68     int width_p = dvi_to_pixels_no_offset (width);
69     int height_p = dvi_to_pixels_no_offset (height);
70     int x = dvi_to_pixels (current_frame->h);
71     int y = dvi_to_pixels (current_frame->v);
72     
73 #if 0
74     cout << "BIRNAN\n" << endl;
75 #endif
76     
77     gdk_draw_rectangle (pixmap, gc, TRUE, 
78                         x, y, 
79                         width_p + 1, height_p + 1);
80     
81     current_frame->h += width;
82 }
83
84 // rule, don't move
85 void 
86 DviPainter::put_rule (int height, 
87                       int width)
88 {
89     cout << "w h " << width << " " << height << " " << endl;
90     
91     int width_p = dvi_to_pixels_no_offset (width);
92     int height_p = dvi_to_pixels_no_offset (height);
93     int x = dvi_to_pixels (current_frame->h);
94     int y = dvi_to_pixels (current_frame->v);
95     
96     cout << "EMFLE\n" << endl;
97     
98     cout << "x y h w " << x << " " << y << " " << height_p << " " 
99          << width_p << endl;
100     
101     gdk_draw_rectangle (pixmap, gc, TRUE, 
102                         x, y, 
103                         width_p + 1, height_p + 1);
104 }
105
106 // push current context
107 DviFrame *
108 DviFrame::copy (void)
109 {
110     DviFrame *frame = new DviFrame ();
111
112     frame->fontmap = this->fontmap;
113     if (frame->fontmap)
114         frame->fontmap->ref();
115     frame->h = this->h;
116     frame->v = this->v;
117     frame->w = this->w;
118     frame->x = this->x;
119     frame->y = this->y;
120     frame->z = this->z;
121     frame->font = this->font;
122     if (frame->font)
123         frame->font->ref();
124     
125     return frame;
126 }
127
128 DviFrame::~DviFrame()
129 {
130     if (this->fontmap)
131         this->fontmap->unref();
132     if (this->font)
133         this->font->unref();
134 }
135
136 void 
137 DviPainter::push (void)
138 {
139     DviFrame *new_frame = current_frame->copy();
140     new_frame->next = current_frame;
141     current_frame = new_frame;
142     if (current_frame->font)
143         cout << "push: there is a font" << endl;
144     else
145         cout << "push: there is not a font" << endl;
146 }
147
148 // pop ccontext
149 void 
150 DviPainter::pop (void)
151 {
152     DviFrame *old_frame = current_frame;
153
154     // FIXME: dvi assumes that fonts survive pops
155     // FIXME: however, do they also survive the final pop of a vfchar?
156     
157     current_frame = current_frame->next;
158
159     if (current_frame && current_frame->font)
160         cout << "pop: there is a font" << endl;
161     else if (current_frame)
162         cout << "pop: there is not font" << endl;
163     else
164         cout << "no current" << endl;
165     
166     old_frame->unref();
167 }
168
169 // move right len
170 void 
171 DviPainter::right (int len)
172 {
173     current_frame->h += len;
174 }
175
176 // move right len, set w = len
177 void 
178 DviPainter::w (int len)
179 {
180     right (len);
181     current_frame->w = len;
182 }
183
184 // move right w
185 void 
186 DviPainter::w_rep ()
187 {
188     right (current_frame->w);
189 }
190
191 // move right len, set x = len
192 void 
193 DviPainter::x (int len)
194 {
195     right (len);
196     current_frame->x = len;
197 }
198
199 // move right x
200 void 
201 DviPainter::x_rep ()
202 {
203     right (current_frame->x);
204 }
205
206 // move down len
207 void 
208 DviPainter::down (int len)
209 {
210     current_frame->v += len;
211 }
212
213 // move down len, set y = len
214 void 
215 DviPainter::y (int len)
216 {
217     down (len);
218     current_frame->y = len;
219 }
220
221 // move down y
222 void 
223 DviPainter::y_rep ()
224 {
225     down (current_frame->y);
226 }
227
228 // move down len, set z = len
229 void 
230 DviPainter::z (int len)
231 {
232     down (len);
233     current_frame->z = len;
234 }
235
236 // move down z
237 void 
238 DviPainter::z_rep ()
239 {
240     down (current_frame->z);
241 }
242
243 // f = font_num 
244 void 
245 DviPainter::font_num (int font_num)
246 {
247     DviFontdefinition *fd = current_frame->fontmap->get_fontdefinition (font_num);
248
249     g_assert (fd);
250     if (fd)
251     {
252         // gtkdvi:
253         int dpi = (int)floor( 0.5 + 1.0 * base_dpi * 
254                               dvi_file->get_magnification() * fd->at_size /
255                               ( 1000.0 * fd->design_size));
256
257         cout << fd->name << " design size: " << fd->design_size << " at size " << fd->at_size << endl;
258         
259         if (current_frame->font)
260             current_frame->font->unref();
261         
262         current_frame->font = 
263             font_factory->create_font (fd->name, dpi, fd->at_size);
264
265         g_assert (current_frame->font);
266         cout << "there is now a font"<< endl;
267     
268     }
269 }
270
271 // do something special
272 void 
273 DviPainter::special (string spc)
274 {
275     cout << "warning: special " << spc << " " << "not handled" << endl;
276 }
277
278 int 
279 DviPainter::tfm_to_dvi (uint tfm, int at_size)
280 {
281     // this is from gtkdvi:
282     int alpha, z, beta, b0, b1, b2, b3, r;
283     
284     alpha = 16;
285     z = at_size;
286     while (z >= (1<<23))
287     {
288         z >>= 1;
289         alpha <<= 1;
290     }
291     beta = 256/alpha;
292     alpha *= z;
293     
294 #if 0
295     b0 = tfm & (0xFF << 24);
296     b1 = tfm & (0xFF << 16);
297     b2 = tfm & (0xFF << 8);
298     b3 = tfm & (0xFF << 0);
299 #endif
300     
301     b0 = tfm >> 24;  
302     b1 = (tfm >> 16) & 255;
303     b2 = (tfm >> 8) & 255;
304     b3 = tfm & 255;
305     
306 #if 0
307     r = (((((b3 * z) / 256) + (b2 * z)) / 256) + (b1 * z))/beta;
308 #endif
309     
310     b1 *= z;
311     b2 *= z;
312     b3 *= z;
313     
314     r = (((b3 / 256 + b2) / 256) + b1) / beta;
315     
316     if (b0 > 0)
317     {
318         if ((b0 > 0) != (tfm > 0))
319             cout << "b0: " << b0 << "tfm: " << tfm << endl;
320         r -= alpha;
321     }
322     
323     return r;
324 }
325
326 DviPainter::DviPainter (GdkPixmap              *pixmap_arg,
327                          GdkGC                 *gc_arg,
328                          DviLib::DviFile       *dvi_file_arg,
329                          uint                   base_dpi_arg,
330                          AbstractFontFactory   *font_factory_arg)
331 {
332     pixmap              = (GdkPixmap *)g_object_ref (pixmap_arg);
333     gc                  = (GdkGC *)g_object_ref (gc_arg);
334     dvi_file            = dvi_file_arg;
335     base_dpi            = base_dpi_arg;
336     font_factory        = font_factory_arg;
337
338     dvi_file->ref();
339     font_factory->ref();
340     
341     current_frame = new DviFrame;
342     current_frame->h = 0;
343     current_frame->v = 0;
344     current_frame->w = 0;
345     current_frame->x = 0;
346     current_frame->y = 0;
347     current_frame->z = 0;
348     current_frame->fontmap = NULL;
349     current_frame->font = NULL;
350     
351     // from gtkdvi:
352     scale =  dvi_file->get_numerator() / 254000.0;
353     scale *= 1.0 * base_dpi / dvi_file->get_denominator ();
354     scale *= dvi_file->get_magnification () / 1000.0;
355 }
356
357 DviPainter::~DviPainter ()
358 {
359     g_object_unref (pixmap);
360     g_object_unref (gc);
361     dvi_file->unref();
362     font_factory->unref();
363     while (current_frame)
364         pop();
365 }
366
367 void
368 DviPainter::fontmap (DviFontMap *fontmap)
369 {
370     fontmap->ref();
371
372     if (current_frame->fontmap)
373         current_frame->fontmap->unref();
374
375     current_frame->fontmap = fontmap;
376 }