Logo ROOT  
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
38Image class.
39
40TASImage is the concrete interface to the image processing library
41libAfterImage.
42
43It allows reading and writing of images in different formats, several image
44manipulations (scaling, tiling, merging, etc.) and displaying in pads. The size
45of the image on the screen does not depend on the original size of the image but
46on the size of the pad. Therefore it is very easy to resize the image on the
47screen by resizing the pad.
48
49Besides reading an image from a file an image can be defined by a two
50dimensional array of values. A palette defines the color of each value.
51
52The image can be zoomed by defining a rectangle with the mouse. The color
53palette can be modified with a GUI, just select StartPaletteEditor() from the
54context menu.
55
56Several examples showing how to use this class are available in the
57ROOT 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#ifndef WIN32
98#ifdef R__HAS_COCOA
99# define X_DISPLAY_MISSING 1
100#endif
101# include <afterbase.h>
102#else
103# include <win32/config.h>
104# include <win32/afterbase.h>
105# define X_DISPLAY_MISSING 1
106#endif
107# include <afterimage.h>
108# include <bmp.h>
109extern "C" {
110# include <draw.h>
111}
112
113// auxiliary functions for general polygon filling
114#include "TASPolyUtils.c"
115
116
117ASVisual *TASImage::fgVisual = 0;
119
120static ASFontManager *gFontManager = 0;
121static unsigned long kAllPlanes = ~0;
123
124// default icon paths
125static char *gIconPaths[7] = {0, 0, 0, 0, 0, 0, 0};
126
127// To scale fonts to the same size as the old TT version
128const Float_t kScale = 0.985;
129
130///////////////////////////// alpha-blending macros ///////////////////////////////
131
132#if defined(__GNUC__) && __GNUC__ >= 4 && ((__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ >= 1) || (__GNUC_MINOR__ >= 3)) && !__INTEL_COMPILER
133#pragma GCC diagnostic ignored "-Wstrict-aliasing"
134#endif
135
136#ifdef R__BYTESWAP
137typedef struct {
138 unsigned char b;
139 unsigned char g;
140 unsigned char r;
141 unsigned char a;
142} __argb32__;
143#else
144typedef struct {
145 unsigned char a;
146 unsigned char r;
147 unsigned char g;
148 unsigned char b;
149} __argb32__;
150#endif
151
152
153//______________________________________________________________________________
154#define _alphaBlend(bot, top) {\
155 __argb32__ *T = (__argb32__*)(top);\
156 __argb32__ *B = (__argb32__*)(bot);\
157 int aa = 255-T->a;\
158 if (!aa) {\
159 *bot = *top;\
160 } else { \
161 B->a = ((B->a*aa)>>8) + T->a;\
162 B->r = (B->r*aa + T->r*T->a)>>8;\
163 B->g = (B->g*aa + T->g*T->a)>>8;\
164 B->b = (B->b*aa + T->b*T->a)>>8;\
165 }\
166}\
167
168
171
172////////////////////////////////////////////////////////////////////////////////
173/// Destroy image.
174
176{
177 if (fImage) {
178 destroy_asimage(&fImage);
179 }
180
181 if (fIsGray && fGrayImage) {
182 destroy_asimage(&fGrayImage);
183 }
184
185 fIsGray = kFALSE;
186 fGrayImage = 0;
187 fImage = 0;
188}
189
190////////////////////////////////////////////////////////////////////////////////
191/// Set default parameters.
192
194{
195 fImage = 0;
196 fScaledImage = 0;
197 fMaxValue = 1;
198 fMinValue = 0;
200 fPaintMode = 1;
201 fZoomOffX = 0;
202 fZoomOffY = 0;
203 fZoomWidth = 0;
204 fZoomHeight = 0;
206
207 fGrayImage = 0;
208 fIsGray = kFALSE;
210
211 if (!fgInit) {
212 set_application_name((char*)(gProgName ? gProgName : "ROOT"));
213 fgInit = kTRUE;
214 }
215}
216
217////////////////////////////////////////////////////////////////////////////////
218/// Default image constructor.
219
221{
222 SetDefaults();
223}
224
225////////////////////////////////////////////////////////////////////////////////
226/// Create an empty image.
227
229{
230 SetDefaults();
231 fImage = create_asimage(w ? w : 20, h ? h : 20, 0);
232 UnZoom();
233}
234
235////////////////////////////////////////////////////////////////////////////////
236/// Create an image object and read from specified file.
237/// For more information see description of function ReadImage()
238/// which is called by this constructor.
239
241{
242 SetDefaults();
243 TString fname = file;
244 gSystem->ExpandPathName(fname);
245 ReadImage(fname.Data());
246}
247
248////////////////////////////////////////////////////////////////////////////////
249/// Create an image depending on the values of imageData.
250/// For more information see function SetImage() which is called
251/// by this constructor.
252
253TASImage::TASImage(const char *name, const Double_t *imageData, UInt_t width,
254 UInt_t height, TImagePalette *palette) : TImage(name)
255{
256 SetDefaults();
257 SetImage(imageData, width, height, palette);
258}
259
260////////////////////////////////////////////////////////////////////////////////
261/// Create an image depending on the values of imageData.
262/// The size of the image is width X (imageData.fN / width).
263/// For more information see function SetImage() which is called by
264/// this constructor.
265
266TASImage::TASImage(const char *name, const TArrayD &imageData, UInt_t width,
267 TImagePalette *palette) : TImage(name)
268{
269 SetDefaults();
270 SetImage(imageData, width, palette);
271}
272
273////////////////////////////////////////////////////////////////////////////////
274/// Create an image depending on the values of imageData.
275/// The size of the image is width X (imageData.fN / width).
276/// For more information see function SetImage() which is called by
277/// this constructor.
278
279TASImage::TASImage(const char *name, const TVectorD &imageData, UInt_t width,
280 TImagePalette *palette) : TImage(name)
281{
282 SetDefaults();
283 SetImage(imageData, width, palette);
284}
285
286////////////////////////////////////////////////////////////////////////////////
287/// Image copy constructor.
288
290{
291 SetDefaults();
292
293 if (img.IsValid()) {
294 fImage = clone_asimage(img.fImage, SCL_DO_ALL);
296 fGrayImage = fGrayImage ? clone_asimage(img.fGrayImage, SCL_DO_ALL) : 0;
297
298 if (img.fImage->alt.vector) {
299 Int_t size = img.fImage->width * img.fImage->height * sizeof(double);
300 fImage->alt.vector = (double*)malloc(size);
301 memcpy(fImage->alt.vector, img.fImage->alt.vector, size);
302 }
303
305 fZoomOffX = img.fZoomOffX;
306 fZoomOffY = img.fZoomOffY;
309 fEditable = img.fEditable;
310 fIsGray = img.fIsGray;
311 }
312}
313
314////////////////////////////////////////////////////////////////////////////////
315/// Image assignment operator.
316
318{
319 if (this != &img && img.IsValid()) {
321
322 DestroyImage();
323 delete fScaledImage;
324 fImage = clone_asimage(img.fImage, SCL_DO_ALL);
326 fGrayImage = fGrayImage ? clone_asimage(img.fGrayImage, SCL_DO_ALL) : 0;
327
328 if (img.fImage->alt.vector) {
329 Int_t size = img.fImage->width * img.fImage->height * sizeof(double);
330 fImage->alt.vector = (double*)malloc(size);
331 memcpy(fImage->alt.vector, img.fImage->alt.vector, size);
332 }
333
334 fScaledImage = img.fScaledImage ? (TASImage*)img.fScaledImage->Clone("") : 0;
336 fZoomOffX = img.fZoomOffX;
337 fZoomOffY = img.fZoomOffY;
340 fEditable = img.fEditable;
341 fIsGray = img.fIsGray;
342 fPaintMode = 1;
343 }
344
345 return *this;
346}
347
348////////////////////////////////////////////////////////////////////////////////
349/// Image destructor, clean up image and visual.
350
352{
353 DestroyImage();
354 delete fScaledImage;
355 fScaledImage = 0;
356}
357
358////////////////////////////////////////////////////////////////////////////////
359/// Set icons paths.
360
361static void init_icon_paths()
362{
363 TString icon_path = gEnv->GetValue("Gui.IconPath", "");
364 if (icon_path.IsNull()) {
365 icon_path = "icons";
367#ifndef R__WIN32
368 icon_path = ".:" + icon_path + ":" + TROOT::GetIconPath() + ":" + EXTRAICONPATH;
369#else
370 icon_path = ".;" + icon_path + ";" + TROOT::GetIconPath() + ";" + EXTRAICONPATH;
371#endif
372 }
373
374 Int_t cnt = 0;
375 Ssiz_t from = 0;
376 TString token;
377#ifndef R__WIN32
378 const char *delim = ":";
379#else
380 const char *delim = ";";
381#endif
382 while (icon_path.Tokenize(token, from, delim) && cnt < 6) {
383 char *path = gSystem->ExpandPathName(token.Data());
384 if (path) {
385 gIconPaths[cnt] = path;
386 cnt++;
387 }
388 }
389 gIconPaths[cnt] = 0;
390}
391
392////////////////////////////////////////////////////////////////////////////////
393/// Guess the file type from the first byte of file.
394
395const char *TASImage::TypeFromMagicNumber(const char *file)
396{
397 UChar_t magic;
398 FILE *fp = fopen(file, "rb");
399 const char *ret = "";
400
401 if (!fp) return 0;
402
403 if (!fread(&magic, 1, 1, fp)) {
404 fclose(fp);
405 return 0;
406 }
407
408 switch (magic) {
409 case 0x00:
410 {
411 if (!fread(&magic, 1, 1, fp)) {
412 fclose(fp);
413 return 0;
414 }
415 if (!fread(&magic, 1, 1, fp)) {
416 fclose(fp);
417 return 0;
418 }
419
420 ret = (magic == 1) ? "ico" : "cur";
421 break;
422 }
423 case 0x25:
424 {
425 if (!fread(&magic, 1, 1, fp)) {
426 fclose(fp);
427 return 0;
428 }
429
430 if (magic == 0x21) ret = "ps";
431 else if (magic == 0x50) ret = "pdf";
432 break;
433 }
434 case 0x42:
435 ret = "bmp";
436 break;
437 case 0x47:
438 ret = "gif";
439 break;
440 case 0x54:
441 ret = "tga";
442 break;
443 case 0x49:
444 ret = "tiff";
445 break;
446 case 0x89:
447 ret = "png";
448 break;
449 case 0xff:
450 ret = "jpg";
451 break;
452 default:
453 ret = "";
454 }
455
456 fclose(fp);
457 return ret;
458}
459
460////////////////////////////////////////////////////////////////////////////////
461/// Read specified image file.
462/// The file type is determined by the file extension (the type argument is
463/// ignored). It will attempt to append .gz and then .Z to the filename and
464/// find such a file. If the filename ends with extension consisting of digits
465/// only, it will attempt to find the file with this extension stripped
466/// off. On success this extension will be used to load subimage from
467/// the file with that number. Subimage is supported for GIF files
468/// (ICO, BMP, CUR, TIFF, XCF to be supported in future).
469/// For example,
470/// ~~~ {.cpp}
471/// i1 = TImage::Open("anim.gif.0"); // read the first subimage
472/// i4 = TImage::Open("anim.gif.3"); // read the forth subimage
473/// ~~~
474/// It is also possible to put XPM raw string (see also SetImageBuffer) as
475/// the first input parameter ("filename"), such string is returned by
476/// GetImageBuffer method.
477
478void TASImage::ReadImage(const char *filename, EImageFileTypes /*type*/)
479{
480 if (!InitVisual()) {
481 Warning("Scale", "Visual not initiated");
482 return;
483 }
484
485 Bool_t xpm = filename && (filename[0] == '/' &&
486 filename[1] == '*') && filename[2] == ' ';
487
488 if (xpm) { // XPM strings in-memory array
489 SetImageBuffer((char**)&filename, TImage::kXpm);
490 fName = "XPM_image";
491 return;
492 }
493
494 if (!gIconPaths[0]) {
496 }
497 // suppress the "root : looking for image ..." messages
498 set_output_threshold(0);
499
500 static ASImageImportParams iparams;
501 iparams.flags = 0;
502 iparams.width = 0;
503 iparams.height = 0;
504 iparams.filter = SCL_DO_ALL;
505 iparams.gamma = SCREEN_GAMMA;
506 iparams.gamma_table = NULL;
507 iparams.compression = GetImageCompression();
508 iparams.format = ASA_ASImage;
509 iparams.search_path = gIconPaths;
510 iparams.subimage = 0;
511 iparams.return_animation_delay = -1;
512
513 TString ext;
514 const char *dot;
515 if (filename) dot = strrchr(filename, '.');
516 else dot = 0;
517 ASImage *image = 0;
518 TString fname = filename;
519
520 if (!dot) {
521 if (filename) ext = TypeFromMagicNumber(filename);
522 else ext = dot + 1;
523 } else {
524 ext = dot + 1;
525 }
526
527 if (!ext.IsNull() && ext.IsDigit()) { // read subimage
528 iparams.subimage = ext.Atoi();
529 fname = fname(0, fname.Length() - ext.Length() - 1);
530 ext = strrchr(fname.Data(), '.') + 1;
531 }
532
533 image = file2ASImage_extra(fname.Data(), &iparams);
534
535 if (image) { // it's OK
536 goto end;
537 } else { // try to read it via plugin
538 if (ext.IsNull()) {
539 return;
540 }
541 ext.ToLower();
542 ext.Strip();
543 UInt_t w = 0;
544 UInt_t h = 0;
545 unsigned char *bitmap = 0;
546
548
549 if (!plug) {
550 TPluginHandler *handler = gROOT->GetPluginManager()->FindHandler("TImagePlugin", ext);
551 if (!handler || ((handler->LoadPlugin() == -1))) {
552 return;
553 }
554 plug = (TImagePlugin*)handler->ExecPlugin(1, ext.Data());
555
556 if (!plug) {
557 return;
558 }
559
560 fgPlugList->Add(plug);
561 }
562
563 if (plug) {
564 if (plug->InheritsFrom(TASImagePlugin::Class())) {
565 image = ((TASImagePlugin*)plug)->File2ASImage(fname.Data());
566 if (image) goto end;
567 }
568 bitmap = plug->ReadFile(fname.Data(), w, h);
569 if (bitmap) {
570 image = bitmap2asimage(bitmap, w, h, 0, 0);
571 }
572 if (!image) {
573 return;
574 }
575 }
576 }
577
578end:
579 fName.Form("%s.", gSystem->BaseName(fname.Data()));
580
581 DestroyImage();
582 delete fScaledImage;
583 fScaledImage = 0;
584
585 fImage = image;
588 fZoomOffX = 0;
589 fZoomOffY = 0;
590 fZoomWidth = fImage->width;
591 fZoomHeight = fImage->height;
592 fPaintMode = 1;
593}
594
595////////////////////////////////////////////////////////////////////////////////
596/// Write image to specified file.
597///
598/// If there is no file extension or if the file extension is unknown, the
599/// type argument will be used to determine the file type. The quality and
600/// compression is derived from the TAttImage values.
601///
602/// It's possible to write image into an animated GIF file by specifying file
603/// name as "myfile.gif+" or "myfile.gif+NN", where NN is the delay of displaying
604/// subimages during animation in 10ms seconds units. NN is not restricted
605/// to two digits. If NN is omitted the delay between subimages is zero.
606/// For an animation that stops after last subimage is reached, one has to
607/// write the last image as .gif+ (zero delay of last image) or .gif+NN
608/// (NN*10ms delay of last image).
609///
610/// For repeated animation (looping), the last subimage must be specified as:
611/// - "myfile.gif++NN++" if you want an infinite looping gif with NN*10ms
612/// delay of the last image.
613/// - "myfile.gif++" for an infinite loop with zero delay of last image.
614/// - "myfile.gif+NN++RR" if you want a finite looping gif with NN*10ms
615/// delay of the last image and the animation to be stopped after RR
616/// repeats. RR is not restricted to two digits.
617///
618/// A deprecated version for saving the last subimage of a looping gif animation is:
619/// - "myfile.gif++NN" for a finite loop where NN is number of repetitions
620/// and NN*10ms the delay of last image. (No separate control of repeats and delay).
621/// Note: If the file "myfile.gif" already exists, the new frames are appended at
622/// the end of the file. To avoid this, delete it first with gSystem->Unlink(myfile.gif);
623///
624/// The following macro creates animated gif from jpeg images with names
625/// - imageNN.jpg, where 1<= NN <= 10
626/// - The delays are set to 10*10ms.
627/// ~~~ {.cpp}
628/// {
629/// TImage *img = 0;
630/// gSystem->Unlink("anim.gif"); // delete existing file
631///
632/// for (int i = 1; i <= 10; i++) {
633/// delete img; // delete previous image
634///
635/// // Read image data. Image can be in any format, e.g. png, gif, etc.
636/// img = TImage::Open(Form("image%d.jpg", i));
637///
638/// if (i < 10) {
639/// img->WriteImage("anim.gif+10"); // 10 centiseconds delay
640/// } else { // the last image written. "++" stands for infinit animation.
641/// img->WriteImage("anim.gif++10++"); // 10 centiseconds delay of last image
642/// }
643/// }
644/// }
645/// ~~~
646
648{
649 if (!IsValid()) {
650 Error("WriteImage", "no image loaded");
651 return;
652 }
653
654 if (!file || !*file) {
655 Error("WriteImage", "no file name specified");
656 return;
657 }
658
659 const char *s;
660 if ((s = strrchr(file, '.'))) {
661 s++;
663 if (t == kUnknown) {
664 Error("WriteImage", "cannot determine a valid file type");
665 return;
666 }
667 if (t != kUnknown)
668 type = t;
669 }
670
671 if (type == kUnknown) {
672 Error("WriteImage", "not a valid file type was specified");
673 return;
674 }
675
676 UInt_t mytype;
677 MapFileTypes(type, mytype);
678 ASImageFileTypes atype = (ASImageFileTypes)mytype;
679
680 UInt_t aquality;
681 EImageQuality quality = GetImageQuality();
682 MapQuality(quality, aquality);
683
684 static TString fname;
685 fname = file;
686 static ASImageExportParams parms;
687 ASImage *im = fScaledImage ? fScaledImage->fImage : fImage;
688
689 switch (type) {
690 case kXpm:
691 parms.xpm.type = atype;
692 parms.xpm.flags = EXPORT_ALPHA;
693 parms.xpm.dither = 4;
694 parms.xpm.opaque_threshold = 127;
695 parms.xpm.max_colors = 512;
696 break;
697 case kBmp:
698 ASImage2bmp(im, fname.Data(), 0);
699 return;
700 case kXcf:
701 ASImage2xcf(im, fname.Data(), 0);
702 return;
703 case kPng:
704 parms.png.type = atype;
705 parms.png.flags = EXPORT_ALPHA;
706 parms.png.compression = !GetImageCompression() ? -1 : int(GetImageCompression());
707 break;
708 case kJpeg:
709 parms.jpeg.type = atype;
710 parms.jpeg.flags = 0;
711 parms.jpeg.quality = aquality;
712 break;
713 case kGif:
714 parms.gif.type = atype;
715 parms.gif.flags = EXPORT_ALPHA;
716 parms.gif.dither = 0;
717 parms.gif.opaque_threshold = 0;
718 break;
719 case kAnimGif:
720 {
721 parms.gif.type = atype;
722 parms.gif.flags = EXPORT_ALPHA | EXPORT_APPEND;
723 parms.gif.dither = 0;
724 parms.gif.opaque_threshold = 0;
725 parms.gif.animate_repeats = 0;
726
727 s += 4; // skip "gif+"
728 int delay = 0;
729
730 const TString sufix = s; // we denote as suffix as everything that is after .gif+
731 const UInt_t sLength = sufix.Length();
732
733 if (sufix=="+") {
734 // .gif++ implies that this is the last image of the animation
735 // and that the gif will loop forever (infinite animation)
736 // and that the delay of last image is 0ms (backward compatibility reasons)
737 delay = 0;
738 parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
739 parms.gif.animate_repeats = 0;// 0 is code for looping forever (if EXPORT_ANIMATION_REPEATS is also set)
740 } else if(sufix=="") {
741 // .gif+ implies that this is a subimage of the animation with zero delay
742 // or the last image of an animation that will not repeat.
743 // Last image delay is zero because atoi("")=0.
744 delay = atoi(s);
745 //Nothing else needed here
746 } else if(!sufix.Contains("+")) {
747 // .gif+NN implies that this is a subimage of the animation
748 // with NN*10ms delay (latency) until the next one.
749 // You can also use this option on the last image if you do not want the gif to replay
750 delay = atoi(s);
751 //Nothing else needed here
752 } else if(sLength>1 && sufix.BeginsWith("+") && sufix.CountChar('+')==1) {
753 // .gif++NN implies that this is the last image of the animation
754 // and that it will loop NN number of times (finite animation)
755 // and that the delay of last image is NN*10ms (backward compatibility reasons).
756 delay = atoi(s);// atoi is smart enough to ignore the "+" sign before.
757 parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
758 parms.gif.animate_repeats = atoi(s);// loops only NN times, then it stops. atoi discards + sign.
759 } else if(sLength>3 && sufix.BeginsWith("+") && sufix.EndsWith("++") && !TString(sufix(1,sLength-3)).Contains("+")) {
760 // .gif++NN++ implies that this is the last image of the animation
761 // and that the gif will loop forever (infinite animation)
762 // and that the delay of last image is NN*10ms.
763 // In contrast, .gif++ is an infinite loop but with 0 delay, whereas the option
764 // .gif++NN is a loop repeated NN times (not infinite) with NN*10ms delay
765 // between last and first loop images.
766 delay = atoi(s);// atoi discards the three plus signs
767 parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
768 parms.gif.animate_repeats = 0;// 0 is code for looping forever (if EXPORT_ANIMATION_REPEATS is also set)
769 } else if(sLength>3 && sufix.CountChar('+')==2 && TString(sufix(1,sLength-2)).Contains("++")) {
770 // .gif+NN++RR implies that this is the last image animation
771 // and that the gif will loop RR number of times (finite animation)
772 // and that the delay of last image is NN*10ms.
773 const TString sDelay = sufix(0,sufix.First('+'));
774 const TString sRepeats = sufix(sufix.First('+')+2,sLength-(sufix.First('+')+2));
775 delay = atoi(sDelay);
776 parms.gif.flags |= EXPORT_ANIMATION_REPEATS;// activate repetition
777 parms.gif.animate_repeats = atoi(sRepeats);// loops NN times.
778 } else {
779 Error("WriteImage", "gif suffix %s not yet supported", s);
780 return;
781 }
782
783 parms.gif.animate_delay = delay;
784
785 int i1 = fname.Index("gif+");
786 if (i1 != kNPOS) {
787 fname = fname(0, i1 + 3);
788 }
789 else {
790 Error("WriteImage", "unexpected gif extension structure %s", fname.Data());
791 return;
792 }
793 break;
794 }
795 case kTiff:
796 parms.tiff.type = atype;
797 parms.tiff.flags = EXPORT_ALPHA;
798 parms.tiff.rows_per_strip = 0;
799 parms.tiff.compression_type = aquality <= 50 ? TIFF_COMPRESSION_JPEG :
800 TIFF_COMPRESSION_NONE;
801 parms.tiff.jpeg_quality = 100;
802 parms.tiff.opaque_threshold = 0;
803 break;
804 default:
805 Error("WriteImage", "file type %s not yet supported", s);
806 return;
807 }
808
809 if (!ASImage2file(im, 0, fname.Data(), atype, &parms)) {
810 Error("WriteImage", "error writing file %s", file);
811 }
812}
813
814////////////////////////////////////////////////////////////////////////////////
815/// Return file type depending on specified extension.
816/// Protected method.
817
819{
820 TString s(ext);
821 s.Strip();
822 s.ToLower();
823
824 if (s == "xpm")
825 return kXpm;
826 if (s == "png")
827 return kPng;
828 if (s == "jpg" || s == "jpeg")
829 return kJpeg;
830 if (s == "xcf")
831 return kXcf;
832 if (s == "ppm")
833 return kPpm;
834 if (s == "pnm")
835 return kPnm;
836 if (s == "bmp")
837 return kBmp;
838 if (s == "ico")
839 return kIco;
840 if (s == "cur")
841 return kCur;
842 if (s == "gif")
843 return kGif;
844 if (s.Contains("gif+"))
845 return kAnimGif;
846 if (s == "tiff")
847 return kTiff;
848 if (s == "xbm")
849 return kXbm;
850 if (s == "tga")
851 return kTga;
852 if (s == "xml")
853 return kXml;
854
855 return kUnknown;
856}
857
858////////////////////////////////////////////////////////////////////////////////
859/// Map file type to/from AfterImage types.
860/// Protected method.
861
863{
864 if (toas) {
865 switch (type) {
866 case kXpm:
867 astype = ASIT_Xpm; break;
868 case kZCompressedXpm:
869 astype = ASIT_ZCompressedXpm; break;
870 case kGZCompressedXpm:
871 astype = ASIT_GZCompressedXpm; break;
872 case kPng:
873 astype = ASIT_Png; break;
874 case kJpeg:
875 astype = ASIT_Jpeg; break;
876 case kXcf:
877 astype = ASIT_Xcf; break;
878 case kPpm:
879 astype = ASIT_Ppm; break;
880 case kPnm:
881 astype = ASIT_Pnm; break;
882 case kBmp:
883 astype = ASIT_Bmp; break;
884 case kIco:
885 astype = ASIT_Ico; break;
886 case kCur:
887 astype = ASIT_Cur; break;
888 case kGif:
889 astype = ASIT_Gif; break;
890 case kAnimGif:
891 astype = ASIT_Gif; break;
892 case kTiff:
893 astype = ASIT_Tiff; break;
894 case kXbm:
895 astype = ASIT_Xbm; break;
896 case kTga:
897 astype = ASIT_Targa; break;
898 case kXml:
899 astype = ASIT_XMLScript; break;
900 default:
901 astype = ASIT_Unknown;
902 }
903 } else {
904 switch (astype) {
905 case ASIT_Xpm:
906 type = kXpm; break;
907 case ASIT_ZCompressedXpm:
908 type = kZCompressedXpm; break;
909 case ASIT_GZCompressedXpm:
910 type = kGZCompressedXpm; break;
911 case ASIT_Png:
912 type = kPng; break;
913 case ASIT_Jpeg:
914 type = kJpeg; break;
915 case ASIT_Xcf:
916 type = kXcf; break;
917 case ASIT_Ppm:
918 type = kPpm; break;
919 case ASIT_Pnm:
920 type = kPnm; break;
921 case ASIT_Bmp:
922 type = kBmp; break;
923 case ASIT_Ico:
924 type = kIco; break;
925 case ASIT_Cur:
926 type = kCur; break;
927 case ASIT_Gif:
928 type = kGif; break;
929 case ASIT_Tiff:
930 type = kTiff; break;
931 case ASIT_Xbm:
932 type = kXbm; break;
933 case ASIT_XMLScript:
934 type = kXml; break;
935 case ASIT_Targa:
936 type = kTga; break;
937 default:
938 type = kUnknown;
939 }
940 }
941}
942
943////////////////////////////////////////////////////////////////////////////////
944/// Map quality to/from AfterImage quality.
945/// Protected method.
946
947void TASImage::MapQuality(EImageQuality &quality, UInt_t &asquality, Bool_t toas)
948{
949 if (toas) {
950 switch (quality) {
951 case kImgPoor:
952 asquality = 25; break;
953 case kImgFast:
954 asquality = 75; break;
955 case kImgGood:
956 asquality = 50; break;
957 case kImgBest:
958 asquality = 100; break;
959 default:
960 asquality = 0;
961 }
962 } else {
963 quality = kImgDefault;
964 if (asquality > 0 && asquality <= 25)
965 quality = kImgPoor;
966 if (asquality > 26 && asquality <= 50)
967 quality = kImgFast;
968 if (asquality > 51 && asquality <= 75)
969 quality = kImgGood;
970 if (asquality > 76 && asquality <= 100)
971 quality = kImgBest;
972 }
973}
974
975////////////////////////////////////////////////////////////////////////////////
976/// Deletes the old image and creates a new image depending on the values
977/// of imageData. The size of the image is width X height.
978///
979/// The color of each pixel depends on the imageData of the corresponding
980/// pixel. The palette is used to convert an image value into its color.
981/// If palette is not defined (palette = 0) a default palette is used.
982/// Any previously defined zooming is reset.
983
984void TASImage::SetImage(const Double_t *imageData, UInt_t width, UInt_t height,
985 TImagePalette *palette)
986{
987 TAttImage::SetPalette(palette);
988
989 if (!InitVisual()) {
990 Warning("SetImage", "Visual not initiated");
991 return;
992 }
993
994 DestroyImage();
995 delete fScaledImage;
996 fScaledImage = 0;
997
998 // get min and max value of image
999 fMinValue = fMaxValue = *imageData;
1000 for (Int_t pixel = 1; pixel < Int_t(width * height); pixel++) {
1001 if (fMinValue > *(imageData + pixel)) fMinValue = *(imageData + pixel);
1002 if (fMaxValue < *(imageData + pixel)) fMaxValue = *(imageData + pixel);
1003 }
1004
1005 // copy ROOT palette to asImage palette
1006 const TImagePalette &pal = GetPalette();
1007
1008 ASVectorPalette asPalette;
1009
1010 asPalette.npoints = pal.fNumPoints;
1011 Int_t col;
1012 for (col = 0; col < 4; col++)
1013 asPalette.channels[col] = new UShort_t[asPalette.npoints];
1014
1015 memcpy(asPalette.channels[0], pal.fColorBlue, pal.fNumPoints * sizeof(UShort_t));
1016 memcpy(asPalette.channels[1], pal.fColorGreen, pal.fNumPoints * sizeof(UShort_t));
1017 memcpy(asPalette.channels[2], pal.fColorRed, pal.fNumPoints * sizeof(UShort_t));
1018 memcpy(asPalette.channels[3], pal.fColorAlpha, pal.fNumPoints * sizeof(UShort_t));
1019
1020 asPalette.points = new Double_t[asPalette.npoints];
1021 for (Int_t point = 0; point < Int_t(asPalette.npoints); point++)
1022 asPalette.points[point] = fMinValue + (fMaxValue - fMinValue) * pal.fPoints[point];
1023
1024 fImage = create_asimage_from_vector(fgVisual, (Double_t*)imageData, width,
1025 height, &asPalette, ASA_ASImage,
1027
1028 delete [] asPalette.points;
1029 for (col = 0; col < 4; col++)
1030 delete [] asPalette.channels[col];
1031
1032 fZoomUpdate = 0;
1033 fZoomOffX = 0;
1034 fZoomOffY = 0;
1035 fZoomWidth = width;
1036 fZoomHeight = height;
1038}
1039
1040////////////////////////////////////////////////////////////////////////////////
1041/// Delete the old image and creates a new image depending on the values
1042/// of imageData. The size of the image is width X (imageData.fN / width).
1043/// The color of each pixel depends on the imageData of the corresponding
1044/// pixel. The palette is used to convert an image value into its color.
1045/// If palette is not defined (palette = 0) a default palette is used.
1046/// Any previously defined zooming is reset.
1047
1048void TASImage::SetImage(const TArrayD &imageData, UInt_t width, TImagePalette *palette)
1049{
1050 SetImage(imageData.GetArray(), width, imageData.GetSize() / width, palette);
1051}
1052
1053////////////////////////////////////////////////////////////////////////////////
1054/// Delete the old image and creates a new image depending on the values
1055/// of imageData. The size of the image is width X (imageData.fN / width).
1056/// The color of each pixel depends on the imageData of the corresponding
1057/// pixel. The palette is used to convert an image value into its color.
1058/// If palette is not defined (palette = 0) a default palette is used.
1059/// Any previously defined zooming is reset.
1060
1061void TASImage::SetImage(const TVectorD &imageData, UInt_t width, TImagePalette *palette)
1062{
1063 SetImage(imageData.GetMatrixArray(), width,
1064 imageData.GetNoElements() / width, palette);
1065}
1066
1067////////////////////////////////////////////////////////////////////////////////
1068/// Create an image from the given pad, afterwards this image can be
1069/// saved in any of the supported image formats.
1070
1072{
1073 if (!pad) {
1074 Error("FromPad", "pad cannot be 0");
1075 return;
1076 }
1077
1078 if (!InitVisual()) {
1079 Warning("FromPad", "Visual not initiated");
1080 return;
1081 }
1082
1083 SetName(pad->GetName());
1084
1085 DestroyImage();
1086 delete fScaledImage;
1087 fScaledImage = 0;
1088
1089 if (gROOT->IsBatch()) { // in batch mode
1090 TVirtualPS *psave = gVirtualPS;
1091 gVirtualPS = (TVirtualPS*)gROOT->ProcessLineFast("new TImageDump()");
1092 gVirtualPS->Open(pad->GetName(), 114); // in memory
1093 gVirtualPS->SetBit(BIT(11)); //kPrintingPS
1094
1096
1097 if (itmp && itmp->fImage) {
1098 itmp->BeginPaint();
1099 }
1100
1101 TVirtualPad *sav = gPad;
1102 gPad = pad;
1103 pad->Paint();
1104 gPad = sav;
1105
1106 if (itmp && itmp->fImage && (itmp != this)) {
1107 fImage = clone_asimage(itmp->fImage, SCL_DO_ALL);
1108 if (itmp->fImage->alt.argb32) {
1109 UInt_t sz = itmp->fImage->width*itmp->fImage->height;
1110 fImage->alt.argb32 = (ARGB32*)safemalloc(sz*sizeof(ARGB32));
1111 memcpy(fImage->alt.argb32, itmp->fImage->alt.argb32, sz*4);
1112 }
1113 }
1114 delete gVirtualPS;
1115 gVirtualPS = psave;
1116 return;
1117 }
1118
1119 // X11 Synchronization
1120 gVirtualX->Update(1);
1121 if (!gThreadXAR) {
1122 gSystem->Sleep(100);
1124 gSystem->Sleep(10);
1126 }
1127
1128 TVirtualPad *canvas = (TVirtualPad*)pad->GetCanvas();
1129 Int_t wid = (pad == canvas) ? pad->GetCanvasID() : pad->GetPixmapID();
1130 gVirtualX->SelectWindow(wid);
1131
1132 Window_t wd = (Window_t)gVirtualX->GetCurrentWindow();
1133 if (!wd) return;
1134
1135 if (w == 0) w = TMath::Abs(pad->UtoPixel(1.));
1136 if (h == 0) h = pad->VtoPixel(0.);
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;
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());
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
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
1911void 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
1945void 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
1981void 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
2022{
2023 if (!IsValid()) {
2024 Warning("Zoom", "Image not valid");
2025 return;
2026 }
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 }
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
2578void 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
2596 // This is for backward compatibility...
2597 if (fn.Last('/') == 0) fn = fn(1, fn.Length() - 1);
2598
2599 const char *ttpath = gEnv->GetValue("Root.TTFontPath",
2601 char *tmpstr = gSystem->Which(ttpath, fn, kReadPermission);
2602 fn = tmpstr;
2603 delete [] tmpstr;
2604
2605 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")) {
2606 ttfont = kTRUE;
2607 }
2608
2609 if (color) {
2610 parse_argb_color(color, &text_color);
2611 }
2612
2613 if (fImage && fImage->alt.argb32 && ttfont) {
2614 DrawTextTTF(x, y, text, size, text_color, fn.Data(), angle);
2615 return;
2616 }
2617
2618 if (!gFontManager) {
2619 gFontManager = create_font_manager(fgVisual->dpy, 0, 0);
2620 }
2621
2622 if (!gFontManager) {
2623 Warning("DrawText", "cannot create Font Manager");
2624 return;
2625 }
2626
2627 ASFont *font = get_asfont(gFontManager, fn.Data(), 0, size, ASF_GuessWho);
2628
2629 if (!font) {
2630 font = get_asfont(gFontManager, "fixed", 0, size, ASF_GuessWho);
2631 if (!font) {
2632 Warning("DrawText", "cannot find a font %s", font_name);
2633 return;
2634 }
2635 }
2636
2637 get_text_size(text, font, (ASText3DType)type, &width, &height);
2638
2639 if (!fImage) {
2640 fImage = create_asimage(width, height, 0);
2641 fill_asimage(fgVisual, fImage, 0, 0, width, height, 0xFFFFFFFF);
2642 }
2643
2644 text_im = draw_text(text, font, (ASText3DType)type, 0);
2645
2646 ASImage *rimg = fImage;
2647
2648 if (fore_file) {
2649 ASImage *tmp = file2ASImage(fore_file, 0xFFFFFFFF, SCREEN_GAMMA, 0, 0);
2650 if (tmp) {
2651 if ((tmp->width != width) || (tmp->height != height)) {
2652 fore_im = tile_asimage(fgVisual, tmp, 0, 0, width, height, 0,
2653 ASA_ASImage, GetImageCompression(), GetImageQuality());
2654 }
2655 destroy_asimage(&tmp);
2656 } else {
2657 fore_im = tmp;
2658 }
2659 }
2660
2661 if (fore_im) {
2662 move_asimage_channel(fore_im, IC_ALPHA, text_im, IC_ALPHA);
2663 destroy_asimage(&text_im);
2664 } else {
2665 fore_im = text_im ;
2666 }
2667
2668 release_font(font);
2669
2670 if (fore_im) {
2671 ASImage *rendered_im;
2672 ASImageLayer layers[2];
2673
2674 init_image_layers(&(layers[0]), 2);
2675 fore_im->back_color = text_color;
2676 layers[0].im = rimg;
2677 layers[0].dst_x = 0;
2678 layers[0].dst_y = 0;
2679 layers[0].clip_width = rimg->width;
2680 layers[0].clip_height = rimg->height;
2681 layers[0].bevel = 0;
2682 layers[1].im = fore_im;
2683 layers[1].dst_x = x;
2684 layers[1].dst_y = y;
2685 layers[1].clip_width = fore_im->width;
2686 layers[1].clip_height = fore_im->height;
2687
2688 rendered_im = merge_layers(fgVisual, &(layers[0]), 2, rimg->width, rimg->height,
2689 ASA_ASImage, GetImageCompression(), GetImageQuality());
2690
2691 destroy_asimage(&fore_im);
2692 DestroyImage();
2693 fImage = rendered_im;
2694 UnZoom();
2695 }
2696}
2697
2698////////////////////////////////////////////////////////////////////////////////
2699/// Merge two images.
2700///
2701/// op is string which specifies overlay operation. Supported operations are:
2702///
2703/// - add - color addition with saturation
2704/// - alphablend - alpha-blending
2705/// - allanon - color values averaging
2706/// - colorize - hue and saturate bottom image same as top image
2707/// - darken - use lowest color value from both images
2708/// - diff - use absolute value of the color difference between two images
2709/// - dissipate - randomly alpha-blend images
2710/// - hue - hue bottom image same as top image
2711/// - lighten - use highest color value from both images
2712/// - overlay - some weird image overlaying(see GIMP)
2713/// - saturate - saturate bottom image same as top image
2714/// - screen - another weird image overlaying(see GIMP)
2715/// - sub - color substraction with saturation
2716/// - tint - tinting image with image
2717/// - value - value bottom image same as top image
2718
2719void TASImage::Merge(const TImage *im, const char *op, Int_t x, Int_t y)
2720{
2721 if (!im) return;
2722
2723 if (!InitVisual()) {
2724 Warning("Merge", "Visual not initiated");
2725 return;
2726 }
2727
2728 ASImage *rendered_im;
2729 ASImageLayer layers[2];
2730
2731 init_image_layers(&(layers[0]), 2);
2732 layers[0].im = fImage;
2733 layers[0].dst_x = 0;
2734 layers[0].dst_y = 0;
2735 layers[0].clip_width = fImage->width;
2736 layers[0].clip_height = fImage->height;
2737 layers[0].bevel = 0;
2738 layers[1].im = ((TASImage*)im)->fImage;
2739 layers[1].dst_x = x;
2740 layers[1].dst_y = y;
2741 layers[1].clip_width = im->GetWidth();
2742 layers[1].clip_height = im->GetHeight();
2743 layers[1].merge_scanlines = blend_scanlines_name2func(op ? op : "add");
2744
2745 rendered_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
2746 ASA_ASImage, GetImageCompression(), GetImageQuality());
2747
2748 DestroyImage();
2749 fImage = rendered_im;
2750 UnZoom();
2751}
2752
2753////////////////////////////////////////////////////////////////////////////////
2754/// Perform Gaussian blur of the image (useful for drop shadows).
2755/// - hr - horizontal radius of the blur
2756/// - vr - vertical radius of the blur
2757
2759{
2760 if (!InitVisual()) {
2761 Warning("Blur", "Visual not initiated");
2762 return;
2763 }
2764
2765 if (!fImage) {
2766 fImage = create_asimage(100, 100, 0);
2767
2768 if (!fImage) {
2769 Warning("Blur", "Failed to create image");
2770 return;
2771 }
2772
2773 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2774 }
2775
2776 ASImage *rendered_im = blur_asimage_gauss(fgVisual, fImage, hr > 0 ? hr : 3,
2777 vr > 0 ? vr : 3, SCL_DO_ALL,
2778 ASA_ASImage, GetImageCompression(), GetImageQuality());
2779 DestroyImage();
2780 fImage = rendered_im;
2781 UnZoom();
2782}
2783
2784////////////////////////////////////////////////////////////////////////////////
2785/// Clone image.
2786
2787TObject *TASImage::Clone(const char *newname) const
2788{
2789 if (!InitVisual() || !fImage) {
2790 Warning("Clone", "Image not initiated");
2791 return 0;
2792 }
2793
2795
2796 if (!im) {
2797 Warning("Clone", "Failed to create image");
2798 return 0;
2799 }
2800
2801 im->SetName(newname);
2802
2803 im->fImage = clone_asimage(fImage, SCL_DO_ALL);
2804 im->fMaxValue = fMaxValue;
2805 im->fMinValue = fMinValue;
2806 im->fZoomOffX = fZoomOffX;
2807 im->fZoomOffY = fZoomOffY;
2808 im->fZoomWidth = fZoomWidth;
2812
2813 if (fImage->alt.argb32) {
2814 UInt_t sz = fImage->width * fImage->height;
2815 im->fImage->alt.argb32 = (ARGB32*)safemalloc(sz*sizeof(ARGB32));
2816 memcpy(im->fImage->alt.argb32, fImage->alt.argb32, sz * sizeof(ARGB32));
2817 }
2818
2819 return im;
2820}
2821
2822////////////////////////////////////////////////////////////////////////////////
2823/// Reduce color-depth of an image and fills vector of "scientific data"
2824/// [0...1]
2825///
2826/// Colors are reduced by allocating color cells to most used colors first,
2827/// and then approximating other colors with those allocated.
2828///
2829/// \param[in] max_colors - maximum size of the colormap.
2830/// \param[in] dither - number of bits to strip off the color data ( 0...7 )
2831/// \param[in] opaque_threshold - alpha channel threshold at which pixel should be treated as opaque
2832
2833Double_t *TASImage::Vectorize(UInt_t max_colors, UInt_t dither, Int_t opaque_threshold)
2834{
2835 if (!InitVisual()) {
2836 Warning("Vectorize", "Visual not initiated");
2837 return 0;
2838 }
2839
2840 if (!fImage) {
2841 fImage = create_asimage(100, 100, 0);
2842
2843 if (!fImage) {
2844 Warning("Vectorize", "Failed to create image");
2845 return 0;
2846 }
2847
2848 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2849 }
2850
2851 ASColormap cmap;
2852 int *res;
2853 UInt_t r=0, g=0, b=0;
2854
2855 dither = dither > 7 ? 7 : dither;
2856
2857 res = colormap_asimage(fImage, &cmap, max_colors, dither, opaque_threshold);
2858
2859 Double_t *vec = new Double_t[fImage->height*fImage->width];
2860 UInt_t v;
2861 Double_t tmp;
2862 fMinValue = 2;
2863 fMaxValue = -1;
2864
2865 for (UInt_t y = 0; y < fImage->height; y++) {
2866 for (UInt_t x = 0; x < fImage->width; x++) {
2867 int i = y*fImage->width + x;
2868 if (res) {
2869 g = INDEX_SHIFT_GREEN(cmap.entries[res[i]].green);
2870 b = INDEX_SHIFT_BLUE(cmap.entries[res[i]].blue);
2871 r = INDEX_SHIFT_RED(cmap.entries[res[i]].red);
2872 }
2873 v = MAKE_INDEXED_COLOR24(r,g,b);
2874 v = (v>>12)&0x0FFF;
2875 tmp = Double_t(v)/0x0FFF;
2876 vec[(fImage->height - y - 1)*fImage->width + x] = tmp;
2877 if (fMinValue > tmp) fMinValue = tmp;
2878 if (fMaxValue < tmp) fMaxValue = tmp;
2879 }
2880 }
2881 TImagePalette *pal = new TImagePalette(cmap.count);
2882
2883 for (UInt_t j = 0; j < cmap.count; j++) {
2884 g = INDEX_SHIFT_GREEN(cmap.entries[j].green);
2885 b = INDEX_SHIFT_BLUE(cmap.entries[j].blue);
2886 r = INDEX_SHIFT_RED(cmap.entries[j].red);
2887 v = MAKE_INDEXED_COLOR24(r,g,b);
2888
2889 v = (v>>12) & 0x0FFF;
2890 pal->fPoints[j] = Double_t(v)/0x0FFF;
2891
2892 pal->fColorRed[j] = cmap.entries[j].red << 8;
2893 pal->fColorGreen[j] = cmap.entries[j].green << 8;
2894 pal->fColorBlue[j] = cmap.entries[j].blue << 8;
2895 pal->fColorAlpha[j] = 0xFF00;
2896 }
2897
2898 destroy_colormap(&cmap, kTRUE);
2899
2900 fPalette = *pal;
2901 fImage->alt.vector = vec;
2902 UnZoom();
2903 // ROOT-7647: res is allocated with `safemalloc` by colormap_asimage
2904 if (res) safefree(res);
2905 return (Double_t*)fImage->alt.vector;
2906}
2907
2908////////////////////////////////////////////////////////////////////////////////
2909/// This function will tile original image to specified size with offsets
2910/// requested, and then it will go though it and adjust hue, saturation and
2911/// value of those pixels that have specific hue, set by affected_hue/
2912/// affected_radius parameters. When affected_radius is greater then 180
2913/// entire image will be adjusted. Note that since grayscale colors have
2914/// no hue - the will not get adjusted. Only saturation and value will be
2915/// adjusted in gray pixels.
2916///
2917/// Hue is measured as an angle on a 360 degree circle, The following is
2918/// relationship of hue values to regular color names :
2919/// - red - 0
2920/// - yellow - 60
2921/// - green - 120
2922/// - cyan - 180
2923/// - blue - 240
2924/// - magenta - 300
2925/// - red - 360
2926///
2927/// All the hue values in parameters will be adjusted to fall within 0-360 range.
2928///
2929/// \param[in] hue hue in degrees in range 0-360. This allows to limit
2930/// impact of color adjustment to affect only limited range of hues.
2931///
2932/// \param[in] radius value in degrees to be used in order to
2933/// calculate the range of affected hues. Range is determined by
2934/// substracting and adding this value from/to affected_hue.
2935///
2936/// \param[in] H value by which to change hues in affected range.
2937/// \param[in] S value by which to change saturation of the pixels in affected hue range.
2938/// \param[in] V value by which to change Value(brightness) of pixels in affected hue range.
2939///
2940/// \param[in] x,y position on infinite surface tiled with original image, of the
2941/// left-top corner of the area to be used for new image.
2942///
2943/// \param[in] width, height size of the area of the original image to be used for new image.
2944/// Default is current width, height of the image.
2945
2947 Int_t x, Int_t y, UInt_t width, UInt_t height)
2948{
2949 if (!InitVisual()) {
2950 Warning("HSV", "Visual not initiated");
2951 return;
2952 }
2953
2954 if (!fImage) {
2955 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
2956
2957 if (!fImage) {
2958 Warning("HSV", "Failed to create image");
2959 return;
2960 }
2961
2962 x = 0;
2963 y = 0;
2964 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2965 }
2966
2967 width = !width ? fImage->width : width;
2968 height = !height ? fImage->height : height;
2969
2970 ASImage *rendered_im = 0;
2971
2972 if (H || S || V) {
2973 rendered_im = adjust_asimage_hsv(fgVisual, fImage, x, y, width, height,
2974 hue, radius, H, S, V, ASA_ASImage, 100,
2975 ASIMAGE_QUALITY_TOP);
2976 }
2977 if (!rendered_im) {
2978 Warning("HSV", "Failed to create rendered image");
2979 return;
2980 }
2981
2982 DestroyImage();
2983 fImage = rendered_im;
2984 UnZoom();
2985}
2986
2987////////////////////////////////////////////////////////////////////////////////
2988/// Render multipoint gradient inside rectangle of size (width, height)
2989/// at position (x,y) within the existing image.
2990///
2991/// \param[in] angle Given in degrees. Default is 0. This is the
2992/// direction of the gradient. Currently the only supported
2993/// values are 0, 45, 90, 135, 180, 225, 270, 315. 0 means left
2994/// to right, 90 means top to bottom, etc.
2995///
2996/// \param[in] colors Whitespace-separated list of colors. At least two
2997/// colors are required. Each color in this list will be visited
2998/// in turn, at the intervals given by the offsets attribute.
2999///
3000/// \param[in] offsets Whitespace-separated list of floating point values
3001/// ranging from 0.0 to 1.0. The colors from the colors attribute
3002/// are given these offsets, and the final gradient is rendered
3003/// from the combination of the two. If both colors and offsets
3004/// are given but the number of colors and offsets do not match,
3005/// the minimum of the two will be used, and the other will be
3006/// truncated to match. If offsets are not given, a smooth
3007/// stepping from 0.0 to 1.0 will be used.
3008
3009void TASImage::Gradient(UInt_t angle, const char *colors, const char *offsets,
3010 Int_t x, Int_t y, UInt_t width, UInt_t height)
3011{
3012 if (!InitVisual()) {
3013 Warning("Gradient", "Visual not initiated");
3014 return;
3015 }
3016
3017 ASImage *rendered_im = 0;
3018 ASGradient gradient;
3019
3020 int reverse = 0, npoints1 = 0, npoints2 = 0;
3021 char *p;
3022 char *pb;
3023 char ch;
3024 TString str = colors;
3025 TString col;
3026
3027 if ((angle > 2 * 180 * 15 / 16) || (angle < 2 * 180 * 1 / 16)) {
3028 gradient.type = GRADIENT_Left2Right;
3029 } else if (angle < 2 * 180 * 3 / 16) {
3030 gradient.type = GRADIENT_TopLeft2BottomRight;
3031 } else if (angle < 2 * 180 * 5 / 16) {
3032 gradient.type = GRADIENT_Top2Bottom;
3033 } else if (angle < 2 * 180 * 7 / 16) {
3034 gradient.type = GRADIENT_BottomLeft2TopRight; reverse = 1;
3035 } else if (angle < 2 * 180 * 9 / 16) {
3036 gradient.type = GRADIENT_Left2Right; reverse = 1;
3037 } else if (angle < 2 * 180 * 11 / 16) {
3038 gradient.type = GRADIENT_TopLeft2BottomRight; reverse = 1;
3039 } else if (angle < 2 * 180 * 13 / 16) {
3040 gradient.type = GRADIENT_Top2Bottom; reverse = 1;
3041 } else {
3042 gradient.type = GRADIENT_BottomLeft2TopRight;
3043 }
3044
3045 for (p = (char*)colors; isspace((int)*p); p++) { }
3046
3047 for (npoints1 = 0; *p; npoints1++) {
3048 if (*p) {
3049 for ( ; *p && !isspace((int)*p); p++) { }
3050 }
3051 for ( ; isspace((int)*p); p++) { }
3052 }
3053 if (offsets) {
3054 for (p = (char*)offsets; isspace((int)*p); p++) { }
3055
3056 for (npoints2 = 0; *p; npoints2++) {
3057 if (*p) {
3058 for ( ; *p && !isspace((int)*p); p++) { }
3059 }
3060 for ( ; isspace((int)*p); p++) { }
3061 }
3062 }
3063 if (npoints1 > 1) {
3064 int i;
3065 if (offsets && (npoints1 > npoints2)) npoints1 = npoints2;
3066
3067 if (!width) {
3068 width = fImage ? fImage->width : 20;
3069 }
3070 if (!height) {
3071 height = fImage ? fImage->height : 20;
3072 }
3073
3074 gradient.color = new ARGB32[npoints1];
3075 gradient.offset = new double[npoints1];
3076
3077 for (p = (char*)colors; isspace((int)*p); p++) { }
3078
3079 for (npoints1 = 0; *p; ) {
3080 pb = p;
3081
3082 if (*p) {
3083 for ( ; *p && !isspace((int)*p); p++) { }
3084 }
3085 for ( ; isspace((int)*p); p++) { }
3086
3087 col = str(pb - colors, p - pb);
3088
3089 if (parse_argb_color(col.Data(), gradient.color + npoints1) != col) {
3090 npoints1++;
3091 } else {
3092 Warning("Gradient", "Failed to parse color [%s] - defaulting to black", pb);
3093 }
3094 }
3095
3096 if (offsets) {
3097 for (p = (char*)offsets; isspace((int)*p); p++) { }
3098
3099 for (npoints2 = 0; *p; ) {
3100 pb = p;
3101
3102 if (*p) {
3103 for ( ; *p && !isspace((int)*p); p++) { }
3104 }
3105 ch = *p; *p = '\0';
3106 gradient.offset[npoints2] = strtod(pb, &pb);
3107
3108 if (pb == p) npoints2++;
3109 *p = ch;
3110 for ( ; isspace((int)*p); p++) { }
3111 }
3112 } else {
3113 for (npoints2 = 0; npoints2 < npoints1; npoints2++) {
3114 gradient.offset[npoints2] = (double)npoints2 / (npoints1 - 1);
3115 }
3116 }
3117 gradient.npoints = npoints1;
3118
3119 if (npoints2 && (gradient.npoints > npoints2)) {
3120 gradient.npoints = npoints2;
3121 }
3122 if (reverse) {
3123 for (i = 0; i < gradient.npoints/2; i++) {
3124 int i2 = gradient.npoints - 1 - i;
3125 ARGB32 c = gradient.color[i];
3126 double o = gradient.offset[i];
3127 gradient.color[i] = gradient.color[i2];
3128 gradient.color[i2] = c;
3129 gradient.offset[i] = gradient.offset[i2];
3130 gradient.offset[i2] = o;
3131 }
3132 for (i = 0; i < gradient.npoints; i++) {
3133 gradient.offset[i] = 1.0 - gradient.offset[i];
3134 }
3135 }
3136 rendered_im = make_gradient(fgVisual, &gradient, width, height, SCL_DO_ALL,
3137 ASA_ASImage, GetImageCompression(), GetImageQuality());
3138
3139 delete [] gradient.color;
3140 delete [] gradient.offset;
3141 }
3142
3143 if (!rendered_im) { // error
3144 Warning("Gradient", "Failed to create gradient image");
3145 return;
3146 }
3147
3148 if (!fImage) {
3149 fImage = rendered_im;
3150 return;
3151 }
3152
3153 ASImageLayer layers[2];
3154
3155 init_image_layers(&(layers[0]), 2);
3156 layers[0].im = fImage;
3157 layers[0].dst_x = 0;
3158 layers[0].dst_y = 0;
3159 layers[0].clip_width = fImage->width;
3160 layers[0].clip_height = fImage->height;
3161 layers[0].bevel = 0;
3162 layers[1].im = rendered_im;
3163 layers[1].dst_x = x;
3164 layers[1].dst_y = y;
3165 layers[1].clip_width = width;
3166 layers[1].clip_height = height;
3167 layers[1].merge_scanlines = alphablend_scanlines;
3168
3169 ASImage *merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
3170 ASA_ASImage, GetImageCompression(), GetImageQuality());
3171 if (!merge_im) {
3172 Warning("Gradient", "Failed to create merged image");
3173 return;
3174 }
3175
3176 destroy_asimage(&rendered_im);
3177 DestroyImage();
3178 fImage = merge_im;
3179 UnZoom();
3180}
3181
3182////////////////////////////////////////////////////////////////////////////////
3183/// Make component hilite.
3184/// (used internally)
3185
3186static CARD8 MakeComponentHilite(int cmp)
3187{
3188 if (cmp < 51) {
3189 cmp = 51;
3190 }
3191 cmp = (cmp * 12) / 10;
3192
3193 return (cmp > 255) ? 255 : cmp;
3194}
3195
3196////////////////////////////////////////////////////////////////////////////////
3197/// Calculate highlite color.
3198/// (used internally)
3199
3200static ARGB32 GetHilite(ARGB32 background)
3201{
3202 return ((MakeComponentHilite((background>>24) & 0x000000FF) << 24) & 0xFF000000) |
3203 ((MakeComponentHilite((background & 0x00FF0000) >> 16) << 16) & 0x00FF0000) |
3204 ((MakeComponentHilite((background & 0x0000FF00) >> 8) << 8) & 0x0000FF00) |
3205 ((MakeComponentHilite((background & 0x000000FF))) & 0x000000FF);
3206}
3207
3208////////////////////////////////////////////////////////////////////////////////
3209/// Calculate shadow color.
3210/// (used internally)
3211
3212static ARGB32 GetShadow(ARGB32 background)
3213{
3214 return (background >> 1) & 0x7F7F7F7F;
3215}
3216
3217////////////////////////////////////////////////////////////////////////////////
3218/// Get average.
3219/// (used internally)
3220
3221static ARGB32 GetAverage(ARGB32 foreground, ARGB32 background)
3222{
3223 CARD16 a, r, g, b;
3224
3225 a = ARGB32_ALPHA8(foreground) + ARGB32_ALPHA8(background);
3226 a = (a<<3)/10;
3227 r = ARGB32_RED8(foreground) + ARGB32_RED8(background);
3228 r = (r<<3)/10;
3229 g = ARGB32_GREEN8(foreground) + ARGB32_GREEN8(background);
3230 g = (g<<3)/10;
3231 b = ARGB32_BLUE8(foreground) + ARGB32_BLUE8(background);
3232 b = (b<<3)/10;
3233
3234 return MAKE_ARGB32(a, r, g, b);
3235}
3236
3237
3238////////////////////////////////////////////////////////////////////////////////
3239/// Bevel is used to create 3D effect while drawing buttons, or any other
3240/// image that needs to be framed. Bevel is drawn using 2 primary colors:
3241/// one for top and left sides - hi color, and another for bottom and
3242/// right sides - low color. Bevel can be drawn over existing image or
3243/// as newly created, as it is shown in code below:
3244/// ~~~ {.cpp}
3245/// TImage *img = TImage::Create();
3246/// img->Bevel(0, 0, 400, 300, "#dddddd", "#000000", 3);
3247/// ~~~
3248
3250 const char *hi_color, const char *lo_color, UShort_t thick,
3251 Bool_t reverse)
3252{
3253 if (!InitVisual()) {
3254 Warning("Bevel", "Visual not initiated");
3255 return;
3256 }
3257
3258 ASImageBevel bevel;
3259 bevel.type = 0;
3260
3261 ARGB32 hi=ARGB32_White, lo=ARGB32_White;
3262 parse_argb_color(hi_color, &hi);
3263 parse_argb_color(lo_color, &lo);
3264
3265 if (reverse) {
3266 bevel.lo_color = hi;
3267 bevel.lolo_color = GetHilite(hi);
3268 bevel.hi_color = lo;
3269 bevel.hihi_color = GetShadow(lo);
3270 } else {
3271 bevel.hi_color = hi;
3272 bevel.hihi_color = GetHilite(hi);
3273 bevel.lo_color = lo;
3274 bevel.lolo_color = GetShadow(lo);
3275 }
3276 bevel.hilo_color = GetAverage(hi, lo);
3277
3278 int extra_hilite = 2;
3279 bevel.left_outline = bevel.top_outline = bevel.right_outline = bevel.bottom_outline = thick;
3280 bevel.left_inline = bevel.top_inline = bevel.right_inline = bevel.bottom_inline = extra_hilite + 1;
3281
3282 if (bevel.top_outline > 1) {
3283 bevel.top_inline += bevel.top_outline - 1;
3284 }
3285
3286 if (bevel.left_outline > 1) {
3287 bevel.left_inline += bevel.left_outline - 1;
3288 }
3289
3290 if (bevel.right_outline > 1) {
3291 bevel.right_inline += bevel.right_outline - 1;
3292 }
3293
3294 if (bevel.bottom_outline > 1) {
3295 bevel.bottom_inline += bevel.bottom_outline - 1;
3296 }
3297
3298 ASImage *merge_im;
3299 ARGB32 fill = ((hi>>24) != 0xff) || ((lo>>24) != 0xff) ? bevel.hilo_color : (bevel.hilo_color | 0xff000000);
3300
3301 if (!fImage) {
3302 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
3303
3304 if (!fImage) {
3305 Warning("Bevel", "Failed to create image");
3306 return;
3307 }
3308
3309 x = 0;
3310 y = 0;
3311 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, fill);
3312 }
3313
3314 width = !width ? fImage->width : width;
3315 height = !height ? fImage->height : height;
3316
3317 ASImageLayer layers[2];
3318 init_image_layers(&(layers[0]), 2);
3319
3320 layers[0].im = fImage;
3321 layers[0].dst_x = 0;
3322 layers[0].dst_y = 0;
3323 layers[0].clip_width = fImage->width;
3324 layers[0].clip_height = fImage->height;
3325 layers[0].bevel = 0;
3326
3327 UInt_t w = width - (bevel.left_outline + bevel.right_outline);
3328 UInt_t h = height - (bevel.top_outline + bevel.bottom_outline);
3329 ASImage *bevel_im = create_asimage(w, h, 0);
3330
3331 if (!bevel_im) {
3332 Warning("Bevel", "Failed to create bevel image");
3333 return;
3334 }
3335
3336 layers[1].im = bevel_im;
3337 fill_asimage(fgVisual, bevel_im, 0, 0, w, h, fill);
3338
3339 layers[1].dst_x = x;
3340 layers[1].dst_y = y;
3341 layers[1].clip_width = width;
3342 layers[1].clip_height = height;
3343 layers[1].bevel = &bevel;
3344 layers[1].merge_scanlines = alphablend_scanlines;
3345
3346 merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
3347 ASA_ASImage, GetImageCompression(), GetImageQuality());
3348 destroy_asimage(&bevel_im);
3349
3350 if (!merge_im) {
3351 Warning("Bevel", "Failed to image");
3352 return;
3353 }
3354
3355 DestroyImage();
3356 fImage = merge_im;
3357 UnZoom();
3358}
3359
3360
3361////////////////////////////////////////////////////////////////////////////////
3362/// Enlarge image, padding it with specified color on each side in
3363/// accordance with requested geometry.
3364
3365void TASImage::Pad(const char *col, UInt_t l, UInt_t r, UInt_t t, UInt_t b)
3366{
3367 Int_t x, y;
3368 UInt_t w, h;
3369
3370 if (!InitVisual()) {
3371 Warning("Pad", "Visual not initiated");
3372 return;
3373 }
3374
3375 if (!fImage) {
3376 fImage = create_asimage(100, 100, 0);
3377
3378 if (!fImage) {
3379 Warning("Pad", "Failed to create image");
3380 return;
3381 }
3382
3383 x = 0;
3384 y = 0;
3385 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
3386 }
3387
3388 ARGB32 color = ARGB32_White;
3389 parse_argb_color(col, &color);
3390
3391 x = l;
3392 y = t;
3393 w = l + fImage->width + r;
3394 h = t + fImage->height + b;
3395
3396 ASImage *img = pad_asimage(fgVisual, fImage, x, y, w, h, color,
3397 ASA_ASImage, GetImageCompression(), GetImageQuality());
3398
3399 if (!img) {
3400 Warning("Pad", "Failed to create output image");
3401 return;
3402 }
3403
3404 DestroyImage();
3405 fImage = img;
3406 UnZoom();
3408}
3409
3410
3411////////////////////////////////////////////////////////////////////////////////
3412/// Crop an image.
3413
3415{
3416 if (!InitVisual()) {
3417 Warning("Crop", "Visual not initiated");
3418 return;
3419 }
3420
3421 if (!fImage) {
3422 Warning("Crop", "No image");
3423 return;
3424 }
3425
3426 x = x < 0 ? 0 : x;
3427 y = y < 0 ? 0 : y;
3428
3429 width = x + width > fImage->width ? fImage->width - x : width;
3430 height = y + height > fImage->height ? fImage->height - y : height;
3431
3432 if ((width == fImage->width) && (height == fImage->height)) {
3433 Warning("Crop", "input size larger than image");
3434 return;
3435 }
3436 ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
3437 x, y, width, height, 0);
3438
3439 if (!imdec) {
3440 Warning("Crop", "Failed to start image decoding");
3441 return;
3442 }
3443
3444 ASImage *img = create_asimage(width, height, 0);
3445
3446 if (!img) {
3447 delete [] imdec;
3448 Warning("Crop", "Failed to create image");
3449 return;
3450 }
3451
3452 ASImageOutput *imout = start_image_output(fgVisual, img, ASA_ASImage,
3454
3455 if (!imout) {
3456 Warning("Crop", "Failed to start image output");
3457 destroy_asimage(&img);
3458 if (imdec) delete [] imdec;
3459 return;
3460 }
3461
3462#ifdef HAVE_MMX
3463 mmx_init();
3464#endif
3465
3466 for (UInt_t i = 0; i < height; i++) {
3467 imdec->decode_image_scanline(imdec);
3468 imout->output_image_scanline(imout, &(imdec->buffer), 1);
3469 }
3470
3471 stop_image_decoding(&imdec);
3472 stop_image_output(&imout);
3473
3474#ifdef HAVE_MMX
3475 mmx_off();
3476#endif
3477
3478 DestroyImage();
3479 fImage = img;
3480 UnZoom();
3482}
3483
3484////////////////////////////////////////////////////////////////////////////////
3485/// Append image.
3486///
3487/// option:
3488/// - "+" - appends to the right side
3489/// - "/" - appends to the bottom
3490
3491void TASImage::Append(const TImage *im, const char *option, const char *color )
3492{
3493 if (!im) return;
3494
3495 if (!InitVisual()) {
3496 Warning("Append", "Visual not initiated");
3497 return;
3498 }
3499
3500 if (!fImage) {
3501 fImage = ((TASImage*)im)->fImage;
3502 return;
3503 }
3504
3505 TString opt = option;
3506 opt.Strip();
3507
3508 UInt_t width = fImage->width;
3509 UInt_t height = fImage->height;
3510
3511 if (opt == "+") {
3512 Pad(color, 0, im->GetWidth(), 0, 0);
3513 Merge(im, "alphablend", width, 0);
3514 } else if (opt == "/") {
3515 Pad(color, 0, 0, 0, im->GetHeight());
3516 Merge(im, "alphablend", 0, height);
3517 } else {
3518 return;
3519 }
3520
3521 UnZoom();
3522}
3523
3524////////////////////////////////////////////////////////////////////////////////
3525/// BeginPaint initializes internal array[width x height] of ARGB32 pixel
3526/// values.
3527///
3528/// That provides quick access to image during paint operations.
3529/// To RLE compress image one needs to call EndPaint method when painting
3530/// is over.
3531
3533{
3534 if (!InitVisual()) {
3535 Warning("BeginPaint", "Visual not initiated");
3536 return;
3537 }
3538
3539 if (!fImage) {
3540 return;
3541 }
3542
3543 fPaintMode = mode;
3544
3545 if (!fPaintMode || fImage->alt.argb32) {
3546 return;
3547 }
3548
3549 ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
3550 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
3551
3552 if (!img) {
3553 Warning("BeginPaint", "Failed to create image");
3554 return;
3555 }
3556
3557 DestroyImage();
3558 fImage = img;
3559}
3560
3561////////////////////////////////////////////////////////////////////////////////
3562/// EndPaint does internal RLE compression of image data.
3563
3565{
3566 if (!fImage) {
3567 Warning("EndPaint", "no image");
3568 return;
3569 }
3570
3571 if (!fImage->alt.argb32) return;
3572
3573 ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
3574 0, ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT);
3575
3576 if (!img) {
3577 Warning("EndPaint", "Failed to create image");
3578 return;
3579 }
3580
3582 DestroyImage();
3583 fImage = img;
3584}
3585
3586////////////////////////////////////////////////////////////////////////////////
3587/// Return a pointer to internal array[width x height] of ARGB32 values
3588/// This array is directly accessible. That allows to manipulate/change the
3589/// image.
3590
3592{
3593 if (!fImage) {
3594 Warning("GetArgbArray", "no image");
3595 return 0;
3596 }
3597
3598 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3599 if (!img) return 0;
3600
3601 if (!img->alt.argb32) {
3602 if (fScaledImage) {
3604 img = fScaledImage->fImage;
3605 } else {
3606 BeginPaint();
3607 img = fImage;
3608 }
3609 }
3610
3611 return (UInt_t *)img->alt.argb32;
3612}
3613
3614////////////////////////////////////////////////////////////////////////////////
3615/// Return a pointer to an array[width x height] of RGBA32 values.
3616/// This array is created from internal ARGB32 array,
3617/// must be deleted after usage.
3618
3620{
3621 if (!fImage) {
3622 Warning("GetRgbaArray", "no image");
3623 return 0;
3624 }
3625
3626 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3627 if (!img) return 0;
3628
3629 if (!img->alt.argb32) {
3630 if (fScaledImage) {
3632 img = fScaledImage->fImage;
3633 } else {
3634 BeginPaint();
3635 img = fImage;
3636 }
3637 }
3638
3639 UInt_t i, j;
3640 Int_t y = 0;
3641 Int_t idx = 0;
3642 UInt_t a, rgb, rgba, argb;
3643 y = 0;
3644
3645 UInt_t *ret = new UInt_t[img->width*img->height];
3646
3647 for (i = 0; i < img->height; i++) {
3648 for (j = 0; j < img->width; j++) {
3649 idx = Idx(y + j);
3650 argb = img->alt.argb32[idx];
3651 a = argb >> 24;
3652 rgb = argb & 0x00ffffff;
3653 rgba = (rgb << 8) + a;
3654 ret[idx] = rgba;
3655 }
3656 y += img->width;
3657 }
3658
3659 return ret;
3660}
3661
3662////////////////////////////////////////////////////////////////////////////////
3663/// Return a pointer to scan-line.
3664
3666{
3667 if (!fImage) {
3668 Warning("GetScanline", "no image");
3669 return 0;
3670 }
3671
3672 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3673 CARD32 *ret = new CARD32[img->width];
3674
3675 ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALL,
3676 0, y, img->width, 1, 0);
3677
3678 if (!imdec) {
3679 delete [] ret;
3680 Warning("GetScanline", "Failed to start image decoding");
3681 return 0;
3682 }
3683
3684#ifdef HAVE_MMX
3685 mmx_init();
3686#endif
3687
3688 imdec->decode_image_scanline(imdec);
3689 memcpy(imdec->buffer.buffer, ret, img->width*sizeof(CARD32));
3690 stop_image_decoding(&imdec);
3691
3692#ifdef HAVE_MMX
3693 mmx_off();
3694#endif
3695
3696 return (UInt_t*)ret;
3697}
3698
3699
3700//______________________________________________________________________________
3701//
3702// Vector graphics
3703// a couple of macros which can be "assembler accelerated"
3704
3705#if defined(R__GNU) && defined(__i386__) && !defined(__sun)
3706#define _MEMSET_(dst, lng, val) __asm__("movl %0,%%eax \n"\
3707 "movl %1,%%edi \n" \
3708 "movl %2,%%ecx \n" \
3709 "cld \n" \
3710 "rep \n" \
3711 "stosl \n" \
3712 : /* no output registers */ \
3713 :"g" (val), "g" (dst), "g" (lng) \
3714 :"eax","edi","ecx" \
3715 )
3716
3717#else
3718 #define _MEMSET_(dst, lng, val) do {\
3719 for( UInt_t j=0; j < lng; j++) *((dst)+j) = val; } while (0)
3720
3721#endif
3722
3723#define FillSpansInternal(npt, ppt, widths, color) do {\
3724 UInt_t yy = ppt[0].fY*fImage->width;\
3725 for (UInt_t i = 0; i < npt; i++) {\
3726 _MEMSET_(&fImage->alt.argb32[Idx(yy + ppt[i].fX)], widths[i], color);\
3727 yy += ((i+1 < npt) && (ppt[i].fY != ppt[i+1].fY) ? fImage->width : 0);\
3728 }\
3729} while (0)
3730
3731////////////////////////////////////////////////////////////////////////////////
3732/// Fill rectangle of size (width, height) at position (x,y)
3733/// within the existing image with specified color.
3734
3736{
3737
3738 if (!InitVisual()) {
3739 Warning("FillRectangle", "Visual not initiated");
3740 return;
3741 }
3742
3743 if (!fImage) {
3744 Warning("FillRectangle", "no image");
3745 return;
3746 }
3747
3748 if (!fImage->alt.argb32) {
3749 BeginPaint();
3750 }
3751
3752 if (!fImage->alt.argb32) {
3753 Warning("FillRectangle", "Failed to get pixel array");
3754 return;
3755 }
3756
3757 ARGB32 color = (ARGB32)col;
3758
3759 if (width == 0) width = 1;
3760 if (height == 0) height = 1;
3761
3762 if (x < 0) {
3763 width += x;
3764 x = 0;
3765 }
3766 if (y < 0) {
3767 height += y;
3768 y = 0;
3769 }
3770
3771 Bool_t has_alpha = (color & 0xff000000) != 0xff000000;
3772
3773 x = x > (int)fImage->width ? (Int_t)fImage->width : x;
3774 y = y > (int)fImage->height ? (Int_t)fImage->height : y;
3775
3776 width = x + width > fImage->width ? fImage->width - x : width;
3777 height = y + height > fImage->height ? fImage->height - y : height;
3778
3779 if (!fImage->alt.argb32) {
3780 fill_asimage(fgVisual, fImage, x, y, width, height, color);
3781 } else {
3782 int yyy = y*fImage->width;
3783 if (!has_alpha) { // use faster memset
3784 ARGB32 *p0 = fImage->alt.argb32 + yyy + x;
3785 ARGB32 *p = p0;
3786 for (UInt_t i = 0; i < height; i++) {
3787 _MEMSET_(p, width, color);
3788 p += fImage->width;
3789 }
3790 } else {
3791 for (UInt_t i = y; i < y + height; i++) {
3792 int j = x + width;
3793 while (j > x) {
3794 j--;
3795 _alphaBlend(&fImage->alt.argb32[Idx(yyy + j)], &color);
3796 }
3797 yyy += fImage->width;
3798 }
3799 }
3800 }
3801}
3802
3803////////////////////////////////////////////////////////////////////////////////
3804/// Fill rectangle of size (width, height) at position (x,y)
3805/// within the existing image with specified color.
3806///
3807/// To create new image with Fill method the following code can be used:
3808/// ~~~ {.cpp}
3809/// TImage *img = TImage::Create();
3810/// img->Fill("#FF00FF", 0, 0, 400, 300);
3811/// ~~~
3812
3813void TASImage::FillRectangle(const char *col, Int_t x, Int_t y, UInt_t width, UInt_t height)
3814{
3815 if (!InitVisual()) {
3816 Warning("Fill", "Visual not initiated");
3817 return;
3818 }
3819
3820 ARGB32 color = ARGB32_White;
3821
3822 if (col) {
3823 parse_argb_color(col, &color);
3824 }
3825
3826 if (!fImage) {
3827 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
3828 x = 0;
3829 y = 0;
3830 }
3831
3832 FillRectangleInternal((UInt_t)color, x, y, width, height);
3833 UnZoom();
3834}
3835
3836////////////////////////////////////////////////////////////////////////////////
3837/// Draw a vertical line.
3838
3840{
3841 ARGB32 color = (ARGB32)col;
3842 UInt_t half = 0;
3843
3844 if (!thick) thick = 1;
3845
3846 if (thick > 1) {
3847 half = thick >> 1;
3848 if (x > half) {
3849 x = x - half;
3850 } else {
3851 x = 0;
3852 thick += (x - half);
3853 }
3854 }
3855
3856 y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
3857 y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
3858 x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
3859
3860 int yy = y1*fImage->width;
3861 for (UInt_t y = y1; y <= y2; y++) {
3862 for (UInt_t w = 0; w < thick; w++) {
3863 if (x + w < fImage->width) {
3864 _alphaBlend(&fImage->alt.argb32[Idx(yy + (x + w))], &color);
3865 }
3866 }
3867 yy += fImage->width;
3868 }
3869}
3870
3871////////////////////////////////////////////////////////////////////////////////
3872/// Draw an horizontal line.
3873
3875{
3876 ARGB32 color = (ARGB32)col;
3877 UInt_t half = 0;
3878
3879 if (!thick) thick = 1;
3880
3881 if (thick > 1) {
3882 half = thick >> 1;
3883 if (y > half) {
3884 y = y - half;
3885 } else {
3886 y = 0;
3887 thick += (y - half);
3888 }
3889 }
3890
3891 y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
3892 x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
3893 x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
3894
3895 int yy = y*fImage->width;
3896 for (UInt_t w = 0; w < thick; w++) {
3897 for (UInt_t x = x1; x <= x2; x++) {
3898 if (y + w < fImage->height) {
3899 _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
3900 }
3901 }
3902 yy += fImage->width;
3903 }
3904}
3905
3906////////////////////////////////////////////////////////////////////////////////
3907/// Draw a line.
3908
3910 const char *col, UInt_t thick)
3911{
3912 ARGB32 color = ARGB32_White;
3913 parse_argb_color(col, &color);
3914 DrawLineInternal(x1, y1, x2, y2, (UInt_t)color, thick);
3915}
3916
3917////////////////////////////////////////////////////////////////////////////////
3918/// Internal line drawing.
3919
3921 UInt_t col, UInt_t thick)
3922{
3923 int dx, dy, d;
3924 int i1, i2;
3925 int x, y, xend, yend;
3926 int xdir, ydir;
3927 int q;
3928 int idx;
3929 int yy;
3930
3931 if (!InitVisual()) {
3932 Warning("DrawLine", "Visual not initiated");
3933 return;
3934 }
3935
3936 if (!fImage) {
3937 Warning("DrawLine", "no image");
3938 return;
3939 }
3940
3941 if (!fImage->alt.argb32) {
3942 BeginPaint();
3943 }
3944
3945 if (!fImage->alt.argb32) {
3946 Warning("DrawLine", "Failed to get pixel array");
3947 return;
3948 }
3949
3950 ARGB32 color = (ARGB32)col;
3951
3952 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
3953 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
3954
3955 if (!dx && !dy) return; // invisible line
3956
3957 if (!dx) {
3958 DrawVLine(x1, y2 > y1 ? y1 : y2,
3959 y2 > y1 ? y2 : y1, color, thick);
3960 return;
3961 }
3962
3963 if (!dy) {
3964 DrawHLine(y1, x2 > x1 ? x1 : x2,
3965 x2 > x1 ? x2 : x1, color, thick);
3966 return;
3967 }
3968
3969 if (thick > 1) {
3970 DrawWideLine(x1, y1, x2, y2, color, thick);
3971 return;
3972 }
3973
3974 if (dy <= dx) {
3975 UInt_t ddy = dy << 1;
3976 i1 = ddy;
3977 i2 = i1 - (dx << 1);
3978 d = i1 - dx;
3979
3980 if (x1 > x2) {
3981 x = x2;
3982 y = y2;
3983 ydir = -1;
3984 xend = x1;
3985 } else {
3986 x = x1;
3987 y = y1;
3988 ydir = 1;
3989 xend = x2;
3990 }
3991
3992 yy = y*fImage->width;
3993 _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
3994 q = (y2 - y1) * ydir;
3995
3996 if (q > 0) {
3997 while (x < xend) {
3998
3999 idx = Idx(yy + x);
4000 _alphaBlend(&fImage->alt.argb32[idx], &color);
4001 x++;
4002
4003 if (d >= 0) {
4004 yy += fImage->width;
4005 d += i2;
4006 } else {
4007 d += i1;
4008 }
4009 }
4010 } else {
4011 while (x < xend) {
4012 idx = Idx(yy + x);
4013 _alphaBlend(&fImage->alt.argb32[idx], &color);
4014 x++;
4015
4016 if (d >= 0) {
4017 yy -= fImage->width;
4018 d += i2;
4019 } else {
4020 d += i1;
4021 }
4022 }
4023 }
4024 } else {
4025 UInt_t ddx = dx << 1;
4026 i1 = ddx;
4027 i2 = i1 - (dy << 1);
4028 d = i1 - dy;
4029
4030 if (y1 > y2) {
4031 y = y2;
4032 x = x2;
4033 yend = y1;
4034 xdir = -1;
4035 } else {
4036 y = y1;
4037 x = x1;
4038 yend = y2;
4039 xdir = 1;
4040 }
4041
4042 yy = y*fImage->width;
4043 _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
4044 q = (x2 - x1) * xdir;
4045
4046 if (q > 0) {
4047 while (y < yend) {
4048 idx = Idx(yy + x);
4049 _alphaBlend(&fImage->alt.argb32[idx], &color);
4050 y++;
4051 yy += fImage->width;
4052
4053 if (d >= 0) {
4054 x++;
4055 d += i2;
4056 } else {
4057 d += i1;
4058 }
4059 }
4060 } else {
4061 while (y < yend) {
4062 idx = Idx(yy + x);
4063 _alphaBlend(&fImage->alt.argb32[idx], &color);
4064 y++;
4065 yy += fImage->width;
4066
4067 if (d >= 0) {
4068 x--;
4069 d += i2;
4070 } else {
4071 d += i1;
4072 }
4073 }
4074 }
4075 }
4076}
4077
4078////////////////////////////////////////////////////////////////////////////////
4079/// Draw a rectangle.
4080
4082 const char *col, UInt_t thick)
4083{
4084 if (!InitVisual()) {
4085 Warning("DrawRectangle", "Visual not initiated");
4086 return;
4087 }
4088
4089 if (!fImage) {
4090 w = w ? w : 20;
4091 h = h ? h : 20;
4092 x = 0;
4093 y = 0;
4094 fImage = create_asimage(w, h, 0);
4095 FillRectangle(col, 0, 0, w, h);
4096 return;
4097 }
4098
4099 if (!fImage->alt.argb32) {
4100 BeginPaint();
4101 }
4102
4103 if (!fImage->alt.argb32) {
4104 Warning("DrawRectangle", "Failed to get pixel array");
4105 return;
4106 }
4107
4108 ARGB32 color = ARGB32_White;
4109 parse_argb_color(col, &color);
4110
4111 DrawHLine(y, x, x + w, (UInt_t)color, thick);
4112 DrawVLine(x + w, y, y + h, (UInt_t)color, thick);
4113 DrawHLine(y + h, x, x + w, (UInt_t)color, thick);
4114 DrawVLine(x, y, y + h, (UInt_t)color, thick);
4115 UnZoom();
4116}
4117
4118////////////////////////////////////////////////////////////////////////////////
4119/// Draw a box.
4120
4121void TASImage::DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, const char *col,
4122 UInt_t thick, Int_t mode)
4123{
4124 Int_t x = TMath::Min(x1, x2);
4125 Int_t y = TMath::Min(y1, y2);
4126 Int_t w = TMath::Abs(x2 - x1);
4127 Int_t h = TMath::Abs(y2 - y1);
4128
4129 ARGB32 color = ARGB32_White;
4130
4131 if (!fImage) {
4132 w = w ? x+w : x+20;
4133 h = h ? y+h : y+20;
4134 fImage = create_asimage(w, h, 0);
4135 FillRectangle(col, 0, 0, w, h);
4136 return;
4137 }
4138
4139 if (x1 == x2) {
4140 parse_argb_color(col, &color);
4141 DrawVLine(x1, y1, y2, color, 1);
4142 return;
4143 }
4144
4145 if (y1 == y2) {
4146 parse_argb_color(col, &color);
4147 DrawHLine(y1, x1, x2, color, 1);
4148 return;
4149 }
4150
4151
4152 switch (mode) {
4153 case TVirtualX::kHollow:
4154 DrawRectangle(x, y, w, h, col, thick);
4155 break;
4156
4157 case TVirtualX::kFilled:
4158 FillRectangle(col, x, y, w, h);
4159 break;
4160
4161 default:
4162 FillRectangle(col, x, y, w, h);
4163 break;
4164 }
4165}
4166
4167////////////////////////////////////////////////////////////////////////////////
4168/// Draw a dashed horizontal line.
4169
4171 const char *pDash, UInt_t col, UInt_t thick)
4172{
4173 UInt_t iDash = 0; // index of current dash
4174 int i = 0;
4175
4176 ARGB32 color = (ARGB32)col;
4177
4178 UInt_t half = 0;
4179
4180 if (thick > 1) {
4181 half = thick >> 1;
4182 if (y > half) {
4183 y = y - half;
4184 } else {
4185 y = 0;
4186 thick += (y - half);
4187 }
4188 }
4189 thick = thick <= 0 ? 1 : thick;
4190
4191 y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
4192 x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
4193 x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
4194
4195 // switch x1, x2
4196 UInt_t tmp = x1;
4197 x1 = x2 < x1 ? x2 : x1;
4198 x2 = x2 < tmp ? tmp : x2;
4199
4200 for (UInt_t x = x1; x <= x2; x++) {
4201 for (UInt_t w = 0; w < thick; w++) {
4202 if (y + w < fImage->height) {
4203 if ((iDash%2)==0) {
4204 _alphaBlend(&fImage->alt.argb32[Idx((y + w)*fImage->width + x)], &color);
4205 }
4206 }
4207 }
4208 i++;
4209
4210 if (i >= pDash[iDash]) {
4211 iDash++;
4212 i = 0;
4213 }
4214 if (iDash >= nDash) {
4215 iDash = 0;
4216 i = 0;
4217 }
4218 }
4219}
4220
4221////////////////////////////////////////////////////////////////////////////////
4222/// Draw a dashed vertical line.
4223
4225 const char *pDash, UInt_t col, UInt_t thick)
4226{
4227 UInt_t iDash = 0; // index of current dash
4228 int i = 0;
4229
4230 ARGB32 color = (ARGB32)col;
4231
4232 UInt_t half = 0;
4233
4234 if (thick > 1) {
4235 half = thick >> 1;
4236 if (x > half) {
4237 x = x - half;
4238 } else {
4239 x = 0;
4240 thick += (x - half);
4241 }
4242 }
4243 thick = thick <= 0 ? 1 : thick;
4244
4245 y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
4246 y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
4247
4248 // switch x1, x2
4249 UInt_t tmp = y1;
4250 y1 = y2 < y1 ? y2 : y1;
4251 y2 = y2 < tmp ? tmp : y2;
4252
4253 x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
4254
4255 int yy = y1*fImage->width;
4256 for (UInt_t y = y1; y <= y2; y++) {
4257 for (UInt_t w = 0; w < thick; w++) {
4258 if (x + w < fImage->width) {
4259 if ((iDash%2)==0) {
4260 _alphaBlend(&fImage->alt.argb32[Idx(yy + (x + w))], &color);
4261 }
4262 }
4263 }
4264 i++;
4265
4266 if (i >= pDash[iDash]) {
4267 iDash++;
4268 i = 0;
4269 }
4270 if (iDash >= nDash) {
4271 iDash = 0;
4272 i = 0;
4273 }
4274 yy += fImage->width;
4275 }
4276}
4277
4278////////////////////////////////////////////////////////////////////////////////
4279/// Draw a dashed line with one pixel width.
4280
4282 UInt_t nDash, const char *tDash, UInt_t color)
4283{
4284 int dx, dy, d;
4285 int i, i1, i2;
4286 int x, y, xend, yend;
4287 int xdir, ydir;
4288 int q;
4289 UInt_t iDash = 0; // index of current dash
4290 int yy;
4291 int idx;
4292
4293 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
4294 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
4295
4296 char *pDash = new char[nDash];
4297
4298 if (dy <= dx) {
4299 double ac = TMath::Cos(TMath::ATan2(dy, dx));
4300
4301 for (i = 0; i < (int)nDash; i++) {
4302 pDash[i] = TMath::Nint(tDash[i] * ac);
4303 }
4304
4305 UInt_t ddy = dy << 1;
4306 i1 = ddy;
4307 i2 = i1 - (dx << 1);
4308 d = i1 - dx;
4309 i = 0;
4310
4311 if (x1 > x2) {
4312 x = x2;
4313 y = y2;
4314 ydir = -1;
4315 xend = x1;
4316 } else {
4317 x = x1;
4318 y = y1;
4319 ydir = 1;
4320 xend = x2;
4321 }
4322
4323 yy = y*fImage->width;
4324 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4325 q = (y2 - y1) * ydir;
4326
4327 if (q > 0) {
4328 while (x < xend) {
4329 idx = Idx(yy + x);
4330 if ((iDash%2) == 0) {
4331 _alphaBlend(&fImage->alt.argb32[idx], &color);
4332 }
4333 x++;
4334 if (d >= 0) {
4335 yy += fImage->width;
4336 d += i2;
4337 } else {
4338 d += i1;
4339 }
4340
4341 i++;
4342 if (i >= pDash[iDash]) {
4343 iDash++;
4344 i = 0;
4345 }
4346 if (iDash >= nDash) {
4347 iDash = 0;
4348 i = 0;
4349 }
4350 }
4351 } else {
4352 while (x < xend) {
4353 idx = Idx(yy + x);
4354 if ((iDash%2) == 0) {
4355 _alphaBlend(&fImage->alt.argb32[idx], &color);
4356 }
4357 x++;
4358 if (d >= 0) {
4359 yy -= fImage->width;
4360 d += i2;
4361 } else {
4362 d += i1;
4363 }
4364
4365 i++;
4366 if (i >= pDash[iDash]) {
4367 iDash++;
4368 i = 0;
4369 }
4370 if (iDash >= nDash) {
4371 iDash = 0;
4372 i = 0;
4373 }
4374 }
4375 }
4376 } else {
4377 double as = TMath::Sin(TMath::ATan2(dy, dx));
4378
4379 for (i = 0; i < (int)nDash; i++) {
4380 pDash[i] = TMath::Nint(tDash[i] * as);
4381 }
4382
4383 UInt_t ddx = dx << 1;
4384 i1 = ddx;
4385 i2 = i1 - (dy << 1);
4386 d = i1 - dy;
4387 i = 0;
4388
4389 if (y1 > y2) {
4390 y = y2;
4391 x = x2;
4392 yend = y1;
4393 xdir = -1;
4394 } else {
4395 y = y1;
4396 x = x1;
4397 yend = y2;
4398 xdir = 1;
4399 }
4400
4401 yy = y*fImage->width;
4402 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4403 q = (x2 - x1) * xdir;
4404
4405 if (q > 0) {
4406 while (y < yend) {
4407 idx = Idx(yy + x);
4408 if ((iDash%2) == 0) {
4409 _alphaBlend(&fImage->alt.argb32[idx], &color);
4410 }
4411 y++;
4412 yy += fImage->width;
4413
4414 if (d >= 0) {
4415 x++;
4416 d += i2;
4417 } else {
4418 d += i1;
4419 }
4420
4421 i++;
4422 if (i >= pDash[iDash]) {
4423 iDash++;
4424 i = 0;
4425 }
4426 if (iDash >= nDash) {
4427 iDash = 0;
4428 i = 0;
4429 }
4430 }
4431 } else {
4432 while (y < yend) {
4433 idx = Idx(yy + x);
4434 if ((iDash%2) == 0) {
4435 _alphaBlend(&fImage->alt.argb32[idx], &color);
4436 }
4437 y++;
4438 yy += fImage->width;
4439
4440 if (d >= 0) {
4441 x--;
4442 d += i2;
4443 } else {
4444 d += i1;
4445 }
4446
4447 i++;
4448 if (i >= pDash[iDash]) {
4449 iDash++;
4450 i = 0;
4451 }
4452 if (iDash >= nDash) {
4453 iDash = 0;
4454 i = 0;
4455 }
4456 }
4457 }
4458 }
4459 delete [] pDash;
4460}
4461
4462////////////////////////////////////////////////////////////////////////////////
4463/// Draw a dashed line with thick pixel width.
4464
4466 UInt_t nDash, const char *tDash, UInt_t color, UInt_t thick)
4467{
4468 int dx, dy;
4469 int i;
4470 double x, y, xend=0, yend=0, x0, y0;
4471 int xdir, ydir;
4472 int q;
4473 UInt_t iDash = 0; // index of current dash
4474
4475 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
4476 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
4477
4478 double *xDash = new double[nDash];
4479 double *yDash = new double[nDash];
4480 double a = TMath::ATan2(dy, dx);
4481 double ac = TMath::Cos(a);
4482 double as = TMath::Sin(a);
4483
4484 for (i = 0; i < (int)nDash; i++) {
4485 xDash[i] = tDash[i] * ac;
4486 yDash[i] = tDash[i] * as;
4487
4488 // dirty trick (must be fixed)
4489 if ((i%2) == 0) {
4490 xDash[i] = xDash[i]/2;
4491 yDash[i] = yDash[i]/2;
4492 } else {
4493 xDash[i] = xDash[i]*2;
4494 yDash[i] = yDash[i]*2;
4495 }
4496 }
4497
4498 if (dy <= dx) {
4499 if (x1 > x2) {
4500 x = x2;
4501 y = y2;
4502 ydir = -1;
4503 xend = x1;
4504 } else {
4505 x = x1;
4506 y = y1;
4507 ydir = 1;
4508 xend = x2;
4509 }
4510
4511 q = (y2 - y1) * ydir;
4512 x0 = x;
4513 y0 = y;
4514 iDash = 0;
4515 yend = y + q;
4516
4517 if (q > 0) {
4518 while ((x < xend) && (y < yend)) {
4519 x += xDash[iDash];
4520 y += yDash[iDash];
4521
4522 if ((iDash%2) == 0) {
4524 TMath::Nint(x), TMath::Nint(y), color, thick);
4525 } else {
4526 x0 = x;
4527 y0 = y;
4528 }
4529
4530 iDash++;
4531
4532 if (iDash >= nDash) {
4533 iDash = 0;
4534 }
4535 }
4536 } else {
4537 while ((x < xend) && (y > yend)) {
4538 x += xDash[iDash];
4539 y -= yDash[iDash];
4540
4541 if ((iDash%2) == 0) {
4543 TMath::Nint(x), TMath::Nint(y), color, thick);
4544 } else {
4545 x0 = x;
4546 y0 = y;
4547 }
4548
4549 iDash++;
4550
4551 if (iDash >= nDash) {
4552 iDash = 0;
4553 }
4554 }
4555 }
4556 } else {
4557
4558 if (y1 > y2) {
4559 y = y2;
4560 x = x2;
4561 yend = y1;
4562 xdir = -1;
4563 } else {
4564 y = y1;
4565 x = x1;
4566 yend = y2;
4567 xdir = 1;
4568 }
4569
4570 q = (x2 - x1) * xdir;
4571 x0 = x;
4572 y0 = y;
4573 iDash = 0;
4574 xend = x + q;
4575
4576 if (q > 0) {
4577 while ((x < xend) && (y < yend)) {
4578 x += xDash[iDash];
4579 y += yDash[iDash];
4580
4581 if ((iDash%2) == 0) {
4583 TMath::Nint(x), TMath::Nint(y), color, thick);
4584 } else {
4585 x0 = x;
4586 y0 = y;
4587 }
4588
4589 iDash++;
4590
4591 if (iDash >= nDash) {
4592 iDash = 0;
4593 }
4594 }
4595 } else {
4596 while ((x > xend) && (y < yend)) {
4597 x -= xDash[iDash];
4598 y += yDash[iDash];
4599
4600 if ((iDash%2) == 0) {
4602 TMath::Nint(x), TMath::Nint(y), color, thick);
4603 } else {
4604 x0 = x;
4605 y0 = y;
4606 }
4607
4608 iDash++;
4609
4610 if (iDash >= nDash) {
4611 iDash = 0;
4612 }
4613 }
4614 }
4615 }
4616 delete [] xDash;
4617 delete [] yDash;
4618}
4619
4620////////////////////////////////////////////////////////////////////////////////
4621/// Draw a dashed line.
4622
4624 const char *pDash, const char *col, UInt_t thick)
4625
4626{
4627 if (!InitVisual()) {
4628 Warning("DrawDashLine", "Visual not initiated");
4629 return;
4630 }
4631
4632 if (!fImage) {
4633 Warning("DrawDashLine", "no image");
4634 return;
4635 }
4636
4637 if (!fImage->alt.argb32) {
4638 BeginPaint();
4639 }
4640
4641 if (!fImage->alt.argb32) {
4642 Warning("DrawDashLine", "Failed to get pixel array");
4643 return;
4644 }
4645
4646 if ((nDash < 2) || !pDash || (nDash%2)) {
4647 Warning("DrawDashLine", "Wrong input parameters n=%d %ld", nDash, (Long_t)sizeof(pDash)-1);
4648 return;
4649 }
4650
4651 ARGB32 color = ARGB32_White;
4652 parse_argb_color(col, &color);
4653
4654 if (x1 == x2) {
4655 DrawDashVLine(x1, y1, y2, nDash, pDash, (UInt_t)color, thick);
4656 } else if (y1 == y2) {
4657 DrawDashHLine(y1, x1, x2, nDash, pDash, (UInt_t)color, thick);
4658 } else {
4659 if (thick < 2) DrawDashZLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color);
4660 else DrawDashZTLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color, thick);
4661 }
4662}
4663
4664////////////////////////////////////////////////////////////////////////////////
4665/// Draw a polyline.
4666
4667void TASImage::DrawPolyLine(UInt_t nn, TPoint *xy, const char *col, UInt_t thick,
4668 TImage::ECoordMode mode)
4669{
4670 ARGB32 color = ARGB32_White;
4671 parse_argb_color(col, &color);
4672
4673 Int_t x0 = xy[0].GetX();
4674 Int_t y0 = xy[0].GetY();
4675 Int_t x = 0;
4676 Int_t y = 0;
4677
4678 for (UInt_t i = 1; i < nn; i++) {
4679 x = (mode == kCoordModePrevious) ? x + xy[i].GetX() : xy[i].GetX();
4680 y = (mode == kCoordModePrevious) ? y + xy[i].GetY() : xy[i].GetY();
4681
4682 DrawLineInternal(x0, y0, x, y, (UInt_t)color, thick);
4683
4684 x0 = x;
4685 y0 = y;
4686 }
4687}
4688
4689////////////////////////////////////////////////////////////////////////////////
4690/// Draw a point at the specified position.
4691
4692void TASImage::PutPixel(Int_t x, Int_t y, const char *col)
4693{
4694 if (!InitVisual()) {
4695 Warning("PutPixel", "Visual not initiated");
4696 return;
4697 }
4698
4699 if (!fImage) {
4700 Warning("PutPixel", "no image");
4701 return;
4702 }
4703
4704 if (!fImage->alt.argb32) {
4705 BeginPaint();
4706 }
4707
4708 if (!fImage->alt.argb32) {
4709 Warning("PutPixel", "Failed to get pixel array");
4710 return;
4711 }
4712
4713 ARGB32 color;
4714 parse_argb_color(col, &color);
4715
4716 if ((x < 0) || (y < 0) || (x >= (int)fImage->width) || (y >= (int)fImage->height)) {
4717 Warning("PutPixel", "Out of range width=%d x=%d, height=%d y=%d",
4718 fImage->width, x, fImage->height, y);
4719 return;
4720 }
4721 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4722}
4723
4724////////////////////////////////////////////////////////////////////////////////
4725/// Draw a poly point.
4726
4727void TASImage::PolyPoint(UInt_t npt, TPoint *ppt, const char *col, TImage::ECoordMode mode)
4728{
4729 if (!InitVisual()) {
4730 Warning("PolyPoint", "Visual not initiated");
4731 return;
4732 }
4733
4734 if (!fImage) {
4735 Warning("PolyPoint", "no image");
4736 return;
4737 }
4738
4739 if (!fImage->alt.argb32) {
4740 BeginPaint();
4741 }
4742
4743 if (!fImage->alt.argb32) {
4744 Warning("PolyPoint", "Failed to get pixel array");
4745 return;
4746 }
4747
4748 if (!npt || !ppt) {
4749 Warning("PolyPoint", "No points specified");
4750 return;
4751 }
4752
4753 TPoint *ipt = 0;
4754 UInt_t i = 0;
4755 ARGB32 color;
4756 parse_argb_color(col, &color);
4757
4758 //make pointlist origin relative
4759 if (mode == kCoordModePrevious) {
4760 ipt = new TPoint[npt];
4761
4762 for (i = 0; i < npt; i++) {
4763 ipt[i].fX += ppt[i].fX;
4764 ipt[i].fY += ppt[i].fY;
4765 }
4766 }
4767 int x, y;
4768
4769 for (i = 0; i < npt; i++) {
4770 x = ipt ? ipt[i].fX : ppt[i].fX;
4771 y = ipt ? ipt[i].fY : ppt[i].fY;
4772
4773 if ((x < 0) || (y < 0) || (x >= (int)fImage->width) || (y >= (int)fImage->height)) {
4774 continue;
4775 }
4776 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4777 }
4778
4779 if (ipt) {
4780 delete [] ipt;
4781 }
4782}
4783
4784////////////////////////////////////////////////////////////////////////////////
4785/// Draw segments.
4786
4787void TASImage::DrawSegments(UInt_t nseg, Segment_t *seg, const char *col, UInt_t thick)
4788{
4789 if (!nseg || !seg) {
4790 Warning("DrawSegments", "Invalid data nseg=%d seg=0x%lx", nseg, (Long_t)seg);
4791 return;
4792 }
4793
4794 TPoint pt[2];
4795
4796 for (UInt_t i = 0; i < nseg; i++) {
4797 pt[0].fX = seg->fX1;
4798 pt[1].fX = seg->fX2;
4799 pt[0].fY = seg->fY1;
4800 pt[1].fY = seg->fY2;
4801
4802 DrawPolyLine(2, pt, col, thick, kCoordModeOrigin);
4803 seg++;
4804 }
4805}
4806
4807////////////////////////////////////////////////////////////////////////////////
4808/// Fill spans with specified color or/and stipple.
4809
4810void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, const char *col,
4811 const char *stipple, UInt_t w, UInt_t h)
4812{
4813 if (!InitVisual()) {
4814 Warning("FillSpans", "Visual not initiated");
4815 return;
4816 }
4817
4818 if (!fImage) {
4819 Warning("FillSpans", "no image");
4820 return;
4821 }
4822
4823 if (!fImage->alt.argb32) {
4824 BeginPaint();
4825 }
4826
4827 if (!fImage->alt.argb32) {
4828 Warning("FillSpans", "Failed to get pixel array");
4829 return;
4830 }
4831
4832 if (!npt || !ppt || !widths || (stipple && (!w || !h))) {
4833 Warning("FillSpans", "Invalid input data npt=%d ppt=0x%lx col=%s widths=0x%lx stipple=0x%lx w=%d h=%d",
4834 npt, (Long_t)ppt, col, (Long_t)widths, (Long_t)stipple, w, h);
4835 return;
4836 }
4837
4838 ARGB32 color;
4839 parse_argb_color(col, &color);
4840 Int_t idx = 0;
4841 UInt_t x = 0;
4842 UInt_t yy;
4843
4844 for (UInt_t i = 0; i < npt; i++) {
4845 yy = ppt[i].fY*fImage->width;
4846 for (UInt_t j = 0; j < widths[i]; j++) {
4847 if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
4848 (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0)) continue;
4849
4850 x = ppt[i].fX + j;
4851 idx = Idx(yy + x);
4852
4853 if (!stipple) {
4854 _alphaBlend(&fImage->alt.argb32[idx], &color);
4855 } else {
4856 Int_t ii = (ppt[i].fY%h)*w + x%w;
4857
4858 if (stipple[ii >> 3] & (1 << (ii%8))) {
4859 _alphaBlend(&fImage->alt.argb32[idx], &color);
4860 }
4861 }
4862 }
4863 }
4864}
4865
4866////////////////////////////////////////////////////////////////////////////////
4867/// Fill spans with tile image.
4868
4869void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, TImage *tile)
4870{
4871 if (!InitVisual()) {
4872 Warning("FillSpans", "Visual not initiated");
4873 return;
4874 }
4875
4876 if (!fImage) {
4877 Warning("FillSpans", "no image");
4878 return;
4879 }
4880
4881 if (!fImage->alt.argb32) {
4882 BeginPaint();
4883 }
4884
4885 if (!fImage->alt.argb32) {
4886 Warning("FillSpans", "Failed to get pixel array");
4887 return;
4888 }
4889
4890 if (!npt || !ppt || !widths || !tile) {
4891 Warning("FillSpans", "Invalid input data npt=%d ppt=0x%lx widths=0x%lx tile=0x%lx",
4892 npt, (Long_t)ppt, (Long_t)widths, (Long_t)tile);
4893 return;
4894 }
4895
4896 Int_t idx = 0;
4897 Int_t ii = 0;
4898 UInt_t x = 0;
4899 UInt_t *arr = tile->GetArgbArray();
4900 if (!arr) return;
4901 UInt_t xx = 0;
4902 UInt_t yy = 0;
4903 UInt_t yyy = 0;
4904
4905 for (UInt_t i = 0; i < npt; i++) {
4906 yyy = ppt[i].fY*fImage->width;
4907
4908 for (UInt_t j = 0; j < widths[i]; j++) {
4909 if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
4910 (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0)) continue;
4911 x = ppt[i].fX + j;
4912 idx = Idx(yyy + x);
4913 xx = x%tile->GetWidth();
4914 yy = ppt[i].fY%tile->GetHeight();
4915 ii = yy*tile->GetWidth() + xx;
4916 _alphaBlend(&fImage->alt.argb32[idx], &arr[ii]);
4917 }
4918 yyy += fImage->width;;
4919 }
4920}
4921
4922////////////////////////////////////////////////////////////////////////////////
4923/// Crop spans.
4924
4925void TASImage::CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths)
4926{
4927 if (!InitVisual()) {
4928 Warning("CropSpans", "Visual not initiated");
4929 return;
4930 }
4931
4932 if (!fImage) {
4933 Warning("CropSpans", "no image");
4934 return;
4935 }
4936
4937 if (!fImage->alt.argb32) {
4938 BeginPaint();
4939 }
4940
4941 if (!fImage->alt.argb32) {
4942 Warning("CropSpans", "Failed to get pixel array");
4943 return;
4944 }
4945
4946 if (!npt || !ppt || !widths) {
4947 Warning("CropSpans", "No points specified npt=%d ppt=0x%lx widths=0x%lx", npt, (Long_t)ppt, (Long_t)widths);
4948 return;
4949 }
4950
4951 int y0 = ppt[0].fY;
4952 int y1 = ppt[npt-1].fY;
4953 UInt_t y = 0;
4954 UInt_t x = 0;
4955 UInt_t i = 0;
4956 UInt_t idx = 0;
4957 UInt_t sz = fImage->width*fImage->height;
4958 UInt_t yy = y*fImage->width;
4959
4960 for (y = 0; (int)y < y0; y++) {
4961 for (x = 0; x < fImage->width; x++) {
4962 idx = Idx(yy + x);
4963 if (idx < sz) fImage->alt.argb32[idx] = 0;
4964 }
4965 yy += fImage->width;
4966 }
4967
4968 for (i = 0; i < npt; i++) {
4969 for (x = 0; (int)x < ppt[i].fX; x++) {
4970 idx = Idx(ppt[i].fY*fImage->width + x);
4971 if (idx < sz) fImage->alt.argb32[idx] = 0;
4972 }
4973 for (x = ppt[i].fX + widths[i] + 1; x < fImage->width; x++) {
4974 idx = Idx(ppt[i].fY*fImage->width + x);
4975 if (idx < sz) fImage->alt.argb32[idx] = 0;
4976 }
4977 }
4978
4979 yy = y1*fImage->width;
4980 for (y = y1; y < fImage->height; y++) {
4981 for (x = 0; x < fImage->width; x++) {
4982 idx = Idx(yy + x);
4983 if (idx < sz) fImage->alt.argb32[idx] = 0;
4984 }
4985 yy += fImage->width;
4986 }
4987}
4988
4989////////////////////////////////////////////////////////////////////////////////
4990/// Copy source region to the destination image. Copy is done according
4991/// to specified function:
4992/// ~~~ {.cpp}
4993/// enum EGraphicsFunction {
4994/// kGXclear = 0, // 0
4995/// kGXand, // src AND dst
4996/// kGXandReverse, // src AND NOT dst
4997/// kGXcopy, // src (default)
4998/// kGXandInverted, // NOT src AND dst
4999/// kGXnoop, // dst
5000/// kGXxor, // src XOR dst
5001/// kGXor, // src OR dst
5002/// kGXnor, // NOT src AND NOT dst
5003/// kGXequiv, // NOT src XOR dst
5004/// kGXinvert, // NOT dst
5005/// kGXorReverse, // src OR NOT dst
5006/// kGXcopyInverted, // NOT src
5007/// kGXorInverted, // NOT src OR dst
5008/// kGXnand, // NOT src OR NOT dst
5009/// kGXset // 1
5010/// };
5011/// ~~~
5012
5014 Int_t xdst, Int_t ydst, Int_t gfunc, EColorChan)
5015{
5016 if (!InitVisual()) {
5017 Warning("CopyArea", "Visual not initiated");
5018 return;
5019 }
5020
5021 if (!fImage) {
5022 Warning("CopyArea", "no image");
5023 return;
5024 }
5025 if (!dst) return;
5026
5027 ASImage *out = ((TASImage*)dst)->GetImage();
5028
5029 int x = 0;
5030 int y = 0;
5031 int idx = 0;
5032 int idx2 = 0;
5033 xsrc = xsrc < 0 ? 0 : xsrc;
5034 ysrc = ysrc < 0 ? 0 : ysrc;
5035
5036 if ((xsrc >= (int)fImage->width) || (ysrc >= (int)fImage->height)) return;
5037
5038 w = xsrc + w > fImage->width ? fImage->width - xsrc : w;
5039 h = ysrc + h > fImage->height ? fImage->height - ysrc : h;
5040 UInt_t yy = (ysrc + y)*fImage->width;
5041
5042 if (!fImage->alt.argb32) {
5043 BeginPaint();
5044 }
5045 if (!out->alt.argb32) {
5046 dst->BeginPaint();
5047 out = ((TASImage*)dst)->GetImage();
5048 }
5049
5050 if (fImage->alt.argb32 && out->alt.argb32) {
5051 for (y = 0; y < (int)h; y++) {
5052 for (x = 0; x < (int)w; x++) {
5053 idx = Idx(yy + x + xsrc);
5054 if ((x + xdst < 0) || (ydst + y < 0) ||
5055 (x + xdst >= (int)out->width) || (y + ydst >= (int)out->height) ) continue;
5056
5057 idx2 = Idx((ydst + y)*out->width + x + xdst);
5058
5059 switch ((EGraphicsFunction)gfunc) {
5060 case kGXclear:
5061 out->alt.argb32[idx2] = 0;
5062 break;
5063 case kGXand:
5064 out->alt.argb32[idx2] &= fImage->alt.argb32[idx];
5065 break;
5066 case kGXandReverse:
5067 out->alt.argb32[idx2] = fImage->alt.argb32[idx] & (~out->alt.argb32[idx2]);
5068 break;
5069 case kGXandInverted:
5070 out->alt.argb32[idx2] &= ~fImage->alt.argb32[idx];
5071 break;
5072 case kGXnoop:
5073 break;
5074 case kGXxor:
5075 out->alt.argb32[idx2] ^= fImage->alt.argb32[idx];
5076 break;
5077 case kGXor:
5078 out->alt.argb32[idx2] |= fImage->alt.argb32[idx];
5079 break;
5080 case kGXnor:
5081 out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) & (~out->alt.argb32[idx2]);
5082 break;
5083 case kGXequiv:
5084 out->alt.argb32[idx2] ^= ~fImage->alt.argb32[idx];
5085 break;
5086 case kGXinvert:
5087 out->alt.argb32[idx2] = ~out->alt.argb32[idx2];
5088 break;
5089 case kGXorReverse:
5090 out->alt.argb32[idx2] = fImage->alt.argb32[idx] | (~out->alt.argb32[idx2]);
5091 break;
5092 case kGXcopyInverted:
5093 out->alt.argb32[idx2] = ~fImage->alt.argb32[idx];
5094 break;
5095 case kGXorInverted:
5096 out->alt.argb32[idx2] |= ~fImage->alt.argb32[idx];
5097 break;
5098 case kGXnand:
5099 out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) | (~out->alt.argb32[idx2]);
5100 break;
5101 case kGXset:
5102 out->alt.argb32[idx2] = 0xFFFFFFFF;
5103 break;
5104 case kGXcopy:
5105 default:
5106 out->alt.argb32[idx2] = fImage->alt.argb32[idx];
5107 break;
5108 }
5109 }
5110 yy += fImage->width;
5111 }
5112 }
5113}
5114
5115////////////////////////////////////////////////////////////////////////////////
5116/// Draw a cell array.
5117///
5118/// \param[in] x1,y1 : left down corner
5119/// \param[in] x2,y2 : right up corner
5120/// \param[in] nx,ny : array size
5121/// \param[in] ic : array of ARGB32 colors
5122///
5123/// Draw a cell array. The drawing is done with the pixel precision
5124/// if (X2-X1)/NX (or Y) is not a exact pixel number the position of
5125/// the top right corner may be wrong.
5126
5128 Int_t ny, UInt_t *ic)
5129{
5130 int i, j, ix, iy, w, h;
5131
5132 ARGB32 color = 0xFFFFFFFF;
5133 ARGB32 icol;
5134
5135 w = TMath::Max((x2-x1)/(nx),1);
5136 h = TMath::Max((y1-y2)/(ny),1);
5137 ix = x1;
5138
5139 for (i = 0; i < nx; i++) {
5140 iy = y1 - h;
5141 for (j = 0; j < ny; j++) {
5142 icol = (ARGB32)ic[i + (nx*j)];
5143 if (icol != color) {
5144 color = icol;
5145 }
5146 FillRectangleInternal((UInt_t)color, ix, iy, w, h);
5147 iy = iy - h;
5148 }
5149 ix = ix + w;
5150 }
5151}
5152
5153////////////////////////////////////////////////////////////////////////////////
5154/// Return alpha-blended value computed from bottom and top pixel values.
5155
5157{
5158 UInt_t ret = bot;
5159
5160 _alphaBlend(&ret, &top);
5161 return ret;
5162}
5163
5164////////////////////////////////////////////////////////////////////////////////
5165/// Return visual.
5166
5167const ASVisual *TASImage::GetVisual()
5168{
5169 return fgVisual;
5170}
5171
5172////////////////////////////////////////////////////////////////////////////////
5173/// Get poly bounds along Y.
5174
5175static int GetPolyYBounds(TPoint *pts, int n, int *by, int *ty)
5176{
5177 TPoint *ptMin;
5178 int ymin, ymax;
5179 TPoint *ptsStart = pts;
5180
5181 ptMin = pts;
5182 ymin = ymax = (pts++)->fY;
5183
5184 while (--n > 0) {
5185 if (pts->fY < ymin) {
5186 ptMin = pts;
5187 ymin = pts->fY;
5188 }
5189 if (pts->fY > ymax) {
5190 ymax = pts->fY;
5191 }
5192 pts++;
5193 }
5194
5195 *by = ymin;
5196 *ty = ymax;
5197 return (ptMin - ptsStart);
5198}
5199
5200////////////////////////////////////////////////////////////////////////////////
5201/// The code is based on Xserver/mi/mipolycon.c
5202/// "Copyright 1987, 1998 The Open Group"
5203
5205 TPoint **outPoint, UInt_t **outWidth)
5206{
5207 int xl = 0; // x vals of leftedges
5208 int xr = 0; // x vals of right edges
5209 int dl = 0; // decision variables
5210 int dr = 0; // decision variables
5211 int ml = 0; // left edge slope
5212 int m1l = 0; // left edge slope+1
5213 int mr = 0, m1r = 0; // right edge slope and slope+1
5214 int incr1l = 0, incr2l = 0; // left edge error increments
5215 int incr1r = 0, incr2r = 0; // right edge error increments
5216 int dy; // delta y
5217 int y; // current scanline
5218 int left, right; // indices to first endpoints
5219 int i; // loop counter
5220 int nextleft, nextright; // indices to second endpoints
5221 TPoint *ptsOut; // output buffer
5222 UInt_t *width; // output buffer
5223 TPoint *firstPoint=0;
5224 UInt_t *firstWidth=0;
5225 int imin; // index of smallest vertex (in y)
5226 int ymin; // y-extents of polygon
5227 int ymax;
5228 Bool_t ret = kTRUE;
5229
5230 *nspans = 0;
5231
5232 if (!InitVisual()) {
5233 Warning("GetPolygonSpans", "Visual not initiated");
5234 return kFALSE;
5235 }
5236
5237 if (!fImage) {
5238 Warning("GetPolygonSpans", "no image");
5239 return kFALSE;
5240 }
5241
5242 if (!fImage->alt.argb32) {
5243 BeginPaint();
5244 }
5245
5246 if (!fImage->alt.argb32) {
5247 Warning("GetPolygonSpans", "Failed to get pixel array");
5248 return kFALSE;
5249 }
5250
5251 if ((npt < 3) || !ppt) {
5252 Warning("GetPolygonSpans", "No points specified npt=%d ppt=0x%lx", npt, (Long_t)ppt);
5253 return kFALSE;
5254 }
5255
5256 // find leftx, bottomy, rightx, topy, and the index
5257 // of bottomy. Also translate the points.
5258 imin = GetPolyYBounds(ppt, npt, &ymin, &ymax);
5259
5260 dy = ymax - ymin + 1;
5261 if ((npt < 3) || (dy < 0)) return kFALSE;
5262
5263 ptsOut = firstPoint = new TPoint[dy];
5264 width = firstWidth = new UInt_t[dy];
5265 ret = kTRUE;
5266
5267 nextleft = nextright = imin;
5268 y = ppt[nextleft].fY;
5269
5270 // loop through all edges of the polygon
5271 do {
5272 // add a left edge if we need to
5273 if (ppt[nextleft].fY == y) {
5274 left = nextleft;
5275
5276 // find the next edge, considering the end
5277 // conditions of the array.
5278 nextleft++;
5279 if (nextleft >= (int)npt) {
5280 nextleft = 0;
5281 }
5282
5283 // now compute all of the random information
5284 // needed to run the iterative algorithm.
5285 BRESINITPGON(ppt[nextleft].fY - ppt[left].fY,
5286 ppt[left].fX, ppt[nextleft].fX,
5287 xl, dl, ml, m1l, incr1l, incr2l);
5288 }
5289
5290 // add a right edge if we need to
5291 if (ppt[nextright].fY == y) {
5292 right = nextright;
5293
5294 // find the next edge, considering the end
5295 // conditions of the array.
5296 nextright--;
5297 if (nextright < 0) {
5298 nextright = npt-1;
5299 }
5300
5301 // now compute all of the random information
5302 // needed to run the iterative algorithm.
5303 BRESINITPGON(ppt[nextright].fY - ppt[right].fY,
5304 ppt[right].fX, ppt[nextright].fX,
5305 xr, dr, mr, m1r, incr1r, incr2r);
5306 }
5307
5308 // generate scans to fill while we still have
5309 // a right edge as well as a left edge.
5310 i = TMath::Min(ppt[nextleft].fY, ppt[nextright].fY) - y;
5311
5312 // in case of non-convex polygon
5313 if (i < 0) {
5314 delete [] firstWidth;
5315 delete [] firstPoint;
5316 return kTRUE;
5317 }
5318
5319 while (i-- > 0) {
5320 ptsOut->fY = y;
5321
5322 // reverse the edges if necessary
5323 if (xl < xr) {
5324 *(width++) = xr - xl;
5325 (ptsOut++)->fX = xl;
5326 } else {
5327 *(width++) = xl - xr;
5328 (ptsOut++)->fX = xr;
5329 }
5330 y++;
5331
5332 // increment down the edges
5333 BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l);
5334 BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r);
5335 }
5336 } while (y != ymax);
5337
5338 *nspans = UInt_t(ptsOut - firstPoint);
5339 *outPoint = firstPoint;
5340 *outWidth = firstWidth;
5341
5342 return ret;
5343}
5344
5345////////////////////////////////////////////////////////////////////////////////
5346/// Fill a convex polygon with background color or bitmap.
5347/// For non convex polygon one must use DrawFillArea method
5348
5349void TASImage::FillPolygon(UInt_t npt, TPoint *ppt, const char *col,
5350 const char *stipple, UInt_t w, UInt_t h)
5351{
5352 UInt_t nspans = 0;
5353 TPoint *firstPoint = 0; // output buffer
5354 UInt_t *firstWidth = 0; // output buffer
5355
5356 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5357 ARGB32 color = ARGB32_White;
5358 parse_argb_color(col, &color);
5359
5360 if (nspans) {
5361 if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple no alpha
5362 FillSpansInternal(nspans, firstPoint, firstWidth, color);
5363 } else {
5364 FillSpans(nspans, firstPoint, firstWidth, col, stipple, w, h);
5365 }
5366
5367 if (del) {
5368 delete [] firstWidth;
5369 delete [] firstPoint;
5370 }
5371 } else {
5372 if (firstWidth) delete [] firstWidth;
5373 if (firstPoint) delete [] firstPoint;
5374 }
5375}
5376
5377////////////////////////////////////////////////////////////////////////////////
5378/// Fill a convex polygon with background image.
5379/// For non convex polygon one must use DrawFillArea method
5380
5382{
5383 UInt_t nspans = 0;
5384 TPoint *firstPoint = 0; // output buffer
5385 UInt_t *firstWidth = 0; // output buffer
5386
5387 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5388
5389 if (nspans) {
5390 FillSpans(nspans, firstPoint, firstWidth, tile);
5391
5392 if (del) {
5393 delete [] firstWidth;
5394 delete [] firstPoint;
5395 }
5396 } else {
5397 if (firstWidth) delete [] firstWidth;
5398 if (firstPoint) delete [] firstPoint;
5399 }
5400}
5401
5402////////////////////////////////////////////////////////////////////////////////
5403/// Crop a convex polygon.
5404
5406{
5407 UInt_t nspans = 0;
5408 TPoint *firstPoint = 0;
5409 UInt_t *firstWidth = 0;
5410
5411 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5412
5413 if (nspans) {
5414 CropSpans(nspans, firstPoint, firstWidth);
5415
5416 if (del) {
5417 delete [] firstWidth;
5418 delete [] firstPoint;
5419 }
5420 } else {
5421 if (firstWidth) delete [] firstWidth;
5422 if (firstPoint) delete [] firstPoint;
5423 }
5424}
5425
5426static const UInt_t NUMPTSTOBUFFER = 512;
5427
5428////////////////////////////////////////////////////////////////////////////////
5429/// Fill a polygon (any type convex, non-convex).
5430
5431void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, const char *col,
5432 const char *stipple, UInt_t w, UInt_t h)
5433{
5434 if (!InitVisual()) {
5435 Warning("DrawFillArea", "Visual not initiated");
5436 return;
5437 }
5438
5439 if (!fImage) {
5440 Warning("DrawFillArea", "no image");
5441 return;
5442 }
5443
5444 if (!fImage->alt.argb32) {
5445 BeginPaint();
5446 }
5447
5448 if (!fImage->alt.argb32) {
5449 Warning("DrawFillArea", "Failed to get pixel array");
5450 return;
5451 }
5452
5453 if ((count < 3) || !ptsIn) {
5454 Warning("DrawFillArea", "No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
5455 return;
5456 }
5457
5458 if (count < 5) {
5459 FillPolygon(count, ptsIn, col, stipple, w, h);
5460 return;
5461 }
5462
5463 ARGB32 color = ARGB32_White;
5464 parse_argb_color(col, &color);
5465
5466 EdgeTableEntry *pAET; // the Active Edge Table
5467 int y; // the current scanline
5468 UInt_t nPts = 0; // number of pts in buffer
5469
5470 ScanLineList *pSLL; // Current ScanLineList
5471 TPoint *ptsOut; // ptr to output buffers
5472 UInt_t *width;
5473 TPoint firstPoint[NUMPTSTOBUFFER]; // the output buffers
5474 UInt_t firstWidth[NUMPTSTOBUFFER];
5475 EdgeTableEntry *pPrevAET; // previous AET entry
5476 EdgeTable ET; // Edge Table header node
5477 EdgeTableEntry AET; // Active ET header node
5478 EdgeTableEntry *pETEs; // Edge Table Entries buff
5479 ScanLineListBlock SLLBlock; // header for ScanLineList
5480 Bool_t del = kTRUE;
5481
5482 static const UInt_t gEdgeTableEntryCacheSize = 200;
5483 static EdgeTableEntry gEdgeTableEntryCache[gEdgeTableEntryCacheSize];
5484
5485 if (count < gEdgeTableEntryCacheSize) {
5486 pETEs = (EdgeTableEntry*)&gEdgeTableEntryCache;
5487 del = kFALSE;
5488 } else {
5489 pETEs = new EdgeTableEntry[count];
5490 del = kTRUE;
5491 }
5492
5493 ptsOut = firstPoint;
5494 width = firstWidth;
5495 CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
5496 pSLL = ET.scanlines.next;
5497
5498 for (y = ET.ymin; y < ET.ymax; y++) {
5499 if (pSLL && y == pSLL->scanline) {
5500 loadAET(&AET, pSLL->edgelist);
5501 pSLL = pSLL->next;
5502 }
5503 pPrevAET = &AET;
5504 pAET = AET.next;
5505
5506 while (pAET) {
5507 ptsOut->fX = pAET->bres.minor_axis;
5508 ptsOut->fY = y;
5509 ptsOut++;
5510 nPts++;
5511
5512 *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
5513
5514 if (nPts == NUMPTSTOBUFFER) {
5515 if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple, no alpha
5516 FillSpansInternal(nPts, firstPoint, firstWidth, color);
5517 } else {
5518 FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
5519 }
5520 ptsOut = firstPoint;
5521 width = firstWidth;
5522 nPts = 0;
5523 }
5524 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5525 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5526 }
5527 InsertionSort(&AET);
5528 }
5529
5530 if (nPts) {
5531 if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple, no alpha
5532 FillSpansInternal(nPts, firstPoint, firstWidth, color);
5533 } else {
5534 FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
5535 }
5536 }
5537
5538 if (del) delete [] pETEs;
5539 FreeStorage(SLLBlock.next);
5540}
5541
5542////////////////////////////////////////////////////////////////////////////////
5543/// Fill a polygon (any type convex, non-convex).
5544
5545void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, TImage *tile)
5546{
5547 if (!InitVisual()) {
5548 Warning("DrawFillArea", "Visual not initiated");
5549 return;
5550 }
5551
5552 if (!fImage) {
5553 Warning("DrawFillArea", "no image");
5554 return;
5555 }
5556
5557 if (!fImage->alt.argb32) {
5558 BeginPaint();
5559 }
5560
5561 if (!fImage->alt.argb32) {
5562 Warning("DrawFillArea", "Failed to get pixel array");
5563 return;
5564 }
5565
5566 if ((count < 3) || !ptsIn) {
5567 Warning("DrawFillArea", "No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
5568 return;
5569 }
5570
5571 if (count < 5) {
5572 FillPolygon(count, ptsIn, tile);
5573 return;
5574 }
5575
5576 EdgeTableEntry *pAET; // the Active Edge Table
5577 int y; // the current scanline
5578 UInt_t nPts = 0; // number of pts in buffer
5579
5580 ScanLineList *pSLL; // Current ScanLineList
5581 TPoint *ptsOut; // ptr to output buffers
5582 UInt_t *width;
5583 TPoint firstPoint[NUMPTSTOBUFFER]; // the output buffers
5584 UInt_t firstWidth[NUMPTSTOBUFFER];
5585 EdgeTableEntry *pPrevAET; // previous AET entry
5586 EdgeTable ET; // Edge Table header node
5587 EdgeTableEntry AET; // Active ET header node
5588 EdgeTableEntry *pETEs; // Edge Table Entries buff
5589 ScanLineListBlock SLLBlock; // header for ScanLineList
5590
5591 pETEs = new EdgeTableEntry[count];
5592
5593 ptsOut = firstPoint;
5594 width = firstWidth;
5595 CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
5596 pSLL = ET.scanlines.next;
5597
5598 for (y = ET.ymin; y < ET.ymax; y++) {
5599 if (pSLL && y == pSLL->scanline) {
5600 loadAET(&AET, pSLL->edgelist);
5601 pSLL = pSLL->next;
5602 }
5603 pPrevAET = &AET;
5604 pAET = AET.next;
5605
5606 while (pAET) {
5607 ptsOut->fX = pAET->bres.minor_axis;
5608 ptsOut->fY = y;
5609 ptsOut++;
5610 nPts++;
5611
5612 *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
5613
5614 if (nPts == NUMPTSTOBUFFER) {
5615 FillSpans(nPts, firstPoint, firstWidth, tile);
5616 ptsOut = firstPoint;
5617 width = firstWidth;
5618 nPts = 0;
5619 }
5620 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5621 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5622 }
5623 InsertionSort(&AET);
5624 }
5625 FillSpans(nPts, firstPoint, firstWidth, tile);
5626
5627 delete [] pETEs;
5628 FreeStorage(SLLBlock.next);
5629}
5630
5631////////////////////////////////////////////////////////////////////////////////
5632/// Create draw context.
5633
5634static ASDrawContext *create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
5635{
5636 ASDrawContext *ctx = new ASDrawContext;
5637
5638 ctx->canvas_width = im->width;
5639 ctx->canvas_height = im->height;
5640 ctx->canvas = im->alt.argb32;
5641 ctx->scratch_canvas = 0;
5642
5643 ctx->flags = ASDrawCTX_CanvasIsARGB;
5644 asim_set_custom_brush_colored( ctx, brush);
5645 return ctx;
5646}
5647
5648////////////////////////////////////////////////////////////////////////////////
5649/// Destroy asdraw context32.
5650
5651static void destroy_asdraw_context32( ASDrawContext *ctx )
5652{
5653 if (ctx) {
5654 if (ctx->scratch_canvas) free(ctx->scratch_canvas);
5655 delete ctx;
5656 }
5657}
5658
5659static const UInt_t kBrushCacheSize = 20;
5661
5662////////////////////////////////////////////////////////////////////////////////
5663/// Draw wide line.
5664
5666 UInt_t color, UInt_t thick)
5667{
5668 Int_t sz = thick*thick;
5669 CARD32 *matrix;
5670 Bool_t use_cache = thick < kBrushCacheSize;
5671
5672 if (use_cache) {
5673 matrix = gBrushCache;
5674 } else {
5675 matrix = new CARD32[sz];
5676 }
5677
5678 for (int i = 0; i < sz; i++) {
5679 matrix[i] = (CARD32)color;
5680 };
5681
5682 ASDrawTool brush;
5683 brush.matrix = matrix;
5684 brush.width = thick;
5685 brush.height = thick;
5686 brush.center_y = brush.center_x = thick/2;
5687
5688 // When the first or last point of a wide line is exactly on the
5689 // window limit the line is drawn vertically or horizontally.
5690 // see https://sft.its.cern.ch/jira/browse/ROOT-8021
5691 UInt_t xx1 = x1;
5692 UInt_t yy1 = y1;
5693 UInt_t xx2 = x2;
5694 UInt_t yy2 = y2;
5695 if (xx1 == fImage->width) --xx1;
5696 if (yy1 == fImage->height) --yy1;
5697 if (xx2 == fImage->width) --xx2;
5698 if (yy2 == fImage->height) --yy2;
5699 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
5700 asim_move_to(ctx, xx1, yy1);
5701 asim_line_to(ctx, xx2, yy2);
5702
5703 if (!use_cache) {
5704 delete [] matrix;
5705 }
5707}
5708
5709////////////////////////////////////////////////////////////////////////////////
5710/// Draw glyph bitmap.
5711
5712void TASImage::DrawGlyph(void *bitmap, UInt_t color, Int_t bx, Int_t by)
5713{
5714 static UInt_t col[5];
5715 Int_t x, y, yy, y0, xx;
5716 Bool_t has_alpha = (color & 0xff000000) != 0xff000000;
5717
5718 ULong_t r, g, b;
5719 int idx = 0;
5720 FT_Bitmap *source = (FT_Bitmap*)bitmap;
5721 UChar_t d = 0, *s = source->buffer;
5722
5723 Int_t dots = Int_t(source->width * source->rows);
5724 r = g = b = 0;
5725 Int_t bxx, byy;
5726
5727 yy = y0 = by > 0 ? by * fImage->width : 0;
5728 for (y = 0; y < (int) source->rows; y++) {
5729 byy = by + y;
5730 if ((byy >= (int)fImage->height) || (byy <0)) continue;
5731
5732 for (x = 0; x < (int) source->width; x++) {
5733 bxx = bx + x;
5734 if ((bxx >= (int)fImage->width) || (bxx < 0)) continue;
5735
5736 idx = Idx(bxx + yy);
5737 r += ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
5738 g += ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
5739 b += (fImage->alt.argb32[idx] & 0x0000ff);
5740 }
5741 yy += fImage->width;
5742 }
5743 if (dots != 0) {
5744 r /= dots;
5745 g /= dots;
5746 b /= dots;
5747 }
5748
5749 col[0] = (r << 16) + (g << 8) + b;
5750 col[4] = color;
5751 Int_t col4r = (col[4] & 0xff0000) >> 16;
5752 Int_t col4g = (col[4] & 0x00ff00) >> 8;
5753 Int_t col4b = (col[4] & 0x0000ff);
5754
5755 // interpolate between fore and background colors
5756 for (x = 3; x > 0; x--) {
5757 xx = 4-x;
5758 Int_t colxr = (col4r*x + r*xx) >> 2;
5759 Int_t colxg = (col4g*x + g*xx) >> 2;
5760 Int_t colxb = (col4b*x + b*xx) >> 2;
5761 col[x] = (colxr << 16) + (colxg << 8) + colxb;
5762 }
5763
5764 yy = y0;
5765 ARGB32 acolor;
5766
5767 Int_t clipx1=0, clipx2=0, clipy1=0, clipy2=0;
5768 Bool_t noClip = kTRUE;
5769
5770 if (gPad) {
5772 clipx1 = gPad->XtoAbsPixel(gPad->GetX1())*is;
5773 clipx2 = gPad->XtoAbsPixel(gPad->GetX2())*is;
5774 clipy1 = gPad->YtoAbsPixel(gPad->GetY1())*is;
5775 clipy2 = gPad->YtoAbsPixel(gPad->GetY2())*is;
5776 noClip = kFALSE;
5777 }
5778
5779 for (y = 0; y < (int) source->rows; y++) {
5780 byy = by + y;
5781
5782 for (x = 0; x < (int) source->width; x++) {
5783 bxx = bx + x;
5784
5785 d = *s++ & 0xff;
5786 d = ((d + 10) * 5) >> 8;
5787 if (d > 4) d = 4;
5788
5789 if (d) {
5790 if ( noClip || ((x < (int) source->width) &&
5791 (bxx < (int)clipx2) && (bxx >= (int)clipx1) &&
5792 (byy >= (int)clipy2) && (byy < (int)clipy1) )) {
5793 idx = Idx(bxx + yy);
5794 acolor = (ARGB32)col[d];
5795 if (has_alpha) {
5796 _alphaBlend(&fImage->alt.argb32[idx], &acolor);
5797 } else {
5798 fImage->alt.argb32[idx] = acolor;
5799 }
5800 }
5801 }
5802 }
5803 yy += fImage->width;
5804 }
5805}
5806
5807////////////////////////////////////////////////////////////////////////////////
5808/// Draw text at the pixel position (x,y).
5809
5811{
5812 if (!text) return;
5813 if (!fImage) return;
5814 if (!gPad) return;
5815
5816 if (!InitVisual()) {
5817 Warning("DrawText", "Visual not initiated");
5818 return;
5819 }
5820
5821 if (!fImage->alt.argb32) {
5822 BeginPaint();
5823 }
5824
5825 if (!TTF::IsInitialized()) TTF::Init();
5826
5827 // set text font
5829
5830 Int_t wh = gPad->XtoPixel(gPad->GetX2());
5831 Int_t hh = gPad->YtoPixel(gPad->GetY1());
5832
5833 // set text size
5834 Float_t ttfsize;
5835 if (wh < hh) {
5836 ttfsize = text->GetTextSize()*wh;
5837 } else {
5838 ttfsize = text->GetTextSize()*hh;
5839 }
5840 TTF::SetTextSize(ttfsize*kScale);
5841
5842 // set text angle
5844
5845 // set text
5846 const wchar_t *wcsTitle = reinterpret_cast<const wchar_t *>(text->GetWcsTitle());
5847 if (wcsTitle != NULL) {
5848 TTF::PrepareString(wcsTitle);
5849 } else {
5851 }
5853
5854 // color
5855 TColor *col = gROOT->GetColor(text->GetTextColor());
5856 if (!col) { // no color, make it black
5857 col = gROOT->GetColor(1);
5858 if (!col) return;
5859 }
5860 ARGB32 color = ARGB32_White;
5861 parse_argb_color(col->AsHexString(), &color);
5862
5863 // Align()
5864 Int_t align = 0;
5865 Int_t txalh = text->GetTextAlign()/10;
5866 Int_t txalv = text->GetTextAlign()%10;
5867
5868 switch (txalh) {
5869 case 0 :
5870 case 1 :
5871 switch (txalv) { //left
5872 case 1 :
5873 align = 7; //bottom
5874 break;
5875 case 2 :
5876 align = 4; //center
5877 break;
5878 case 3 :
5879 align = 1; //top
5880 break;
5881 }
5882 break;
5883 case 2 :
5884 switch (txalv) { //center
5885 case 1 :
5886 align = 8; //bottom
5887 break;
5888 case 2 :
5889 align = 5; //center
5890 break;
5891 case 3 :
5892 align = 2; //top
5893 break;
5894 }
5895 break;
5896 case 3 :
5897 switch (txalv) { //right
5898 case 1 :
5899 align = 9; //bottom
5900 break;
5901 case 2 :
5902 align = 6; //center
5903 break;
5904 case 3 :
5905 align = 3; //top
5906 break;
5907 }
5908 break;
5909 }
5910
5911 FT_Vector ftal;
5912
5913 // vertical alignment
5914 if (align == 1 || align == 2 || align == 3) {
5915 ftal.y = TTF::GetAscent();
5916 } else if (align == 4 || align == 5 || align == 6) {
5917 ftal.y = TTF::GetAscent()/2;
5918 } else {
5919 ftal.y = 0;
5920 }
5921
5922 // horizontal alignment
5923 if (align == 3 || align == 6 || align == 9) {
5924 ftal.x = TTF::GetWidth();
5925 } else if (align == 2 || align == 5 || align == 8) {
5926 ftal.x = TTF::GetWidth()/2;
5927 } else {
5928 ftal.x = 0;
5929 }
5930
5931 FT_Vector_Transform(&ftal, TTF::GetRotMatrix());
5932 ftal.x = (ftal.x >> 6);
5933 ftal.y = (ftal.y >> 6);
5934
5935 TTF::TTGlyph *glyph = TTF::GetGlyphs();
5936
5937 for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
5938 if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 )) continue;
5939
5940 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
5941 FT_Bitmap *source = &bitmap->bitmap;
5942
5943 Int_t bx = x - ftal.x + bitmap->left;
5944 Int_t by = y + ftal.y - bitmap->top;
5945
5946 DrawGlyph(source, color, bx, by);
5947 }
5948}
5949
5950////////////////////////////////////////////////////////////////////////////////
5951/// Draw text using TrueType fonts.
5952
5953void TASImage::DrawTextTTF(Int_t x, Int_t y, const char *text, Int_t size,
5954 UInt_t color, const char *font_name, Float_t angle)
5955{
5956 if (!TTF::IsInitialized()) TTF::Init();
5957
5958 TTF::SetTextFont(font_name);
5959 TTF::SetTextSize(size);
5963
5964 TTF::TTGlyph *glyph = TTF::GetGlyphs();
5965
5966 // compute the size and position that will contain the text
5967 // Int_t Xoff = 0; if (TTF::GetBox().xMin < 0) Xoff = -TTF::GetBox().xMin;
5968 Int_t Yoff = 0; if (TTF::GetBox().yMin < 0) Yoff = -TTF::GetBox().yMin;
5969 Int_t h = TTF::GetBox().yMax + Yoff;
5970
5971 for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
5972 if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 )) continue;
5973
5974 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
5975 FT_Bitmap *source = &bitmap->bitmap;
5976
5977 Int_t bx = x + bitmap->left;
5978 Int_t by = y + h - bitmap->top;
5979 DrawGlyph(source, color, bx, by);
5980 }
5981}
5982
5983////////////////////////////////////////////////////////////////////////////////
5984/// Return in-memory buffer compressed according image type.
5985/// Buffer must be deallocated after usage.
5986/// This method can be used for sending images over network.
5987
5988void TASImage::GetImageBuffer(char **buffer, int *size, EImageFileTypes type)
5989{
5990 static ASImageExportParams params;
5991 Bool_t ret = kFALSE;
5992 int isize = 0;
5993 char *ibuff = 0;
5994 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
5995
5996 if (!img) return;
5997
5998 switch (type) {
5999 case TImage::kXpm:
6000 ret = ASImage2xpmRawBuff(img, (CARD8 **)buffer, size, 0);
6001 break;
6002 default:
6003 ret = ASImage2PNGBuff(img, (CARD8 **)buffer, size, &params);
6004 }
6005
6006 if (!ret) {
6007 *size = isize;
6008 *buffer = ibuff;
6009 }
6010}
6011
6012////////////////////////////////////////////////////////////////////////////////
6013/// Create image from compressed buffer.
6014/// Supported formats:
6015///
6016/// - PNG - by default
6017/// - XPM - two options exist:
6018/// 1. xpm as a single string (raw buffer). Such string
6019/// is returned by GetImageBuffer method.
6020/// For example:
6021/// ~~~ {.cpp}
6022/// char *buf;
6023/// int sz;
6024/// im1->GetImageBuffer(&buf, &int, TImage::kXpm); /*raw buffer*/
6025/// TImage *im2 = TImage::Create();
6026/// im2->SetImageBuffer(&buf, TImage::kXpm);
6027/// ~~~
6028/// 2. xpm as an array of strings (pre-parsed)
6029/// ~~~ {.cpp}
6030/// For example:
6031/// char *xpm[] = {
6032/// "64 28 58 1",
6033/// " c #0A030C",
6034/// ". c #1C171B"
6035/// ...
6036/// TImage *im = TImage::Create();
6037/// im->SetImageBuffer(xpm, TImage::kXpm);
6038/// ~~~
6039
6041{
6042 DestroyImage();
6043
6044 static ASImageImportParams params;
6045 params.flags = 0;
6046 params.width = 0;
6047 params.height = 0 ;
6048 params.filter = SCL_DO_ALL;
6049 params.gamma = 0;
6050 params.gamma_table = 0;
6051 params.compression = 0;
6052 params.format = ASA_ASImage;
6053 params.search_path = 0;
6054 params.subimage = 0;
6055
6056 switch (type) {
6057 case TImage::kXpm:
6058 {
6059 char *ptr = buffer[0];
6060 while (isspace((int)*ptr)) ++ptr;
6061 if (atoi(ptr)) { // pre-parsed and preloaded data
6062 fImage = xpm_data2ASImage((const char**)buffer, &params);
6063 } else {
6064 fImage = xpmRawBuff2ASImage((const char*)*buffer, &params);
6065 }
6066 break;
6067 }
6068 default:
6069 fImage = PNGBuff2ASimage((CARD8 *)*buffer, &params);
6070 break;
6071 }
6072
6073 if (!fImage) {
6074 return kFALSE;
6075 }
6076
6077 if (fName.IsNull()) {
6078 fName.Form("img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
6079 }
6080 UnZoom();
6081 return kTRUE;
6082}
6083
6084////////////////////////////////////////////////////////////////////////////////
6085/// Create image thumbnail.
6086
6088{
6089 int size;
6090 const int sz = 64;
6091
6092 if (!fImage) {
6093 return;
6094 }
6095
6096 if (!InitVisual()) {
6097 return;
6098 }
6099
6100 static char *buf = 0;
6101 int w, h;
6102 ASImage *img = 0;
6103
6104 if (fImage->width > fImage->height) {
6105 w = sz;
6106 h = (fImage->height*sz)/fImage->width;
6107 } else {
6108 h = sz;
6109 w = (fImage->width*sz)/fImage->height;
6110 }
6111
6112 w = w < 8 ? 8 : w;
6113 h = h < 8 ? 8 : h;
6114
6115 img = scale_asimage(fgVisual, fImage, w, h, ASA_ASImage,
6117 if (!img) {
6118 return;
6119 }
6120
6121 // contrasting
6122 ASImage *rendered_im;
6123 ASImageLayer layers[2];
6124 init_image_layers(&(layers[0]), 2);
6125 layers[0].im = img;
6126 layers[0].dst_x = 0;
6127 layers[0].dst_y = 0;
6128 layers[0].clip_width = img->width;
6129 layers[0].clip_height = img->height;
6130 layers[0].bevel = 0;
6131 layers[1].im = img;
6132 layers[1].dst_x = 0;
6133 layers[1].dst_y = 0;
6134 layers[1].clip_width = img->width;
6135 layers[1].clip_height = img->height;
6136 layers[1].merge_scanlines = blend_scanlines_name2func("tint");
6137 rendered_im = merge_layers(fgVisual, &(layers[0]), 2, img->width, img->height,
6138 ASA_ASImage, GetImageCompression(), GetImageQuality());
6139 destroy_asimage(&img);
6140 img = rendered_im;
6141
6142 // pad image
6143 ASImage *padimg = 0;
6144 int d = 0;
6145
6146 if (w == sz) {
6147 d = (sz - h) >> 1;
6148 padimg = pad_asimage(fgVisual, img, 0, d, sz, sz, 0x00ffffff,
6149 ASA_ASImage, GetImageCompression(), GetImageQuality());
6150 } else {
6151 d = (sz - w) >> 1;
6152 padimg = pad_asimage(fgVisual, img, d, 0, sz, sz, 0x00ffffff,
6153 ASA_ASImage, GetImageCompression(), GetImageQuality());
6154 }
6155
6156 if (!padimg) {
6157 destroy_asimage(&img);
6158 return;
6159 }
6160
6161 void *ptr = &buf;
6162 ASImage2xpmRawBuff(padimg, (CARD8 **)ptr, &size, 0);
6163 fTitle = buf;
6164
6165 destroy_asimage(&padimg);
6166}
6167
6168////////////////////////////////////////////////////////////////////////////////
6169/// Streamer for ROOT I/O.
6170
6171void TASImage::Streamer(TBuffer &b)
6172{
6173 Bool_t image_type = 0;
6174 char *buffer = 0;
6175 int size = 0;
6176 int w, h;
6177 UInt_t R__s, R__c;
6178
6179 if (b.IsReading()) {
6180 Version_t version = b.ReadVersion(&R__s, &R__c);
6181 if (version == 0) { //dumb prototype for schema evolution
6182 return;
6183 }
6184
6185 if ( version == 1 ) {
6186 Int_t fileVersion = b.GetVersionOwner();
6187 if (fileVersion > 0 && fileVersion < 50000 ) {
6188 TImage::Streamer(b);
6189 b >> fMaxValue;
6190 b >> fMinValue;
6191 b >> fZoomOffX;
6192 b >> fZoomOffY;
6193 b >> fZoomWidth;
6194 b >> fZoomHeight;
6195 if ( fileVersion < 40200 ) {
6196 Bool_t zoomUpdate;
6197 b >> zoomUpdate;
6198 fZoomUpdate = zoomUpdate;
6199 } else {
6200 b >> fZoomUpdate;
6201 b >> fEditable;
6202 Bool_t paintMode;
6203 b >> paintMode;
6204 fPaintMode = paintMode;
6205 }
6206 b.CheckByteCount(R__s, R__c, TASImage::IsA());
6207 return;
6208 }
6209 }
6210
6211 TNamed::Streamer(b);
6212 b >> image_type;
6213
6214 if (image_type != 0) { // read PNG compressed image
6215 b >> size;
6216 buffer = new char[size];
6217 b.ReadFastArray(buffer, size);
6218 SetImageBuffer(&buffer, TImage::kPng);
6219 delete [] buffer;
6220 } else { // read vector with palette
6221 TAttImage::Streamer(b);
6222 b >> w;
6223 b >> h;
6224 size = w*h;
6225 Double_t *vec = new Double_t[size];
6226 b.ReadFastArray(vec, size);
6227 SetImage(vec, w, h, &fPalette);
6228 delete [] vec;
6229 }
6230 b.CheckByteCount(R__s, R__c, TASImage::IsA());
6231 } else {
6232 if (!fImage) {
6233 return;
6234 }
6235 R__c = b.WriteVersion(TASImage::IsA(), kTRUE);
6236
6237 if (fName.IsNull()) {
6238 fName.Form("img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
6239 }
6240 TNamed::Streamer(b);
6241
6242 image_type = fImage->alt.vector ? 0 : 1;
6243 b << image_type;
6244
6245 if (image_type != 0) { // write PNG compressed image
6246 GetImageBuffer(&buffer, &size, TImage::kPng);
6247 b << size;
6248 b.WriteFastArray(buffer, size);
6249 delete buffer;
6250 } else { // write vector with palette
6251 TAttImage::Streamer(b);
6252 b << fImage->width;
6253 b << fImage->height;
6254 b.WriteFastArray(fImage->alt.vector, fImage->width*fImage->height);
6255 }
6256 b.SetByteCount(R__c, kTRUE);
6257 }
6258}
6259
6260////////////////////////////////////////////////////////////////////////////////
6261/// Browse image.
6262
6264{
6265 if (fImage->alt.vector) {
6266 Draw("n");
6267 } else {
6268 Draw("nxxx");
6269 }
6271}
6272
6273////////////////////////////////////////////////////////////////////////////////
6274/// Title is used to keep 32x32 xpm image's thumbnail.
6275
6276const char *TASImage::GetTitle() const
6277{
6278 if (!gDirectory || !gDirectory->IsWritable()) {
6279 return 0;
6280 }
6281
6282 TASImage *mutble = (TASImage *)this;
6283
6284 if (fTitle.IsNull()) {
6285 mutble->SetTitle(fName.Data());
6286 }
6287
6288 return fTitle.Data();
6289}
6290
6291////////////////////////////////////////////////////////////////////////////////
6292/// Set a title for an image.
6293
6294void TASImage::SetTitle(const char *title)
6295{
6296 if (fTitle.IsNull()) {
6298 }
6299
6300 if (fTitle.IsNull()) {
6301 return;
6302 }
6303
6304 int start = fTitle.Index("/*") + 3;
6305 int stop = fTitle.Index("*/") - 1;
6306
6307 if ((start > 0) && (stop - start > 0)) {
6308 fTitle.Replace(start, stop - start, title);
6309 }
6310}
6311
6312////////////////////////////////////////////////////////////////////////////////
6313/// Draw a cubic bezier line.
6314
6316 Int_t x3, Int_t y3, const char *col, UInt_t thick)
6317{
6318 Int_t sz = thick*thick;
6319 CARD32 *matrix;
6320 Bool_t use_cache = thick < kBrushCacheSize;
6321
6322 ARGB32 color = ARGB32_White;
6323 parse_argb_color(col, &color);
6324
6325 if (use_cache) {
6326 matrix = gBrushCache;
6327 } else {
6328 matrix = new CARD32[sz];
6329 }
6330
6331 for (int i = 0; i < sz; i++) {
6332 matrix[i] = (CARD32)color;
6333 };
6334
6335 ASDrawTool brush;
6336 brush.matrix = matrix;
6337 brush.width = thick;
6338 brush.height = thick;
6339 brush.center_y = brush.center_x = thick/2;
6340
6341 ASDrawContext *ctx = 0;
6342
6343 ctx = create_draw_context_argb32(fImage, &brush);
6344 asim_cube_bezier(ctx, x1, y1, x2, y2, x3, y3);
6345
6346 if (!use_cache) {
6347 delete [] matrix;
6348 }
6350}
6351
6352////////////////////////////////////////////////////////////////////////////////
6353/// Draw a straight ellipse.
6354/// If thick < 0 - draw filled ellipse.
6355
6357 const char *col, Int_t thick)
6358{
6359 thick = !thick ? 1 : thick;
6360 Int_t sz = thick*thick;
6361 CARD32 *matrix;
6362 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6363
6364 ARGB32 color = ARGB32_White;
6365 parse_argb_color(col, &color);
6366
6367 if (use_cache) {
6368 matrix = gBrushCache;
6369 } else {
6370 matrix = new CARD32[sz];
6371 }
6372
6373 for (int i = 0; i < sz; i++) {
6374 matrix[i] = (CARD32)color;
6375 };
6376
6377 ASDrawTool brush;
6378 brush.matrix = matrix;
6379 brush.width = thick > 0 ? thick : 1;
6380 brush.height = thick > 0 ? thick : 1;
6381 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6382
6383 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6384 asim_straight_ellips(ctx, x, y, rx, ry, thick < 0);
6385
6386 if (!use_cache) {
6387 delete [] matrix;
6388 }
6390}
6391
6392////////////////////////////////////////////////////////////////////////////////
6393/// Draw a circle.
6394/// If thick < 0 - draw filled circle
6395
6396void TASImage::DrawCircle(Int_t x, Int_t y, Int_t r, const char *col, Int_t thick)
6397{
6398 thick = !thick ? 1 : thick;
6399 Int_t sz = thick*thick;
6400 CARD32 *matrix;
6401 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6402
6403 ARGB32 color = ARGB32_White;
6404 parse_argb_color(col, &color);
6405
6406///matrix = new CARD32[sz];
6407 if (use_cache) {
6408 matrix = gBrushCache;
6409 } else {
6410 matrix = new CARD32[sz];
6411 }
6412
6413 for (int i = 0; i < sz; i++) {
6414 matrix[i] = (CARD32)color;
6415 }
6416
6417 ASDrawTool brush;
6418 brush.matrix = matrix;
6419 brush.height = brush.width = thick > 0 ? thick : 1;
6420 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6421
6422 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6423 asim_circle(ctx, x, y, r, thick < 0);
6424
6425///free (matrix);
6426 if (!use_cache) {
6427 delete [] matrix;
6428 }
6430}
6431
6432////////////////////////////////////////////////////////////////////////////////
6433/// Draw an ellipse.
6434/// If thick < 0 - draw filled ellips
6435
6437 const char *col, Int_t thick)
6438{
6439 thick = !thick ? 1 : thick;
6440 Int_t sz = thick*thick;
6441 CARD32 *matrix;
6442 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6443
6444 ARGB32 color = ARGB32_White;
6445 parse_argb_color(col, &color);
6446
6447 if (use_cache) {
6448 matrix = gBrushCache;
6449 } else {
6450 matrix = new CARD32[sz];
6451 }
6452
6453 for (int i = 0; i < sz; i++) {
6454 matrix[i] = (CARD32)color;
6455 };
6456
6457 ASDrawTool brush;
6458 brush.matrix = matrix;
6459 brush.width = thick > 0 ? thick : 1;
6460 brush.height = thick > 0 ? thick : 1;
6461 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6462
6463 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6464 asim_ellips(ctx, x, y, rx, ry, angle, thick < 0);
6465
6466 if (!use_cache) {
6467 delete [] matrix;
6468 }
6470}
6471
6472////////////////////////////////////////////////////////////////////////////////
6473/// Draw an ellipse.
6474/// If thick < 0 - draw filled ellipse.
6475
6477 const char *col, Int_t thick)
6478{
6479 thick = !thick ? 1 : thick;
6480 Int_t sz = thick*thick;
6481 CARD32 *matrix;
6482 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6483
6484 ARGB32 color = ARGB32_White;
6485 parse_argb_color(col, &color);
6486
6487 if (use_cache) {
6488 matrix = gBrushCache;
6489 } else {
6490 matrix = new CARD32[sz];
6491 }
6492
6493 for (int i = 0; i < sz; i++) {
6494 matrix[i] = (CARD32)color;
6495 };
6496
6497 ASDrawTool brush;
6498 brush.matrix = matrix;
6499 brush.width = thick > 0 ? thick : 1;
6500 brush.height = thick > 0 ? thick : 1;
6501 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6502
6503 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6504 asim_ellips2(ctx, x, y, rx, ry, angle, thick < 0);
6505
6506 if (!use_cache) {
6507 delete [] matrix;
6508 }
6510}
6511
6512////////////////////////////////////////////////////////////////////////////////
6513/// Flood fill.
6514
6515void TASImage::FloodFill(Int_t /*x*/, Int_t /*y*/, const char * /*col*/,
6516 const char * /*minc*/, const char * /*maxc*/)
6517{
6518}
6519
6520////////////////////////////////////////////////////////////////////////////////
6521/// Convert RGB image to Gray image and vice versa.
6522
6524{
6525 if (fIsGray == on) {
6526 return;
6527 }
6528
6529 if (!IsValid()) {
6530 Warning("Gray", "Image not initiated");
6531 return;
6532 }
6533
6534 if (!InitVisual()) {
6535 Warning("Gray", "Visual not initiated");
6536 return;
6537 }
6538
6539 if (!fGrayImage && !on) {
6540 return;
6541 }
6542 ASImage *sav = 0;
6543 delete fScaledImage;
6544 fScaledImage = 0;
6545
6546 if (fGrayImage) {
6547 sav = fImage;
6549 fGrayImage = sav;
6550 fIsGray = on;
6551 return;
6552 }
6553
6554 if (!on) return;
6555
6556 UInt_t l, r, g, b, idx;
6557 int y = 0;
6558 UInt_t i, j;
6559
6560 if (fImage->alt.argb32) {
6561 fGrayImage = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
6562 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
6563
6564 for (i = 0; i < fImage->height; i++) {
6565 for (j = 0; j < fImage->width; j++) {
6566 idx = Idx(y + j);
6567
6568 r = ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
6569 g = ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
6570 b = (fImage->alt.argb32[idx] & 0x0000ff);
6571 l = (57*r + 181*g + 18*b)/256;
6572 fGrayImage->alt.argb32[idx] = (l << 16) + (l << 8) + l;
6573 }
6574 y += fImage->width;
6575 }
6576 } else {
6577 fGrayImage = create_asimage(fImage->width, fImage->height, 0);
6578
6579 ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
6580 0, 0, fImage->width, fImage->height, 0);
6581
6582 if (!imdec) {
6583 return;
6584 }
6585#ifdef HAVE_MMX
6586 mmx_init();
6587#endif
6588 ASImageOutput *imout = start_image_output(fgVisual, fGrayImage, ASA_ASImage,
6590 if (!imout) {
6591 Warning("ToGray", "Failed to start image output");
6592 delete fScaledImage;
6593 fScaledImage = 0;
6594 delete [] imdec;
6595 return;
6596 }
6597
6598 CARD32 *aa = imdec->buffer.alpha;
6599 CARD32 *rr = imdec->buffer.red;
6600 CARD32 *gg = imdec->buffer.green;
6601 CARD32 *bb = imdec->buffer.blue;
6602
6603 ASScanline result;
6604 prepare_scanline(fImage->width, 0, &result, fgVisual->BGR_mode);
6605
6606 for (i = 0; i < fImage->height; i++) {
6607 imdec->decode_image_scanline(imdec);
6608 result.flags = imdec->buffer.flags;
6609 result.back_color = imdec->buffer.back_color;
6610
6611 for (j = 0; j < fImage->width; j++) {
6612 l = (57*rr[j] + 181*gg[j]+ 18*bb[j])/256;
6613 result.alpha[j] = aa[j];
6614 result.red[j] = l;
6615 result.green[j] = l;
6616 result.blue[j] = l;
6617 }
6618 imout->output_image_scanline(imout, &result, 1);
6619 }
6620
6621 stop_image_decoding(&imdec);
6622 stop_image_output(&imout);
6623#ifdef HAVE_MMX
6624 mmx_off();
6625#endif
6626 }
6627
6628 sav = fImage;
6630 fGrayImage = sav;
6631 fIsGray = kTRUE;
6632}
6633
6634////////////////////////////////////////////////////////////////////////////////
6635/// Create an image (screenshot) from specified window.
6636
6638{
6639 Int_t xy;
6640
6641 x = x < 0 ? 0 : x;
6642 y = y < 0 ? 0 : y;
6643
6644 // X11 Synchronization
6645 gVirtualX->Update(1);
6646 if (!gThreadXAR) {
6647 gSystem->Sleep(10);
6649 gSystem->Sleep(10);
6651 }
6652
6653 if (!w || !h) {
6654 gVirtualX->GetWindowSize(wid, xy, xy, w, h);
6655 }
6656
6657 if ((x >= (Int_t)w) || (y >= (Int_t)h)) {
6658 return;
6659 }
6660
6661 if (!InitVisual()) {
6662 Warning("FromWindow", "Visual not initiated");
6663 return;
6664 }
6665
6666 DestroyImage();
6667 delete fScaledImage;
6668 fScaledImage = 0;
6669
6670 static int x11 = -1;
6671 if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
6672
6673 if (x11) { //use built-in optimized version
6674 fImage = pixmap2asimage(fgVisual, wid, x, y, w, h, kAllPlanes, 0, 0);
6675 } else {
6676 unsigned char *bits = gVirtualX->GetColorBits(wid, 0, 0, w, h);
6677
6678 if (!bits) { // error
6679 return;
6680 }
6681 fImage = bitmap2asimage(bits, w, h, 0, 0);
6682 delete [] bits;
6683 }
6684}
6685
6686////////////////////////////////////////////////////////////////////////////////
6687/// Creates an image (screenshot) from a RGBA buffer.
6688
6690{
6691 DestroyImage();
6692 delete fScaledImage;
6693 fScaledImage = 0;
6694
6695 UChar_t* xx = new UChar_t[4*w];
6696 for (UInt_t i = 0; i < h/2; ++i) {
6697 memcpy(xx, buf + 4*w*i, 4*w);
6698 memcpy(buf + 4*w*i, buf + 4*w*(h-i-1), 4*w);
6699 memcpy(buf + 4*w*(h-i-1), xx, 4*w);
6700 }
6701 delete [] xx;
6702
6703 fImage = bitmap2asimage(buf, w, h, 0, 0);
6704}
6705
6706////////////////////////////////////////////////////////////////////////////////
6707/// Switch on/off the image palette.
6708/// That also invokes calling vectorization of image.
6709
6711{
6712 if (!fImage) {
6713 return;
6714 }
6715
6716 if (!fImage->alt.vector && on) {
6717 Vectorize();
6718 }
6719 fPaletteEnabled = on;
6720
6721 if (on) {
6722 Double_t left = gPad->GetLeftMargin();
6723 Double_t right = gPad->GetRightMargin();
6724 Double_t top = gPad->GetTopMargin();
6725 Double_t bottom = gPad->GetBottomMargin();
6726
6727 gPad->Range(-left / (1.0 - left - right),
6728 -bottom / (1.0 - top - bottom),
6729 1 + right / (1.0 - left - right),
6730 1 + top / ( 1.0 - top - bottom));
6731 gPad->RangeAxis(0, 0, 1, 1);
6732 }
6733
6734}
6735
6736////////////////////////////////////////////////////////////////////////////////
6737/// Save a primitive as a C++ statement(s) on output stream "out".
6738
6739void TASImage::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
6740{
6741 char *buf = 0;
6742 int sz;
6743
6744 UInt_t w = GetWidth();
6745 UInt_t h = GetHeight();
6746
6747 if (w > 500) { // workaround CINT limitations
6748 w = 500;
6749 Double_t scale = 500./GetWidth();
6750 h = TMath::Nint(GetHeight()*scale);
6751 Scale(w, h);
6752 }
6753
6754 GetImageBuffer(&buf, &sz, TImage::kXpm);
6755
6756 TString name = GetName();
6757 name.ReplaceAll(".", "_");
6758 TString str = buf;
6759 static int ii = 0;
6760 ii++;
6761
6762 str.ReplaceAll("static", "const");
6763 TString xpm = "xpm_";
6764 xpm += name;
6765 xpm += ii;
6766 str.ReplaceAll("asxpm", xpm.Data());
6767 out << std::endl << str << std::endl << std::endl;
6768
6769 out << " TImage *";
6770 out << xpm << "_img = TImage::Create();" << std::endl;
6771 out << " " << xpm << "_img->SetImageBuffer( (char **)" << xpm << ", TImage::kXpm);" << std::endl;
6772 out << " " << xpm << "_img->Draw();" << std::endl;
6773}
6774
6775////////////////////////////////////////////////////////////////////////////////
6776/// Set an image printing resolution in Dots Per Inch units.
6777///
6778/// \param[in] name - the name of jpeg file.
6779/// \param[in] set - dpi resolution.
6780///
6781/// Returns kFALSE in case of error.
6782
6784{
6785 static char buf[32];
6786 FILE *fp = fopen(name, "rb+");
6787
6788 if (!fp) {
6789 printf("file %s : failed to open\n", name);
6790 return kFALSE;
6791 }
6792
6793 if (!fread(buf, 1, 20, fp)) {
6794 fclose(fp);
6795 return kFALSE;
6796 }
6797
6798 char dpi1 = (set & 0xffff) >> 8;
6799 char dpi2 = set & 0xff;
6800
6801 int i = 0;
6802
6803 int dpi = 0; // start of dpi data
6804 for (i = 0; i < 20; i++) {
6805 if ((buf[i] == 0x4a) && (buf[i+1] == 0x46) && (buf[i+2] == 0x49) &&
6806 (buf[i+3] == 0x46) && (buf[i+4] == 0x00) ) {
6807 dpi = i + 7;
6808 break;
6809 }
6810 }
6811
6812 if (i == 20 || dpi+4 >= 20) { // jpeg maker was not found
6813 fclose(fp);
6814 printf("file %s : wrong JPEG format\n", name);
6815 return kFALSE;
6816 }
6817
6818 buf[dpi] = 1; // format specified in dots per inch
6819
6820 // set x density in dpi units
6821 buf[dpi + 1] = dpi1;
6822 buf[dpi + 2] = dpi2;
6823
6824 // set y density in dpi units
6825 buf[dpi + 3] = dpi1;
6826 buf[dpi + 4] = dpi2;
6827
6828 rewind(fp);
6829 fwrite(buf, 1, 20, fp);
6830 fclose(fp);
6831
6832 return kTRUE;
6833}
6834
6835////////////////////////////////////////////////////////////////////////////////
6836/// Return a valid index in fImage tables to avoid seg-fault by accessing out of
6837/// indices out of array's ranges.
6838
6840{
6841 // The size of arrays like fImage->alt.argb32 is fImage->width*fImage->height
6842 return TMath::Min(idx,(Int_t)(fImage->width*fImage->height));
6843}
6844
@ kButton1Motion
Definition: Buttons.h:20
@ kButton1Up
Definition: Buttons.h:19
@ kButton1Down
Definition: Buttons.h:17
void Class()
Definition: Class.C:29
const Mask_t kGCClipXOrigin
Definition: GuiTypes.h:302
EGraphicsFunction
Definition: GuiTypes.h:66
@ kGXorReverse
Definition: GuiTypes.h:78
@ kGXnand
Definition: GuiTypes.h:81
@ kGXandReverse
Definition: GuiTypes.h:69
@ kGXor
Definition: GuiTypes.h:74
@ kGXcopy
Definition: GuiTypes.h:70
@ kGXorInverted
Definition: GuiTypes.h:80
@ kGXandInverted
Definition: GuiTypes.h:71
@ kGXequiv
Definition: GuiTypes.h:76
@ kGXset
Definition: GuiTypes.h:82
@ kGXnor
Definition: GuiTypes.h:75
@ kGXnoop
Definition: GuiTypes.h:72
@ kGXinvert
Definition: GuiTypes.h:77
@ kGXxor
Definition: GuiTypes.h:73
@ kGXand
Definition: GuiTypes.h:68
@ kGXclear
Definition: GuiTypes.h:67
@ kGXcopyInverted
Definition: GuiTypes.h:79
Handle_t Pixmap_t
Definition: GuiTypes.h:29
Handle_t Drawable_t
Definition: GuiTypes.h:30
const Handle_t kNone
Definition: GuiTypes.h:87
Handle_t GContext_t
Definition: GuiTypes.h:37
const Mask_t kGCClipYOrigin
Definition: GuiTypes.h:303
const Mask_t kGCClipMask
Definition: GuiTypes.h:304
Handle_t Window_t
Definition: GuiTypes.h:28
ROOT::R::TRInterface & r
Definition: Object.C:4
#define d(i)
Definition: RSha256.hxx:102
#define b(i)
Definition: RSha256.hxx:100
#define c(i)
Definition: RSha256.hxx:101
#define g(i)
Definition: RSha256.hxx:105
#define h(i)
Definition: RSha256.hxx:106
static const double x2[5]
static const double x1[5]
static const double x3[11]
unsigned short UShort_t
Definition: RtypesCore.h:36
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
unsigned char UChar_t
Definition: RtypesCore.h:34
int Ssiz_t
Definition: RtypesCore.h:63
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
double Double_t
Definition: RtypesCore.h:55
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define BIT(n)
Definition: Rtypes.h:83
#define ClassImp(name)
Definition: Rtypes.h:365
#define SETBIT(n, i)
Definition: Rtypes.h:84
#define CLRBIT(n, i)
Definition: Rtypes.h:85
static ARGB32 GetShadow(ARGB32 background)
Calculate shadow color.
Definition: TASImage.cxx:3212
static const UInt_t kBrushCacheSize
Definition: TASImage.cxx:5659
static CARD32 gBrushCache[kBrushCacheSize *kBrushCacheSize]
Definition: TASImage.cxx:5660
const Float_t kScale
Definition: TASImage.cxx:128
static unsigned long kAllPlanes
Definition: TASImage.cxx:121
static ARGB32 GetAverage(ARGB32 foreground, ARGB32 background)
Get average.
Definition: TASImage.cxx:3221
static char * gIconPaths[7]
Definition: TASImage.cxx:125
static int GetPolyYBounds(TPoint *pts, int n, int *by, int *ty)
Get poly bounds along Y.
Definition: TASImage.cxx:5175
static CARD8 MakeComponentHilite(int cmp)
Make component hilite.
Definition: TASImage.cxx:3186
static ARGB32 GetHilite(ARGB32 background)
Calculate highlite color.
Definition: TASImage.cxx:3200
static const UInt_t NUMPTSTOBUFFER
Definition: TASImage.cxx:5426
static ASFontManager * gFontManager
Definition: TASImage.cxx:120
static void init_icon_paths()
Set icons paths.
Definition: TASImage.cxx:361
#define _MEMSET_(dst, lng, val)
Definition: TASImage.cxx:3718
#define FillSpansInternal(npt, ppt, widths, color)
Definition: TASImage.cxx:3723
static ASDrawContext * create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
Create draw context.
Definition: TASImage.cxx:5634
#define _alphaBlend(bot, top)
Definition: TASImage.cxx:154
static void destroy_asdraw_context32(ASDrawContext *ctx)
Destroy asdraw context32.
Definition: TASImage.cxx:5651
struct _EdgeTableEntry EdgeTableEntry
struct _ScanLineListBlock ScanLineListBlock
struct _ScanLineList ScanLineList
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
Definition: TASPolyUtils.c:287
static int InsertionSort(EdgeTableEntry *AET)
Definition: TASPolyUtils.c:485
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2)
Definition: TASPolyUtils.c:93
static void loadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
Definition: TASPolyUtils.c:455
static void FreeStorage(ScanLineListBlock *pSLLBlock)
Definition: TASPolyUtils.c:524
static void CreateETandAET(int count, TPoint *pts, EdgeTable *ET, EdgeTableEntry *AET, EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock)
Definition: TASPolyUtils.c:365
#define BRESINCRPGON(d, minval, m, m1, incr1, incr2)
Definition: TASPolyUtils.c:115
#define gDirectory
Definition: TDirectory.h:223
include TDocParser_001 C image html pict1_TDocParser_001 png width
Definition: TDocParser.cxx:121
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
char name[80]
Definition: TGX11.cxx:109
int type
Definition: TGX11.cxx:120
XPoint xy[kMAXMK]
Definition: TGX11.cxx:122
XID Colormap
Definition: TGX11.h:38
float * q
Definition: THbookFile.cxx:87
float ymin
Definition: THbookFile.cxx:93
float type_of_call hi(const int &, const int &)
float ymax
Definition: THbookFile.cxx:93
#define gROOT
Definition: TROOT.h:415
R__EXTERN TRandom * gRandom
Definition: TRandom.h:62
char * Form(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:407
R__EXTERN const char * gProgName
Definition: TSystem.h:244
@ kReadPermission
Definition: TSystem.h:48
R__EXTERN TSystem * gSystem
Definition: TSystem.h:560
R__EXTERN TVirtualPS * gVirtualPS
Definition: TVirtualPS.h:81
#define gPad
Definition: TVirtualPad.h:286
R__EXTERN Int_t(* gThreadXAR)(const char *xact, Int_t nb, void **ar, Int_t *iret)
Definition: TVirtualPad.h:288
#define gVirtualX
Definition: TVirtualX.h:345
@ kCross
Definition: TVirtualX.h:46
Color * colors
Definition: X3DBuffer.c:21
#define free
Definition: civetweb.c:1539
#define snprintf
Definition: civetweb.c:1540
#define malloc
Definition: civetweb.c:1536
Image class.
Definition: TASImage.h:31
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:5349
Bool_t IsEditable() const
Definition: TASImage.h:95
Bool_t SetJpegDpi(const char *name, UInt_t dpi=72)
Set an image printing resolution in Dots Per Inch units.
Definition: TASImage.cxx:6783
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:3920
Pixmap_t GetPixmap()
Returns image pixmap.
Definition: TASImage.cxx:2268
Int_t fPaintMode
! 1 - fast mode, 0 - low memory slow mode
Definition: TASImage.h:67
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:5013
Bool_t SetImageBuffer(char **buffer, EImageFileTypes type=TImage::kPng)
Create image from compressed buffer.
Definition: TASImage.cxx:6040
Double_t fMinValue
! min value in image
Definition: TASImage.h:60
UInt_t GetScaledWidth() const
Return width of the displayed image not of the original image.
Definition: TASImage.cxx:2166
void Merge(const TImage *im, const char *op="alphablend", Int_t x=0, Int_t y=0)
Merge two images.
Definition: TASImage.cxx:2719
void DrawHLine(UInt_t y, UInt_t x1, UInt_t x2, UInt_t col, UInt_t thick)
Draw an horizontal line.
Definition: TASImage.cxx:3874
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:4810
static Bool_t fgInit
global flag to init afterimage only once
Definition: TASImage.h:73
const char * TypeFromMagicNumber(const char *file)
Guess the file type from the first byte of file.
Definition: TASImage.cxx:395
Double_t fMaxValue
! max value in image
Definition: TASImage.h:59
void Append(const TImage *im, const char *option="+", const char *color="#00000000")
Append image.
Definition: TASImage.cxx:3491
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:6396
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:5127
void MapQuality(EImageQuality &quality, UInt_t &asquality, Bool_t toas=kTRUE)
Map quality to/from AfterImage quality.
Definition: TASImage.cxx:947
void Crop(Int_t x=0, Int_t y=0, UInt_t width=0, UInt_t height=0)
Crop an image.
Definition: TASImage.cxx:3414
void CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths)
Crop spans.
Definition: TASImage.cxx:4925
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
UInt_t * GetScanline(UInt_t y)
Return a pointer to scan-line.
Definition: TASImage.cxx:3665
UInt_t fZoomWidth
! width of zoomed image in image pixels
Definition: TASImage.h:63
Bool_t fEditable
! kTRUE image can be resized, moved by resizing/moving gPad
Definition: TASImage.h:66
Int_t fZoomUpdate
! kZoom - new zooming required, kZoomOps - other ops in action, kNoZoom - no zooming or ops
Definition: TASImage.h:65
void EndPaint()
EndPaint does internal RLE compression of image data.
Definition: TASImage.cxx:3564
void DrawVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t col, UInt_t thick)
Draw a vertical line.
Definition: TASImage.cxx:3839
UInt_t GetWidth() const
Return width of original image not of the displayed image.
Definition: TASImage.cxx:2148
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,...
Definition: TASImage.cxx:3009
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:6356
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
ASImage * fImage
! pointer to image structure of original image
Definition: TASImage.h:57
UInt_t GetHeight() const
Return height of original image not of the displayed image.
Definition: TASImage.cxx:2157
UInt_t fZoomHeight
! hight of zoomed image in image pixels
Definition: TASImage.h:64
static THashTable * fgPlugList
! hash table containing loaded plugins
Definition: TASImage.h:70
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's r...
Definition: TASImage.cxx:6839
void DrawSegments(UInt_t nseg, Segment_t *seg, const char *col="#000000", UInt_t thick=1)
Draw segments.
Definition: TASImage.cxx:4787
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:4667
void SetDefaults()
Set default parameters.
Definition: TASImage.cxx:193
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:5665
void CropPolygon(UInt_t npt, TPoint *ppt)
Crop a convex polygon.
Definition: TASImage.cxx:5405
void StartPaletteEditor()
Start palette editor.
Definition: TASImage.cxx:2249
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:3249
void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TASImage.cxx:6739
UInt_t * GetRgbaArray()
Return a pointer to an array[width x height] of RGBA32 values.
Definition: TASImage.cxx:3619
void PolyPoint(UInt_t npt, TPoint *ppt, const char *col="#000000", TImage::ECoordMode mode=kCoordModeOrigin)
Draw a poly point.
Definition: TASImage.cxx:4727
Pixmap_t GetMask()
Returns image mask pixmap (alpha channel).
Definition: TASImage.cxx:2300
static const ASVisual * GetVisual()
Return visual.
Definition: TASImage.cxx:5167
const char * GetTitle() const
Title is used to keep 32x32 xpm image's thumbnail.
Definition: TASImage.cxx:6276
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
void SetPaletteEnabled(Bool_t on=kTRUE)
Switch on/off the image palette.
Definition: TASImage.cxx:6710
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 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
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:3735
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:4623
void DrawGlyph(void *bitmap, UInt_t color, Int_t x, Int_t y)
Draw glyph bitmap.
Definition: TASImage.cxx:5712
TASImage * fScaledImage
! temporary scaled and zoomed image produced from original image
Definition: TASImage.h:58
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:3813
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:3909
UInt_t fZoomOffX
! X - offset for zooming in image pixels
Definition: TASImage.h:61
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:6637
@ kZoom
Definition: TASImage.h:34
@ kNoZoom
Definition: TASImage.h:34
@ kZoomOps
Definition: TASImage.h:34
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:5431
void GetImageBuffer(char **buffer, int *size, EImageFileTypes type=TImage::kPng)
Return in-memory buffer compressed according image type.
Definition: TASImage.cxx:5988
Int_t DistancetoPrimitive(Int_t px, Int_t py)
Is the mouse in the image ?
Definition: TASImage.cxx:1678
EImageFileTypes GetFileType(const char *ext)
Return file type depending on specified extension.
Definition: TASImage.cxx:818
void Browse(TBrowser *)
Browse image.
Definition: TASImage.cxx:6263
void Gray(Bool_t on=kTRUE)
Convert RGB image to Gray image and vice versa.
Definition: TASImage.cxx:6523
void Tile(UInt_t width, UInt_t height)
Tile the original image.
Definition: TASImage.cxx:1981
void Draw(Option_t *option="")
Draw image.
Definition: TASImage.cxx:1167
void WriteImage(const char *file, EImageFileTypes type=TImage::kUnknown)
Write image to specified file.
Definition: TASImage.cxx:647
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
static UInt_t AlphaBlend(UInt_t bot, UInt_t top)
Return alpha-blended value computed from bottom and top pixel values.
Definition: TASImage.cxx:5156
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:5953
void ReadImage(const char *file, EImageFileTypes type=TImage::kUnknown)
Read specified image file.
Definition: TASImage.cxx:478
void BeginPaint(Bool_t fast=kTRUE)
BeginPaint initializes internal array[width x height] of ARGB32 pixel values.
Definition: TASImage.cxx:3532
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:4465
void DestroyImage()
Destroy image.
Definition: TASImage.cxx:175
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:6436
static Bool_t InitVisual()
Static function to initialize the ASVisual.
Definition: TASImage.cxx:2195
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:6515
UInt_t fZoomOffY
! Y - offset for zooming im image pixels
Definition: TASImage.h:62
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:2833
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:2946
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
void Scale(UInt_t width, UInt_t height)
Scale the original image.
Definition: TASImage.cxx:1911
void Mirror(Bool_t vert=kTRUE)
Mirror image in place.
Definition: TASImage.cxx:2118
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:6476
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
ASImage * fGrayImage
! gray image
Definition: TASImage.h:68
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:4224
UInt_t * GetArgbArray()
Return a pointer to internal array[width x height] of ARGB32 values This array is directly accessible...
Definition: TASImage.cxx:3591
void MapFileTypes(EImageFileTypes &type, UInt_t &astype, Bool_t toas=kTRUE)
Map file type to/from AfterImage types.
Definition: TASImage.cxx:862
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:4170
void PutPixel(Int_t x, Int_t y, const char *col="#000000")
Draw a point at the specified position.
Definition: TASImage.cxx:4692
void UnZoom()
Un-zoom the image to original size.
Definition: TASImage.cxx:2043
void SetPalette(const TImagePalette *palette)
Set a new palette to an image.
Definition: TASImage.cxx:1855
TASImage()
Default image constructor.
Definition: TASImage.cxx:220
TASImage & operator=(const TASImage &img)
Image assignment operator.
Definition: TASImage.cxx:317
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:6315
Double_t * GetVecArray()
Return a pointer to internal array[width x height] of double values [0,1].
Definition: TASImage.cxx:2478
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:4281
void Paint(Option_t *option="")
Paint image.
Definition: TASImage.cxx:1361
Bool_t IsValid() const
Definition: TASImage.h:184
void Flip(Int_t flip=180)
Flip image in place.
Definition: TASImage.cxx:2071
void FromGLBuffer(UChar_t *buf, UInt_t w, UInt_t h)
Creates an image (screenshot) from a RGBA buffer.
Definition: TASImage.cxx:6689
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:1071
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:5204
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:4081
void ExecuteEvent(Int_t event, Int_t px, Int_t py)
Execute mouse events.
Definition: TASImage.cxx:1701
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:3365
static ASVisual * fgVisual
pointer to visual structure
Definition: TASImage.h:72
virtual ~TASImage()
Image destructor, clean up image and visual.
Definition: TASImage.cxx:351
void GetZoomPosition(UInt_t &x, UInt_t &y, UInt_t &w, UInt_t &h) const
Return the zoom parameters.
Definition: TASImage.cxx:2184
TObject * Clone(const char *newname) const
Clone image.
Definition: TASImage.cxx:2787
void Blur(Double_t hr=3, Double_t vr=3)
Perform Gaussian blur of the image (useful for drop shadows).
Definition: TASImage.cxx:2758
UInt_t GetScaledHeight() const
Return height of the displayed image not of the original image.
Definition: TASImage.cxx:2175
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:984
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:4121
void SetTitle(const char *title="")
Set a title for an image.
Definition: TASImage.cxx:6294
Bool_t fIsGray
! kTRUE if image is gray
Definition: TASImage.h:69
void CreateThumbnail()
Create image thumbnail.
Definition: TASImage.cxx:6087
Array of doubles (64 bits per element).
Definition: TArrayD.h:27
void AddAt(Double_t c, Int_t i)
Set the double c value at position i in the array.
Definition: TArrayD.cxx:94
const Double_t * GetArray() const
Definition: TArrayD.h:43
Array of longs (32 or 64 bits per element).
Definition: TArrayL.h:27
void AddAt(Long_t c, Int_t i)
Add long c at position i. Check for out of bounds.
Definition: TArrayL.cxx:93
Int_t GetSize() const
Definition: TArray.h:47
virtual void SetFillColor(Color_t fcolor)
Set the fill area color.
Definition: TAttFill.h:37
virtual void SetFillStyle(Style_t fstyle)
Set the fill area style.
Definition: TAttFill.h:39
virtual void SetPalette(const TImagePalette *palette)
Set a new palette for the image.
Definition: TAttImage.cxx:650
Bool_t fConstRatio
keep aspect ratio of image on the screen
Definition: TAttImage.h:74
EImageQuality GetImageQuality() const
Definition: TAttImage.h:87
Bool_t GetConstRatio() const
Definition: TAttImage.h:85
virtual const TImagePalette & GetPalette() const
Definition: TAttImage.h:88
@ kImgPoor
Definition: TAttImage.h:65
@ kImgDefault
Definition: TAttImage.h:64
@ kImgFast
Definition: TAttImage.h:66
@ kImgGood
Definition: TAttImage.h:67
@ kImgBest
Definition: TAttImage.h:68
TImagePalette fPalette
color palette for value -> color conversion
Definition: TAttImage.h:75
UInt_t GetImageCompression() const
Definition: TAttImage.h:86
Bool_t fPaletteEnabled
! kTRUE - palette is drawn on the image
Definition: TAttImage.h:77
virtual void StartPaletteEditor()
Opens a GUI to edit the color palette.
Definition: TAttImage.cxx:780
virtual void SetLineColor(Color_t lcolor)
Set the line color.
Definition: TAttLine.h:40
virtual Float_t GetTextSize() const
Return the text size.
Definition: TAttText.h:36
virtual Short_t GetTextAlign() const
Return the text alignment.
Definition: TAttText.h:32
virtual Font_t GetTextFont() const
Return the text font.
Definition: TAttText.h:35
virtual Color_t GetTextColor() const
Return the text color.
Definition: TAttText.h:34
virtual Float_t GetTextAngle() const
Return the text angle.
Definition: TAttText.h:33
Create a Box.
Definition: TBox.h:24
virtual void SetY2(Double_t y2)
Definition: TBox.h:66
virtual void SetX1(Double_t x1)
Definition: TBox.h:63
virtual void Draw(Option_t *option="")
Draw this box with its current attributes.
Definition: TBox.cxx:194
virtual void SetX2(Double_t x2)
Definition: TBox.h:64
virtual void SetY1(Double_t y1)
Definition: TBox.h:65
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
Buffer base class used for serializing objects.
Definition: TBuffer.h:42
The color creation and management class.
Definition: TColor.h:19
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:2041
const char * AsHexString() const
Return color as hexadecimal string.
Definition: TColor.cxx:1209
Int_t GetNumber() const
Definition: TColor.h:55
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
Define a Frame.
Definition: TFrame.h:19
virtual void Draw(Option_t *option="")
Draw this frame with its current attributes.
Definition: TFrame.cxx:69
The axis painter class.
Definition: TGaxis.h:24
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:956
THashTable implements a hash table to store TObject's.
Definition: THashTable.h:35
void Add(TObject *obj)
Add object to the hash table.
Definition: THashTable.cxx:92
TObject * FindObject(const char *name) const
Find object using its name.
Definition: THashTable.cxx:238
A class to define a conversion from pixel values to pixel color.
Definition: TAttImage.h:33
UShort_t * fColorRed
[fNumPoints] red color at each anchor point
Definition: TAttImage.h:38
Double_t * fPoints
[fNumPoints] value of each anchor point [0..1]
Definition: TAttImage.h:37
virtual Int_t FindColor(UShort_t r, UShort_t g, UShort_t b)
Returns an index of the closest color.
Definition: TAttImage.cxx:485
UShort_t * fColorGreen
[fNumPoints] green color at each anchor point
Definition: TAttImage.h:39
UShort_t * fColorBlue
[fNumPoints] blue color at each anchor point
Definition: TAttImage.h:40
UInt_t fNumPoints
number of anchor points
Definition: TAttImage.h:36
UShort_t * fColorAlpha
[fNumPoints] alpha at each anchor point
Definition: TAttImage.h:41
virtual unsigned char * ReadFile(const char *filename, UInt_t &w, UInt_t &h)=0
An abstract interface to image processing library.
Definition: TImage.h:29
EColorChan
Definition: TImage.h:90
ECoordMode
Definition: TImage.h:85
@ kCoordModePrevious
Definition: TImage.h:87
@ kCoordModeOrigin
Definition: TImage.h:86
EImageFileTypes
Definition: TImage.h:36
@ kBmp
Definition: TImage.h:45
@ kPng
Definition: TImage.h:40
@ kJpeg
Definition: TImage.h:41
@ kXcf
Definition: TImage.h:42
@ kPnm
Definition: TImage.h:44
@ kIco
Definition: TImage.h:46
@ kXml
Definition: TImage.h:53
@ kXpm
Definition: TImage.h:37
@ kPpm
Definition: TImage.h:43
@ kTga
Definition: TImage.h:52
@ kAnimGif
Definition: TImage.h:55
@ kZCompressedXpm
Definition: TImage.h:38
@ kUnknown
Definition: TImage.h:54
@ kXbm
Definition: TImage.h:50
@ kCur
Definition: TImage.h:47
@ kTiff
Definition: TImage.h:49
@ kGZCompressedXpm
Definition: TImage.h:39
@ kGif
Definition: TImage.h:48
virtual UInt_t * GetArgbArray()
Definition: TImage.h:237
virtual UInt_t GetWidth() const
Definition: TImage.h:228
static TImage * Create()
Create an image.
Definition: TImage.cxx:36
TImage & operator=(const TImage &img)
Definition: TImage.h:104
virtual void Merge(const TImage *, const char *="alphablend", Int_t=0, Int_t=0)
Definition: TImage.h:172
EText3DType
Definition: TImage.h:58
virtual void BeginPaint(Bool_t=kTRUE)
Definition: TImage.h:182
virtual UInt_t GetHeight() const
Definition: TImage.h:229
TString fTitle
Definition: TNamed.h:33
TString fName
Definition: TNamed.h:32
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual void Delete(Option_t *option="")
Delete this object.
Definition: TObject.cxx:169
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition: TObject.cxx:195
Long_t ExecPlugin(int nargs, const T &... params)
Int_t LoadPlugin()
Load the plugin library for this handler.
Definition: TPoint.h:31
SCoord_t fY
Definition: TPoint.h:36
SCoord_t fX
Definition: TPoint.h:35
static const TString & GetTTFFontDir()
Get the fonts directory in the installation. Static utility function.
Definition: TROOT.cxx:3124
static const TString & GetIconPath()
Get the icon path in the installation. Static utility function.
Definition: TROOT.cxx:3103
virtual UInt_t Integer(UInt_t imax)
Returns a random integer uniformly distributed on the interval [ 0, imax-1 ].
Definition: TRandom.cxx:349
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1125
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1921
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2177
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:677
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:499
const char * Data() const
Definition: TString.h:364
Bool_t IsDigit() const
Returns true if all characters in string are digits (0-9) or white spaces, i.e.
Definition: TString.cxx:1763
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:892
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2197
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
Bool_t IsNull() const
Definition: TString.h:402
Int_t CountChar(Int_t c) const
Return number of times character c occurs in the string.
Definition: TString.cxx:476
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
Float_t GetScreenFactor() const
Definition: TStyle.h:244
Float_t GetImageScaling() const
Definition: TStyle.h:227
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1265
virtual const char * HomeDirectory(const char *userName=0)
Return the user's home directory.
Definition: TSystem.cxx:895
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1072
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:942
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:447
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1537
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:426
TTF helper class containing glyphs description.
Definition: TTF.h:65
FT_Glyph fImage
glyph image
Definition: TTF.h:69
static Bool_t IsInitialized()
Definition: TTF.cxx:608
static void PrepareString(const char *string)
Put the characters in "string" in the "glyphs" array.
Definition: TTF.cxx:250
static void Init()
Initialise the TrueType fonts interface.
Definition: TTF.cxx:65
static void LayoutGlyphs()
Compute the glyphs positions, fgAscent and fgWidth (needed for alignment).
Definition: TTF.cxx:181
static void SetRotationMatrix(Float_t angle)
Set the rotation matrix used to rotate the font outlines.
Definition: TTF.cxx:342
static void SetTextFont(Font_t fontnumber)
Set specified font.
Definition: TTF.cxx:491
static Int_t GetAscent()
Definition: TTF.cxx:622
static TTGlyph * GetGlyphs()
Definition: TTF.cxx:650
static Int_t GetNumGlyphs()
Definition: TTF.cxx:629
static Int_t GetWidth()
Definition: TTF.cxx:615
static const FT_BBox & GetBox()
Definition: TTF.cxx:643
static void SetTextSize(Float_t textsize)
Set current text size.
Definition: TTF.cxx:562
static FT_Matrix * GetRotMatrix()
Definition: TTF.cxx:636
Base class for several text objects.
Definition: TText.h:23
const void * GetWcsTitle(void) const
Returns the text as UNICODE.
Definition: TText.cxx:129
Int_t GetNoElements() const
Definition: TVectorT.h:76
Element * GetMatrixArray()
Definition: TVectorT.h:78
TVirtualPS is an abstract interface to Postscript, PDF, SVG.
Definition: TVirtualPS.h:30
virtual void CellArrayEnd()=0
virtual void CellArrayFill(Int_t r, Int_t g, Int_t b)=0
virtual void CellArrayBegin(Int_t W, Int_t H, Double_t x1, Double_t x2, Double_t y1, Double_t y2)=0
virtual void * GetStream() const
Definition: TVirtualPS.h:71
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.
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition: TVirtualPad.h:50
virtual void Paint(Option_t *option="")=0
This method must be overridden if a class wants to paint itself.
virtual Int_t GetPixmapID() const =0
virtual Int_t VtoPixel(Double_t v) const =0
virtual const char * GetName() const =0
Returns name of object.
virtual Int_t UtoPixel(Double_t u) const =0
virtual Int_t GetCanvasID() const =0
virtual TCanvas * GetCanvas() const =0
virtual void SetBorderMode(Short_t bordermode)
Definition: TWbox.h:51
TPaveText * pt
TText * text
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16
#define H(x, y, z)
TString as(SEXP s)
Definition: RExports.h:71
RooArgSet S(const RooAbsArg &v1)
static constexpr double s
Int_t Nint(T x)
Round to nearest integer. Rounds half integers to the nearest even integer.
Definition: TMath.h:703
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
Double_t ATan2(Double_t y, Double_t x)
Definition: TMath.h:669
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
Double_t Cos(Double_t)
Definition: TMath.h:631
Double_t Sin(Double_t)
Definition: TMath.h:627
Short_t Abs(Short_t d)
Definition: TMathBase.h:120
Definition: file.py:1
fill
Definition: fit1_py.py:6
const char * cnt
Definition: TXMLSetup.cxx:74
Pixmap_t fClipMask
Definition: GuiTypes.h:246
Int_t fClipYOrigin
Definition: GuiTypes.h:245
Int_t fClipXOrigin
Definition: GuiTypes.h:244
Mask_t fMask
Definition: GuiTypes.h:250
Short_t fY2
Definition: GuiTypes.h:351
Short_t fX1
Definition: GuiTypes.h:351
Short_t fX2
Definition: GuiTypes.h:351
Short_t fY1
Definition: GuiTypes.h:351
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
Definition: triangle.c:7889