source: tags/testbuild/WINDOW/aw_device.hxx

Last change on this file was 11126, 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: 26.8 KB
Line 
1#ifndef AW_DEVICE_HXX
2#define AW_DEVICE_HXX
3
4#ifndef AW_POSITION_HXX
5#include <aw_position.hxx>
6#endif
7#ifndef ATTRIBUTES_H
8#include <attributes.h>
9#endif
10#ifndef ARBTOOLS_H
11#include <arbtools.h>
12#endif
13#ifndef _GLIBCXX_ALGORITHM
14#include <algorithm>
15#endif
16#ifndef _LIMITS_H
17#include <limits.h>
18#endif
19
20#if defined(DEBUG) && defined(DEBUG_GRAPHICS)
21// if you want flush() to be called after every motif command :
22#define AUTO_FLUSH(device) (device)->flush()
23#else
24#define AUTO_FLUSH(device)
25#endif
26
27#define AW_INT(x) ((int)(((x)>=0.0) ? ((float)(x)+.5) : ((float)(x)-.5)))
28
29// #define AW_PIXELS_PER_MM 1.0001 // stupid and wrong
30
31#define DPI_SCREEN  80   // fixed
32#define DPI_PRINTER 1200 // default resolution of xfig 3.2
33
34const AW_bitset AW_SCREEN        = 1;
35const AW_bitset AW_CLICK         = 2;
36const AW_bitset AW_CLICK_DROP    = 4;
37const AW_bitset AW_SIZE          = 8;
38const AW_bitset AW_SIZE_UNSCALED = 16;  // for text and text-size dependant parts
39const AW_bitset AW_PRINTER       = 32;  // print/xfig-export
40const AW_bitset AW_PRINTER_EXT   = 64;  // (+Handles) use combined with AW_PRINTER only
41const AW_bitset AW_PRINTER_CLIP  = 128; // print screen only
42
43const AW_bitset AW_ALL_DEVICES          = (AW_bitset)-1; // @@@ allowed to used this ?
44const AW_bitset AW_ALL_DEVICES_SCALED   = (AW_ALL_DEVICES & ~AW_SIZE_UNSCALED);
45const AW_bitset AW_ALL_DEVICES_UNSCALED = (AW_ALL_DEVICES & ~AW_SIZE);
46
47enum AW_DEVICE_TYPE {
48    AW_DEVICE_SCREEN  = AW_SCREEN,
49    AW_DEVICE_CLICK   = AW_CLICK,
50    AW_DEVICE_SIZE    = AW_SIZE,
51    AW_DEVICE_PRINTER = AW_PRINTER, 
52};
53
54enum {
55    AW_FIXED             = -1,
56    AW_TIMES             = 0,
57    AW_TIMES_ITALIC      = 1,
58    AW_TIMES_BOLD        = 2,
59    AW_TIMES_BOLD_ITALIC = 3,
60
61    AW_COURIER              = 12,
62    AW_COURIER_OBLIQUE      = 13,
63    AW_COURIER_BOLD         = 14,
64    AW_COURIER_BOLD_OBLIQUE = 15,
65
66    AW_HELVETICA                     = 16,
67    AW_HELVETICA_OBLIQUE             = 17,
68    AW_HELVETICA_BOLD                = 18,
69    AW_HELVETICA_BOLD_OBLIQUE        = 19,
70    AW_HELVETICA_NARROW              = 20,
71    AW_HELVETICA_NARROW_OBLIQUE      = 21,
72    AW_HELVETICA_NARROW_BOLD         = 22,
73    AW_HELVETICA_NARROW_BOLD_OBLIQUE = 23,
74
75    AW_LUCIDA_SANS                 = 35,
76    AW_LUCIDA_SANS_OBLIQUE         = 36,
77    AW_LUCIDA_SANS_BOLD            = 37,
78    AW_LUCIDA_SANS_BOLD_OBLIQUE    = 38,
79    AW_LUCIDA_SANS_TYPEWRITER      = 39,
80    AW_LUCIDA_SANS_TYPEWRITER_BOLD = 40,
81    AW_SCREEN_MEDIUM               = 41,
82    AW_SCREEN_BOLD                 = 42,
83    AW_CLEAN_MEDIUM                = 43,
84    AW_CLEAN_BOLD                  = 44,
85    AW_TERMINAL_MEDIUM             = 45,
86    AW_TERMINAL_BOLD               = 46,
87
88    AW_NUM_FONTS      = 63,
89    AW_NUM_FONTS_XFIG = 35, // immutable
90
91    AW_DEFAULT_NORMAL_FONT = AW_LUCIDA_SANS,
92    AW_DEFAULT_BOLD_FONT   = AW_LUCIDA_SANS_BOLD,
93    AW_DEFAULT_FIXED_FONT  = AW_LUCIDA_SANS_TYPEWRITER,
94};
95
96enum AW_cursor_type {
97    AW_cursor_insert,
98    AW_cursor_overwrite
99};
100
101// --------------------------------------------------
102// general note on world- vs. pixel-positions:(WORLD_vs_PIXEL)
103//
104// A position is interpreted as the center of the corresponding pixel
105// (pixel refers to screen; printer pixel are 15 times smaller!)
106//
107// Hence, when scaling factor is 1.0, then
108// - any position inside [-0.5, 0.5[ will fall into the pixel 0, any inside [0.5, 1.5[ into pixel 1.
109// - a line from 0.0 to 2.0 will paint THREE pixels (0, 1 and 2). A line from -0.5 to 2.499 will to the same
110// - clipping to area [0, 100] should in fact clip to [-0.5, 100.5[ (@@@ check this)
111
112class AW_zoomable {
113    AW::Vector offset;
114    AW_pos     scale;
115    AW_pos     unscale;         // = 1.0/scale
116
117public:
118    AW_zoomable() { this->reset(); };
119    virtual ~AW_zoomable() {}
120
121    void zoom(AW_pos scale);
122
123    AW_pos get_scale() const { return scale; };
124    AW_pos get_unscale() const { return unscale; };
125    AW::Vector get_offset() const { return offset; }
126
127    void rotate(AW_pos angle);
128
129    void set_offset(const AW::Vector& off) { offset = off*scale; }
130    void shift(const AW::Vector& doff) { offset += doff*scale; }
131
132    void reset();
133
134    double transform_size(const double& size) const { return size*scale; }
135    double rtransform_size(const double& size) const { return size*unscale; }
136
137    double rtransform_pixelsize(int pixelsize) const {
138        // return world-size needed to draw line/box with length/size == 'pixelsize'
139        return (pixelsize-1)*unscale;
140    }
141
142    // transforming a Vector only scales the vector (a Vector has no position!)
143    AW::Vector transform (const AW::Vector& vec) const { return vec*scale; }
144    AW::Vector rtransform(const AW::Vector& vec) const { return vec*unscale; }
145
146    // transform a Position
147    AW::Position transform (const AW::Position& pos) const { return transform(AW::Vector(pos+offset)).endpoint(); }
148    AW::Position rtransform(const AW::Position& pos) const { return rtransform(AW::Vector(pos)).endpoint()-offset; }
149#if defined(WARN_TODO) && 0
150#warning fix transformations
151    // @@@ I think this calculation is wrong, cause offset is already scaled
152    //     (same applies to old-style transform/rtransform below)
153#endif
154
155    AW::LineVector transform (const AW::LineVector& lvec) const { return AW::LineVector(transform(lvec.start()), transform(lvec.line_vector())); }
156    AW::LineVector rtransform(const AW::LineVector& lvec) const { return AW::LineVector(rtransform(lvec.start()), rtransform(lvec.line_vector())); }
157
158    AW::Rectangle transform (const AW::Rectangle& rect) const { return AW::Rectangle(transform(static_cast<const AW::LineVector&>(rect))); }
159    AW::Rectangle rtransform(const AW::Rectangle& rect) const { return AW::Rectangle(rtransform(static_cast<const AW::LineVector&>(rect))); }
160   
161    // old style functions, not preferred:
162    void transform(AW_pos x, AW_pos y, AW_pos& xout, AW_pos& yout) const {
163        xout = (x+offset.x())*scale;
164        yout = (y+offset.y())*scale;
165    }
166    void rtransform(AW_pos x, AW_pos y, AW_pos& xout, AW_pos& yout) const {
167        xout = x*unscale - offset.x();
168        yout = y*unscale - offset.y();
169    }
170};
171
172struct AW_font_overlap { bool top, bottom, left, right; };
173
174class AW_clipable {
175    const AW_screen_area& common_screen;
176    const AW_screen_area& get_screen() const { return common_screen; }
177
178    AW_screen_area  clip_rect;    // holds the clipping rectangle coordinates
179    AW_font_overlap font_overlap;
180
181    void set_cliprect_oversize(const AW_screen_area& rect, bool allow_oversize);
182protected:
183    int compoutcode(AW_pos xx, AW_pos yy) const {
184        // calculate outcode for clipping the current line
185        // order - top,bottom,right,left
186        int code = 0;
187        if (clip_rect.b - yy < 0)       code = 4;
188        else if (yy - clip_rect.t < 0)  code = 8;
189        if (clip_rect.r - xx < 0)       code |= 2;
190        else if (xx - clip_rect.l < 0)  code |= 1;
191        return (code);
192    };
193
194    void set_cliprect(const AW_screen_area& rect) { clip_rect = rect; }
195
196public:
197   
198    AW_clipable(const AW_screen_area& screen)
199        : common_screen(screen)
200    {
201        clip_rect.clear();
202        set_font_overlap(false);
203    }
204    virtual ~AW_clipable() {}
205
206    bool is_below_clip(double ypos) const { return ypos > clip_rect.b; }
207    bool is_above_clip(double ypos) const { return ypos < clip_rect.t; }
208    bool is_leftof_clip(double xpos) const { return xpos < clip_rect.l; }
209    bool is_rightof_clip(double xpos) const { return xpos > clip_rect.r; }
210
211    bool is_outside_clip(AW::Position pos) const {
212        return
213            is_below_clip(pos.ypos()) || is_above_clip(pos.ypos()) ||
214            is_leftof_clip(pos.xpos()) || is_rightof_clip(pos.xpos());
215    }
216    bool is_outside_clip(AW::Rectangle rect) const {
217        return !rect.overlaps_with(AW::Rectangle(get_cliprect(), AW::INCLUSIVE_OUTLINE));
218    }
219
220    bool clip(AW_pos x0, AW_pos y0, AW_pos x1, AW_pos y1, AW_pos& x0out, AW_pos& y0out, AW_pos& x1out, AW_pos& y1out);
221    bool clip(const AW::LineVector& line, AW::LineVector& clippedLine);
222
223    bool box_clip(AW_pos x0, AW_pos y0, AW_pos x1, AW_pos y1, AW_pos& x0out, AW_pos& y0out, AW_pos& x1out, AW_pos& y1out);
224    bool box_clip(const AW::Rectangle& rect, AW::Rectangle& clippedRect);
225    bool force_into_clipbox(const AW::Position& pos, AW::Position& forcedPos);
226
227    void set_top_clip_border(int top, bool allow_oversize = false);
228    void set_bottom_clip_border(int bottom, bool allow_oversize = false); // absolute
229    void set_bottom_clip_margin(int bottom, bool allow_oversize = false); // relative
230    void set_left_clip_border(int left, bool allow_oversize = false);
231    void set_right_clip_border(int right, bool allow_oversize = false);
232    const AW_screen_area& get_cliprect() const { return clip_rect; }
233
234    void set_clipall() {
235        // clip all -> nothing drawn afterwards
236        AW_screen_area rect = { 0, -1, 0, -1};
237        set_cliprect_oversize(rect, false);
238    }
239
240    bool completely_clipped() const { return clip_rect.l>clip_rect.r || clip_rect.t>clip_rect.b; }
241
242    bool allow_top_font_overlap() const { return font_overlap.top; }
243    bool allow_bottom_font_overlap() const { return font_overlap.bottom; }
244    bool allow_left_font_overlap() const { return font_overlap.left; }
245    bool allow_right_font_overlap() const { return font_overlap.right; }
246    const AW_font_overlap& get_font_overlap() const { return font_overlap; }
247   
248    void set_top_font_overlap(bool allow) { font_overlap.top = allow; }
249    void set_bottom_font_overlap(bool allow) { font_overlap.bottom = allow; }
250    void set_left_font_overlap(bool allow) { font_overlap.left = allow; }
251    void set_right_font_overlap(bool allow) { font_overlap.right = allow; }
252
253    void set_vertical_font_overlap(bool allow) { font_overlap.top = font_overlap.bottom = allow; }
254    void set_horizontal_font_overlap(bool allow) { font_overlap.left = font_overlap.right = allow; }
255    void set_font_overlap(bool allow) { set_vertical_font_overlap(allow); set_horizontal_font_overlap(allow); }
256    void set_font_overlap(const AW_font_overlap& fo) { font_overlap = fo; }
257
258    // like set_xxx_clip_border but make window only smaller:
259
260    void reduce_top_clip_border(int top);
261    void reduce_bottom_clip_border(int bottom);
262    void reduce_left_clip_border(int left);
263    void reduce_right_clip_border(int right);
264
265    int reduceClipBorders(int top, int bottom, int left, int right);
266};
267
268struct AW_font_limits {
269    short ascent;
270    short descent;
271    short height;
272    short width;
273    short min_width;
274
275    void reset() {
276        ascent    = descent = height = width = 0;
277        min_width = SHRT_MAX;
278    }
279
280    void notify_ascent(short a) { ascent = std::max(a, ascent); }
281    void notify_descent(short d) { descent = std::max(d, descent); }
282    void notify_width(short w) {
283        width     = std::max(w, width);
284        min_width = std::min(w, min_width);
285    }
286
287    void notify_all(short a_ascent, short a_descent, short a_width) {
288        notify_ascent (a_ascent);
289        notify_descent(a_descent);
290        notify_width  (a_width);
291    }
292
293    void calc_height() { height = ascent+descent+1; }
294
295    bool is_monospaced() const { return width == min_width; }
296
297    AW_font_limits() { reset(); }
298    AW_font_limits(const AW_font_limits& lim1, const AW_font_limits& lim2)
299        : ascent(std::max(lim1.ascent, lim2.ascent)),
300          descent(std::max(lim1.descent, lim2.descent)),
301          width(std::max(lim1.width, lim2.width)),
302          min_width(std::min(lim1.min_width, lim2.min_width))
303    {
304        calc_height();
305    }
306};
307
308// -----------------------------------------------
309//      Graphic context (linestyle, width ...)
310
311enum AW_linestyle {
312    AW_SOLID,
313    AW_DASHED,
314    AW_DOTTED, 
315};
316
317
318enum AW_function {
319    AW_COPY,
320    AW_XOR
321};
322
323class AW_common;
324
325class AW_stylable : virtual Noncopyable {
326    AW_common *common;
327public:
328    AW_stylable(AW_common *common_) : common(common_) {}
329    virtual ~AW_stylable() {};
330   
331    AW_common *get_common() const { return common; }
332
333    void new_gc(int gc);
334    void set_grey_level(int gc, AW_grey_level grey_level); 
335    void set_font(int gc, AW_font fontnr, int size, int *found_size);
336    void set_line_attributes(int gc, short width, AW_linestyle style);
337    void set_function(int gc, AW_function function);
338    void establish_default(int gc);
339    void set_foreground_color(int gc, AW_color_idx color); // lines ....
340    int  get_string_size(int gc, const  char *string, long textlen) const; // get the size of the string
341
342    const AW_font_limits& get_font_limits(int gc, char c) const; // for one characters (c == 0 -> for all characters)
343
344    int get_available_fontsizes(int gc, AW_font font_nr, int *available_sizes);
345   
346    void reset_style();
347};
348
349class  AW_clip_scale_stack;
350struct AW_world;
351class  AW_device;
352
353class AW_click_cd : virtual Noncopyable {
354    AW_CL              cd1;
355    AW_CL              cd2;
356    AW_device         *my_device;
357    const AW_click_cd *previous;
358
359    void link();
360
361public:
362    AW_click_cd(AW_device *device, AW_CL CD1, AW_CL CD2)
363        : cd1(CD1),
364          cd2(CD2),
365          my_device(device)
366    { link(); }
367    AW_click_cd(AW_device *device, AW_CL CD1)
368        : cd1(CD1),
369          cd2(0),
370          my_device(device)
371    { link(); }
372    ~AW_click_cd();
373
374    void disable();
375    void enable();
376
377    AW_CL get_cd1() const { return cd1; }
378    AW_CL get_cd2() const { return cd2; }
379
380    void set_cd1(AW_CL cd) { cd1 = cd; }
381    void set_cd2(AW_CL cd) { cd2 = cd; }
382};
383
384typedef bool (*TextOverlayCallback)(AW_device *device, int gc, const char *opt_string, size_t opt_string_len, size_t start, size_t size, AW_pos x, AW_pos y, AW_pos opt_ascent, AW_pos opt_descent, AW_CL cduser);
385
386class AW_device : public AW_zoomable, public AW_stylable, public AW_clipable {
387    AW_device(const AW_device& other);
388    AW_device& operator=(const AW_device& other);
389
390protected:
391    AW_clip_scale_stack *clip_scale_stack;
392
393    const AW_click_cd *click_cd;
394    friend class       AW_click_cd;
395
396    AW_bitset filter;
397
398    static const AW_screen_area& get_common_screen(const AW_common *common_);
399   
400public:
401    AW_device(class AW_common *common_)
402        : AW_stylable(common_),
403          AW_clipable(get_common_screen(common_)),
404          clip_scale_stack(NULL),
405          click_cd(NULL), 
406          filter(AW_ALL_DEVICES) 
407    {}
408    virtual ~AW_device() {}
409
410    const AW_click_cd *get_click_cd() const { return click_cd; }
411    AW_bitset get_filter() const { return filter; }
412
413    void reset(); // pops all clip_scales
414
415    const AW_screen_area& get_area_size() const;
416    AW::Rectangle get_rtransformed_cliprect() const { return rtransform(AW::Rectangle(get_cliprect(), AW::INCLUSIVE_OUTLINE)); }
417
418    void set_filter(AW_bitset filteri);   // set the main filter mask
419
420    void push_clip_scale();     // push clipping area and scale
421    void pop_clip_scale();     // pop them
422
423    virtual AW_DEVICE_TYPE type() = 0;
424
425    bool ready_to_draw(int gc); // unused atm
426
427private:
428    // * functions below return 1 if any pixel is drawn, 0 otherwise
429    // * primary functions (always virtual; pure virtual in all devices used as baseclass)
430
431    virtual bool line_impl(int gc, const AW::LineVector& Line, AW_bitset filteri)                                                  = 0;
432    virtual bool text_impl(int gc, const char *str, const AW::Position& pos, AW_pos alignment, AW_bitset filteri, long opt_strlen) = 0;
433    virtual bool box_impl(int gc, bool filled, const AW::Rectangle& rect, AW_bitset filteri)                                       = 0;
434    virtual bool filled_area_impl(int gc, int npos, const AW::Position *pos, AW_bitset filteri)                                    = 0;
435
436    virtual bool circle_impl(int gc, bool filled, const AW::Position& center, const AW::Vector& radius, AW_bitset filteri)                                  = 0;
437    virtual bool arc_impl(int gc, bool filled, const AW::Position& center, const AW::Vector& radius, int start_degrees, int arc_degrees, AW_bitset filteri) = 0;
438
439    virtual bool invisible_impl(const AW::Position& pos, AW_bitset filteri) = 0;
440
441    virtual void specific_reset() = 0;
442
443protected:
444
445    // * second level functions
446    // generic implementations which may be used by primary functions of derived classes
447   
448    bool generic_box(int gc, bool filled, const AW::Rectangle& rect, AW_bitset filteri);
449    bool generic_circle(int gc, bool filled, const AW::Position& center, const AW::Vector& radius, AW_bitset filteri) {
450        return generic_box(gc, filled, AW::Rectangle(center-radius, center+radius), filteri);
451    }
452    bool generic_arc(int gc, bool filled, const AW::Position& center, const AW::Vector& radius, int /*start_degrees*/, int /*arc_degrees*/, AW_bitset filteri) {
453        return generic_circle(gc, filled, center, radius, filteri);
454    }
455    bool generic_filled_area(int gc, int npos, const AW::Position *pos, AW_bitset filteri);
456    bool generic_invisible(const AW::Position& pos, AW_bitset filteri);
457
458public:
459    // * third level functions (never virtual/overloaded by derived classes)
460
461    bool line(int gc, const AW::LineVector& Line, AW_bitset filteri = AW_ALL_DEVICES_SCALED) {
462        return line_impl(gc, Line, filteri);
463    }
464    bool line(int gc, const AW::Position& pos1, const AW::Position& pos2, AW_bitset filteri = AW_ALL_DEVICES_SCALED) {
465        return line_impl(gc, AW::LineVector(pos1, pos2), filteri);
466    }
467    bool line(int gc, AW_pos x0, AW_pos y0, AW_pos x1, AW_pos y1, AW_bitset filteri = AW_ALL_DEVICES_SCALED) {
468        return line_impl(gc, AW::LineVector(x0, y0, x1, y1), filteri);
469    }
470
471    bool text(int         gc,
472              const char *string,
473              AW_pos      x,
474              AW_pos      y,
475              AW_pos      alignment  = 0.0, // 0.0 alignment left 0.5 centered 1.0 right justified
476              AW_bitset   filteri    = AW_ALL_DEVICES_UNSCALED,
477              long        opt_strlen = 0) {
478        return text_impl(gc, string, AW::Position(x, y), alignment, filteri, opt_strlen);
479    }
480    bool text(int                  gc,
481              const char          *string,
482              const AW::Position&  pos,
483              AW_pos               alignment  = 0.0, // 0.0 alignment left 0.5 centered 1.0 right justified
484              AW_bitset            filteri    = AW_ALL_DEVICES_UNSCALED,
485              long                 opt_strlen = 0) {
486        return text_impl(gc, string, pos, alignment, filteri, opt_strlen);
487    }
488
489    bool invisible(const AW::Position& pos, AW_bitset filteri = AW_ALL_DEVICES_SCALED) {
490        return invisible_impl(pos, filteri);
491    }
492
493    bool box(int gc, bool filled, const AW::Rectangle& rect, AW_bitset filteri = AW_ALL_DEVICES_SCALED) {
494        return box_impl(gc, filled, rect, filteri);
495    }
496    bool box(int gc, bool filled, const AW::Position& pos, const AW::Vector& size, AW_bitset filteri = AW_ALL_DEVICES_SCALED) {
497        return box_impl(gc, filled, AW::Rectangle(pos, size), filteri);
498    }
499    bool box(int gc, bool filled, AW_pos x0, AW_pos y0, AW_pos width, AW_pos height, AW_bitset filteri = AW_ALL_DEVICES_SCALED) {
500        return box_impl(gc, filled, AW::Rectangle(AW::Position(x0, y0), AW::Vector(width, height)), filteri);
501    }
502
503    bool circle(int gc, bool filled, const AW::Position& center, const AW::Vector& radius, AW_bitset filteri = AW_ALL_DEVICES_SCALED) {
504        return circle_impl(gc, filled, center, radius, filteri);
505    }
506    bool circle(int gc, bool filled, AW_pos x0, AW_pos y0, AW_pos xradius, AW_pos yradius, AW_bitset filteri = AW_ALL_DEVICES_SCALED)  {
507        return circle_impl(gc, filled, AW::Position(x0, y0), AW::Vector(xradius, yradius), filteri);
508    }
509    bool circle(int gc, bool filled, const AW::Rectangle& rect, AW_bitset filteri = AW_ALL_DEVICES_SCALED) {
510        // draw ellipse into Rectangle
511        return circle_impl(gc, filled, rect.centroid(), AW::Vector(rect.width()/2, rect.height()/2), filteri);
512    }
513
514    // draw arcs (Note: passed degrees are nagative compared to unit circle!)
515    bool arc(int gc, bool filled, AW_pos x0, AW_pos y0, AW_pos xradius, AW_pos yradius, int start_degrees, int arc_degrees, AW_bitset filteri = AW_ALL_DEVICES_SCALED)  {
516        return arc_impl(gc, filled, AW::Position(x0, y0), AW::Vector(xradius, yradius), start_degrees, arc_degrees, filteri);
517    }
518    bool arc(int gc, bool filled, const AW::Position& pos, const AW::Vector& radius, int start_degrees, int arc_degrees, AW_bitset filteri = AW_ALL_DEVICES_SCALED) {
519        return arc_impl(gc, filled, pos, radius, start_degrees, arc_degrees, filteri);
520    }
521
522    // @@@ rename to 'polygone' and pass 'filled' parameter
523    bool filled_area(int gc, int npoints, const AW_pos *points, AW_bitset filteri = AW_ALL_DEVICES_SCALED)  {
524        AW::Position *pos = new AW::Position[npoints];
525        for (int n = 0; n<npoints; ++n) {
526            pos[n].setx(points[n*2]);
527            pos[n].sety(points[n*2+1]);
528        }
529        bool result = filled_area_impl(gc, npoints, pos, filteri);
530        delete [] pos;
531        return result;
532    }
533    bool filled_area(int gc, int npos, const AW::Position *pos, AW_bitset filteri = AW_ALL_DEVICES_SCALED)  {
534        return filled_area_impl(gc, npos, pos, filteri);
535    }
536
537    // reduces any string (or virtual string) to its actual drawn size and calls the function f with the result
538    bool text_overlay(int gc, const char *opt_string, long opt_strlen,   // either string or strlen != 0
539                      const AW::Position& pos, AW_pos alignment, AW_bitset filteri, AW_CL cduser, 
540                      AW_pos opt_ascent, AW_pos opt_descent,  // optional height (if == 0 take font height)
541                      TextOverlayCallback toc);
542
543
544    // ********* X11 Device only ********
545    virtual void clear(AW_bitset filteri);
546    virtual void clear_part(const AW::Rectangle& rect, AW_bitset filteri);
547
548    void clear_part(AW_pos x, AW_pos y, AW_pos width, AW_pos height, AW_bitset filteri) {
549        clear_part(AW::Rectangle(AW::Position(x, y), AW::Vector(width, height)), filteri);
550    }
551
552    virtual void    move_region(AW_pos src_x, AW_pos src_y, AW_pos width, AW_pos height, AW_pos dest_x, AW_pos dest_y);
553    virtual void    fast();                                         // e.g. zoom linewidth off
554    virtual void    slow();
555    virtual void    flush();                                        // empty X11 buffers
556};
557
558
559inline void AW_click_cd::link() {
560    previous            = my_device->click_cd;
561    my_device->click_cd = this;
562}
563inline AW_click_cd::~AW_click_cd() { my_device->click_cd = previous; }
564inline void AW_click_cd::disable() { my_device->click_cd = NULL; }
565inline void AW_click_cd::enable() { my_device->click_cd = this; }
566
567class AW_device_print : public AW_device { // derived from a Noncopyable
568    FILE *out;
569    bool  color_mode;
570
571    bool line_impl(int gc, const AW::LineVector& Line, AW_bitset filteri);
572    bool text_impl(int gc, const char *str, const AW::Position& pos, AW_pos alignment, AW_bitset filteri, long opt_strlen);
573    bool box_impl(int gc, bool filled, const AW::Rectangle& rect, AW_bitset filteri);
574    bool circle_impl(int gc, bool filled, const AW::Position& center, const AW::Vector& radius, AW_bitset filteri);
575    bool arc_impl(int gc, bool filled, const AW::Position& center, const AW::Vector& radius, int start_degrees, int arc_degrees, AW_bitset filteri);
576    bool filled_area_impl(int gc, int npos, const AW::Position *pos, AW_bitset filteri);
577    bool invisible_impl(const AW::Position& pos, AW_bitset filteri);
578
579    void specific_reset() {}
580
581public:
582    AW_device_print(AW_common *common_)
583        : AW_device(common_),
584          out(0),
585          color_mode(false)
586    {}
587
588    GB_ERROR open(const char *path) __ATTR__USERESULT;
589    void close();
590
591    FILE *get_FILE() { return out; }
592
593    // AW_device interface:
594    AW_DEVICE_TYPE type();
595
596    int find_color_idx(AW_rgb color);
597    void set_color_mode(bool mode);
598
599};
600
601class AW_simple_device : public AW_device {
602    bool box_impl(int gc, bool /*filled*/, const AW::Rectangle& rect, AW_bitset filteri) {
603        return generic_box(gc, false, rect, filteri);
604    }
605    bool filled_area_impl(int gc, int npos, const AW::Position *pos, AW_bitset filteri) {
606        return generic_filled_area(gc, npos, pos, filteri);
607    }
608    bool circle_impl(int gc, bool filled, const AW::Position& center, const AW::Vector& radius, AW_bitset filteri) {
609        return generic_circle(gc, filled, center, radius, filteri);
610    }
611    bool arc_impl(int gc, bool filled, const AW::Position& center, const AW::Vector& radius, int start_degrees, int arc_degrees, AW_bitset filteri) {
612        return generic_arc(gc, filled, center, radius, start_degrees, arc_degrees, filteri);
613    }
614public:
615    AW_simple_device(AW_common *common_) : AW_device(common_) {}
616};
617
618class AW_size_tracker {
619    bool     drawn;
620    AW_world size;
621
622    void extend(AW_pos& low, AW_pos val, AW_pos& high) {
623        low = std::min(low, val);
624        high = std::max(high, val);
625    }
626public:
627    AW_size_tracker() { restart(); }
628
629    void restart() { drawn = false; size.clear(); }
630    void track(const AW::Position& pos) {
631        if (drawn) {
632            extend(size.l, pos.xpos(), size.r);
633            extend(size.t, pos.ypos(), size.b);
634        }
635        else {
636            size.l = size.r = pos.xpos();
637            size.t = size.b = pos.ypos();
638            drawn  = true;
639        }
640    }
641
642    bool was_drawn() const { return drawn; }
643    const AW_world& get_size() const { return size; }
644    AW::Rectangle get_size_as_Rectangle() const {
645        return AW::Rectangle(AW::Position(size.l, size.t), AW::Position(size.r, size.b));
646    }
647};
648
649class AW_device_size : public AW_simple_device {
650    AW_size_tracker scaled;   // all zoomable parts (e.g. tree skeleton)
651    AW_size_tracker unscaled; // all unzoomable parts (e.g. text at tree-tips or group-brackets)
652
653    void dot_transformed(const AW::Position& pos, AW_bitset filteri);
654    void dot_transformed(AW_pos X, AW_pos Y, AW_bitset filteri) { dot_transformed(AW::Position(X, Y), filteri); }
655
656    void dot(const AW::Position& p, AW_bitset filteri) { dot_transformed(transform(p), filteri); }
657    void dot(AW_pos x, AW_pos y, AW_bitset filteri) { dot(AW::Position(x, y), filteri); }
658
659    bool line_impl(int gc, const AW::LineVector& Line, AW_bitset filteri);
660    bool text_impl(int gc, const char *str, const AW::Position& pos, AW_pos alignment, AW_bitset filteri, long opt_strlen);
661    bool invisible_impl(const AW::Position& pos, AW_bitset filteri);
662
663    void specific_reset();
664   
665public:
666    AW_device_size(AW_common *common_) : AW_simple_device(common_) {}
667
668    void restart_tracking();
669
670    AW_DEVICE_TYPE type();
671
672    // all get_size_information...() return screen coordinates
673
674    void get_size_information(AW_world *ptr) const __ATTR__DEPRECATED_TODO("whole AW_world is deprecated") {
675        *ptr = scaled.get_size();
676    }
677    AW::Rectangle get_size_information() const { return scaled.get_size_as_Rectangle(); }
678    AW::Rectangle get_size_information_unscaled() const { return unscaled.get_size_as_Rectangle(); }
679    AW::Rectangle get_size_information_inclusive_text() const {
680        return get_size_information().bounding_box(get_size_information_unscaled());
681    }
682
683    AW_borders get_unscaleable_overlap() const;
684};
685
686#else
687#error aw_device.hxx included twice
688#endif
Note: See TracBrowser for help on using the repository browser.