source: tags/ms_r16q3/AWT/AWT_canio.cxx

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