Logo ROOT   6.08/07
Reference Guide
TASImage.cxx
Go to the documentation of this file.
1 // @(#)root/asimage:$Id: TASImage.cxx,v 1.54 2006/03/13 15:18:56 rdm E
2 // Author: Fons Rademakers, Reiner Rohlfs, Valeriy Onuchin 28/11/2001
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /**************************************************************************
13  * Some parts of this source are based on libAfterImage 2.00.00
14  * (http://www.afterstep.org/)
15  *
16  * Copyright (c) 2002 Sasha Vasko <sasha@aftercode.net>
17  * Copyright (c) 1998, 1999 Ethan Fischer <allanon@crystaltokyo.com>
18  *
19  * This program is free software; you can redistribute it and/or modify
20  * it under the terms of the GNU Library General Public License as
21  * published by the Free Software Foundation; either version 2 of the
22  * License, or (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU Library General Public
30  * License along with this program; if not, write to the Free Software
31  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  *
33  **************************************************************************/
34 
35 /** \class TASImage
36 \ingroup asimage
37 
38 Image class.
39 
40 TASImage is the concrete interface to the image processing library
41 libAfterImage.
42 
43 It allows reading and writing of images in different formats, several image
44 manipulations (scaling, tiling, merging, etc.) and displaying in pads. The size
45 of the image on the screen does not depend on the original size of the image but
46 on the size of the pad. Therefore it is very easy to resize the image on the
47 screen by resizing the pad.
48 
49 Besides reading an image from a file an image can be defined by a two
50 dimensional array of values. A palette defines the color of each value.
51 
52 The image can be zoomed by defining a rectangle with the mouse. The color
53 palette can be modified with a GUI, just select StartPaletteEditor() from the
54 context menu.
55 
56 Several examples showing how to use this class are available in the
57 ROOT tutorials: `$ROOTSYS/tutorials/image/`
58 */
59 
60 # include <ft2build.h>
61 # include FT_FREETYPE_H
62 # include FT_GLYPH_H
63 #include "TASImage.h"
64 #include "TASImagePlugin.h"
65 #include "TROOT.h"
66 #include "TMath.h"
67 #include "TSystem.h"
68 #include "TVirtualX.h"
69 #include "TVirtualPad.h"
70 #include "TArrayD.h"
71 #include "TVectorD.h"
72 #include "TVirtualPS.h"
73 #include "TGaxis.h"
74 #include "TColor.h"
75 #include "TObjArray.h"
76 #include "TArrayL.h"
77 #include "TPoint.h"
78 #include "TFrame.h"
79 #include "TTF.h"
80 #include "TRandom.h"
81 #include "Riostream.h"
82 #include "THashTable.h"
83 #include "TPluginManager.h"
84 #include "TEnv.h"
85 #include "TStyle.h"
86 #include "TText.h"
87 #include "RConfigure.h"
88 #include "TVirtualPadPainter.h"
89 
90 #ifndef WIN32
91 #ifndef R__HAS_COCOA
92 # include <X11/Xlib.h>
93 #endif
94 #else
95 # include "Windows4root.h"
96 #endif
97 extern "C" {
98 #ifndef WIN32
99 #ifdef R__HAS_COCOA
100 # define X_DISPLAY_MISSING 1
101 #endif
102 # include <afterbase.h>
103 #else
104 # include <win32/config.h>
105 # include <win32/afterbase.h>
106 # define X_DISPLAY_MISSING 1
107 #endif
108 # include <afterimage.h>
109 # include <bmp.h>
110 # include <draw.h>
111 }
112 
113 // auxiliary functions for general polygon filling
114 #include "TASPolyUtils.c"
115 
116 
117 ASVisual *TASImage::fgVisual = 0;
119 
120 static ASFontManager *gFontManager = 0;
121 static unsigned long kAllPlanes = ~0;
123 
124 // default icon paths
125 static char *gIconPaths[7] = {0, 0, 0, 0, 0, 0, 0};
126 
127 ///////////////////////////// alpha-blending macros ///////////////////////////////
128 
129 #if defined(__GNUC__) && __GNUC__ >= 4 && ((__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ >= 1) || (__GNUC_MINOR__ >= 3)) && !__INTEL_COMPILER
130 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
131 #endif
132 
133 #ifdef R__BYTESWAP
134 typedef struct {
135  unsigned char b;
136  unsigned char g;
137  unsigned char r;
138  unsigned char a;
139 } __argb32__;
140 #else
141 typedef struct {
142  unsigned char a;
143  unsigned char r;
144  unsigned char g;
145  unsigned char b;
146 } __argb32__;
147 #endif
148 
149 
150 //______________________________________________________________________________
151 #define _alphaBlend(bot, top) {\
152  __argb32__ *T = (__argb32__*)(top);\
153  __argb32__ *B = (__argb32__*)(bot);\
154  int aa = 255-T->a;\
155  if (!aa) {\
156  *bot = *top;\
157  } else { \
158  B->a = ((B->a*aa)>>8) + T->a;\
159  B->r = (B->r*aa + T->r*T->a)>>8;\
160  B->g = (B->g*aa + T->g*T->a)>>8;\
161  B->b = (B->b*aa + T->b*T->a)>>8;\
162  }\
163 }\
164 
165 
168 
169 ////////////////////////////////////////////////////////////////////////////////
170 /// Destroy image.
171 
172 void TASImage::DestroyImage()
173 {
174  if (fImage) {
175  destroy_asimage(&fImage);
176  }
177 
178  if (fIsGray && fGrayImage) {
179  destroy_asimage(&fGrayImage);
180  }
181 
182  fIsGray = kFALSE;
183  fGrayImage = 0;
184  fImage = 0;
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// Set default parameters.
189 
191 {
192  fImage = 0;
193  fScaledImage = 0;
194  fMaxValue = 1;
195  fMinValue = 0;
196  fEditable = kFALSE;
197  fPaintMode = 1;
198  fZoomOffX = 0;
199  fZoomOffY = 0;
200  fZoomWidth = 0;
201  fZoomHeight = 0;
203 
204  fGrayImage = 0;
205  fIsGray = kFALSE;
207 
208  if (!fgInit) {
209  set_application_name((char*)(gProgName ? gProgName : "ROOT"));
210  fgInit = kTRUE;
211  }
212 }
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 /// Default image constructor.
216 
218 {
219  SetDefaults();
220 }
221 
222 ////////////////////////////////////////////////////////////////////////////////
223 /// Create an empty image.
224 
226 {
227  SetDefaults();
228  fImage = create_asimage(w ? w : 20, h ? h : 20, 0);
229  UnZoom();
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 /// Create an image object and read from specified file.
234 /// For more information see description of function ReadImage()
235 /// which is called by this constructor.
236 
238 {
239  SetDefaults();
240  TString fname = file;
241  gSystem->ExpandPathName(fname);
242  ReadImage(fname.Data());
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// Create an image depending on the values of imageData.
247 /// For more information see function SetImage() which is called
248 /// by this constructor.
249 
250 TASImage::TASImage(const char *name, const Double_t *imageData, UInt_t width,
251  UInt_t height, TImagePalette *palette) : TImage(name)
252 {
253  SetDefaults();
254  SetImage(imageData, width, height, palette);
255 }
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 /// Create an image depending on the values of imageData.
259 /// The size of the image is width X (imageData.fN / width).
260 /// For more information see function SetImage() which is called by
261 /// this constructor.
262 
263 TASImage::TASImage(const char *name, const TArrayD &imageData, UInt_t width,
264  TImagePalette *palette) : TImage(name)
265 {
266  SetDefaults();
267  SetImage(imageData, width, palette);
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 /// Create an image depending on the values of imageData.
272 /// The size of the image is width X (imageData.fN / width).
273 /// For more information see function SetImage() which is called by
274 /// this constructor.
275 
276 TASImage::TASImage(const char *name, const TVectorD &imageData, UInt_t width,
277  TImagePalette *palette) : TImage(name)
278 {
279  SetDefaults();
280  SetImage(imageData, width, palette);
281 }
282 
283 ////////////////////////////////////////////////////////////////////////////////
284 /// Image copy constructor.
285 
287 {
288  SetDefaults();
289 
290  if (img.IsValid()) {
291  fImage = clone_asimage(img.fImage, SCL_DO_ALL);
293  fGrayImage = fGrayImage ? clone_asimage(img.fGrayImage, SCL_DO_ALL) : 0;
294 
295  if (img.fImage->alt.vector) {
296  Int_t size = img.fImage->width * img.fImage->height * sizeof(double);
297  fImage->alt.vector = (double*)malloc(size);
298  memcpy(fImage->alt.vector, img.fImage->alt.vector, size);
299  }
300 
302  fZoomOffX = img.fZoomOffX;
303  fZoomOffY = img.fZoomOffY;
304  fZoomWidth = img.fZoomWidth;
305  fZoomHeight = img.fZoomHeight;
306  fEditable = img.fEditable;
307  fIsGray = img.fIsGray;
308  }
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 /// Image assignment operator.
313 
315 {
316  if (this != &img && img.IsValid()) {
317  TImage::operator=(img);
318 
319  DestroyImage();
320  delete fScaledImage;
321  fImage = clone_asimage(img.fImage, SCL_DO_ALL);
323  fGrayImage = fGrayImage ? clone_asimage(img.fGrayImage, SCL_DO_ALL) : 0;
324 
325  if (img.fImage->alt.vector) {
326  Int_t size = img.fImage->width * img.fImage->height * sizeof(double);
327  fImage->alt.vector = (double*)malloc(size);
328  memcpy(fImage->alt.vector, img.fImage->alt.vector, size);
329  }
330 
331  fScaledImage = img.fScaledImage ? (TASImage*)img.fScaledImage->Clone("") : 0;
333  fZoomOffX = img.fZoomOffX;
334  fZoomOffY = img.fZoomOffY;
335  fZoomWidth = img.fZoomWidth;
336  fZoomHeight = img.fZoomHeight;
337  fEditable = img.fEditable;
338  fIsGray = img.fIsGray;
339  fPaintMode = 1;
340  }
341 
342  return *this;
343 }
344 
345 ////////////////////////////////////////////////////////////////////////////////
346 /// Image destructor, clean up image and visual.
347 
349 {
350  DestroyImage();
351  delete fScaledImage;
352  fScaledImage = 0;
353 }
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 /// Set icons paths.
357 
358 static void init_icon_paths()
359 {
360  const char *icons = "/icons";
361 #ifdef R__WIN32
362  icons = "\\icons";
363 #endif
364 
365  TString homeIcons = gSystem->HomeDirectory();
366  homeIcons += icons;
367 
368  TString rootIcons = gSystem->Getenv("ROOTSYS");
369  rootIcons += icons;
370 
371  TString guiIcons = gEnv->GetValue("Gui.IconPath", "");
372 
373  gIconPaths[0] = StrDup(".");
374  gIconPaths[1] = StrDup(homeIcons.Data());
375  gIconPaths[2] = StrDup(rootIcons.Data());
376  gIconPaths[3] = StrDup(guiIcons.Data());
377 
378 #ifdef ROOTICONPATH
379  gIconPaths[4] = StrDup(ROOTICONPATH);
380 #endif
381 
382 #ifdef EXTRAICONPATH
383  gIconPaths[5] = StrDup(EXTRAICONPATH);
384 #endif
385 
386  gIconPaths[6] = 0;
387 }
388 
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Guess the file type from the first byte of file.
391 
392 const char *TASImage::TypeFromMagicNumber(const char *file)
393 {
394  UChar_t magic;
395  FILE *fp = fopen(file, "rb");
396  const char *ret = "";
397 
398  if (!fp) return 0;
399 
400  if (!fread(&magic, 1, 1, fp)) {
401  fclose(fp);
402  return 0;
403  }
404 
405  switch (magic) {
406  case 0x00:
407  {
408  if (!fread(&magic, 1, 1, fp)) {
409  fclose(fp);
410  return 0;
411  }
412  if (!fread(&magic, 1, 1, fp)) {
413  fclose(fp);
414  return 0;
415  }
416 
417  ret = (magic == 1) ? "ico" : "cur";
418  break;
419  }
420  case 0x25:
421  {
422  if (!fread(&magic, 1, 1, fp)) {
423  fclose(fp);
424  return 0;
425  }
426 
427  if (magic == 0x21) ret = "ps";
428  else if (magic == 0x50) ret = "pdf";
429  break;
430  }
431  case 0x42:
432  ret = "bmp";
433  break;
434  case 0x47:
435  ret = "gif";
436  break;
437  case 0x54:
438  ret = "tga";
439  break;
440  case 0x49:
441  ret = "tiff";
442  break;
443  case 0x89:
444  ret = "png";
445  break;
446  case 0xff:
447  ret = "jpg";
448  break;
449  default:
450  ret = "";
451  }
452 
453  fclose(fp);
454  return ret;
455 }
456 
457 ////////////////////////////////////////////////////////////////////////////////
458 /// Read specified image file.
459 /// The file type is determined by the file extension (the type argument is
460 /// ignored). It will attempt to append .gz and then .Z to the filename and
461 /// find such a file. If the filename ends with extension consisting of digits
462 /// only, it will attempt to find the file with this extension stripped
463 /// off. On success this extension will be used to load subimage from
464 /// the file with that number. Subimage is supported for GIF files
465 /// (ICO, BMP, CUR, TIFF, XCF to be supported in future).
466 /// For example,
467 /// ~~~ {.cpp}
468 /// i1 = TImage::Open("anim.gif.0"); // read the first subimage
469 /// i4 = TImage::Open("anim.gif.3"); // read the forth subimage
470 /// ~~~
471 /// It is also possible to put XPM raw string (see also SetImageBuffer) as
472 /// the first input parameter ("filename"), such string is returned by
473 /// GetImageBuffer method.
474 
475 void TASImage::ReadImage(const char *filename, EImageFileTypes /*type*/)
476 {
477  if (!InitVisual()) {
478  Warning("Scale", "Visual not initiated");
479  return;
480  }
481 
482  Bool_t xpm = filename && (filename[0] == '/' &&
483  filename[1] == '*') && filename[2] == ' ';
484 
485  if (xpm) { // XPM strings in-memory array
486  SetImageBuffer((char**)&filename, TImage::kXpm);
487  fName = "XPM_image";
488  return;
489  }
490 
491  if (!gIconPaths[0]) {
492  init_icon_paths();
493  }
494  // suppress the "root : looking for image ..." messages
495  set_output_threshold(0);
496 
497  static ASImageImportParams iparams;
498  iparams.flags = 0;
499  iparams.width = 0;
500  iparams.height = 0;
501  iparams.filter = SCL_DO_ALL;
502  iparams.gamma = SCREEN_GAMMA;
503  iparams.gamma_table = NULL;
504  iparams.compression = GetImageCompression();
505  iparams.format = ASA_ASImage;
506  iparams.search_path = gIconPaths;
507  iparams.subimage = 0;
508  iparams.return_animation_delay = -1;
509 
510  TString ext;
511  const char *dot;
512  if (filename) dot = strrchr(filename, '.');
513  else dot = 0;
514  ASImage *image = 0;
515  TString fname = filename;
516 
517  if (!dot) {
518  if (filename) ext = TypeFromMagicNumber(filename);
519  else ext = dot + 1;
520  } else {
521  ext = dot + 1;
522  }
523 
524  if (!ext.IsNull() && ext.IsDigit()) { // read subimage
525  iparams.subimage = ext.Atoi();
526  fname = fname(0, fname.Length() - ext.Length() - 1);
527  ext = strrchr(fname.Data(), '.') + 1;
528  }
529 
530  image = file2ASImage_extra(fname.Data(), &iparams);
531 
532  if (image) { // it's OK
533  goto end;
534  } else { // try to read it via plugin
535  if (ext.IsNull()) {
536  return;
537  }
538  ext.ToLower();
539  ext.Strip();
540  UInt_t w = 0;
541  UInt_t h = 0;
542  unsigned char *bitmap = 0;
543 
545 
546  if (!plug) {
547  TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler("TImagePlugin", ext);
548  if (!handler || ((handler->LoadPlugin() == -1))) {
549  return;
550  }
551  plug = (TImagePlugin*)handler->ExecPlugin(1, ext.Data());
552 
553  if (!plug) {
554  return;
555  }
556 
557  fgPlugList->Add(plug);
558  }
559 
560  if (plug) {
561  if (plug->InheritsFrom(TASImagePlugin::Class())) {
562  image = ((TASImagePlugin*)plug)->File2ASImage(fname.Data());
563  if (image) goto end;
564  }
565  bitmap = plug->ReadFile(fname.Data(), w, h);
566  if (bitmap) {
567  image = bitmap2asimage(bitmap, w, h, 0, 0);
568  }
569  if (!image) {
570  return;
571  }
572  }
573  }
574 
575 end:
576  fName.Form("%s.", gSystem->BaseName(fname.Data()));
577 
578  DestroyImage();
579  delete fScaledImage;
580  fScaledImage = 0;
581 
582  fImage = image;
584  fEditable = kFALSE;
585  fZoomOffX = 0;
586  fZoomOffY = 0;
587  fZoomWidth = fImage->width;
588  fZoomHeight = fImage->height;
589  fPaintMode = 1;
590 }
591 
592 ////////////////////////////////////////////////////////////////////////////////
593 /// Write image to specified file.
594 ///
595 /// If there is no file extension or if the file extension is unknown, the
596 /// type argument will be used to determine the file type. The quality and
597 /// compression is derived from the TAttImage values.
598 ///
599 /// It's possible to write image into an animated GIF file by specifying file
600 /// name as "myfile.gif+" or "myfile.gif+NN", where NN is the delay of displaying
601 /// subimages during animation in 10ms seconds units. NN is not restricted
602 /// to two digits. If NN is omitted the delay between subimages is zero.
603 /// For an animation that stops after last subimage is reached, one has to
604 /// write the last image as .gif+ (zero delay of last image) or .gif+NN
605 /// (NN*10ms delay of last image).
606 ///
607 /// For repeated animation (looping), the last subimage must be specified as:
608 /// - "myfile.gif++NN++" if you want an infinite looping gif with NN*10ms
609 /// delay of the last image.
610 /// - "myfile.gif++" for an infinite loop with zero delay of last image.
611 /// - "myfile.gif+NN++RR" if you want a finite looping gif with NN*10ms
612 /// delay of the last image and the animation to be stopped after RR
613 /// repeats. RR is not restricted to two digits.
614 ///
615 /// A deprecated version for saving the last subimage of a looping gif animation is:
616 /// - "myfile.gif++NN" for a finite loop where NN is number of repetitions
617 /// and NN*10ms the delay of last image. (No separate control of repeats and delay).
618 /// Note: If the file "myfile.gif" already exists, the new frames are appended at
619 /// the end of the file. To avoid this, delete it first with gSystem->Unlink(myfile.gif);
620 ///
621 /// The following macro creates animated gif from jpeg images with names
622 /// - imageNN.jpg, where 1<= NN <= 10
623 /// - The delays are set to 10*10ms.
624 /// ~~~ {.cpp}
625 /// {
626 /// TImage *img = 0;
627 /// gSystem->Unlink("anim.gif"); // delete existing file
628 ///
629 /// for (int i = 1; i <= 10; i++) {
630 /// delete img; // delete previous image
631 ///
632 /// // Read image data. Image can be in any format, e.g. png, gif, etc.
633 /// img = TImage::Open(Form("image%d.jpg", i));
634 ///
635 /// if (i < 10) {
636 /// img->WriteImage("anim.gif+10"); // 10 centiseconds delay
637 /// } else { // the last image written. "++" stands for infinit animation.
638 /// img->WriteImage("anim.gif++10++"); // 10 centiseconds delay of last image
639 /// }
640 /// }
641 /// }
642 /// ~~~
643 
645 {
646  if (!IsValid()) {
647  Error("WriteImage", "no image loaded");
648  return;
649  }
650 
651  if (!file || !*file) {
652  Error("WriteImage", "no file name specified");
653  return;
654  }
655 
656  const char *s;
657  if ((s = strrchr(file, '.'))) {
658  s++;
660  if (t == kUnknown) {
661  Error("WriteImage", "cannot determine a valid file type");
662  return;
663  }
664  if (t != kUnknown)
665  type = t;
666  }
667 
668  if (type == kUnknown) {
669  Error("WriteImage", "not a valid file type was specified");
670  return;
671  }
672 
673  UInt_t mytype;
674  MapFileTypes(type, mytype);
675  ASImageFileTypes atype = (ASImageFileTypes)mytype;
676 
677  UInt_t aquality;
678  EImageQuality quality = GetImageQuality();
679  MapQuality(quality, aquality);
680 
681  static TString fname;
682  fname = file;
683  static ASImageExportParams parms;
684  ASImage *im = fScaledImage ? fScaledImage->fImage : fImage;
685 
686  switch (type) {
687  case kXpm:
688  parms.xpm.type = atype;
689  parms.xpm.flags = EXPORT_ALPHA;
690  parms.xpm.dither = 4;
691  parms.xpm.opaque_threshold = 127;
692  parms.xpm.max_colors = 512;
693  break;
694  case kBmp:
695  ASImage2bmp(im, fname.Data(), 0);
696  return;
697  case kXcf:
698  ASImage2xcf(im, fname.Data(), 0);
699  return;
700  case kPng:
701  parms.png.type = atype;
702  parms.png.flags = EXPORT_ALPHA;
703  parms.png.compression = !GetImageCompression() ? -1 : int(GetImageCompression());
704  break;
705  case kJpeg:
706  parms.jpeg.type = atype;
707  parms.jpeg.flags = 0;
708  parms.jpeg.quality = aquality;
709  break;
710  case kGif:
711  parms.gif.type = atype;
712  parms.gif.flags = EXPORT_ALPHA;
713  parms.gif.dither = 0;
714  parms.gif.opaque_threshold = 0;
715  break;
716  case kAnimGif:
717  {
718  parms.gif.type = atype;
719  parms.gif.flags = EXPORT_ALPHA | EXPORT_APPEND;
720  parms.gif.dither = 0;
721  parms.gif.opaque_threshold = 0;
722  parms.gif.animate_repeats = 0;
723 
724  s += 4; // skip "gif+"
725  int delay = 0;
726 
727  const TString sufix = s; // we denote as suffix as everything that is after .gif+
728  const UInt_t sLength = sufix.Length();
729 
730  if (sufix=="+") {
731  // .gif++ implies that this is the last image of the animation
732  // and that the gif will loop forever (infinite animation)
733  // and that the delay of last image is 0ms (backward compatibility reasons)
734  delay = 0;
735  parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
736  parms.gif.animate_repeats = 0;// 0 is code for looping forever (if EXPORT_ANIMATION_REPEATS is also set)
737  } else if(sufix=="") {
738  // .gif+ implies that this is a subimage of the animation with zero delay
739  // or the last image of an animation that will not repeat.
740  // Last image delay is zero because atoi("")=0.
741  delay = atoi(s);
742  //Nothing else needed here
743  } else if(!sufix.Contains("+")) {
744  // .gif+NN implies that this is a subimage of the animation
745  // with NN*10ms delay (latency) until the next one.
746  // You can also use this option on the last image if you do not want the gif to replay
747  delay = atoi(s);
748  //Nothing else needed here
749  } else if(sLength>1 && sufix.BeginsWith("+") && sufix.CountChar('+')==1) {
750  // .gif++NN implies that this is the last image of the animation
751  // and that it will loop NN number of times (finite animation)
752  // and that the delay of last image is NN*10ms (backward compatibility reasons).
753  delay = atoi(s);// atoi is smart enough to ignore the "+" sign before.
754  parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
755  parms.gif.animate_repeats = atoi(s);// loops only NN times, then it stops. atoi discards + sign.
756  } else if(sLength>3 && sufix.BeginsWith("+") && sufix.EndsWith("++") && !TString(sufix(1,sLength-3)).Contains("+")) {
757  // .gif++NN++ implies that this is the last image of the animation
758  // and that the gif will loop forever (infinite animation)
759  // and that the delay of last image is NN*10ms.
760  // In contrast, .gif++ is an infinite loop but with 0 delay, whereas the option
761  // .gif++NN is a loop repeated NN times (not infinite) with NN*10ms delay
762  // between last and first loop images.
763  delay = atoi(s);// atoi discards the three plus signs
764  parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
765  parms.gif.animate_repeats = 0;// 0 is code for looping forever (if EXPORT_ANIMATION_REPEATS is also set)
766  } else if(sLength>3 && sufix.CountChar('+')==2 && TString(sufix(1,sLength-2)).Contains("++")) {
767  // .gif+NN++RR implies that this is the last image animation
768  // and that the gif will loop RR number of times (finite animation)
769  // and that the delay of last image is NN*10ms.
770  const TString sDelay = sufix(0,sufix.First('+'));
771  const TString sRepeats = sufix(sufix.First('+')+2,sLength-(sufix.First('+')+2));
772  delay = atoi(sDelay);
773  parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
774  parms.gif.animate_repeats = atoi(sRepeats);// loops NN times.
775  } else {
776  Error("WriteImage", "gif suffix %s not yet supported", s);
777  return;
778  }
779 
780  parms.gif.animate_delay = delay;
781 
782  int i1 = fname.Index("gif+");
783  if (i1 != kNPOS) {
784  fname = fname(0, i1 + 3);
785  }
786  else {
787  Error("WriteImage", "unexpected gif extension structure %s", fname.Data());
788  return;
789  }
790  break;
791  }
792  case kTiff:
793  parms.tiff.type = atype;
794  parms.tiff.flags = EXPORT_ALPHA;
795  parms.tiff.rows_per_strip = 0;
796  parms.tiff.compression_type = aquality <= 50 ? TIFF_COMPRESSION_JPEG :
797  TIFF_COMPRESSION_NONE;
798  parms.tiff.jpeg_quality = 100;
799  parms.tiff.opaque_threshold = 0;
800  break;
801  default:
802  Error("WriteImage", "file type %s not yet supported", s);
803  return;
804  }
805 
806  if (!ASImage2file(im, 0, fname.Data(), atype, &parms)) {
807  Error("WriteImage", "error writing file %s", file);
808  }
809 }
810 
811 ////////////////////////////////////////////////////////////////////////////////
812 /// Return file type depending on specified extension.
813 /// Protected method.
814 
816 {
817  TString s(ext);
818  s.Strip();
819  s.ToLower();
820 
821  if (s == "xpm")
822  return kXpm;
823  if (s == "png")
824  return kPng;
825  if (s == "jpg" || s == "jpeg")
826  return kJpeg;
827  if (s == "xcf")
828  return kXcf;
829  if (s == "ppm")
830  return kPpm;
831  if (s == "pnm")
832  return kPnm;
833  if (s == "bmp")
834  return kBmp;
835  if (s == "ico")
836  return kIco;
837  if (s == "cur")
838  return kCur;
839  if (s == "gif")
840  return kGif;
841  if (s.Contains("gif+"))
842  return kAnimGif;
843  if (s == "tiff")
844  return kTiff;
845  if (s == "xbm")
846  return kXbm;
847  if (s == "tga")
848  return kTga;
849  if (s == "xml")
850  return kXml;
851 
852  return kUnknown;
853 }
854 
855 ////////////////////////////////////////////////////////////////////////////////
856 /// Map file type to/from AfterImage types.
857 /// Protected method.
858 
860 {
861  if (toas) {
862  switch (type) {
863  case kXpm:
864  astype = ASIT_Xpm; break;
865  case kZCompressedXpm:
866  astype = ASIT_ZCompressedXpm; break;
867  case kGZCompressedXpm:
868  astype = ASIT_GZCompressedXpm; break;
869  case kPng:
870  astype = ASIT_Png; break;
871  case kJpeg:
872  astype = ASIT_Jpeg; break;
873  case kXcf:
874  astype = ASIT_Xcf; break;
875  case kPpm:
876  astype = ASIT_Ppm; break;
877  case kPnm:
878  astype = ASIT_Pnm; break;
879  case kBmp:
880  astype = ASIT_Bmp; break;
881  case kIco:
882  astype = ASIT_Ico; break;
883  case kCur:
884  astype = ASIT_Cur; break;
885  case kGif:
886  astype = ASIT_Gif; break;
887  case kAnimGif:
888  astype = ASIT_Gif; break;
889  case kTiff:
890  astype = ASIT_Tiff; break;
891  case kXbm:
892  astype = ASIT_Xbm; break;
893  case kTga:
894  astype = ASIT_Targa; break;
895  case kXml:
896  astype = ASIT_XMLScript; break;
897  default:
898  astype = ASIT_Unknown;
899  }
900  } else {
901  switch (astype) {
902  case ASIT_Xpm:
903  type = kXpm; break;
904  case ASIT_ZCompressedXpm:
905  type = kZCompressedXpm; break;
906  case ASIT_GZCompressedXpm:
907  type = kGZCompressedXpm; break;
908  case ASIT_Png:
909  type = kPng; break;
910  case ASIT_Jpeg:
911  type = kJpeg; break;
912  case ASIT_Xcf:
913  type = kXcf; break;
914  case ASIT_Ppm:
915  type = kPpm; break;
916  case ASIT_Pnm:
917  type = kPnm; break;
918  case ASIT_Bmp:
919  type = kBmp; break;
920  case ASIT_Ico:
921  type = kIco; break;
922  case ASIT_Cur:
923  type = kCur; break;
924  case ASIT_Gif:
925  type = kGif; break;
926  case ASIT_Tiff:
927  type = kTiff; break;
928  case ASIT_Xbm:
929  type = kXbm; break;
930  case ASIT_XMLScript:
931  type = kXml; break;
932  case ASIT_Targa:
933  type = kTga; break;
934  default:
935  type = kUnknown;
936  }
937  }
938 }
939 
940 ////////////////////////////////////////////////////////////////////////////////
941 /// Map quality to/from AfterImage quality.
942 /// Protected method.
943 
944 void TASImage::MapQuality(EImageQuality &quality, UInt_t &asquality, Bool_t toas)
945 {
946  if (toas) {
947  switch (quality) {
948  case kImgPoor:
949  asquality = 25; break;
950  case kImgFast:
951  asquality = 75; break;
952  case kImgGood:
953  asquality = 50; break;
954  case kImgBest:
955  asquality = 100; break;
956  default:
957  asquality = 0;
958  }
959  } else {
960  quality = kImgDefault;
961  if (asquality > 0 && asquality <= 25)
962  quality = kImgPoor;
963  if (asquality > 26 && asquality <= 50)
964  quality = kImgFast;
965  if (asquality > 51 && asquality <= 75)
966  quality = kImgGood;
967  if (asquality > 76 && asquality <= 100)
968  quality = kImgBest;
969  }
970 }
971 
972 ////////////////////////////////////////////////////////////////////////////////
973 /// Deletes the old image and creates a new image depending on the values
974 /// of imageData. The size of the image is width X height.
975 ///
976 /// The color of each pixel depends on the imageData of the corresponding
977 /// pixel. The palette is used to convert an image value into its color.
978 /// If palette is not defined (palette = 0) a default palette is used.
979 /// Any previously defined zooming is reset.
980 
981 void TASImage::SetImage(const Double_t *imageData, UInt_t width, UInt_t height,
982  TImagePalette *palette)
983 {
984  TAttImage::SetPalette(palette);
985 
986  if (!InitVisual()) {
987  Warning("SetImage", "Visual not initiated");
988  return;
989  }
990 
991  DestroyImage();
992  delete fScaledImage;
993  fScaledImage = 0;
994 
995  // get min and max value of image
996  fMinValue = fMaxValue = *imageData;
997  for (Int_t pixel = 1; pixel < Int_t(width * height); pixel++) {
998  if (fMinValue > *(imageData + pixel)) fMinValue = *(imageData + pixel);
999  if (fMaxValue < *(imageData + pixel)) fMaxValue = *(imageData + pixel);
1000  }
1001 
1002  // copy ROOT palette to asImage palette
1003  const TImagePalette &pal = GetPalette();
1004 
1005  ASVectorPalette asPalette;
1006 
1007  asPalette.npoints = pal.fNumPoints;
1008  Int_t col;
1009  for (col = 0; col < 4; col++)
1010  asPalette.channels[col] = new UShort_t[asPalette.npoints];
1011 
1012  memcpy(asPalette.channels[0], pal.fColorBlue, pal.fNumPoints * sizeof(UShort_t));
1013  memcpy(asPalette.channels[1], pal.fColorGreen, pal.fNumPoints * sizeof(UShort_t));
1014  memcpy(asPalette.channels[2], pal.fColorRed, pal.fNumPoints * sizeof(UShort_t));
1015  memcpy(asPalette.channels[3], pal.fColorAlpha, pal.fNumPoints * sizeof(UShort_t));
1016 
1017  asPalette.points = new Double_t[asPalette.npoints];
1018  for (Int_t point = 0; point < Int_t(asPalette.npoints); point++)
1019  asPalette.points[point] = fMinValue + (fMaxValue - fMinValue) * pal.fPoints[point];
1020 
1021  fImage = create_asimage_from_vector(fgVisual, (Double_t*)imageData, width,
1022  height, &asPalette, ASA_ASImage,
1024 
1025  delete [] asPalette.points;
1026  for (col = 0; col < 4; col++)
1027  delete [] asPalette.channels[col];
1028 
1029  fZoomUpdate = 0;
1030  fZoomOffX = 0;
1031  fZoomOffY = 0;
1032  fZoomWidth = width;
1033  fZoomHeight = height;
1035 }
1036 
1037 ////////////////////////////////////////////////////////////////////////////////
1038 /// Delete the old image and creates a new image depending on the values
1039 /// of imageData. The size of the image is width X (imageData.fN / width).
1040 /// The color of each pixel depends on the imageData of the corresponding
1041 /// pixel. The palette is used to convert an image value into its color.
1042 /// If palette is not defined (palette = 0) a default palette is used.
1043 /// Any previously defined zooming is reset.
1044 
1045 void TASImage::SetImage(const TArrayD &imageData, UInt_t width, TImagePalette *palette)
1046 {
1047  SetImage(imageData.GetArray(), width, imageData.GetSize() / width, palette);
1048 }
1049 
1050 ////////////////////////////////////////////////////////////////////////////////
1051 /// Delete the old image and creates a new image depending on the values
1052 /// of imageData. The size of the image is width X (imageData.fN / width).
1053 /// The color of each pixel depends on the imageData of the corresponding
1054 /// pixel. The palette is used to convert an image value into its color.
1055 /// If palette is not defined (palette = 0) a default palette is used.
1056 /// Any previously defined zooming is reset.
1057 
1058 void TASImage::SetImage(const TVectorD &imageData, UInt_t width, TImagePalette *palette)
1059 {
1060  SetImage(imageData.GetMatrixArray(), width,
1061  imageData.GetNoElements() / width, palette);
1062 }
1063 
1064 ////////////////////////////////////////////////////////////////////////////////
1065 /// Create an image from the given pad, afterwards this image can be
1066 /// saved in any of the supported image formats.
1067 
1069 {
1070  if (!pad) {
1071  Error("FromPad", "pad cannot be 0");
1072  return;
1073  }
1074 
1075  if (!InitVisual()) {
1076  Warning("FromPad", "Visual not initiated");
1077  return;
1078  }
1079 
1080  SetName(pad->GetName());
1081 
1082  DestroyImage();
1083  delete fScaledImage;
1084  fScaledImage = 0;
1085 
1086  if (gROOT->IsBatch()) { // in batch mode
1087  TVirtualPS *psave = gVirtualPS;
1088  gVirtualPS = (TVirtualPS*)gROOT->ProcessLineFast("new TImageDump()");
1089  gVirtualPS->Open(pad->GetName(), 114); // in memory
1090  gVirtualPS->SetBit(BIT(11)); //kPrintingPS
1091 
1092  TASImage *itmp = (TASImage*)gVirtualPS->GetStream();
1093 
1094  if (itmp && itmp->fImage) {
1095  itmp->BeginPaint();
1096  }
1097 
1098  TVirtualPad *sav = gPad;
1099  gPad = pad;
1100  pad->Paint();
1101  gPad = sav;
1102 
1103  if (itmp && itmp->fImage && (itmp != this)) {
1104  fImage = clone_asimage(itmp->fImage, SCL_DO_ALL);
1105  if (itmp->fImage->alt.argb32) {
1106  UInt_t sz = itmp->fImage->width*itmp->fImage->height;
1107  fImage->alt.argb32 = (ARGB32*)safemalloc(sz*sizeof(ARGB32));
1108  memcpy(fImage->alt.argb32, itmp->fImage->alt.argb32, sz*4);
1109  }
1110  }
1111  delete gVirtualPS;
1112  gVirtualPS = psave;
1113  return;
1114  }
1115 
1116  if (w == 0) {
1117  w = TMath::Abs(pad->UtoPixel(1.));
1118  }
1119 
1120  if (h == 0) {
1121  h = pad->VtoPixel(0.);
1122  }
1123  // synchronization
1124  gVirtualX->Update(1);
1125  if (!gThreadXAR) {
1127  gSystem->Sleep(10);
1129  }
1130 
1131  TVirtualPad *canvas = (TVirtualPad*)pad->GetCanvas();
1132  Int_t wid = (pad == canvas) ? pad->GetCanvasID() : pad->GetPixmapID();
1133  gVirtualX->SelectWindow(wid);
1134 
1135  Window_t wd = (Window_t)gVirtualX->GetCurrentWindow();
1136  if (!wd) return;
1137 
1138  static int x11 = -1;
1139  if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
1140 
1141  if (x11) { //use built-in optimized version
1142  fImage = pixmap2asimage(fgVisual, wd, x, y, w, h, kAllPlanes, 0, 0);
1143  } else {
1144  unsigned char *bits = gVirtualX->GetColorBits(wd, 0, 0, w, h);
1145 
1146  if (!bits) { // error
1147  return;
1148  }
1149  fImage = bitmap2asimage(bits, w, h, 0, 0);
1150  delete [] bits;
1151  }
1152 }
1153 
1154 ////////////////////////////////////////////////////////////////////////////////
1155 /// Draw image.
1156 /// Support the following drawing options:
1157 /// - "T[x,y[,tint]]" : tile image (use specified offset and tint),
1158 /// e.g. "T100,100,#556655"
1159 /// with this option the zooming is not possible
1160 /// and disabled
1161 /// - "N" : display in new canvas (of original image size)
1162 /// - "X" : image is drawn expanded to pad size
1163 /// - "Z" : image is vectorized and image palette is drawn
1164 ///
1165 /// The default is to display the image in the current gPad.
1166 
1168 {
1169  if (!fImage) {
1170  Error("Draw", "no image set");
1171  return;
1172  }
1173 
1174  TString opt = option;
1175  opt.ToLower();
1176  if (opt.Contains("n") || !gPad || !gPad->IsEditable()) {
1177  Int_t w = -64;
1178  Int_t h = 64;
1179  w = (fImage->width > 64) ? (Int_t)fImage->width : w;
1180  h = (fImage->height > 64) ? (Int_t)fImage->height : h;
1181 
1182  Float_t cx = 1./gStyle->GetScreenFactor();
1183  w = Int_t(w*cx) + 4;
1184  h = Int_t(h*cx) + 28;
1185  TString rname = GetName();
1186  rname.ReplaceAll(".", "");
1187  rname += Form("\", \"%s (%d x %d)", rname.Data(), fImage->width, fImage->height);
1188  rname = "new TCanvas(\"" + rname + Form("\", %d, %d);", w, h);
1189  gROOT->ProcessLineFast(rname.Data());
1190  }
1191 
1192  if (!opt.Contains("x")) {
1193  Double_t left = gPad->GetLeftMargin();
1194  Double_t right = gPad->GetRightMargin();
1195  Double_t top = gPad->GetTopMargin();
1196  Double_t bottom = gPad->GetBottomMargin();
1197 
1198  gPad->Range(-left / (1.0 - left - right),
1199  -bottom / (1.0 - top - bottom),
1200  1 + right / (1.0 - left - right),
1201  1 + top / ( 1.0 - top - bottom));
1202  gPad->RangeAxis(0, 0, 1, 1);
1203  }
1204 
1205  TFrame *frame = gPad->GetFrame();
1206  if (frame) {
1207  frame->SetBorderMode(0);
1208  frame->SetFillColor(gPad->GetFillColor());
1209  frame->SetLineColor(gPad->GetFillColor());
1210  frame->Draw();
1211  }
1212 
1213  TObject::Draw(option);
1214 }
1215 
1216 ////////////////////////////////////////////////////////////////////////////////
1217 /// Draw asimage on drawable.
1218 
1220  Int_t xsrc, Int_t ysrc, UInt_t wsrc, UInt_t hsrc,
1221  Option_t *opt)
1222 {
1223  if (!im) return;
1224 
1225  wsrc = wsrc ? wsrc : im->width;
1226  hsrc = hsrc ? hsrc : im->height;
1227 
1228  static int x11 = -1;
1229  if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
1230 
1231  Pixmap_t mask = kNone;
1232 
1233  if (x11) {
1234  UInt_t hh = hsrc;
1235  UInt_t ow = wsrc%8;
1236  UInt_t ww = wsrc - ow + (ow ? 8 : 0);
1237 
1238  UInt_t bit = 0;
1239  int i = 0;
1240  UInt_t yy = 0;
1241  UInt_t xx = 0;
1242 
1243  char *bits = new char[ww*hh]; //an array of bits
1244 
1245  ASImageDecoder *imdec = start_image_decoding(fgVisual, im, SCL_DO_ALPHA,
1246  xsrc, ysrc, ww, 0, 0);
1247  if (imdec) {
1248  for (yy = 0; yy < hh; yy++) {
1249  imdec->decode_image_scanline(imdec);
1250  CARD32 *a = imdec->buffer.alpha;
1251 
1252  for (xx = 0; xx < ww; xx++) {
1253  if (a[xx]) {
1254  SETBIT(bits[i], bit);
1255  } else {
1256  CLRBIT(bits[i], bit);
1257  }
1258  bit++;
1259  if (bit == 8) {
1260  bit = 0;
1261  i++;
1262  }
1263  }
1264  }
1265  }
1266 
1267  stop_image_decoding(&imdec);
1268 
1269  mask = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(),
1270  (const char *)bits, ww, hh);
1271  delete [] bits;
1272  }
1273 
1274  GCValues_t gv;
1275  static GContext_t gc = 0;
1276 
1278  gv.fClipMask = mask;
1279  gv.fClipXOrigin = x;
1280  gv.fClipYOrigin = y;
1281 
1282  if (!gc) {
1283  gc = gVirtualX->CreateGC(gVirtualX->GetDefaultRootWindow(), &gv);
1284  } else {
1285  gVirtualX->ChangeGC(gc, &gv);
1286  }
1287 
1288  if (x11 && (!gPad || gPad->GetGLDevice() == -1)) { //use built-in optimized version
1289  asimage2drawable(fgVisual, wid, im, (GC)gc, xsrc, ysrc, x, y, wsrc, hsrc, 1);
1290  } else {
1291  ASImage *img = 0;
1292  unsigned char *bits = (unsigned char *)im->alt.argb32;
1293  if (!bits) {
1294  img = tile_asimage(fgVisual, im, xsrc, ysrc, wsrc, hsrc,
1295  0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
1296  if (img)
1297  bits = (unsigned char *)img->alt.argb32;
1298  }
1299 
1300  if (bits) {
1301  TString option(opt);
1302  option.ToLower();
1303 
1304  if (gPad && gPad->GetGLDevice() != -1) {
1305  if (TVirtualPadPainter *painter = gPad->GetPainter())
1306  painter->DrawPixels(bits, wsrc, hsrc, x, y, !option.Contains("opaque"));
1307  } else {
1308  Pixmap_t pic = gVirtualX->CreatePixmapFromData(bits, wsrc, hsrc);
1309  if (pic) {
1310  if (!option.Contains("opaque")) {
1311  SETBIT(wsrc,31);
1312  SETBIT(hsrc,31);
1313  }
1314  gVirtualX->CopyArea(pic, wid, gc, 0, 0, wsrc, hsrc, x, y);
1315  gVirtualX->DeletePixmap(pic);
1316  }
1317  }
1318  }
1319 
1320  if (img) {
1321  destroy_asimage(&img);
1322  }
1323  }
1324 
1325  // free mask pixmap
1326  if (gv.fClipMask != kNone) gVirtualX->DeletePixmap(gv.fClipMask);
1327 
1328  gv.fMask = kGCClipMask;
1329  gv.fClipMask = kNone;
1330  if (gc) gVirtualX->ChangeGC(gc, &gv);
1331 }
1332 
1333 ////////////////////////////////////////////////////////////////////////////////
1334 /// Draw image on the drawable wid (pixmap, window) at x,y position.
1335 ///
1336 /// \param[in] wid : Drawable (pixmap or window) on which image is drawn.
1337 /// \param[in] x,y : Window coordinates where image is drawn.
1338 /// \param[in] xsrc, ysrc : X and Y coordinates of an image area to be drawn.
1339 /// \param[in] wsrc, hsrc : Width and height image area to be drawn.
1340 
1342  UInt_t wsrc, UInt_t hsrc, Option_t *opt)
1343 {
1345  xsrc, ysrc, wsrc, hsrc, opt);
1346 }
1347 
1348 ////////////////////////////////////////////////////////////////////////////////
1349 /// Paint image.
1350 /// Support the following drawing options:
1351 /// - "T[x,y[,tint]]" : tile image (use specified offset and tint),
1352 /// e.g. "T100,100,#556655"
1353 /// with this option the zooming is not possible
1354 /// and disabled
1355 /// - "N" : display in new canvas (of original image size)
1356 /// - "X" : image is drawn expanded to pad size
1357 /// - "Z" : image is vectorized and image palette is drawn
1358 ///
1359 /// The default is to display the image in the current gPad.
1360 
1362 {
1363  if (!fImage) {
1364  Error("Paint", "no image set");
1365  return;
1366  }
1367 
1368  if (!InitVisual()) {
1369  Warning("Paint", "Visual not initiated");
1370  return;
1371  }
1372 
1373  Int_t tile_x = 0, tile_y = 0;
1374  CARD32 tile_tint = 0;
1375  Bool_t tile = kFALSE;
1376  Bool_t expand = kFALSE;
1377 
1378  TString opt = option;
1379  opt.ToLower();
1380 
1381  if (opt.Contains("t")) {
1382  char stint[64];
1383  if (sscanf(opt.Data() + opt.Index("t"), "t%d,%d,%s", &tile_x, &tile_y,
1384  stint) <= 3) {
1385  tile = kTRUE;
1386  if (parse_argb_color(stint, (CARD32*)&tile_tint) == stint)
1387  tile_tint = 0;
1388  } else {
1389  Error("Paint", "tile option error");
1390  }
1391  } else if (opt.Contains("x")) {
1392  expand = kTRUE;
1393  fConstRatio = kFALSE;
1394  } else if (opt.Contains("z")) {
1396 
1397  if (!fImage->alt.vector) {
1398  Vectorize(256);
1399  }
1400  }
1401 
1402  ASImage *image = fImage;
1403 
1404  // Get geometry of pad
1405  Int_t to_w = gPad->UtoPixel(1.);
1406  Int_t to_h = gPad->VtoPixel(0.);
1407 
1408  // remove the size by the margin of the pad
1409  if (!expand) {
1410  to_h = (Int_t)(to_h * (1.0 - gPad->GetBottomMargin() - gPad->GetTopMargin() ) + 0.5);
1411  to_w = (Int_t)(to_w * (1.0 - gPad->GetLeftMargin() - gPad->GetRightMargin() ) + 0.5);
1412  }
1413 
1414  if ((to_w < 25 || to_h < 25) && !expand) {
1415  Error("Paint", "pad too small to display an image");
1416  return;
1417  }
1418 
1419  if (GetConstRatio()) {
1420  if ((Double_t)to_w / (Double_t)fZoomWidth <
1421  (Double_t)to_h / (Double_t)fZoomHeight)
1422  to_h = Int_t(Double_t(fZoomHeight) * to_w / fZoomWidth);
1423  else
1424  to_w = Int_t(Double_t(fZoomWidth) * to_h / fZoomHeight);
1425  }
1426  // upper left corner and size of the palette in pixels
1427  Int_t pal_Ax = to_w + gPad->UtoAbsPixel(gPad->GetLeftMargin()) +
1428  (gPad->UtoAbsPixel(gPad->GetRightMargin()) / 10);
1429  Int_t pal_Ay = gPad->YtoAbsPixel(1.0);
1430  Int_t pal_x = to_w + gPad->UtoPixel(gPad->GetLeftMargin()) +
1431  (gPad->UtoPixel(gPad->GetRightMargin()) / 10);
1432  Int_t pal_y = gPad->YtoPixel(1.0);
1433  Int_t pal_w = gPad->UtoPixel(gPad->GetRightMargin()) / 3;
1434  Int_t pal_h = to_h;
1435 
1436  ASImage *grad_im = 0;
1437 
1438  if (fImage->alt.vector && fPaletteEnabled) {
1439  // draw the palette
1440  ASGradient grad;
1441  const TImagePalette &pal = GetPalette();
1442 
1443  grad.npoints = pal.fNumPoints;
1444  grad.type = GRADIENT_Top2Bottom;
1445  grad.color = new ARGB32[grad.npoints];
1446  grad.offset = new double[grad.npoints];
1447 
1448  for (Int_t pt = 0; pt < grad.npoints; pt++) {
1449  Int_t oldPt = grad.npoints - pt -1;
1450  grad.offset[pt] = 1 - pal.fPoints[oldPt];
1451  grad.color[pt] = (((ARGB32)(pal.fColorBlue[oldPt] & 0xff00)) >> 8) |
1452  (((ARGB32)(pal.fColorGreen[oldPt] & 0xff00)) ) |
1453  (((ARGB32)(pal.fColorRed[oldPt] & 0xff00)) << 8) |
1454  (((ARGB32)(pal.fColorAlpha[oldPt] & 0xff00)) << 16);
1455  }
1456 
1457  grad_im = make_gradient(fgVisual, &grad , UInt_t(pal_w),
1458  pal_h, SCL_DO_COLOR,
1459  ASA_ARGB32, GetImageCompression(), GetImageQuality());
1460 
1461  delete [] grad.color;
1462  delete [] grad.offset;
1463  }
1464 
1465  if (tile) {
1466  delete fScaledImage;
1468  if (!fScaledImage) return;
1469  fScaledImage->fImage = tile_asimage(fgVisual, fImage, tile_x, tile_y,
1470  to_w, to_h, tile_tint, ASA_ASImage,
1472  image = fScaledImage->fImage;
1473 
1474  } else if (fZoomUpdate == kZoomOps) {
1475  image = fImage;
1476 
1477  } else {
1478  // Scale and zoom image if needed
1479  if (Int_t(fImage->width) != to_w || Int_t(fImage->height) != to_h ||
1480  fImage->width != fZoomWidth || fImage->height != fZoomHeight) {
1481 
1482  if (fScaledImage && (Int_t(fScaledImage->GetWidth()) != to_w ||
1483  Int_t(fScaledImage->GetHeight()) != to_h ||
1484  fZoomUpdate)) {
1485 
1486  delete fScaledImage;
1487  fScaledImage = 0;
1488  }
1489 
1490  if (!fScaledImage) {
1492  if (!fScaledImage) return;
1493 
1494  if (fZoomWidth && fZoomHeight &&
1495  ((fImage->width != fZoomWidth) || (fImage->height != fZoomHeight))) {
1496  // zoom and scale image
1497  ASImage *tmpImage = 0;
1498 
1499  tmpImage = tile_asimage(fgVisual, fImage, fZoomOffX,
1500  fImage->height - fZoomHeight - fZoomOffY,
1501  fZoomWidth, fZoomHeight, 0, ASA_ASImage,
1503 
1504  if (tmpImage) {
1505  fScaledImage->fImage = scale_asimage(fgVisual, tmpImage, to_w, to_h,
1506  ASA_ASImage, GetImageCompression(),
1507  GetImageQuality());
1508  destroy_asimage(&tmpImage);
1509  }
1510  } else {
1511  // scale image, no zooming
1512  fScaledImage->fImage = scale_asimage(fgVisual, fImage, to_w, to_h,
1513  ASA_ASImage, GetImageCompression(),
1514  GetImageQuality());
1515  }
1516  }
1517  image = fScaledImage->fImage;
1518  }
1519  }
1520  fZoomUpdate = 0;
1521 
1522  if (!image) {
1523  Error("Paint", "image could not be rendered to display");
1524  return;
1525  }
1526 
1527  int tox = expand ? 0 : int(gPad->UtoPixel(1.) * gPad->GetLeftMargin());
1528  int toy = expand ? 0 : int(gPad->VtoPixel(0.) * gPad->GetTopMargin());
1529 
1530  if (!gROOT->IsBatch()) {
1531  Window_t wid = (Window_t)gVirtualX->GetWindowID(gPad->GetPixmapID());
1532  Image2Drawable(fScaledImage ? fScaledImage->fImage : fImage, wid, tox, toy);
1533 
1534  if (grad_im && fPaletteEnabled) {
1535  // draw color bar
1536  Image2Drawable(grad_im, wid, pal_x, pal_y);
1537 
1538  // values of palette
1539  TGaxis axis;
1540  Int_t ndiv = 510;
1541  double min = fMinValue;
1542  double max = fMaxValue;
1543  axis.SetLineColor(0); // draw white ticks
1544  Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
1545  axis.PaintAxis(pal_Xpos, gPad->PixeltoY(pal_Ay + pal_h - 1),
1546  pal_Xpos, gPad->PixeltoY(pal_Ay),
1547  min, max, ndiv, "+LU");
1548  min = fMinValue;
1549  max = fMaxValue;
1550  axis.SetLineColor(1); // draw black ticks
1551  axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
1552  pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
1553  min, max, ndiv, "+L");
1554  }
1555  }
1556 
1557  // loop over pixmap and draw image to PostScript
1558  if (gVirtualPS) {
1559  if (gVirtualPS->InheritsFrom("TImageDump")) { // PostScript is asimage
1560  TImage *dump = (TImage *)gVirtualPS->GetStream();
1561  if (!dump) return;
1562  dump->Merge(fScaledImage ? fScaledImage : this, "alphablend",
1563  gPad->XtoAbsPixel(0), gPad->YtoAbsPixel(1));
1564 
1565  if (grad_im) {
1566  TASImage tgrad;
1567  tgrad.fImage = grad_im;
1568  dump->Merge(&tgrad, "alphablend", pal_Ax, pal_Ay);
1569 
1570  // values of palette
1571  TGaxis axis;
1572  Int_t ndiv = 510;
1573  double min = fMinValue;
1574  double max = fMaxValue;
1575  axis.SetLineColor(1); // draw black ticks
1576  Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
1577  axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
1578  pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
1579  min, max, ndiv, "+L");
1580  }
1581  return;
1582  } else if (gVirtualPS->InheritsFrom("TPDF")) {
1583  Warning("Paint", "PDF not implemented yet");
1584  return;
1585  } else if (gVirtualPS->InheritsFrom("TSVG")) {
1586  Warning("Paint", "SVG not implemented yet");
1587  return;
1588  }
1589 
1590  // get special color cell to be reused during image printing
1591  TObjArray *colors = (TObjArray*) gROOT->GetListOfColors();
1592  TColor *color = 0;
1593  // Look for color by name
1594  if ((color = (TColor*)colors->FindObject("Image_PS")) == 0)
1595  color = new TColor(colors->GetEntries(), 1., 1., 1., "Image_PS");
1596 
1597  gVirtualPS->SetFillColor(color->GetNumber());
1598  gVirtualPS->SetFillStyle(1001);
1599 
1600  Double_t dx = gPad->GetX2()-gPad->GetX1();
1601  Double_t dy = gPad->GetY2()-gPad->GetY1();
1602  Double_t x1,x2,y1,y2;
1603 
1604  if (expand) {
1605  x1 = gPad->GetX1();
1606  x2 = x1+dx/image->width;
1607  y1 = gPad->GetY2();
1608  y2 = y1+dy/image->height;
1609  } else {
1610  x1 = gPad->GetX1()+dx*gPad->GetLeftMargin();
1611  x2 = x1+(dx*(1-gPad->GetRightMargin()-gPad->GetLeftMargin()))/image->width;
1612  y1 = gPad->GetY2()-dy*gPad->GetTopMargin();
1613  y2 = y1+(dy*(1-gPad->GetTopMargin()-gPad->GetBottomMargin()))/image->height;
1614  }
1615 
1616  gVirtualPS->CellArrayBegin(image->width, image->height, x1, x2, y1, y2);
1617 
1618  ASImageDecoder *imdec = start_image_decoding(fgVisual, image, SCL_DO_ALL,
1619  0, 0, image->width, image->height, 0);
1620  if (!imdec) return;
1621  for (Int_t yt = 0; yt < (Int_t)image->height; yt++) {
1622  imdec->decode_image_scanline(imdec);
1623  for (Int_t xt = 0; xt < (Int_t)image->width; xt++)
1624  gVirtualPS->CellArrayFill(imdec->buffer.red[xt],
1625  imdec->buffer.green[xt],
1626  imdec->buffer.blue[xt]);
1627  }
1628  stop_image_decoding(&imdec);
1630 
1631  // print the color bar
1632  if (grad_im) {
1633  Double_t xconv = (gPad->AbsPixeltoX(pal_Ax + pal_w) - gPad->AbsPixeltoX(pal_Ax)) / grad_im->width;
1634  Double_t yconv = (gPad->AbsPixeltoY(pal_Ay - pal_h) - gPad->AbsPixeltoY(pal_Ay)) / grad_im->height;
1635  x1 = gPad->AbsPixeltoX(pal_Ax);
1636  x2 = x1 + xconv;
1637  y2 = gPad->AbsPixeltoY(pal_Ay);
1638  y1 = y2 - yconv;
1639  gVirtualPS->CellArrayBegin(grad_im->width, grad_im->height,
1640  x1, x2, y1, y2);
1641 
1642  imdec = start_image_decoding(fgVisual, grad_im, SCL_DO_ALL,
1643  0, 0, grad_im->width, grad_im->height, 0);
1644  if (imdec) {
1645  for (Int_t yt = 0; yt < (Int_t)grad_im->height; yt++) {
1646  imdec->decode_image_scanline(imdec);
1647  for (Int_t xt = 0; xt < (Int_t)grad_im->width; xt++)
1648  gVirtualPS->CellArrayFill(imdec->buffer.red[xt],
1649  imdec->buffer.green[xt],
1650  imdec->buffer.blue[xt]);
1651  }
1652  }
1653  stop_image_decoding(&imdec);
1655 
1656  // values of palette
1657  TGaxis axis;
1658  Int_t ndiv = 510;
1659  double min = fMinValue;
1660  double max = fMaxValue;
1661  axis.SetLineColor(1); // draw black ticks
1662  Double_t pal_Xpos = gPad->AbsPixeltoX(pal_Ax + pal_w);
1663  axis.PaintAxis(pal_Xpos, gPad->AbsPixeltoY(pal_Ay + pal_h),
1664  pal_Xpos, gPad->AbsPixeltoY(pal_Ay + 1),
1665  min, max, ndiv, "+L");
1666 
1667  }
1668  }
1669 
1670  if (grad_im) {
1671  destroy_asimage(&grad_im);
1672  }
1673 }
1674 
1675 ////////////////////////////////////////////////////////////////////////////////
1676 /// Is the mouse in the image ?
1677 
1679 {
1680  Int_t pxl, pyl, pxt, pyt;
1681 
1682  Int_t px1 = gPad->XtoAbsPixel(0);
1683  Int_t py1 = gPad->YtoAbsPixel(0);
1684  Int_t px2 = gPad->XtoAbsPixel(1);
1685  Int_t py2 = gPad->YtoAbsPixel(1);
1686 
1687  if (px1 < px2) {pxl = px1; pxt = px2;}
1688  else {pxl = px2; pxt = px1;}
1689  if (py1 < py2) {pyl = py1; pyt = py2;}
1690  else {pyl = py2; pyt = py1;}
1691 
1692  if ((px > pxl && px < pxt) && (py > pyl && py < pyt))
1693  return 0;
1694 
1695  return 999999;
1696 }
1697 
1698 ////////////////////////////////////////////////////////////////////////////////
1699 /// Execute mouse events.
1700 
1702 {
1703  static TBox *ZoomBox;
1704 
1705  if (!gPad) return;
1706 
1707  if (IsEditable()) {
1708  gPad->ExecuteEvent(event, px, py);
1709  return;
1710  }
1711 
1712  gPad->SetCursor(kCross);
1713 
1714  static Int_t px1old, py1old, px2old, py2old;
1715  static Int_t px1, py1, px2, py2, pxl, pyl, pxt, pyt;
1716 
1717  if (!IsValid()) return;
1718 
1719  if (event == kButton1Motion || event == kButton1Down ||
1720  event == kButton1Up) {
1721 
1722  // convert to image pixel on screen
1723  Int_t imgX = px - gPad->XtoAbsPixel(0);
1724  Int_t imgY = py - gPad->YtoAbsPixel(1);
1725 
1726  if (imgX < 0) px = px - imgX;
1727  if (imgY < 0) py = py - imgY;
1728 
1729  ASImage *image = fImage;
1730  if (fScaledImage) image = fScaledImage->fImage;
1731 
1732  if (imgX >= (int)image->width) px = px - imgX + image->width - 1;
1733  if (imgY >= (int)image->height) py = py - imgY + image->height - 1;
1734 
1735  switch (event) {
1736 
1737  case kButton1Down:
1738  px1 = gPad->XtoAbsPixel(gPad->GetX1());
1739  py1 = gPad->YtoAbsPixel(gPad->GetY1());
1740  px2 = gPad->XtoAbsPixel(gPad->GetX2());
1741  py2 = gPad->YtoAbsPixel(gPad->GetY2());
1742  px1old = px; py1old = py;
1743  break;
1744 
1745  case kButton1Motion:
1746  px2old = px;
1747  px2old = TMath::Max(px2old, px1);
1748  px2old = TMath::Min(px2old, px2);
1749  py2old = py;
1750  py2old = TMath::Max(py2old, py2);
1751  py2old = TMath::Min(py2old, py1);
1752  pxl = TMath::Min(px1old, px2old);
1753  pxt = TMath::Max(px1old, px2old);
1754  pyl = TMath::Max(py1old, py2old);
1755  pyt = TMath::Min(py1old, py2old);
1756 
1757  if (ZoomBox) {
1758  ZoomBox->SetX1(gPad->AbsPixeltoX(pxl));
1759  ZoomBox->SetY1(gPad->AbsPixeltoY(pyl));
1760  ZoomBox->SetX2(gPad->AbsPixeltoX(pxt));
1761  ZoomBox->SetY2(gPad->AbsPixeltoY(pyt));
1762  }
1763  else {
1764  ZoomBox = new TBox(pxl, pyl, pxt, pyt);
1765  ZoomBox->SetFillStyle(0);
1766  ZoomBox->Draw("l*");
1767  }
1768  gPad->Modified(kTRUE);
1769  gPad->Update();
1770  break;
1771 
1772  case kButton1Up:
1773  // do nothing if zoom area is too small
1774  if ( TMath::Abs(pxl - pxt) < 5 || TMath::Abs(pyl - pyt) < 5)
1775  return;
1776 
1777  pxl = 0;
1778  pxt = 0;
1779  pyl = 0;
1780  pyt = 0;
1781 
1782  Double_t xfact = (fScaledImage) ? (Double_t)fScaledImage->fImage->width / fZoomWidth : 1;
1783  Double_t yfact = (fScaledImage) ? (Double_t)fScaledImage->fImage->height / fZoomHeight : 1;
1784 
1785  Int_t imgX1 = px1old - gPad->XtoAbsPixel(0);
1786  Int_t imgY1 = py1old - gPad->YtoAbsPixel(1);
1787  Int_t imgX2 = px - gPad->XtoAbsPixel(0);
1788  Int_t imgY2 = py - gPad->YtoAbsPixel(1);
1789 
1790  imgY1 = image->height - 1 - imgY1;
1791  imgY2 = image->height - 1 - imgY2;
1792  imgX1 = (Int_t)(imgX1 / xfact) + fZoomOffX;
1793  imgY1 = (Int_t)(imgY1 / yfact) + fZoomOffY;
1794  imgX2 = (Int_t)(imgX2 / xfact) + fZoomOffX;
1795  imgY2 = (Int_t)(imgY2 / yfact) + fZoomOffY;
1796 
1797  Zoom((imgX1 < imgX2) ? imgX1 : imgX2, (imgY1 < imgY2) ? imgY1 : imgY2,
1798  TMath::Abs(imgX1 - imgX2) + 1, TMath::Abs(imgY1 - imgY2) + 1);
1799 
1800  if (ZoomBox) {
1801  ZoomBox->Delete();
1802  ZoomBox = 0;
1803  }
1804  gPad->Modified(kTRUE);
1805  gPad->Update();
1806  break;
1807  }
1808  }
1809 }
1810 
1811 ////////////////////////////////////////////////////////////////////////////////
1812 /// Get image pixel coordinates and the pixel value at the mouse pointer.
1813 
1815 {
1816  static char info[64];
1817  info[0] = 0;
1818 
1819  if (!IsValid()) return info;
1820 
1821  // convert to image pixel on screen
1822  px -= gPad->XtoAbsPixel(0);
1823  py -= gPad->YtoAbsPixel(1);
1824 
1825  // no info if mouse is outside of image
1826  if (px < 0 || py < 0) return info;
1827 
1828  ASImage *image = fImage;
1829  if (fScaledImage) image = fScaledImage->fImage;
1830  if (px >= (int)image->width || py >= (int)image->height)
1831  return info;
1832 
1833  py = image->height - 1 - py;
1834  // convert to original image size and take zooming into account
1835  if (fScaledImage) {
1836  px = (Int_t)(px / (Double_t)fScaledImage->fImage->width * fZoomWidth ) + fZoomOffX;
1837  py = (Int_t)(py / (Double_t)fScaledImage->fImage->height * fZoomHeight) + fZoomOffY;
1838  }
1839 
1840  if (fImage->alt.vector) {
1841  snprintf(info,64,"x: %d y: %d %.5g",
1842  px, py, fImage->alt.vector[px + py * fImage->width]);
1843  } else {
1844  snprintf(info,64,"x: %d y: %d", px, py);
1845  }
1846 
1847  return info;
1848 }
1849 
1850 ////////////////////////////////////////////////////////////////////////////////
1851 /// Set a new palette to an image.
1852 /// Only images that were created with the SetImage() functions can be
1853 /// modified with this function. The previously used palette is destroyed.
1854 
1856 {
1857  TAttImage::SetPalette(palette);
1858 
1859  if (!InitVisual()) {
1860  Warning("SetPalette", "Visual not initiated");
1861  return;
1862  }
1863 
1864  if (!IsValid()) {
1865  Warning("SetPalette", "Image not valid");
1866  return;
1867  }
1868 
1869  if (fImage->alt.vector == 0)
1870  return;
1871 
1872  // copy ROOT palette to asImage palette
1873  const TImagePalette &pal = GetPalette();
1874 
1875  ASVectorPalette asPalette;
1876  asPalette.npoints = pal.fNumPoints;
1877  asPalette.channels[0] = new CARD16 [asPalette.npoints];
1878  asPalette.channels[1] = new CARD16 [asPalette.npoints];
1879  asPalette.channels[2] = new CARD16 [asPalette.npoints];
1880  asPalette.channels[3] = new CARD16 [asPalette.npoints];
1881  memcpy(asPalette.channels[0], pal.fColorBlue, pal.fNumPoints * sizeof(UShort_t));
1882  memcpy(asPalette.channels[1], pal.fColorGreen, pal.fNumPoints * sizeof(UShort_t));
1883  memcpy(asPalette.channels[2], pal.fColorRed, pal.fNumPoints * sizeof(UShort_t));
1884  memcpy(asPalette.channels[3], pal.fColorAlpha, pal.fNumPoints * sizeof(UShort_t));
1885 
1886  asPalette.points = new double[asPalette.npoints];
1887  for (Int_t point = 0; point < Int_t(asPalette.npoints); point++)
1888  asPalette.points[point] = fMinValue + (fMaxValue - fMinValue) * pal.fPoints[point];
1889 
1890  // use the new palette in this image
1891  colorize_asimage_vector(fgVisual, fImage, &asPalette, ASA_ASImage, GetImageQuality());
1892 
1893  delete [] asPalette.points;
1894  for (Int_t col = 0; col < 4; col++)
1895  delete [] asPalette.channels[col];
1896 
1897 
1898  delete fScaledImage;
1899  fScaledImage = 0;
1900 }
1901 
1902 ////////////////////////////////////////////////////////////////////////////////
1903 /// Scale the original image.
1904 /// The size of the image on the screen does not change because it is defined
1905 /// by the size of the pad.
1906 /// This function can be used to change the size of an image before writing
1907 /// it into a file. The colors of the new pixels are interpolated.
1908 /// An image created with the SetImage() functions cannot be modified with
1909 /// the function SetPalette() any more after a call of this function!
1910 
1911 void TASImage::Scale(UInt_t toWidth, UInt_t toHeight)
1912 {
1913  if (!IsValid()) {
1914  Warning("Scale", "Image not initiated");
1915  return;
1916  }
1917 
1918  if (!InitVisual()) {
1919  Warning("Scale", "Visual not initiated");
1920  return;
1921  }
1922 
1923  if (toWidth < 1)
1924  toWidth = 1;
1925  if (toHeight < 1 )
1926  toHeight = 1;
1927  if (toWidth > 30000)
1928  toWidth = 30000;
1929  if (toHeight > 30000)
1930  toHeight = 30000;
1931 
1932  ASImage *img = scale_asimage(fgVisual, fImage, toWidth, toHeight,
1933  ASA_ASImage, GetImageCompression(),
1934  GetImageQuality());
1935  DestroyImage();
1936  fImage = img;
1937  UnZoom();
1939 }
1940 
1941 ////////////////////////////////////////////////////////////////////////////////
1942 /// Another method of enlarging images where corners remain unchanged,
1943 /// but middle part gets tiled.
1944 
1945 void TASImage::Slice(UInt_t xStart, UInt_t xEnd, UInt_t yStart, UInt_t yEnd,
1946  UInt_t toWidth, UInt_t toHeight)
1947 {
1948  if (!IsValid()) {
1949  Warning("Scale", "Image not initiated");
1950  return;
1951  }
1952 
1953  if (!InitVisual()) {
1954  Warning("Scale", "Visual not initiated");
1955  return;
1956  }
1957 
1958  if (toWidth < 1)
1959  toWidth = 1;
1960  if (toHeight < 1 )
1961  toHeight = 1;
1962  if (toWidth > 30000)
1963  toWidth = 30000;
1964  if (toHeight > 30000)
1965  toHeight = 30000;
1966 
1967  ASImage *img = slice_asimage(fgVisual, fImage, xStart, xEnd,
1968  yStart, yEnd, toWidth, toHeight,
1969  ASA_ASImage, GetImageCompression(),
1970  GetImageQuality());
1971 
1972  DestroyImage();
1973  fImage = img;
1974  UnZoom();
1976 }
1977 
1978 ////////////////////////////////////////////////////////////////////////////////
1979 /// Tile the original image.
1980 
1981 void TASImage::Tile(UInt_t toWidth, UInt_t toHeight)
1982 {
1983  if (!IsValid()) {
1984  Warning("Tile", "Image not initiated");
1985  return;
1986  }
1987 
1988  if (!InitVisual()) {
1989  Warning("Tile", "Visual not initiated");
1990  return;
1991  }
1992 
1993  if (toWidth < 1)
1994  toWidth = 1;
1995  if (toHeight < 1 )
1996  toHeight = 1;
1997  if (toWidth > 30000)
1998  toWidth = 30000;
1999  if (toHeight > 30000)
2000  toHeight = 30000;
2001 
2002  ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, toWidth, toHeight, 0,
2003  ASA_ASImage, GetImageCompression(), GetImageQuality());
2004  DestroyImage();
2005  fImage = img;
2006  UnZoom();
2008 }
2009 
2010 ////////////////////////////////////////////////////////////////////////////////
2011 /// The area of an image displayed in a pad is defined by this function.
2012 /// Note: the size on the screen is defined by the size of the pad.
2013 /// The original image is not modified by this function.
2014 /// If width or height is larger than the original image they are reduced to
2015 /// the width and height of the image.
2016 /// If the off values are too large (off + width > image width) than the off
2017 /// values are decreased. For example: offX = image width - width
2018 /// Note: the parameters are always relative to the original image not to the
2019 /// size of an already zoomed image.
2020 
2021 void TASImage::Zoom(UInt_t offX, UInt_t offY, UInt_t width, UInt_t height)
2022 {
2023  if (!IsValid()) {
2024  Warning("Zoom", "Image not valid");
2025  return;
2026  }
2027  fZoomUpdate = kZoom;
2028 
2029  fZoomWidth = (width == 0) ? 1 : ((width > fImage->width) ? fImage->width : width);
2030  fZoomHeight = (height == 0) ? 1 : ((height > fImage->height) ? fImage->height : height);
2031  fZoomOffX = offX;
2032  if (fZoomOffX + fZoomWidth > fImage->width)
2033  fZoomOffX = fImage->width - fZoomWidth;
2034  fZoomOffY = offY;
2035  if (fZoomOffY + fZoomHeight > fImage->height)
2036  fZoomOffY = fImage->height - fZoomHeight;
2037 }
2038 
2039 ////////////////////////////////////////////////////////////////////////////////
2040 /// Un-zoom the image to original size.
2041 /// UnZoom() - performs undo for Zoom,Crop,Scale actions
2042 
2044 {
2045  if (!IsValid()) {
2046  Warning("UnZoom", "Image not valid");
2047  return;
2048  }
2049  fZoomUpdate = kZoom;
2050  fZoomOffX = 0;
2051  fZoomOffY = 0;
2052  fZoomWidth = fImage->width;
2053  fZoomHeight = fImage->height;
2054 
2055  delete fScaledImage;
2056  fScaledImage = 0;
2057 }
2058 
2059 ////////////////////////////////////////////////////////////////////////////////
2060 /// Flip image in place.
2061 ///
2062 /// Flip is either 90, 180, 270, 180 is default.
2063 /// This function manipulates the original image and destroys the
2064 /// scaled and zoomed image which will be recreated at the next call of
2065 /// the Draw function. If the image is zoomed the zoom - coordinates are
2066 /// now relative to the new image.
2067 /// This function cannot be used for images which were created with the
2068 /// SetImage() functions, because the original pixel values would be
2069 /// destroyed.
2070 
2072 {
2073  if (!IsValid()) {
2074  Warning("Flip", "Image not valid");
2075  return;
2076  }
2077  if (!InitVisual()) {
2078  Warning("Flip", "Visual not initiated");
2079  return;
2080  }
2081 
2082  if (fImage->alt.vector) {
2083  Warning("Flip", "flip does not work for data images");
2084  return;
2085  }
2086 
2087  Int_t rflip = flip/90;
2088 
2089  UInt_t w = fImage->width;
2090  UInt_t h = fImage->height;
2091 
2092  if (rflip & 1) {
2093  w = fImage->height;
2094  h = fImage->width;
2095  }
2096 
2097  ASImage *img = flip_asimage(fgVisual, fImage, 0, 0, w, h, rflip,
2098  ASA_ASImage, GetImageCompression(),
2099  GetImageQuality());
2100  DestroyImage();
2101  fImage = img;
2102  UnZoom();
2103 }
2104 
2105 ////////////////////////////////////////////////////////////////////////////////
2106 /// Mirror image in place.
2107 ///
2108 /// If vert is true mirror in vertical axis, horizontal otherwise.
2109 /// Vertical is default.
2110 /// This function manipulates the original image and destroys the
2111 /// scaled and zoomed image which will be recreated at the next call of
2112 /// the Draw function. If the image is zoomed the zoom - coordinates are
2113 /// now relative to the new image.
2114 /// This function cannot be used for images which were created with the
2115 /// SetImage() functions, because the original pixel values would be
2116 /// destroyed.
2117 
2119 {
2120  if (!IsValid()) {
2121  Warning("Mirror", "Image not valid");
2122  return;
2123  }
2124 
2125  if (!InitVisual()) {
2126  Warning("Mirror", "Visual not initiated");
2127  return;
2128  }
2129 
2130  if (fImage->alt.vector) {
2131  Warning("Mirror", "mirror does not work for data images");
2132  return;
2133  }
2134 
2135  ASImage *img = mirror_asimage(fgVisual, fImage, 0, 0,
2136  fImage->width, fImage->height, vert,
2137  ASA_ASImage, GetImageCompression(),
2138  GetImageQuality());
2139  DestroyImage();
2140  fImage = img;
2141  UnZoom();
2142 }
2143 
2144 ////////////////////////////////////////////////////////////////////////////////
2145 /// Return width of original image not of the displayed image.
2146 /// (Number of image pixels)
2147 
2149 {
2150  return fImage ? fImage->width : 0;
2151 }
2152 
2153 ////////////////////////////////////////////////////////////////////////////////
2154 /// Return height of original image not of the displayed image.
2155 /// (Number of image pixels)
2156 
2158 {
2159  return fImage ? fImage->height : 0;
2160 }
2161 
2162 ////////////////////////////////////////////////////////////////////////////////
2163 /// Return width of the displayed image not of the original image.
2164 /// (Number of screen pixels)
2165 
2167 {
2168  return fScaledImage ? fScaledImage->fImage->width : GetWidth();
2169 }
2170 
2171 ////////////////////////////////////////////////////////////////////////////////
2172 /// Return height of the displayed image not of the original image.
2173 /// (Number of screen pixels)
2174 
2176 {
2177  return fScaledImage ? fScaledImage->fImage->height : GetHeight();
2178 }
2179 
2180 ////////////////////////////////////////////////////////////////////////////////
2181 /// Return the zoom parameters.
2182 /// This is useful when the zoom has been done interactively using the mouse.
2183 
2185 {
2186  x = fZoomOffX;
2187  y = fZoomOffY;
2188  w = fZoomWidth;
2189  h = fZoomHeight;
2190 }
2191 
2192 ////////////////////////////////////////////////////////////////////////////////
2193 /// Static function to initialize the ASVisual.
2194 
2196 {
2197  Display *disp;
2198 
2199  Bool_t inbatch = fgVisual && (fgVisual->dpy == (void*)1); // was in batch
2200  Bool_t noX = gROOT->IsBatch() || gVirtualX->InheritsFrom("TGWin32");
2201 
2202  // was in batch, but switched to gui
2203  if (inbatch && !noX) {
2204  destroy_asvisual(fgVisual, kFALSE);
2205  fgVisual = 0;
2206  }
2207 
2208  if (fgVisual && fgVisual->dpy) { // already initialized
2209  return kTRUE;
2210  }
2211 
2212  // batch or win32 mode
2213  if (!fgVisual && noX) {
2214  disp = 0;
2215  fgVisual = create_asvisual(0, 0, 0, 0);
2216  fgVisual->dpy = (Display*)1; //fake (not used)
2217  return kTRUE;
2218  }
2219 
2220 #ifndef WIN32
2221 #ifdef R__HAS_COCOA
2222  fgVisual = create_asvisual(0, 0, 0, 0);
2223  fgVisual->dpy = (Display*)1; //fake (not used)
2224 #else
2225  disp = (Display*) gVirtualX->GetDisplay();
2226  Int_t screen = gVirtualX->GetScreen();
2227  Int_t depth = gVirtualX->GetDepth();
2228  Visual *vis = (Visual*) gVirtualX->GetVisual();
2229  Colormap cmap = (Colormap) gVirtualX->GetColormap();
2230 
2231  if (vis == 0 || cmap == 0) {
2232  fgVisual = create_asvisual(0, 0, 0, 0);
2233  } else {
2234  fgVisual = create_asvisual_for_id(disp, screen, depth,
2235  XVisualIDFromVisual(vis), cmap, 0);
2236  }
2237 #endif
2238 #else
2239  fgVisual = create_asvisual(0, 0, 0, 0);
2240  fgVisual->dpy = (Display*)1; //fake (not used)
2241 #endif
2242 
2243  return kTRUE;
2244 }
2245 
2246 ////////////////////////////////////////////////////////////////////////////////
2247 /// Start palette editor.
2248 
2250 {
2251  if (!IsValid()) {
2252  Warning("StartPaletteEditor", "Image not valid");
2253  return;
2254  }
2255  if (fImage->alt.vector == 0) {
2256  Warning("StartPaletteEditor", "palette can be modified only for data images");
2257  return;
2258  }
2259 
2260  // Opens a GUI to edit the color palette
2262 }
2263 
2264 ////////////////////////////////////////////////////////////////////////////////
2265 /// Returns image pixmap.
2266 /// The pixmap must deleted by user.
2267 
2269 {
2270  if (!InitVisual()) {
2271  Warning("GetPixmap", "Visual not initiated");
2272  return 0;
2273  }
2274 
2275  Pixmap_t ret;
2276 
2277  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2278 
2279  static int x11 = -1;
2280  if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
2281 
2282  if (x11) { // use builtin version
2283  ret = (Pixmap_t)asimage2pixmap(fgVisual, gVirtualX->GetDefaultRootWindow(),
2284  img, 0, kTRUE);
2285  } else {
2286  if (!fImage->alt.argb32) {
2287  BeginPaint();
2288  }
2289  ret = gVirtualX->CreatePixmapFromData((unsigned char*)fImage->alt.argb32,
2290  fImage->width, fImage->height);
2291  }
2292 
2293  return ret;
2294 }
2295 
2296 ////////////////////////////////////////////////////////////////////////////////
2297 /// Returns image mask pixmap (alpha channel).
2298 /// The pixmap must deleted by user.
2299 
2301 {
2302  Pixmap_t pxmap = 0;
2303 
2304  if (!InitVisual()) {
2305  Warning("GetMask", "Visual not initiated");
2306  return pxmap;
2307  }
2308 
2309  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2310 
2311  if (!img) {
2312  Warning("GetMask", "No image");
2313  return pxmap;
2314  }
2315 
2316  UInt_t hh = img->height;
2317  UInt_t ow = img->width%8;
2318  UInt_t ww = img->width - ow + (ow ? 8 : 0);
2319 
2320  UInt_t bit = 0;
2321  int i = 0;
2322  UInt_t y = 0;
2323  UInt_t x = 0;
2324 
2325  char *bits = new char[ww*hh]; //an array of bits
2326 
2327  ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALPHA,
2328  0, 0, ww, 0, 0);
2329  if (!imdec) {
2330  delete [] bits;
2331  return 0;
2332  }
2333 
2334  for (y = 0; y < hh; y++) {
2335  imdec->decode_image_scanline(imdec);
2336  CARD32 *a = imdec->buffer.alpha;
2337 
2338  for (x = 0; x < ww; x++) {
2339  if (a[x]) {
2340  SETBIT(bits[i], bit);
2341  } else {
2342  CLRBIT(bits[i], bit);
2343  }
2344  bit++;
2345  if (bit == 8) {
2346  bit = 0;
2347  i++;
2348  }
2349  }
2350  }
2351 
2352  stop_image_decoding(&imdec);
2353  pxmap = gVirtualX->CreateBitmap(gVirtualX->GetDefaultRootWindow(), (const char *)bits,
2354  ww, hh);
2355  delete [] bits;
2356  return pxmap;
2357 }
2358 
2359 ////////////////////////////////////////////////////////////////////////////////
2360 /// Create image from pixmap.
2361 
2363 {
2364  if (!InitVisual()) {
2365  Warning("SetImage", "Visual not initiated");
2366  return;
2367  }
2368 
2369  DestroyImage();
2370  delete fScaledImage;
2371  fScaledImage = 0;
2372 
2373  Int_t xy;
2374  UInt_t w, h;
2375  gVirtualX->GetWindowSize(pxm, xy, xy, w, h);
2376 
2377  if (fName.IsNull()) fName.Form("img_%dx%d",w, h);
2378 
2379  static int x11 = -1;
2380  if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
2381 
2382  if (x11) { //use built-in optimized version
2383  fImage = picture2asimage(fgVisual, pxm, mask, 0, 0, w, h, kAllPlanes, 1, 0);
2384  } else {
2385  unsigned char *bits = gVirtualX->GetColorBits(pxm, 0, 0, w, h);
2386  if (!bits) { // error
2387  return;
2388  }
2389 
2390  // no mask
2391  if (!mask) {
2392  fImage = bitmap2asimage(bits, w, h, 0, 0);
2393  delete [] bits;
2394  return;
2395  }
2396  unsigned char *mask_bits = gVirtualX->GetColorBits(mask, 0, 0, w, h);
2397  fImage = bitmap2asimage(bits, w, h, 0, mask_bits);
2398  delete [] mask_bits;
2399  delete [] bits;
2400  }
2401 }
2402 
2403 ////////////////////////////////////////////////////////////////////////////////
2404 /// Return 2D array of machine dependent pixel values.
2405 
2407 {
2408  if (!fImage) {
2409  Warning("GetPixels", "Wrong Image");
2410  return 0;
2411  }
2412 
2413  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2414  ASImageDecoder *imdec;
2415 
2416  width = !width ? img->width : width;
2417  height = !height ? img->height : height;
2418 
2419  if (x < 0) {
2420  width -= x;
2421  x = 0 ;
2422  }
2423  if (y < 0) {
2424  height -= y;
2425  y = 0;
2426  }
2427 
2428  if ((x >= (int)img->width) || (y >= (int)img->height)) {
2429  return 0;
2430  }
2431 
2432  if ((int)(x + width) > (int)img->width) {
2433  width = img->width - x;
2434  }
2435 
2436  if ((int)(y + height) > (int)img->height) {
2437  height = img->height - y;
2438  }
2439 
2440  if ((imdec = start_image_decoding(0, fImage, SCL_DO_ALL, 0, y,
2441  img->width, height, 0)) == 0) {
2442  Warning("GetPixels", "Failed to create image decoder");
2443  return 0;
2444  }
2445 
2446  TArrayL *ret = new TArrayL(width * height);
2447  Int_t r = 0;
2448  Int_t g = 0;
2449  Int_t b = 0;
2450  Long_t p = 0;
2451 
2452  for (UInt_t k = 0; k < height; k++) {
2453  imdec->decode_image_scanline(imdec);
2454 
2455  for (UInt_t i = 0; i < width; ++i) {
2456  if ((r == (Int_t)imdec->buffer.red[i]) &&
2457  (g == (Int_t)imdec->buffer.green[i]) &&
2458  (b == (Int_t)imdec->buffer.blue[i])) {
2459  } else {
2460  r = (Int_t)imdec->buffer.red[i];
2461  g = (Int_t)imdec->buffer.green[i];
2462  b = (Int_t)imdec->buffer.blue[i];
2463  p = (Long_t)TColor::RGB2Pixel(r, g, b);
2464  }
2465  ret->AddAt(p, k*width + i);
2466  }
2467  }
2468 
2469  stop_image_decoding(&imdec);
2470  return ret;
2471 }
2472 
2473 ////////////////////////////////////////////////////////////////////////////////
2474 /// Return a pointer to internal array[width x height] of double values [0,1].
2475 /// This array is directly accessible. That allows to manipulate/change the
2476 /// image.
2477 
2479 {
2480  if (!fImage) {
2481  Warning("GetVecArray", "Bad Image");
2482  return 0;
2483  }
2484  if (fImage->alt.vector) {
2485  return fImage->alt.vector;
2486  }
2487  // vectorize
2488  return 0;
2489 }
2490 
2491 ////////////////////////////////////////////////////////////////////////////////
2492 /// In case of vectorized image return an associated array of doubles
2493 /// otherwise this method creates and returns a 2D array of doubles corresponding to palette.
2494 /// If palette is ZERO a color converted to double value [0, 1] according to formula
2495 /// ~~~ {.cpp}
2496 /// Double_t((r << 16) + (g << 8) + b)/0xFFFFFF
2497 /// ~~~
2498 /// The returned array must be deleted after usage.
2499 
2501 {
2502  if (!fImage) {
2503  Warning("GetArray", "Bad Image");
2504  return 0;
2505  }
2506 
2507  TArrayD *ret;
2508 
2509  if (fImage->alt.vector) {
2510  ret = new TArrayD(fImage->width*fImage->height, fImage->alt.vector);
2511  return ret;
2512  }
2513 
2514  ASImageDecoder *imdec;
2515 
2516  w = w ? w : fImage->width;
2517  h = h ? h : fImage->height;
2518 
2519  if ((fImage->width != w) || (fImage->height != h)) {
2520  Scale(w, h);
2521  }
2522 
2523  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
2524 
2525  if ((imdec = start_image_decoding(0, img, SCL_DO_ALL, 0, 0,
2526  img->width, 0, 0)) == 0) {
2527  Warning("GetArray", "Failed to create image decoder");
2528  return 0;
2529  }
2530 
2531  ret = new TArrayD(w * h);
2532  CARD32 r = 0;
2533  CARD32 g = 0;
2534  CARD32 b = 0;
2535  Int_t p = 0;
2536  Double_t v = 0;
2537 
2538  for (UInt_t k = 0; k < h; k++) {
2539  imdec->decode_image_scanline(imdec);
2540 
2541  for (UInt_t i = 0; i < w; ++i) {
2542  if ((r == imdec->buffer.red[i]) &&
2543  (g == imdec->buffer.green[i]) &&
2544  (b == imdec->buffer.blue[i])) {
2545  } else {
2546  r = imdec->buffer.red[i];
2547  g = imdec->buffer.green[i];
2548  b = imdec->buffer.blue[i];
2549  if (palette) p = palette->FindColor(r, g, b);
2550  }
2551  v = palette ? palette->fPoints[p] : Double_t((r << 16) + (g << 8) + b)/0xFFFFFF;
2552  ret->AddAt(v, (h-k-1)*w + i);
2553  }
2554  }
2555 
2556  stop_image_decoding(&imdec);
2557  return ret;
2558 }
2559 
2560 ////////////////////////////////////////////////////////////////////////////////
2561 /// Draw text of size (in pixels for TrueType fonts)
2562 /// at position (x, y) with color specified by hex string.
2563 ///
2564 /// - font_name: TrueType font's filename or X font spec or alias.
2565 /// 3D style of text is one of the following:
2566 /// * 0 plain 2D text,
2567 /// * 1 embossed,
2568 /// * 2 sunken,
2569 /// * 3 shade above,
2570 /// * 4 shade below,
2571 /// * 5 embossed thick,
2572 /// * 6 sunken thick.
2573 /// * 7 outline above,
2574 /// * 8 ouline below,
2575 /// * 9 full ouline.
2576 /// - fore_file specifies foreground texture of text.
2577 
2578 void TASImage::DrawText(Int_t x, Int_t y, const char *text, Int_t size,
2579  const char *color, const char *font_name,
2580  EText3DType type, const char *fore_file, Float_t angle)
2581 {
2582  UInt_t width=0, height=0;
2583  ARGB32 text_color = ARGB32_Black;
2584  ASImage *fore_im = 0;
2585  ASImage *text_im = 0;
2586  Bool_t ttfont = kFALSE;
2587 
2588  if (!InitVisual()) {
2589  Warning("DrawText", "Visual not initiated");
2590  return;
2591  }
2592 
2593  TString fn = font_name;
2594  fn.Strip();
2595  char *tmpstr = 0;
2596 
2597  if (fn.EndsWith(".pfa") || fn.EndsWith(".PFA") || fn.EndsWith(".pfb") || fn.EndsWith(".PFB") || fn.EndsWith(".ttf") || fn.EndsWith(".TTF") || fn.EndsWith(".otf") || fn.EndsWith(".OTF")) {
2598  tmpstr = gSystem->ExpandPathName(fn.Data());
2599  fn = tmpstr;
2600  ttfont = kTRUE;
2601  }
2602  delete [] tmpstr;
2603 
2604  if (color) {
2605  parse_argb_color(color, &text_color);
2606  }
2607 
2608  if (fImage && fImage->alt.argb32 && ttfont) {
2609  DrawTextTTF(x, y, text, size, text_color, fn.Data(), angle);
2610  return;
2611  }
2612 
2613  if (!gFontManager) {
2614  gFontManager = create_font_manager(fgVisual->dpy, 0, 0);
2615  }
2616 
2617  if (!gFontManager) {
2618  Warning("DrawText", "cannot create Font Manager");
2619  return;
2620  }
2621 
2622  ASFont *font = get_asfont(gFontManager, fn.Data(), 0, size, ASF_GuessWho);
2623 
2624  if (!font) {
2625  font = get_asfont(gFontManager, "fixed", 0, size, ASF_GuessWho);
2626  if (!font) {
2627  Warning("DrawText", "cannot find a font %s", font_name);
2628  return;
2629  }
2630  }
2631 
2632  get_text_size(text, font, (ASText3DType)type, &width, &height);
2633 
2634  if (!fImage) {
2635  fImage = create_asimage(width, height, 0);
2636  fill_asimage(fgVisual, fImage, 0, 0, width, height, 0xFFFFFFFF);
2637  }
2638 
2639  text_im = draw_text(text, font, (ASText3DType)type, 0);
2640 
2641  ASImage *rimg = fImage;
2642 
2643  if (fore_file) {
2644  ASImage *tmp = file2ASImage(fore_file, 0xFFFFFFFF, SCREEN_GAMMA, 0, 0);
2645  if (tmp) {
2646  if ((tmp->width != width) || (tmp->height != height)) {
2647  fore_im = tile_asimage(fgVisual, tmp, 0, 0, width, height, 0,
2648  ASA_ASImage, GetImageCompression(), GetImageQuality());
2649  }
2650  destroy_asimage(&tmp);
2651  } else {
2652  fore_im = tmp;
2653  }
2654  }
2655 
2656  if (fore_im) {
2657  move_asimage_channel(fore_im, IC_ALPHA, text_im, IC_ALPHA);
2658  destroy_asimage(&text_im);
2659  } else {
2660  fore_im = text_im ;
2661  }
2662 
2663  release_font(font);
2664 
2665  if (fore_im) {
2666  ASImage *rendered_im;
2667  ASImageLayer layers[2];
2668 
2669  init_image_layers(&(layers[0]), 2);
2670  fore_im->back_color = text_color;
2671  layers[0].im = rimg;
2672  layers[0].dst_x = 0;
2673  layers[0].dst_y = 0;
2674  layers[0].clip_width = rimg->width;
2675  layers[0].clip_height = rimg->height;
2676  layers[0].bevel = 0;
2677  layers[1].im = fore_im;
2678  layers[1].dst_x = x;
2679  layers[1].dst_y = y;
2680  layers[1].clip_width = fore_im->width;
2681  layers[1].clip_height = fore_im->height;
2682 
2683  rendered_im = merge_layers(fgVisual, &(layers[0]), 2, rimg->width, rimg->height,
2684  ASA_ASImage, GetImageCompression(), GetImageQuality());
2685 
2686  destroy_asimage(&fore_im);
2687  DestroyImage();
2688  fImage = rendered_im;
2689  UnZoom();
2690  }
2691 }
2692 
2693 ////////////////////////////////////////////////////////////////////////////////
2694 /// Merge two images.
2695 ///
2696 /// op is string which specifies overlay operation. Supported operations are:
2697 ///
2698 /// - add - color addition with saturation
2699 /// - alphablend - alpha-blending
2700 /// - allanon - color values averaging
2701 /// - colorize - hue and saturate bottom image same as top image
2702 /// - darken - use lowest color value from both images
2703 /// - diff - use absolute value of the color difference between two images
2704 /// - dissipate - randomly alpha-blend images
2705 /// - hue - hue bottom image same as top image
2706 /// - lighten - use highest color value from both images
2707 /// - overlay - some weird image overlaying(see GIMP)
2708 /// - saturate - saturate bottom image same as top image
2709 /// - screen - another weird image overlaying(see GIMP)
2710 /// - sub - color substraction with saturation
2711 /// - tint - tinting image with image
2712 /// - value - value bottom image same as top image
2713 
2714 void TASImage::Merge(const TImage *im, const char *op, Int_t x, Int_t y)
2715 {
2716  if (!im) return;
2717 
2718  if (!InitVisual()) {
2719  Warning("Merge", "Visual not initiated");
2720  return;
2721  }
2722 
2723  ASImage *rendered_im;
2724  ASImageLayer layers[2];
2725 
2726  init_image_layers(&(layers[0]), 2);
2727  layers[0].im = fImage;
2728  layers[0].dst_x = 0;
2729  layers[0].dst_y = 0;
2730  layers[0].clip_width = fImage->width;
2731  layers[0].clip_height = fImage->height;
2732  layers[0].bevel = 0;
2733  layers[1].im = ((TASImage*)im)->fImage;
2734  layers[1].dst_x = x;
2735  layers[1].dst_y = y;
2736  layers[1].clip_width = im->GetWidth();
2737  layers[1].clip_height = im->GetHeight();
2738  layers[1].merge_scanlines = blend_scanlines_name2func(op ? op : "add");
2739 
2740  rendered_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
2741  ASA_ASImage, GetImageCompression(), GetImageQuality());
2742 
2743  DestroyImage();
2744  fImage = rendered_im;
2745  UnZoom();
2746 }
2747 
2748 ////////////////////////////////////////////////////////////////////////////////
2749 /// Perform Gaussian blur of the image (useful for drop shadows).
2750 /// - hr - horizontal radius of the blur
2751 /// - vr - vertical radius of the blur
2752 
2754 {
2755  if (!InitVisual()) {
2756  Warning("Blur", "Visual not initiated");
2757  return;
2758  }
2759 
2760  if (!fImage) {
2761  fImage = create_asimage(100, 100, 0);
2762 
2763  if (!fImage) {
2764  Warning("Blur", "Failed to create image");
2765  return;
2766  }
2767 
2768  fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2769  }
2770 
2771  ASImage *rendered_im = blur_asimage_gauss(fgVisual, fImage, hr > 0 ? hr : 3,
2772  vr > 0 ? vr : 3, SCL_DO_ALL,
2773  ASA_ASImage, GetImageCompression(), GetImageQuality());
2774  DestroyImage();
2775  fImage = rendered_im;
2776  UnZoom();
2777 }
2778 
2779 ////////////////////////////////////////////////////////////////////////////////
2780 /// Clone image.
2781 
2782 TObject *TASImage::Clone(const char *newname) const
2783 {
2784  if (!InitVisual() || !fImage) {
2785  Warning("Clone", "Image not initiated");
2786  return 0;
2787  }
2788 
2789  TASImage *im = (TASImage*)TImage::Create();
2790 
2791  if (!im) {
2792  Warning("Clone", "Failed to create image");
2793  return 0;
2794  }
2795 
2796  im->SetName(newname);
2797 
2798  im->fImage = clone_asimage(fImage, SCL_DO_ALL);
2799  im->fMaxValue = fMaxValue;
2800  im->fMinValue = fMinValue;
2801  im->fZoomOffX = fZoomOffX;
2802  im->fZoomOffY = fZoomOffY;
2803  im->fZoomWidth = fZoomWidth;
2804  im->fZoomHeight = fZoomHeight;
2805  im->fZoomUpdate = fZoomUpdate;
2807 
2808  if (fImage->alt.argb32) {
2809  UInt_t sz = fImage->width * fImage->height;
2810  im->fImage->alt.argb32 = (ARGB32*)safemalloc(sz*sizeof(ARGB32));
2811  memcpy(im->fImage->alt.argb32, fImage->alt.argb32, sz * sizeof(ARGB32));
2812  }
2813 
2814  return im;
2815 }
2816 
2817 ////////////////////////////////////////////////////////////////////////////////
2818 /// Reduce color-depth of an image and fills vector of "scientific data"
2819 /// [0...1]
2820 ///
2821 /// Colors are reduced by allocating color cells to most used colors first,
2822 /// and then approximating other colors with those allocated.
2823 ///
2824 /// \param[in] max_colors - maximum size of the colormap.
2825 /// \param[in] dither - number of bits to strip off the color data ( 0...7 )
2826 /// \param[in] opaque_threshold - alpha channel threshold at which pixel should be treated as opaque
2827 
2828 Double_t *TASImage::Vectorize(UInt_t max_colors, UInt_t dither, Int_t opaque_threshold)
2829 {
2830  if (!InitVisual()) {
2831  Warning("Vectorize", "Visual not initiated");
2832  return 0;
2833  }
2834 
2835  if (!fImage) {
2836  fImage = create_asimage(100, 100, 0);
2837 
2838  if (!fImage) {
2839  Warning("Vectorize", "Failed to create image");
2840  return 0;
2841  }
2842 
2843  fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2844  }
2845 
2846  ASColormap cmap;
2847  int *res;
2848  UInt_t r=0, g=0, b=0;
2849 
2850  dither = dither > 7 ? 7 : dither;
2851 
2852  res = colormap_asimage(fImage, &cmap, max_colors, dither, opaque_threshold);
2853 
2854  Double_t *vec = new Double_t[fImage->height*fImage->width];
2855  UInt_t v;
2856  Double_t tmp;
2857  fMinValue = 2;
2858  fMaxValue = -1;
2859 
2860  for (UInt_t y = 0; y < fImage->height; y++) {
2861  for (UInt_t x = 0; x < fImage->width; x++) {
2862  int i = y*fImage->width + x;
2863  if (res) {
2864  g = INDEX_SHIFT_GREEN(cmap.entries[res[i]].green);
2865  b = INDEX_SHIFT_BLUE(cmap.entries[res[i]].blue);
2866  r = INDEX_SHIFT_RED(cmap.entries[res[i]].red);
2867  }
2868  v = MAKE_INDEXED_COLOR24(r,g,b);
2869  v = (v>>12)&0x0FFF;
2870  tmp = Double_t(v)/0x0FFF;
2871  vec[(fImage->height - y - 1)*fImage->width + x] = tmp;
2872  if (fMinValue > tmp) fMinValue = tmp;
2873  if (fMaxValue < tmp) fMaxValue = tmp;
2874  }
2875  }
2876  TImagePalette *pal = new TImagePalette(cmap.count);
2877 
2878  for (UInt_t j = 0; j < cmap.count; j++) {
2879  g = INDEX_SHIFT_GREEN(cmap.entries[j].green);
2880  b = INDEX_SHIFT_BLUE(cmap.entries[j].blue);
2881  r = INDEX_SHIFT_RED(cmap.entries[j].red);
2882  v = MAKE_INDEXED_COLOR24(r,g,b);
2883 
2884  v = (v>>12) & 0x0FFF;
2885  pal->fPoints[j] = Double_t(v)/0x0FFF;
2886 
2887  pal->fColorRed[j] = cmap.entries[j].red << 8;
2888  pal->fColorGreen[j] = cmap.entries[j].green << 8;
2889  pal->fColorBlue[j] = cmap.entries[j].blue << 8;
2890  pal->fColorAlpha[j] = 0xFF00;
2891  }
2892 
2893  destroy_colormap(&cmap, kTRUE);
2894 
2895  fPalette = *pal;
2896  fImage->alt.vector = vec;
2897  UnZoom();
2898  if (res) delete res;
2899  return (Double_t*)fImage->alt.vector;
2900 }
2901 
2902 ////////////////////////////////////////////////////////////////////////////////
2903 /// This function will tile original image to specified size with offsets
2904 /// requested, and then it will go though it and adjust hue, saturation and
2905 /// value of those pixels that have specific hue, set by affected_hue/
2906 /// affected_radius parameters. When affected_radius is greater then 180
2907 /// entire image will be adjusted. Note that since grayscale colors have
2908 /// no hue - the will not get adjusted. Only saturation and value will be
2909 /// adjusted in gray pixels.
2910 ///
2911 /// Hue is measured as an angle on a 360 degree circle, The following is
2912 /// relationship of hue values to regular color names :
2913 /// - red - 0
2914 /// - yellow - 60
2915 /// - green - 120
2916 /// - cyan - 180
2917 /// - blue - 240
2918 /// - magenta - 300
2919 /// - red - 360
2920 ///
2921 /// All the hue values in parameters will be adjusted to fall within 0-360 range.
2922 ///
2923 /// \param[in] hue hue in degrees in range 0-360. This allows to limit
2924 /// impact of color adjustment to affect only limited range of hues.
2925 ///
2926 /// \param[in] radius value in degrees to be used in order to
2927 /// calculate the range of affected hues. Range is determined by
2928 /// substracting and adding this value from/to affected_hue.
2929 ///
2930 /// \param[in] H value by which to change hues in affected range.
2931 /// \param[in] S value by which to change saturation of the pixels in affected hue range.
2932 /// \param[in] V value by which to change Value(brightness) of pixels in affected hue range.
2933 ///
2934 /// \param[in] x,y position on infinite surface tiled with original image, of the
2935 /// left-top corner of the area to be used for new image.
2936 ///
2937 /// \param[in] width, height size of the area of the original image to be used for new image.
2938 /// Default is current width, height of the image.
2939 
2940 void TASImage::HSV(UInt_t hue, UInt_t radius, Int_t H, Int_t S, Int_t V,
2941  Int_t x, Int_t y, UInt_t width, UInt_t height)
2942 {
2943  if (!InitVisual()) {
2944  Warning("HSV", "Visual not initiated");
2945  return;
2946  }
2947 
2948  if (!fImage) {
2949  fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
2950 
2951  if (!fImage) {
2952  Warning("HSV", "Failed to create image");
2953  return;
2954  }
2955 
2956  x = 0;
2957  y = 0;
2958  fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2959  }
2960 
2961  width = !width ? fImage->width : width;
2962  height = !height ? fImage->height : height;
2963 
2964  ASImage *rendered_im = 0;
2965 
2966  if (H || S || V) {
2967  rendered_im = adjust_asimage_hsv(fgVisual, fImage, x, y, width, height,
2968  hue, radius, H, S, V, ASA_ASImage, 100,
2969  ASIMAGE_QUALITY_TOP);
2970  }
2971  if (!rendered_im) {
2972  Warning("HSV", "Failed to create rendered image");
2973  return;
2974  }
2975 
2976  DestroyImage();
2977  fImage = rendered_im;
2978  UnZoom();
2979 }
2980 
2981 ////////////////////////////////////////////////////////////////////////////////
2982 /// Render multipoint gradient inside rectangle of size (width, height)
2983 /// at position (x,y) within the existing image.
2984 ///
2985 /// \param[in] angle Given in degrees. Default is 0. This is the
2986 /// direction of the gradient. Currently the only supported
2987 /// values are 0, 45, 90, 135, 180, 225, 270, 315. 0 means left
2988 /// to right, 90 means top to bottom, etc.
2989 ///
2990 /// \param[in] colors Whitespace-separated list of colors. At least two
2991 /// colors are required. Each color in this list will be visited
2992 /// in turn, at the intervals given by the offsets attribute.
2993 ///
2994 /// \param[in] offsets Whitespace-separated list of floating point values
2995 /// ranging from 0.0 to 1.0. The colors from the colors attribute
2996 /// are given these offsets, and the final gradient is rendered
2997 /// from the combination of the two. If both colors and offsets
2998 /// are given but the number of colors and offsets do not match,
2999 /// the minimum of the two will be used, and the other will be
3000 /// truncated to match. If offsets are not given, a smooth
3001 /// stepping from 0.0 to 1.0 will be used.
3002 
3003 void TASImage::Gradient(UInt_t angle, const char *colors, const char *offsets,
3004  Int_t x, Int_t y, UInt_t width, UInt_t height)
3005 {
3006  if (!InitVisual()) {
3007  Warning("Gradient", "Visual not initiated");
3008  return;
3009  }
3010 
3011  ASImage *rendered_im = 0;
3012  ASGradient gradient;
3013 
3014  int reverse = 0, npoints1 = 0, npoints2 = 0;
3015  char *p;
3016  char *pb;
3017  char ch;
3018  TString str = colors;
3019  TString col;
3020 
3021  if ((angle > 2 * 180 * 15 / 16) || (angle < 2 * 180 * 1 / 16)) {
3022  gradient.type = GRADIENT_Left2Right;
3023  } else if (angle < 2 * 180 * 3 / 16) {
3024  gradient.type = GRADIENT_TopLeft2BottomRight;
3025  } else if (angle < 2 * 180 * 5 / 16) {
3026  gradient.type = GRADIENT_Top2Bottom;
3027  } else if (angle < 2 * 180 * 7 / 16) {
3028  gradient.type = GRADIENT_BottomLeft2TopRight; reverse = 1;
3029  } else if (angle < 2 * 180 * 9 / 16) {
3030  gradient.type = GRADIENT_Left2Right; reverse = 1;
3031  } else if (angle < 2 * 180 * 11 / 16) {
3032  gradient.type = GRADIENT_TopLeft2BottomRight; reverse = 1;
3033  } else if (angle < 2 * 180 * 13 / 16) {
3034  gradient.type = GRADIENT_Top2Bottom; reverse = 1;
3035  } else {
3036  gradient.type = GRADIENT_BottomLeft2TopRight;
3037  }
3038 
3039  for (p = (char*)colors; isspace((int)*p); p++) { }
3040 
3041  for (npoints1 = 0; *p; npoints1++) {
3042  if (*p) {
3043  for ( ; *p && !isspace((int)*p); p++) { }
3044  }
3045  for ( ; isspace((int)*p); p++) { }
3046  }
3047  if (offsets) {
3048  for (p = (char*)offsets; isspace((int)*p); p++) { }
3049 
3050  for (npoints2 = 0; *p; npoints2++) {
3051  if (*p) {
3052  for ( ; *p && !isspace((int)*p); p++) { }
3053  }
3054  for ( ; isspace((int)*p); p++) { }
3055  }
3056  }
3057  if (npoints1 > 1) {
3058  int i;
3059  if (offsets && (npoints1 > npoints2)) npoints1 = npoints2;
3060 
3061  if (!width) {
3062  width = fImage ? fImage->width : 20;
3063  }
3064  if (!height) {
3065  height = fImage ? fImage->height : 20;
3066  }
3067 
3068  gradient.color = new ARGB32[npoints1];
3069  gradient.offset = new double[npoints1];
3070 
3071  for (p = (char*)colors; isspace((int)*p); p++) { }
3072 
3073  for (npoints1 = 0; *p; ) {
3074  pb = p;
3075 
3076  if (*p) {
3077  for ( ; *p && !isspace((int)*p); p++) { }
3078  }
3079  for ( ; isspace((int)*p); p++) { }
3080 
3081  col = str(pb - colors, p - pb);
3082 
3083  if (parse_argb_color(col.Data(), gradient.color + npoints1) != col) {
3084  npoints1++;
3085  } else {
3086  Warning("Gradient", "Failed to parse color [%s] - defaulting to black", pb);
3087  }
3088  }
3089 
3090  if (offsets) {
3091  for (p = (char*)offsets; isspace((int)*p); p++) { }
3092 
3093  for (npoints2 = 0; *p; ) {
3094  pb = p;
3095 
3096  if (*p) {
3097  for ( ; *p && !isspace((int)*p); p++) { }
3098  }
3099  ch = *p; *p = '\0';
3100  gradient.offset[npoints2] = strtod(pb, &pb);
3101 
3102  if (pb == p) npoints2++;
3103  *p = ch;
3104  for ( ; isspace((int)*p); p++) { }
3105  }
3106  } else {
3107  for (npoints2 = 0; npoints2 < npoints1; npoints2++) {
3108  gradient.offset[npoints2] = (double)npoints2 / (npoints1 - 1);
3109  }
3110  }
3111  gradient.npoints = npoints1;
3112 
3113  if (npoints2 && (gradient.npoints > npoints2)) {
3114  gradient.npoints = npoints2;
3115  }
3116  if (reverse) {
3117  for (i = 0; i < gradient.npoints/2; i++) {
3118  int i2 = gradient.npoints - 1 - i;
3119  ARGB32 c = gradient.color[i];
3120  double o = gradient.offset[i];
3121  gradient.color[i] = gradient.color[i2];
3122  gradient.color[i2] = c;
3123  gradient.offset[i] = gradient.offset[i2];
3124  gradient.offset[i2] = o;
3125  }
3126  for (i = 0; i < gradient.npoints; i++) {
3127  gradient.offset[i] = 1.0 - gradient.offset[i];
3128  }
3129  }
3130  rendered_im = make_gradient(fgVisual, &gradient, width, height, SCL_DO_ALL,
3131  ASA_ASImage, GetImageCompression(), GetImageQuality());
3132 
3133  delete [] gradient.color;
3134  delete [] gradient.offset;
3135  }
3136 
3137  if (!rendered_im) { // error
3138  Warning("Gradient", "Failed to create gradient image");
3139  return;
3140  }
3141 
3142  if (!fImage) {
3143  fImage = rendered_im;
3144  return;
3145  }
3146 
3147  ASImageLayer layers[2];
3148 
3149  init_image_layers(&(layers[0]), 2);
3150  layers[0].im = fImage;
3151  layers[0].dst_x = 0;
3152  layers[0].dst_y = 0;
3153  layers[0].clip_width = fImage->width;
3154  layers[0].clip_height = fImage->height;
3155  layers[0].bevel = 0;
3156  layers[1].im = rendered_im;
3157  layers[1].dst_x = x;
3158  layers[1].dst_y = y;
3159  layers[1].clip_width = width;
3160  layers[1].clip_height = height;
3161  layers[1].merge_scanlines = alphablend_scanlines;
3162 
3163  ASImage *merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
3164  ASA_ASImage, GetImageCompression(), GetImageQuality());
3165  if (!merge_im) {
3166  Warning("Gradient", "Failed to create merged image");
3167  return;
3168  }
3169 
3170  destroy_asimage(&rendered_im);
3171  DestroyImage();
3172  fImage = merge_im;
3173  UnZoom();
3174 }
3175 
3176 ////////////////////////////////////////////////////////////////////////////////
3177 /// Make component hilite.
3178 /// (used internally)
3179 
3180 static CARD8 MakeComponentHilite(int cmp)
3181 {
3182  if (cmp < 51) {
3183  cmp = 51;
3184  }
3185  cmp = (cmp * 12) / 10;
3186 
3187  return (cmp > 255) ? 255 : cmp;
3188 }
3189 
3190 ////////////////////////////////////////////////////////////////////////////////
3191 /// Calculate highlite color.
3192 /// (used internally)
3193 
3194 static ARGB32 GetHilite(ARGB32 background)
3195 {
3196  return ((MakeComponentHilite((background>>24) & 0x000000FF) << 24) & 0xFF000000) |
3197  ((MakeComponentHilite((background & 0x00FF0000) >> 16) << 16) & 0x00FF0000) |
3198  ((MakeComponentHilite((background & 0x0000FF00) >> 8) << 8) & 0x0000FF00) |
3199  ((MakeComponentHilite((background & 0x000000FF))) & 0x000000FF);
3200 }
3201 
3202 ////////////////////////////////////////////////////////////////////////////////
3203 /// Calculate shadow color.
3204 /// (used internally)
3205 
3206 static ARGB32 GetShadow(ARGB32 background)
3207 {
3208  return (background >> 1) & 0x7F7F7F7F;
3209 }
3210 
3211 ////////////////////////////////////////////////////////////////////////////////
3212 /// Get average.
3213 /// (used internally)
3214 
3215 static ARGB32 GetAverage(ARGB32 foreground, ARGB32 background)
3216 {
3217  CARD16 a, r, g, b;
3218 
3219  a = ARGB32_ALPHA8(foreground) + ARGB32_ALPHA8(background);
3220  a = (a<<3)/10;
3221  r = ARGB32_RED8(foreground) + ARGB32_RED8(background);
3222  r = (r<<3)/10;
3223  g = ARGB32_GREEN8(foreground) + ARGB32_GREEN8(background);
3224  g = (g<<3)/10;
3225  b = ARGB32_BLUE8(foreground) + ARGB32_BLUE8(background);
3226  b = (b<<3)/10;
3227 
3228  return MAKE_ARGB32(a, r, g, b);
3229 }
3230 
3231 
3232 ////////////////////////////////////////////////////////////////////////////////
3233 /// Bevel is used to create 3D effect while drawing buttons, or any other
3234 /// image that needs to be framed. Bevel is drawn using 2 primary colors:
3235 /// one for top and left sides - hi color, and another for bottom and
3236 /// right sides - low color. Bevel can be drawn over existing image or
3237 /// as newly created, as it is shown in code below:
3238 /// ~~~ {.cpp}
3239 /// TImage *img = TImage::Create();
3240 /// img->Bevel(0, 0, 400, 300, "#dddddd", "#000000", 3);
3241 /// ~~~
3242 
3243 void TASImage::Bevel(Int_t x, Int_t y, UInt_t width, UInt_t height,
3244  const char *hi_color, const char *lo_color, UShort_t thick,
3245  Bool_t reverse)
3246 {
3247  if (!InitVisual()) {
3248  Warning("Bevel", "Visual not initiated");
3249  return;
3250  }
3251 
3252  ASImageBevel bevel;
3253  bevel.type = 0;
3254 
3255  ARGB32 hi=ARGB32_White, lo=ARGB32_White;
3256  parse_argb_color(hi_color, &hi);
3257  parse_argb_color(lo_color, &lo);
3258 
3259  if (reverse) {
3260  bevel.lo_color = hi;
3261  bevel.lolo_color = GetHilite(hi);
3262  bevel.hi_color = lo;
3263  bevel.hihi_color = GetShadow(lo);
3264  } else {
3265  bevel.hi_color = hi;
3266  bevel.hihi_color = GetHilite(hi);
3267  bevel.lo_color = lo;
3268  bevel.lolo_color = GetShadow(lo);
3269  }
3270  bevel.hilo_color = GetAverage(hi, lo);
3271 
3272  int extra_hilite = 2;
3273  bevel.left_outline = bevel.top_outline = bevel.right_outline = bevel.bottom_outline = thick;
3274  bevel.left_inline = bevel.top_inline = bevel.right_inline = bevel.bottom_inline = extra_hilite + 1;
3275 
3276  if (bevel.top_outline > 1) {
3277  bevel.top_inline += bevel.top_outline - 1;
3278  }
3279 
3280  if (bevel.left_outline > 1) {
3281  bevel.left_inline += bevel.left_outline - 1;
3282  }
3283 
3284  if (bevel.right_outline > 1) {
3285  bevel.right_inline += bevel.right_outline - 1;
3286  }
3287 
3288  if (bevel.bottom_outline > 1) {
3289  bevel.bottom_inline += bevel.bottom_outline - 1;
3290  }
3291 
3292  ASImage *merge_im;
3293  ARGB32 fill = ((hi>>24) != 0xff) || ((lo>>24) != 0xff) ? bevel.hilo_color : (bevel.hilo_color | 0xff000000);
3294 
3295  if (!fImage) {
3296  fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
3297 
3298  if (!fImage) {
3299  Warning("Bevel", "Failed to create image");
3300  return;
3301  }
3302 
3303  x = 0;
3304  y = 0;
3305  fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, fill);
3306  }
3307 
3308  width = !width ? fImage->width : width;
3309  height = !height ? fImage->height : height;
3310 
3311  ASImageLayer layers[2];
3312  init_image_layers(&(layers[0]), 2);
3313 
3314  layers[0].im = fImage;
3315  layers[0].dst_x = 0;
3316  layers[0].dst_y = 0;
3317  layers[0].clip_width = fImage->width;
3318  layers[0].clip_height = fImage->height;
3319  layers[0].bevel = 0;
3320 
3321  UInt_t w = width - (bevel.left_outline + bevel.right_outline);
3322  UInt_t h = height - (bevel.top_outline + bevel.bottom_outline);
3323  ASImage *bevel_im = create_asimage(w, h, 0);
3324 
3325  if (!bevel_im) {
3326  Warning("Bevel", "Failed to create bevel image");
3327  return;
3328  }
3329 
3330  layers[1].im = bevel_im;
3331  fill_asimage(fgVisual, bevel_im, 0, 0, w, h, fill);
3332 
3333  layers[1].dst_x = x;
3334  layers[1].dst_y = y;
3335  layers[1].clip_width = width;
3336  layers[1].clip_height = height;
3337  layers[1].bevel = &bevel;
3338  layers[1].merge_scanlines = alphablend_scanlines;
3339 
3340  merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
3341  ASA_ASImage, GetImageCompression(), GetImageQuality());
3342  destroy_asimage(&bevel_im);
3343 
3344  if (!merge_im) {
3345  Warning("Bevel", "Failed to image");
3346  return;
3347  }
3348 
3349  DestroyImage();
3350  fImage = merge_im;
3351  UnZoom();
3352 }
3353 
3354 
3355 ////////////////////////////////////////////////////////////////////////////////
3356 /// Enlarge image, padding it with specified color on each side in
3357 /// accordance with requested geometry.
3358 
3359 void TASImage::Pad(const char *col, UInt_t l, UInt_t r, UInt_t t, UInt_t b)
3360 {
3361  Int_t x, y;
3362  UInt_t w, h;
3363 
3364  if (!InitVisual()) {
3365  Warning("Pad", "Visual not initiated");
3366  return;
3367  }
3368 
3369  if (!fImage) {
3370  fImage = create_asimage(100, 100, 0);
3371 
3372  if (!fImage) {
3373  Warning("Pad", "Failed to create image");
3374  return;
3375  }
3376 
3377  x = 0;
3378  y = 0;
3379  fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
3380  }
3381 
3382  ARGB32 color = ARGB32_White;
3383  parse_argb_color(col, &color);
3384 
3385  x = l;
3386  y = t;
3387  w = l + fImage->width + r;
3388  h = t + fImage->height + b;
3389 
3390  ASImage *img = pad_asimage(fgVisual, fImage, x, y, w, h, color,
3391  ASA_ASImage, GetImageCompression(), GetImageQuality());
3392 
3393  if (!img) {
3394  Warning("Pad", "Failed to create output image");
3395  return;
3396  }
3397 
3398  DestroyImage();
3399  fImage = img;
3400  UnZoom();
3402 }
3403 
3404 
3405 ////////////////////////////////////////////////////////////////////////////////
3406 /// Crop an image.
3407 
3408 void TASImage::Crop(Int_t x, Int_t y, UInt_t width, UInt_t height)
3409 {
3410  if (!InitVisual()) {
3411  Warning("Crop", "Visual not initiated");
3412  return;
3413  }
3414 
3415  if (!fImage) {
3416  Warning("Crop", "No image");
3417  return;
3418  }
3419 
3420  x = x < 0 ? 0 : x;
3421  y = y < 0 ? 0 : y;
3422 
3423  width = x + width > fImage->width ? fImage->width - x : width;
3424  height = y + height > fImage->height ? fImage->height - y : height;
3425 
3426  if ((width == fImage->width) && (height == fImage->height)) {
3427  Warning("Crop", "input size larger than image");
3428  return;
3429  }
3430  ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
3431  x, y, width, height, 0);
3432 
3433  if (!imdec) {
3434  Warning("Crop", "Failed to start image decoding");
3435  return;
3436  }
3437 
3438  ASImage *img = create_asimage(width, height, 0);
3439 
3440  if (!img) {
3441  delete [] imdec;
3442  Warning("Crop", "Failed to create image");
3443  return;
3444  }
3445 
3446  ASImageOutput *imout = start_image_output(fgVisual, img, ASA_ASImage,
3448 
3449  if (!imout) {
3450  Warning("Crop", "Failed to start image output");
3451  destroy_asimage(&img);
3452  if (imdec) delete [] imdec;
3453  return;
3454  }
3455 
3456 #ifdef HAVE_MMX
3457  mmx_init();
3458 #endif
3459 
3460  for (UInt_t i = 0; i < height; i++) {
3461  imdec->decode_image_scanline(imdec);
3462  imout->output_image_scanline(imout, &(imdec->buffer), 1);
3463  }
3464 
3465  stop_image_decoding(&imdec);
3466  stop_image_output(&imout);
3467 
3468 #ifdef HAVE_MMX
3469  mmx_off();
3470 #endif
3471 
3472  DestroyImage();
3473  fImage = img;
3474  UnZoom();
3476 }
3477 
3478 ////////////////////////////////////////////////////////////////////////////////
3479 /// Append image.
3480 ///
3481 /// option:
3482 /// - "+" - appends to the right side
3483 /// - "/" - appends to the bottom
3484 
3485 void TASImage::Append(const TImage *im, const char *option, const char *color )
3486 {
3487  if (!im) return;
3488 
3489  if (!InitVisual()) {
3490  Warning("Append", "Visual not initiated");
3491  return;
3492  }
3493 
3494  if (!fImage) {
3495  fImage = ((TASImage*)im)->fImage;
3496  return;
3497  }
3498 
3499  TString opt = option;
3500  opt.Strip();
3501 
3502  UInt_t width = fImage->width;
3503  UInt_t height = fImage->height;
3504 
3505  if (opt == "+") {
3506  Pad(color, 0, im->GetWidth(), 0, 0);
3507  Merge(im, "alphablend", width, 0);
3508  } else if (opt == "/") {
3509  Pad(color, 0, 0, 0, im->GetHeight());
3510  Merge(im, "alphablend", 0, height);
3511  } else {
3512  return;
3513  }
3514 
3515  UnZoom();
3516 }
3517 
3518 ////////////////////////////////////////////////////////////////////////////////
3519 /// BeginPaint initializes internal array[width x height] of ARGB32 pixel
3520 /// values.
3521 ///
3522 /// That provides quick access to image during paint operations.
3523 /// To RLE compress image one needs to call EndPaint method when painting
3524 /// is over.
3525 
3527 {
3528  if (!InitVisual()) {
3529  Warning("BeginPaint", "Visual not initiated");
3530  return;
3531  }
3532 
3533  if (!fImage) {
3534  return;
3535  }
3536 
3537  fPaintMode = mode;
3538 
3539  if (!fPaintMode || fImage->alt.argb32) {
3540  return;
3541  }
3542 
3543  ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
3544  0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
3545 
3546  if (!img) {
3547  Warning("BeginPaint", "Failed to create image");
3548  return;
3549  }
3550 
3551  DestroyImage();
3552  fImage = img;
3553 }
3554 
3555 ////////////////////////////////////////////////////////////////////////////////
3556 /// EndPaint does internal RLE compression of image data.
3557 
3559 {
3560  if (!fImage) {
3561  Warning("EndPaint", "no image");
3562  return;
3563  }
3564 
3565  if (!fImage->alt.argb32) return;
3566 
3567  ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
3568  0, ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT);
3569 
3570  if (!img) {
3571  Warning("EndPaint", "Failed to create image");
3572  return;
3573  }
3574 
3575  fPaintMode = kFALSE;
3576  DestroyImage();
3577  fImage = img;
3578 }
3579 
3580 ////////////////////////////////////////////////////////////////////////////////
3581 /// Return a pointer to internal array[width x height] of ARGB32 values
3582 /// This array is directly accessible. That allows to manipulate/change the
3583 /// image.
3584 
3586 {
3587  if (!fImage) {
3588  Warning("GetArgbArray", "no image");
3589  return 0;
3590  }
3591 
3592  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3593  if (!img) return 0;
3594 
3595  if (!img->alt.argb32) {
3596  if (fScaledImage) {
3598  img = fScaledImage->fImage;
3599  } else {
3600  BeginPaint();
3601  img = fImage;
3602  }
3603  }
3604 
3605  return (UInt_t *)img->alt.argb32;
3606 }
3607 
3608 ////////////////////////////////////////////////////////////////////////////////
3609 /// Return a pointer to an array[width x height] of RGBA32 values.
3610 /// This array is created from internal ARGB32 array,
3611 /// must be deleted after usage.
3612 
3614 {
3615  if (!fImage) {
3616  Warning("GetRgbaArray", "no image");
3617  return 0;
3618  }
3619 
3620  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3621  if (!img) return 0;
3622 
3623  if (!img->alt.argb32) {
3624  if (fScaledImage) {
3626  img = fScaledImage->fImage;
3627  } else {
3628  BeginPaint();
3629  img = fImage;
3630  }
3631  }
3632 
3633  UInt_t i, j;
3634  Int_t y = 0;
3635  Int_t idx = 0;
3636  UInt_t a, rgb, rgba, argb;
3637  y = 0;
3638 
3639  UInt_t *ret = new UInt_t[img->width*img->height];
3640 
3641  for (i = 0; i < img->height; i++) {
3642  for (j = 0; j < img->width; j++) {
3643  idx = Idx(y + j);
3644  argb = img->alt.argb32[idx];
3645  a = argb >> 24;
3646  rgb = argb & 0x00ffffff;
3647  rgba = (rgb << 8) + a;
3648  ret[idx] = rgba;
3649  }
3650  y += img->width;
3651  }
3652 
3653  return ret;
3654 }
3655 
3656 ////////////////////////////////////////////////////////////////////////////////
3657 /// Return a pointer to scan-line.
3658 
3660 {
3661  if (!fImage) {
3662  Warning("GetScanline", "no image");
3663  return 0;
3664  }
3665 
3666  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3667  CARD32 *ret = new CARD32[img->width];
3668 
3669  ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALL,
3670  0, y, img->width, 1, 0);
3671 
3672  if (!imdec) {
3673  delete [] ret;
3674  Warning("GetScanline", "Failed to start image decoding");
3675  return 0;
3676  }
3677 
3678 #ifdef HAVE_MMX
3679  mmx_init();
3680 #endif
3681 
3682  imdec->decode_image_scanline(imdec);
3683  memcpy(imdec->buffer.buffer, ret, img->width*sizeof(CARD32));
3684  stop_image_decoding(&imdec);
3685 
3686 #ifdef HAVE_MMX
3687  mmx_off();
3688 #endif
3689 
3690  return (UInt_t*)ret;
3691 }
3692 
3693 
3694 //______________________________________________________________________________
3695 //
3696 // Vector graphics
3697 // a couple of macros which can be "assembler accelerated"
3698 
3699 #if defined(R__GNU) && defined(__i386__) && !defined(__sun)
3700 #define _MEMSET_(dst, lng, val) __asm__("movl %0,%%eax \n"\
3701  "movl %1,%%edi \n" \
3702  "movl %2,%%ecx \n" \
3703  "cld \n" \
3704  "rep \n" \
3705  "stosl \n" \
3706  : /* no output registers */ \
3707  :"g" (val), "g" (dst), "g" (lng) \
3708  :"eax","edi","ecx" \
3709  )
3710 
3711 #else
3712  #define _MEMSET_(dst, lng, val) do {\
3713  for( UInt_t j=0; j < lng; j++) *((dst)+j) = val; } while (0)
3714 
3715 #endif
3716 
3717 #define FillSpansInternal(npt, ppt, widths, color) do {\
3718  UInt_t yy = ppt[0].fY*fImage->width;\
3719  for (UInt_t i = 0; i < npt; i++) {\
3720  _MEMSET_(&fImage->alt.argb32[Idx(yy + ppt[i].fX)], widths[i], color);\
3721  yy += ((i+1 < npt) && (ppt[i].fY != ppt[i+1].fY) ? fImage->width : 0);\
3722  }\
3723 } while (0)
3724 
3725 ////////////////////////////////////////////////////////////////////////////////
3726 /// Fill rectangle of size (width, height) at position (x,y)
3727 /// within the existing image with specified color.
3728 
3730 {
3731 
3732  if (!InitVisual()) {
3733  Warning("FillRectangle", "Visual not initiated");
3734  return;
3735  }
3736 
3737  if (!fImage) {
3738  Warning("FillRectangle", "no image");
3739  return;
3740  }
3741 
3742  if (!fImage->alt.argb32) {
3743  BeginPaint();
3744  }
3745 
3746  if (!fImage->alt.argb32) {
3747  Warning("FillRectangle", "Failed to get pixel array");
3748  return;
3749  }
3750 
3751  ARGB32 color = (ARGB32)col;
3752 
3753  if (width == 0) width = 1;
3754  if (height == 0) height = 1;
3755 
3756  if (x < 0) {
3757  width += x;
3758  x = 0;
3759  }
3760  if (y < 0) {
3761  height += y;
3762  y = 0;
3763  }
3764 
3765  Bool_t has_alpha = (color & 0xff000000) != 0xff000000;
3766 
3767  x = x > (int)fImage->width ? (Int_t)fImage->width : x;
3768  y = y > (int)fImage->height ? (Int_t)fImage->height : y;
3769 
3770  width = x + width > fImage->width ? fImage->width - x : width;
3771  height = y + height > fImage->height ? fImage->height - y : height;
3772 
3773  if (!fImage->alt.argb32) {
3774  fill_asimage(fgVisual, fImage, x, y, width, height, color);
3775  } else {
3776  int yyy = y*fImage->width;
3777  if (!has_alpha) { // use faster memset
3778  ARGB32 *p0 = fImage->alt.argb32 + yyy + x;
3779  ARGB32 *p = p0;
3780  for (UInt_t i = 0; i < height; i++) {
3781  _MEMSET_(p, width, color);
3782  p += fImage->width;
3783  }
3784  } else {
3785  for (UInt_t i = y; i < y + height; i++) {
3786  int j = x + width;
3787  while (j > x) {
3788  j--;
3789  _alphaBlend(&fImage->alt.argb32[Idx(yyy + j)], &color);
3790  }
3791  yyy += fImage->width;
3792  }
3793  }
3794  }
3795 }
3796 
3797 ////////////////////////////////////////////////////////////////////////////////
3798 /// Fill rectangle of size (width, height) at position (x,y)
3799 /// within the existing image with specified color.
3800 ///
3801 /// To create new image with Fill method the following code can be used:
3802 /// ~~~ {.cpp}
3803 /// TImage *img = TImage::Create();
3804 /// img->Fill("#FF00FF", 0, 0, 400, 300);
3805 /// ~~~
3806 
3807 void TASImage::FillRectangle(const char *col, Int_t x, Int_t y, UInt_t width, UInt_t height)
3808 {
3809  if (!InitVisual()) {
3810  Warning("Fill", "Visual not initiated");
3811  return;
3812  }
3813 
3814  ARGB32 color = ARGB32_White;
3815 
3816  if (col) {
3817  parse_argb_color(col, &color);
3818  }
3819 
3820  if (!fImage) {
3821  fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
3822  x = 0;
3823  y = 0;
3824  }
3825 
3826  FillRectangleInternal((UInt_t)color, x, y, width, height);
3827  UnZoom();
3828 }
3829 
3830 ////////////////////////////////////////////////////////////////////////////////
3831 /// Draw a vertical line.
3832 
3834 {
3835  ARGB32 color = (ARGB32)col;
3836  UInt_t half = 0;
3837 
3838  if (!thick) thick = 1;
3839 
3840  if (thick > 1) {
3841  half = thick >> 1;
3842  if (x > half) {
3843  x = x - half;
3844  } else {
3845  x = 0;
3846  thick += (x - half);
3847  }
3848  }
3849 
3850  y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
3851  y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
3852  x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
3853 
3854  int yy = y1*fImage->width;
3855  for (UInt_t y = y1; y <= y2; y++) {
3856  for (UInt_t w = 0; w < thick; w++) {
3857  if (x + w < fImage->width) {
3858  _alphaBlend(&fImage->alt.argb32[Idx(yy + (x + w))], &color);
3859  }
3860  }
3861  yy += fImage->width;
3862  }
3863 }
3864 
3865 ////////////////////////////////////////////////////////////////////////////////
3866 /// Draw an horizontal line.
3867 
3869 {
3870  ARGB32 color = (ARGB32)col;
3871  UInt_t half = 0;
3872 
3873  if (!thick) thick = 1;
3874 
3875  if (thick > 1) {
3876  half = thick >> 1;
3877  if (y > half) {
3878  y = y - half;
3879  } else {
3880  y = 0;
3881  thick += (y - half);
3882  }
3883  }
3884 
3885  y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
3886  x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
3887  x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
3888 
3889  int yy = y*fImage->width;
3890  for (UInt_t w = 0; w < thick; w++) {
3891  for (UInt_t x = x1; x <= x2; x++) {
3892  if (y + w < fImage->height) {
3893  _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
3894  }
3895  }
3896  yy += fImage->width;
3897  }
3898 }
3899 
3900 ////////////////////////////////////////////////////////////////////////////////
3901 /// Draw a line.
3902 
3904  const char *col, UInt_t thick)
3905 {
3906  ARGB32 color = ARGB32_White;
3907  parse_argb_color(col, &color);
3908  DrawLineInternal(x1, y1, x2, y2, (UInt_t)color, thick);
3909 }
3910 
3911 ////////////////////////////////////////////////////////////////////////////////
3912 /// Internal line drawing.
3913 
3915  UInt_t col, UInt_t thick)
3916 {
3917  int dx, dy, d;
3918  int i1, i2;
3919  int x, y, xend, yend;
3920  int xdir, ydir;
3921  int q;
3922  int idx;
3923  int yy;
3924 
3925  if (!InitVisual()) {
3926  Warning("DrawLine", "Visual not initiated");
3927  return;
3928  }
3929 
3930  if (!fImage) {
3931  Warning("DrawLine", "no image");
3932  return;
3933  }
3934 
3935  if (!fImage->alt.argb32) {
3936  BeginPaint();
3937  }
3938 
3939  if (!fImage->alt.argb32) {
3940  Warning("DrawLine", "Failed to get pixel array");
3941  return;
3942  }
3943 
3944  ARGB32 color = (ARGB32)col;
3945 
3946  dx = TMath::Abs(Int_t(x2) - Int_t(x1));
3947  dy = TMath::Abs(Int_t(y2) - Int_t(y1));
3948 
3949  if (!dx) {
3950  DrawVLine(x1, y2 > y1 ? y1 : y2,
3951  y2 > y1 ? y2 : y1, color, thick);
3952  return;
3953  }
3954 
3955  if (!dy) {
3956  DrawHLine(y1, x2 > x1 ? x1 : x2,
3957  x2 > x1 ? x2 : x1, color, thick);
3958  return;
3959  }
3960 
3961  if (thick > 1) {
3962  DrawWideLine(x1, y1, x2, y2, color, thick);
3963  return;
3964  }
3965 
3966  if (dy <= dx) {
3967  UInt_t ddy = dy << 1;
3968  i1 = ddy;
3969  i2 = i1 - (dx << 1);
3970  d = i1 - dx;
3971 
3972  if (x1 > x2) {
3973  x = x2;
3974  y = y2;
3975  ydir = -1;
3976  xend = x1;
3977  } else {
3978  x = x1;
3979  y = y1;
3980  ydir = 1;
3981  xend = x2;
3982  }
3983 
3984  yy = y*fImage->width;
3985  _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
3986  q = (y2 - y1) * ydir;
3987 
3988  if (q > 0) {
3989  while (x < xend) {
3990 
3991  idx = Idx(yy + x);
3992  _alphaBlend(&fImage->alt.argb32[idx], &color);
3993  x++;
3994 
3995  if (d >= 0) {
3996  yy += fImage->width;
3997  d += i2;
3998  } else {
3999  d += i1;
4000  }
4001  }
4002  } else {
4003  while (x < xend) {
4004  idx = Idx(yy + x);
4005  _alphaBlend(&fImage->alt.argb32[idx], &color);
4006  x++;
4007 
4008  if (d >= 0) {
4009  yy -= fImage->width;
4010  d += i2;
4011  } else {
4012  d += i1;
4013  }
4014  }
4015  }
4016  } else {
4017  UInt_t ddx = dx << 1;
4018  i1 = ddx;
4019  i2 = i1 - (dy << 1);
4020  d = i1 - dy;
4021 
4022  if (y1 > y2) {
4023  y = y2;
4024  x = x2;
4025  yend = y1;
4026  xdir = -1;
4027  } else {
4028  y = y1;
4029  x = x1;
4030  yend = y2;
4031  xdir = 1;
4032  }
4033 
4034  yy = y*fImage->width;
4035  _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
4036  q = (x2 - x1) * xdir;
4037 
4038  if (q > 0) {
4039  while (y < yend) {
4040  idx = Idx(yy + x);
4041  _alphaBlend(&fImage->alt.argb32[idx], &color);
4042  y++;
4043  yy += fImage->width;
4044 
4045  if (d >= 0) {
4046  x++;
4047  d += i2;
4048  } else {
4049  d += i1;
4050  }
4051  }
4052  } else {
4053  while (y < yend) {
4054  idx = Idx(yy + x);
4055  _alphaBlend(&fImage->alt.argb32[idx], &color);
4056  y++;
4057  yy += fImage->width;
4058 
4059  if (d >= 0) {
4060  x--;
4061  d += i2;
4062  } else {
4063  d += i1;
4064  }
4065  }
4066  }
4067  }
4068 }
4069 
4070 ////////////////////////////////////////////////////////////////////////////////
4071 /// Draw a rectangle.
4072 
4074  const char *col, UInt_t thick)
4075 {
4076  if (!InitVisual()) {
4077  Warning("DrawRectangle", "Visual not initiated");
4078  return;
4079  }
4080 
4081  if (!fImage) {
4082  w = w ? w : 20;
4083  h = h ? h : 20;
4084  x = 0;
4085  y = 0;
4086  fImage = create_asimage(w, h, 0);
4087  FillRectangle(col, 0, 0, w, h);
4088  return;
4089  }
4090 
4091  if (!fImage->alt.argb32) {
4092  BeginPaint();
4093  }
4094 
4095  if (!fImage->alt.argb32) {
4096  Warning("DrawRectangle", "Failed to get pixel array");
4097  return;
4098  }
4099 
4100  ARGB32 color = ARGB32_White;
4101  parse_argb_color(col, &color);
4102 
4103  DrawHLine(y, x, x + w, (UInt_t)color, thick);
4104  DrawVLine(x + w, y, y + h, (UInt_t)color, thick);
4105  DrawHLine(y + h, x, x + w, (UInt_t)color, thick);
4106  DrawVLine(x, y, y + h, (UInt_t)color, thick);
4107  UnZoom();
4108 }
4109 
4110 ////////////////////////////////////////////////////////////////////////////////
4111 /// Draw a box.
4112 
4113 void TASImage::DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, const char *col,
4114  UInt_t thick, Int_t mode)
4115 {
4116  Int_t x = TMath::Min(x1, x2);
4117  Int_t y = TMath::Min(y1, y2);
4118  Int_t w = TMath::Abs(x2 - x1);
4119  Int_t h = TMath::Abs(y2 - y1);
4120 
4121  ARGB32 color = ARGB32_White;
4122 
4123  if (!fImage) {
4124  w = w ? x+w : x+20;
4125  h = h ? y+h : y+20;
4126  fImage = create_asimage(w, h, 0);
4127  FillRectangle(col, 0, 0, w, h);
4128  return;
4129  }
4130 
4131  if (x1 == x2) {
4132  parse_argb_color(col, &color);
4133  DrawVLine(x1, y1, y2, color, 1);
4134  return;
4135  }
4136 
4137  if (y1 == y2) {
4138  parse_argb_color(col, &color);
4139  DrawHLine(y1, x1, x2, color, 1);
4140  return;
4141  }
4142 
4143 
4144  switch (mode) {
4145  case TVirtualX::kHollow:
4146  DrawRectangle(x, y, w, h, col, thick);
4147  break;
4148 
4149  case TVirtualX::kFilled:
4150  FillRectangle(col, x, y, w, h);
4151  break;
4152 
4153  default:
4154  FillRectangle(col, x, y, w, h);
4155  break;
4156  }
4157 }
4158 
4159 ////////////////////////////////////////////////////////////////////////////////
4160 /// Draw a dashed horizontal line.
4161 
4163  const char *pDash, UInt_t col, UInt_t thick)
4164 {
4165  UInt_t iDash = 0; // index of current dash
4166  int i = 0;
4167 
4168  ARGB32 color = (ARGB32)col;
4169 
4170  UInt_t half = 0;
4171 
4172  if (thick > 1) {
4173  half = thick >> 1;
4174  if (y > half) {
4175  y = y - half;
4176  } else {
4177  y = 0;
4178  thick += (y - half);
4179  }
4180  }
4181  thick = thick <= 0 ? 1 : thick;
4182 
4183  y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
4184  x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
4185  x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
4186 
4187  // switch x1, x2
4188  UInt_t tmp = x1;
4189  x1 = x2 < x1 ? x2 : x1;
4190  x2 = x2 < tmp ? tmp : x2;
4191 
4192  for (UInt_t x = x1; x <= x2; x++) {
4193  for (UInt_t w = 0; w < thick; w++) {
4194  if (y + w < fImage->height) {
4195  if ((iDash%2)==0) {
4196  _alphaBlend(&fImage->alt.argb32[Idx((y + w)*fImage->width + x)], &color);
4197  }
4198  }
4199  }
4200  i++;
4201 
4202  if (i >= pDash[iDash]) {
4203  iDash++;
4204  i = 0;
4205  }
4206  if (iDash >= nDash) {
4207  iDash = 0;
4208  i = 0;
4209  }
4210  }
4211 }
4212 
4213 ////////////////////////////////////////////////////////////////////////////////
4214 /// Draw a dashed vertical line.
4215 
4217  const char *pDash, UInt_t col, UInt_t thick)
4218 {
4219  UInt_t iDash = 0; // index of current dash
4220  int i = 0;
4221 
4222  ARGB32 color = (ARGB32)col;
4223 
4224  UInt_t half = 0;
4225 
4226  if (thick > 1) {
4227  half = thick >> 1;
4228  if (x > half) {
4229  x = x - half;
4230  } else {
4231  x = 0;
4232  thick += (x - half);
4233  }
4234  }
4235  thick = thick <= 0 ? 1 : thick;
4236 
4237  y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
4238  y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
4239 
4240  // switch x1, x2
4241  UInt_t tmp = y1;
4242  y1 = y2 < y1 ? y2 : y1;
4243  y2 = y2 < tmp ? tmp : y2;
4244 
4245  x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
4246 
4247  int yy = y1*fImage->width;
4248  for (UInt_t y = y1; y <= y2; y++) {
4249  for (UInt_t w = 0; w < thick; w++) {
4250  if (x + w < fImage->width) {
4251  if ((iDash%2)==0) {
4252  _alphaBlend(&fImage->alt.argb32[Idx(yy + (x + w))], &color);
4253  }
4254  }
4255  }
4256  i++;
4257 
4258  if (i >= pDash[iDash]) {
4259  iDash++;
4260  i = 0;
4261  }
4262  if (iDash >= nDash) {
4263  iDash = 0;
4264  i = 0;
4265  }
4266  yy += fImage->width;
4267  }
4268 }
4269 
4270 ////////////////////////////////////////////////////////////////////////////////
4271 /// Draw a dashed line with one pixel width.
4272 
4274  UInt_t nDash, const char *tDash, UInt_t color)
4275 {
4276  int dx, dy, d;
4277  int i, i1, i2;
4278  int x, y, xend, yend;
4279  int xdir, ydir;
4280  int q;
4281  UInt_t iDash = 0; // index of current dash
4282  int yy;
4283  int idx;
4284 
4285  dx = TMath::Abs(Int_t(x2) - Int_t(x1));
4286  dy = TMath::Abs(Int_t(y2) - Int_t(y1));
4287 
4288  char *pDash = new char[nDash];
4289 
4290  if (dy <= dx) {
4291  double ac = TMath::Cos(TMath::ATan2(dy, dx));
4292 
4293  for (i = 0; i < (int)nDash; i++) {
4294  pDash[i] = TMath::Nint(tDash[i] * ac);
4295  }
4296 
4297  UInt_t ddy = dy << 1;
4298  i1 = ddy;
4299  i2 = i1 - (dx << 1);
4300  d = i1 - dx;
4301  i = 0;
4302 
4303  if (x1 > x2) {
4304  x = x2;
4305  y = y2;
4306  ydir = -1;
4307  xend = x1;
4308  } else {
4309  x = x1;
4310  y = y1;
4311  ydir = 1;
4312  xend = x2;
4313  }
4314 
4315  yy = y*fImage->width;
4316  _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4317  q = (y2 - y1) * ydir;
4318 
4319  if (q > 0) {
4320  while (x < xend) {
4321  idx = Idx(yy + x);
4322  if ((iDash%2) == 0) {
4323  _alphaBlend(&fImage->alt.argb32[idx], &color);
4324  }
4325  x++;
4326  if (d >= 0) {
4327  yy += fImage->width;
4328  d += i2;
4329  } else {
4330  d += i1;
4331  }
4332 
4333  i++;
4334  if (i >= pDash[iDash]) {
4335  iDash++;
4336  i = 0;
4337  }
4338  if (iDash >= nDash) {
4339  iDash = 0;
4340  i = 0;
4341  }
4342  }
4343  } else {
4344  while (x < xend) {
4345  idx = Idx(yy + x);
4346  if ((iDash%2) == 0) {
4347  _alphaBlend(&fImage->alt.argb32[idx], &color);
4348  }
4349  x++;
4350  if (d >= 0) {
4351  yy -= fImage->width;
4352  d += i2;
4353  } else {
4354  d += i1;
4355  }
4356 
4357  i++;
4358  if (i >= pDash[iDash]) {
4359  iDash++;
4360  i = 0;
4361  }
4362  if (iDash >= nDash) {
4363  iDash = 0;
4364  i = 0;
4365  }
4366  }
4367  }
4368  } else {
4369  double as = TMath::Sin(TMath::ATan2(dy, dx));
4370 
4371  for (i = 0; i < (int)nDash; i++) {
4372  pDash[i] = TMath::Nint(tDash[i] * as);
4373  }
4374 
4375  UInt_t ddx = dx << 1;
4376  i1 = ddx;
4377  i2 = i1 - (dy << 1);
4378  d = i1 - dy;
4379  i = 0;
4380 
4381  if (y1 > y2) {
4382  y = y2;
4383  x = x2;
4384  yend = y1;
4385  xdir = -1;
4386  } else {
4387  y = y1;
4388  x = x1;
4389  yend = y2;
4390  xdir = 1;
4391  }
4392 
4393  yy = y*fImage->width;
4394  _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4395  q = (x2 - x1) * xdir;
4396 
4397  if (q > 0) {
4398  while (y < yend) {
4399  idx = Idx(yy + x);
4400  if ((iDash%2) == 0) {
4401  _alphaBlend(&fImage->alt.argb32[idx], &color);
4402  }
4403  y++;
4404  yy += fImage->width;
4405 
4406  if (d >= 0) {
4407  x++;
4408  d += i2;
4409  } else {
4410  d += i1;
4411  }
4412 
4413  i++;
4414  if (i >= pDash[iDash]) {
4415  iDash++;
4416  i = 0;
4417  }
4418  if (iDash >= nDash) {
4419  iDash = 0;
4420  i = 0;
4421  }
4422  }
4423  } else {
4424  while (y < yend) {
4425  idx = Idx(yy + x);
4426  if ((iDash%2) == 0) {
4427  _alphaBlend(&fImage->alt.argb32[idx], &color);
4428  }
4429  y++;
4430  yy += fImage->width;
4431 
4432  if (d >= 0) {
4433  x--;
4434  d += i2;
4435  } else {
4436  d += i1;
4437  }
4438 
4439  i++;
4440  if (i >= pDash[iDash]) {
4441  iDash++;
4442  i = 0;
4443  }
4444  if (iDash >= nDash) {
4445  iDash = 0;
4446  i = 0;
4447  }
4448  }
4449  }
4450  }
4451  delete [] pDash;
4452 }
4453 
4454 ////////////////////////////////////////////////////////////////////////////////
4455 /// Draw a dashed line with thick pixel width.
4456 
4458  UInt_t nDash, const char *tDash, UInt_t color, UInt_t thick)
4459 {
4460  int dx, dy;
4461  int i;
4462  double x, y, xend=0, yend=0, x0, y0;
4463  int xdir, ydir;
4464  int q;
4465  UInt_t iDash = 0; // index of current dash
4466 
4467  dx = TMath::Abs(Int_t(x2) - Int_t(x1));
4468  dy = TMath::Abs(Int_t(y2) - Int_t(y1));
4469 
4470  double *xDash = new double[nDash];
4471  double *yDash = new double[nDash];
4472  double a = TMath::ATan2(dy, dx);
4473  double ac = TMath::Cos(a);
4474  double as = TMath::Sin(a);
4475 
4476  for (i = 0; i < (int)nDash; i++) {
4477  xDash[i] = tDash[i] * ac;
4478  yDash[i] = tDash[i] * as;
4479 
4480  // dirty trick (must be fixed)
4481  if ((i%2) == 0) {
4482  xDash[i] = xDash[i]/2;
4483  yDash[i] = yDash[i]/2;
4484  } else {
4485  xDash[i] = xDash[i]*2;
4486  yDash[i] = yDash[i]*2;
4487  }
4488  }
4489 
4490  if (dy <= dx) {
4491  if (x1 > x2) {
4492  x = x2;
4493  y = y2;
4494  ydir = -1;
4495  xend = x1;
4496  } else {
4497  x = x1;
4498  y = y1;
4499  ydir = 1;
4500  xend = x2;
4501  }
4502 
4503  q = (y2 - y1) * ydir;
4504  x0 = x;
4505  y0 = y;
4506  iDash = 0;
4507  yend = y + q;
4508 
4509  if (q > 0) {
4510  while ((x < xend) && (y < yend)) {
4511  x += xDash[iDash];
4512  y += yDash[iDash];
4513 
4514  if ((iDash%2) == 0) {
4516  TMath::Nint(x), TMath::Nint(y), color, thick);
4517  } else {
4518  x0 = x;
4519  y0 = y;
4520  }
4521 
4522  iDash++;
4523 
4524  if (iDash >= nDash) {
4525  iDash = 0;
4526  }
4527  }
4528  } else {
4529  while ((x < xend) && (y > yend)) {
4530  x += xDash[iDash];
4531  y -= yDash[iDash];
4532 
4533  if ((iDash%2) == 0) {
4535  TMath::Nint(x), TMath::Nint(y), color, thick);
4536  } else {
4537  x0 = x;
4538  y0 = y;
4539  }
4540 
4541  iDash++;
4542 
4543  if (iDash >= nDash) {
4544  iDash = 0;
4545  }
4546  }
4547  }
4548  } else {
4549 
4550  if (y1 > y2) {
4551  y = y2;
4552  x = x2;
4553  yend = y1;
4554  xdir = -1;
4555  } else {
4556  y = y1;
4557  x = x1;
4558  yend = y2;
4559  xdir = 1;
4560  }
4561 
4562  q = (x2 - x1) * xdir;
4563  x0 = x;
4564  y0 = y;
4565  iDash = 0;
4566  xend = x + q;
4567 
4568  if (q > 0) {
4569  while ((x < xend) && (y < yend)) {
4570  x += xDash[iDash];
4571  y += yDash[iDash];
4572 
4573  if ((iDash%2) == 0) {
4575  TMath::Nint(x), TMath::Nint(y), color, thick);
4576  } else {
4577  x0 = x;
4578  y0 = y;
4579  }
4580 
4581  iDash++;
4582 
4583  if (iDash >= nDash) {
4584  iDash = 0;
4585  }
4586  }
4587  } else {
4588  while ((x > xend) && (y < yend)) {
4589  x -= xDash[iDash];
4590  y += yDash[iDash];
4591 
4592  if ((iDash%2) == 0) {
4594  TMath::Nint(x), TMath::Nint(y), color, thick);
4595  } else {
4596  x0 = x;
4597  y0 = y;
4598  }
4599 
4600  iDash++;
4601 
4602  if (iDash >= nDash) {
4603  iDash = 0;
4604  }
4605  }
4606  }
4607  }
4608  delete [] xDash;
4609  delete [] yDash;
4610 }
4611 
4612 ////////////////////////////////////////////////////////////////////////////////
4613 /// Draw a dashed line.
4614 
4616  const char *pDash, const char *col, UInt_t thick)
4617 
4618 {
4619  if (!InitVisual()) {
4620  Warning("DrawDashLine", "Visual not initiated");
4621  return;
4622  }
4623 
4624  if (!fImage) {
4625  Warning("DrawDashLine", "no image");
4626  return;
4627  }
4628 
4629  if (!fImage->alt.argb32) {
4630  BeginPaint();
4631  }
4632 
4633  if (!fImage->alt.argb32) {
4634  Warning("DrawDashLine", "Failed to get pixel array");
4635  return;
4636  }
4637 
4638  if ((nDash < 2) || !pDash || (nDash%2)) {
4639  Warning("DrawDashLine", "Wrong input parameters n=%d %ld", nDash, (Long_t)sizeof(pDash)-1);
4640  return;
4641  }
4642 
4643  ARGB32 color = ARGB32_White;
4644  parse_argb_color(col, &color);
4645 
4646  if (x1 == x2) {
4647  DrawDashVLine(x1, y1, y2, nDash, pDash, (UInt_t)color, thick);
4648  } else if (y1 == y2) {
4649  DrawDashHLine(y1, x1, x2, nDash, pDash, (UInt_t)color, thick);
4650  } else {
4651  if (thick < 2) DrawDashZLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color);
4652  else DrawDashZTLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color, thick);
4653  }
4654 }
4655 
4656 ////////////////////////////////////////////////////////////////////////////////
4657 /// Draw a polyline.
4658 
4659 void TASImage::DrawPolyLine(UInt_t nn, TPoint *xy, const char *col, UInt_t thick,
4660  TImage::ECoordMode mode)
4661 {
4662  ARGB32 color = ARGB32_White;
4663  parse_argb_color(col, &color);
4664 
4665  Int_t x0 = xy[0].GetX();
4666  Int_t y0 = xy[0].GetY();
4667  Int_t x = 0;
4668  Int_t y = 0;
4669 
4670  for (UInt_t i = 1; i < nn; i++) {
4671  x = (mode == kCoordModePrevious) ? x + xy[i].GetX() : xy[i].GetX();
4672  y = (mode == kCoordModePrevious) ? y + xy[i].GetY() : xy[i].GetY();
4673 
4674  DrawLineInternal(x0, y0, x, y, (UInt_t)color, thick);
4675 
4676  x0 = x;
4677  y0 = y;
4678  }
4679 }
4680 
4681 ////////////////////////////////////////////////////////////////////////////////
4682 /// Draw a point at the specified position.
4683 
4684 void TASImage::PutPixel(Int_t x, Int_t y, const char *col)
4685 {
4686  if (!InitVisual()) {
4687  Warning("PutPixel", "Visual not initiated");
4688  return;
4689  }
4690 
4691  if (!fImage) {
4692  Warning("PutPixel", "no image");
4693  return;
4694  }
4695 
4696  if (!fImage->alt.argb32) {
4697  BeginPaint();
4698  }
4699 
4700  if (!fImage->alt.argb32) {
4701  Warning("PutPixel", "Failed to get pixel array");
4702  return;
4703  }
4704 
4705  ARGB32 color;
4706  parse_argb_color(col, &color);
4707 
4708  if ((x < 0) || (y < 0) || (x >= (int)fImage->width) || (y >= (int)fImage->height)) {
4709  Warning("PutPixel", "Out of range width=%d x=%d, height=%d y=%d",
4710  fImage->width, x, fImage->height, y);
4711  return;
4712  }
4713  _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4714 }
4715 
4716 ////////////////////////////////////////////////////////////////////////////////
4717 /// Draw a poly point.
4718 
4719 void TASImage::PolyPoint(UInt_t npt, TPoint *ppt, const char *col, TImage::ECoordMode mode)
4720 {
4721  if (!InitVisual()) {
4722  Warning("PolyPoint", "Visual not initiated");
4723  return;
4724  }
4725 
4726  if (!fImage) {
4727  Warning("PolyPoint", "no image");
4728  return;
4729  }
4730 
4731  if (!fImage->alt.argb32) {
4732  BeginPaint();
4733  }
4734 
4735  if (!fImage->alt.argb32) {
4736  Warning("PolyPoint", "Failed to get pixel array");
4737  return;
4738  }
4739 
4740  if (!npt || !ppt) {
4741  Warning("PolyPoint", "No points specified");
4742  return;
4743  }
4744 
4745  TPoint *ipt = 0;
4746  UInt_t i = 0;
4747  ARGB32 color;
4748  parse_argb_color(col, &color);
4749 
4750  //make pointlist origin relative
4751  if (mode == kCoordModePrevious) {
4752  ipt = new TPoint[npt];
4753 
4754  for (i = 0; i < npt; i++) {
4755  ipt[i].fX += ppt[i].fX;
4756  ipt[i].fY += ppt[i].fY;
4757  }
4758  }
4759  int x, y;
4760 
4761  for (i = 0; i < npt; i++) {
4762  x = ipt ? ipt[i].fX : ppt[i].fX;
4763  y = ipt ? ipt[i].fY : ppt[i].fY;
4764 
4765  if ((x < 0) || (y < 0) || (x >= (int)fImage->width) || (y >= (int)fImage->height)) {
4766  continue;
4767  }
4768  _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4769  }
4770 
4771  if (ipt) {
4772  delete [] ipt;
4773  }
4774 }
4775 
4776 ////////////////////////////////////////////////////////////////////////////////
4777 /// Draw segments.
4778 
4779 void TASImage::DrawSegments(UInt_t nseg, Segment_t *seg, const char *col, UInt_t thick)
4780 {
4781  if (!nseg || !seg) {
4782  Warning("DrawSegments", "Invalid data nseg=%d seg=0x%lx", nseg, (Long_t)seg);
4783  return;
4784  }
4785 
4786  TPoint pt[2];
4787 
4788  for (UInt_t i = 0; i < nseg; i++) {
4789  pt[0].fX = seg->fX1;
4790  pt[1].fX = seg->fX2;
4791  pt[0].fY = seg->fY1;
4792  pt[1].fY = seg->fY2;
4793 
4794  DrawPolyLine(2, pt, col, thick, kCoordModeOrigin);
4795  seg++;
4796  }
4797 }
4798 
4799 ////////////////////////////////////////////////////////////////////////////////
4800 /// Fill spans with specified color or/and stipple.
4801 
4802 void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, const char *col,
4803  const char *stipple, UInt_t w, UInt_t h)
4804 {
4805  if (!InitVisual()) {
4806  Warning("FillSpans", "Visual not initiated");
4807  return;
4808  }
4809 
4810  if (!fImage) {
4811  Warning("FillSpans", "no image");
4812  return;
4813  }
4814 
4815  if (!fImage->alt.argb32) {
4816  BeginPaint();
4817  }
4818 
4819  if (!fImage->alt.argb32) {
4820  Warning("FillSpans", "Failed to get pixel array");
4821  return;
4822  }
4823 
4824  if (!npt || !ppt || !widths || (stipple && (!w || !h))) {
4825  Warning("FillSpans", "Invalid input data npt=%d ppt=0x%lx col=%s widths=0x%lx stipple=0x%lx w=%d h=%d",
4826  npt, (Long_t)ppt, col, (Long_t)widths, (Long_t)stipple, w, h);
4827  return;
4828  }
4829 
4830  ARGB32 color;
4831  parse_argb_color(col, &color);
4832  Int_t idx = 0;
4833  UInt_t x = 0;
4834  UInt_t yy;
4835 
4836  for (UInt_t i = 0; i < npt; i++) {
4837  yy = ppt[i].fY*fImage->width;
4838  for (UInt_t j = 0; j < widths[i]; j++) {
4839  if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
4840  (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0)) continue;
4841 
4842  x = ppt[i].fX + j;
4843  idx = Idx(yy + x);
4844 
4845  if (!stipple) {
4846  _alphaBlend(&fImage->alt.argb32[idx], &color);
4847  } else {
4848  Int_t ii = (ppt[i].fY%h)*w + x%w;
4849 
4850  if (stipple[ii >> 3] & (1 << (ii%8))) {
4851  _alphaBlend(&fImage->alt.argb32[idx], &color);
4852  }
4853  }
4854  }
4855  }
4856 }
4857 
4858 ////////////////////////////////////////////////////////////////////////////////
4859 /// Fill spans with tile image.
4860 
4861 void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, TImage *tile)
4862 {
4863  if (!InitVisual()) {
4864  Warning("FillSpans", "Visual not initiated");
4865  return;
4866  }
4867 
4868  if (!fImage) {
4869  Warning("FillSpans", "no image");
4870  return;
4871  }
4872 
4873  if (!fImage->alt.argb32) {
4874  BeginPaint();
4875  }
4876 
4877  if (!fImage->alt.argb32) {
4878  Warning("FillSpans", "Failed to get pixel array");
4879  return;
4880  }
4881 
4882  if (!npt || !ppt || !widths || !tile) {
4883  Warning("FillSpans", "Invalid input data npt=%d ppt=0x%lx widths=0x%lx tile=0x%lx",
4884  npt, (Long_t)ppt, (Long_t)widths, (Long_t)tile);
4885  return;
4886  }
4887 
4888  Int_t idx = 0;
4889  Int_t ii = 0;
4890  UInt_t x = 0;
4891  UInt_t *arr = tile->GetArgbArray();
4892  if (!arr) return;
4893  UInt_t xx = 0;
4894  UInt_t yy = 0;
4895  UInt_t yyy = 0;
4896 
4897  for (UInt_t i = 0; i < npt; i++) {
4898  yyy = ppt[i].fY*fImage->width;
4899 
4900  for (UInt_t j = 0; j < widths[i]; j++) {
4901  if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
4902  (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0)) continue;
4903  x = ppt[i].fX + j;
4904  idx = Idx(yyy + x);
4905  xx = x%tile->GetWidth();
4906  yy = ppt[i].fY%tile->GetHeight();
4907  ii = yy*tile->GetWidth() + xx;
4908  _alphaBlend(&fImage->alt.argb32[idx], &arr[ii]);
4909  }
4910  yyy += fImage->width;;
4911  }
4912 }
4913 
4914 ////////////////////////////////////////////////////////////////////////////////
4915 /// Crop spans.
4916 
4917 void TASImage::CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths)
4918 {
4919  if (!InitVisual()) {
4920  Warning("CropSpans", "Visual not initiated");
4921  return;
4922  }
4923 
4924  if (!fImage) {
4925  Warning("CropSpans", "no image");
4926  return;
4927  }
4928 
4929  if (!fImage->alt.argb32) {
4930  BeginPaint();
4931  }
4932 
4933  if (!fImage->alt.argb32) {
4934  Warning("CropSpans", "Failed to get pixel array");
4935  return;
4936  }
4937 
4938  if (!npt || !ppt || !widths) {
4939  Warning("CropSpans", "No points specified npt=%d ppt=0x%lx widths=0x%lx", npt, (Long_t)ppt, (Long_t)widths);
4940  return;
4941  }
4942 
4943  int y0 = ppt[0].fY;
4944  int y1 = ppt[npt-1].fY;
4945  UInt_t y = 0;
4946  UInt_t x = 0;
4947  UInt_t i = 0;
4948  UInt_t idx = 0;
4949  UInt_t sz = fImage->width*fImage->height;
4950  UInt_t yy = y*fImage->width;
4951 
4952  for (y = 0; (int)y < y0; y++) {
4953  for (x = 0; x < fImage->width; x++) {
4954  idx = Idx(yy + x);
4955  if (idx < sz) fImage->alt.argb32[idx] = 0;
4956  }
4957  yy += fImage->width;
4958  }
4959 
4960  for (i = 0; i < npt; i++) {
4961  for (x = 0; (int)x < ppt[i].fX; x++) {
4962  idx = Idx(ppt[i].fY*fImage->width + x);
4963  if (idx < sz) fImage->alt.argb32[idx] = 0;
4964  }
4965  for (x = ppt[i].fX + widths[i] + 1; x < fImage->width; x++) {
4966  idx = Idx(ppt[i].fY*fImage->width + x);
4967  if (idx < sz) fImage->alt.argb32[idx] = 0;
4968  }
4969  }
4970 
4971  yy = y1*fImage->width;
4972  for (y = y1; y < fImage->height; y++) {
4973  for (x = 0; x < fImage->width; x++) {
4974  idx = Idx(yy + x);
4975  if (idx < sz) fImage->alt.argb32[idx] = 0;
4976  }
4977  yy += fImage->width;
4978  }
4979 }
4980 
4981 ////////////////////////////////////////////////////////////////////////////////
4982 /// Copy source region to the destination image. Copy is done according
4983 /// to specified function:
4984 /// ~~~ {.cpp}
4985 /// enum EGraphicsFunction {
4986 /// kGXclear = 0, // 0
4987 /// kGXand, // src AND dst
4988 /// kGXandReverse, // src AND NOT dst
4989 /// kGXcopy, // src (default)
4990 /// kGXandInverted, // NOT src AND dst
4991 /// kGXnoop, // dst
4992 /// kGXxor, // src XOR dst
4993 /// kGXor, // src OR dst
4994 /// kGXnor, // NOT src AND NOT dst
4995 /// kGXequiv, // NOT src XOR dst
4996 /// kGXinvert, // NOT dst
4997 /// kGXorReverse, // src OR NOT dst
4998 /// kGXcopyInverted, // NOT src
4999 /// kGXorInverted, // NOT src OR dst
5000 /// kGXnand, // NOT src OR NOT dst
5001 /// kGXset // 1
5002 /// };
5003 /// ~~~
5004 
5005 void TASImage::CopyArea(TImage *dst, Int_t xsrc, Int_t ysrc, UInt_t w, UInt_t h,
5006  Int_t xdst, Int_t ydst, Int_t gfunc, EColorChan)
5007 {
5008  if (!InitVisual()) {
5009  Warning("CopyArea", "Visual not initiated");
5010  return;
5011  }
5012 
5013  if (!fImage) {
5014  Warning("CopyArea", "no image");
5015  return;
5016  }
5017  if (!dst) return;
5018 
5019  ASImage *out = ((TASImage*)dst)->GetImage();
5020 
5021  int x = 0;
5022  int y = 0;
5023  int idx = 0;
5024  int idx2 = 0;
5025  xsrc = xsrc < 0 ? 0 : xsrc;
5026  ysrc = ysrc < 0 ? 0 : ysrc;
5027 
5028  if ((xsrc >= (int)fImage->width) || (ysrc >= (int)fImage->height)) return;
5029 
5030  w = xsrc + w > fImage->width ? fImage->width - xsrc : w;
5031  h = ysrc + h > fImage->height ? fImage->height - ysrc : h;
5032  UInt_t yy = (ysrc + y)*fImage->width;
5033 
5034  if (!fImage->alt.argb32) {
5035  BeginPaint();
5036  }
5037  if (!out->alt.argb32) {
5038  dst->BeginPaint();
5039  out = ((TASImage*)dst)->GetImage();
5040  }
5041 
5042  if (fImage->alt.argb32 && out->alt.argb32) {
5043  for (y = 0; y < (int)h; y++) {
5044  for (x = 0; x < (int)w; x++) {
5045  idx = Idx(yy + x + xsrc);
5046  if ((x + xdst < 0) || (ydst + y < 0) ||
5047  (x + xdst >= (int)out->width) || (y + ydst >= (int)out->height) ) continue;
5048 
5049  idx2 = Idx((ydst + y)*out->width + x + xdst);
5050 
5051  switch ((EGraphicsFunction)gfunc) {
5052  case kGXclear:
5053  out->alt.argb32[idx2] = 0;
5054  break;
5055  case kGXand:
5056  out->alt.argb32[idx2] &= fImage->alt.argb32[idx];
5057  break;
5058  case kGXandReverse:
5059  out->alt.argb32[idx2] = fImage->alt.argb32[idx] & (~out->alt.argb32[idx2]);
5060  break;
5061  case kGXandInverted:
5062  out->alt.argb32[idx2] &= ~fImage->alt.argb32[idx];
5063  break;
5064  case kGXnoop:
5065  break;
5066  case kGXxor:
5067  out->alt.argb32[idx2] ^= fImage->alt.argb32[idx];
5068  break;
5069  case kGXor:
5070  out->alt.argb32[idx2] |= fImage->alt.argb32[idx];
5071  break;
5072  case kGXnor:
5073  out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) & (~out->alt.argb32[idx2]);
5074  break;
5075  case kGXequiv:
5076  out->alt.argb32[idx2] ^= ~fImage->alt.argb32[idx];
5077  break;
5078  case kGXinvert:
5079  out->alt.argb32[idx2] = ~out->alt.argb32[idx2];
5080  break;
5081  case kGXorReverse:
5082  out->alt.argb32[idx2] = fImage->alt.argb32[idx] | (~out->alt.argb32[idx2]);
5083  break;
5084  case kGXcopyInverted:
5085  out->alt.argb32[idx2] = ~fImage->alt.argb32[idx];
5086  break;
5087  case kGXorInverted:
5088  out->alt.argb32[idx2] |= ~fImage->alt.argb32[idx];
5089  break;
5090  case kGXnand:
5091  out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) | (~out->alt.argb32[idx2]);
5092  break;
5093  case kGXset:
5094  out->alt.argb32[idx2] = 0xFFFFFFFF;
5095  break;
5096  case kGXcopy:
5097  default:
5098  out->alt.argb32[idx2] = fImage->alt.argb32[idx];
5099  break;
5100  }
5101  }
5102  yy += fImage->width;
5103  }
5104  }
5105 }
5106 
5107 ////////////////////////////////////////////////////////////////////////////////
5108 /// Draw a cell array.
5109 ///
5110 /// \param[in] x1,y1 : left down corner
5111 /// \param[in] x2,y2 : right up corner
5112 /// \param[in] nx,ny : array size
5113 /// \param[in] ic : array of ARGB32 colors
5114 ///
5115 /// Draw a cell array. The drawing is done with the pixel precision
5116 /// if (X2-X1)/NX (or Y) is not a exact pixel number the position of
5117 /// the top right corner may be wrong.
5118 
5120  Int_t ny, UInt_t *ic)
5121 {
5122  int i, j, ix, iy, w, h;
5123 
5124  ARGB32 color = 0xFFFFFFFF;
5125  ARGB32 icol;
5126 
5127  w = TMath::Max((x2-x1)/(nx),1);
5128  h = TMath::Max((y1-y2)/(ny),1);
5129  ix = x1;
5130 
5131  for (i = 0; i < nx; i++) {
5132  iy = y1 - h;
5133  for (j = 0; j < ny; j++) {
5134  icol = (ARGB32)ic[i + (nx*j)];
5135  if (icol != color) {
5136  color = icol;
5137  }
5138  FillRectangleInternal((UInt_t)color, ix, iy, w, h);
5139  iy = iy - h;
5140  }
5141  ix = ix + w;
5142  }
5143 }
5144 
5145 ////////////////////////////////////////////////////////////////////////////////
5146 /// Return alpha-blended value computed from bottom and top pixel values.
5147 
5149 {
5150  UInt_t ret = bot;
5151 
5152  _alphaBlend(&ret, &top);
5153  return ret;
5154 }
5155 
5156 ////////////////////////////////////////////////////////////////////////////////
5157 /// Return visual.
5158 
5159 const ASVisual *TASImage::GetVisual()
5160 {
5161  return fgVisual;
5162 }
5163 
5164 ////////////////////////////////////////////////////////////////////////////////
5165 /// Get poly bounds along Y.
5166 
5167 static int GetPolyYBounds(TPoint *pts, int n, int *by, int *ty)
5168 {
5169  TPoint *ptMin;
5170  int ymin, ymax;
5171  TPoint *ptsStart = pts;
5172 
5173  ptMin = pts;
5174  ymin = ymax = (pts++)->fY;
5175 
5176  while (--n > 0) {
5177  if (pts->fY < ymin) {
5178  ptMin = pts;
5179  ymin = pts->fY;
5180  }
5181  if (pts->fY > ymax) {
5182  ymax = pts->fY;
5183  }
5184  pts++;
5185  }
5186 
5187  *by = ymin;
5188  *ty = ymax;
5189  return (ptMin - ptsStart);
5190 }
5191 
5192 ////////////////////////////////////////////////////////////////////////////////
5193 /// The code is based on Xserver/mi/mipolycon.c
5194 /// "Copyright 1987, 1998 The Open Group"
5195 
5197  TPoint **outPoint, UInt_t **outWidth)
5198 {
5199  int xl = 0; // x vals of leftedges
5200  int xr = 0; // x vals of right edges
5201  int dl = 0; // decision variables
5202  int dr = 0; // decision variables
5203  int ml = 0; // left edge slope
5204  int m1l = 0; // left edge slope+1
5205  int mr = 0, m1r = 0; // right edge slope and slope+1
5206  int incr1l = 0, incr2l = 0; // left edge error increments
5207  int incr1r = 0, incr2r = 0; // right edge error increments
5208  int dy; // delta y
5209  int y; // current scanline
5210  int left, right; // indices to first endpoints
5211  int i; // loop counter
5212  int nextleft, nextright; // indices to second endpoints
5213  TPoint *ptsOut; // output buffer
5214  UInt_t *width; // output buffer
5215  TPoint *firstPoint=0;
5216  UInt_t *firstWidth=0;
5217  int imin; // index of smallest vertex (in y)
5218  int ymin; // y-extents of polygon
5219  int ymax;
5220  Bool_t ret = kTRUE;
5221 
5222  *nspans = 0;
5223 
5224  if (!InitVisual()) {
5225  Warning("GetPolygonSpans", "Visual not initiated");
5226  return kFALSE;
5227  }
5228 
5229  if (!fImage) {
5230  Warning("GetPolygonSpans", "no image");
5231  return kFALSE;
5232  }
5233 
5234  if (!fImage->alt.argb32) {
5235  BeginPaint();
5236  }
5237 
5238  if (!fImage->alt.argb32) {
5239  Warning("GetPolygonSpans", "Failed to get pixel array");
5240  return kFALSE;
5241  }
5242 
5243  if ((npt < 3) || !ppt) {
5244  Warning("GetPolygonSpans", "No points specified npt=%d ppt=0x%lx", npt, (Long_t)ppt);
5245  return kFALSE;
5246  }
5247 
5248  // find leftx, bottomy, rightx, topy, and the index
5249  // of bottomy. Also translate the points.
5250  imin = GetPolyYBounds(ppt, npt, &ymin, &ymax);
5251 
5252  dy = ymax - ymin + 1;
5253  if ((npt < 3) || (dy < 0)) return kFALSE;
5254 
5255  ptsOut = firstPoint = new TPoint[dy];
5256  width = firstWidth = new UInt_t[dy];
5257  ret = kTRUE;
5258 
5259  nextleft = nextright = imin;
5260  y = ppt[nextleft].fY;
5261 
5262  // loop through all edges of the polygon
5263  do {
5264  // add a left edge if we need to
5265  if (ppt[nextleft].fY == y) {
5266  left = nextleft;
5267 
5268  // find the next edge, considering the end
5269  // conditions of the array.
5270  nextleft++;
5271  if (nextleft >= (int)npt) {
5272  nextleft = 0;
5273  }
5274 
5275  // now compute all of the random information
5276  // needed to run the iterative algorithm.
5277  BRESINITPGON(ppt[nextleft].fY - ppt[left].fY,
5278  ppt[left].fX, ppt[nextleft].fX,
5279  xl, dl, ml, m1l, incr1l, incr2l);
5280  }
5281 
5282  // add a right edge if we need to
5283  if (ppt[nextright].fY == y) {
5284  right = nextright;
5285 
5286  // find the next edge, considering the end
5287  // conditions of the array.
5288  nextright--;
5289  if (nextright < 0) {
5290  nextright = npt-1;
5291  }
5292 
5293  // now compute all of the random information
5294  // needed to run the iterative algorithm.
5295  BRESINITPGON(ppt[nextright].fY - ppt[right].fY,
5296  ppt[right].fX, ppt[nextright].fX,
5297  xr, dr, mr, m1r, incr1r, incr2r);
5298  }
5299 
5300  // generate scans to fill while we still have
5301  // a right edge as well as a left edge.
5302  i = TMath::Min(ppt[nextleft].fY, ppt[nextright].fY) - y;
5303 
5304  // in case of non-convex polygon
5305  if (i < 0) {
5306  delete [] firstWidth;
5307  delete [] firstPoint;
5308  return kTRUE;
5309  }
5310 
5311  while (i-- > 0) {
5312  ptsOut->fY = y;
5313 
5314  // reverse the edges if necessary
5315  if (xl < xr) {
5316  *(width++) = xr - xl;
5317  (ptsOut++)->fX = xl;
5318  } else {
5319  *(width++) = xl - xr;
5320  (ptsOut++)->fX = xr;
5321  }
5322  y++;
5323 
5324  // increment down the edges
5325  BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l);
5326  BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r);
5327  }
5328  } while (y != ymax);
5329 
5330  *nspans = UInt_t(ptsOut - firstPoint);
5331  *outPoint = firstPoint;
5332  *outWidth = firstWidth;
5333 
5334  return ret;
5335 }
5336 
5337 ////////////////////////////////////////////////////////////////////////////////
5338 /// Fill a convex polygon with background color or bitmap.
5339 /// For non convex polygon one must use DrawFillArea method
5340 
5341 void TASImage::FillPolygon(UInt_t npt, TPoint *ppt, const char *col,
5342  const char *stipple, UInt_t w, UInt_t h)
5343 {
5344  UInt_t nspans = 0;
5345  TPoint *firstPoint = 0; // output buffer
5346  UInt_t *firstWidth = 0; // output buffer
5347 
5348  Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5349  ARGB32 color = ARGB32_White;
5350  parse_argb_color(col, &color);
5351 
5352  if (nspans) {
5353  if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple no alpha
5354  FillSpansInternal(nspans, firstPoint, firstWidth, color);
5355  } else {
5356  FillSpans(nspans, firstPoint, firstWidth, col, stipple, w, h);
5357  }
5358 
5359  if (del) {
5360  delete [] firstWidth;
5361  delete [] firstPoint;
5362  }
5363  } else {
5364  if (firstWidth) delete [] firstWidth;
5365  if (firstPoint) delete [] firstPoint;
5366  }
5367 }
5368 
5369 ////////////////////////////////////////////////////////////////////////////////
5370 /// Fill a convex polygon with background image.
5371 /// For non convex polygon one must use DrawFillArea method
5372 
5374 {
5375  UInt_t nspans = 0;
5376  TPoint *firstPoint = 0; // output buffer
5377  UInt_t *firstWidth = 0; // output buffer
5378 
5379  Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5380 
5381  if (nspans) {
5382  FillSpans(nspans, firstPoint, firstWidth, tile);
5383 
5384  if (del) {
5385  delete [] firstWidth;
5386  delete [] firstPoint;
5387  }
5388  } else {
5389  if (firstWidth) delete [] firstWidth;
5390  if (firstPoint) delete [] firstPoint;
5391  }
5392 }
5393 
5394 ////////////////////////////////////////////////////////////////////////////////
5395 /// Crop a convex polygon.
5396 
5398 {
5399  UInt_t nspans = 0;
5400  TPoint *firstPoint = 0;
5401  UInt_t *firstWidth = 0;
5402 
5403  Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5404 
5405  if (nspans) {
5406  CropSpans(nspans, firstPoint, firstWidth);
5407 
5408  if (del) {
5409  delete [] firstWidth;
5410  delete [] firstPoint;
5411  }
5412  } else {
5413  if (firstWidth) delete [] firstWidth;
5414  if (firstPoint) delete [] firstPoint;
5415  }
5416 }
5417 
5418 static const UInt_t NUMPTSTOBUFFER = 512;
5419 
5420 ////////////////////////////////////////////////////////////////////////////////
5421 /// Fill a polygon (any type convex, non-convex).
5422 
5423 void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, const char *col,
5424  const char *stipple, UInt_t w, UInt_t h)
5425 {
5426  if (!InitVisual()) {
5427  Warning("DrawFillArea", "Visual not initiated");
5428  return;
5429  }
5430 
5431  if (!fImage) {
5432  Warning("DrawFillArea", "no image");
5433  return;
5434  }
5435 
5436  if (!fImage->alt.argb32) {
5437  BeginPaint();
5438  }
5439 
5440  if (!fImage->alt.argb32) {
5441  Warning("DrawFillArea", "Failed to get pixel array");
5442  return;
5443  }
5444 
5445  if ((count < 3) || !ptsIn) {
5446  Warning("DrawFillArea", "No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
5447  return;
5448  }
5449 
5450  if (count < 5) {
5451  FillPolygon(count, ptsIn, col, stipple, w, h);
5452  return;
5453  }
5454 
5455  ARGB32 color = ARGB32_White;
5456  parse_argb_color(col, &color);
5457 
5458  EdgeTableEntry *pAET; // the Active Edge Table
5459  int y; // the current scanline
5460  UInt_t nPts = 0; // number of pts in buffer
5461 
5462  ScanLineList *pSLL; // Current ScanLineList
5463  TPoint *ptsOut; // ptr to output buffers
5464  UInt_t *width;
5465  TPoint firstPoint[NUMPTSTOBUFFER]; // the output buffers
5466  UInt_t firstWidth[NUMPTSTOBUFFER];
5467  EdgeTableEntry *pPrevAET; // previous AET entry
5468  EdgeTable ET; // Edge Table header node
5469  EdgeTableEntry AET; // Active ET header node
5470  EdgeTableEntry *pETEs; // Edge Table Entries buff
5471  ScanLineListBlock SLLBlock; // header for ScanLineList
5472  Bool_t del = kTRUE;
5473 
5474  static const UInt_t gEdgeTableEntryCacheSize = 200;
5475  static EdgeTableEntry gEdgeTableEntryCache[gEdgeTableEntryCacheSize];
5476 
5477  if (count < gEdgeTableEntryCacheSize) {
5478  pETEs = (EdgeTableEntry*)&gEdgeTableEntryCache;
5479  del = kFALSE;
5480  } else {
5481  pETEs = new EdgeTableEntry[count];
5482  del = kTRUE;
5483  }
5484 
5485  ptsOut = firstPoint;
5486  width = firstWidth;
5487  CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
5488  pSLL = ET.scanlines.next;
5489 
5490  for (y = ET.ymin; y < ET.ymax; y++) {
5491  if (pSLL && y == pSLL->scanline) {
5492  loadAET(&AET, pSLL->edgelist);
5493  pSLL = pSLL->next;
5494  }
5495  pPrevAET = &AET;
5496  pAET = AET.next;
5497 
5498  while (pAET) {
5499  ptsOut->fX = pAET->bres.minor_axis;
5500  ptsOut->fY = y;
5501  ptsOut++;
5502  nPts++;
5503 
5504  *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
5505 
5506  if (nPts == NUMPTSTOBUFFER) {
5507  if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple, no alpha
5508  FillSpansInternal(nPts, firstPoint, firstWidth, color);
5509  } else {
5510  FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
5511  }
5512  ptsOut = firstPoint;
5513  width = firstWidth;
5514  nPts = 0;
5515  }
5516  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5517  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5518  }
5519  InsertionSort(&AET);
5520  }
5521 
5522  if (nPts) {
5523  if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple, no alpha
5524  FillSpansInternal(nPts, firstPoint, firstWidth, color);
5525  } else {
5526  FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
5527  }
5528  }
5529 
5530  if (del) delete [] pETEs;
5531  FreeStorage(SLLBlock.next);
5532 }
5533 
5534 ////////////////////////////////////////////////////////////////////////////////
5535 /// Fill a polygon (any type convex, non-convex).
5536 
5537 void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, TImage *tile)
5538 {
5539  if (!InitVisual()) {
5540  Warning("DrawFillArea", "Visual not initiated");
5541  return;
5542  }
5543 
5544  if (!fImage) {
5545  Warning("DrawFillArea", "no image");
5546  return;
5547  }
5548 
5549  if (!fImage->alt.argb32) {
5550  BeginPaint();
5551  }
5552 
5553  if (!fImage->alt.argb32) {
5554  Warning("DrawFillArea", "Failed to get pixel array");
5555  return;
5556  }
5557 
5558  if ((count < 3) || !ptsIn) {
5559  Warning("DrawFillArea", "No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
5560  return;
5561  }
5562 
5563  if (count < 5) {
5564  FillPolygon(count, ptsIn, tile);
5565  return;
5566  }
5567 
5568  EdgeTableEntry *pAET; // the Active Edge Table
5569  int y; // the current scanline
5570  UInt_t nPts = 0; // number of pts in buffer
5571 
5572  ScanLineList *pSLL; // Current ScanLineList
5573  TPoint *ptsOut; // ptr to output buffers
5574  UInt_t *width;
5575  TPoint firstPoint[NUMPTSTOBUFFER]; // the output buffers
5576  UInt_t firstWidth[NUMPTSTOBUFFER];
5577  EdgeTableEntry *pPrevAET; // previous AET entry
5578  EdgeTable ET; // Edge Table header node
5579  EdgeTableEntry AET; // Active ET header node
5580  EdgeTableEntry *pETEs; // Edge Table Entries buff
5581  ScanLineListBlock SLLBlock; // header for ScanLineList
5582 
5583  pETEs = new EdgeTableEntry[count];
5584 
5585  ptsOut = firstPoint;
5586  width = firstWidth;
5587  CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
5588  pSLL = ET.scanlines.next;
5589 
5590  for (y = ET.ymin; y < ET.ymax; y++) {
5591  if (pSLL && y == pSLL->scanline) {
5592  loadAET(&AET, pSLL->edgelist);
5593  pSLL = pSLL->next;
5594  }
5595  pPrevAET = &AET;
5596  pAET = AET.next;
5597 
5598  while (pAET) {
5599  ptsOut->fX = pAET->bres.minor_axis;
5600  ptsOut->fY = y;
5601  ptsOut++;
5602  nPts++;
5603 
5604  *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
5605 
5606  if (nPts == NUMPTSTOBUFFER) {
5607  FillSpans(nPts, firstPoint, firstWidth, tile);
5608  ptsOut = firstPoint;
5609  width = firstWidth;
5610  nPts = 0;
5611  }
5612  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5613  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5614  }
5615  InsertionSort(&AET);
5616  }
5617  FillSpans(nPts, firstPoint, firstWidth, tile);
5618 
5619  delete [] pETEs;
5620  FreeStorage(SLLBlock.next);
5621 }
5622 
5623 ////////////////////////////////////////////////////////////////////////////////
5624 /// Create draw context.
5625 
5626 static ASDrawContext *create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
5627 {
5628  ASDrawContext *ctx = new ASDrawContext;
5629 
5630  ctx->canvas_width = im->width;
5631  ctx->canvas_height = im->height;
5632  ctx->canvas = im->alt.argb32;
5633  ctx->scratch_canvas = 0;
5634 
5635  ctx->flags = ASDrawCTX_CanvasIsARGB;
5636  asim_set_custom_brush_colored( ctx, brush);
5637  return ctx;
5638 }
5639 
5640 ////////////////////////////////////////////////////////////////////////////////
5641 /// Destroy asdraw context32.
5642 
5643 static void destroy_asdraw_context32( ASDrawContext *ctx )
5644 {
5645  if (ctx) {
5646  if (ctx->scratch_canvas) free(ctx->scratch_canvas);
5647  delete ctx;
5648  }
5649 }
5650 
5651 static const UInt_t kBrushCacheSize = 20;
5653 
5654 ////////////////////////////////////////////////////////////////////////////////
5655 /// Draw wide line.
5656 
5658  UInt_t color, UInt_t thick)
5659 {
5660  Int_t sz = thick*thick;
5661  CARD32 *matrix;
5662  Bool_t use_cache = thick < kBrushCacheSize;
5663 
5664  if (use_cache) {
5665  matrix = gBrushCache;
5666  } else {
5667  matrix = new CARD32[sz];
5668  }
5669 
5670  for (int i = 0; i < sz; i++) {
5671  matrix[i] = (CARD32)color;
5672  };
5673 
5674  ASDrawTool brush;
5675  brush.matrix = matrix;
5676  brush.width = thick;
5677  brush.height = thick;
5678  brush.center_y = brush.center_x = thick/2;
5679 
5680  // When the first or last point of a wide line is exactly on the
5681  // window limit the line is drawn vertically or horizontally.
5682  // see https://sft.its.cern.ch/jira/browse/ROOT-8021
5683  UInt_t xx1 = x1;
5684  UInt_t yy1 = y1;
5685  UInt_t xx2 = x2;
5686  UInt_t yy2 = y2;
5687  if (xx1 == fImage->width) --xx1;
5688  if (yy1 == fImage->height) --yy1;
5689  if (xx2 == fImage->width) --xx2;
5690  if (yy2 == fImage->height) --yy2;
5691  ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
5692  asim_move_to(ctx, xx1, yy1);
5693  asim_line_to(ctx, xx2, yy2);
5694 
5695  if (!use_cache) {
5696  delete [] matrix;
5697  }
5699 }
5700 
5701 ////////////////////////////////////////////////////////////////////////////////
5702 /// Draw glyph bitmap.
5703 
5704 void TASImage::DrawGlyph(void *bitmap, UInt_t color, Int_t bx, Int_t by)
5705 {
5706  static UInt_t col[5];
5707  Int_t x, y, yy, y0, xx;
5708  Bool_t has_alpha = (color & 0xff000000) != 0xff000000;
5709 
5710  ULong_t r, g, b;
5711  int idx = 0;
5712  FT_Bitmap *source = (FT_Bitmap*)bitmap;
5713  UChar_t d = 0, *s = source->buffer;
5714 
5715  Int_t dots = Int_t(source->width * source->rows);
5716  r = g = b = 0;
5717  Int_t bxx, byy;
5718 
5719  yy = y0 = by > 0 ? by * fImage->width : 0;
5720  for (y = 0; y < (int) source->rows; y++) {
5721  byy = by + y;
5722  if ((byy >= (int)fImage->height) || (byy <0)) continue;
5723 
5724  for (x = 0; x < (int) source->width; x++) {
5725  bxx = bx + x;
5726  if ((bxx >= (int)fImage->width) || (bxx < 0)) continue;
5727 
5728  idx = Idx(bxx + yy);
5729  r += ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
5730  g += ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
5731  b += (fImage->alt.argb32[idx] & 0x0000ff);
5732  }
5733  yy += fImage->width;
5734  }
5735  if (dots != 0) {
5736  r /= dots;
5737  g /= dots;
5738  b /= dots;
5739  }
5740 
5741  col[0] = (r << 16) + (g << 8) + b;
5742  col[4] = color;
5743  Int_t col4r = (col[4] & 0xff0000) >> 16;
5744  Int_t col4g = (col[4] & 0x00ff00) >> 8;
5745  Int_t col4b = (col[4] & 0x0000ff);
5746 
5747  // interpolate between fore and background colors
5748  for (x = 3; x > 0; x--) {
5749  xx = 4-x;
5750  Int_t colxr = (col4r*x + r*xx) >> 2;
5751  Int_t colxg = (col4g*x + g*xx) >> 2;
5752  Int_t colxb = (col4b*x + b*xx) >> 2;
5753  col[x] = (colxr << 16) + (colxg << 8) + colxb;
5754  }
5755 
5756  yy = y0;
5757  ARGB32 acolor;
5758  for (y = 0; y < (int) source->rows; y++) {
5759  byy = by + y;
5760  if ((byy >= (int)fImage->height) || (byy <0)) continue;
5761 
5762  for (x = 0; x < (int) source->width; x++) {
5763  bxx = bx + x;
5764  //if ((bxx >= (int)fImage->width) || (bxx < 0)) continue;
5765 
5766  d = *s++ & 0xff;
5767  d = ((d + 10) * 5) >> 8;
5768  if (d > 4) d = 4;
5769 
5770  if (d && (x < (int) source->width) && (bxx < (int)fImage->width) && (bxx >= 0)) {
5771  idx = Idx(bxx + yy);
5772  acolor = (ARGB32)col[d];
5773  if (has_alpha) {
5774  _alphaBlend(&fImage->alt.argb32[idx], &acolor);
5775  } else {
5776  fImage->alt.argb32[idx] = acolor;
5777  }
5778  }
5779  }
5780  yy += fImage->width;
5781  }
5782 }
5783 
5784 ////////////////////////////////////////////////////////////////////////////////
5785 /// Draw text at the pixel position (x,y).
5786 
5788 {
5789  if (!text) return;
5790  if (!fImage) return;
5791  if (!gPad) return;
5792 
5793  if (!InitVisual()) {
5794  Warning("DrawText", "Visual not initiated");
5795  return;
5796  }
5797 
5798  if (!fImage->alt.argb32) {
5799  BeginPaint();
5800  }
5801 
5802  if (!TTF::IsInitialized()) TTF::Init();
5803 
5804  // set text font
5805  TTF::SetTextFont(text->GetTextFont());
5806 
5807  Int_t wh = gPad->XtoPixel(gPad->GetX2());
5808  Int_t hh = gPad->YtoPixel(gPad->GetY1());
5809 
5810  // set text size
5811  Float_t ttfsize;
5812  if (wh < hh) {
5813  ttfsize = text->GetTextSize()*wh;
5814  } else {
5815  ttfsize = text->GetTextSize()*hh;
5816  }
5817  TTF::SetTextSize(ttfsize);
5818 
5819  // set text angle
5821 
5822  // set text
5823  const wchar_t *wcsTitle = reinterpret_cast<const wchar_t *>(text->GetWcsTitle());
5824  if (wcsTitle != NULL) {
5825  TTF::PrepareString(wcsTitle);
5826  } else {
5827  TTF::PrepareString(text->GetTitle());
5828  }
5830 
5831  // color
5832  TColor *col = gROOT->GetColor(text->GetTextColor());
5833  if (!col) { // no color, make it black
5834  col = gROOT->GetColor(1);
5835  if (!col) return;
5836  }
5837  ARGB32 color = ARGB32_White;
5838  parse_argb_color(col->AsHexString(), &color);
5839 
5840  // Align()
5841  Int_t align = 0;
5842  Int_t txalh = text->GetTextAlign()/10;
5843  Int_t txalv = text->GetTextAlign()%10;
5844 
5845  switch (txalh) {
5846  case 0 :
5847  case 1 :
5848  switch (txalv) { //left
5849  case 1 :
5850  align = 7; //bottom
5851  break;
5852  case 2 :
5853  align = 4; //center
5854  break;
5855  case 3 :
5856  align = 1; //top
5857  break;
5858  }
5859  break;
5860  case 2 :
5861  switch (txalv) { //center
5862  case 1 :
5863  align = 8; //bottom
5864  break;
5865  case 2 :
5866  align = 5; //center
5867  break;
5868  case 3 :
5869  align = 2; //top
5870  break;
5871  }
5872  break;
5873  case 3 :
5874  switch (txalv) { //right
5875  case 1 :
5876  align = 9; //bottom
5877  break;
5878  case 2 :
5879  align = 6; //center
5880  break;
5881  case 3 :
5882  align = 3; //top
5883  break;
5884  }
5885  break;
5886  }
5887 
5888  FT_Vector ftal;
5889 
5890  // vertical alignment
5891  if (align == 1 || align == 2 || align == 3) {
5892  ftal.y = TTF::GetAscent();
5893  } else if (align == 4 || align == 5 || align == 6) {
5894  ftal.y = TTF::GetAscent()/2;
5895  } else {
5896  ftal.y = 0;
5897  }
5898 
5899  // horizontal alignment
5900  if (align == 3 || align == 6 || align == 9) {
5901  ftal.x = TTF::GetWidth();
5902  } else if (align == 2 || align == 5 || align == 8) {
5903  ftal.x = TTF::GetWidth()/2;
5904  } else {
5905  ftal.x = 0;
5906  }
5907 
5908  FT_Vector_Transform(&ftal, TTF::GetRotMatrix());
5909  ftal.x = (ftal.x >> 6);
5910  ftal.y = (ftal.y >> 6);
5911 
5912  TTF::TTGlyph *glyph = TTF::GetGlyphs();
5913 
5914  for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
5915  if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 )) continue;
5916 
5917  FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
5918  FT_Bitmap *source = &bitmap->bitmap;
5919 
5920  Int_t bx = x - ftal.x + bitmap->left;
5921  Int_t by = y + ftal.y - bitmap->top;
5922 
5923  DrawGlyph(source, color, bx, by);
5924  }
5925 }
5926 
5927 ////////////////////////////////////////////////////////////////////////////////
5928 /// Draw text using TrueType fonts.
5929 
5930 void TASImage::DrawTextTTF(Int_t x, Int_t y, const char *text, Int_t size,
5931  UInt_t color, const char *font_name, Float_t angle)
5932 {
5933  if (!TTF::IsInitialized()) TTF::Init();
5934 
5935  TTF::SetTextFont(font_name);
5936  TTF::SetTextSize(size);
5937  TTF::SetRotationMatrix(angle);
5938  TTF::PrepareString(text);
5940 
5941  TTF::TTGlyph *glyph = TTF::GetGlyphs();
5942 
5943  // compute the size and position that will contain the text
5944  // Int_t Xoff = 0; if (TTF::GetBox().xMin < 0) Xoff = -TTF::GetBox().xMin;
5945  Int_t Yoff = 0; if (TTF::GetBox().yMin < 0) Yoff = -TTF::GetBox().yMin;
5946  Int_t h = TTF::GetBox().yMax + Yoff;
5947 
5948  for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
5949  if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 )) continue;
5950 
5951  FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
5952  FT_Bitmap *source = &bitmap->bitmap;
5953 
5954  Int_t bx = x + bitmap->left;
5955  Int_t by = y + h - bitmap->top;
5956  DrawGlyph(source, color, bx, by);
5957  }
5958 }
5959 
5960 ////////////////////////////////////////////////////////////////////////////////
5961 /// Return in-memory buffer compressed according image type.
5962 /// Buffer must be deallocated after usage.
5963 /// This method can be used for sending images over network.
5964 
5965 void TASImage::GetImageBuffer(char **buffer, int *size, EImageFileTypes type)
5966 {
5967  static ASImageExportParams params;
5968  Bool_t ret = kFALSE;
5969  int isize = 0;
5970  char *ibuff = 0;
5971  ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
5972 
5973  if (!img) return;
5974 
5975  switch (type) {
5976  case TImage::kXpm:
5977  ret = ASImage2xpmRawBuff(img, (CARD8 **)buffer, size, 0);
5978  break;
5979  default:
5980  ret = ASImage2PNGBuff(img, (CARD8 **)buffer, size, &params);
5981  }
5982 
5983  if (!ret) {
5984  *size = isize;
5985  *buffer = ibuff;
5986  }
5987 }
5988 
5989 ////////////////////////////////////////////////////////////////////////////////
5990 /// Create image from compressed buffer.
5991 /// Supported formats:
5992 ///
5993 /// - PNG - by default
5994 /// - XPM - two options exist:
5995 /// 1. xpm as a single string (raw buffer). Such string
5996 /// is returned by GetImageBuffer method.
5997 /// For example:
5998 /// ~~~ {.cpp}
5999 /// char *buf;
6000 /// int sz;
6001 /// im1->GetImageBuffer(&buf, &int, TImage::kXpm); /*raw buffer*/
6002 /// TImage *im2 = TImage::Create();
6003 /// im2->SetImageBuffer(&buf, TImage::kXpm);
6004 /// ~~~
6005 /// 2. xpm as an array of strings (pre-parsed)
6006 /// ~~~ {.cpp}
6007 /// For example:
6008 /// char *xpm[] = {
6009 /// "64 28 58 1",
6010 /// " c #0A030C",
6011 /// ". c #1C171B"
6012 /// ...
6013 /// TImage *im = TImage::Create();
6014 /// im->SetImageBuffer(xpm, TImage::kXpm);
6015 /// ~~~
6016 
6018 {
6019  DestroyImage();
6020 
6021  static ASImageImportParams params;
6022  params.flags = 0;
6023  params.width = 0;
6024  params.height = 0 ;
6025  params.filter = SCL_DO_ALL;
6026  params.gamma = 0;
6027  params.gamma_table = 0;
6028  params.compression = 0;
6029  params.format = ASA_ASImage;
6030  params.search_path = 0;
6031  params.subimage = 0;
6032 
6033  switch (type) {
6034  case TImage::kXpm:
6035  {
6036  char *ptr = buffer[0];
6037  while (isspace((int)*ptr)) ++ptr;
6038  if (atoi(ptr)) { // pre-parsed and preloaded data
6039  fImage = xpm_data2ASImage((const char**)buffer, &params);
6040  } else {
6041  fImage = xpmRawBuff2ASImage((const char*)*buffer, &params);
6042  }
6043  break;
6044  }
6045  default:
6046  fImage = PNGBuff2ASimage((CARD8 *)*buffer, &params);
6047  break;
6048  }
6049 
6050  if (!fImage) {
6051  return kFALSE;
6052  }
6053 
6054  if (fName.IsNull()) {
6055  fName.Form("img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
6056  }
6057  UnZoom();
6058  return kTRUE;
6059 }
6060 
6061 ////////////////////////////////////////////////////////////////////////////////
6062 /// Create image thumbnail.
6063 
6065 {
6066  int size;
6067  const int sz = 64;
6068 
6069  if (!fImage) {
6070  return;
6071  }
6072 
6073  if (!InitVisual()) {
6074  return;
6075  }
6076 
6077  static char *buf = 0;
6078  int w, h;
6079  ASImage *img = 0;
6080 
6081  if (fImage->width > fImage->height) {
6082  w = sz;
6083  h = (fImage->height*sz)/fImage->width;
6084  } else {
6085  h = sz;
6086  w = (fImage->width*sz)/fImage->height;
6087  }
6088 
6089  w = w < 8 ? 8 : w;
6090  h = h < 8 ? 8 : h;
6091 
6092  img = scale_asimage(fgVisual, fImage, w, h, ASA_ASImage,
6094  if (!img) {
6095  return;
6096  }
6097 
6098  // contrasting
6099  ASImage *rendered_im;
6100  ASImageLayer layers[2];
6101  init_image_layers(&(layers[0]), 2);
6102  layers[0].im = img;
6103  layers[0].dst_x = 0;
6104  layers[0].dst_y = 0;
6105  layers[0].clip_width = img->width;
6106  layers[0].clip_height = img->height;
6107  layers[0].bevel = 0;
6108  layers[1].im = img;
6109  layers[1].dst_x = 0;
6110  layers[1].dst_y = 0;
6111  layers[1].clip_width = img->width;
6112  layers[1].clip_height = img->height;
6113  layers[1].merge_scanlines = blend_scanlines_name2func("tint");
6114  rendered_im = merge_layers(fgVisual, &(layers[0]), 2, img->width, img->height,
6115  ASA_ASImage, GetImageCompression(), GetImageQuality());
6116  destroy_asimage(&img);
6117  img = rendered_im;
6118 
6119  // pad image
6120  ASImage *padimg = 0;
6121  int d = 0;
6122 
6123  if (w == sz) {
6124  d = (sz - h) >> 1;
6125  padimg = pad_asimage(fgVisual, img, 0, d, sz, sz, 0x00ffffff,
6126  ASA_ASImage, GetImageCompression(), GetImageQuality());
6127  } else {
6128  d = (sz - w) >> 1;
6129  padimg = pad_asimage(fgVisual, img, d, 0, sz, sz, 0x00ffffff,
6130  ASA_ASImage, GetImageCompression(), GetImageQuality());
6131  }
6132 
6133  if (!padimg) {
6134  destroy_asimage(&img);
6135  return;
6136  }
6137 
6138  void *ptr = &buf;
6139  ASImage2xpmRawBuff(padimg, (CARD8 **)ptr, &size, 0);
6140  fTitle = buf;
6141 
6142  destroy_asimage(&padimg);
6143 }
6144 
6145 ////////////////////////////////////////////////////////////////////////////////
6146 /// Streamer for ROOT I/O.
6147 
6148 void TASImage::Streamer(TBuffer &b)
6149 {
6150  Bool_t image_type = 0;
6151  char *buffer = 0;
6152  int size = 0;
6153  int w, h;
6154  UInt_t R__s, R__c;
6155 
6156  if (b.IsReading()) {
6157  Version_t version = b.ReadVersion(&R__s, &R__c);
6158  if (version == 0) { //dumb prototype for schema evolution
6159  return;
6160  }
6161 
6162  if ( version == 1 ) {
6163  Int_t fileVersion = b.GetVersionOwner();
6164  if (fileVersion > 0 && fileVersion < 50000 ) {
6165  TImage::Streamer(b);
6166  b >> fMaxValue;
6167  b >> fMinValue;
6168  b >> fZoomOffX;
6169  b >> fZoomOffY;
6170  b >> fZoomWidth;
6171  b >> fZoomHeight;
6172  if ( fileVersion < 40200 ) {
6173  Bool_t zoomUpdate;
6174  b >> zoomUpdate;
6175  fZoomUpdate = zoomUpdate;
6176  } else {
6177  b >> fZoomUpdate;
6178  b >> fEditable;
6179  Bool_t paintMode;
6180  b >> paintMode;
6181  fPaintMode = paintMode;
6182  }
6183  b.CheckByteCount(R__s, R__c, TASImage::IsA());
6184  return;
6185  }
6186  }
6187 
6188  TNamed::Streamer(b);
6189  b >> image_type;
6190 
6191  if (image_type != 0) { // read PNG compressed image
6192  b >> size;
6193  buffer = new char[size];
6194  b.ReadFastArray(buffer, size);
6195  SetImageBuffer(&buffer, TImage::kPng);
6196  delete [] buffer;
6197  } else { // read vector with palette
6198  TAttImage::Streamer(b);
6199  b >> w;
6200  b >> h;
6201  size = w*h;
6202  Double_t *vec = new Double_t[size];
6203  b.ReadFastArray(vec, size);
6204  SetImage(vec, w, h, &fPalette);
6205  delete [] vec;
6206  }
6207  b.CheckByteCount(R__s, R__c, TASImage::IsA());
6208  } else {
6209  if (!fImage) {
6210  return;
6211  }
6212  R__c = b.WriteVersion(TASImage::IsA(), kTRUE);
6213 
6214  if (fName.IsNull()) {
6215  fName.Form("img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
6216  }
6217  TNamed::Streamer(b);
6218 
6219  image_type = fImage->alt.vector ? 0 : 1;
6220  b << image_type;
6221 
6222  if (image_type != 0) { // write PNG compressed image
6223  GetImageBuffer(&buffer, &size, TImage::kPng);
6224  b << size;
6225  b.WriteFastArray(buffer, size);
6226  delete buffer;
6227  } else { // write vector with palette
6228  TAttImage::Streamer(b);
6229  b << fImage->width;
6230  b << fImage->height;
6231  b.WriteFastArray(fImage->alt.vector, fImage->width*fImage->height);
6232  }
6233  b.SetByteCount(R__c, kTRUE);
6234  }
6235 }
6236 
6237 ////////////////////////////////////////////////////////////////////////////////
6238 /// Browse image.
6239 
6241 {
6242  if (fImage->alt.vector) {
6243  Draw("n");
6244  } else {
6245  Draw("nxxx");
6246  }
6247  CreateThumbnail();
6248 }
6249 
6250 ////////////////////////////////////////////////////////////////////////////////
6251 /// Title is used to keep 32x32 xpm image's thumbnail.
6252 
6253 const char *TASImage::GetTitle() const
6254 {
6255  if (!gDirectory || !gDirectory->IsWritable()) {
6256  return 0;
6257  }
6258 
6259  TASImage *mutble = (TASImage *)this;
6260 
6261  if (fTitle.IsNull()) {
6262  mutble->SetTitle(fName.Data());
6263  }
6264 
6265  return fTitle.Data();
6266 }
6267 
6268 ////////////////////////////////////////////////////////////////////////////////
6269 /// Set a title for an image.
6270 
6271 void TASImage::SetTitle(const char *title)
6272 {
6273  if (fTitle.IsNull()) {
6274  CreateThumbnail();
6275  }
6276 
6277  if (fTitle.IsNull()) {
6278  return;
6279  }
6280 
6281  int start = fTitle.Index("/*") + 3;
6282  int stop = fTitle.Index("*/") - 1;
6283 
6284  if ((start > 0) && (stop - start > 0)) {
6285  fTitle.Replace(start, stop - start, title);
6286  }
6287 }
6288 
6289 ////////////////////////////////////////////////////////////////////////////////
6290 /// Draw a cubic bezier line.
6291 
6293  Int_t x3, Int_t y3, const char *col, UInt_t thick)
6294 {
6295  Int_t sz = thick*thick;
6296  CARD32 *matrix;
6297  Bool_t use_cache = thick < kBrushCacheSize;
6298 
6299  ARGB32 color = ARGB32_White;
6300  parse_argb_color(col, &color);
6301 
6302  if (use_cache) {
6303  matrix = gBrushCache;
6304  } else {
6305  matrix = new CARD32[sz];
6306  }
6307 
6308  for (int i = 0; i < sz; i++) {
6309  matrix[i] = (CARD32)color;
6310  };
6311 
6312  ASDrawTool brush;
6313  brush.matrix = matrix;
6314  brush.width = thick;
6315  brush.height = thick;
6316  brush.center_y = brush.center_x = thick/2;
6317 
6318  ASDrawContext *ctx = 0;
6319 
6320  ctx = create_draw_context_argb32(fImage, &brush);
6321  asim_cube_bezier(ctx, x1, y1, x2, y2, x3, y3);
6322 
6323  if (!use_cache) {
6324  delete [] matrix;
6325  }
6327 }
6328 
6329 ////////////////////////////////////////////////////////////////////////////////
6330 /// Draw a straight ellipse.
6331 /// If thick < 0 - draw filled ellipse.
6332 
6334  const char *col, Int_t thick)
6335 {
6336  thick = !thick ? 1 : thick;
6337  Int_t sz = thick*thick;
6338  CARD32 *matrix;
6339  Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6340 
6341  ARGB32 color = ARGB32_White;
6342  parse_argb_color(col, &color);
6343 
6344  if (use_cache) {
6345  matrix = gBrushCache;
6346  } else {
6347  matrix = new CARD32[sz];
6348  }
6349 
6350  for (int i = 0; i < sz; i++) {
6351  matrix[i] = (CARD32)color;
6352  };
6353 
6354  ASDrawTool brush;
6355  brush.matrix = matrix;
6356  brush.width = thick > 0 ? thick : 1;
6357  brush.height = thick > 0 ? thick : 1;
6358  brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6359 
6360  ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6361  asim_straight_ellips(ctx, x, y, rx, ry, thick < 0);
6362 
6363  if (!use_cache) {
6364  delete [] matrix;
6365  }
6367 }
6368 
6369 ////////////////////////////////////////////////////////////////////////////////
6370 /// Draw a circle.
6371 /// If thick < 0 - draw filled circle
6372 
6373 void TASImage::DrawCircle(Int_t x, Int_t y, Int_t r, const char *col, Int_t thick)
6374 {
6375  thick = !thick ? 1 : thick;
6376  Int_t sz = thick*thick;
6377  CARD32 *matrix;
6378  Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6379 
6380  ARGB32 color = ARGB32_White;
6381  parse_argb_color(col, &color);
6382 
6383 ///matrix = new CARD32[sz];
6384  if (use_cache) {
6385  matrix = gBrushCache;
6386  } else {
6387  matrix = new CARD32[sz];
6388  }
6389 
6390  for (int i = 0; i < sz; i++) {
6391  matrix[i] = (CARD32)color;
6392  }
6393 
6394  ASDrawTool brush;
6395  brush.matrix = matrix;
6396  brush.height = brush.width = thick > 0 ? thick : 1;
6397  brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6398 
6399  ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6400  asim_circle(ctx, x, y, r, thick < 0);
6401 
6402 ///free (matrix);
6403  if (!use_cache) {
6404  delete [] matrix;
6405  }
6407 }
6408 
6409 ////////////////////////////////////////////////////////////////////////////////
6410 /// Draw an ellipse.
6411 /// If thick < 0 - draw filled ellips
6412 
6414  const char *col, Int_t thick)
6415 {
6416  thick = !thick ? 1 : thick;
6417  Int_t sz = thick*thick;
6418  CARD32 *matrix;
6419  Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6420 
6421  ARGB32 color = ARGB32_White;
6422  parse_argb_color(col, &color);
6423 
6424  if (use_cache) {
6425  matrix = gBrushCache;
6426  } else {
6427  matrix = new CARD32[sz];
6428  }
6429 
6430  for (int i = 0; i < sz; i++) {
6431  matrix[i] = (CARD32)color;
6432  };
6433 
6434  ASDrawTool brush;
6435  brush.matrix = matrix;
6436  brush.width = thick > 0 ? thick : 1;
6437  brush.height = thick > 0 ? thick : 1;
6438  brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6439 
6440  ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6441  asim_ellips(ctx, x, y, rx, ry, angle, thick < 0);
6442 
6443  if (!use_cache) {
6444  delete [] matrix;
6445  }
6447 }
6448 
6449 ////////////////////////////////////////////////////////////////////////////////
6450 /// Draw an ellipse.
6451 /// If thick < 0 - draw filled ellipse.
6452 
6454  const char *col, Int_t thick)
6455 {
6456  thick = !thick ? 1 : thick;
6457  Int_t sz = thick*thick;
6458  CARD32 *matrix;
6459  Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6460 
6461  ARGB32 color = ARGB32_White;
6462  parse_argb_color(col, &color);
6463 
6464  if (use_cache) {
6465  matrix = gBrushCache;
6466  } else {
6467  matrix = new CARD32[sz];
6468  }
6469 
6470  for (int i = 0; i < sz; i++) {
6471  matrix[i] = (CARD32)color;
6472  };
6473 
6474  ASDrawTool brush;
6475  brush.matrix = matrix;
6476  brush.width = thick > 0 ? thick : 1;
6477  brush.height = thick > 0 ? thick : 1;
6478  brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6479 
6480  ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6481  asim_ellips2(ctx, x, y, rx, ry, angle, thick < 0);
6482 
6483  if (!use_cache) {
6484  delete [] matrix;
6485  }
6487 }
6488 
6489 ////////////////////////////////////////////////////////////////////////////////
6490 /// Flood fill.
6491 
6492 void TASImage::FloodFill(Int_t /*x*/, Int_t /*y*/, const char * /*col*/,
6493  const char * /*minc*/, const char * /*maxc*/)
6494 {
6495 }
6496 
6497 ////////////////////////////////////////////////////////////////////////////////
6498 /// Convert RGB image to Gray image and vice versa.
6499 
6501 {
6502  if (fIsGray == on) {
6503  return;
6504  }
6505 
6506  if (!IsValid()) {
6507  Warning("Gray", "Image not initiated");
6508  return;
6509  }
6510 
6511  if (!InitVisual()) {
6512  Warning("Gray", "Visual not initiated");
6513  return;
6514  }
6515 
6516  if (!fGrayImage && !on) {
6517  return;
6518  }
6519  ASImage *sav = 0;
6520  delete fScaledImage;
6521  fScaledImage = 0;
6522 
6523  if (fGrayImage) {
6524  sav = fImage;
6525  fImage = fGrayImage;
6526  fGrayImage = sav;
6527  fIsGray = on;
6528  return;
6529  }
6530 
6531  if (!on) return;
6532 
6533  UInt_t l, r, g, b, idx;
6534  int y = 0;
6535  UInt_t i, j;
6536 
6537  if (fImage->alt.argb32) {
6538  fGrayImage = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
6539  0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
6540 
6541  for (i = 0; i < fImage->height; i++) {
6542  for (j = 0; j < fImage->width; j++) {
6543  idx = Idx(y + j);
6544 
6545  r = ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
6546  g = ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
6547  b = (fImage->alt.argb32[idx] & 0x0000ff);
6548  l = (57*r + 181*g + 18*b)/256;
6549  fGrayImage->alt.argb32[idx] = (l << 16) + (l << 8) + l;
6550  }
6551  y += fImage->width;
6552  }
6553  } else {
6554  fGrayImage = create_asimage(fImage->width, fImage->height, 0);
6555 
6556  ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
6557  0, 0, fImage->width, fImage->height, 0);
6558 
6559  if (!imdec) {
6560  return;
6561  }
6562 #ifdef HAVE_MMX
6563  mmx_init();
6564 #endif
6565  ASImageOutput *imout = start_image_output(fgVisual, fGrayImage, ASA_ASImage,
6567  if (!imout) {
6568  Warning("ToGray", "Failed to start image output");
6569  delete fScaledImage;
6570  fScaledImage = 0;
6571  delete [] imdec;
6572  return;
6573  }
6574 
6575  CARD32 *aa = imdec->buffer.alpha;
6576  CARD32 *rr = imdec->buffer.red;
6577  CARD32 *gg = imdec->buffer.green;
6578  CARD32 *bb = imdec->buffer.blue;
6579 
6580  ASScanline result;
6581  prepare_scanline(fImage->width, 0, &result, fgVisual->BGR_mode);
6582 
6583  for (i = 0; i < fImage->height; i++) {
6584  imdec->decode_image_scanline(imdec);
6585  result.flags = imdec->buffer.flags;
6586  result.back_color = imdec->buffer.back_color;
6587 
6588  for (j = 0; j < fImage->width; j++) {
6589  l = (57*rr[j] + 181*gg[j]+ 18*bb[j])/256;
6590  result.alpha[j] = aa[j];
6591  result.red[j] = l;
6592  result.green[j] = l;
6593  result.blue[j] = l;
6594  }
6595  imout->output_image_scanline(imout, &result, 1);
6596  }
6597 
6598  stop_image_decoding(&imdec);
6599  stop_image_output(&imout);
6600 #ifdef HAVE_MMX
6601  mmx_off();
6602 #endif
6603  }
6604 
6605  sav = fImage;
6606  fImage = fGrayImage;
6607  fGrayImage = sav;
6608  fIsGray = kTRUE;
6609 }
6610 
6611 ////////////////////////////////////////////////////////////////////////////////
6612 /// Create an image (screenshot) from specified window.
6613 
6615 {
6616  Int_t xy;
6617 
6618  x = x < 0 ? 0 : x;
6619  y = y < 0 ? 0 : y;
6620 
6621  // synchronization
6622  gVirtualX->Update(1);
6623  if (!gThreadXAR) {
6625  gSystem->Sleep(10);
6627  }
6628 
6629  if (!w || !h) {
6630  gVirtualX->GetWindowSize(wid, xy, xy, w, h);
6631  }
6632 
6633  if ((x >= (Int_t)w) || (y >= (Int_t)h)) {
6634  return;
6635  }
6636 
6637  if (!InitVisual()) {
6638  Warning("FromWindow", "Visual not initiated");
6639  return;
6640  }
6641 
6642  DestroyImage();
6643  delete fScaledImage;
6644  fScaledImage = 0;
6645 
6646  static int x11 = -1;
6647  if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
6648 
6649  if (x11) { //use built-in optimized version
6650  fImage = pixmap2asimage(fgVisual, wid, x, y, w, h, kAllPlanes, 0, 0);
6651  } else {
6652  unsigned char *bits = gVirtualX->GetColorBits(wid, 0, 0, w, h);
6653 
6654  if (!bits) { // error
6655  return;
6656  }
6657  fImage = bitmap2asimage(bits, w, h, 0, 0);
6658  delete [] bits;
6659  }
6660 }
6661 
6662 ////////////////////////////////////////////////////////////////////////////////
6663 /// Creates an image (screenshot) from a RGBA buffer.
6664 
6666 {
6667  DestroyImage();
6668  delete fScaledImage;
6669  fScaledImage = 0;
6670 
6671  UChar_t* xx = new UChar_t[4*w];
6672  for (UInt_t i = 0; i < h/2; ++i) {
6673  memcpy(xx, buf + 4*w*i, 4*w);
6674  memcpy(buf + 4*w*i, buf + 4*w*(h-i-1), 4*w);
6675  memcpy(buf + 4*w*(h-i-1), xx, 4*w);
6676  }
6677  delete [] xx;
6678 
6679  fImage = bitmap2asimage(buf, w, h, 0, 0);
6680 }
6681 
6682 ////////////////////////////////////////////////////////////////////////////////
6683 /// Switch on/off the image palette.
6684 /// That also invokes calling vectorization of image.
6685 
6687 {
6688  if (!fImage) {
6689  return;
6690  }
6691 
6692  if (!fImage->alt.vector && on) {
6693  Vectorize();
6694  }
6695  fPaletteEnabled = on;
6696 
6697  if (on) {
6698  Double_t left = gPad->GetLeftMargin();
6699  Double_t right = gPad->GetRightMargin();
6700  Double_t top = gPad->GetTopMargin();
6701  Double_t bottom = gPad->GetBottomMargin();
6702 
6703  gPad->Range(-left / (1.0 - left - right),
6704  -bottom / (1.0 - top - bottom),
6705  1 + right / (1.0 - left - right),
6706  1 + top / ( 1.0 - top - bottom));
6707  gPad->RangeAxis(0, 0, 1, 1);
6708  }
6709 
6710 }
6711 
6712 ////////////////////////////////////////////////////////////////////////////////
6713 /// Save a primitive as a C++ statement(s) on output stream "out".
6714 
6715 void TASImage::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
6716 {
6717  char *buf = 0;
6718  int sz;
6719 
6720  UInt_t w = GetWidth();
6721  UInt_t h = GetHeight();
6722 
6723  if (w > 500) { // workaround CINT limitations
6724  w = 500;
6725  Double_t scale = 500./GetWidth();
6726  h = TMath::Nint(GetHeight()*scale);
6727  Scale(w, h);
6728  }
6729 
6730  GetImageBuffer(&buf, &sz, TImage::kXpm);
6731 
6732  TString name = GetName();
6733  name.ReplaceAll(".", "_");
6734  TString str = buf;
6735  static int ii = 0;
6736  ii++;
6737 
6738  str.ReplaceAll("static", "const");
6739  TString xpm = "xpm_";
6740  xpm += name;
6741  xpm += ii;
6742  str.ReplaceAll("asxpm", xpm.Data());
6743  out << std::endl << str << std::endl << std::endl;
6744 
6745  out << " TImage *";
6746  out << xpm << "_img = TImage::Create();" << std::endl;
6747  out << " " << xpm << "_img->SetImageBuffer( (char **)" << xpm << ", TImage::kXpm);" << std::endl;
6748  out << " " << xpm << "_img->Draw();" << std::endl;
6749 }
6750 
6751 ////////////////////////////////////////////////////////////////////////////////
6752 /// Set an image printing resolution in Dots Per Inch units.
6753 ///
6754 /// \param[in] name - the name of jpeg file.
6755 /// \param[in] set - dpi resolution.
6756 ///
6757 /// Returns kFALSE in case of error.
6758 
6760 {
6761  static char buf[32];
6762  FILE *fp = fopen(name, "rb+");
6763 
6764  if (!fp) {
6765  printf("file %s : failed to open\n", name);
6766  return kFALSE;
6767  }
6768 
6769  if (!fread(buf, 1, 20, fp)) {
6770  fclose(fp);
6771  return kFALSE;
6772  }
6773 
6774  char dpi1 = (set & 0xffff) >> 8;
6775  char dpi2 = set & 0xff;
6776 
6777  int i = 0;
6778 
6779  int dpi = 0; // start of dpi data
6780  for (i = 0; i < 20; i++) {
6781  if ((buf[i] == 0x4a) && (buf[i+1] == 0x46) && (buf[i+2] == 0x49) &&
6782  (buf[i+3] == 0x46) && (buf[i+4] == 0x00) ) {
6783  dpi = i + 7;
6784  break;
6785  }
6786  }
6787 
6788  if (i == 20 || dpi+4 >= 20) { // jpeg maker was not found
6789  fclose(fp);
6790  printf("file %s : wrong JPEG format\n", name);
6791  return kFALSE;
6792  }
6793 
6794  buf[dpi] = 1; // format specified in dots per inch
6795 
6796  // set x density in dpi units
6797  buf[dpi + 1] = dpi1;
6798  buf[dpi + 2] = dpi2;
6799 
6800  // set y density in dpi units
6801  buf[dpi + 3] = dpi1;
6802  buf[dpi + 4] = dpi2;
6803 
6804  rewind(fp);
6805  fwrite(buf, 1, 20, fp);
6806  fclose(fp);
6807 
6808  return kTRUE;
6809 }
6810 
6811 ////////////////////////////////////////////////////////////////////////////////
6812 /// Return a valid index in fImage tables to avoid seg-fault by accessing out of
6813 /// indices out of array's ranges.
6814 
6816 {
6817  // The size of arrays like fImage->alt.argb32 is fImage->width*fImage->height
6818  return TMath::Min(idx,(Int_t)(fImage->width*fImage->height));
6819 }
6820 
Int_t fClipXOrigin
Definition: GuiTypes.h:246
const int nx
Definition: kalman.C:16
TString fTitle
Definition: TNamed.h:37
void SetTitle(const char *title="")
Set a title for an image.
Definition: TASImage.cxx:6271
Double_t * Vectorize(UInt_t max_colors=256, UInt_t dither=4, Int_t opaque_threshold=1)
Reduce color-depth of an image and fills vector of "scientific data" [0...1].
Definition: TASImage.cxx:2828
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:929
Definition: GuiTypes.h:76
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
Definition: TASPolyUtils.c:287
Bool_t IsReading() const
Definition: TBuffer.h:83
static void Init()
Initialise the TrueType fonts interface.
Definition: TTF.cxx:67
Short_t fX1
Definition: GuiTypes.h:353
Double_t * fPoints
[fNumPoints] value of each anchor point [0..1]
Definition: TAttImage.h:43
static void FreeStorage(ScanLineListBlock *pSLLBlock)
Definition: TASPolyUtils.c:524
An array of TObjects.
Definition: TObjArray.h:39
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:421
EImageFileTypes
Definition: TImage.h:44
virtual void CellArrayFill(Int_t r, Int_t g, Int_t b)=0
static ASFontManager * gFontManager
Definition: TASImage.cxx:120
static void init_icon_paths()
Set icons paths.
Definition: TASImage.cxx:358
virtual UInt_t GetHeight() const
Definition: TImage.h:237
void DrawDashZTLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t nDash, const char *pDash, UInt_t col, UInt_t thick)
Draw a dashed line with thick pixel width.
Definition: TASImage.cxx:4457
void PutPixel(Int_t x, Int_t y, const char *col="#000000")
Draw a point at the specified position.
Definition: TASImage.cxx:4684
static ARGB32 GetAverage(ARGB32 foreground, ARGB32 background)
Get average.
Definition: TASImage.cxx:3215
virtual void Paint(Option_t *option="")=0
This method must be overridden if a class wants to paint itself.
short Version_t
Definition: RtypesCore.h:61
virtual Color_t GetTextColor() const
Return the text color.
Definition: TAttText.h:40
static Bool_t InitVisual()
Static function to initialize the ASVisual.
Definition: TASImage.cxx:2195
void SetPaletteEnabled(Bool_t on=kTRUE)
Switch on/off the image palette.
Definition: TASImage.cxx:6686
float Float_t
Definition: RtypesCore.h:53
virtual void SetBorderMode(Short_t bordermode)
Definition: TWbox.h:53
virtual Short_t GetTextAlign() const
Return the text alignment.
Definition: TAttText.h:38
return c
const char Option_t
Definition: RtypesCore.h:62
Bool_t IsValid() const
Definition: TASImage.h:186
void DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, const char *col="#000000", UInt_t thick=1, Int_t mode=0)
Draw a box.
Definition: TASImage.cxx:4113
Image class.
Definition: TASImage.h:33
float ymin
Definition: THbookFile.cxx:93
Create a Box.
Definition: TBox.h:36
virtual UInt_t GetWidth() const
Definition: TImage.h:236
static const ASVisual * GetVisual()
Return visual.
Definition: TASImage.cxx:5159
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
EImageFileTypes GetFileType(const char *ext)
Return file type depending on specified extension.
Definition: TASImage.cxx:815
R__EXTERN TStyle * gStyle
Definition: TStyle.h:418
const Double_t * GetArray() const
Definition: TArrayD.h:45
static Bool_t IsInitialized()
Definition: TTF.cxx:618
FT_Glyph fImage
glyph image
Definition: TTF.h:71
unsigned short UShort_t
Definition: RtypesCore.h:36
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:131
#define BIT(n)
Definition: Rtypes.h:120
TH1 * h
Definition: legend2.C:5
void Draw(Option_t *option="")
Draw image.
Definition: TASImage.cxx:1167
virtual Float_t GetTextAngle() const
Return the text angle.
Definition: TAttText.h:39
fill
Definition: fit1_py.py:6
static unsigned long kAllPlanes
Definition: TASImage.cxx:121
char * GetObjectInfo(Int_t px, Int_t py) const
Get image pixel coordinates and the pixel value at the mouse pointer.
Definition: TASImage.cxx:1814
void DrawRectangle(UInt_t x, UInt_t y, UInt_t w, UInt_t h, const char *col="#000000", UInt_t thick=1)
Draw a rectangle.
Definition: TASImage.cxx:4073
void CopyArea(TImage *dst, Int_t xsrc, Int_t ysrc, UInt_t w, UInt_t h, Int_t xdst=0, Int_t ydst=0, Int_t gfunc=3, EColorChan chan=kAllChan)
Copy source region to the destination image.
Definition: TASImage.cxx:5005
virtual const char * HomeDirectory(const char *userName=0)
Return the user&#39;s home directory.
Definition: TSystem.cxx:882
SCoord_t fX
Definition: TPoint.h:37
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
virtual UInt_t * GetArgbArray()
Definition: TImage.h:245
UInt_t GetScaledWidth() const
Return width of the displayed image not of the original image.
Definition: TASImage.cxx:2166
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
#define gROOT
Definition: TROOT.h:364
#define H(x, y, z)
UInt_t GetHeight() const
Return height of original image not of the displayed image.
Definition: TASImage.cxx:2157
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
Bool_t fEditable
! kTRUE image can be resized, moved by resizing/moving gPad
Definition: TASImage.h:68
UInt_t * GetArgbArray()
Return a pointer to internal array[width x height] of ARGB32 values This array is directly accessible...
Definition: TASImage.cxx:3585
Handle_t GContext_t
Definition: GuiTypes.h:39
Int_t LoadPlugin()
Load the plugin library for this handler.
EImageQuality GetImageQuality() const
Definition: TAttImage.h:93
SCoord_t fY
Definition: TPoint.h:38
Basic string class.
Definition: TString.h:137
#define CLRBIT(n, i)
Definition: Rtypes.h:122
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:170
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1089
void StartPaletteEditor()
Start palette editor.
Definition: TASImage.cxx:2249
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Short_t fY1
Definition: GuiTypes.h:353
TArc * a
Definition: textangle.C:12
void ReadImage(const char *file, EImageFileTypes type=TImage::kUnknown)
Read specified image file.
Definition: TASImage.cxx:475
UInt_t GetWidth() const
Return width of original image not of the displayed image.
Definition: TASImage.cxx:2148
const Bool_t kFALSE
Definition: Rtypes.h:92
SCoord_t GetY() const
Definition: TPoint.h:50
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition: TObject.cxx:255
virtual void SetX1(Double_t x1)
Definition: TBox.h:75
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition: TAttFill.h:44
void Zoom(UInt_t offX, UInt_t offY, UInt_t width, UInt_t height)
The area of an image displayed in a pad is defined by this function.
Definition: TASImage.cxx:2021
virtual void CellArrayEnd()=0
void FromPad(TVirtualPad *pad, Int_t x=0, Int_t y=0, UInt_t w=0, UInt_t h=0)
Create an image from the given pad, afterwards this image can be saved in any of the supported image ...
Definition: TASImage.cxx:1068
Handle_t Drawable_t
Definition: GuiTypes.h:32
Int_t fClipYOrigin
Definition: GuiTypes.h:247
An abstract interface to image processing library.
Definition: TImage.h:37
SCoord_t GetX() const
Definition: TPoint.h:49
virtual void Merge(const TImage *, const char *="alphablend", Int_t=0, Int_t=0)
Definition: TImage.h:180
void Browse(TBrowser *)
Browse image.
Definition: TASImage.cxx:6240
void CreateThumbnail()
Create image thumbnail.
Definition: TASImage.cxx:6064
Pixmap_t fClipMask
Definition: GuiTypes.h:248
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
Float_t GetScreenFactor() const
Definition: TStyle.h:256
void DrawLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, const char *col="#000000", UInt_t thick=1)
Draw a line.
Definition: TASImage.cxx:3903
void DrawCubeBezier(Int_t x1, Int_t y1, Int_t x2, Int_t y2, Int_t x3, Int_t y3, const char *col="#000000", UInt_t thick=1)
Draw a cubic bezier line.
Definition: TASImage.cxx:6292
const char * Class
Definition: TXMLSetup.cxx:64
virtual void SetX2(Double_t x2)
Definition: TBox.h:76
XID Colormap
Definition: TGX11.h:40
#define malloc
Definition: civetweb.c:818
Short_t Abs(Short_t d)
Definition: TMathBase.h:110
Bool_t fPaletteEnabled
! kTRUE - palette is drawn on the image
Definition: TAttImage.h:83
UInt_t * GetScanline(UInt_t y)
Return a pointer to scan-line.
Definition: TASImage.cxx:3659
void DrawTextTTF(Int_t x, Int_t y, const char *text, Int_t size, UInt_t color, const char *font_name, Float_t angle)
Draw text using TrueType fonts.
Definition: TASImage.cxx:5930
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
static CARD32 gBrushCache[kBrushCacheSize *kBrushCacheSize]
Definition: TASImage.cxx:5652
static ARGB32 GetShadow(ARGB32 background)
Calculate shadow color.
Definition: TASImage.cxx:3206
UShort_t * fColorRed
[fNumPoints] red color at each anchor point
Definition: TAttImage.h:44
Double_t * GetVecArray()
Return a pointer to internal array[width x height] of double values [0,1].
Definition: TASImage.cxx:2478
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:625
Bool_t SetImageBuffer(char **buffer, EImageFileTypes type=TImage::kPng)
Create image from compressed buffer.
Definition: TASImage.cxx:6017
static THashTable * fgPlugList
! hash table containing loaded plugins
Definition: TASImage.h:72
void PolyPoint(UInt_t npt, TPoint *ppt, const char *col="#000000", TImage::ECoordMode mode=kCoordModeOrigin)
Draw a poly point.
Definition: TASImage.cxx:4719
Short_t fX2
Definition: GuiTypes.h:353
Int_t DistancetoPrimitive(Int_t px, Int_t py)
Is the mouse in the image ?
Definition: TASImage.cxx:1678
void Paint(Option_t *option="")
Paint image.
Definition: TASImage.cxx:1361
const Mask_t kGCClipMask
Definition: GuiTypes.h:306
static const double x2[5]
Int_t Idx(Int_t idx)
Return a valid index in fImage tables to avoid seg-fault by accessing out of indices out of array&#39;s r...
Definition: TASImage.cxx:6815
THashTable implements a hash table to store TObject&#39;s.
Definition: THashTable.h:39
Double_t x[n]
Definition: legend1.C:17
static void LayoutGlyphs()
Compute the glyphs positions, fgAscent and fgWidth (needed for alignment).
Definition: TTF.cxx:183
EColorChan
Definition: TImage.h:98
R__EXTERN Int_t(* gThreadXAR)(const char *xact, Int_t nb, void **ar, Int_t *iret)
Definition: TVirtualPad.h:291
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:442
virtual const char * GetName() const =0
Returns name of object.
void BeginPaint(Bool_t fast=kTRUE)
BeginPaint initializes internal array[width x height] of ARGB32 pixel values.
Definition: TASImage.cxx:3526
static void SetTextFont(Font_t fontnumber)
Set specified font.
Definition: TTF.cxx:496
virtual Float_t GetTextSize() const
Return the text size.
Definition: TAttText.h:42
virtual TObject * FindObject(const char *name) const
Find an object in this collection using its name.
Definition: TObjArray.cxx:396
virtual Int_t GetVersionOwner() const =0
void EndPaint()
EndPaint does internal RLE compression of image data.
Definition: TASImage.cxx:3558
Short_t fY2
Definition: GuiTypes.h:353
#define BRESINCRPGON(d, minval, m, m1, incr1, incr2)
Definition: TASPolyUtils.c:115
const int ny
Definition: kalman.C:17
static void PrepareString(const char *string)
Put the characters in "string" in the "glyphs" array.
Definition: TTF.cxx:249
void DrawCellArray(Int_t x1, Int_t y1, Int_t x2, Int_t y2, Int_t nx, Int_t ny, UInt_t *ic)
Draw a cell array.
Definition: TASImage.cxx:5119
void MapFileTypes(EImageFileTypes &type, UInt_t &astype, Bool_t toas=kTRUE)
Map file type to/from AfterImage types.
Definition: TASImage.cxx:859
TArrayD * GetArray(UInt_t w=0, UInt_t h=0, TImagePalette *pal=gWebImagePalette)
In case of vectorized image return an associated array of doubles otherwise this method creates and r...
Definition: TASImage.cxx:2500
UInt_t fZoomOffY
! Y - offset for zooming im image pixels
Definition: TASImage.h:64
void Gray(Bool_t on=kTRUE)
Convert RGB image to Gray image and vice versa.
Definition: TASImage.cxx:6500
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1628
virtual UInt_t Integer(UInt_t imax)
Returns a random integer on [ 0, imax-1 ].
Definition: TRandom.cxx:320
static UInt_t AlphaBlend(UInt_t bot, UInt_t top)
Return alpha-blended value computed from bottom and top pixel values.
Definition: TASImage.cxx:5148
static void loadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
Definition: TASPolyUtils.c:455
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2221
void WriteImage(const char *file, EImageFileTypes type=TImage::kUnknown)
Write image to specified file.
Definition: TASImage.cxx:644
virtual void * GetStream() const
Definition: TVirtualPS.h:81
Base class for several text objects.
Definition: TText.h:33
virtual void Draw(Option_t *option="")
Draw this frame with its current attributes.
Definition: TFrame.cxx:69
static TTGlyph * GetGlyphs()
Definition: TTF.cxx:660
static ASDrawContext * create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
Create draw context.
Definition: TASImage.cxx:5626
void DrawFillArea(UInt_t npt, TPoint *ppt, const char *col="#000000", const char *stipple=0, UInt_t w=16, UInt_t h=16)
Fill a polygon (any type convex, non-convex).
Definition: TASImage.cxx:5423
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:467
static int GetPolyYBounds(TPoint *pts, int n, int *by, int *ty)
Get poly bounds along Y.
Definition: TASImage.cxx:5167
Double_t ATan2(Double_t, Double_t)
Definition: TMath.h:454
virtual const TImagePalette & GetPalette() const
Definition: TAttImage.h:94
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:59
static ULong_t RGB2Pixel(Int_t r, Int_t g, Int_t b)
Convert r,g,b to graphics system dependent pixel value.
Definition: TColor.cxx:1954
void Scale(UInt_t width, UInt_t height)
Scale the original image.
Definition: TASImage.cxx:1911
void DrawGlyph(void *bitmap, UInt_t color, Int_t x, Int_t y)
Draw glyph bitmap.
Definition: TASImage.cxx:5704
virtual Int_t GetPixmapID() const =0
void Pad(const char *color="#00FFFFFF", UInt_t left=0, UInt_t right=0, UInt_t top=0, UInt_t bottom=0)
Enlarge image, padding it with specified color on each side in accordance with requested geometry...
Definition: TASImage.cxx:3359
Int_t fPaintMode
! 1 - fast mode, 0 - low memory slow mode
Definition: TASImage.h:69
Definition: TPoint.h:33
void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TASImage.cxx:6715
TArrayL * GetPixels(Int_t x=0, Int_t y=0, UInt_t w=0, UInt_t h=0)
Return 2D array of machine dependent pixel values.
Definition: TASImage.cxx:2406
void DrawDashZLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t nDash, const char *pDash, UInt_t col)
Draw a dashed line with one pixel width.
Definition: TASImage.cxx:4273
Element * GetMatrixArray()
Definition: TVectorT.h:84
void DrawDashHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t nDash, const char *pDash, UInt_t col, UInt_t thick)
Draw a dashed horizontal line.
Definition: TASImage.cxx:4162
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:46
virtual Int_t UtoPixel(Double_t u) const =0
void GetZoomPosition(UInt_t &x, UInt_t &y, UInt_t &w, UInt_t &h) const
Return the zoom parameters.
Definition: TASImage.cxx:2184
Bool_t SetJpegDpi(const char *name, UInt_t dpi=72)
Set an image printing resolution in Dots Per Inch units.
Definition: TASImage.cxx:6759
void FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, const char *col="#000000", const char *stipple=0, UInt_t w=16, UInt_t h=16)
Fill spans with specified color or/and stipple.
Definition: TASImage.cxx:4802
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:229
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:41
void DrawCircle(Int_t x, Int_t y, Int_t r, const char *col="#000000", Int_t thick=1)
Draw a circle.
Definition: TASImage.cxx:6373
RooArgSet S(const RooAbsArg &v1)
R__EXTERN const char * gProgName
Definition: TSystem.h:234
void UnZoom()
Un-zoom the image to original size.
Definition: TASImage.cxx:2043
void FillRectangleInternal(UInt_t col, Int_t x, Int_t y, UInt_t width, UInt_t height)
Fill rectangle of size (width, height) at position (x,y) within the existing image with specified col...
Definition: TASImage.cxx:3729
Bool_t fIsGray
! kTRUE if image is gray
Definition: TASImage.h:71
void SetImage(const Double_t *imageData, UInt_t width, UInt_t height, TImagePalette *palette=0)
Deletes the old image and creates a new image depending on the values of imageData.
Definition: TASImage.cxx:981
float ymax
Definition: THbookFile.cxx:93
virtual void PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax, Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt="", Double_t gridlength=0, Bool_t drawGridOnly=kFALSE)
Control function to draw an axis.
Definition: TGaxis.cxx:742
static char * gIconPaths[7]
Definition: TASImage.cxx:125
void Append(const TImage *im, const char *option="+", const char *color="#00000000")
Append image.
Definition: TASImage.cxx:3485
void SetPalette(const TImagePalette *palette)
Set a new palette to an image.
Definition: TASImage.cxx:1855
void DrawWideLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t col, UInt_t thick)
Draw wide line.
Definition: TASImage.cxx:5657
TPaveText * pt
static Int_t GetWidth()
Definition: TTF.cxx:625
TRandom2 r(17)
Double_t fMaxValue
! max value in image
Definition: TASImage.h:61
UInt_t GetScaledHeight() const
Return height of the displayed image not of the original image.
Definition: TASImage.cxx:2175
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
const char * GetTitle() const
Title is used to keep 32x32 xpm image&#39;s thumbnail.
Definition: TASImage.cxx:6253
Int_t GetSize() const
Definition: TArray.h:49
SVector< double, 2 > v
Definition: Dict.h:5
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
void Merge(const TImage *im, const char *op="alphablend", Int_t x=0, Int_t y=0)
Merge two images.
Definition: TASImage.cxx:2714
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:42
#define FillSpansInternal(npt, ppt, widths, color)
Definition: TASImage.cxx:3717
const Mask_t kGCClipXOrigin
Definition: GuiTypes.h:304
void FromWindow(Drawable_t wid, Int_t x=0, Int_t y=0, UInt_t w=0, UInt_t h=0)
Create an image (screenshot) from specified window.
Definition: TASImage.cxx:6614
virtual Font_t GetTextFont() const
Return the text font.
Definition: TAttText.h:41
Long_t ExecPlugin(int nargs, const T &... params)
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:496
TImagePalette fPalette
color palette for value -> color conversion
Definition: TAttImage.h:81
void FloodFill(Int_t x, Int_t y, const char *col, const char *min_col, const char *max_col=0)
Flood fill.
Definition: TASImage.cxx:6492
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:488
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:558
void CropPolygon(UInt_t npt, TPoint *ppt)
Crop a convex polygon.
Definition: TASImage.cxx:5397
static FT_Matrix * GetRotMatrix()
Definition: TTF.cxx:646
void CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths)
Crop spans.
Definition: TASImage.cxx:4917
UShort_t * fColorAlpha
[fNumPoints] alpha at each anchor point
Definition: TAttImage.h:47
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2322
unsigned int UInt_t
Definition: RtypesCore.h:42
TTF helper class containing glyphs description.
Definition: TTF.h:67
void Slice(UInt_t xStart, UInt_t xEnd, UInt_t yStart, UInt_t yEnd, UInt_t toWidth, UInt_t toHeight)
Another method of enlarging images where corners remain unchanged, but middle part gets tiled...
Definition: TASImage.cxx:1945
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:925
char * Form(const char *fmt,...)
const Handle_t kNone
Definition: GuiTypes.h:89
virtual void CellArrayBegin(Int_t W, Int_t H, Double_t x1, Double_t x2, Double_t y1, Double_t y2)=0
Ssiz_t Length() const
Definition: TString.h:390
UInt_t GetImageCompression() const
Definition: TAttImage.h:92
Pixmap_t GetMask()
Returns image mask pixmap (alpha channel).
Definition: TASImage.cxx:2300
virtual void SetPalette(const TImagePalette *palette)
Set a new palette for the image.
Definition: TAttImage.cxx:650
Array of longs (32 or 64 bits per element).
Definition: TArrayL.h:29
void AddAt(Long_t c, Int_t i)
Add long c at position i. Check for out of bounds.
Definition: TArrayL.cxx:93
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1070
TLine * l
Definition: textangle.C:4
const Mask_t kGCClipYOrigin
Definition: GuiTypes.h:305
Int_t GetNoElements() const
Definition: TVectorT.h:82
The axis painter class.
Definition: TGaxis.h:30
void FillPolygon(UInt_t npt, TPoint *ppt, const char *col="#000000", const char *stipple=0, UInt_t w=16, UInt_t h=16)
Fill a convex polygon with background color or bitmap.
Definition: TASImage.cxx:5341
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
void Blur(Double_t hr=3, Double_t vr=3)
Perform Gaussian blur of the image (useful for drop shadows).
Definition: TASImage.cxx:2753
UInt_t fNumPoints
number of anchor points
Definition: TAttImage.h:42
virtual Int_t GetCanvasID() const =0
UInt_t fZoomOffX
! X - offset for zooming in image pixels
Definition: TASImage.h:63
void MapQuality(EImageQuality &quality, UInt_t &asquality, Bool_t toas=kTRUE)
Map quality to/from AfterImage quality.
Definition: TASImage.cxx:944
static void CreateETandAET(int count, TPoint *pts, EdgeTable *ET, EdgeTableEntry *AET, EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock)
Definition: TASPolyUtils.c:365
Bool_t IsEditable() const
Definition: TASImage.h:97
void Flip(Int_t flip=180)
Flip image in place.
Definition: TASImage.cxx:2071
R__EXTERN TRandom * gRandom
Definition: TRandom.h:66
static int InsertionSort(EdgeTableEntry *AET)
Definition: TASPolyUtils.c:485
UShort_t * fColorBlue
[fNumPoints] blue color at each anchor point
Definition: TAttImage.h:46
TString fName
Definition: TNamed.h:36
virtual void ReadFastArray(Bool_t *b, Int_t n)=0
virtual void WriteFastArray(const Bool_t *b, Int_t n)=0
virtual ~TASImage()
Image destructor, clean up image and visual.
Definition: TASImage.cxx:348
#define gVirtualX
Definition: TVirtualX.h:362
static const UInt_t NUMPTSTOBUFFER
Definition: TASImage.cxx:5418
TASImage * fScaledImage
! temporary scaled and zoomed image produced from original image
Definition: TASImage.h:60
void FillRectangle(const char *col=0, Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0)
Fill rectangle of size (width, height) at position (x,y) within the existing image with specified col...
Definition: TASImage.cxx:3807
Define a Frame.
Definition: TFrame.h:21
Double_t Cos(Double_t)
Definition: TMath.h:424
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2514
void HSV(UInt_t hue=0, UInt_t radius=360, Int_t H=0, Int_t S=0, Int_t V=0, Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0)
This function will tile original image to specified size with offsets requested, and then it will go ...
Definition: TASImage.cxx:2940
virtual void SetY2(Double_t y2)
Definition: TBox.h:78
Bool_t fConstRatio
keep aspect ratio of image on the screen
Definition: TAttImage.h:80
UInt_t * GetRgbaArray()
Return a pointer to an array[width x height] of RGBA32 values.
Definition: TASImage.cxx:3613
long Long_t
Definition: RtypesCore.h:50
Color * colors
Definition: X3DBuffer.c:19
void Tile(UInt_t width, UInt_t height)
Tile the original image.
Definition: TASImage.cxx:1981
Int_t fZoomUpdate
! kZoom - new zooming required, kZoomOps - other ops in action, kNoZoom - no zooming or ops ...
Definition: TASImage.h:67
void DrawText(Int_t x=0, Int_t y=0, const char *text="", Int_t size=12, const char *color=0, const char *font="fixed", EText3DType type=TImage::kPlain, const char *fore_file=0, Float_t angle=0)
Draw text of size (in pixels for TrueType fonts) at position (x, y) with color specified by hex strin...
Definition: TASImage.cxx:2578
void Bevel(Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0, const char *hi="#ffdddddd", const char *lo="#ff555555", UShort_t thick=1, Bool_t pressed=kFALSE)
Bevel is used to create 3D effect while drawing buttons, or any other image that needs to be framed...
Definition: TASImage.cxx:3243
TObject * FindObject(const char *name) const
Find object using its name.
Definition: THashTable.cxx:210
void DrawPolyLine(UInt_t nn, TPoint *xy, const char *col="#000000", UInt_t thick=1, TImage::ECoordMode mode=kCoordModeOrigin)
Draw a polyline.
Definition: TASImage.cxx:4659
static const double x1[5]
void Crop(Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0)
Crop an image.
Definition: TASImage.cxx:3408
#define ClassImp(name)
Definition: Rtypes.h:279
struct _EdgeTableEntry EdgeTableEntry
void Mirror(Bool_t vert=kTRUE)
Mirror image in place.
Definition: TASImage.cxx:2118
static Int_t GetAscent()
Definition: TTF.cxx:632
void DrawEllips(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle, const char *col="#000000", Int_t thick=1)
Draw an ellipse.
Definition: TASImage.cxx:6413
double Double_t
Definition: RtypesCore.h:55
void PaintImage(Drawable_t wid, Int_t x, Int_t y, Int_t xsrc=0, Int_t ysrc=0, UInt_t wsrc=0, UInt_t hsrc=0, Option_t *opt="")
Draw image on the drawable wid (pixmap, window) at x,y position.
Definition: TASImage.cxx:1341
TText * text
int type
Definition: TGX11.cxx:120
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
#define free
Definition: civetweb.c:821
unsigned long ULong_t
Definition: RtypesCore.h:51
UInt_t fZoomHeight
! hight of zoomed image in image pixels
Definition: TASImage.h:66
ECoordMode
Definition: TImage.h:93
virtual Int_t FindColor(UShort_t r, UShort_t g, UShort_t b)
Returns an index of the closest color.
Definition: TAttImage.cxx:485
Double_t y[n]
Definition: legend1.C:17
static ARGB32 GetHilite(ARGB32 background)
Calculate highlite color.
Definition: TASImage.cxx:3194
static void destroy_asdraw_context32(ASDrawContext *ctx)
Destroy asdraw context32.
Definition: TASImage.cxx:5643
void Add(TObject *obj)
Add object to the hash table.
Definition: THashTable.cxx:76
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
void DrawDashLine(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t nDash, const char *pDash, const char *col="#000000", UInt_t thick=1)
Draw a dashed line.
Definition: TASImage.cxx:4615
#define _MEMSET_(dst, lng, val)
Definition: TASImage.cxx:3712
The color creation and management class.
Definition: TColor.h:23
struct _ScanLineListBlock ScanLineListBlock
static CARD8 MakeComponentHilite(int cmp)
Make component hilite.
Definition: TASImage.cxx:3180
void GetImageBuffer(char **buffer, int *size, EImageFileTypes type=TImage::kPng)
Return in-memory buffer compressed according image type.
Definition: TASImage.cxx:5965
void FromGLBuffer(UChar_t *buf, UInt_t w, UInt_t h)
Creates an image (screenshot) from a RGBA buffer.
Definition: TASImage.cxx:6665
#define _alphaBlend(bot, top)
Definition: TASImage.cxx:151
TImage & operator=(const TImage &img)
Definition: TImage.h:112
A class to define a conversion from pixel values to pixel color.
Definition: TAttImage.h:39
void DrawLineInternal(UInt_t x1, UInt_t y1, UInt_t x2, UInt_t y2, UInt_t col, UInt_t thick)
Internal line drawing.
Definition: TASImage.cxx:3914
TObject * Clone(const char *newname) const
Clone image.
Definition: TASImage.cxx:2782
Array of doubles (64 bits per element).
Definition: TArrayD.h:29
Bool_t IsNull() const
Definition: TString.h:387
virtual void Draw(Option_t *option="")
Draw this box with its current attributes.
Definition: TBox.cxx:180
#define SETBIT(n, i)
Definition: Rtypes.h:121
Mother of all ROOT objects.
Definition: TObject.h:37
Double_t fMinValue
! min value in image
Definition: TASImage.h:62
void DrawDashVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t nDash, const char *pDash, UInt_t col, UInt_t thick)
Draw a dashed vertical line.
Definition: TASImage.cxx:4216
static void SetRotationMatrix(Float_t angle)
Set the rotation matrix used to rotate the font outlines.
Definition: TTF.cxx:341
typedef void((*Func_t)())
static ASVisual * fgVisual
pointer to visual structure
Definition: TASImage.h:74
Handle_t Window_t
Definition: GuiTypes.h:30
UShort_t * fColorGreen
[fNumPoints] green color at each anchor point
Definition: TAttImage.h:45
Mask_t fMask
Definition: GuiTypes.h:252
TASImage()
Default image constructor.
Definition: TASImage.cxx:217
void AddAt(Double_t c, Int_t i)
Add double c at position i. Check for out of bounds.
Definition: TArrayD.cxx:93
static Bool_t fgInit
global flag to init afterimage only once
Definition: TASImage.h:75
void DrawEllips2(Int_t x, Int_t y, Int_t rx, Int_t ry, Int_t angle, const char *col="#000000", Int_t thick=1)
Draw an ellipse.
Definition: TASImage.cxx:6453
virtual Int_t VtoPixel(Double_t v) const =0
const Ssiz_t kNPOS
Definition: Rtypes.h:115
const char * TypeFromMagicNumber(const char *file)
Guess the file type from the first byte of file.
Definition: TASImage.cxx:392
void DrawSegments(UInt_t nseg, Segment_t *seg, const char *col="#000000", UInt_t thick=1)
Draw segments.
Definition: TASImage.cxx:4779
Definition: file.py:1
void DrawStraightEllips(Int_t x, Int_t y, Int_t rx, Int_t ry, const char *col="#000000", Int_t thick=1)
Draw a straight ellipse.
Definition: TASImage.cxx:6333
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
Handle_t Pixmap_t
Definition: GuiTypes.h:31
struct _ScanLineList ScanLineList
Double_t Sin(Double_t)
Definition: TMath.h:421
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
Definition: TRolke.cxx:630
#define NULL
Definition: Rtypes.h:82
const void * GetWcsTitle(void) const
Returns the text as UNICODE.
Definition: TText.cxx:130
#define snprintf
Definition: civetweb.c:822
R__EXTERN TVirtualPS * gVirtualPS
Definition: TVirtualPS.h:91
Int_t GetNumber() const
Definition: TColor.h:58
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
#define gPad
Definition: TVirtualPad.h:289
virtual void StartPaletteEditor()
Opens a GUI to edit the color palette.
Definition: TAttImage.cxx:779
TASImage & operator=(const TASImage &img)
Image assignment operator.
Definition: TASImage.cxx:314
Int_t CountChar(Int_t c) const
Return number of times character c occurs in the string.
Definition: TString.cxx:444
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1965
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2)
Definition: TASPolyUtils.c:93
static void SetTextSize(Float_t textsize)
Set current text size.
Definition: TTF.cxx:572
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1807
float type_of_call hi(const int &, const int &)
#define gDirectory
Definition: TDirectory.h:221
double result[121]
unsigned char UChar_t
Definition: RtypesCore.h:34
TVirtualPS is an abstract interface to Postscript, PDF, SVG.
Definition: TVirtualPS.h:40
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1244
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
Definition: triangle.c:7889
const int nn
UInt_t fZoomWidth
! width of zoomed image in image pixels
Definition: TASImage.h:65
ASImage * fGrayImage
! gray image
Definition: TASImage.h:70
EText3DType
Definition: TImage.h:66
static TImage * Create()
Create an image.
Definition: TImage.cxx:36
void DestroyImage()
Destroy image.
Definition: TASImage.cxx:172
const char * AsHexString() const
Return color as hexadecimal string.
Definition: TColor.cxx:1174
void DrawHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t col, UInt_t thick)
Draw an horizontal line.
Definition: TASImage.cxx:3868
static const UInt_t kBrushCacheSize
Definition: TASImage.cxx:5651
static Int_t GetNumGlyphs()
Definition: TTF.cxx:639
const Bool_t kTRUE
Definition: Rtypes.h:91
float * q
Definition: THbookFile.cxx:87
Pixmap_t GetPixmap()
Returns image pixmap.
Definition: TASImage.cxx:2268
virtual void SetY1(Double_t y1)
Definition: TBox.h:77
Int_t Nint(T x)
Definition: TMath.h:480
ASImage * fImage
! pointer to image structure of original image
Definition: TASImage.h:59
Bool_t GetPolygonSpans(UInt_t npt, TPoint *ppt, UInt_t *nspans, TPoint **firstPoint, UInt_t **firstWidth)
The code is based on Xserver/mi/mipolycon.c "Copyright 1987, 1998 The Open Group".
Definition: TASImage.cxx:5196
void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Execute mouse events.
Definition: TASImage.cxx:1701
const Int_t n
Definition: legend1.C:16
void SetDefaults()
Set default parameters.
Definition: TASImage.cxx:190
EGraphicsFunction
Definition: GuiTypes.h:68
virtual void Open(const char *filename, Int_t type=-111)=0
To make it possible to use GL for 2D graphic in a TPad/TCanvas.
virtual unsigned char * ReadFile(const char *filename, UInt_t &w, UInt_t &h)=0
char name[80]
Definition: TGX11.cxx:109
static void Image2Drawable(ASImage *im, Drawable_t wid, Int_t x, Int_t y, Int_t xsrc=0, Int_t ysrc=0, UInt_t wsrc=0, UInt_t hsrc=0, Option_t *opt="")
Draw asimage on drawable.
Definition: TASImage.cxx:1219
void Gradient(UInt_t angle=0, const char *colors="#FFFFFF #000000", const char *offsets=0, Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0)
Render multipoint gradient inside rectangle of size (width, height) at position (x,y) within the existing image.
Definition: TASImage.cxx:3003
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:911
if(line.BeginsWith("/*"))
Definition: HLFactory.cxx:443
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
static const FT_BBox & GetBox()
Definition: TTF.cxx:653
Bool_t GetConstRatio() const
Definition: TAttImage.h:91
virtual TCanvas * GetCanvas() const =0
static const double x3[11]
void DrawVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t col, UInt_t thick)
Draw a vertical line.
Definition: TASImage.cxx:3833
virtual void BeginPaint(Bool_t=kTRUE)
Definition: TImage.h:190
const char * Data() const
Definition: TString.h:349