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

Last change on this file was 11948, checked in by westram, 11 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.0 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    GB_ERROR error = device->open(xfig_name);
560
561    if (!error) {
562        Rectangle drawsize = get_drawsize(scr, draw_all);
563        Rectangle world_drawsize;
564
565        if (draw_all) {
566            Rectangle with_border = add_border_to_drawsize(drawsize, border);
567
568            double zoom = scr->trans_to_fit;
569            device->zoom(zoom); // same zoom as used by get_drawsize above
570
571            world_drawsize = device->rtransform(drawsize);
572
573            Vector ulc2origin = Origin-with_border.upper_left_corner();
574            Vector offset     = device->rtransform(ulc2origin)*device->get_unscale();
575
576            device->set_offset(offset);
577
578            device->set_bottom_clip_border((int)(with_border.height()+1), true);
579            device->set_right_clip_border((int)(with_border.width()+1), true);
580        }
581        else {
582            scr->init_device(device);
583            world_drawsize = device->rtransform(drawsize);
584        }
585
586        AW_bitset filter       = AW_PRINTER;
587        if (handles) filter   |= AW_PRINTER_EXT;
588        if (!draw_all) filter |= AW_PRINTER_CLIP;
589
590        device->set_filter(filter);
591        scr->gfx->show(device);
592
593        if (add_invisibles) {
594            Position ul = world_drawsize.upper_left_corner();
595            Position lr = world_drawsize.lower_right_corner();
596
597            // move invisible points towards center (in case they are clipped away)
598            Vector stepInside = device->rtransform(Vector(1, 1));
599            int maxloop = 10;
600
601            bool drawnUL = false;
602            bool drawnLR = false;
603
604            while (!(drawnLR && drawnUL) && maxloop-->0) {
605                if (!drawnUL) {
606                    drawnUL  = device->invisible(ul);
607                    ul      += stepInside;
608                }
609                if (!drawnLR) {
610                    drawnLR  = device->invisible(lr);
611                    lr      -= stepInside;
612                }
613            }
614            awt_assert(drawnLR && drawnUL);
615        }
616
617        device->close();
618    }
619    return error;
620}
621
622// --------------------------------------------------------------------------------
623
624static void canvas_to_xfig_and_run_xfig(AW_window *aww, AW_CL cl_canvas) {
625    AWT_canvas *scr  = (AWT_canvas*)cl_canvas;
626    AW_root    *awr  = aww->get_root();
627    char       *xfig = AW_get_selected_fullname(awr, AWAR_CANIO_FILE_BASE);
628   
629    GB_ERROR error = NULL;
630    if (xfig[0] == 0) {
631        error = "Please enter a file name";
632    }
633    else {
634        error = canvas_to_xfig(scr, xfig, true, 0.0);
635        if (!error) {
636            awr->awar(AWAR_CANIO_FILE_DIR)->touch(); // reload dir to show created xfig
637            error = GBK_system(GBS_global_string("xfig %s &", xfig));
638        }
639    }
640    if (error) aw_message(error);
641    free(xfig);
642}
643
644static void canvas_to_printer(AW_window *aww, AW_CL cl_canvas) {
645    AWT_canvas     *scr       = (AWT_canvas*)cl_canvas;
646    GB_transaction  ta(scr->gb_main);
647    AW_root        *awr       = aww->get_root();
648    GB_ERROR        error     = 0;
649    char           *dest      = 0;
650    PrintDest       printdest = (PrintDest)awr->awar(AWAR_CANIO_DEST)->read_int();
651
652    switch (printdest) {
653        case PDEST_POSTSCRIPT: {
654            dest = AW_get_selected_fullname(awr, AWAR_CANIO_FILE_BASE);
655            FILE *out = fopen(dest, "w");
656            if (!out) error = GB_export_IO_error("writing", dest);
657            else fclose(out);
658            break;
659        }
660        default: {
661            char *name = GB_unique_filename("arb_print", "ps");
662            dest       = GB_create_tempfile(name);
663            free(name);
664
665            if (!dest) error = GB_await_error();
666            break;
667        }
668    }
669
670    if (!error) {
671        char *xfig;
672        {
673            char *name = GB_unique_filename("arb_print", "xfig");
674            xfig       = GB_create_tempfile(name);
675            free(name);
676        }
677
678        arb_progress progress("Printing");
679        progress.subtitle("Exporting Data");
680
681        if (!xfig) error = GB_await_error();
682        if (!error) {
683            double border = awr->awar(AWAR_CANIO_BORDERSIZE)->read_float();
684            error         = canvas_to_xfig(scr, xfig, true, border);
685        }
686
687        if (!error) {
688            awt_assert(GB_is_privatefile(xfig, true));
689
690            // ----------------------------------------
691            progress.subtitle("Converting to Postscript");
692
693            {
694                bool   landscape     = awr->awar(AWAR_CANIO_LANDSCAPE)->read_int();
695                bool   useOverlap    = awr->awar(AWAR_CANIO_OVERLAP)->read_int();
696                double magnification = awr->awar(AWAR_CANIO_MAGNIFICATION)->read_int() * 0.01;
697                int    paper         = awr->awar(AWAR_CANIO_PAPER)->read_int();
698
699                const PaperFormat& format = knownPaperFormat[paper];
700
701                GBS_strstruct cmd(500);
702                cmd.cat("fig2dev");
703
704                cmd.cat(" -L ps"); // postscript output
705                if (useOverlap) {
706                    cmd.cat(" -M"); // generate multiple pages if needed
707                    cmd.cat(" -O"); // generate overlap (if printing to multiple pages)
708                }
709                cmd.nprintf(20, " -m %f", magnification);
710                cmd.cat(landscape ? " -l 0" : " -p 0");              // landscape or portrait
711                cmd.nprintf(30, " -z %s", format.get_fig2dev_val()); // paperformat
712
713                cmd.put(' '); cmd.cat(xfig); // input
714                cmd.put(' '); cmd.cat(dest); // output
715
716                error = GBK_system(cmd.get_data());
717            }
718
719            // if user saves to .ps -> no special file permissions are required
720            awt_assert(printdest == PDEST_POSTSCRIPT || GB_is_privatefile(dest, false));
721
722            if (!error) {
723                progress.subtitle("Printing");
724
725                switch (printdest) {
726                    case PDEST_PREVIEW: {
727                        GB_CSTR gs      = GB_getenvARB_GS();
728                        GB_CSTR command = GBS_global_string("(%s %s;rm -f %s) &", gs, dest, dest);
729                        error           = GBK_system(command);
730                        break;
731                    }
732                    case PDEST_POSTSCRIPT:
733                        break;
734
735                    case PDEST_PRINTER: {
736                        char *prt = awr->awar(AWAR_CANIO_PRINTER)->read_string();
737                        error     = GBK_system(GBS_global_string("%s %s", prt, dest));
738                        free(prt);
739                        GB_unlink_or_warn(dest, &error);
740                        break;
741                    }
742                }
743            }
744        }
745        if (xfig) {
746#if defined(DEBUG) && 0
747            // show intermediate xfig and unlink it
748            GBK_system(GBS_global_string("( xfig %s; rm %s) &", xfig, xfig));
749#else // !defined(DEBUG)
750            GB_unlink_or_warn(xfig, &error);
751#endif
752            free(xfig);
753        }
754    }
755
756    free(dest);
757
758    if (error) aw_message(error);
759}
760
761// --------------------------------------------------------------------------------
762
763void AWT_popup_tree_export_window(AW_window *parent_win, AW_CL cl_canvas, AW_CL) {
764    static AW_window_simple *aws = 0;
765
766    AW_root *awr = parent_win->get_root();
767    create_export_awars(awr);
768    resetFiletype(awr, "fig", "print.fig");
769
770    if (!aws) {
771        aws = new AW_window_simple;
772        aws->init(awr, "EXPORT_TREE_AS_XFIG", "EXPORT TREE TO XFIG");
773        aws->load_xfig("awt/export.fig");
774
775        aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
776        aws->create_button("CLOSE", "CLOSE", "C");
777
778        aws->at("help"); aws->callback(makeHelpCallback("tree2file.hlp"));
779        aws->create_button("HELP", "HELP", "H");
780
781        aws->label_length(15);
782
783        AW_create_standard_fileselection(aws, AWAR_CANIO_FILE_BASE);
784
785        aws->at("what");
786        aws->label("Clip at Screen");
787        aws->create_toggle_field(AWAR_CANIO_CLIP, 1);
788        aws->insert_toggle("#print/clipscreen.xpm", "S", 0);
789        aws->insert_toggle("#print/clipall.xpm", "A", 1);
790        aws->update_toggle_field();
791
792        aws->at("remove_root");
793        aws->label("Show Handles");
794        aws->create_toggle_field(AWAR_CANIO_HANDLES, 1);
795        aws->insert_toggle("#print/nohandles.xpm", "S", 0);
796        aws->insert_toggle("#print/handles.xpm", "A", 1);
797        aws->update_toggle_field();
798
799        aws->at("color");
800        aws->label("Export colors");
801        aws->create_toggle(AWAR_CANIO_COLOR);
802
803        aws->at("xfig"); aws->callback(canvas_to_xfig_and_run_xfig, cl_canvas);
804        aws->create_autosize_button("START_XFIG", "EXPORT to XFIG", "X");
805    }
806
807    aws->activate();
808}
809
810void AWT_popup_sec_export_window(AW_window *parent_win, AW_CL cl_canvas, AW_CL) {
811    static AW_window_simple *aws = 0;
812
813    AW_root *awr = parent_win->get_root();
814    create_export_awars(awr);
815    resetFiletype(awr, "fig", "print.fig");
816
817    if (!aws) {
818        aws = new AW_window_simple;
819        aws->init(awr, "EXPORT_TREE_AS_XFIG", "EXPORT STRUCTURE TO XFIG");
820        aws->load_xfig("awt/secExport.fig");
821
822        aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
823        aws->create_button("CLOSE", "CLOSE", "C");
824
825        aws->at("help"); aws->callback(makeHelpCallback("tree2file.hlp"));
826        aws->create_button("HELP", "HELP", "H");
827
828        aws->label_length(15);
829        AW_create_standard_fileselection(aws, AWAR_CANIO_FILE_BASE);
830
831        aws->at("what");
832        aws->label("Clip Options");
833        aws->create_option_menu(AWAR_CANIO_CLIP);
834        aws->insert_option("Export screen only", "s", 0);
835        aws->insert_default_option("Export complete structure", "c", 1);
836        aws->update_option_menu();
837
838        aws->at("color");
839        aws->label("Export colors");
840        aws->create_toggle(AWAR_CANIO_COLOR);
841
842        aws->at("xfig"); aws->callback(canvas_to_xfig_and_run_xfig, cl_canvas);
843        aws->create_autosize_button("START_XFIG", "EXPORT to XFIG", "X");
844    }
845
846    aws->activate();
847}
848
849static void columns_changed_cb(AW_window *aww) { set_mag_from_psize(aww->get_root(), true); }
850static void rows_changed_cb(AW_window *aww) { set_mag_from_psize(aww->get_root(), false); }
851
852static void fit_pages_cb(AW_window *aww, AW_CL cl_pages) {
853    AW_root *awr = aww->get_root();
854    int      wanted_pages;
855
856    if (cl_pages>0)
857        wanted_pages = cl_pages;
858    else {
859        wanted_pages = awr->awar(AWAR_CANIO_PAGES)->read_int();
860    }
861    fit_pages(awr, wanted_pages, true);
862}
863
864void AWT_popup_print_window(AW_window *parent_win, AW_CL cl_canvas, AW_CL) {
865    AW_root                 *awr = parent_win->get_root();
866    AWT_canvas              *scr = (AWT_canvas*)cl_canvas;
867    static AW_window_simple *aws = 0;
868
869    create_print_awars(awr, scr);
870    resetFiletype(awr, "ps", "print.ps");
871
872    if (!aws) {
873        aws = new AW_window_simple;
874        aws->init(awr, "PRINT_CANVAS", "PRINT GRAPHIC");
875        aws->load_xfig("awt/print.fig");
876
877        aws->at("close"); aws->callback((AW_CB0)AW_POPDOWN);
878        aws->create_button("CLOSE", "CLOSE", "C");
879
880        aws->at("help"); aws->callback(makeHelpCallback("tree2prt.hlp"));
881        aws->create_button("HELP", "HELP", "H");
882
883        // -----------------------------
884        //      select what to print
885
886        aws->label_length(15);
887
888        aws->at("what");
889        aws->label("Clip at Screen");
890        aws->create_toggle_field(AWAR_CANIO_CLIP, 1);
891        aws->insert_toggle("#print/clipscreen.xpm", "S", 0);
892        aws->insert_toggle("#print/clipall.xpm", "A", 1);
893        aws->update_toggle_field();
894
895        aws->at("remove_root");
896        aws->label("Show Handles");
897        aws->create_toggle_field(AWAR_CANIO_HANDLES, 1);
898        aws->insert_toggle("#print/nohandles.xpm", "S", 0);
899        aws->insert_toggle("#print/handles.xpm", "A", 1);
900        aws->update_toggle_field();
901
902        aws->at("color");
903        aws->label("Export colors");
904        aws->create_toggle(AWAR_CANIO_COLOR);
905
906        // --------------------
907        //      page layout
908
909        aws->at("getsize");
910        aws->callback((AW_CB1)awt_print_tree_check_size, (AW_CL)scr);
911        aws->create_autosize_button(0, "Get Graphic Size");
912
913        aws->button_length(6);
914        aws->at("gsizex"); aws->create_button(0, AWAR_CANIO_GFX_SX);
915        aws->at("gsizey"); aws->create_button(0, AWAR_CANIO_GFX_SY);
916        aws->at("osizex"); aws->create_button(0, AWAR_CANIO_OUT_SX);
917        aws->at("osizey"); aws->create_button(0, AWAR_CANIO_OUT_SY);
918
919        aws->at("magnification");
920        aws->create_input_field(AWAR_CANIO_MAGNIFICATION, 4);
921
922        aws->label_length(0);
923        aws->at("orientation");
924        aws->create_toggle_field(AWAR_CANIO_LANDSCAPE, 1);
925        aws->insert_toggle("#print/landscape.xpm", "L", 1);
926        aws->insert_toggle("#print/portrait.xpm",  "P", 0);
927        aws->update_toggle_field();
928
929        aws->at("bsize"); aws->create_input_field(AWAR_CANIO_BORDERSIZE, 4);
930
931        // -------------------
932        //      paper size
933
934        aws->at("psizex"); aws->create_input_field(AWAR_CANIO_PAPER_SX, 5);
935        aws->at("psizey"); aws->create_input_field(AWAR_CANIO_PAPER_SY, 5);
936
937        aws->at("paper");
938        aws->create_option_menu(AWAR_CANIO_PAPER);
939        aws->insert_default_option(knownPaperFormat[0].get_description(), "", 0);
940        for (int f = 1; f<int(ARRAY_ELEMS(knownPaperFormat)); ++f) {
941            const PaperFormat& format = knownPaperFormat[f];
942            aws->insert_option(format.get_description(), "", f);
943        }
944        aws->update_option_menu();
945
946        aws->at("usize"); aws->create_input_field(AWAR_CANIO_PAPER_USABLE, 4);
947
948
949        // -----------------------
950        //      multiple pages
951
952        aws->at("sizex");
953        aws->callback(columns_changed_cb);
954        aws->create_input_field(AWAR_CANIO_PAGE_SX, 4);
955        aws->at("sizey");
956        aws->callback(rows_changed_cb);
957        aws->create_input_field(AWAR_CANIO_PAGE_SY, 4);
958
959        aws->at("best_fit");
960        aws->callback(fit_pages_cb, 0);
961        aws->create_autosize_button("fit_on", "Fit on");
962
963        aws->at("pages");
964        aws->create_input_field(AWAR_CANIO_PAGES, 3);
965
966        aws->at("plock");
967        aws->create_toggle(AWAR_CANIO_PAGELOCK);
968       
969        aws->button_length(1);
970        {
971            char name[] = "p0";
972            for (int p = 1; p <= 9; ++p) {
973                name[1] = '0'+p; // at-label, macro-name and button-text
974                if (aws->at_ifdef(name)) {
975                    aws->at(name);
976                    aws->callback(fit_pages_cb, p);
977                    aws->create_button(name, name+1);
978                }
979            }
980        }
981
982        aws->at("overlap");
983        aws->create_toggle(AWAR_CANIO_OVERLAP);
984        aws->at("amount");
985        aws->create_input_field(AWAR_CANIO_OVERLAP_PERCENT, 4);
986
987        aws->at("f2dbug");
988        aws->create_toggle(AWAR_CANIO_F2DBUG);
989
990        // --------------------
991        //      destination
992
993        aws->at("printto");
994        aws->label_length(12);
995        aws->label("Destination");
996        aws->create_toggle_field(AWAR_CANIO_DEST);
997        aws->insert_toggle("Printer",           "P", PDEST_PRINTER);
998        aws->insert_toggle("File (Postscript)", "F", PDEST_POSTSCRIPT);
999        aws->insert_toggle("Preview",           "V", PDEST_PREVIEW);
1000        aws->update_toggle_field();
1001
1002        aws->at("printer");
1003        aws->create_input_field(AWAR_CANIO_PRINTER, 16);
1004
1005        aws->at("filename");
1006        aws->create_input_field(AWAR_CANIO_FILE_NAME, 16);
1007
1008        aws->at("go");
1009        aws->highlight();
1010        aws->callback(canvas_to_printer, (AW_CL)scr);
1011        aws->create_autosize_button("PRINT", "PRINT", "P");
1012    }
1013
1014    awt_print_tree_check_size(0, (AW_CL)scr);
1015    aws->activate();
1016}
Note: See TracBrowser for help on using the repository browser.