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 // @@@ change implementation of draw functions
14 // * filter has to be checked early (in AW_device)
15 // * functions shall use Position/LineVector/Rectangle only
16 
17 using namespace AW;
18 
19 // ---------------------
20 // AW_device_Xm
21 
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 
27 bool 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 
44 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*/) {
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 
57 bool 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 
70 };
71 
72 const int PIXMAP_SIZE = 8; // 8x8 stipple mask
73 const int STIPPLE_TYPES = FILLED_875+1;
74 
75 static 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 
100 AW_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 
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 }
142 void 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 
148 bool 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 
184 bool 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 
239 bool 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 
244 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) {
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 
287 void AW_device_Xm::clear(AW_bitset filteri) {
288  if (filteri & filter) {
289  XClearWindow(XDRAW_PARAM2(get_common()));
290  AUTO_FLUSH(this);
291  }
292 }
293 
294 void 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 
311 void AW_device_Xm::flush() {
312  XFlush(get_common()->get_display());
313 }
314 
315 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) {
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 
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:72
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:25
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:44
const Position & upper_left_corner() const
const double & y() const
StippleType
Definition: AW_Xm.cxx:61
float AW_grey_level
Definition: aw_base.hxx:46
const int STIPPLE_TYPES
Definition: AW_Xm.cxx:73
double left() const
static Pixmap getStipplePixmap(AW_common_Xm *common, StippleType stippleType)
Definition: AW_Xm.cxx:75
#define XDRAW_PARAM2(common)
Definition: AW_Xm.cxx:24
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:116
AW_DEVICE_TYPE
Definition: aw_device.hxx:48
const double & x() const