source: tags/arb-6.0/AWT/AWT_canio.cxx

Last change on this file was 12267, checked in by westram, 10 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.2 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : AWT_canio.cxx                                      //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Institute of Microbiology (Technical University Munich)        //
7//   http://www.arb-home.de/                                        //
8//                                                                  //
9// ================================================================ //
10
11#include "awt_canvas.hxx"
12
13#include <aw_file.hxx>
14#include <aw_awar.hxx>
15#include <aw_msg.hxx>
16#include <arb_progress.h>
17#include <aw_root.hxx>
18#include <arbdbt.h>
19#include <arb_defs.h>
20#include <arb_strbuf.h>
21#include <arb_file.h>
22
23using namespace AW;
24
25#define awt_assert(cond) arb_assert(cond)
26
27// --------------------------------------------------------------------------------
28
29#define AWAR_CANIO                 "NT/print/"
30#define AWAR_CANIO_LANDSCAPE       AWAR_CANIO "landscape"
31#define AWAR_CANIO_CLIP            AWAR_CANIO "clip"
32#define AWAR_CANIO_HANDLES         AWAR_CANIO "handles"
33#define AWAR_CANIO_COLOR           AWAR_CANIO "color"
34#define AWAR_CANIO_DEST            AWAR_CANIO "dest"
35#define AWAR_CANIO_PRINTER         AWAR_CANIO "printer"
36#define AWAR_CANIO_OVERLAP_WANTED  AWAR_CANIO "overlap"
37#define AWAR_CANIO_OVERLAP_PERCENT AWAR_CANIO "operc"
38#define AWAR_CANIO_BORDERSIZE      AWAR_CANIO "border"
39#define AWAR_CANIO_PAPER           AWAR_CANIO "paper"
40#define AWAR_CANIO_PAPER_USABLE    AWAR_CANIO "useable"
41#define AWAR_CANIO_F2DBUG          AWAR_CANIO "f2dbug"
42#define AWAR_CANIO_PAGES           AWAR_CANIO "pages"
43#define AWAR_CANIO_PAGELOCK        AWAR_CANIO "plock"
44
45#define AWAR_CANIO_TMP "tmp/" AWAR_CANIO
46
47#define AWAR_CANIO_MAGNIFICATION AWAR_CANIO_TMP "magnification"
48#define AWAR_CANIO_OVERLAP       AWAR_CANIO_TMP "overlap"
49#define AWAR_CANIO_GFX_SX        AWAR_CANIO_TMP "gsizex" // graphic size in inch
50#define AWAR_CANIO_GFX_SY        AWAR_CANIO_TMP "gsizey"
51#define AWAR_CANIO_OUT_SX        AWAR_CANIO_TMP "osizex" // output size in inch
52#define AWAR_CANIO_OUT_SY        AWAR_CANIO_TMP "osizey"
53#define AWAR_CANIO_PAPER_SX      AWAR_CANIO_TMP "psizex" // paper size in inch
54#define AWAR_CANIO_PAPER_SY      AWAR_CANIO_TMP "psizey"
55#define AWAR_CANIO_PAGE_SX       AWAR_CANIO_TMP "sizex"  // size in pages
56#define AWAR_CANIO_PAGE_SY       AWAR_CANIO_TMP "sizey"
57
58#define AWAR_CANIO_FILE_BASE   AWAR_CANIO_TMP "file"
59#define AWAR_CANIO_FILE_NAME   AWAR_CANIO_FILE_BASE "/file_name"
60#define AWAR_CANIO_FILE_DIR    AWAR_CANIO_FILE_BASE "/directory"
61#define AWAR_CANIO_FILE_FILTER AWAR_CANIO_FILE_BASE "/filter"
62
63// --------------------------------------------------------------------------------
64
65enum PrintDest {
66    PDEST_PRINTER    = 0,
67    PDEST_POSTSCRIPT = 1,
68    PDEST_PREVIEW    = 2,
69};
70
71// --------------------------------------------------------------------------------
72
73enum LengthUnit { INCH, MM };
74
75static const double mm_per_inch = 25.4;
76inline double inch2mm(double inches) { return inches*mm_per_inch; }
77inline double mm2inch(double mms) { return mms/mm_per_inch; }
78
79class PaperFormat {
80    const char *description;
81    const char *fig2dev_val;
82    LengthUnit  unit;
83    double      shortSide, longSide;
84
85public:
86    PaperFormat(const char *name, LengthUnit lu, double shortSide_, double longSide_)
87        : description(name),
88          fig2dev_val(name),
89          unit(lu),
90          shortSide(shortSide_),
91          longSide(longSide_)
92    {
93        awt_assert(shortSide<longSide);
94    }
95    PaperFormat(const char *aname, const char *fname, LengthUnit lu, double shortSide_, double longSide_)
96        : description(aname),
97          fig2dev_val(fname),
98          unit(lu),
99          shortSide(shortSide_),
100          longSide(longSide_)
101    {
102        awt_assert(shortSide<longSide);
103    }
104
105    double short_inch() const { return unit == INCH ? shortSide : mm2inch(shortSide); }
106    double long_inch() const { return unit == INCH ? longSide : mm2inch(longSide); }
107
108    const char *get_description() const { return description; }
109    const char *get_fig2dev_val() const { return fig2dev_val; }
110};
111
112// (c&p from fig2dev:)
113//  Available paper sizes are:
114//      "Letter" (8.5" x 11" also "A"),
115//      "Legal" (11" x 14")
116//      "Ledger" (11" x 17"),
117//      "Tabloid" (17" x 11", really Ledger in Landscape mode),
118//      "A" (8.5" x 11" also "Letter"),
119//      "B" (11" x 17" also "Ledger"),
120//      "C" (17" x 22"),
121//      "D" (22" x 34"),
122//      "E" (34" x 44"),
123//      "A4" (21  cm x  29.7cm),
124//      "A3" (29.7cm x  42  cm),
125//      "A2" (42  cm x  59.4cm),
126//      "A1" (59.4cm x  84.1cm),
127//      "A0" (84.1cm x 118.9cm),
128//      and "B5" (18.2cm x 25.7cm).
129
130static PaperFormat knownPaperFormat[] = {
131    PaperFormat("A4", MM, 210, 297), // first is the default
132    PaperFormat("A3", MM, 297, 420),
133    PaperFormat("A2", MM, 420, 594),
134    PaperFormat("A1", MM, 594, 841),
135    PaperFormat("A0", MM, 841, 1189),
136    PaperFormat("B5", MM, 182, 257),
137   
138    PaperFormat("A (Letter)", "A", INCH, 8.5, 11),
139    PaperFormat("Legal",           INCH, 11, 14),
140    PaperFormat("B (Ledger)", "B", INCH, 11, 17),
141    PaperFormat("C",          "C", INCH, 17, 22),
142    PaperFormat("D",          "D", INCH, 22, 34),
143    PaperFormat("E",          "E", INCH, 34, 44),
144};
145
146// --------------------------------------------------------------------------------
147
148static Rectangle get_drawsize(AWT_canvas *scr, bool draw_all) {
149    // returns size of drawn graphic in screen-coordinates
150   
151    Rectangle       drawsize;
152    GB_transaction  ta(scr->gb_main);
153    AW_device_size *size_device = scr->aww->get_size_device(AW_MIDDLE_AREA);
154
155    if (draw_all) {
156        size_device->reset();
157        size_device->zoom(scr->trans_to_fit);
158        size_device->set_filter(AW_PRINTER|AW_PRINTER_EXT);
159        scr->gfx->show(size_device);
160        drawsize = size_device->get_size_information();
161    }
162    else {
163        drawsize = Rectangle(size_device->get_area_size(), INCLUSIVE_OUTLINE);
164    }
165
166    return drawsize;
167}
168
169static Rectangle add_border_to_drawsize(const Rectangle& drawsize, double border_percent) {
170    double borderratio     = border_percent*.01;
171    double draw2bordersize = -borderratio/(borderratio-1.0);
172    Vector bordersize      = drawsize.diagonal() * (draw2bordersize*0.5);
173
174    return Rectangle(drawsize.upper_left_corner()-bordersize,
175                     drawsize.lower_right_corner()+bordersize);
176}
177
178static void awt_print_tree_check_size(void *, AW_CL cl_canvas) {
179    AWT_canvas *scr         = (AWT_canvas*)cl_canvas;
180    AW_root    *awr         = scr->awr;
181    long        draw_all    = awr->awar(AWAR_CANIO_CLIP)->read_int();
182    double      border      = awr->awar(AWAR_CANIO_BORDERSIZE)->read_float();
183    Rectangle   drawsize    = get_drawsize(scr, draw_all);
184    Rectangle   with_border = add_border_to_drawsize(drawsize, border);
185
186    awr->awar(AWAR_CANIO_GFX_SX)->write_float((with_border.width())/DPI_SCREEN);
187    awr->awar(AWAR_CANIO_GFX_SY)->write_float((with_border.height())/DPI_SCREEN);
188}
189
190inline int xy2pages(double sx, double sy) {
191    return (int(sx+0.99)*int(sy+0.99));
192}
193
194static bool allow_page_size_check_cb = true;
195static bool allow_overlap_toggled_cb = true;
196
197inline void set_paper_size_xy(AW_root *awr, double px, double py) {
198    // modify papersize but perform only one callback
199
200    bool old_allow           = allow_page_size_check_cb;
201    allow_page_size_check_cb = false;
202    awr->awar(AWAR_CANIO_PAPER_SX)->write_float(px);
203    allow_page_size_check_cb = old_allow;
204    awr->awar(AWAR_CANIO_PAPER_SY)->write_float(py);
205}
206
207static void overlap_toggled_cb(AW_root *awr) {
208    if (allow_overlap_toggled_cb) {
209        int new_val = awr->awar(AWAR_CANIO_OVERLAP)->read_int();
210        awr->awar(AWAR_CANIO_OVERLAP_WANTED)->write_int(new_val);
211    }
212}
213
214static long calc_mag_from_psize(AW_root *awr, double papersize, double gfxsize, double wantedpages, bool use_x) {
215    bool   wantOverlap = awr->awar(AWAR_CANIO_OVERLAP_WANTED)->read_int();
216    double usableSize = 0;
217
218    if (wantOverlap && wantedpages>1) {
219        double overlapPercent = awr->awar(AWAR_CANIO_OVERLAP_PERCENT)->read_float();
220        double usableRatio    = (100.0-overlapPercent)/100.0;
221
222        // See also fig2devbug in page_size_check_cb()
223        bool fig2devbug = !use_x && awr->awar(AWAR_CANIO_F2DBUG)->read_int();
224        if (fig2devbug) {
225            bool landscape = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
226            fig2devbug     = fig2devbug && !landscape; // only occurs in portrait mode
227        }
228
229        if (fig2devbug) {
230            usableSize = wantedpages*papersize*usableRatio;
231        }
232        else {
233            usableSize = (papersize*usableRatio)*(wantedpages-1)+papersize;
234        }
235    }
236    else {
237        usableSize = wantedpages*papersize;
238    }
239
240    return usableSize*100/gfxsize; // always "round" to floor
241}
242
243static void set_mag_from_psize(AW_root *awr, bool use_x) {
244    const char *papersize_name   = use_x ? AWAR_CANIO_PAPER_SX : AWAR_CANIO_PAPER_SY;
245    const char *gfxsize_name     = use_x ? AWAR_CANIO_GFX_SX : AWAR_CANIO_GFX_SY;
246    const char *wantedpages_name = use_x ? AWAR_CANIO_PAGE_SX : AWAR_CANIO_PAGE_SY;
247
248    double   papersize   = awr->awar(papersize_name)->read_float();
249    double   gfxsize     = awr->awar(gfxsize_name)->read_float();
250    double   wantedpages = awr->awar(wantedpages_name)->read_float();
251    long     mag         = calc_mag_from_psize(awr, papersize, gfxsize, wantedpages, use_x);
252
253    awr->awar(AWAR_CANIO_MAGNIFICATION)->write_int(mag);
254}
255
256static void fit_pages(AW_root *awr, int wanted_pages, bool allow_orientation_change) {
257    int         best_orientation    = -1;
258    const char *best_zoom_awar_name = 0;
259    float       best_zoom           = 0;
260    int         best_magnification  = 0;
261    int         best_pages          = 0;
262
263    bool lockpages = awr->awar(AWAR_CANIO_PAGELOCK)->read_int();
264    awr->awar(AWAR_CANIO_PAGELOCK)->write_int(0);
265
266    if (!allow_orientation_change) {
267        best_orientation = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
268    }
269
270    for (int o = 0; o <= 1; ++o) {
271        if (!allow_orientation_change && o != best_orientation) continue;
272
273        awr->awar(AWAR_CANIO_LANDSCAPE)->write_int(o); // set orientation (calls page_size_check_cb)
274
275        for (int xy = 0; xy <= 1; ++xy) {
276            const char *awar_name = xy == 0 ? AWAR_CANIO_PAGE_SX : AWAR_CANIO_PAGE_SY;
277
278            for (int pcount = 1; pcount <= wanted_pages; pcount++) {
279                double zoom = pcount*1.0;
280                awr->awar(awar_name)->write_float(zoom); // set zoom (x or y)
281
282                set_mag_from_psize(awr, xy == 0);
283
284                double sx            = awr->awar(AWAR_CANIO_PAGE_SX)->read_float();
285                double sy            = awr->awar(AWAR_CANIO_PAGE_SY)->read_float();
286                int    pages         = xy2pages(sx, sy);
287
288                if (pages>wanted_pages) break; // pcount-loop
289
290                if (pages <= wanted_pages && pages >= best_pages) {
291                    int magnification = awr->awar(AWAR_CANIO_MAGNIFICATION)->read_int();    // read calculated magnification
292                    if (magnification>best_magnification) {
293                        // fits on wanted_pages and is best result yet
294                        best_magnification  = magnification;
295                        best_orientation    = o;
296                        best_zoom_awar_name = awar_name;
297                        best_zoom           = zoom;
298                        best_pages          = pages;
299                    }
300                }
301            }
302        }
303    }
304
305    if (best_zoom_awar_name) {
306        // take the best found values :
307        awr->awar(AWAR_CANIO_LANDSCAPE)->write_int(best_orientation);
308        awr->awar(best_zoom_awar_name)->write_float(best_zoom);
309        awr->awar(AWAR_CANIO_PAGES)->write_int(best_pages);
310        awr->awar(AWAR_CANIO_MAGNIFICATION)->write_int(best_magnification); 
311
312        if (best_pages != wanted_pages) {
313            aw_message(GBS_global_string("That didn't fit on %i page(s) - using %i page(s)",
314                                         wanted_pages, best_pages));
315        }
316    }
317    else {
318        aw_message(GBS_global_string("That didn't fit on %i page(s) - impossible settings", wanted_pages));
319    }
320   
321    awr->awar(AWAR_CANIO_PAGELOCK)->write_int(lockpages);
322}
323
324static void page_size_check_cb(AW_root *awr) {
325    if (!allow_page_size_check_cb) return;
326
327    bool landscape    = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
328    bool lockpages    = awr->awar(AWAR_CANIO_PAGELOCK)->read_int();
329    int  locked_pages = awr->awar(AWAR_CANIO_PAGES)->read_int();
330
331    double px = awr->awar(AWAR_CANIO_PAPER_SX)->read_float(); // paper-size
332    double py = awr->awar(AWAR_CANIO_PAPER_SY)->read_float();
333
334    if (landscape != (px>py)) {
335        set_paper_size_xy(awr, py, px); // recalls this function
336        return;
337    }
338
339    long magnification = awr->awar(AWAR_CANIO_MAGNIFICATION)->read_int();
340   
341    double gx = awr->awar(AWAR_CANIO_GFX_SX)->read_float(); // graphic size
342    double gy = awr->awar(AWAR_CANIO_GFX_SY)->read_float();
343
344    // output size
345    double ox = (gx*magnification)/100; // resulting size of output in inches
346    double oy = (gy*magnification)/100;
347    awr->awar(AWAR_CANIO_OUT_SX)->write_float(ox);
348    awr->awar(AWAR_CANIO_OUT_SY)->write_float(oy);
349
350    bool wantOverlap = awr->awar(AWAR_CANIO_OVERLAP_WANTED)->read_int();
351    bool useOverlap  = awr->awar(AWAR_CANIO_OVERLAP)->read_int();
352
353    double sx = 0.0; // resulting pages
354    double sy = 0.0;
355
356    bool fits_on_one_page = (ox <= px && oy <= py);
357
358    if (wantOverlap && !fits_on_one_page) {
359        double overlapPercent = awr->awar(AWAR_CANIO_OVERLAP_PERCENT)->read_float();
360        double pageRatio      = (100.0-overlapPercent)/100.0;
361
362        double rpx = px*pageRatio; // usable page-size (due to overlap)
363        double rpy = py*pageRatio;
364
365        while (ox>px) { ox -= rpx; sx += 1.0; }
366        sx += ox/px;
367
368        bool fig2devbug = !landscape;
369        if (fig2devbug) fig2devbug = awr->awar(AWAR_CANIO_F2DBUG)->read_int();
370
371        if (fig2devbug) {
372            // fig2dev has a bug with printing multiple portrait pages with overlap:
373            // Regardless of whether there is a needed overlapping in y-direction
374            // it prints a empty border at top of all top-row-pages and then clips
375            // the fig in the bottom-row (even if there is only one row).
376            // See also fig2devbug in calc_mag_from_psize()
377            sy += oy/rpy;
378        }
379        else {
380            while (oy>py) { oy -= rpy; sy += 1.0; }
381            sy += oy/py;
382        }
383    }
384    else {
385        sx = ox/px;
386        sy = oy/py;
387    }
388
389    // write amount of pages needed
390    awr->awar(AWAR_CANIO_PAGE_SX)->write_float(sx);
391    awr->awar(AWAR_CANIO_PAGE_SY)->write_float(sy);
392
393    int pages = xy2pages(sx, sy);
394    if (lockpages) {
395        fit_pages(awr, locked_pages, false); // Note: recurses with !lockpages
396        return;
397    }
398
399    awr->awar(AWAR_CANIO_PAGES)->write_int(pages);
400
401    // correct DISPLAYED overlapping..
402    bool willUseOverlap = wantOverlap && (pages != 1);
403    if (willUseOverlap != useOverlap) {
404        bool old_allow           = allow_overlap_toggled_cb;
405        allow_overlap_toggled_cb = false; // ..but do not modify wanted overlapping
406
407        awr->awar(AWAR_CANIO_OVERLAP)->write_int(willUseOverlap);
408
409        allow_overlap_toggled_cb = old_allow;
410    }
411}
412
413inline double round_psize(double psize) { return AW_INT(psize*10)/10.0; }
414
415static void paper_changed_cb(AW_root *awr) {
416    int                paper     = awr->awar(AWAR_CANIO_PAPER)->read_int();
417    const PaperFormat& format    = knownPaperFormat[paper];
418    bool               landscape = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
419    double             useable   = awr->awar(AWAR_CANIO_PAPER_USABLE)->read_float()/100.0;
420
421    if (landscape) {
422        set_paper_size_xy(awr, useable*format.long_inch(), useable*format.short_inch());
423    }
424    else {
425        set_paper_size_xy(awr, useable*format.short_inch(), useable*format.long_inch());
426    }
427}
428
429// --------------------------------------------------------------------------------
430
431static bool export_awars_created = false;
432static bool print_awars_created = false;
433
434static void create_export_awars(AW_root *awr) {
435    if (!export_awars_created) {
436        AW_default def = AW_ROOT_DEFAULT;
437
438        awr->awar_int(AWAR_CANIO_CLIP, 0, def);
439        awr->awar_int(AWAR_CANIO_HANDLES, 1, def);
440        awr->awar_int(AWAR_CANIO_COLOR, 1, def);
441
442        awr->awar_string(AWAR_CANIO_FILE_NAME, "print.fig", def);
443        awr->awar_string(AWAR_CANIO_FILE_DIR, "", def);
444        awr->awar_string(AWAR_CANIO_FILE_FILTER, "fig", def);
445
446        awr->awar_int(AWAR_CANIO_LANDSCAPE, 0, def);
447        awr->awar_int(AWAR_CANIO_MAGNIFICATION, 100, def);
448
449        // constraints:
450
451        awr->awar(AWAR_CANIO_MAGNIFICATION)->set_minmax(1, 10000);
452
453        export_awars_created = true;
454    }
455}
456
457static void resetFiletype(AW_root *awr, const char *filter, const char *defaultFilename) {
458    AW_awar *awar_filter    = awr->awar(AWAR_CANIO_FILE_FILTER);
459    char    *current_filter = awar_filter->read_string();
460
461    if (strcmp(current_filter, filter) != 0) {
462        awar_filter->write_string(filter);
463        awr->awar(AWAR_CANIO_FILE_NAME)->write_string(defaultFilename);
464    }
465    free(current_filter);
466}
467
468static void create_print_awars(AW_root *awr, AWT_canvas *scr) {
469    create_export_awars(awr);
470
471    if (!print_awars_created) {
472        AW_default def = AW_ROOT_DEFAULT;
473
474        awr->awar_int(AWAR_CANIO_PAGES, 1, def);
475        awr->awar_int(AWAR_CANIO_PAGELOCK, 1, def);
476
477        awr->awar_int(AWAR_CANIO_OVERLAP_WANTED, 1, def);
478        awr->awar_int(AWAR_CANIO_OVERLAP, 1, def)->add_callback(overlap_toggled_cb);
479        awr->awar_float(AWAR_CANIO_OVERLAP_PERCENT, 13.0, def); // determined
480
481        awr->awar_int(AWAR_CANIO_F2DBUG, 1, def); // bug still exists in most recent version (3.2 5d from July 23, 2010)
482
483        awr->awar_float(AWAR_CANIO_BORDERSIZE, 0.0, def);
484
485        awr->awar_float(AWAR_CANIO_GFX_SX);
486        awr->awar_float(AWAR_CANIO_GFX_SY);
487
488        awr->awar_float(AWAR_CANIO_OUT_SX);
489        awr->awar_float(AWAR_CANIO_OUT_SY);
490
491        awr->awar_float(AWAR_CANIO_PAPER_SX);
492        awr->awar_float(AWAR_CANIO_PAPER_SY);
493
494        awr->awar_int(AWAR_CANIO_PAPER, 0)->add_callback(paper_changed_cb); // sets first format (A4)
495        awr->awar_float(AWAR_CANIO_PAPER_USABLE, 95)->add_callback(paper_changed_cb); // 95% of paper are usable
496
497        awr->awar_float(AWAR_CANIO_PAGE_SX);
498        awr->awar_float(AWAR_CANIO_PAGE_SY);
499
500        awr->awar_int(AWAR_CANIO_DEST);
501
502        {
503            char *print_command;
504            if (getenv("PRINTER")) {
505                print_command = GBS_eval_env("lpr -h -P$(PRINTER)");
506            } else   print_command = strdup("lpr -h");
507
508            awr->awar_string(AWAR_CANIO_PRINTER, print_command, def);
509            free(print_command);
510        }
511
512        // constraints and automatics:
513
514        awr->awar(AWAR_CANIO_PAPER_SX)->set_minmax(0.1, 100);
515        awr->awar(AWAR_CANIO_PAPER_SY)->set_minmax(0.1, 100);
516
517        awt_print_tree_check_size(0, (AW_CL)scr);
518
519        awr->awar(AWAR_CANIO_CLIP)->add_callback((AW_RCB1)awt_print_tree_check_size, (AW_CL)scr);
520        awr->awar(AWAR_CANIO_BORDERSIZE)->add_callback((AW_RCB1)awt_print_tree_check_size, (AW_CL)scr);
521
522        { // add callbacks for page recalculation
523            const char *checked_awars[] = {
524                AWAR_CANIO_MAGNIFICATION,
525                AWAR_CANIO_LANDSCAPE,
526                AWAR_CANIO_BORDERSIZE,
527                AWAR_CANIO_OVERLAP_WANTED, AWAR_CANIO_OVERLAP_PERCENT,
528                AWAR_CANIO_F2DBUG, 
529                AWAR_CANIO_PAPER_SX,         AWAR_CANIO_PAPER_SY,
530                AWAR_CANIO_GFX_SX,         AWAR_CANIO_GFX_SY,
531                0
532            };
533            for (int ca = 0; checked_awars[ca]; ca++) {
534                awr->awar(checked_awars[ca])->add_callback(page_size_check_cb);
535            }
536        }
537
538        paper_changed_cb(awr); // also calls page_size_check_cb
539        print_awars_created = true;
540    }
541}
542
543// --------------------------------------------------------------------------------
544
545static GB_ERROR canvas_to_xfig(AWT_canvas *scr, const char *xfig_name, bool add_invisibles, double border) {
546    // if 'add_invisibles' is true => print 2 invisible dots to make fig2dev center correctly
547
548    GB_transaction  ta(scr->gb_main);
549    AW_root        *awr = scr->awr;
550
551    bool draw_all  = awr->awar(AWAR_CANIO_CLIP)->read_int();
552    bool handles   = awr->awar(AWAR_CANIO_HANDLES)->read_int();
553    bool use_color = awr->awar(AWAR_CANIO_COLOR)->read_int();
554
555    AW_device_print *device = scr->aww->get_print_device(AW_MIDDLE_AREA);
556
557    device->reset();
558    device->set_color_mode(use_color);
559#ifdef ARB_GTK
560    GB_ERROR error = NULL;
561#else
562    GB_ERROR error = device->open(xfig_name);
563#endif
564
565    if (!error) {
566        Rectangle drawsize = get_drawsize(scr, draw_all);
567        Rectangle world_drawsize;
568
569        if (draw_all) {
570            Rectangle with_border = add_border_to_drawsize(drawsize, border);
571
572            double zoom = scr->trans_to_fit;
573            device->zoom(zoom); // same zoom as used by get_drawsize above
574
575            world_drawsize = device->rtransform(drawsize);
576
577            Vector ulc2origin = Origin-with_border.upper_left_corner();
578            Vector offset     = device->rtransform(ulc2origin)*device->get_unscale();
579
580            device->set_offset(offset);
581
582            device->set_bottom_clip_border((int)(with_border.height()+1), true);
583            device->set_right_clip_border((int)(with_border.width()+1), true);
584        }
585        else {
586            scr->init_device(device);
587            world_drawsize = device->rtransform(drawsize);
588        }
589
590        AW_bitset filter       = AW_PRINTER;
591        if (handles) filter   |= AW_PRINTER_EXT;
592        if (!draw_all) filter |= AW_PRINTER_CLIP;
593
594        device->set_filter(filter);
595#ifdef ARB_GTK
596        error = device->open(xfig_name);
597        if (error) return error;
598#endif     
599        scr->gfx->show(device);
600
601        if (add_invisibles) {
602            Position ul = world_drawsize.upper_left_corner();
603            Position lr = world_drawsize.lower_right_corner();
604
605            // move invisible points towards center (in case they are clipped away)
606            Vector stepInside = device->rtransform(Vector(1, 1));
607            int maxloop = 10;
608
609            bool drawnUL = false;
610            bool drawnLR = false;
611
612            while (!(drawnLR && drawnUL) && maxloop-->0) {
613                if (!drawnUL) {
614                    drawnUL  = device->invisible(ul);
615                    ul      += stepInside;
616                }
617                if (!drawnLR) {
618                    drawnLR  = device->invisible(lr);
619                    lr      -= stepInside;
620                }
621            }
622            awt_assert(drawnLR && drawnUL);
623        }
624
625        device->close();
626    }
627    return error;
628}
629
630// --------------------------------------------------------------------------------
631
632static void canvas_to_xfig_and_run_xfig(AW_window *aww, AWT_canvas *scr) {
633    AW_root *awr  = aww->get_root();
634    char    *xfig = AW_get_selected_fullname(awr, AWAR_CANIO_FILE_BASE);
635
636    GB_ERROR error = NULL;
637    if (xfig[0] == 0) {
638        error = "Please enter a file name";
639    }
640    else {
641        error = canvas_to_xfig(scr, xfig, true, 0.0);
642        if (!error) {
643            awr->awar(AWAR_CANIO_FILE_DIR)->touch(); // reload dir to show created xfig
644#if defined(ARB_GTK)
645            error = GBK_system(GBS_global_string("evince %s &", xfig));
646#else
647            error = GBK_system(GBS_global_string("xfig %s &", xfig));
648#endif
649        }
650    }
651    if (error) aw_message(error);
652    free(xfig);
653}
654
655static void canvas_to_printer(AW_window *aww, AW_CL cl_canvas) {
656    AWT_canvas     *scr       = (AWT_canvas*)cl_canvas;
657    GB_transaction  ta(scr->gb_main);
658    AW_root        *awr       = aww->get_root();
659    GB_ERROR        error     = 0;
660    char           *dest      = 0;
661    PrintDest       printdest = (PrintDest)awr->awar(AWAR_CANIO_DEST)->read_int();
662
663    switch (printdest) {
664        case PDEST_POSTSCRIPT: {
665            dest = AW_get_selected_fullname(awr, AWAR_CANIO_FILE_BASE);
666            FILE *out = fopen(dest, "w");
667            if (!out) error = GB_export_IO_error("writing", dest);
668            else fclose(out);
669            break;
670        }
671        default: {
672            char *name = GB_unique_filename("arb_print", "ps");
673            dest       = GB_create_tempfile(name);
674            free(name);
675
676            if (!dest) error = GB_await_error();
677            break;
678        }
679    }
680
681    if (!error) {
682        char *xfig;
683        {
684            char *name = GB_unique_filename("arb_print", "xfig");
685            xfig       = GB_create_tempfile(name);
686            free(name);
687        }
688
689        arb_progress progress("Printing");
690        progress.subtitle("Exporting Data");
691
692        if (!xfig) error = GB_await_error();
693        if (!error) {
694            double border = awr->awar(AWAR_CANIO_BORDERSIZE)->read_float();
695            error         = canvas_to_xfig(scr, xfig, true, border);
696        }
697
698        if (!error) {
699            awt_assert(GB_is_privatefile(xfig, true));
700
701            // ----------------------------------------
702            progress.subtitle("Converting to Postscript");
703
704            {
705                bool   landscape     = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
706                bool   useOverlap    = awr->awar(AWAR_CANIO_OVERLAP)->read_int();
707                double magnification = awr->awar(AWAR_CANIO_MAGNIFICATION)->read_int() * 0.01;
708                int    paper         = awr->awar(AWAR_CANIO_PAPER)->read_int();
709
710                const PaperFormat& format = knownPaperFormat[paper];
711
712                GBS_strstruct cmd(500);
713                cmd.cat("fig2dev");
714
715                cmd.cat(" -L ps"); // postscript output
716                if (useOverlap) {
717                    cmd.cat(" -M"); // generate multiple pages if needed
718                    cmd.cat(" -O"); // generate overlap (if printing to multiple pages)
719                }
720                cmd.nprintf(20, " -m %f", magnification);
721                cmd.cat(landscape ? " -l 0" : " -p 0");              // landscape or portrait
722                cmd.nprintf(30, " -z %s", format.get_fig2dev_val()); // paperformat
723
724                cmd.put(' '); cmd.cat(xfig); // input
725                cmd.put(' '); cmd.cat(dest); // output
726
727                error = GBK_system(cmd.get_data());
728            }
729
730            // if user saves to .ps -> no special file permissions are required
731            awt_assert(printdest == PDEST_POSTSCRIPT || GB_is_privatefile(dest, false));
732
733            if (!error) {
734                progress.subtitle("Printing");
735
736                switch (printdest) {
737                    case PDEST_PREVIEW: {
738                        GB_CSTR gs      = GB_getenvARB_GS();
739                        GB_CSTR command = GBS_global_string("(%s %s;rm -f %s) &", gs, dest, dest);
740                        error           = GBK_system(command);
741                        break;
742                    }
743                    case PDEST_POSTSCRIPT:
744                        break;
745
746                    case PDEST_PRINTER: {
747                        char *prt = awr->awar(AWAR_CANIO_PRINTER)->read_string();
748                        error     = GBK_system(GBS_global_string("%s %s", prt, dest));
749                        free(prt);
750                        GB_unlink_or_warn(dest, &error);
751                        break;
752                    }
753                }
754            }
755        }
756        if (xfig) {
757#if defined(DEBUG) && 0
758            // show intermediate xfig and unlink it
759            GBK_system(GBS_global_string("( xfig %s; rm %s) &", xfig, xfig));
760#else // !defined(DEBUG)
761            GB_unlink_or_warn(xfig, &error);
762#endif
763            free(xfig);
764        }
765    }
766
767    free(dest);
768
769    if (error) aw_message(error);
770}
771
772// --------------------------------------------------------------------------------
773
774void AWT_popup_tree_export_window(AW_window *parent_win, AWT_canvas *scr) {
775    static AW_window_simple *aws = 0;
776
777    AW_root *awr = parent_win->get_root();
778    create_export_awars(awr);
779#if defined(ARB_GTK)
780    resetFiletype(awr, "pdf", "print.pdf");
781#else
782    resetFiletype(awr, "fig", "print.fig");
783#endif
784
785    if (!aws) {
786        aws = new AW_window_simple;
787        aws->init(awr, "EXPORT_TREE_AS_XFIG", "EXPORT TREE TO XFIG");
788        aws->load_xfig("awt/export.fig");
789
790        aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
791        aws->create_button("CLOSE", "CLOSE", "C");
792
793        aws->at("help"); aws->callback(makeHelpCallback("tree2file.hlp"));
794        aws->create_button("HELP", "HELP", "H");
795
796        aws->label_length(15);
797
798        AW_create_standard_fileselection(aws, AWAR_CANIO_FILE_BASE);
799
800        aws->at("what");
801        aws->label("Clip at Screen");
802        aws->create_toggle_field(AWAR_CANIO_CLIP, 1);
803        aws->insert_toggle("#print/clipscreen.xpm", "S", 0);
804        aws->insert_toggle("#print/clipall.xpm", "A", 1);
805        aws->update_toggle_field();
806
807        aws->at("remove_root");
808        aws->label("Show Handles");
809        aws->create_toggle_field(AWAR_CANIO_HANDLES, 1);
810        aws->insert_toggle("#print/nohandles.xpm", "S", 0);
811        aws->insert_toggle("#print/handles.xpm", "A", 1);
812        aws->update_toggle_field();
813
814        aws->at("color");
815        aws->label("Export colors");
816        aws->create_toggle(AWAR_CANIO_COLOR);
817
818        aws->at("xfig"); aws->callback(makeWindowCallback(canvas_to_xfig_and_run_xfig, scr));
819        aws->create_autosize_button("START_XFIG", "EXPORT to XFIG", "X");
820    }
821
822    aws->activate();
823}
824
825void AWT_popup_sec_export_window(AW_window *parent_win, AWT_canvas *scr) {
826    static AW_window_simple *aws = 0;
827
828    AW_root *awr = parent_win->get_root();
829    create_export_awars(awr);
830    resetFiletype(awr, "fig", "print.fig");
831
832    if (!aws) {
833        aws = new AW_window_simple;
834        aws->init(awr, "EXPORT_TREE_AS_XFIG", "EXPORT STRUCTURE TO XFIG");
835        aws->load_xfig("awt/secExport.fig");
836
837        aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
838        aws->create_button("CLOSE", "CLOSE", "C");
839
840        aws->at("help"); aws->callback(makeHelpCallback("tree2file.hlp"));
841        aws->create_button("HELP", "HELP", "H");
842
843        aws->label_length(15);
844        AW_create_standard_fileselection(aws, AWAR_CANIO_FILE_BASE);
845
846        aws->at("what");
847        aws->label("Clip Options");
848        aws->create_option_menu(AWAR_CANIO_CLIP, true);
849        aws->insert_option("Export screen only", "s", 0);
850        aws->insert_default_option("Export complete structure", "c", 1);
851        aws->update_option_menu();
852
853        aws->at("color");
854        aws->label("Export colors");
855        aws->create_toggle(AWAR_CANIO_COLOR);
856
857        aws->at("xfig"); aws->callback(makeWindowCallback(canvas_to_xfig_and_run_xfig, scr));
858        aws->create_autosize_button("START_XFIG", "EXPORT to XFIG", "X");
859    }
860
861    aws->activate();
862}
863
864static void columns_changed_cb(AW_window *aww) { set_mag_from_psize(aww->get_root(), true); }
865static void rows_changed_cb(AW_window *aww) { set_mag_from_psize(aww->get_root(), false); }
866
867static void fit_pages_cb(AW_window *aww, AW_CL cl_pages) {
868    AW_root *awr = aww->get_root();
869    int      wanted_pages;
870
871    if (cl_pages>0)
872        wanted_pages = cl_pages;
873    else {
874        wanted_pages = awr->awar(AWAR_CANIO_PAGES)->read_int();
875    }
876    fit_pages(awr, wanted_pages, true);
877}
878
879void AWT_popup_print_window(AW_window *parent_win, AWT_canvas *scr) {
880    AW_root                 *awr = parent_win->get_root();
881    static AW_window_simple *aws = 0;
882
883    create_print_awars(awr, scr);
884    resetFiletype(awr, "ps", "print.ps");
885
886    if (!aws) {
887        aws = new AW_window_simple;
888        aws->init(awr, "PRINT_CANVAS", "PRINT GRAPHIC");
889        aws->load_xfig("awt/print.fig");
890
891        aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
892        aws->create_button("CLOSE", "CLOSE", "C");
893
894        aws->at("help"); aws->callback(makeHelpCallback("tree2prt.hlp"));
895        aws->create_button("HELP", "HELP", "H");
896
897        // -----------------------------
898        //      select what to print
899
900        aws->label_length(15);
901
902        aws->at("what");
903        aws->label("Clip at Screen");
904        aws->create_toggle_field(AWAR_CANIO_CLIP, 1);
905        aws->insert_toggle("#print/clipscreen.xpm", "S", 0);
906        aws->insert_toggle("#print/clipall.xpm", "A", 1);
907        aws->update_toggle_field();
908
909        aws->at("remove_root");
910        aws->label("Show Handles");
911        aws->create_toggle_field(AWAR_CANIO_HANDLES, 1);
912        aws->insert_toggle("#print/nohandles.xpm", "S", 0);
913        aws->insert_toggle("#print/handles.xpm", "A", 1);
914        aws->update_toggle_field();
915
916        aws->at("color");
917        aws->label("Export colors");
918        aws->create_toggle(AWAR_CANIO_COLOR);
919
920        // --------------------
921        //      page layout
922
923        aws->at("getsize");
924        aws->callback((AW_CB1)awt_print_tree_check_size, (AW_CL)scr);
925        aws->create_autosize_button(0, "Get Graphic Size");
926
927        aws->button_length(6);
928        aws->at("gsizex"); aws->create_button(0, AWAR_CANIO_GFX_SX);
929        aws->at("gsizey"); aws->create_button(0, AWAR_CANIO_GFX_SY);
930        aws->at("osizex"); aws->create_button(0, AWAR_CANIO_OUT_SX);
931        aws->at("osizey"); aws->create_button(0, AWAR_CANIO_OUT_SY);
932
933        aws->at("magnification");
934        aws->create_input_field(AWAR_CANIO_MAGNIFICATION, 4);
935
936        aws->label_length(0);
937        aws->at("orientation");
938        aws->create_toggle_field(AWAR_CANIO_LANDSCAPE, 1);
939        aws->insert_toggle("#print/landscape.xpm", "L", 1);
940        aws->insert_toggle("#print/portrait.xpm",  "P", 0);
941        aws->update_toggle_field();
942
943        aws->at("bsize"); aws->create_input_field(AWAR_CANIO_BORDERSIZE, 4);
944
945        // -------------------
946        //      paper size
947
948        aws->at("psizex"); aws->create_input_field(AWAR_CANIO_PAPER_SX, 5);
949        aws->at("psizey"); aws->create_input_field(AWAR_CANIO_PAPER_SY, 5);
950
951        aws->at("paper");
952        aws->create_option_menu(AWAR_CANIO_PAPER, true);
953        aws->insert_default_option(knownPaperFormat[0].get_description(), "", 0);
954        for (int f = 1; f<int(ARRAY_ELEMS(knownPaperFormat)); ++f) {
955            const PaperFormat& format = knownPaperFormat[f];
956            aws->insert_option(format.get_description(), "", f);
957        }
958        aws->update_option_menu();
959
960        aws->at("usize"); aws->create_input_field(AWAR_CANIO_PAPER_USABLE, 4);
961
962
963        // -----------------------
964        //      multiple pages
965
966        aws->at("sizex");
967        aws->callback(columns_changed_cb);
968        aws->create_input_field(AWAR_CANIO_PAGE_SX, 4);
969        aws->at("sizey");
970        aws->callback(rows_changed_cb);
971        aws->create_input_field(AWAR_CANIO_PAGE_SY, 4);
972
973        aws->at("best_fit");
974        aws->callback(fit_pages_cb, 0);
975        aws->create_autosize_button("fit_on", "Fit on");
976
977        aws->at("pages");
978        aws->create_input_field(AWAR_CANIO_PAGES, 3);
979
980        aws->at("plock");
981        aws->create_toggle(AWAR_CANIO_PAGELOCK);
982       
983        aws->button_length(1);
984        {
985            char name[] = "p0";
986            for (int p = 1; p <= 9; ++p) {
987                name[1] = '0'+p; // at-label, macro-name and button-text
988                if (aws->at_ifdef(name)) {
989                    aws->at(name);
990                    aws->callback(fit_pages_cb, p);
991                    aws->create_button(name, name+1);
992                }
993            }
994        }
995
996        aws->at("overlap");
997        aws->create_toggle(AWAR_CANIO_OVERLAP);
998        aws->at("amount");
999        aws->create_input_field(AWAR_CANIO_OVERLAP_PERCENT, 4);
1000
1001        aws->at("f2dbug");
1002        aws->create_toggle(AWAR_CANIO_F2DBUG);
1003
1004        // --------------------
1005        //      destination
1006
1007        aws->at("printto");
1008        aws->label_length(12);
1009        aws->label("Destination");
1010        aws->create_toggle_field(AWAR_CANIO_DEST);
1011        aws->insert_toggle("Printer",           "P", PDEST_PRINTER);
1012        aws->insert_toggle("File (Postscript)", "F", PDEST_POSTSCRIPT);
1013        aws->insert_toggle("Preview",           "V", PDEST_PREVIEW);
1014        aws->update_toggle_field();
1015
1016        aws->at("printer");
1017        aws->create_input_field(AWAR_CANIO_PRINTER, 16);
1018
1019        aws->at("filename");
1020        aws->create_input_field(AWAR_CANIO_FILE_NAME, 16);
1021
1022        aws->at("go");
1023        aws->highlight();
1024        aws->callback(canvas_to_printer, (AW_CL)scr);
1025        aws->create_autosize_button("PRINT", "PRINT", "P");
1026    }
1027
1028    awt_print_tree_check_size(0, (AW_CL)scr);
1029    aws->activate();
1030}
Note: See TracBrowser for help on using the repository browser.