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