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

Last change on this file since 19700 was 18628, checked in by tbretz, 8 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.