source: branches/stable/WINDOW/AW_Xm.cxx

Last change on this file was 18665, checked in by westram, 3 years ago
  • change many WARN_TODO triggered warnings into todo markers.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.3 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : AW_Xm.cxx                                         //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include <aw_Xm.hxx>
12
13// @@@ change implementation of draw functions
14// * filter has to be checked early (in AW_device)
15// * functions shall use Position/LineVector/Rectangle only
16
17using namespace AW;
18
19// ---------------------
20//      AW_device_Xm
21
22AW_DEVICE_TYPE AW_device_Xm::type() { return AW_DEVICE_SCREEN; }
23
24#define XDRAW_PARAM2(common)    (common)->get_display(), (common)->get_window_id()
25#define XDRAW_PARAM3(common,gc) XDRAW_PARAM2(common), (common)->get_GC(gc)
26
27bool AW_device_Xm::line_impl(int gc, const LineVector& Line, AW_bitset filteri) {
28    bool drawflag = false;
29    if (filteri & filter) {
30        LineVector transLine = transform(Line);
31        LineVector clippedLine;
32        drawflag = clip(transLine, clippedLine);
33        if (drawflag) {
34            XDrawLine(XDRAW_PARAM3(get_common(), gc),
35                      AW_INT(clippedLine.start().xpos()), AW_INT(clippedLine.start().ypos()),
36                      AW_INT(clippedLine.head().xpos()), AW_INT(clippedLine.head().ypos()));
37            AUTO_FLUSH(this);
38        }
39    }
40
41    return drawflag;
42}
43
44static bool AW_draw_string_on_screen(AW_device *device, int gc, const char *textBuffer, size_t textStart, size_t textLen, const AW::Position& pos, AW_CL /*cduser*/) {
45    // aw_assert(textLen <= strlen(textBuffer)); // already asserted by caller (text_overlay)
46
47    AW_device_Xm *device_xm = DOWNCAST(AW_device_Xm*, device);
48    AW::Position  POS(device_xm->transform(pos));
49
50    XDrawString(XDRAW_PARAM3(device_xm->get_common(), gc), AW_INT(POS.xpos()), AW_INT(POS.ypos()), textBuffer + textStart,  (int)textLen);
51    AUTO_FLUSH(device);
52
53    return true;
54}
55
56
57bool AW_device_Xm::text_impl(int gc, const SizedCstr& cstr, const AW::Position& pos, AW_pos alignment, AW_bitset filteri) {
58    return text_overlay(gc, cstr, pos, alignment, filteri, AW_draw_string_on_screen);
59}
60
61enum StippleType {
62    ST_UNDEFINED = -1,
63    FILLED_125   = 0,
64    FILLED_25,
65    FILLED_375,
66    FILLED_50,
67    FILLED_625,
68    FILLED_75,
69    FILLED_875,
70};
71
72const int PIXMAP_SIZE   = 8; // 8x8 stipple mask
73const int STIPPLE_TYPES = FILLED_875+1;
74
75static Pixmap getStipplePixmap(AW_common_Xm *common, StippleType stippleType) {
76    aw_assert(stippleType>=0 && stippleType<STIPPLE_TYPES);
77
78    static Pixmap pixmap[STIPPLE_TYPES];
79    static bool   initialized = false;
80
81    if (!initialized) {
82        for (int t = 0; t<STIPPLE_TYPES; ++t) {
83            static unsigned char stippleBits[STIPPLE_TYPES][PIXMAP_SIZE] = {
84                { 0x40, 0x08, 0x01, 0x20, 0x04, 0x80, 0x10, 0x02 }, // 12.5%
85                { 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 }, // 25%
86                { 0x15, 0xa2, 0x54, 0x8a, 0x51, 0x2a, 0x45, 0xa8 }, // 37.5%
87                { 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa }, // 50%
88                { 0xd5, 0xba, 0x57, 0xea, 0x5d, 0xab, 0x75, 0xae }, // 62.5%
89                { 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee }, // 75%
90                { 0xbf, 0xf7, 0xfe, 0xdf, 0xfb, 0x7f, 0xef, 0xfd }  // 87.5%
91            };
92            pixmap[t] = XCreateBitmapFromData(common->get_display(), common->get_window_id(), reinterpret_cast<const char *>(stippleBits[t]), PIXMAP_SIZE, PIXMAP_SIZE);
93        }
94        initialized = true;
95    }
96
97    return pixmap[stippleType];
98}
99
100AW_device::Fill_Style AW_device_Xm::setFillstyleForGreylevel(int gc, AW::FillStyle filled) {
101    // sets fillstyle and stipple for current greylevel of 'gc'
102
103    switch (filled.get_style()) {
104        case AW::FillStyle::SOLID: return FS_SOLID;
105        case AW::FillStyle::EMPTY: return FS_EMPTY;
106
107        case AW::FillStyle::SHADED:
108        case AW::FillStyle::SHADED_WITH_BORDER:
109            break; // detect using greylevel
110    }
111
112    AW_grey_level greylevel = get_grey_level(gc);
113
114    if (greylevel<0.0625) {
115        return FS_EMPTY;
116    }
117    if (greylevel<0.9375) { // otherwise draw solid
118        StippleType stippleType = ST_UNDEFINED;
119
120        if      (greylevel<0.1875) stippleType = FILLED_125;
121        else if (greylevel<0.3125) stippleType = FILLED_25;
122        else if (greylevel<0.4375) stippleType = FILLED_375;
123        else if (greylevel<0.5626) stippleType = FILLED_50;
124        else if (greylevel<0.6875) stippleType = FILLED_625;
125        else if (greylevel<0.8125) stippleType = FILLED_75;
126        else stippleType                       = FILLED_875;
127
128        AW_common_Xm *Common  = get_common();
129        Pixmap        stipple = getStipplePixmap(Common, stippleType);
130
131        Display *Disp = Common->get_display();
132        GC       xgc  = Common->get_GC(gc);
133
134        XSetFillRule(Disp, xgc,  WindingRule);
135        XSetStipple(Disp, xgc, stipple);
136        XSetFillStyle(Disp, xgc, FillStippled);
137
138        return FS_GREY;
139    }
140    return FS_SOLID;
141}
142void AW_device_Xm::resetFillstyleForGreylevel(int gc) {
143    // should be called after using setFillstyleForGreylevel (to undo XSetFillStyle)
144    // (Note: may be skipped if setFillstyleForGreylevel did not return FS_GREY)
145    XSetFillStyle(get_common()->get_display(), get_common()->get_GC(gc), FillSolid);
146}
147
148bool AW_device_Xm::box_impl(int gc, AW::FillStyle filled, const Rectangle& rect, AW_bitset filteri) {
149    bool drawflag = false;
150    if (filteri & filter) {
151        if (filled.is_empty()) {
152            drawflag = generic_box(gc, rect, filteri);
153        }
154        else {
155            Rectangle transRect = transform(rect);
156            Rectangle clippedRect;
157            drawflag = box_clip(transRect, clippedRect);
158            if (drawflag) {
159                Fill_Style fillStyle = setFillstyleForGreylevel(gc, filled);
160
161                if (fillStyle != FS_EMPTY) {
162                    XFillRectangle(XDRAW_PARAM3(get_common(), gc),
163                                   AW_INT(clippedRect.left()),
164                                   AW_INT(clippedRect.top()),
165                                   AW_INT(clippedRect.width())+1, // see aw_device.hxx@WORLD_vs_PIXEL
166                                   AW_INT(clippedRect.height())+1);
167
168                    if (fillStyle == FS_GREY) resetFillstyleForGreylevel(gc);
169                }
170                if (fillStyle != FS_SOLID && filled.get_style() != AW::FillStyle::SHADED) {
171                    // draw solid box-border (for empty and grey box)
172                    // (Note: using XDrawRectangle here is wrong)
173                    generic_box(gc, rect, filteri);
174                }
175                else {
176                    AUTO_FLUSH(this);
177                }
178            }
179        }
180    }
181    return drawflag;
182}
183
184bool AW_device_Xm::polygon_impl(int gc, AW::FillStyle filled, int npos, const AW::Position *pos, AW_bitset filteri) {
185    bool drawflag = false;
186    if (filteri & filter) {
187        if (filled.is_empty()) {
188            drawflag = generic_polygon(gc, npos, pos, filteri);
189        }
190        else {
191            Position *transPos = new Position[npos];
192            for (int p = 0; p<npos; ++p) {
193                transPos[p] = transform(pos[p]);
194            }
195
196            int           nclippedPos;
197            AW::Position *clippedPos = NULp;
198
199            drawflag = box_clip(npos, transPos, nclippedPos, clippedPos);
200            if (drawflag) {
201                Fill_Style fillStyle = setFillstyleForGreylevel(gc, filled);
202
203                if (fillStyle != FS_EMPTY) {
204                    XPoint *xpos = new XPoint[nclippedPos];
205
206                    for (int p = 0; p<nclippedPos; ++p) {
207                        xpos[p].x = AW_INT(clippedPos[p].xpos());
208                        xpos[p].y = AW_INT(clippedPos[p].ypos());
209                    }
210
211                    XFillPolygon(XDRAW_PARAM3(get_common(), gc),
212                                 xpos,
213                                 nclippedPos,
214                                 // Complex,
215                                 // Nonconvex,
216                                 Convex,
217                                 CoordModeOrigin);
218
219                    if (fillStyle == FS_GREY) resetFillstyleForGreylevel(gc);
220                    delete [] xpos;
221                }
222                if (fillStyle != FS_SOLID && filled.get_style() != AW::FillStyle::SHADED) {
223                    // draw solid polygon-border (for empty and grey polygon)
224                    // (Note: using XDrawRectangle here is wrong)
225                    generic_polygon(gc, npos, pos, filteri);
226                }
227                else {
228                    AUTO_FLUSH(this);
229                }
230            }
231
232            delete [] clippedPos;
233            delete [] transPos;
234        }
235    }
236    return drawflag;
237}
238
239bool AW_device_Xm::circle_impl(int gc, AW::FillStyle filled, const AW::Position& center, const AW::Vector& radius, AW_bitset filteri) {
240    aw_assert(radius.x()>0 && radius.y()>0);
241    return arc_impl(gc, filled, center, radius, 0, 360, filteri);
242}
243
244bool AW_device_Xm::arc_impl(int gc, AW::FillStyle filled, const AW::Position& center, const AW::Vector& radius, int start_degrees, int arc_degrees, AW_bitset filteri) {
245    // degrees start at east side of unit circle,
246    // but orientation is clockwise (because ARBs y-coordinate grows downwards)
247
248    bool drawflag = false;
249    if (filteri & filter) {
250        Rectangle Box(center-radius, center+radius);
251        Rectangle screen_box = transform(Box);
252
253        drawflag = !is_outside_clip(screen_box);
254        if (drawflag) {
255            int             width  = AW_INT(screen_box.width());
256            int             height = AW_INT(screen_box.height());
257            const Position& ulc    = screen_box.upper_left_corner();
258            int             xl     = AW_INT(ulc.xpos());
259            int             yl     = AW_INT(ulc.ypos());
260
261            aw_assert(arc_degrees >= -360 && arc_degrees <= 360);
262
263            // ARB -> X
264            start_degrees = -start_degrees;
265            arc_degrees   = -arc_degrees;
266
267            while (start_degrees<0) start_degrees += 360;
268
269            Fill_Style fillStyle = setFillstyleForGreylevel(gc, filled);
270            if (fillStyle != FS_EMPTY) {
271                XFillArc(XDRAW_PARAM3(get_common(), gc), xl, yl, width, height, 64*start_degrees, 64*arc_degrees);
272                if (fillStyle == FS_GREY) resetFillstyleForGreylevel(gc);
273                if (fillStyle != FS_SOLID && filled.get_style() != AW::FillStyle::SHADED) {
274                    // draw solid arc-border (for grey arcs) - does not draw pie-lines, only outline is drawn
275                    arc_impl(gc, AW::FillStyle::EMPTY, center, radius, start_degrees, arc_degrees, filteri);
276                }
277            }
278            else {
279                XDrawArc(XDRAW_PARAM3(get_common(), gc), xl, yl, width, height, 64*start_degrees, 64*arc_degrees);
280            }
281            AUTO_FLUSH(this);
282        }
283    }
284    return drawflag;
285}
286
287void AW_device_Xm::clear(AW_bitset filteri) {
288    if (filteri & filter) {
289        XClearWindow(XDRAW_PARAM2(get_common()));
290        AUTO_FLUSH(this);
291    }
292}
293
294void AW_device_Xm::clear_part(const Rectangle& rect, AW_bitset filteri) {
295    if (filteri & filter) {
296        Rectangle transRect = transform(rect);
297        Rectangle clippedRect;
298        bool drawflag = box_clip(transRect, clippedRect);
299        if (drawflag) {
300            XClearArea(XDRAW_PARAM2(get_common()),
301                       AW_INT(clippedRect.left()),
302                       AW_INT(clippedRect.top()),
303                       AW_INT(clippedRect.width())+1, // see aw_device.hxx@WORLD_vs_PIXEL
304                       AW_INT(clippedRect.height())+1,
305                       False);
306            AUTO_FLUSH(this);
307        }
308    }
309}
310
311void AW_device_Xm::flush() {
312    XFlush(get_common()->get_display());
313}
314
315void AW_device_Xm::move_region(AW_pos src_x, AW_pos src_y, AW_pos width, AW_pos height, AW_pos dest_x, AW_pos dest_y) {
316    int gc = 0;
317    XCopyArea(get_common()->get_display(), get_common()->get_window_id(), get_common()->get_window_id(), get_common()->get_GC(gc),
318              AW_INT(src_x), AW_INT(src_y), AW_INT(width), AW_INT(height),
319              AW_INT(dest_x), AW_INT(dest_y));
320    AUTO_FLUSH(this);
321}
322
Note: See TracBrowser for help on using the repository browser.