source: trunk/FACT++/drive/MGImage.cc@ 20083

Last change on this file since 20083 was 18628, checked in by tbretz, 10 years ago
Dientengle from root and Mars, added the drawing function from their previous location.
File size: 12.5 KB
Line 
1//
2// This File contains the definition of the MGImage-class
3//
4// Author: Thomas Bretz
5// Version: V1.0 (1-8-2000)
6//
7// x11/src/GX11Gui.cxx
8//
9
10//////////////////////////////////////////////////////////////////////////////
11//
12// MGImage
13//
14// If sync-mode is enabled the Redraw function is secured by a mutex (ignore
15// error messages about it comming from root) This has the advantage that
16// if you use a timer for screen update reading and writing the image is
17// synchronized. In this way you don't get flickering half images.
18//
19//////////////////////////////////////////////////////////////////////////////
20#include "MGImage.h"
21
22#include <iostream>
23
24#include <TGX11.h>
25#include <TMutex.h>
26
27#include <TMath.h>
28
29//#include "MLog.h"
30//#include "MLogManip.h"
31
32using namespace std;
33
34MGImage::MGImage(const TGWindow* p, UInt_t w, UInt_t h, UInt_t options, ULong_t back)
35 : TGFrame(p, w, h, options, back), fWidth(w), fHeight(h)
36{
37 // p = pointer to MainFrame (not owner)
38 // w = width of frame
39 // h = width of frame
40
41 //
42 // Creat drawing semaphore
43 //
44 fMuxPixmap = new TMutex;
45
46 Resize(GetWidth(), GetHeight());
47
48 //
49 // create empty pixmap
50 //
51 fDefGC = gVirtualX->CreateGC(fId, 0);
52 fImage = (XImage*)gVirtualX->CreateImage(fWidth, fHeight);
53
54 cout << "Detected Color Depth: " << gVirtualX->GetDepth() << endl;
55}
56
57MGImage::~MGImage()
58{
59// if (fMuxPixmap->Lock()==13)
60// cout << "MGImage::~MGImage - mutex is already locked by this thread" << endl;
61
62 cout << "Deleting MGImage..." << endl;
63
64 gVirtualX->DeleteGC(fDefGC);
65 gVirtualX->DeleteImage((Drawable_t)fImage);
66
67 //cout << fMuxPixmap->UnLock() << endl;
68
69 delete fMuxPixmap;
70
71 cout << "MGImage destroyed." << endl;
72}
73
74void MGImage::DoRedraw()
75{
76 if (TestBit(kSyncMode))
77 while (fMuxPixmap->Lock()==13)
78 usleep(1);
79
80 // gVirtualX->DrawLine(fId, fDefGC, 0, 0, fWidth+2, 0);
81 // gVirtualX->DrawLine(fId, fDefGC, 0, 0, 0, fHeight+2);
82 // gVirtualX->DrawLine(fId, fDefGC, fWidth+2, 0, fWidth+2, fHeight+2);
83 // gVirtualX->DrawLine(fId, fDefGC, 0, fHeight+2, fWidth+2, fHeight+2);
84
85 // if (TestBit(kNeedRedraw))
86 {
87 gVirtualX->PutImage(fId, fDefGC, (Drawable_t)fImage, 0, 0, 0, 0,
88 fWidth, fHeight);
89 ResetBit(kNeedRedraw);
90 }
91
92 if (TestBit(kSyncMode))
93 if (fMuxPixmap->UnLock()==13)
94 cout << "MGImage::DoRedraw - tried to unlock mutex locked by other thread." << endl;
95}
96
97void MGImage::DrawImg16(unsigned short *d, char *s, char *e)
98{
99 // d=destination, s=source, e=end
100 // rrrrrggg gggbbbbb
101 //
102 while (s<e)
103 {
104 // 11111100 11111000 11111000
105 // *d++ = (*s&0xfc) | (*s&0xf8)<<5 | (*s&0xf8)<<11;
106
107 // 11111000 11111100 11111000
108 *d++ = (*s&0xf8)<<8 | (*s&0xfc)<<3 | (*s>>3);
109 s++;
110 }
111}
112
113void MGImage::DrawImg24(char *d, char *s, char *e)
114{
115 // d=destination, s=source, e=end
116 // rrrrrrrr gggggggg bbbbbbbb aaaaaaaa
117 //
118 while (s<e)
119 {
120 *d++ = *s;
121 *d++ = *s;
122 *d++ = *s++;
123 d++;
124 }
125}
126
127void MGImage::DrawImg(const byte *buffer)
128{
129 if (TestBit(kSyncMode))
130 while (fMuxPixmap->Lock()==13)
131 usleep(1);
132 else
133 {
134 const Int_t rc = fMuxPixmap->Lock();
135 if (rc==13)
136 cout << "MGImage::DrawImg - mutex is already locked by this thread" << endl;
137 if (rc)
138 return;
139 }
140
141 switch (gVirtualX->GetDepth())
142 {
143 case 8:
144 memcpy(fImage->data, buffer, fWidth*fHeight);
145 break;
146 case 16:
147 DrawImg16((unsigned short*)fImage->data, (char*)buffer, (char*)(buffer+fWidth*fHeight));
148 break;
149 case 24:
150 DrawImg24(fImage->data, (char*)buffer, (char*)(buffer+fWidth*fHeight));
151 break;
152 default:
153 cout << "Sorry, " << gVirtualX->GetDepth() << "bit color depth not yet implemented." << endl;
154 }
155
156 SetBit(kNeedRedraw);
157
158 if (fMuxPixmap->UnLock()==13)
159 cout << "MGImage::DrawImage - tried to unlock mutex locked by other thread." << endl;
160}
161
162void MGImage::DrawColImg16(unsigned short *d, char *s1, char *s2, char *e)
163{
164 // d=destination, s1=source1, s2=source2, e=end
165 // d: rrrrrggg gggbbbbb
166 // s2: 00rrggbb
167 //
168 while (s1<e)
169 {
170 if (*s2)
171 {
172 // 00000011 00001100 00110000
173 //*d++ = (*s2&0x3) | (*s2&0xb)<<3 | (*s2&0x30)<<7;
174 *d++ = (*s2&0x3)<<3 | (*s2&0xb)<<6 | (*s2&0x30)<<10;
175 }
176 else
177 {
178 // 11111100 11111000 11111100
179 *d++ = (*s1&0xfc) | (*s1&0xf8)<<5 | (*s1&0xfc)<<11;
180 }
181 s1++;
182 s2++;
183 }
184}
185
186void MGImage::DrawColImg24(char *d, char *s1, char *s2, char *e)
187{
188 // d=destination, s1=source1, s2=source2, e=end
189 while (s1<e)
190 {
191 if (*s2)
192 {
193 *d++ = ((*s2>>4)&0x3)*85;
194 *d++ = ((*s2>>2)&0x3)*85;
195 *d++ = ((*s2++ )&0x3)*85;
196 d++;
197 s1++;
198 }
199 else
200 {
201 *d++ = *s1;
202 *d++ = *s1;
203 *d++ = *s1++;
204 d++;
205 s2++;
206 }
207 }
208}
209
210void MGImage::DrawColImg(const byte *gbuf, const byte *cbuf)
211{
212 if (TestBit(kSyncMode))
213 while (fMuxPixmap->Lock()==13)
214 usleep(1);
215 else
216 {
217 const Int_t rc = fMuxPixmap->Lock();
218 if (rc==13)
219 cout << "MGImage::DrawColImg - mutex is already locked by this thread" << endl;
220 if (rc)
221 return;
222 }
223
224 // FROM libAfterImage:
225 // -------------------
226 //#define ALPHA_TRANSPARENT 0x00
227 //#define ALPHA_SEMI_TRANSPARENT 0x7F
228 //#define ALPHA_SOLID 0xFF
229 // * Lowermost 8 bits - Blue channel
230 // * bits 8 to 15 - Green channel
231 // * bits 16 to 23 - Red channel
232 // * bits 24 to 31 - Alpha channel
233 //#define ARGB32_White 0xFFFFFFFF
234 //#define ARGB32_Black 0xFF000000
235
236 // FIXME: This loop depends on the screen color depth
237 switch (gVirtualX->GetDepth())
238 {
239 case 16:
240 DrawColImg16((unsigned short*)fImage->data, (char*)gbuf, (char*)cbuf, (char*)(gbuf+fWidth*fHeight));
241 break;
242 case 24:
243 DrawColImg24(fImage->data, (char*)gbuf, (char*)cbuf, (char*)(gbuf+fWidth*fHeight));
244 break;
245 default:
246 cout << "Sorry, " << gVirtualX->GetDepth() << "bit color depth not yet implemented." << endl;
247 }
248
249 SetBit(kNeedRedraw);
250
251 if (fMuxPixmap->UnLock()==13)
252 cout << "MGImage::DrawColImage - tried to unlock mutex locked by other thread." << endl;
253}
254
255// --------------------------------------------------------------------------
256//
257// Convert root colors to arbitrary bitmap coordinates
258//
259UChar_t MGImage::Color(int col)
260{
261 switch (col)
262 {
263 case kBlack: return 0;
264 case kWhite: return 0xff;
265 case kYellow: return 0x0f;
266 case kRed: return 2;
267 case kGreen: return 2<<2;
268 case kBlue: return 2<<4;
269 default:
270 return 0;
271 }
272}
273
274// --------------------------------------------------------------------------
275//
276// Draw a line into the buffer (size w*h) from (x1, y1) to (x2, y2) with
277// the color col and the line style style (default: solid)
278//
279void MGImage::DrawLine(UChar_t *buf, int w, int h, Float_t x1, Float_t y1, Float_t x2, Float_t y2, UChar_t col, Int_t style)
280{
281 const Int_t step = style==kSolid?1:3;
282 const Double_t len = TMath::Hypot(x2-x1, y2-y1);
283 const Double_t dx = (x2-x1)/len*step;
284 const Double_t dy = (y2-y1)/len*step;
285
286 Double_t x = x1;
287 Double_t y = y1;
288
289 for (int i=0; i<len; i+=step)
290 {
291 x+= dx;
292 y+= dy;
293
294 const Int_t iy = TMath::Nint(y);
295 if (iy<0 || iy>=h)
296 continue;
297
298 const Int_t ix = TMath::Nint(x);
299 if (ix<0 || ix>=w)
300 continue;
301
302 buf[ix+iy*w] = col;
303 }
304}
305
306// --------------------------------------------------------------------------
307//
308// Draw a box into the buffer (size w*h) from (x1, y1) to (x2, y2) with
309// the color col and the line style style (default: solid)
310//
311void MGImage::DrawBox(UChar_t *buf, int w, int h, Float_t x1, Float_t y1, Float_t x2, Float_t y2, UChar_t col, Int_t style)
312{
313 DrawLine(buf, w, h, x1, y1, x2, y1, col, style);
314 DrawLine(buf, w, h, x1, y2, x2, y1, col, style);
315 DrawLine(buf, w, h, x1, y1, x1, y2, col, style);
316 DrawLine(buf, w, h, x2, y1, x2, y2, col, style);
317}
318
319// --------------------------------------------------------------------------
320//
321// Draw a hexagon into the buffer (size w*h) around (x, y) with radius r and
322// the color col.
323//
324void MGImage::DrawHexagon(UChar_t *buf, int w, int h, Float_t px, Float_t py, Float_t d, UChar_t col, Int_t style)
325{
326 const Int_t np = 6;
327
328 const Double_t dy[np+1] = { .5 , 0. , -.5 , -.5 , 0. , .5 , .5 };
329 const Double_t dx[np+1] = { .2886, .5772, .2886, -.2886, -.5772, -.2886, .2886 };
330
331 //
332 // calculate the positions of the pixel corners
333 //
334 Double_t x[np+1], y[np+1];
335 for (Int_t i=0; i<np+1; i++)
336 {
337 x[i] = px + dx[i]*d;
338 y[i] = py + dy[i]*d;
339 }
340
341 for (int i=0; i<6; i++)
342 DrawLine(buf, w, h, x[i], y[i], x[i+1], y[i+1], col, style);
343}
344
345// --------------------------------------------------------------------------
346//
347// Draw a circle into the buffer (size w*h) around (x, y) with radius r and
348// the color col.
349//
350void MGImage::DrawCircle(UChar_t *buf, int w, int h, Float_t x, Float_t y, Float_t r, UChar_t col)
351{
352 const Int_t n = TMath::Nint(sqrt(2.)*r*TMath::Pi()/2);
353 for (int i=0; i<n-1; i++)
354 {
355 const Double_t angle = TMath::TwoPi()*i/n;
356
357 const Double_t dx = r*cos(angle);
358 const Double_t dy = r*sin(angle);
359
360 const Int_t x1 = TMath::Nint(x+dx);
361 const Int_t x2 = TMath::Nint(x-dx);
362
363 const Int_t y1 = TMath::Nint(y+dy);
364 if (y1>=0 && y1<h)
365 {
366 if (x1>=0 && x1<w)
367 buf[x1+y1*w] = col;
368
369 if (x2>=0 && x2<w)
370 buf[x2+y1*w] = col;
371 }
372
373 const Int_t y2 = TMath::Nint(y-dy);
374 if (y2>=0 && y2<h)
375 {
376 if (x1>=0 && x1<w)
377 buf[x1+y2*w] = col;
378
379 if (x2>=0 && x2<w)
380 buf[x2+y2*w] = col;
381 }
382 }
383}
384
385// --------------------------------------------------------------------------
386//
387// Draw a dot into the buffer (size w*h) at (x, y) with color col.
388//
389void MGImage::DrawDot(UChar_t *buf, int w, int h, Float_t cx, Float_t cy, UChar_t col)
390{
391 const Int_t x1 = TMath::Nint(cx);
392 const Int_t y1 = TMath::Nint(cy);
393
394 if (x1>=0 && y1>=0 && x1<w && y1<h)
395 buf[x1+y1*w] = col;
396}
397
398// --------------------------------------------------------------------------
399//
400// Draw a line into the buffer. The TObject must be a TLine.
401// Currently only solid and non sloid line are supported.
402//
403/*
404void MGImage::DrawLine(TObject *o, UChar_t *buf, int w, int h, Double_t scale)
405{
406 TLine *l = dynamic_cast<TLine*>(o);
407 if (!l)
408 return;
409
410 const Double_t x1 = 0.5*w-(l->GetX1()/scale);
411 const Double_t x2 = 0.5*w-(l->GetX2()/scale);
412 const Double_t y1 = 0.5*h-(l->GetY1()/scale);
413 const Double_t y2 = 0.5*h-(l->GetY2()/scale);
414
415 const Int_t col = Color(l->GetLineColor());
416 DrawLine(buf, w, h, x1, y1, x2, y2, col, l->GetLineStyle());
417}
418*/
419void MGImage::DrawMultiply(UChar_t *buf, int w, int h, Float_t cx, Float_t cy, Float_t size, UChar_t col)
420{
421 DrawLine(buf, w, h, cx-size, cy-size, cx+size, cy+size, col);
422 DrawLine(buf, w, h, cx+size, cy-size, cx-size, cy+size, col);
423}
424
425void MGImage::DrawCross(UChar_t *buf, int w, int h, Float_t cx, Float_t cy, Float_t size, UChar_t col)
426{
427 DrawLine(buf, w, h, cx-size, cy, cx+size, cy, col);
428 DrawLine(buf, w, h, cx, cy-size, cx, cy+size, col);
429}
430
431// --------------------------------------------------------------------------
432//
433// Draw marker into the buffer. The TObject must be a TMarker.
434// Currently kCircle, kMultiply and KDot are supported.
435/*
436void MGImage::DrawMarker(TObject *o, UChar_t *buf, int w, int h, Double_t scale)
437{
438 TMarker *m = dynamic_cast<TMarker*>(o);
439 if (!m)
440 return;
441
442 Double_t x = 0.5*w-(m->GetX()/scale);
443 Double_t y = 0.5*h-(m->GetY()/scale);
444
445 Int_t col = Color(m->GetMarkerColor());
446
447 switch (m->GetMarkerStyle())
448 {
449 case kCircle:
450 DrawCircle(buf, w, h, x, y, m->GetMarkerSize()*2+1, col);
451 break;
452 case kDot:
453 DrawDot(buf, w, h, x, y, col);
454 break;
455 case kMultiply:
456 DrawMultiply(buf, w, h, x, y, m->GetMarkerSize()*2+1, col);
457 break;
458 case kCross:
459 DrawCross(buf, w, h, x, y, m->GetMarkerSize()*2+1, col);
460 break;
461 }
462}
463*/
Note: See TracBrowser for help on using the repository browser.