1 /****************************************************************************
2  * Copyright (C) 2008-2011 by Matteo Franchin                               *
3  *                                                                          *
4  * This file is part of Box.                                                *
5  *                                                                          *
6  *   Box is free software: you can redistribute it and/or modify it         *
7  *   under the terms of the GNU Lesser General Public License as published  *
8  *   by the Free Software Foundation, either version 3 of the License, or   *
9  *   (at your option) any later version.                                    *
10  *                                                                          *
11  *   Box is distributed in the hope that it will be useful,                 *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
14  *   GNU Lesser General Public License for more details.                    *
15  *                                                                          *
16  *   You should have received a copy of the GNU Lesser General Public       *
17  *   License along with Box.  If not, see <http://www.gnu.org/licenses/>.   *
18  ****************************************************************************/
19 
20 /* Questo file contiene le dichiarazioni di strutture, macro e procedure
21  * grafiche non dipendenti dal modo in cui i dati relativi all'immagine
22  * vengono memorizzati(bit per pixel).
23  */
24 
25 #ifndef _BOX_LIBG_GRAPHIC_H
26 #  define _BOX_LIBG_GRAPHIC_H
27 
28 #  include "types.h"
29 #  include "gpath.h"
30 #  include "obj.h"
31 #  include "matrix.h"
32 #  include "winmap.h"
33 
34 /** Enumeration of possible errors occuring in the graphic library */
35 typedef enum {
36   BOXGERR_NO_ERR=0,
37   BOXGERR_UNEXPECTED,
38   BOXGERR_NO_MEMORY,
39   BOXGERR_MISS_WIN_TYPE,
40   BOXGERR_CAIRO_MISSES_PS,
41   BOXGERR_CAIRO_MISSES_PDF,
42   BOXGERR_CAIRO_MISSES_SVG,
43   BOXGERR_UNKNOWN_WIN_TYPE,
44   BOXGERR_WIN_SIZE_MISSING,
45   BOXGERR_WIN_RES_MISSING,
46   BOXGERR_WIN_FILENAME_MISSING,
47   BOXGERR_CAIRO_SURFACE_ERR,
48   BOXGERR_CAIRO_CONTEXT_ERR,
49   BOXGERR_CAIRO_PATTERN_ERR,
50   BOXGERR_CMD_BAD_ARGS,
51   BOXGERR_CMD_MISSING_ARGS,
52   BOXGERR_CMD_UNEXPECTED_ARGS,
53   BOXGERR_CMD_EXEC,
54   BOXGERR_CMD_BAD,
55   BOXGERR_CMD_EMPTY,
56   BOXGERR_CMD_BAD_INDEX
57 
58 } BoxGErr;
59 
60 /** Return a string corresponding to the given error code. */
61 const char *BoxGErr_To_Str(BoxGErr err);
62 
63 typedef enum {
64   FILLSTYLE_VOID=0,
65   FILLSTYLE_PLAIN,
66   FILLSTYLE_EO,
67   FILLSTYLE_CLIP,
68   FILLSTYLE_EOCLIP
69 } FillStyle;
70 
71 /* The color type */
72 typedef struct {
73   BoxReal r, g, b, a;
74 } Color;
75 
76 /* Definisce la struttura adatta a contenere il colore di un punto */
77 typedef struct {
78   unsigned char r;  /* Componente rossa */
79   unsigned char g;  /* Componente verde */
80   unsigned char b;  /* Componente blu */
81 } ColorBytes;
82 
83 #define color ColorBytes
84 
85 /* Questa e' la struttura di un elemento della palette */
86 struct palitem {
87   long index;    /* Numero del colore nella tavolazza */
88   ColorBytes c;    /* Colore */
89   struct palitem *next;  /* Puntatore al prossimo elemento */
90 };
91 
92 typedef struct palitem palitem;
93 
94 /* Questa e' la struttura di una palette (= tavolazza di colori) */
95 typedef struct {
96   long dim;  /* Dimensione della tavolazza (numero di colori inseribili) */
97   long num;  /* Numero dei colori attualmente inseriti */
98   long hashdim;  /* Dimensione della hash-table */
99   long hashmul;  /* Numero utilizzato dalla hash-function */
100   int reduce;    /* Livello di riduzione (approssimazione) dei colori */
101   palitem **hashtable;  /* Puntatore alla hash-table */
102 } palette;
103 
104 /** This structure is used to make uniform the functions for opening
105  * graphic windows of different types.
106  */
107 typedef struct {
108   struct {
109     int type : 1, origin : 1, size : 1,
110         resolution : 1, file_name : 1, num_layers: 1;
111   } have;
112   int type;
113   BoxPoint origin, size,
114            resolution; /** Resolution in points per mm */
115   char *file_name;
116   int num_layers;
117 } BoxGWinPlan;
118 
119 /** Font feature: slant */
120 typedef enum {
121   FONT_SLANT_NORMAL, FONT_SLANT_ITALIC, FONT_SLANT_OBLIQUE
122 } FontSlant;
123 
124 /** Font feature: weight */
125 typedef enum {
126   FONT_WEIGHT_NORMAL, FONT_WEIGHT_BOLD
127 } FontWeight;
128 
129 /** Alternatives for joining two segments of a line */
130 typedef enum {
131   JOIN_STYLE_MITER=0, JOIN_STYLE_ROUND, JOIN_STYLE_BEVEL
132 } JoinStyle;
133 
134 /** Alternatives for line endings. */
135 typedef enum {CAP_STYLE_BUTT=0, CAP_STYLE_ROUND, CAP_STYLE_SQUARE} CapStyle;
136 
137 /** All what is needed by the rdraw method */
138 typedef struct {
139   FillStyle fill_style;
140   BoxReal scale, bord_width, bord_miter_limit;
141   JoinStyle bord_join_style;
142   Color bord_color;
143   CapStyle bord_cap;
144   BoxInt bord_num_dashes;
145   BoxReal *bord_dashes, bord_dash_offset;
146 } DrawStyle;
147 
148 /** Enumeration of possible color gradient types */
149 typedef enum {
150   COLOR_GRAD_TYPE_LINEAR=0,
151   COLOR_GRAD_TYPE_RADIAL
152 } ColorGradType;
153 
154 /** Structure used to specify a color in the gradient vector (see ColorGrad)
155  */
156 typedef struct {
157   BoxReal position;
158   Color color;
159 } ColorGradItem;
160 
161 /** Decides what should be done outside the gradient area. */
162 typedef enum {
163   COLOR_GRAD_EXT_NONE=0,
164   COLOR_GRAD_EXT_REPEAT,
165   COLOR_GRAD_EXT_REFLECT,
166   COLOR_GRAD_EXT_PAD
167 } ColorGradExt;
168 
169 /** Structure containing the specification for linear or circular gradients.
170  * the gradient can be linear or circular. In the case of linear gradients
171  * P(t) is a point in the segment point1-point2 which goes linearly from
172  * point1 to point2, for t going from 0 to 1.
173  * The color is constant in each line passing through P(t) and changes as
174  * a function of t.
175  */
176 typedef struct {
177   ColorGradType type;
178   ColorGradExt extend;
179   BoxPoint point1, point2, ref1, ref2;
180   BoxReal radius1, radius2;
181   BoxInt num_items;
182   ColorGradItem *items;
183 } ColorGrad;
184 
185 /** Enumerate all the available method of a BoxGWin object. */
186 typedef enum {
187   BOXGWIN_METHOD_CREATE_PATH,
188   BOXGWIN_METHOD_BEGIN_DRAWING,
189   BOXGWIN_METHOD_DRAW_PATH,
190   BOXGWIN_METHOD_LINE_PATH,
191   BOXGWIN_METHOD_ADD_LINE_PATH,
192   BOXGWIN_METHOD_ADD_JOIN_PATH,
193   BOXGWIN_METHOD_ADD_CIRCLE_PATH,
194   BOXGWIN_METHOD_ADD_TEXT_PATH,
195   BOXGWIN_METHOD_ADD_FAKE_POINT,
196   BOXGWIN_METHOD_CLOSE_PATH,
197   BOXGWIN_METHOD_SET_FG_COLOR,
198   BOXGWIN_METHOD_SET_BG_COLOR,
199   BOXGWIN_METHOD_SET_GRADIENT,
200   BOXGWIN_METHOD_SET_FONT,
201   BOXGWIN_METHOD_SAVE_TO_FILE,
202   BOXGWIN_METHOD_INTERPRET,
203   BOXGWIN_METHOD_FINISH,
204   BOXGWIN_METHOD_SET_COLOR,
205   BOXGWIN_METHOD_DRAW_POINT,
206   BOXGWIN_METHOD_DRAW_HOR_LINE,
207   BOXGWIN_METHOD_UNBLOCK,
208   BOXGWIN_METHOD_NOTIFY_NOT_IMPLEMENTED
209 
210 } BoxGWinMethod;
211 
212 /** Return a string describing the method 'm'. */
213 const char *BoxGWinMethod_To_String(BoxGWinMethod m);
214 
215 /** Descriptor of a graphic Window */
216 typedef struct BoxGWin_struct BoxGWin;
217 
218 /* BoxGWin would need some cleaning. At the moment it contains stuff which
219  * is not relevant for all kinds of windows...
220  */
221 struct BoxGWin_struct {
222   /** String which identifies the type of the window */
223   char *win_type_str;
224 
225   /* High level functions */
226 
227   /** @see BoxGWin_Create_Path */
228   void (*create_path)(BoxGWin *w);
229 
230   /** @see BoxGWin_Begin_Drawing */
231   void (*begin_drawing)(BoxGWin *w);
232 
233   /** @see BoxGWin_Draw_Path */
234   void (*draw_path)(BoxGWin *w, DrawStyle *style);
235 
236   /** @see BoxGWin_Add_Line_Path */
237   void (*add_line_path)(BoxGWin *w, BoxPoint *a, BoxPoint *b);
238 
239   /** @see BoxGWin_Add_Join_Path */
240   void (*add_join_path)(BoxGWin *w, BoxPoint *a, BoxPoint *b, BoxPoint *c);
241 
242   /** @see BoxGWin_Close_Path */
243   void (*close_path)(BoxGWin *w);
244 
245   /** @see BoxGWin_Add_Circle_Path */
246   void (*add_circle_path)(BoxGWin *w,
247                           BoxPoint *ctr, BoxPoint *a, BoxPoint *b);
248 
249   /** @see BoxGWin_Set_Fg_Color */
250   void (*set_fg_color)(BoxGWin *w, Color *c);
251 
252   /** @see BoxGWin_Set_Bg_Color */
253   void (*set_bg_color)(BoxGWin *w, Color *c);
254 
255   /** @see BoxGWin_Set_Gradient */
256   void (*set_gradient)(BoxGWin *w, ColorGrad *cg);
257 
258   /** @see BoxGWin_Set_Font */
259   void (*set_font)(BoxGWin *w, const char *font_name);
260 
261   /** @see BoxGWin_Add_Text_Path */
262   void (*add_text_path)(BoxGWin *w,
263                         BoxPoint *ctr, BoxPoint *right, BoxPoint *up,
264                         BoxPoint *from, const char *text);
265 
266   /** @see BoxGWin_Add_Fake_Point */
267   void (*add_fake_point)(BoxGWin *w, BoxPoint *p);
268 
269   /** @see BoxGWin_Save_To_File */
270   int (*save_to_file)(BoxGWin *w, const char *file_name);
271 
272   /** @see BoxGWin_Interpret_Obj */
273   BoxTask (*interpret)(BoxGWin *w, BoxGObj *commands, BoxGWinMap *map);
274 
275   /** If set to 1, inhibits error messages */
276   int quiet;
277 
278   /* Low level functions (should probably be moved out of here) */
279 
280   /** terminates drawing operations on the window and make it unusable.
281    * @see BoxGWin_Finish, BoxGWin_Destroy
282    */
283   void (*finish)(BoxGWin *w);
284 
285   /** @see BoxGWin_Set_Color */
286   void (*set_color)(BoxGWin *w, int col);
287 
288   /** @see BoxGWin_Draw_Point */
289   void (*draw_point)(BoxGWin *w, BoxInt ptx, BoxInt pty);
290 
291   /** @see BoxGWin_Draw_Hor_Line */
292   void (*draw_hor_line)(BoxGWin *w, BoxInt y, BoxInt x1, BoxInt x2);
293 
294   /** Restore the window methods, which may have been changed after an error
295    * has occurred.
296    */
297   void (*repair)(BoxGWin *w);
298 
299   /** This function is used to notify that a given method has of the window
300    * has not been implemented.
301    */
302   BoxGWin *(*notify_not_implemented)(BoxGWin *w, BoxGWinMethod method);
303 
304   void *ptr;           /**< Pointer to the window data */
305   void *data;          /**< Pointer to extra data dependent on the window
306                             type */
307 
308   BoxReal
309     ltx, lty,          /**< Coordinates of top left-corner (in mm)*/
310     rdx, rdy,          /**< Coordinates of bottom right-corner (in mm) */
311     minx, miny,        /**< Minimum coordinates (in mm) */
312     maxx, maxy,        /**< Maximum coordinates (in mm) */
313     lx, ly,            /**< Width and height (in mm, positive) */
314     versox, versoy,    /**< Unit vectors x and y (either +1 or -1) */
315     stepx, stepy,      /**< Coordinate variations to move a pixel on the left
316                             and on the bottom */
317     resx, resy;        /**< x and y resolution (points per mm) */
318 
319   BoxInt numptx, numpty;  /**< Number of points in each direction */
320   palitem *bgcol;      /**< Background color */
321   palitem *fgcol;      /**< Current foreground color */
322   palette *pal;        /**< Color palette */
323   long bitperpixel;    /**< Bit necessary to store a single pixel */
324   long bytesperline;   /**< Bytes required for each row */
325   long dim;            /**< Total size (in bytes) of the window */
326 };
327 
328 #define BoxGWin_Fail(source, msg)
329 
330 /* Define some macros to provide functions which can be called as one would
331  * normally expect: Method_Of_Obj(obj, arg1, arg2, ...) rather than
332  * obj->method_name(obj, ...).
333  */
334 
335 /****************************************************************************
336  * HIGH LEVEL ROUTINES
337  */
338 
339 /** Initialize the window for drawing */
340 #define BoxGWin_Begin_Drawing(win) ((win)->begin_drawing)(win)
341 
342 /** Finalize the window */
343 void BoxGWin_Finish(BoxGWin *w);
344 
345 /** Create a new path (rreset) */
346 #define BoxGWin_Create_Path(win) ((win)->create_path)(win)
347 
348 /** Close the current path (rclose) */
349 #define BoxGWin_Close_Path(win) ((win)->close_path)(win)
350 
351 /** Draw the current path using the given drawing style. (rdraw) */
352 #define BoxGWin_Draw_Path(win, style) ((win)->draw_path)((win), (style))
353 
354 /** Generate the path for a line connecting the two points 'a' and 'b' */
355 #define BoxGWin_Add_Line_Path(win, a, b) \
356   ((win)->add_line_path)((win), (a), (b))
357 
358 /** Generate the join connecting point 'a' to 'c' with corner in 'b'. */
359 #define BoxGWin_Add_Join_Path(win, a, b, c) \
360   ((win)->add_join_path)((win), (a), (b), (c))
361 
362 /** Generate the path for a circle in the reference system identified by
363  * the origin 'ctr' and the unit axis points 'a' and 'b'.
364  */
365 #define BoxGWin_Add_Circle_Path(win, ctr, right, up) \
366   ((win)->add_circle_path)((win), (ctr), (right), (up))
367 
368 /** Set the foreground color. */
369 #define BoxGWin_Set_Fg_Color(win, c) \
370   ((win)->set_fg_color)((win), (c))
371 
372 /** Set the background color. */
373 #define BoxGWin_Set_Bg_Color(win, c) \
374   ((win)->set_bg_color)((win), (c))
375 
376 /** Set the gradient as a source for filling. */
377 #define BoxGWin_Set_Gradient(win, cg) \
378   ((win)->set_gradient)((win), (cg))
379 
380 /** Add a fake point to the window. Fake points only have an effect on the
381  * bounding box (can be used to make sure a point is visible in the figure).
382  */
383 #define BoxGWin_Add_Fake_Point(win, p) \
384   ((win)->add_fake_point)((win), (p))
385 
386 /** Interpret raw commands contained inside an Obj object. */
387 #define BoxGWin_Interpret_Obj(win, obj, map) \
388   ((win)->interpret)((win), (obj), (map))
389 
390 /** Set the current font from the font name provided in the string. */
391 #define BoxGWin_Set_Font(win, name) \
392   ((win)->set_font)((win), (name))
393 
394 /** Generate the path for the given text on the reference frame
395   * defined by the origin 'ctr' and the two axes ('ctr', 'right' and 'up'
396   * are the point at position (0, 0), (0, 1) and (1, 0), respectively in the
397   * reference frame. The text is printed in the direction (0, 0) -> (1, 0)
398   * with font size 1.0 (meaning that the three points 'ctr', 'right' and 'up'
399   * can be used to magnify the text and transform it in any way).
400   */
401 #define BoxGWin_Add_Text_Path(win, ctr, right, up, from, text) \
402   ((win)->add_text_path)((win), (ctr), (right), (up), (from), (text))
403 
404 /** Save the window to a file */
405 #define BoxGWin_Save_To_File(win, filename) \
406   ((win)->save_to_file)((win), (filename))
407 
408 /****************************************************************************
409  * LOW LEVEL ROUTINES
410  */
411 
412 /** Draw a point. */
413 #define BoxGWin_Draw_Point(win, x, y) \
414   ((win)->draw_point)((win), (x), (y))
415 
416 /** Draw an horizontal line. */
417 #define BoxGWin_Draw_Hor_Line(win, y, x1, x2) \
418   ((win)->draw_hor_line)((win), (y), (x1), (x2))
419 
420 /** Finalize the window */
421 #define BoxGWin_Set_Color(win, col_index) \
422   ((win)->set_color)((win), (col_index))
423 
424 /****************************************************************************/
425 
426 /* Per convertire in millimetri, radianti, punti per millimetro */
427 extern BoxReal grp_tomm;
428 extern BoxReal grp_torad;
429 extern BoxReal grp_toppmm;
430 
431 /* Window type (in BoxGWinPlan) */
432 typedef enum {WT_NONE=-1, WT_BM1=0, WT_BM4, WT_BM8, WT_FIG,
433               WT_PS, WT_EPS, WT_A1, WT_A8, WT_RGB24, WT_ARGB32,
434               WT_PDF, WT_SVG, WT_MAX} WT;
435 
436 /** Get the window ID (an integer number) from the window type (a string) */
437 int BoxGWin_Type_From_String(const char *type_str);
438 
439 /** Create a default BoxGWin object. A default BoxGWin window is converted
440  * automatically to a recording (Fig) windows when the window is first used.
441  */
442 BoxGWin *BoxGWin_Create_Default(void);
443 
444 /** Create an invalid BoxGWin object. All BoxGWin object should be constructed
445  * by extending an invalid BoxGWin object (and should thus call the function
446  * below in their constructors).
447  */
448 BoxGWin *BoxGWin_Create_Invalid(BoxGErr *err);
449 
450 /** Destroy a BoxGWin object created with BoxGWin_Create_Invalid. All BoxGWin
451  * destructors should be implemented by calling this function.
452  */
453 void BoxGWin_Destroy(BoxGWin *w);
454 
455 /** Unified function to open any kind of window */
456 BoxGWin *BoxGWin_Create(BoxGWinPlan *plan);
457 
458 /** Make sure the components of 'c' lie inside [0, 1] and correct them,
459  * if needed.
460  */
461 void Color_Trunc(Color *c);
462 
463 
464 /** Create a Window which displays the given error message, when someone
465  * tries to use it. The error message is fprinted to the give stream.
466  */
467 BoxGWin *BoxGWin_Create_Faulty(FILE *out, const char *msg);
468 
469 /* Dichiarazioni delle procedure della libreria */
470 /* Funzioni grafiche di alto livello */
471 BoxGWin *BoxGWin_Create_BM1(BoxReal ltx, BoxReal lty, BoxReal rdx, BoxReal rdy,
472                             BoxReal resx, BoxReal resy);
473 BoxGWin *BoxGWin_Create_BM4(BoxReal ltx, BoxReal lty, BoxReal rdx, BoxReal rdy,
474                             BoxReal resx, BoxReal resy);
475 BoxGWin *BoxGWin_Create_BM8(BoxReal ltx, BoxReal lty, BoxReal rdx, BoxReal rdy,
476                             BoxReal resx, BoxReal resy);
477 BoxTask BoxGWin_Init_Fig(BoxGWin *w, int numlayers);
478 BoxGWin *BoxGWin_Create_Fig(int numlayers);
479 BoxGWin *BoxGWin_Create_PS(const char *file);
480 BoxGWin *BoxGWin_Create_EPS(const char *file, BoxReal x, BoxReal y);
481 int ps_save_fig(const char *file_name, BoxGWin *figure);
482 int eps_save_fig(const char *file_name, BoxGWin *figure);
483 
484 /** Type of function called when BoxGWin_Block_With has been used. */
485 typedef BoxGWin *(*BoxGOnError)(BoxGWin *w, BoxGWinMethod method);
486 
487 /** Block the window 'w', such that it reports errors when used. */
488 void BoxGWin_Block(BoxGWin *w);
489 
490 /** Similar to BoxGWin_Block, but when the window 'w' is used,
491  * the function on_error is called, instead of reporting an error.
492  */
493 void BoxGWin_Block_With(BoxGWin *w, BoxGOnError on_error);
494 
495 /** Restore the window 'w', after it has been blocked with BoxGWin_Block
496  * or BoxGWin_Block_With
497  */
498 #define BoxGWin_Repair(w) \
499   do {(w)->repair(w)} while(0)
500 
501 /** Returns 1 if the window has been created with BoxGWin_Create_Faulty,
502  * 0 otherwise.
503  */
504 int BoxGWin_Is_Faulty(BoxGWin *w);
505 
506 /* Procedure per la gestione di una palette */
507 void grp_color_build(Color *cb, ColorBytes *c);
508 void grp_color_reduce(palette *p, ColorBytes *c);
509 palette *grp_palette_build(long numcol, long hashdim, long hashmul, int reduce);
510 palitem *grp_color_find(palette *p, ColorBytes *c);
511 palitem *grp_color_request(palette *p, ColorBytes *c);
512 int grp_palette_transform(palette *p, int (*operation)(palitem *pi));
513 void grp_palette_destroy(palette *p);
514 
515 /** Draw a path encoded inside a GPath object. */
516 void BoxGWin_Draw_GPath(BoxGWin *w, GPath *gp);
517 
518 void rst_repair(BoxGWin *gw);
519 
520 /* Costanti per la conversione */
521 #define grp_mmperinch  25.4
522 #define grp_radperdeg  0.01745329252
523 #define grp_radpergrad  0.01570796327
524 #define grp_ppmmperdpi  0.03937007874
525 #define grp_mm_per_inch 25.4
526 #define grp_inch_per_psunit (1.0/72.0)
527 
528 #endif
529