Logo ROOT   6.16/01
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 if (res) delete res;
2904 return (Double_t*)fImage->alt.vector;
2905}
2906
2907////////////////////////////////////////////////////////////////////////////////
2908/// This function will tile original image to specified size with offsets
2909/// requested, and then it will go though it and adjust hue, saturation and
2910/// value of those pixels that have specific hue, set by affected_hue/
2911/// affected_radius parameters. When affected_radius is greater then 180
2912/// entire image will be adjusted. Note that since grayscale colors have
2913/// no hue - the will not get adjusted. Only saturation and value will be
2914/// adjusted in gray pixels.
2915///
2916/// Hue is measured as an angle on a 360 degree circle, The following is
2917/// relationship of hue values to regular color names :
2918/// - red - 0
2919/// - yellow - 60
2920/// - green - 120
2921/// - cyan - 180
2922/// - blue - 240
2923/// - magenta - 300
2924/// - red - 360
2925///
2926/// All the hue values in parameters will be adjusted to fall within 0-360 range.
2927///
2928/// \param[in] hue hue in degrees in range 0-360. This allows to limit
2929/// impact of color adjustment to affect only limited range of hues.
2930///
2931/// \param[in] radius value in degrees to be used in order to
2932/// calculate the range of affected hues. Range is determined by
2933/// substracting and adding this value from/to affected_hue.
2934///
2935/// \param[in] H value by which to change hues in affected range.
2936/// \param[in] S value by which to change saturation of the pixels in affected hue range.
2937/// \param[in] V value by which to change Value(brightness) of pixels in affected hue range.
2938///
2939/// \param[in] x,y position on infinite surface tiled with original image, of the
2940/// left-top corner of the area to be used for new image.
2941///
2942/// \param[in] width, height size of the area of the original image to be used for new image.
2943/// Default is current width, height of the image.
2944
2946 Int_t x, Int_t y, UInt_t width, UInt_t height)
2947{
2948 if (!InitVisual()) {
2949 Warning("HSV", "Visual not initiated");
2950 return;
2951 }
2952
2953 if (!fImage) {
2954 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
2955
2956 if (!fImage) {
2957 Warning("HSV", "Failed to create image");
2958 return;
2959 }
2960
2961 x = 0;
2962 y = 0;
2963 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
2964 }
2965
2966 width = !width ? fImage->width : width;
2967 height = !height ? fImage->height : height;
2968
2969 ASImage *rendered_im = 0;
2970
2971 if (H || S || V) {
2972 rendered_im = adjust_asimage_hsv(fgVisual, fImage, x, y, width, height,
2973 hue, radius, H, S, V, ASA_ASImage, 100,
2974 ASIMAGE_QUALITY_TOP);
2975 }
2976 if (!rendered_im) {
2977 Warning("HSV", "Failed to create rendered image");
2978 return;
2979 }
2980
2981 DestroyImage();
2982 fImage = rendered_im;
2983 UnZoom();
2984}
2985
2986////////////////////////////////////////////////////////////////////////////////
2987/// Render multipoint gradient inside rectangle of size (width, height)
2988/// at position (x,y) within the existing image.
2989///
2990/// \param[in] angle Given in degrees. Default is 0. This is the
2991/// direction of the gradient. Currently the only supported
2992/// values are 0, 45, 90, 135, 180, 225, 270, 315. 0 means left
2993/// to right, 90 means top to bottom, etc.
2994///
2995/// \param[in] colors Whitespace-separated list of colors. At least two
2996/// colors are required. Each color in this list will be visited
2997/// in turn, at the intervals given by the offsets attribute.
2998///
2999/// \param[in] offsets Whitespace-separated list of floating point values
3000/// ranging from 0.0 to 1.0. The colors from the colors attribute
3001/// are given these offsets, and the final gradient is rendered
3002/// from the combination of the two. If both colors and offsets
3003/// are given but the number of colors and offsets do not match,
3004/// the minimum of the two will be used, and the other will be
3005/// truncated to match. If offsets are not given, a smooth
3006/// stepping from 0.0 to 1.0 will be used.
3007
3008void TASImage::Gradient(UInt_t angle, const char *colors, const char *offsets,
3009 Int_t x, Int_t y, UInt_t width, UInt_t height)
3010{
3011 if (!InitVisual()) {
3012 Warning("Gradient", "Visual not initiated");
3013 return;
3014 }
3015
3016 ASImage *rendered_im = 0;
3017 ASGradient gradient;
3018
3019 int reverse = 0, npoints1 = 0, npoints2 = 0;
3020 char *p;
3021 char *pb;
3022 char ch;
3023 TString str = colors;
3024 TString col;
3025
3026 if ((angle > 2 * 180 * 15 / 16) || (angle < 2 * 180 * 1 / 16)) {
3027 gradient.type = GRADIENT_Left2Right;
3028 } else if (angle < 2 * 180 * 3 / 16) {
3029 gradient.type = GRADIENT_TopLeft2BottomRight;
3030 } else if (angle < 2 * 180 * 5 / 16) {
3031 gradient.type = GRADIENT_Top2Bottom;
3032 } else if (angle < 2 * 180 * 7 / 16) {
3033 gradient.type = GRADIENT_BottomLeft2TopRight; reverse = 1;
3034 } else if (angle < 2 * 180 * 9 / 16) {
3035 gradient.type = GRADIENT_Left2Right; reverse = 1;
3036 } else if (angle < 2 * 180 * 11 / 16) {
3037 gradient.type = GRADIENT_TopLeft2BottomRight; reverse = 1;
3038 } else if (angle < 2 * 180 * 13 / 16) {
3039 gradient.type = GRADIENT_Top2Bottom; reverse = 1;
3040 } else {
3041 gradient.type = GRADIENT_BottomLeft2TopRight;
3042 }
3043
3044 for (p = (char*)colors; isspace((int)*p); p++) { }
3045
3046 for (npoints1 = 0; *p; npoints1++) {
3047 if (*p) {
3048 for ( ; *p && !isspace((int)*p); p++) { }
3049 }
3050 for ( ; isspace((int)*p); p++) { }
3051 }
3052 if (offsets) {
3053 for (p = (char*)offsets; isspace((int)*p); p++) { }
3054
3055 for (npoints2 = 0; *p; npoints2++) {
3056 if (*p) {
3057 for ( ; *p && !isspace((int)*p); p++) { }
3058 }
3059 for ( ; isspace((int)*p); p++) { }
3060 }
3061 }
3062 if (npoints1 > 1) {
3063 int i;
3064 if (offsets && (npoints1 > npoints2)) npoints1 = npoints2;
3065
3066 if (!width) {
3067 width = fImage ? fImage->width : 20;
3068 }
3069 if (!height) {
3070 height = fImage ? fImage->height : 20;
3071 }
3072
3073 gradient.color = new ARGB32[npoints1];
3074 gradient.offset = new double[npoints1];
3075
3076 for (p = (char*)colors; isspace((int)*p); p++) { }
3077
3078 for (npoints1 = 0; *p; ) {
3079 pb = p;
3080
3081 if (*p) {
3082 for ( ; *p && !isspace((int)*p); p++) { }
3083 }
3084 for ( ; isspace((int)*p); p++) { }
3085
3086 col = str(pb - colors, p - pb);
3087
3088 if (parse_argb_color(col.Data(), gradient.color + npoints1) != col) {
3089 npoints1++;
3090 } else {
3091 Warning("Gradient", "Failed to parse color [%s] - defaulting to black", pb);
3092 }
3093 }
3094
3095 if (offsets) {
3096 for (p = (char*)offsets; isspace((int)*p); p++) { }
3097
3098 for (npoints2 = 0; *p; ) {
3099 pb = p;
3100
3101 if (*p) {
3102 for ( ; *p && !isspace((int)*p); p++) { }
3103 }
3104 ch = *p; *p = '\0';
3105 gradient.offset[npoints2] = strtod(pb, &pb);
3106
3107 if (pb == p) npoints2++;
3108 *p = ch;
3109 for ( ; isspace((int)*p); p++) { }
3110 }
3111 } else {
3112 for (npoints2 = 0; npoints2 < npoints1; npoints2++) {
3113 gradient.offset[npoints2] = (double)npoints2 / (npoints1 - 1);
3114 }
3115 }
3116 gradient.npoints = npoints1;
3117
3118 if (npoints2 && (gradient.npoints > npoints2)) {
3119 gradient.npoints = npoints2;
3120 }
3121 if (reverse) {
3122 for (i = 0; i < gradient.npoints/2; i++) {
3123 int i2 = gradient.npoints - 1 - i;
3124 ARGB32 c = gradient.color[i];
3125 double o = gradient.offset[i];
3126 gradient.color[i] = gradient.color[i2];
3127 gradient.color[i2] = c;
3128 gradient.offset[i] = gradient.offset[i2];
3129 gradient.offset[i2] = o;
3130 }
3131 for (i = 0; i < gradient.npoints; i++) {
3132 gradient.offset[i] = 1.0 - gradient.offset[i];
3133 }
3134 }
3135 rendered_im = make_gradient(fgVisual, &gradient, width, height, SCL_DO_ALL,
3136 ASA_ASImage, GetImageCompression(), GetImageQuality());
3137
3138 delete [] gradient.color;
3139 delete [] gradient.offset;
3140 }
3141
3142 if (!rendered_im) { // error
3143 Warning("Gradient", "Failed to create gradient image");
3144 return;
3145 }
3146
3147 if (!fImage) {
3148 fImage = rendered_im;
3149 return;
3150 }
3151
3152 ASImageLayer layers[2];
3153
3154 init_image_layers(&(layers[0]), 2);
3155 layers[0].im = fImage;
3156 layers[0].dst_x = 0;
3157 layers[0].dst_y = 0;
3158 layers[0].clip_width = fImage->width;
3159 layers[0].clip_height = fImage->height;
3160 layers[0].bevel = 0;
3161 layers[1].im = rendered_im;
3162 layers[1].dst_x = x;
3163 layers[1].dst_y = y;
3164 layers[1].clip_width = width;
3165 layers[1].clip_height = height;
3166 layers[1].merge_scanlines = alphablend_scanlines;
3167
3168 ASImage *merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
3169 ASA_ASImage, GetImageCompression(), GetImageQuality());
3170 if (!merge_im) {
3171 Warning("Gradient", "Failed to create merged image");
3172 return;
3173 }
3174
3175 destroy_asimage(&rendered_im);
3176 DestroyImage();
3177 fImage = merge_im;
3178 UnZoom();
3179}
3180
3181////////////////////////////////////////////////////////////////////////////////
3182/// Make component hilite.
3183/// (used internally)
3184
3185static CARD8 MakeComponentHilite(int cmp)
3186{
3187 if (cmp < 51) {
3188 cmp = 51;
3189 }
3190 cmp = (cmp * 12) / 10;
3191
3192 return (cmp > 255) ? 255 : cmp;
3193}
3194
3195////////////////////////////////////////////////////////////////////////////////
3196/// Calculate highlite color.
3197/// (used internally)
3198
3199static ARGB32 GetHilite(ARGB32 background)
3200{
3201 return ((MakeComponentHilite((background>>24) & 0x000000FF) << 24) & 0xFF000000) |
3202 ((MakeComponentHilite((background & 0x00FF0000) >> 16) << 16) & 0x00FF0000) |
3203 ((MakeComponentHilite((background & 0x0000FF00) >> 8) << 8) & 0x0000FF00) |
3204 ((MakeComponentHilite((background & 0x000000FF))) & 0x000000FF);
3205}
3206
3207////////////////////////////////////////////////////////////////////////////////
3208/// Calculate shadow color.
3209/// (used internally)
3210
3211static ARGB32 GetShadow(ARGB32 background)
3212{
3213 return (background >> 1) & 0x7F7F7F7F;
3214}
3215
3216////////////////////////////////////////////////////////////////////////////////
3217/// Get average.
3218/// (used internally)
3219
3220static ARGB32 GetAverage(ARGB32 foreground, ARGB32 background)
3221{
3222 CARD16 a, r, g, b;
3223
3224 a = ARGB32_ALPHA8(foreground) + ARGB32_ALPHA8(background);
3225 a = (a<<3)/10;
3226 r = ARGB32_RED8(foreground) + ARGB32_RED8(background);
3227 r = (r<<3)/10;
3228 g = ARGB32_GREEN8(foreground) + ARGB32_GREEN8(background);
3229 g = (g<<3)/10;
3230 b = ARGB32_BLUE8(foreground) + ARGB32_BLUE8(background);
3231 b = (b<<3)/10;
3232
3233 return MAKE_ARGB32(a, r, g, b);
3234}
3235
3236
3237////////////////////////////////////////////////////////////////////////////////
3238/// Bevel is used to create 3D effect while drawing buttons, or any other
3239/// image that needs to be framed. Bevel is drawn using 2 primary colors:
3240/// one for top and left sides - hi color, and another for bottom and
3241/// right sides - low color. Bevel can be drawn over existing image or
3242/// as newly created, as it is shown in code below:
3243/// ~~~ {.cpp}
3244/// TImage *img = TImage::Create();
3245/// img->Bevel(0, 0, 400, 300, "#dddddd", "#000000", 3);
3246/// ~~~
3247
3249 const char *hi_color, const char *lo_color, UShort_t thick,
3250 Bool_t reverse)
3251{
3252 if (!InitVisual()) {
3253 Warning("Bevel", "Visual not initiated");
3254 return;
3255 }
3256
3257 ASImageBevel bevel;
3258 bevel.type = 0;
3259
3260 ARGB32 hi=ARGB32_White, lo=ARGB32_White;
3261 parse_argb_color(hi_color, &hi);
3262 parse_argb_color(lo_color, &lo);
3263
3264 if (reverse) {
3265 bevel.lo_color = hi;
3266 bevel.lolo_color = GetHilite(hi);
3267 bevel.hi_color = lo;
3268 bevel.hihi_color = GetShadow(lo);
3269 } else {
3270 bevel.hi_color = hi;
3271 bevel.hihi_color = GetHilite(hi);
3272 bevel.lo_color = lo;
3273 bevel.lolo_color = GetShadow(lo);
3274 }
3275 bevel.hilo_color = GetAverage(hi, lo);
3276
3277 int extra_hilite = 2;
3278 bevel.left_outline = bevel.top_outline = bevel.right_outline = bevel.bottom_outline = thick;
3279 bevel.left_inline = bevel.top_inline = bevel.right_inline = bevel.bottom_inline = extra_hilite + 1;
3280
3281 if (bevel.top_outline > 1) {
3282 bevel.top_inline += bevel.top_outline - 1;
3283 }
3284
3285 if (bevel.left_outline > 1) {
3286 bevel.left_inline += bevel.left_outline - 1;
3287 }
3288
3289 if (bevel.right_outline > 1) {
3290 bevel.right_inline += bevel.right_outline - 1;
3291 }
3292
3293 if (bevel.bottom_outline > 1) {
3294 bevel.bottom_inline += bevel.bottom_outline - 1;
3295 }
3296
3297 ASImage *merge_im;
3298 ARGB32 fill = ((hi>>24) != 0xff) || ((lo>>24) != 0xff) ? bevel.hilo_color : (bevel.hilo_color | 0xff000000);
3299
3300 if (!fImage) {
3301 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
3302
3303 if (!fImage) {
3304 Warning("Bevel", "Failed to create image");
3305 return;
3306 }
3307
3308 x = 0;
3309 y = 0;
3310 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, fill);
3311 }
3312
3313 width = !width ? fImage->width : width;
3314 height = !height ? fImage->height : height;
3315
3316 ASImageLayer layers[2];
3317 init_image_layers(&(layers[0]), 2);
3318
3319 layers[0].im = fImage;
3320 layers[0].dst_x = 0;
3321 layers[0].dst_y = 0;
3322 layers[0].clip_width = fImage->width;
3323 layers[0].clip_height = fImage->height;
3324 layers[0].bevel = 0;
3325
3326 UInt_t w = width - (bevel.left_outline + bevel.right_outline);
3327 UInt_t h = height - (bevel.top_outline + bevel.bottom_outline);
3328 ASImage *bevel_im = create_asimage(w, h, 0);
3329
3330 if (!bevel_im) {
3331 Warning("Bevel", "Failed to create bevel image");
3332 return;
3333 }
3334
3335 layers[1].im = bevel_im;
3336 fill_asimage(fgVisual, bevel_im, 0, 0, w, h, fill);
3337
3338 layers[1].dst_x = x;
3339 layers[1].dst_y = y;
3340 layers[1].clip_width = width;
3341 layers[1].clip_height = height;
3342 layers[1].bevel = &bevel;
3343 layers[1].merge_scanlines = alphablend_scanlines;
3344
3345 merge_im = merge_layers(fgVisual, &(layers[0]), 2, fImage->width, fImage->height,
3346 ASA_ASImage, GetImageCompression(), GetImageQuality());
3347 destroy_asimage(&bevel_im);
3348
3349 if (!merge_im) {
3350 Warning("Bevel", "Failed to image");
3351 return;
3352 }
3353
3354 DestroyImage();
3355 fImage = merge_im;
3356 UnZoom();
3357}
3358
3359
3360////////////////////////////////////////////////////////////////////////////////
3361/// Enlarge image, padding it with specified color on each side in
3362/// accordance with requested geometry.
3363
3364void TASImage::Pad(const char *col, UInt_t l, UInt_t r, UInt_t t, UInt_t b)
3365{
3366 Int_t x, y;
3367 UInt_t w, h;
3368
3369 if (!InitVisual()) {
3370 Warning("Pad", "Visual not initiated");
3371 return;
3372 }
3373
3374 if (!fImage) {
3375 fImage = create_asimage(100, 100, 0);
3376
3377 if (!fImage) {
3378 Warning("Pad", "Failed to create image");
3379 return;
3380 }
3381
3382 x = 0;
3383 y = 0;
3384 fill_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height, ARGB32_White);
3385 }
3386
3387 ARGB32 color = ARGB32_White;
3388 parse_argb_color(col, &color);
3389
3390 x = l;
3391 y = t;
3392 w = l + fImage->width + r;
3393 h = t + fImage->height + b;
3394
3395 ASImage *img = pad_asimage(fgVisual, fImage, x, y, w, h, color,
3396 ASA_ASImage, GetImageCompression(), GetImageQuality());
3397
3398 if (!img) {
3399 Warning("Pad", "Failed to create output image");
3400 return;
3401 }
3402
3403 DestroyImage();
3404 fImage = img;
3405 UnZoom();
3407}
3408
3409
3410////////////////////////////////////////////////////////////////////////////////
3411/// Crop an image.
3412
3414{
3415 if (!InitVisual()) {
3416 Warning("Crop", "Visual not initiated");
3417 return;
3418 }
3419
3420 if (!fImage) {
3421 Warning("Crop", "No image");
3422 return;
3423 }
3424
3425 x = x < 0 ? 0 : x;
3426 y = y < 0 ? 0 : y;
3427
3428 width = x + width > fImage->width ? fImage->width - x : width;
3429 height = y + height > fImage->height ? fImage->height - y : height;
3430
3431 if ((width == fImage->width) && (height == fImage->height)) {
3432 Warning("Crop", "input size larger than image");
3433 return;
3434 }
3435 ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
3436 x, y, width, height, 0);
3437
3438 if (!imdec) {
3439 Warning("Crop", "Failed to start image decoding");
3440 return;
3441 }
3442
3443 ASImage *img = create_asimage(width, height, 0);
3444
3445 if (!img) {
3446 delete [] imdec;
3447 Warning("Crop", "Failed to create image");
3448 return;
3449 }
3450
3451 ASImageOutput *imout = start_image_output(fgVisual, img, ASA_ASImage,
3453
3454 if (!imout) {
3455 Warning("Crop", "Failed to start image output");
3456 destroy_asimage(&img);
3457 if (imdec) delete [] imdec;
3458 return;
3459 }
3460
3461#ifdef HAVE_MMX
3462 mmx_init();
3463#endif
3464
3465 for (UInt_t i = 0; i < height; i++) {
3466 imdec->decode_image_scanline(imdec);
3467 imout->output_image_scanline(imout, &(imdec->buffer), 1);
3468 }
3469
3470 stop_image_decoding(&imdec);
3471 stop_image_output(&imout);
3472
3473#ifdef HAVE_MMX
3474 mmx_off();
3475#endif
3476
3477 DestroyImage();
3478 fImage = img;
3479 UnZoom();
3481}
3482
3483////////////////////////////////////////////////////////////////////////////////
3484/// Append image.
3485///
3486/// option:
3487/// - "+" - appends to the right side
3488/// - "/" - appends to the bottom
3489
3490void TASImage::Append(const TImage *im, const char *option, const char *color )
3491{
3492 if (!im) return;
3493
3494 if (!InitVisual()) {
3495 Warning("Append", "Visual not initiated");
3496 return;
3497 }
3498
3499 if (!fImage) {
3500 fImage = ((TASImage*)im)->fImage;
3501 return;
3502 }
3503
3504 TString opt = option;
3505 opt.Strip();
3506
3507 UInt_t width = fImage->width;
3508 UInt_t height = fImage->height;
3509
3510 if (opt == "+") {
3511 Pad(color, 0, im->GetWidth(), 0, 0);
3512 Merge(im, "alphablend", width, 0);
3513 } else if (opt == "/") {
3514 Pad(color, 0, 0, 0, im->GetHeight());
3515 Merge(im, "alphablend", 0, height);
3516 } else {
3517 return;
3518 }
3519
3520 UnZoom();
3521}
3522
3523////////////////////////////////////////////////////////////////////////////////
3524/// BeginPaint initializes internal array[width x height] of ARGB32 pixel
3525/// values.
3526///
3527/// That provides quick access to image during paint operations.
3528/// To RLE compress image one needs to call EndPaint method when painting
3529/// is over.
3530
3532{
3533 if (!InitVisual()) {
3534 Warning("BeginPaint", "Visual not initiated");
3535 return;
3536 }
3537
3538 if (!fImage) {
3539 return;
3540 }
3541
3542 fPaintMode = mode;
3543
3544 if (!fPaintMode || fImage->alt.argb32) {
3545 return;
3546 }
3547
3548 ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
3549 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
3550
3551 if (!img) {
3552 Warning("BeginPaint", "Failed to create image");
3553 return;
3554 }
3555
3556 DestroyImage();
3557 fImage = img;
3558}
3559
3560////////////////////////////////////////////////////////////////////////////////
3561/// EndPaint does internal RLE compression of image data.
3562
3564{
3565 if (!fImage) {
3566 Warning("EndPaint", "no image");
3567 return;
3568 }
3569
3570 if (!fImage->alt.argb32) return;
3571
3572 ASImage *img = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
3573 0, ASA_ASImage, 0, ASIMAGE_QUALITY_DEFAULT);
3574
3575 if (!img) {
3576 Warning("EndPaint", "Failed to create image");
3577 return;
3578 }
3579
3581 DestroyImage();
3582 fImage = img;
3583}
3584
3585////////////////////////////////////////////////////////////////////////////////
3586/// Return a pointer to internal array[width x height] of ARGB32 values
3587/// This array is directly accessible. That allows to manipulate/change the
3588/// image.
3589
3591{
3592 if (!fImage) {
3593 Warning("GetArgbArray", "no image");
3594 return 0;
3595 }
3596
3597 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3598 if (!img) return 0;
3599
3600 if (!img->alt.argb32) {
3601 if (fScaledImage) {
3603 img = fScaledImage->fImage;
3604 } else {
3605 BeginPaint();
3606 img = fImage;
3607 }
3608 }
3609
3610 return (UInt_t *)img->alt.argb32;
3611}
3612
3613////////////////////////////////////////////////////////////////////////////////
3614/// Return a pointer to an array[width x height] of RGBA32 values.
3615/// This array is created from internal ARGB32 array,
3616/// must be deleted after usage.
3617
3619{
3620 if (!fImage) {
3621 Warning("GetRgbaArray", "no image");
3622 return 0;
3623 }
3624
3625 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3626 if (!img) return 0;
3627
3628 if (!img->alt.argb32) {
3629 if (fScaledImage) {
3631 img = fScaledImage->fImage;
3632 } else {
3633 BeginPaint();
3634 img = fImage;
3635 }
3636 }
3637
3638 UInt_t i, j;
3639 Int_t y = 0;
3640 Int_t idx = 0;
3641 UInt_t a, rgb, rgba, argb;
3642 y = 0;
3643
3644 UInt_t *ret = new UInt_t[img->width*img->height];
3645
3646 for (i = 0; i < img->height; i++) {
3647 for (j = 0; j < img->width; j++) {
3648 idx = Idx(y + j);
3649 argb = img->alt.argb32[idx];
3650 a = argb >> 24;
3651 rgb = argb & 0x00ffffff;
3652 rgba = (rgb << 8) + a;
3653 ret[idx] = rgba;
3654 }
3655 y += img->width;
3656 }
3657
3658 return ret;
3659}
3660
3661////////////////////////////////////////////////////////////////////////////////
3662/// Return a pointer to scan-line.
3663
3665{
3666 if (!fImage) {
3667 Warning("GetScanline", "no image");
3668 return 0;
3669 }
3670
3671 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
3672 CARD32 *ret = new CARD32[img->width];
3673
3674 ASImageDecoder *imdec = start_image_decoding(fgVisual, img, SCL_DO_ALL,
3675 0, y, img->width, 1, 0);
3676
3677 if (!imdec) {
3678 delete [] ret;
3679 Warning("GetScanline", "Failed to start image decoding");
3680 return 0;
3681 }
3682
3683#ifdef HAVE_MMX
3684 mmx_init();
3685#endif
3686
3687 imdec->decode_image_scanline(imdec);
3688 memcpy(imdec->buffer.buffer, ret, img->width*sizeof(CARD32));
3689 stop_image_decoding(&imdec);
3690
3691#ifdef HAVE_MMX
3692 mmx_off();
3693#endif
3694
3695 return (UInt_t*)ret;
3696}
3697
3698
3699//______________________________________________________________________________
3700//
3701// Vector graphics
3702// a couple of macros which can be "assembler accelerated"
3703
3704#if defined(R__GNU) && defined(__i386__) && !defined(__sun)
3705#define _MEMSET_(dst, lng, val) __asm__("movl %0,%%eax \n"\
3706 "movl %1,%%edi \n" \
3707 "movl %2,%%ecx \n" \
3708 "cld \n" \
3709 "rep \n" \
3710 "stosl \n" \
3711 : /* no output registers */ \
3712 :"g" (val), "g" (dst), "g" (lng) \
3713 :"eax","edi","ecx" \
3714 )
3715
3716#else
3717 #define _MEMSET_(dst, lng, val) do {\
3718 for( UInt_t j=0; j < lng; j++) *((dst)+j) = val; } while (0)
3719
3720#endif
3721
3722#define FillSpansInternal(npt, ppt, widths, color) do {\
3723 UInt_t yy = ppt[0].fY*fImage->width;\
3724 for (UInt_t i = 0; i < npt; i++) {\
3725 _MEMSET_(&fImage->alt.argb32[Idx(yy + ppt[i].fX)], widths[i], color);\
3726 yy += ((i+1 < npt) && (ppt[i].fY != ppt[i+1].fY) ? fImage->width : 0);\
3727 }\
3728} while (0)
3729
3730////////////////////////////////////////////////////////////////////////////////
3731/// Fill rectangle of size (width, height) at position (x,y)
3732/// within the existing image with specified color.
3733
3735{
3736
3737 if (!InitVisual()) {
3738 Warning("FillRectangle", "Visual not initiated");
3739 return;
3740 }
3741
3742 if (!fImage) {
3743 Warning("FillRectangle", "no image");
3744 return;
3745 }
3746
3747 if (!fImage->alt.argb32) {
3748 BeginPaint();
3749 }
3750
3751 if (!fImage->alt.argb32) {
3752 Warning("FillRectangle", "Failed to get pixel array");
3753 return;
3754 }
3755
3756 ARGB32 color = (ARGB32)col;
3757
3758 if (width == 0) width = 1;
3759 if (height == 0) height = 1;
3760
3761 if (x < 0) {
3762 width += x;
3763 x = 0;
3764 }
3765 if (y < 0) {
3766 height += y;
3767 y = 0;
3768 }
3769
3770 Bool_t has_alpha = (color & 0xff000000) != 0xff000000;
3771
3772 x = x > (int)fImage->width ? (Int_t)fImage->width : x;
3773 y = y > (int)fImage->height ? (Int_t)fImage->height : y;
3774
3775 width = x + width > fImage->width ? fImage->width - x : width;
3776 height = y + height > fImage->height ? fImage->height - y : height;
3777
3778 if (!fImage->alt.argb32) {
3779 fill_asimage(fgVisual, fImage, x, y, width, height, color);
3780 } else {
3781 int yyy = y*fImage->width;
3782 if (!has_alpha) { // use faster memset
3783 ARGB32 *p0 = fImage->alt.argb32 + yyy + x;
3784 ARGB32 *p = p0;
3785 for (UInt_t i = 0; i < height; i++) {
3786 _MEMSET_(p, width, color);
3787 p += fImage->width;
3788 }
3789 } else {
3790 for (UInt_t i = y; i < y + height; i++) {
3791 int j = x + width;
3792 while (j > x) {
3793 j--;
3794 _alphaBlend(&fImage->alt.argb32[Idx(yyy + j)], &color);
3795 }
3796 yyy += fImage->width;
3797 }
3798 }
3799 }
3800}
3801
3802////////////////////////////////////////////////////////////////////////////////
3803/// Fill rectangle of size (width, height) at position (x,y)
3804/// within the existing image with specified color.
3805///
3806/// To create new image with Fill method the following code can be used:
3807/// ~~~ {.cpp}
3808/// TImage *img = TImage::Create();
3809/// img->Fill("#FF00FF", 0, 0, 400, 300);
3810/// ~~~
3811
3812void TASImage::FillRectangle(const char *col, Int_t x, Int_t y, UInt_t width, UInt_t height)
3813{
3814 if (!InitVisual()) {
3815 Warning("Fill", "Visual not initiated");
3816 return;
3817 }
3818
3819 ARGB32 color = ARGB32_White;
3820
3821 if (col) {
3822 parse_argb_color(col, &color);
3823 }
3824
3825 if (!fImage) {
3826 fImage = create_asimage(width ? width : 20, height ? height : 20, 0);
3827 x = 0;
3828 y = 0;
3829 }
3830
3831 FillRectangleInternal((UInt_t)color, x, y, width, height);
3832 UnZoom();
3833}
3834
3835////////////////////////////////////////////////////////////////////////////////
3836/// Draw a vertical line.
3837
3839{
3840 ARGB32 color = (ARGB32)col;
3841 UInt_t half = 0;
3842
3843 if (!thick) thick = 1;
3844
3845 if (thick > 1) {
3846 half = thick >> 1;
3847 if (x > half) {
3848 x = x - half;
3849 } else {
3850 x = 0;
3851 thick += (x - half);
3852 }
3853 }
3854
3855 y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
3856 y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
3857 x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
3858
3859 int yy = y1*fImage->width;
3860 for (UInt_t y = y1; y <= y2; y++) {
3861 for (UInt_t w = 0; w < thick; w++) {
3862 if (x + w < fImage->width) {
3863 _alphaBlend(&fImage->alt.argb32[Idx(yy + (x + w))], &color);
3864 }
3865 }
3866 yy += fImage->width;
3867 }
3868}
3869
3870////////////////////////////////////////////////////////////////////////////////
3871/// Draw an horizontal line.
3872
3874{
3875 ARGB32 color = (ARGB32)col;
3876 UInt_t half = 0;
3877
3878 if (!thick) thick = 1;
3879
3880 if (thick > 1) {
3881 half = thick >> 1;
3882 if (y > half) {
3883 y = y - half;
3884 } else {
3885 y = 0;
3886 thick += (y - half);
3887 }
3888 }
3889
3890 y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
3891 x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
3892 x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
3893
3894 int yy = y*fImage->width;
3895 for (UInt_t w = 0; w < thick; w++) {
3896 for (UInt_t x = x1; x <= x2; x++) {
3897 if (y + w < fImage->height) {
3898 _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
3899 }
3900 }
3901 yy += fImage->width;
3902 }
3903}
3904
3905////////////////////////////////////////////////////////////////////////////////
3906/// Draw a line.
3907
3909 const char *col, UInt_t thick)
3910{
3911 ARGB32 color = ARGB32_White;
3912 parse_argb_color(col, &color);
3913 DrawLineInternal(x1, y1, x2, y2, (UInt_t)color, thick);
3914}
3915
3916////////////////////////////////////////////////////////////////////////////////
3917/// Internal line drawing.
3918
3920 UInt_t col, UInt_t thick)
3921{
3922 int dx, dy, d;
3923 int i1, i2;
3924 int x, y, xend, yend;
3925 int xdir, ydir;
3926 int q;
3927 int idx;
3928 int yy;
3929
3930 if (!InitVisual()) {
3931 Warning("DrawLine", "Visual not initiated");
3932 return;
3933 }
3934
3935 if (!fImage) {
3936 Warning("DrawLine", "no image");
3937 return;
3938 }
3939
3940 if (!fImage->alt.argb32) {
3941 BeginPaint();
3942 }
3943
3944 if (!fImage->alt.argb32) {
3945 Warning("DrawLine", "Failed to get pixel array");
3946 return;
3947 }
3948
3949 ARGB32 color = (ARGB32)col;
3950
3951 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
3952 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
3953
3954 if (!dx && !dy) return; // invisible line
3955
3956 if (!dx) {
3957 DrawVLine(x1, y2 > y1 ? y1 : y2,
3958 y2 > y1 ? y2 : y1, color, thick);
3959 return;
3960 }
3961
3962 if (!dy) {
3963 DrawHLine(y1, x2 > x1 ? x1 : x2,
3964 x2 > x1 ? x2 : x1, color, thick);
3965 return;
3966 }
3967
3968 if (thick > 1) {
3969 DrawWideLine(x1, y1, x2, y2, color, thick);
3970 return;
3971 }
3972
3973 if (dy <= dx) {
3974 UInt_t ddy = dy << 1;
3975 i1 = ddy;
3976 i2 = i1 - (dx << 1);
3977 d = i1 - dx;
3978
3979 if (x1 > x2) {
3980 x = x2;
3981 y = y2;
3982 ydir = -1;
3983 xend = x1;
3984 } else {
3985 x = x1;
3986 y = y1;
3987 ydir = 1;
3988 xend = x2;
3989 }
3990
3991 yy = y*fImage->width;
3992 _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
3993 q = (y2 - y1) * ydir;
3994
3995 if (q > 0) {
3996 while (x < xend) {
3997
3998 idx = Idx(yy + x);
3999 _alphaBlend(&fImage->alt.argb32[idx], &color);
4000 x++;
4001
4002 if (d >= 0) {
4003 yy += fImage->width;
4004 d += i2;
4005 } else {
4006 d += i1;
4007 }
4008 }
4009 } else {
4010 while (x < xend) {
4011 idx = Idx(yy + x);
4012 _alphaBlend(&fImage->alt.argb32[idx], &color);
4013 x++;
4014
4015 if (d >= 0) {
4016 yy -= fImage->width;
4017 d += i2;
4018 } else {
4019 d += i1;
4020 }
4021 }
4022 }
4023 } else {
4024 UInt_t ddx = dx << 1;
4025 i1 = ddx;
4026 i2 = i1 - (dy << 1);
4027 d = i1 - dy;
4028
4029 if (y1 > y2) {
4030 y = y2;
4031 x = x2;
4032 yend = y1;
4033 xdir = -1;
4034 } else {
4035 y = y1;
4036 x = x1;
4037 yend = y2;
4038 xdir = 1;
4039 }
4040
4041 yy = y*fImage->width;
4042 _alphaBlend(&fImage->alt.argb32[Idx(yy + x)], &color);
4043 q = (x2 - x1) * xdir;
4044
4045 if (q > 0) {
4046 while (y < yend) {
4047 idx = Idx(yy + x);
4048 _alphaBlend(&fImage->alt.argb32[idx], &color);
4049 y++;
4050 yy += fImage->width;
4051
4052 if (d >= 0) {
4053 x++;
4054 d += i2;
4055 } else {
4056 d += i1;
4057 }
4058 }
4059 } else {
4060 while (y < yend) {
4061 idx = Idx(yy + x);
4062 _alphaBlend(&fImage->alt.argb32[idx], &color);
4063 y++;
4064 yy += fImage->width;
4065
4066 if (d >= 0) {
4067 x--;
4068 d += i2;
4069 } else {
4070 d += i1;
4071 }
4072 }
4073 }
4074 }
4075}
4076
4077////////////////////////////////////////////////////////////////////////////////
4078/// Draw a rectangle.
4079
4081 const char *col, UInt_t thick)
4082{
4083 if (!InitVisual()) {
4084 Warning("DrawRectangle", "Visual not initiated");
4085 return;
4086 }
4087
4088 if (!fImage) {
4089 w = w ? w : 20;
4090 h = h ? h : 20;
4091 x = 0;
4092 y = 0;
4093 fImage = create_asimage(w, h, 0);
4094 FillRectangle(col, 0, 0, w, h);
4095 return;
4096 }
4097
4098 if (!fImage->alt.argb32) {
4099 BeginPaint();
4100 }
4101
4102 if (!fImage->alt.argb32) {
4103 Warning("DrawRectangle", "Failed to get pixel array");
4104 return;
4105 }
4106
4107 ARGB32 color = ARGB32_White;
4108 parse_argb_color(col, &color);
4109
4110 DrawHLine(y, x, x + w, (UInt_t)color, thick);
4111 DrawVLine(x + w, y, y + h, (UInt_t)color, thick);
4112 DrawHLine(y + h, x, x + w, (UInt_t)color, thick);
4113 DrawVLine(x, y, y + h, (UInt_t)color, thick);
4114 UnZoom();
4115}
4116
4117////////////////////////////////////////////////////////////////////////////////
4118/// Draw a box.
4119
4120void TASImage::DrawBox(Int_t x1, Int_t y1, Int_t x2, Int_t y2, const char *col,
4121 UInt_t thick, Int_t mode)
4122{
4123 Int_t x = TMath::Min(x1, x2);
4124 Int_t y = TMath::Min(y1, y2);
4125 Int_t w = TMath::Abs(x2 - x1);
4126 Int_t h = TMath::Abs(y2 - y1);
4127
4128 ARGB32 color = ARGB32_White;
4129
4130 if (!fImage) {
4131 w = w ? x+w : x+20;
4132 h = h ? y+h : y+20;
4133 fImage = create_asimage(w, h, 0);
4134 FillRectangle(col, 0, 0, w, h);
4135 return;
4136 }
4137
4138 if (x1 == x2) {
4139 parse_argb_color(col, &color);
4140 DrawVLine(x1, y1, y2, color, 1);
4141 return;
4142 }
4143
4144 if (y1 == y2) {
4145 parse_argb_color(col, &color);
4146 DrawHLine(y1, x1, x2, color, 1);
4147 return;
4148 }
4149
4150
4151 switch (mode) {
4152 case TVirtualX::kHollow:
4153 DrawRectangle(x, y, w, h, col, thick);
4154 break;
4155
4156 case TVirtualX::kFilled:
4157 FillRectangle(col, x, y, w, h);
4158 break;
4159
4160 default:
4161 FillRectangle(col, x, y, w, h);
4162 break;
4163 }
4164}
4165
4166////////////////////////////////////////////////////////////////////////////////
4167/// Draw a dashed horizontal line.
4168
4170 const char *pDash, UInt_t col, UInt_t thick)
4171{
4172 UInt_t iDash = 0; // index of current dash
4173 int i = 0;
4174
4175 ARGB32 color = (ARGB32)col;
4176
4177 UInt_t half = 0;
4178
4179 if (thick > 1) {
4180 half = thick >> 1;
4181 if (y > half) {
4182 y = y - half;
4183 } else {
4184 y = 0;
4185 thick += (y - half);
4186 }
4187 }
4188 thick = thick <= 0 ? 1 : thick;
4189
4190 y = y + thick >= fImage->height ? fImage->height - thick - 1 : y;
4191 x2 = x2 >= fImage->width ? fImage->width - 1 : x2;
4192 x1 = x1 >= fImage->width ? fImage->width - 1 : x1;
4193
4194 // switch x1, x2
4195 UInt_t tmp = x1;
4196 x1 = x2 < x1 ? x2 : x1;
4197 x2 = x2 < tmp ? tmp : x2;
4198
4199 for (UInt_t x = x1; x <= x2; x++) {
4200 for (UInt_t w = 0; w < thick; w++) {
4201 if (y + w < fImage->height) {
4202 if ((iDash%2)==0) {
4203 _alphaBlend(&fImage->alt.argb32[Idx((y + w)*fImage->width + x)], &color);
4204 }
4205 }
4206 }
4207 i++;
4208
4209 if (i >= pDash[iDash]) {
4210 iDash++;
4211 i = 0;
4212 }
4213 if (iDash >= nDash) {
4214 iDash = 0;
4215 i = 0;
4216 }
4217 }
4218}
4219
4220////////////////////////////////////////////////////////////////////////////////
4221/// Draw a dashed vertical line.
4222
4224 const char *pDash, UInt_t col, UInt_t thick)
4225{
4226 UInt_t iDash = 0; // index of current dash
4227 int i = 0;
4228
4229 ARGB32 color = (ARGB32)col;
4230
4231 UInt_t half = 0;
4232
4233 if (thick > 1) {
4234 half = thick >> 1;
4235 if (x > half) {
4236 x = x - half;
4237 } else {
4238 x = 0;
4239 thick += (x - half);
4240 }
4241 }
4242 thick = thick <= 0 ? 1 : thick;
4243
4244 y2 = y2 >= fImage->height ? fImage->height - 1 : y2;
4245 y1 = y1 >= fImage->height ? fImage->height - 1 : y1;
4246
4247 // switch x1, x2
4248 UInt_t tmp = y1;
4249 y1 = y2 < y1 ? y2 : y1;
4250 y2 = y2 < tmp ? tmp : y2;
4251
4252 x = x + thick >= fImage->width ? fImage->width - thick - 1 : x;
4253
4254 int yy = y1*fImage->width;
4255 for (UInt_t y = y1; y <= y2; y++) {
4256 for (UInt_t w = 0; w < thick; w++) {
4257 if (x + w < fImage->width) {
4258 if ((iDash%2)==0) {
4259 _alphaBlend(&fImage->alt.argb32[Idx(yy + (x + w))], &color);
4260 }
4261 }
4262 }
4263 i++;
4264
4265 if (i >= pDash[iDash]) {
4266 iDash++;
4267 i = 0;
4268 }
4269 if (iDash >= nDash) {
4270 iDash = 0;
4271 i = 0;
4272 }
4273 yy += fImage->width;
4274 }
4275}
4276
4277////////////////////////////////////////////////////////////////////////////////
4278/// Draw a dashed line with one pixel width.
4279
4281 UInt_t nDash, const char *tDash, UInt_t color)
4282{
4283 int dx, dy, d;
4284 int i, i1, i2;
4285 int x, y, xend, yend;
4286 int xdir, ydir;
4287 int q;
4288 UInt_t iDash = 0; // index of current dash
4289 int yy;
4290 int idx;
4291
4292 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
4293 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
4294
4295 char *pDash = new char[nDash];
4296
4297 if (dy <= dx) {
4298 double ac = TMath::Cos(TMath::ATan2(dy, dx));
4299
4300 for (i = 0; i < (int)nDash; i++) {
4301 pDash[i] = TMath::Nint(tDash[i] * ac);
4302 }
4303
4304 UInt_t ddy = dy << 1;
4305 i1 = ddy;
4306 i2 = i1 - (dx << 1);
4307 d = i1 - dx;
4308 i = 0;
4309
4310 if (x1 > x2) {
4311 x = x2;
4312 y = y2;
4313 ydir = -1;
4314 xend = x1;
4315 } else {
4316 x = x1;
4317 y = y1;
4318 ydir = 1;
4319 xend = x2;
4320 }
4321
4322 yy = y*fImage->width;
4323 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4324 q = (y2 - y1) * ydir;
4325
4326 if (q > 0) {
4327 while (x < xend) {
4328 idx = Idx(yy + x);
4329 if ((iDash%2) == 0) {
4330 _alphaBlend(&fImage->alt.argb32[idx], &color);
4331 }
4332 x++;
4333 if (d >= 0) {
4334 yy += fImage->width;
4335 d += i2;
4336 } else {
4337 d += i1;
4338 }
4339
4340 i++;
4341 if (i >= pDash[iDash]) {
4342 iDash++;
4343 i = 0;
4344 }
4345 if (iDash >= nDash) {
4346 iDash = 0;
4347 i = 0;
4348 }
4349 }
4350 } else {
4351 while (x < xend) {
4352 idx = Idx(yy + x);
4353 if ((iDash%2) == 0) {
4354 _alphaBlend(&fImage->alt.argb32[idx], &color);
4355 }
4356 x++;
4357 if (d >= 0) {
4358 yy -= fImage->width;
4359 d += i2;
4360 } else {
4361 d += i1;
4362 }
4363
4364 i++;
4365 if (i >= pDash[iDash]) {
4366 iDash++;
4367 i = 0;
4368 }
4369 if (iDash >= nDash) {
4370 iDash = 0;
4371 i = 0;
4372 }
4373 }
4374 }
4375 } else {
4376 double as = TMath::Sin(TMath::ATan2(dy, dx));
4377
4378 for (i = 0; i < (int)nDash; i++) {
4379 pDash[i] = TMath::Nint(tDash[i] * as);
4380 }
4381
4382 UInt_t ddx = dx << 1;
4383 i1 = ddx;
4384 i2 = i1 - (dy << 1);
4385 d = i1 - dy;
4386 i = 0;
4387
4388 if (y1 > y2) {
4389 y = y2;
4390 x = x2;
4391 yend = y1;
4392 xdir = -1;
4393 } else {
4394 y = y1;
4395 x = x1;
4396 yend = y2;
4397 xdir = 1;
4398 }
4399
4400 yy = y*fImage->width;
4401 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4402 q = (x2 - x1) * xdir;
4403
4404 if (q > 0) {
4405 while (y < yend) {
4406 idx = Idx(yy + x);
4407 if ((iDash%2) == 0) {
4408 _alphaBlend(&fImage->alt.argb32[idx], &color);
4409 }
4410 y++;
4411 yy += fImage->width;
4412
4413 if (d >= 0) {
4414 x++;
4415 d += i2;
4416 } else {
4417 d += i1;
4418 }
4419
4420 i++;
4421 if (i >= pDash[iDash]) {
4422 iDash++;
4423 i = 0;
4424 }
4425 if (iDash >= nDash) {
4426 iDash = 0;
4427 i = 0;
4428 }
4429 }
4430 } else {
4431 while (y < yend) {
4432 idx = Idx(yy + x);
4433 if ((iDash%2) == 0) {
4434 _alphaBlend(&fImage->alt.argb32[idx], &color);
4435 }
4436 y++;
4437 yy += fImage->width;
4438
4439 if (d >= 0) {
4440 x--;
4441 d += i2;
4442 } else {
4443 d += i1;
4444 }
4445
4446 i++;
4447 if (i >= pDash[iDash]) {
4448 iDash++;
4449 i = 0;
4450 }
4451 if (iDash >= nDash) {
4452 iDash = 0;
4453 i = 0;
4454 }
4455 }
4456 }
4457 }
4458 delete [] pDash;
4459}
4460
4461////////////////////////////////////////////////////////////////////////////////
4462/// Draw a dashed line with thick pixel width.
4463
4465 UInt_t nDash, const char *tDash, UInt_t color, UInt_t thick)
4466{
4467 int dx, dy;
4468 int i;
4469 double x, y, xend=0, yend=0, x0, y0;
4470 int xdir, ydir;
4471 int q;
4472 UInt_t iDash = 0; // index of current dash
4473
4474 dx = TMath::Abs(Int_t(x2) - Int_t(x1));
4475 dy = TMath::Abs(Int_t(y2) - Int_t(y1));
4476
4477 double *xDash = new double[nDash];
4478 double *yDash = new double[nDash];
4479 double a = TMath::ATan2(dy, dx);
4480 double ac = TMath::Cos(a);
4481 double as = TMath::Sin(a);
4482
4483 for (i = 0; i < (int)nDash; i++) {
4484 xDash[i] = tDash[i] * ac;
4485 yDash[i] = tDash[i] * as;
4486
4487 // dirty trick (must be fixed)
4488 if ((i%2) == 0) {
4489 xDash[i] = xDash[i]/2;
4490 yDash[i] = yDash[i]/2;
4491 } else {
4492 xDash[i] = xDash[i]*2;
4493 yDash[i] = yDash[i]*2;
4494 }
4495 }
4496
4497 if (dy <= dx) {
4498 if (x1 > x2) {
4499 x = x2;
4500 y = y2;
4501 ydir = -1;
4502 xend = x1;
4503 } else {
4504 x = x1;
4505 y = y1;
4506 ydir = 1;
4507 xend = x2;
4508 }
4509
4510 q = (y2 - y1) * ydir;
4511 x0 = x;
4512 y0 = y;
4513 iDash = 0;
4514 yend = y + q;
4515
4516 if (q > 0) {
4517 while ((x < xend) && (y < yend)) {
4518 x += xDash[iDash];
4519 y += yDash[iDash];
4520
4521 if ((iDash%2) == 0) {
4523 TMath::Nint(x), TMath::Nint(y), color, thick);
4524 } else {
4525 x0 = x;
4526 y0 = y;
4527 }
4528
4529 iDash++;
4530
4531 if (iDash >= nDash) {
4532 iDash = 0;
4533 }
4534 }
4535 } else {
4536 while ((x < xend) && (y > yend)) {
4537 x += xDash[iDash];
4538 y -= yDash[iDash];
4539
4540 if ((iDash%2) == 0) {
4542 TMath::Nint(x), TMath::Nint(y), color, thick);
4543 } else {
4544 x0 = x;
4545 y0 = y;
4546 }
4547
4548 iDash++;
4549
4550 if (iDash >= nDash) {
4551 iDash = 0;
4552 }
4553 }
4554 }
4555 } else {
4556
4557 if (y1 > y2) {
4558 y = y2;
4559 x = x2;
4560 yend = y1;
4561 xdir = -1;
4562 } else {
4563 y = y1;
4564 x = x1;
4565 yend = y2;
4566 xdir = 1;
4567 }
4568
4569 q = (x2 - x1) * xdir;
4570 x0 = x;
4571 y0 = y;
4572 iDash = 0;
4573 xend = x + q;
4574
4575 if (q > 0) {
4576 while ((x < xend) && (y < yend)) {
4577 x += xDash[iDash];
4578 y += yDash[iDash];
4579
4580 if ((iDash%2) == 0) {
4582 TMath::Nint(x), TMath::Nint(y), color, thick);
4583 } else {
4584 x0 = x;
4585 y0 = y;
4586 }
4587
4588 iDash++;
4589
4590 if (iDash >= nDash) {
4591 iDash = 0;
4592 }
4593 }
4594 } else {
4595 while ((x > xend) && (y < yend)) {
4596 x -= xDash[iDash];
4597 y += yDash[iDash];
4598
4599 if ((iDash%2) == 0) {
4601 TMath::Nint(x), TMath::Nint(y), color, thick);
4602 } else {
4603 x0 = x;
4604 y0 = y;
4605 }
4606
4607 iDash++;
4608
4609 if (iDash >= nDash) {
4610 iDash = 0;
4611 }
4612 }
4613 }
4614 }
4615 delete [] xDash;
4616 delete [] yDash;
4617}
4618
4619////////////////////////////////////////////////////////////////////////////////
4620/// Draw a dashed line.
4621
4623 const char *pDash, const char *col, UInt_t thick)
4624
4625{
4626 if (!InitVisual()) {
4627 Warning("DrawDashLine", "Visual not initiated");
4628 return;
4629 }
4630
4631 if (!fImage) {
4632 Warning("DrawDashLine", "no image");
4633 return;
4634 }
4635
4636 if (!fImage->alt.argb32) {
4637 BeginPaint();
4638 }
4639
4640 if (!fImage->alt.argb32) {
4641 Warning("DrawDashLine", "Failed to get pixel array");
4642 return;
4643 }
4644
4645 if ((nDash < 2) || !pDash || (nDash%2)) {
4646 Warning("DrawDashLine", "Wrong input parameters n=%d %ld", nDash, (Long_t)sizeof(pDash)-1);
4647 return;
4648 }
4649
4650 ARGB32 color = ARGB32_White;
4651 parse_argb_color(col, &color);
4652
4653 if (x1 == x2) {
4654 DrawDashVLine(x1, y1, y2, nDash, pDash, (UInt_t)color, thick);
4655 } else if (y1 == y2) {
4656 DrawDashHLine(y1, x1, x2, nDash, pDash, (UInt_t)color, thick);
4657 } else {
4658 if (thick < 2) DrawDashZLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color);
4659 else DrawDashZTLine(x1, y1, x2, y2, nDash, pDash, (UInt_t)color, thick);
4660 }
4661}
4662
4663////////////////////////////////////////////////////////////////////////////////
4664/// Draw a polyline.
4665
4666void TASImage::DrawPolyLine(UInt_t nn, TPoint *xy, const char *col, UInt_t thick,
4667 TImage::ECoordMode mode)
4668{
4669 ARGB32 color = ARGB32_White;
4670 parse_argb_color(col, &color);
4671
4672 Int_t x0 = xy[0].GetX();
4673 Int_t y0 = xy[0].GetY();
4674 Int_t x = 0;
4675 Int_t y = 0;
4676
4677 for (UInt_t i = 1; i < nn; i++) {
4678 x = (mode == kCoordModePrevious) ? x + xy[i].GetX() : xy[i].GetX();
4679 y = (mode == kCoordModePrevious) ? y + xy[i].GetY() : xy[i].GetY();
4680
4681 DrawLineInternal(x0, y0, x, y, (UInt_t)color, thick);
4682
4683 x0 = x;
4684 y0 = y;
4685 }
4686}
4687
4688////////////////////////////////////////////////////////////////////////////////
4689/// Draw a point at the specified position.
4690
4691void TASImage::PutPixel(Int_t x, Int_t y, const char *col)
4692{
4693 if (!InitVisual()) {
4694 Warning("PutPixel", "Visual not initiated");
4695 return;
4696 }
4697
4698 if (!fImage) {
4699 Warning("PutPixel", "no image");
4700 return;
4701 }
4702
4703 if (!fImage->alt.argb32) {
4704 BeginPaint();
4705 }
4706
4707 if (!fImage->alt.argb32) {
4708 Warning("PutPixel", "Failed to get pixel array");
4709 return;
4710 }
4711
4712 ARGB32 color;
4713 parse_argb_color(col, &color);
4714
4715 if ((x < 0) || (y < 0) || (x >= (int)fImage->width) || (y >= (int)fImage->height)) {
4716 Warning("PutPixel", "Out of range width=%d x=%d, height=%d y=%d",
4717 fImage->width, x, fImage->height, y);
4718 return;
4719 }
4720 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4721}
4722
4723////////////////////////////////////////////////////////////////////////////////
4724/// Draw a poly point.
4725
4726void TASImage::PolyPoint(UInt_t npt, TPoint *ppt, const char *col, TImage::ECoordMode mode)
4727{
4728 if (!InitVisual()) {
4729 Warning("PolyPoint", "Visual not initiated");
4730 return;
4731 }
4732
4733 if (!fImage) {
4734 Warning("PolyPoint", "no image");
4735 return;
4736 }
4737
4738 if (!fImage->alt.argb32) {
4739 BeginPaint();
4740 }
4741
4742 if (!fImage->alt.argb32) {
4743 Warning("PolyPoint", "Failed to get pixel array");
4744 return;
4745 }
4746
4747 if (!npt || !ppt) {
4748 Warning("PolyPoint", "No points specified");
4749 return;
4750 }
4751
4752 TPoint *ipt = 0;
4753 UInt_t i = 0;
4754 ARGB32 color;
4755 parse_argb_color(col, &color);
4756
4757 //make pointlist origin relative
4758 if (mode == kCoordModePrevious) {
4759 ipt = new TPoint[npt];
4760
4761 for (i = 0; i < npt; i++) {
4762 ipt[i].fX += ppt[i].fX;
4763 ipt[i].fY += ppt[i].fY;
4764 }
4765 }
4766 int x, y;
4767
4768 for (i = 0; i < npt; i++) {
4769 x = ipt ? ipt[i].fX : ppt[i].fX;
4770 y = ipt ? ipt[i].fY : ppt[i].fY;
4771
4772 if ((x < 0) || (y < 0) || (x >= (int)fImage->width) || (y >= (int)fImage->height)) {
4773 continue;
4774 }
4775 _alphaBlend(&fImage->alt.argb32[Idx(y*fImage->width + x)], &color);
4776 }
4777
4778 if (ipt) {
4779 delete [] ipt;
4780 }
4781}
4782
4783////////////////////////////////////////////////////////////////////////////////
4784/// Draw segments.
4785
4786void TASImage::DrawSegments(UInt_t nseg, Segment_t *seg, const char *col, UInt_t thick)
4787{
4788 if (!nseg || !seg) {
4789 Warning("DrawSegments", "Invalid data nseg=%d seg=0x%lx", nseg, (Long_t)seg);
4790 return;
4791 }
4792
4793 TPoint pt[2];
4794
4795 for (UInt_t i = 0; i < nseg; i++) {
4796 pt[0].fX = seg->fX1;
4797 pt[1].fX = seg->fX2;
4798 pt[0].fY = seg->fY1;
4799 pt[1].fY = seg->fY2;
4800
4801 DrawPolyLine(2, pt, col, thick, kCoordModeOrigin);
4802 seg++;
4803 }
4804}
4805
4806////////////////////////////////////////////////////////////////////////////////
4807/// Fill spans with specified color or/and stipple.
4808
4809void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, const char *col,
4810 const char *stipple, UInt_t w, UInt_t h)
4811{
4812 if (!InitVisual()) {
4813 Warning("FillSpans", "Visual not initiated");
4814 return;
4815 }
4816
4817 if (!fImage) {
4818 Warning("FillSpans", "no image");
4819 return;
4820 }
4821
4822 if (!fImage->alt.argb32) {
4823 BeginPaint();
4824 }
4825
4826 if (!fImage->alt.argb32) {
4827 Warning("FillSpans", "Failed to get pixel array");
4828 return;
4829 }
4830
4831 if (!npt || !ppt || !widths || (stipple && (!w || !h))) {
4832 Warning("FillSpans", "Invalid input data npt=%d ppt=0x%lx col=%s widths=0x%lx stipple=0x%lx w=%d h=%d",
4833 npt, (Long_t)ppt, col, (Long_t)widths, (Long_t)stipple, w, h);
4834 return;
4835 }
4836
4837 ARGB32 color;
4838 parse_argb_color(col, &color);
4839 Int_t idx = 0;
4840 UInt_t x = 0;
4841 UInt_t yy;
4842
4843 for (UInt_t i = 0; i < npt; i++) {
4844 yy = ppt[i].fY*fImage->width;
4845 for (UInt_t j = 0; j < widths[i]; j++) {
4846 if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
4847 (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0)) continue;
4848
4849 x = ppt[i].fX + j;
4850 idx = Idx(yy + x);
4851
4852 if (!stipple) {
4853 _alphaBlend(&fImage->alt.argb32[idx], &color);
4854 } else {
4855 Int_t ii = (ppt[i].fY%h)*w + x%w;
4856
4857 if (stipple[ii >> 3] & (1 << (ii%8))) {
4858 _alphaBlend(&fImage->alt.argb32[idx], &color);
4859 }
4860 }
4861 }
4862 }
4863}
4864
4865////////////////////////////////////////////////////////////////////////////////
4866/// Fill spans with tile image.
4867
4868void TASImage::FillSpans(UInt_t npt, TPoint *ppt, UInt_t *widths, TImage *tile)
4869{
4870 if (!InitVisual()) {
4871 Warning("FillSpans", "Visual not initiated");
4872 return;
4873 }
4874
4875 if (!fImage) {
4876 Warning("FillSpans", "no image");
4877 return;
4878 }
4879
4880 if (!fImage->alt.argb32) {
4881 BeginPaint();
4882 }
4883
4884 if (!fImage->alt.argb32) {
4885 Warning("FillSpans", "Failed to get pixel array");
4886 return;
4887 }
4888
4889 if (!npt || !ppt || !widths || !tile) {
4890 Warning("FillSpans", "Invalid input data npt=%d ppt=0x%lx widths=0x%lx tile=0x%lx",
4891 npt, (Long_t)ppt, (Long_t)widths, (Long_t)tile);
4892 return;
4893 }
4894
4895 Int_t idx = 0;
4896 Int_t ii = 0;
4897 UInt_t x = 0;
4898 UInt_t *arr = tile->GetArgbArray();
4899 if (!arr) return;
4900 UInt_t xx = 0;
4901 UInt_t yy = 0;
4902 UInt_t yyy = 0;
4903
4904 for (UInt_t i = 0; i < npt; i++) {
4905 yyy = ppt[i].fY*fImage->width;
4906
4907 for (UInt_t j = 0; j < widths[i]; j++) {
4908 if ((ppt[i].fX >= (Int_t)fImage->width) || (ppt[i].fX < 0) ||
4909 (ppt[i].fY >= (Int_t)fImage->height) || (ppt[i].fY < 0)) continue;
4910 x = ppt[i].fX + j;
4911 idx = Idx(yyy + x);
4912 xx = x%tile->GetWidth();
4913 yy = ppt[i].fY%tile->GetHeight();
4914 ii = yy*tile->GetWidth() + xx;
4915 _alphaBlend(&fImage->alt.argb32[idx], &arr[ii]);
4916 }
4917 yyy += fImage->width;;
4918 }
4919}
4920
4921////////////////////////////////////////////////////////////////////////////////
4922/// Crop spans.
4923
4924void TASImage::CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths)
4925{
4926 if (!InitVisual()) {
4927 Warning("CropSpans", "Visual not initiated");
4928 return;
4929 }
4930
4931 if (!fImage) {
4932 Warning("CropSpans", "no image");
4933 return;
4934 }
4935
4936 if (!fImage->alt.argb32) {
4937 BeginPaint();
4938 }
4939
4940 if (!fImage->alt.argb32) {
4941 Warning("CropSpans", "Failed to get pixel array");
4942 return;
4943 }
4944
4945 if (!npt || !ppt || !widths) {
4946 Warning("CropSpans", "No points specified npt=%d ppt=0x%lx widths=0x%lx", npt, (Long_t)ppt, (Long_t)widths);
4947 return;
4948 }
4949
4950 int y0 = ppt[0].fY;
4951 int y1 = ppt[npt-1].fY;
4952 UInt_t y = 0;
4953 UInt_t x = 0;
4954 UInt_t i = 0;
4955 UInt_t idx = 0;
4956 UInt_t sz = fImage->width*fImage->height;
4957 UInt_t yy = y*fImage->width;
4958
4959 for (y = 0; (int)y < y0; y++) {
4960 for (x = 0; x < fImage->width; x++) {
4961 idx = Idx(yy + x);
4962 if (idx < sz) fImage->alt.argb32[idx] = 0;
4963 }
4964 yy += fImage->width;
4965 }
4966
4967 for (i = 0; i < npt; i++) {
4968 for (x = 0; (int)x < ppt[i].fX; x++) {
4969 idx = Idx(ppt[i].fY*fImage->width + x);
4970 if (idx < sz) fImage->alt.argb32[idx] = 0;
4971 }
4972 for (x = ppt[i].fX + widths[i] + 1; x < fImage->width; x++) {
4973 idx = Idx(ppt[i].fY*fImage->width + x);
4974 if (idx < sz) fImage->alt.argb32[idx] = 0;
4975 }
4976 }
4977
4978 yy = y1*fImage->width;
4979 for (y = y1; y < fImage->height; y++) {
4980 for (x = 0; x < fImage->width; x++) {
4981 idx = Idx(yy + x);
4982 if (idx < sz) fImage->alt.argb32[idx] = 0;
4983 }
4984 yy += fImage->width;
4985 }
4986}
4987
4988////////////////////////////////////////////////////////////////////////////////
4989/// Copy source region to the destination image. Copy is done according
4990/// to specified function:
4991/// ~~~ {.cpp}
4992/// enum EGraphicsFunction {
4993/// kGXclear = 0, // 0
4994/// kGXand, // src AND dst
4995/// kGXandReverse, // src AND NOT dst
4996/// kGXcopy, // src (default)
4997/// kGXandInverted, // NOT src AND dst
4998/// kGXnoop, // dst
4999/// kGXxor, // src XOR dst
5000/// kGXor, // src OR dst
5001/// kGXnor, // NOT src AND NOT dst
5002/// kGXequiv, // NOT src XOR dst
5003/// kGXinvert, // NOT dst
5004/// kGXorReverse, // src OR NOT dst
5005/// kGXcopyInverted, // NOT src
5006/// kGXorInverted, // NOT src OR dst
5007/// kGXnand, // NOT src OR NOT dst
5008/// kGXset // 1
5009/// };
5010/// ~~~
5011
5013 Int_t xdst, Int_t ydst, Int_t gfunc, EColorChan)
5014{
5015 if (!InitVisual()) {
5016 Warning("CopyArea", "Visual not initiated");
5017 return;
5018 }
5019
5020 if (!fImage) {
5021 Warning("CopyArea", "no image");
5022 return;
5023 }
5024 if (!dst) return;
5025
5026 ASImage *out = ((TASImage*)dst)->GetImage();
5027
5028 int x = 0;
5029 int y = 0;
5030 int idx = 0;
5031 int idx2 = 0;
5032 xsrc = xsrc < 0 ? 0 : xsrc;
5033 ysrc = ysrc < 0 ? 0 : ysrc;
5034
5035 if ((xsrc >= (int)fImage->width) || (ysrc >= (int)fImage->height)) return;
5036
5037 w = xsrc + w > fImage->width ? fImage->width - xsrc : w;
5038 h = ysrc + h > fImage->height ? fImage->height - ysrc : h;
5039 UInt_t yy = (ysrc + y)*fImage->width;
5040
5041 if (!fImage->alt.argb32) {
5042 BeginPaint();
5043 }
5044 if (!out->alt.argb32) {
5045 dst->BeginPaint();
5046 out = ((TASImage*)dst)->GetImage();
5047 }
5048
5049 if (fImage->alt.argb32 && out->alt.argb32) {
5050 for (y = 0; y < (int)h; y++) {
5051 for (x = 0; x < (int)w; x++) {
5052 idx = Idx(yy + x + xsrc);
5053 if ((x + xdst < 0) || (ydst + y < 0) ||
5054 (x + xdst >= (int)out->width) || (y + ydst >= (int)out->height) ) continue;
5055
5056 idx2 = Idx((ydst + y)*out->width + x + xdst);
5057
5058 switch ((EGraphicsFunction)gfunc) {
5059 case kGXclear:
5060 out->alt.argb32[idx2] = 0;
5061 break;
5062 case kGXand:
5063 out->alt.argb32[idx2] &= fImage->alt.argb32[idx];
5064 break;
5065 case kGXandReverse:
5066 out->alt.argb32[idx2] = fImage->alt.argb32[idx] & (~out->alt.argb32[idx2]);
5067 break;
5068 case kGXandInverted:
5069 out->alt.argb32[idx2] &= ~fImage->alt.argb32[idx];
5070 break;
5071 case kGXnoop:
5072 break;
5073 case kGXxor:
5074 out->alt.argb32[idx2] ^= fImage->alt.argb32[idx];
5075 break;
5076 case kGXor:
5077 out->alt.argb32[idx2] |= fImage->alt.argb32[idx];
5078 break;
5079 case kGXnor:
5080 out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) & (~out->alt.argb32[idx2]);
5081 break;
5082 case kGXequiv:
5083 out->alt.argb32[idx2] ^= ~fImage->alt.argb32[idx];
5084 break;
5085 case kGXinvert:
5086 out->alt.argb32[idx2] = ~out->alt.argb32[idx2];
5087 break;
5088 case kGXorReverse:
5089 out->alt.argb32[idx2] = fImage->alt.argb32[idx] | (~out->alt.argb32[idx2]);
5090 break;
5091 case kGXcopyInverted:
5092 out->alt.argb32[idx2] = ~fImage->alt.argb32[idx];
5093 break;
5094 case kGXorInverted:
5095 out->alt.argb32[idx2] |= ~fImage->alt.argb32[idx];
5096 break;
5097 case kGXnand:
5098 out->alt.argb32[idx2] = (~fImage->alt.argb32[idx]) | (~out->alt.argb32[idx2]);
5099 break;
5100 case kGXset:
5101 out->alt.argb32[idx2] = 0xFFFFFFFF;
5102 break;
5103 case kGXcopy:
5104 default:
5105 out->alt.argb32[idx2] = fImage->alt.argb32[idx];
5106 break;
5107 }
5108 }
5109 yy += fImage->width;
5110 }
5111 }
5112}
5113
5114////////////////////////////////////////////////////////////////////////////////
5115/// Draw a cell array.
5116///
5117/// \param[in] x1,y1 : left down corner
5118/// \param[in] x2,y2 : right up corner
5119/// \param[in] nx,ny : array size
5120/// \param[in] ic : array of ARGB32 colors
5121///
5122/// Draw a cell array. The drawing is done with the pixel precision
5123/// if (X2-X1)/NX (or Y) is not a exact pixel number the position of
5124/// the top right corner may be wrong.
5125
5127 Int_t ny, UInt_t *ic)
5128{
5129 int i, j, ix, iy, w, h;
5130
5131 ARGB32 color = 0xFFFFFFFF;
5132 ARGB32 icol;
5133
5134 w = TMath::Max((x2-x1)/(nx),1);
5135 h = TMath::Max((y1-y2)/(ny),1);
5136 ix = x1;
5137
5138 for (i = 0; i < nx; i++) {
5139 iy = y1 - h;
5140 for (j = 0; j < ny; j++) {
5141 icol = (ARGB32)ic[i + (nx*j)];
5142 if (icol != color) {
5143 color = icol;
5144 }
5145 FillRectangleInternal((UInt_t)color, ix, iy, w, h);
5146 iy = iy - h;
5147 }
5148 ix = ix + w;
5149 }
5150}
5151
5152////////////////////////////////////////////////////////////////////////////////
5153/// Return alpha-blended value computed from bottom and top pixel values.
5154
5156{
5157 UInt_t ret = bot;
5158
5159 _alphaBlend(&ret, &top);
5160 return ret;
5161}
5162
5163////////////////////////////////////////////////////////////////////////////////
5164/// Return visual.
5165
5166const ASVisual *TASImage::GetVisual()
5167{
5168 return fgVisual;
5169}
5170
5171////////////////////////////////////////////////////////////////////////////////
5172/// Get poly bounds along Y.
5173
5174static int GetPolyYBounds(TPoint *pts, int n, int *by, int *ty)
5175{
5176 TPoint *ptMin;
5177 int ymin, ymax;
5178 TPoint *ptsStart = pts;
5179
5180 ptMin = pts;
5181 ymin = ymax = (pts++)->fY;
5182
5183 while (--n > 0) {
5184 if (pts->fY < ymin) {
5185 ptMin = pts;
5186 ymin = pts->fY;
5187 }
5188 if (pts->fY > ymax) {
5189 ymax = pts->fY;
5190 }
5191 pts++;
5192 }
5193
5194 *by = ymin;
5195 *ty = ymax;
5196 return (ptMin - ptsStart);
5197}
5198
5199////////////////////////////////////////////////////////////////////////////////
5200/// The code is based on Xserver/mi/mipolycon.c
5201/// "Copyright 1987, 1998 The Open Group"
5202
5204 TPoint **outPoint, UInt_t **outWidth)
5205{
5206 int xl = 0; // x vals of leftedges
5207 int xr = 0; // x vals of right edges
5208 int dl = 0; // decision variables
5209 int dr = 0; // decision variables
5210 int ml = 0; // left edge slope
5211 int m1l = 0; // left edge slope+1
5212 int mr = 0, m1r = 0; // right edge slope and slope+1
5213 int incr1l = 0, incr2l = 0; // left edge error increments
5214 int incr1r = 0, incr2r = 0; // right edge error increments
5215 int dy; // delta y
5216 int y; // current scanline
5217 int left, right; // indices to first endpoints
5218 int i; // loop counter
5219 int nextleft, nextright; // indices to second endpoints
5220 TPoint *ptsOut; // output buffer
5221 UInt_t *width; // output buffer
5222 TPoint *firstPoint=0;
5223 UInt_t *firstWidth=0;
5224 int imin; // index of smallest vertex (in y)
5225 int ymin; // y-extents of polygon
5226 int ymax;
5227 Bool_t ret = kTRUE;
5228
5229 *nspans = 0;
5230
5231 if (!InitVisual()) {
5232 Warning("GetPolygonSpans", "Visual not initiated");
5233 return kFALSE;
5234 }
5235
5236 if (!fImage) {
5237 Warning("GetPolygonSpans", "no image");
5238 return kFALSE;
5239 }
5240
5241 if (!fImage->alt.argb32) {
5242 BeginPaint();
5243 }
5244
5245 if (!fImage->alt.argb32) {
5246 Warning("GetPolygonSpans", "Failed to get pixel array");
5247 return kFALSE;
5248 }
5249
5250 if ((npt < 3) || !ppt) {
5251 Warning("GetPolygonSpans", "No points specified npt=%d ppt=0x%lx", npt, (Long_t)ppt);
5252 return kFALSE;
5253 }
5254
5255 // find leftx, bottomy, rightx, topy, and the index
5256 // of bottomy. Also translate the points.
5257 imin = GetPolyYBounds(ppt, npt, &ymin, &ymax);
5258
5259 dy = ymax - ymin + 1;
5260 if ((npt < 3) || (dy < 0)) return kFALSE;
5261
5262 ptsOut = firstPoint = new TPoint[dy];
5263 width = firstWidth = new UInt_t[dy];
5264 ret = kTRUE;
5265
5266 nextleft = nextright = imin;
5267 y = ppt[nextleft].fY;
5268
5269 // loop through all edges of the polygon
5270 do {
5271 // add a left edge if we need to
5272 if (ppt[nextleft].fY == y) {
5273 left = nextleft;
5274
5275 // find the next edge, considering the end
5276 // conditions of the array.
5277 nextleft++;
5278 if (nextleft >= (int)npt) {
5279 nextleft = 0;
5280 }
5281
5282 // now compute all of the random information
5283 // needed to run the iterative algorithm.
5284 BRESINITPGON(ppt[nextleft].fY - ppt[left].fY,
5285 ppt[left].fX, ppt[nextleft].fX,
5286 xl, dl, ml, m1l, incr1l, incr2l);
5287 }
5288
5289 // add a right edge if we need to
5290 if (ppt[nextright].fY == y) {
5291 right = nextright;
5292
5293 // find the next edge, considering the end
5294 // conditions of the array.
5295 nextright--;
5296 if (nextright < 0) {
5297 nextright = npt-1;
5298 }
5299
5300 // now compute all of the random information
5301 // needed to run the iterative algorithm.
5302 BRESINITPGON(ppt[nextright].fY - ppt[right].fY,
5303 ppt[right].fX, ppt[nextright].fX,
5304 xr, dr, mr, m1r, incr1r, incr2r);
5305 }
5306
5307 // generate scans to fill while we still have
5308 // a right edge as well as a left edge.
5309 i = TMath::Min(ppt[nextleft].fY, ppt[nextright].fY) - y;
5310
5311 // in case of non-convex polygon
5312 if (i < 0) {
5313 delete [] firstWidth;
5314 delete [] firstPoint;
5315 return kTRUE;
5316 }
5317
5318 while (i-- > 0) {
5319 ptsOut->fY = y;
5320
5321 // reverse the edges if necessary
5322 if (xl < xr) {
5323 *(width++) = xr - xl;
5324 (ptsOut++)->fX = xl;
5325 } else {
5326 *(width++) = xl - xr;
5327 (ptsOut++)->fX = xr;
5328 }
5329 y++;
5330
5331 // increment down the edges
5332 BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l);
5333 BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r);
5334 }
5335 } while (y != ymax);
5336
5337 *nspans = UInt_t(ptsOut - firstPoint);
5338 *outPoint = firstPoint;
5339 *outWidth = firstWidth;
5340
5341 return ret;
5342}
5343
5344////////////////////////////////////////////////////////////////////////////////
5345/// Fill a convex polygon with background color or bitmap.
5346/// For non convex polygon one must use DrawFillArea method
5347
5348void TASImage::FillPolygon(UInt_t npt, TPoint *ppt, const char *col,
5349 const char *stipple, UInt_t w, UInt_t h)
5350{
5351 UInt_t nspans = 0;
5352 TPoint *firstPoint = 0; // output buffer
5353 UInt_t *firstWidth = 0; // output buffer
5354
5355 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5356 ARGB32 color = ARGB32_White;
5357 parse_argb_color(col, &color);
5358
5359 if (nspans) {
5360 if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple no alpha
5361 FillSpansInternal(nspans, firstPoint, firstWidth, color);
5362 } else {
5363 FillSpans(nspans, firstPoint, firstWidth, col, stipple, w, h);
5364 }
5365
5366 if (del) {
5367 delete [] firstWidth;
5368 delete [] firstPoint;
5369 }
5370 } else {
5371 if (firstWidth) delete [] firstWidth;
5372 if (firstPoint) delete [] firstPoint;
5373 }
5374}
5375
5376////////////////////////////////////////////////////////////////////////////////
5377/// Fill a convex polygon with background image.
5378/// For non convex polygon one must use DrawFillArea method
5379
5381{
5382 UInt_t nspans = 0;
5383 TPoint *firstPoint = 0; // output buffer
5384 UInt_t *firstWidth = 0; // output buffer
5385
5386 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5387
5388 if (nspans) {
5389 FillSpans(nspans, firstPoint, firstWidth, tile);
5390
5391 if (del) {
5392 delete [] firstWidth;
5393 delete [] firstPoint;
5394 }
5395 } else {
5396 if (firstWidth) delete [] firstWidth;
5397 if (firstPoint) delete [] firstPoint;
5398 }
5399}
5400
5401////////////////////////////////////////////////////////////////////////////////
5402/// Crop a convex polygon.
5403
5405{
5406 UInt_t nspans = 0;
5407 TPoint *firstPoint = 0;
5408 UInt_t *firstWidth = 0;
5409
5410 Bool_t del = GetPolygonSpans(npt, ppt, &nspans, &firstPoint, &firstWidth);
5411
5412 if (nspans) {
5413 CropSpans(nspans, firstPoint, firstWidth);
5414
5415 if (del) {
5416 delete [] firstWidth;
5417 delete [] firstPoint;
5418 }
5419 } else {
5420 if (firstWidth) delete [] firstWidth;
5421 if (firstPoint) delete [] firstPoint;
5422 }
5423}
5424
5425static const UInt_t NUMPTSTOBUFFER = 512;
5426
5427////////////////////////////////////////////////////////////////////////////////
5428/// Fill a polygon (any type convex, non-convex).
5429
5430void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, const char *col,
5431 const char *stipple, UInt_t w, UInt_t h)
5432{
5433 if (!InitVisual()) {
5434 Warning("DrawFillArea", "Visual not initiated");
5435 return;
5436 }
5437
5438 if (!fImage) {
5439 Warning("DrawFillArea", "no image");
5440 return;
5441 }
5442
5443 if (!fImage->alt.argb32) {
5444 BeginPaint();
5445 }
5446
5447 if (!fImage->alt.argb32) {
5448 Warning("DrawFillArea", "Failed to get pixel array");
5449 return;
5450 }
5451
5452 if ((count < 3) || !ptsIn) {
5453 Warning("DrawFillArea", "No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
5454 return;
5455 }
5456
5457 if (count < 5) {
5458 FillPolygon(count, ptsIn, col, stipple, w, h);
5459 return;
5460 }
5461
5462 ARGB32 color = ARGB32_White;
5463 parse_argb_color(col, &color);
5464
5465 EdgeTableEntry *pAET; // the Active Edge Table
5466 int y; // the current scanline
5467 UInt_t nPts = 0; // number of pts in buffer
5468
5469 ScanLineList *pSLL; // Current ScanLineList
5470 TPoint *ptsOut; // ptr to output buffers
5471 UInt_t *width;
5472 TPoint firstPoint[NUMPTSTOBUFFER]; // the output buffers
5473 UInt_t firstWidth[NUMPTSTOBUFFER];
5474 EdgeTableEntry *pPrevAET; // previous AET entry
5475 EdgeTable ET; // Edge Table header node
5476 EdgeTableEntry AET; // Active ET header node
5477 EdgeTableEntry *pETEs; // Edge Table Entries buff
5478 ScanLineListBlock SLLBlock; // header for ScanLineList
5479 Bool_t del = kTRUE;
5480
5481 static const UInt_t gEdgeTableEntryCacheSize = 200;
5482 static EdgeTableEntry gEdgeTableEntryCache[gEdgeTableEntryCacheSize];
5483
5484 if (count < gEdgeTableEntryCacheSize) {
5485 pETEs = (EdgeTableEntry*)&gEdgeTableEntryCache;
5486 del = kFALSE;
5487 } else {
5488 pETEs = new EdgeTableEntry[count];
5489 del = kTRUE;
5490 }
5491
5492 ptsOut = firstPoint;
5493 width = firstWidth;
5494 CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
5495 pSLL = ET.scanlines.next;
5496
5497 for (y = ET.ymin; y < ET.ymax; y++) {
5498 if (pSLL && y == pSLL->scanline) {
5499 loadAET(&AET, pSLL->edgelist);
5500 pSLL = pSLL->next;
5501 }
5502 pPrevAET = &AET;
5503 pAET = AET.next;
5504
5505 while (pAET) {
5506 ptsOut->fX = pAET->bres.minor_axis;
5507 ptsOut->fY = y;
5508 ptsOut++;
5509 nPts++;
5510
5511 *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
5512
5513 if (nPts == NUMPTSTOBUFFER) {
5514 if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple, no alpha
5515 FillSpansInternal(nPts, firstPoint, firstWidth, color);
5516 } else {
5517 FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
5518 }
5519 ptsOut = firstPoint;
5520 width = firstWidth;
5521 nPts = 0;
5522 }
5523 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5524 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5525 }
5526 InsertionSort(&AET);
5527 }
5528
5529 if (nPts) {
5530 if (!stipple && ((color & 0xff000000)==0xff000000)) { //no stipple, no alpha
5531 FillSpansInternal(nPts, firstPoint, firstWidth, color);
5532 } else {
5533 FillSpans(nPts, firstPoint, firstWidth, col, stipple, w, h);
5534 }
5535 }
5536
5537 if (del) delete [] pETEs;
5538 FreeStorage(SLLBlock.next);
5539}
5540
5541////////////////////////////////////////////////////////////////////////////////
5542/// Fill a polygon (any type convex, non-convex).
5543
5544void TASImage::DrawFillArea(UInt_t count, TPoint *ptsIn, TImage *tile)
5545{
5546 if (!InitVisual()) {
5547 Warning("DrawFillArea", "Visual not initiated");
5548 return;
5549 }
5550
5551 if (!fImage) {
5552 Warning("DrawFillArea", "no image");
5553 return;
5554 }
5555
5556 if (!fImage->alt.argb32) {
5557 BeginPaint();
5558 }
5559
5560 if (!fImage->alt.argb32) {
5561 Warning("DrawFillArea", "Failed to get pixel array");
5562 return;
5563 }
5564
5565 if ((count < 3) || !ptsIn) {
5566 Warning("DrawFillArea", "No points specified npt=%d ppt=0x%lx", count, (Long_t)ptsIn);
5567 return;
5568 }
5569
5570 if (count < 5) {
5571 FillPolygon(count, ptsIn, tile);
5572 return;
5573 }
5574
5575 EdgeTableEntry *pAET; // the Active Edge Table
5576 int y; // the current scanline
5577 UInt_t nPts = 0; // number of pts in buffer
5578
5579 ScanLineList *pSLL; // Current ScanLineList
5580 TPoint *ptsOut; // ptr to output buffers
5581 UInt_t *width;
5582 TPoint firstPoint[NUMPTSTOBUFFER]; // the output buffers
5583 UInt_t firstWidth[NUMPTSTOBUFFER];
5584 EdgeTableEntry *pPrevAET; // previous AET entry
5585 EdgeTable ET; // Edge Table header node
5586 EdgeTableEntry AET; // Active ET header node
5587 EdgeTableEntry *pETEs; // Edge Table Entries buff
5588 ScanLineListBlock SLLBlock; // header for ScanLineList
5589
5590 pETEs = new EdgeTableEntry[count];
5591
5592 ptsOut = firstPoint;
5593 width = firstWidth;
5594 CreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock);
5595 pSLL = ET.scanlines.next;
5596
5597 for (y = ET.ymin; y < ET.ymax; y++) {
5598 if (pSLL && y == pSLL->scanline) {
5599 loadAET(&AET, pSLL->edgelist);
5600 pSLL = pSLL->next;
5601 }
5602 pPrevAET = &AET;
5603 pAET = AET.next;
5604
5605 while (pAET) {
5606 ptsOut->fX = pAET->bres.minor_axis;
5607 ptsOut->fY = y;
5608 ptsOut++;
5609 nPts++;
5610
5611 *width++ = pAET->next->bres.minor_axis - pAET->bres.minor_axis;
5612
5613 if (nPts == NUMPTSTOBUFFER) {
5614 FillSpans(nPts, firstPoint, firstWidth, tile);
5615 ptsOut = firstPoint;
5616 width = firstWidth;
5617 nPts = 0;
5618 }
5619 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5620 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
5621 }
5622 InsertionSort(&AET);
5623 }
5624 FillSpans(nPts, firstPoint, firstWidth, tile);
5625
5626 delete [] pETEs;
5627 FreeStorage(SLLBlock.next);
5628}
5629
5630////////////////////////////////////////////////////////////////////////////////
5631/// Create draw context.
5632
5633static ASDrawContext *create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
5634{
5635 ASDrawContext *ctx = new ASDrawContext;
5636
5637 ctx->canvas_width = im->width;
5638 ctx->canvas_height = im->height;
5639 ctx->canvas = im->alt.argb32;
5640 ctx->scratch_canvas = 0;
5641
5642 ctx->flags = ASDrawCTX_CanvasIsARGB;
5643 asim_set_custom_brush_colored( ctx, brush);
5644 return ctx;
5645}
5646
5647////////////////////////////////////////////////////////////////////////////////
5648/// Destroy asdraw context32.
5649
5650static void destroy_asdraw_context32( ASDrawContext *ctx )
5651{
5652 if (ctx) {
5653 if (ctx->scratch_canvas) free(ctx->scratch_canvas);
5654 delete ctx;
5655 }
5656}
5657
5658static const UInt_t kBrushCacheSize = 20;
5660
5661////////////////////////////////////////////////////////////////////////////////
5662/// Draw wide line.
5663
5665 UInt_t color, UInt_t thick)
5666{
5667 Int_t sz = thick*thick;
5668 CARD32 *matrix;
5669 Bool_t use_cache = thick < kBrushCacheSize;
5670
5671 if (use_cache) {
5672 matrix = gBrushCache;
5673 } else {
5674 matrix = new CARD32[sz];
5675 }
5676
5677 for (int i = 0; i < sz; i++) {
5678 matrix[i] = (CARD32)color;
5679 };
5680
5681 ASDrawTool brush;
5682 brush.matrix = matrix;
5683 brush.width = thick;
5684 brush.height = thick;
5685 brush.center_y = brush.center_x = thick/2;
5686
5687 // When the first or last point of a wide line is exactly on the
5688 // window limit the line is drawn vertically or horizontally.
5689 // see https://sft.its.cern.ch/jira/browse/ROOT-8021
5690 UInt_t xx1 = x1;
5691 UInt_t yy1 = y1;
5692 UInt_t xx2 = x2;
5693 UInt_t yy2 = y2;
5694 if (xx1 == fImage->width) --xx1;
5695 if (yy1 == fImage->height) --yy1;
5696 if (xx2 == fImage->width) --xx2;
5697 if (yy2 == fImage->height) --yy2;
5698 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
5699 asim_move_to(ctx, xx1, yy1);
5700 asim_line_to(ctx, xx2, yy2);
5701
5702 if (!use_cache) {
5703 delete [] matrix;
5704 }
5706}
5707
5708////////////////////////////////////////////////////////////////////////////////
5709/// Draw glyph bitmap.
5710
5711void TASImage::DrawGlyph(void *bitmap, UInt_t color, Int_t bx, Int_t by)
5712{
5713 static UInt_t col[5];
5714 Int_t x, y, yy, y0, xx;
5715 Bool_t has_alpha = (color & 0xff000000) != 0xff000000;
5716
5717 ULong_t r, g, b;
5718 int idx = 0;
5719 FT_Bitmap *source = (FT_Bitmap*)bitmap;
5720 UChar_t d = 0, *s = source->buffer;
5721
5722 Int_t dots = Int_t(source->width * source->rows);
5723 r = g = b = 0;
5724 Int_t bxx, byy;
5725
5726 yy = y0 = by > 0 ? by * fImage->width : 0;
5727 for (y = 0; y < (int) source->rows; y++) {
5728 byy = by + y;
5729 if ((byy >= (int)fImage->height) || (byy <0)) continue;
5730
5731 for (x = 0; x < (int) source->width; x++) {
5732 bxx = bx + x;
5733 if ((bxx >= (int)fImage->width) || (bxx < 0)) continue;
5734
5735 idx = Idx(bxx + yy);
5736 r += ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
5737 g += ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
5738 b += (fImage->alt.argb32[idx] & 0x0000ff);
5739 }
5740 yy += fImage->width;
5741 }
5742 if (dots != 0) {
5743 r /= dots;
5744 g /= dots;
5745 b /= dots;
5746 }
5747
5748 col[0] = (r << 16) + (g << 8) + b;
5749 col[4] = color;
5750 Int_t col4r = (col[4] & 0xff0000) >> 16;
5751 Int_t col4g = (col[4] & 0x00ff00) >> 8;
5752 Int_t col4b = (col[4] & 0x0000ff);
5753
5754 // interpolate between fore and background colors
5755 for (x = 3; x > 0; x--) {
5756 xx = 4-x;
5757 Int_t colxr = (col4r*x + r*xx) >> 2;
5758 Int_t colxg = (col4g*x + g*xx) >> 2;
5759 Int_t colxb = (col4b*x + b*xx) >> 2;
5760 col[x] = (colxr << 16) + (colxg << 8) + colxb;
5761 }
5762
5763 yy = y0;
5764 ARGB32 acolor;
5765
5766 Int_t clipx1=0, clipx2=0, clipy1=0, clipy2=0;
5767 Bool_t noClip = kTRUE;
5768
5769 if (gPad) {
5771 clipx1 = gPad->XtoAbsPixel(gPad->GetX1())*is;
5772 clipx2 = gPad->XtoAbsPixel(gPad->GetX2())*is;
5773 clipy1 = gPad->YtoAbsPixel(gPad->GetY1())*is;
5774 clipy2 = gPad->YtoAbsPixel(gPad->GetY2())*is;
5775 noClip = kFALSE;
5776 }
5777
5778 for (y = 0; y < (int) source->rows; y++) {
5779 byy = by + y;
5780
5781 for (x = 0; x < (int) source->width; x++) {
5782 bxx = bx + x;
5783
5784 d = *s++ & 0xff;
5785 d = ((d + 10) * 5) >> 8;
5786 if (d > 4) d = 4;
5787
5788 if (d) {
5789 if ( noClip || ((x < (int) source->width) &&
5790 (bxx < (int)clipx2) && (bxx >= (int)clipx1) &&
5791 (byy >= (int)clipy2) && (byy < (int)clipy1) )) {
5792 idx = Idx(bxx + yy);
5793 acolor = (ARGB32)col[d];
5794 if (has_alpha) {
5795 _alphaBlend(&fImage->alt.argb32[idx], &acolor);
5796 } else {
5797 fImage->alt.argb32[idx] = acolor;
5798 }
5799 }
5800 }
5801 }
5802 yy += fImage->width;
5803 }
5804}
5805
5806////////////////////////////////////////////////////////////////////////////////
5807/// Draw text at the pixel position (x,y).
5808
5810{
5811 if (!text) return;
5812 if (!fImage) return;
5813 if (!gPad) return;
5814
5815 if (!InitVisual()) {
5816 Warning("DrawText", "Visual not initiated");
5817 return;
5818 }
5819
5820 if (!fImage->alt.argb32) {
5821 BeginPaint();
5822 }
5823
5824 if (!TTF::IsInitialized()) TTF::Init();
5825
5826 // set text font
5828
5829 Int_t wh = gPad->XtoPixel(gPad->GetX2());
5830 Int_t hh = gPad->YtoPixel(gPad->GetY1());
5831
5832 // set text size
5833 Float_t ttfsize;
5834 if (wh < hh) {
5835 ttfsize = text->GetTextSize()*wh;
5836 } else {
5837 ttfsize = text->GetTextSize()*hh;
5838 }
5839 TTF::SetTextSize(ttfsize*kScale);
5840
5841 // set text angle
5843
5844 // set text
5845 const wchar_t *wcsTitle = reinterpret_cast<const wchar_t *>(text->GetWcsTitle());
5846 if (wcsTitle != NULL) {
5847 TTF::PrepareString(wcsTitle);
5848 } else {
5850 }
5852
5853 // color
5854 TColor *col = gROOT->GetColor(text->GetTextColor());
5855 if (!col) { // no color, make it black
5856 col = gROOT->GetColor(1);
5857 if (!col) return;
5858 }
5859 ARGB32 color = ARGB32_White;
5860 parse_argb_color(col->AsHexString(), &color);
5861
5862 // Align()
5863 Int_t align = 0;
5864 Int_t txalh = text->GetTextAlign()/10;
5865 Int_t txalv = text->GetTextAlign()%10;
5866
5867 switch (txalh) {
5868 case 0 :
5869 case 1 :
5870 switch (txalv) { //left
5871 case 1 :
5872 align = 7; //bottom
5873 break;
5874 case 2 :
5875 align = 4; //center
5876 break;
5877 case 3 :
5878 align = 1; //top
5879 break;
5880 }
5881 break;
5882 case 2 :
5883 switch (txalv) { //center
5884 case 1 :
5885 align = 8; //bottom
5886 break;
5887 case 2 :
5888 align = 5; //center
5889 break;
5890 case 3 :
5891 align = 2; //top
5892 break;
5893 }
5894 break;
5895 case 3 :
5896 switch (txalv) { //right
5897 case 1 :
5898 align = 9; //bottom
5899 break;
5900 case 2 :
5901 align = 6; //center
5902 break;
5903 case 3 :
5904 align = 3; //top
5905 break;
5906 }
5907 break;
5908 }
5909
5910 FT_Vector ftal;
5911
5912 // vertical alignment
5913 if (align == 1 || align == 2 || align == 3) {
5914 ftal.y = TTF::GetAscent();
5915 } else if (align == 4 || align == 5 || align == 6) {
5916 ftal.y = TTF::GetAscent()/2;
5917 } else {
5918 ftal.y = 0;
5919 }
5920
5921 // horizontal alignment
5922 if (align == 3 || align == 6 || align == 9) {
5923 ftal.x = TTF::GetWidth();
5924 } else if (align == 2 || align == 5 || align == 8) {
5925 ftal.x = TTF::GetWidth()/2;
5926 } else {
5927 ftal.x = 0;
5928 }
5929
5930 FT_Vector_Transform(&ftal, TTF::GetRotMatrix());
5931 ftal.x = (ftal.x >> 6);
5932 ftal.y = (ftal.y >> 6);
5933
5934 TTF::TTGlyph *glyph = TTF::GetGlyphs();
5935
5936 for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
5937 if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 )) continue;
5938
5939 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
5940 FT_Bitmap *source = &bitmap->bitmap;
5941
5942 Int_t bx = x - ftal.x + bitmap->left;
5943 Int_t by = y + ftal.y - bitmap->top;
5944
5945 DrawGlyph(source, color, bx, by);
5946 }
5947}
5948
5949////////////////////////////////////////////////////////////////////////////////
5950/// Draw text using TrueType fonts.
5951
5952void TASImage::DrawTextTTF(Int_t x, Int_t y, const char *text, Int_t size,
5953 UInt_t color, const char *font_name, Float_t angle)
5954{
5955 if (!TTF::IsInitialized()) TTF::Init();
5956
5957 TTF::SetTextFont(font_name);
5958 TTF::SetTextSize(size);
5962
5963 TTF::TTGlyph *glyph = TTF::GetGlyphs();
5964
5965 // compute the size and position that will contain the text
5966 // Int_t Xoff = 0; if (TTF::GetBox().xMin < 0) Xoff = -TTF::GetBox().xMin;
5967 Int_t Yoff = 0; if (TTF::GetBox().yMin < 0) Yoff = -TTF::GetBox().yMin;
5968 Int_t h = TTF::GetBox().yMax + Yoff;
5969
5970 for (int n = 0; n < TTF::GetNumGlyphs(); n++, glyph++) {
5971 if (FT_Glyph_To_Bitmap(&glyph->fImage, ft_render_mode_normal, 0, 1 )) continue;
5972
5973 FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph->fImage;
5974 FT_Bitmap *source = &bitmap->bitmap;
5975
5976 Int_t bx = x + bitmap->left;
5977 Int_t by = y + h - bitmap->top;
5978 DrawGlyph(source, color, bx, by);
5979 }
5980}
5981
5982////////////////////////////////////////////////////////////////////////////////
5983/// Return in-memory buffer compressed according image type.
5984/// Buffer must be deallocated after usage.
5985/// This method can be used for sending images over network.
5986
5987void TASImage::GetImageBuffer(char **buffer, int *size, EImageFileTypes type)
5988{
5989 static ASImageExportParams params;
5990 Bool_t ret = kFALSE;
5991 int isize = 0;
5992 char *ibuff = 0;
5993 ASImage *img = fScaledImage ? fScaledImage->fImage : fImage;
5994
5995 if (!img) return;
5996
5997 switch (type) {
5998 case TImage::kXpm:
5999 ret = ASImage2xpmRawBuff(img, (CARD8 **)buffer, size, 0);
6000 break;
6001 default:
6002 ret = ASImage2PNGBuff(img, (CARD8 **)buffer, size, &params);
6003 }
6004
6005 if (!ret) {
6006 *size = isize;
6007 *buffer = ibuff;
6008 }
6009}
6010
6011////////////////////////////////////////////////////////////////////////////////
6012/// Create image from compressed buffer.
6013/// Supported formats:
6014///
6015/// - PNG - by default
6016/// - XPM - two options exist:
6017/// 1. xpm as a single string (raw buffer). Such string
6018/// is returned by GetImageBuffer method.
6019/// For example:
6020/// ~~~ {.cpp}
6021/// char *buf;
6022/// int sz;
6023/// im1->GetImageBuffer(&buf, &int, TImage::kXpm); /*raw buffer*/
6024/// TImage *im2 = TImage::Create();
6025/// im2->SetImageBuffer(&buf, TImage::kXpm);
6026/// ~~~
6027/// 2. xpm as an array of strings (pre-parsed)
6028/// ~~~ {.cpp}
6029/// For example:
6030/// char *xpm[] = {
6031/// "64 28 58 1",
6032/// " c #0A030C",
6033/// ". c #1C171B"
6034/// ...
6035/// TImage *im = TImage::Create();
6036/// im->SetImageBuffer(xpm, TImage::kXpm);
6037/// ~~~
6038
6040{
6041 DestroyImage();
6042
6043 static ASImageImportParams params;
6044 params.flags = 0;
6045 params.width = 0;
6046 params.height = 0 ;
6047 params.filter = SCL_DO_ALL;
6048 params.gamma = 0;
6049 params.gamma_table = 0;
6050 params.compression = 0;
6051 params.format = ASA_ASImage;
6052 params.search_path = 0;
6053 params.subimage = 0;
6054
6055 switch (type) {
6056 case TImage::kXpm:
6057 {
6058 char *ptr = buffer[0];
6059 while (isspace((int)*ptr)) ++ptr;
6060 if (atoi(ptr)) { // pre-parsed and preloaded data
6061 fImage = xpm_data2ASImage((const char**)buffer, &params);
6062 } else {
6063 fImage = xpmRawBuff2ASImage((const char*)*buffer, &params);
6064 }
6065 break;
6066 }
6067 default:
6068 fImage = PNGBuff2ASimage((CARD8 *)*buffer, &params);
6069 break;
6070 }
6071
6072 if (!fImage) {
6073 return kFALSE;
6074 }
6075
6076 if (fName.IsNull()) {
6077 fName.Form("img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
6078 }
6079 UnZoom();
6080 return kTRUE;
6081}
6082
6083////////////////////////////////////////////////////////////////////////////////
6084/// Create image thumbnail.
6085
6087{
6088 int size;
6089 const int sz = 64;
6090
6091 if (!fImage) {
6092 return;
6093 }
6094
6095 if (!InitVisual()) {
6096 return;
6097 }
6098
6099 static char *buf = 0;
6100 int w, h;
6101 ASImage *img = 0;
6102
6103 if (fImage->width > fImage->height) {
6104 w = sz;
6105 h = (fImage->height*sz)/fImage->width;
6106 } else {
6107 h = sz;
6108 w = (fImage->width*sz)/fImage->height;
6109 }
6110
6111 w = w < 8 ? 8 : w;
6112 h = h < 8 ? 8 : h;
6113
6114 img = scale_asimage(fgVisual, fImage, w, h, ASA_ASImage,
6116 if (!img) {
6117 return;
6118 }
6119
6120 // contrasting
6121 ASImage *rendered_im;
6122 ASImageLayer layers[2];
6123 init_image_layers(&(layers[0]), 2);
6124 layers[0].im = img;
6125 layers[0].dst_x = 0;
6126 layers[0].dst_y = 0;
6127 layers[0].clip_width = img->width;
6128 layers[0].clip_height = img->height;
6129 layers[0].bevel = 0;
6130 layers[1].im = img;
6131 layers[1].dst_x = 0;
6132 layers[1].dst_y = 0;
6133 layers[1].clip_width = img->width;
6134 layers[1].clip_height = img->height;
6135 layers[1].merge_scanlines = blend_scanlines_name2func("tint");
6136 rendered_im = merge_layers(fgVisual, &(layers[0]), 2, img->width, img->height,
6137 ASA_ASImage, GetImageCompression(), GetImageQuality());
6138 destroy_asimage(&img);
6139 img = rendered_im;
6140
6141 // pad image
6142 ASImage *padimg = 0;
6143 int d = 0;
6144
6145 if (w == sz) {
6146 d = (sz - h) >> 1;
6147 padimg = pad_asimage(fgVisual, img, 0, d, sz, sz, 0x00ffffff,
6148 ASA_ASImage, GetImageCompression(), GetImageQuality());
6149 } else {
6150 d = (sz - w) >> 1;
6151 padimg = pad_asimage(fgVisual, img, d, 0, sz, sz, 0x00ffffff,
6152 ASA_ASImage, GetImageCompression(), GetImageQuality());
6153 }
6154
6155 if (!padimg) {
6156 destroy_asimage(&img);
6157 return;
6158 }
6159
6160 void *ptr = &buf;
6161 ASImage2xpmRawBuff(padimg, (CARD8 **)ptr, &size, 0);
6162 fTitle = buf;
6163
6164 destroy_asimage(&padimg);
6165}
6166
6167////////////////////////////////////////////////////////////////////////////////
6168/// Streamer for ROOT I/O.
6169
6170void TASImage::Streamer(TBuffer &b)
6171{
6172 Bool_t image_type = 0;
6173 char *buffer = 0;
6174 int size = 0;
6175 int w, h;
6176 UInt_t R__s, R__c;
6177
6178 if (b.IsReading()) {
6179 Version_t version = b.ReadVersion(&R__s, &R__c);
6180 if (version == 0) { //dumb prototype for schema evolution
6181 return;
6182 }
6183
6184 if ( version == 1 ) {
6185 Int_t fileVersion = b.GetVersionOwner();
6186 if (fileVersion > 0 && fileVersion < 50000 ) {
6187 TImage::Streamer(b);
6188 b >> fMaxValue;
6189 b >> fMinValue;
6190 b >> fZoomOffX;
6191 b >> fZoomOffY;
6192 b >> fZoomWidth;
6193 b >> fZoomHeight;
6194 if ( fileVersion < 40200 ) {
6195 Bool_t zoomUpdate;
6196 b >> zoomUpdate;
6197 fZoomUpdate = zoomUpdate;
6198 } else {
6199 b >> fZoomUpdate;
6200 b >> fEditable;
6201 Bool_t paintMode;
6202 b >> paintMode;
6203 fPaintMode = paintMode;
6204 }
6205 b.CheckByteCount(R__s, R__c, TASImage::IsA());
6206 return;
6207 }
6208 }
6209
6210 TNamed::Streamer(b);
6211 b >> image_type;
6212
6213 if (image_type != 0) { // read PNG compressed image
6214 b >> size;
6215 buffer = new char[size];
6216 b.ReadFastArray(buffer, size);
6217 SetImageBuffer(&buffer, TImage::kPng);
6218 delete [] buffer;
6219 } else { // read vector with palette
6220 TAttImage::Streamer(b);
6221 b >> w;
6222 b >> h;
6223 size = w*h;
6224 Double_t *vec = new Double_t[size];
6225 b.ReadFastArray(vec, size);
6226 SetImage(vec, w, h, &fPalette);
6227 delete [] vec;
6228 }
6229 b.CheckByteCount(R__s, R__c, TASImage::IsA());
6230 } else {
6231 if (!fImage) {
6232 return;
6233 }
6234 R__c = b.WriteVersion(TASImage::IsA(), kTRUE);
6235
6236 if (fName.IsNull()) {
6237 fName.Form("img_%dx%d.%d", fImage->width, fImage->height, gRandom->Integer(1000));
6238 }
6239 TNamed::Streamer(b);
6240
6241 image_type = fImage->alt.vector ? 0 : 1;
6242 b << image_type;
6243
6244 if (image_type != 0) { // write PNG compressed image
6245 GetImageBuffer(&buffer, &size, TImage::kPng);
6246 b << size;
6247 b.WriteFastArray(buffer, size);
6248 delete buffer;
6249 } else { // write vector with palette
6250 TAttImage::Streamer(b);
6251 b << fImage->width;
6252 b << fImage->height;
6253 b.WriteFastArray(fImage->alt.vector, fImage->width*fImage->height);
6254 }
6255 b.SetByteCount(R__c, kTRUE);
6256 }
6257}
6258
6259////////////////////////////////////////////////////////////////////////////////
6260/// Browse image.
6261
6263{
6264 if (fImage->alt.vector) {
6265 Draw("n");
6266 } else {
6267 Draw("nxxx");
6268 }
6270}
6271
6272////////////////////////////////////////////////////////////////////////////////
6273/// Title is used to keep 32x32 xpm image's thumbnail.
6274
6275const char *TASImage::GetTitle() const
6276{
6277 if (!gDirectory || !gDirectory->IsWritable()) {
6278 return 0;
6279 }
6280
6281 TASImage *mutble = (TASImage *)this;
6282
6283 if (fTitle.IsNull()) {
6284 mutble->SetTitle(fName.Data());
6285 }
6286
6287 return fTitle.Data();
6288}
6289
6290////////////////////////////////////////////////////////////////////////////////
6291/// Set a title for an image.
6292
6293void TASImage::SetTitle(const char *title)
6294{
6295 if (fTitle.IsNull()) {
6297 }
6298
6299 if (fTitle.IsNull()) {
6300 return;
6301 }
6302
6303 int start = fTitle.Index("/*") + 3;
6304 int stop = fTitle.Index("*/") - 1;
6305
6306 if ((start > 0) && (stop - start > 0)) {
6307 fTitle.Replace(start, stop - start, title);
6308 }
6309}
6310
6311////////////////////////////////////////////////////////////////////////////////
6312/// Draw a cubic bezier line.
6313
6315 Int_t x3, Int_t y3, const char *col, UInt_t thick)
6316{
6317 Int_t sz = thick*thick;
6318 CARD32 *matrix;
6319 Bool_t use_cache = thick < kBrushCacheSize;
6320
6321 ARGB32 color = ARGB32_White;
6322 parse_argb_color(col, &color);
6323
6324 if (use_cache) {
6325 matrix = gBrushCache;
6326 } else {
6327 matrix = new CARD32[sz];
6328 }
6329
6330 for (int i = 0; i < sz; i++) {
6331 matrix[i] = (CARD32)color;
6332 };
6333
6334 ASDrawTool brush;
6335 brush.matrix = matrix;
6336 brush.width = thick;
6337 brush.height = thick;
6338 brush.center_y = brush.center_x = thick/2;
6339
6340 ASDrawContext *ctx = 0;
6341
6342 ctx = create_draw_context_argb32(fImage, &brush);
6343 asim_cube_bezier(ctx, x1, y1, x2, y2, x3, y3);
6344
6345 if (!use_cache) {
6346 delete [] matrix;
6347 }
6349}
6350
6351////////////////////////////////////////////////////////////////////////////////
6352/// Draw a straight ellipse.
6353/// If thick < 0 - draw filled ellipse.
6354
6356 const char *col, Int_t thick)
6357{
6358 thick = !thick ? 1 : thick;
6359 Int_t sz = thick*thick;
6360 CARD32 *matrix;
6361 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6362
6363 ARGB32 color = ARGB32_White;
6364 parse_argb_color(col, &color);
6365
6366 if (use_cache) {
6367 matrix = gBrushCache;
6368 } else {
6369 matrix = new CARD32[sz];
6370 }
6371
6372 for (int i = 0; i < sz; i++) {
6373 matrix[i] = (CARD32)color;
6374 };
6375
6376 ASDrawTool brush;
6377 brush.matrix = matrix;
6378 brush.width = thick > 0 ? thick : 1;
6379 brush.height = thick > 0 ? thick : 1;
6380 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6381
6382 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6383 asim_straight_ellips(ctx, x, y, rx, ry, thick < 0);
6384
6385 if (!use_cache) {
6386 delete [] matrix;
6387 }
6389}
6390
6391////////////////////////////////////////////////////////////////////////////////
6392/// Draw a circle.
6393/// If thick < 0 - draw filled circle
6394
6395void TASImage::DrawCircle(Int_t x, Int_t y, Int_t r, const char *col, Int_t thick)
6396{
6397 thick = !thick ? 1 : thick;
6398 Int_t sz = thick*thick;
6399 CARD32 *matrix;
6400 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6401
6402 ARGB32 color = ARGB32_White;
6403 parse_argb_color(col, &color);
6404
6405///matrix = new CARD32[sz];
6406 if (use_cache) {
6407 matrix = gBrushCache;
6408 } else {
6409 matrix = new CARD32[sz];
6410 }
6411
6412 for (int i = 0; i < sz; i++) {
6413 matrix[i] = (CARD32)color;
6414 }
6415
6416 ASDrawTool brush;
6417 brush.matrix = matrix;
6418 brush.height = brush.width = thick > 0 ? thick : 1;
6419 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6420
6421 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6422 asim_circle(ctx, x, y, r, thick < 0);
6423
6424///free (matrix);
6425 if (!use_cache) {
6426 delete [] matrix;
6427 }
6429}
6430
6431////////////////////////////////////////////////////////////////////////////////
6432/// Draw an ellipse.
6433/// If thick < 0 - draw filled ellips
6434
6436 const char *col, Int_t thick)
6437{
6438 thick = !thick ? 1 : thick;
6439 Int_t sz = thick*thick;
6440 CARD32 *matrix;
6441 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6442
6443 ARGB32 color = ARGB32_White;
6444 parse_argb_color(col, &color);
6445
6446 if (use_cache) {
6447 matrix = gBrushCache;
6448 } else {
6449 matrix = new CARD32[sz];
6450 }
6451
6452 for (int i = 0; i < sz; i++) {
6453 matrix[i] = (CARD32)color;
6454 };
6455
6456 ASDrawTool brush;
6457 brush.matrix = matrix;
6458 brush.width = thick > 0 ? thick : 1;
6459 brush.height = thick > 0 ? thick : 1;
6460 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6461
6462 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6463 asim_ellips(ctx, x, y, rx, ry, angle, thick < 0);
6464
6465 if (!use_cache) {
6466 delete [] matrix;
6467 }
6469}
6470
6471////////////////////////////////////////////////////////////////////////////////
6472/// Draw an ellipse.
6473/// If thick < 0 - draw filled ellipse.
6474
6476 const char *col, Int_t thick)
6477{
6478 thick = !thick ? 1 : thick;
6479 Int_t sz = thick*thick;
6480 CARD32 *matrix;
6481 Bool_t use_cache = (thick > 0) && ((UInt_t)thick < kBrushCacheSize);
6482
6483 ARGB32 color = ARGB32_White;
6484 parse_argb_color(col, &color);
6485
6486 if (use_cache) {
6487 matrix = gBrushCache;
6488 } else {
6489 matrix = new CARD32[sz];
6490 }
6491
6492 for (int i = 0; i < sz; i++) {
6493 matrix[i] = (CARD32)color;
6494 };
6495
6496 ASDrawTool brush;
6497 brush.matrix = matrix;
6498 brush.width = thick > 0 ? thick : 1;
6499 brush.height = thick > 0 ? thick : 1;
6500 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
6501
6502 ASDrawContext *ctx = create_draw_context_argb32(fImage, &brush);
6503 asim_ellips2(ctx, x, y, rx, ry, angle, thick < 0);
6504
6505 if (!use_cache) {
6506 delete [] matrix;
6507 }
6509}
6510
6511////////////////////////////////////////////////////////////////////////////////
6512/// Flood fill.
6513
6514void TASImage::FloodFill(Int_t /*x*/, Int_t /*y*/, const char * /*col*/,
6515 const char * /*minc*/, const char * /*maxc*/)
6516{
6517}
6518
6519////////////////////////////////////////////////////////////////////////////////
6520/// Convert RGB image to Gray image and vice versa.
6521
6523{
6524 if (fIsGray == on) {
6525 return;
6526 }
6527
6528 if (!IsValid()) {
6529 Warning("Gray", "Image not initiated");
6530 return;
6531 }
6532
6533 if (!InitVisual()) {
6534 Warning("Gray", "Visual not initiated");
6535 return;
6536 }
6537
6538 if (!fGrayImage && !on) {
6539 return;
6540 }
6541 ASImage *sav = 0;
6542 delete fScaledImage;
6543 fScaledImage = 0;
6544
6545 if (fGrayImage) {
6546 sav = fImage;
6548 fGrayImage = sav;
6549 fIsGray = on;
6550 return;
6551 }
6552
6553 if (!on) return;
6554
6555 UInt_t l, r, g, b, idx;
6556 int y = 0;
6557 UInt_t i, j;
6558
6559 if (fImage->alt.argb32) {
6560 fGrayImage = tile_asimage(fgVisual, fImage, 0, 0, fImage->width, fImage->height,
6561 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
6562
6563 for (i = 0; i < fImage->height; i++) {
6564 for (j = 0; j < fImage->width; j++) {
6565 idx = Idx(y + j);
6566
6567 r = ((fImage->alt.argb32[idx] & 0xff0000) >> 16);
6568 g = ((fImage->alt.argb32[idx] & 0x00ff00) >> 8);
6569 b = (fImage->alt.argb32[idx] & 0x0000ff);
6570 l = (57*r + 181*g + 18*b)/256;
6571 fGrayImage->alt.argb32[idx] = (l << 16) + (l << 8) + l;
6572 }
6573 y += fImage->width;
6574 }
6575 } else {
6576 fGrayImage = create_asimage(fImage->width, fImage->height, 0);
6577
6578 ASImageDecoder *imdec = start_image_decoding(fgVisual, fImage, SCL_DO_ALL,
6579 0, 0, fImage->width, fImage->height, 0);
6580
6581 if (!imdec) {
6582 return;
6583 }
6584#ifdef HAVE_MMX
6585 mmx_init();
6586#endif
6587 ASImageOutput *imout = start_image_output(fgVisual, fGrayImage, ASA_ASImage,
6589 if (!imout) {
6590 Warning("ToGray", "Failed to start image output");
6591 delete fScaledImage;
6592 fScaledImage = 0;
6593 delete [] imdec;
6594 return;
6595 }
6596
6597 CARD32 *aa = imdec->buffer.alpha;
6598 CARD32 *rr = imdec->buffer.red;
6599 CARD32 *gg = imdec->buffer.green;
6600 CARD32 *bb = imdec->buffer.blue;
6601
6602 ASScanline result;
6603 prepare_scanline(fImage->width, 0, &result, fgVisual->BGR_mode);
6604
6605 for (i = 0; i < fImage->height; i++) {
6606 imdec->decode_image_scanline(imdec);
6607 result.flags = imdec->buffer.flags;
6608 result.back_color = imdec->buffer.back_color;
6609
6610 for (j = 0; j < fImage->width; j++) {
6611 l = (57*rr[j] + 181*gg[j]+ 18*bb[j])/256;
6612 result.alpha[j] = aa[j];
6613 result.red[j] = l;
6614 result.green[j] = l;
6615 result.blue[j] = l;
6616 }
6617 imout->output_image_scanline(imout, &result, 1);
6618 }
6619
6620 stop_image_decoding(&imdec);
6621 stop_image_output(&imout);
6622#ifdef HAVE_MMX
6623 mmx_off();
6624#endif
6625 }
6626
6627 sav = fImage;
6629 fGrayImage = sav;
6630 fIsGray = kTRUE;
6631}
6632
6633////////////////////////////////////////////////////////////////////////////////
6634/// Create an image (screenshot) from specified window.
6635
6637{
6638 Int_t xy;
6639
6640 x = x < 0 ? 0 : x;
6641 y = y < 0 ? 0 : y;
6642
6643 // X11 Synchronization
6644 gVirtualX->Update(1);
6645 if (!gThreadXAR) {
6646 gSystem->Sleep(10);
6648 gSystem->Sleep(10);
6650 }
6651
6652 if (!w || !h) {
6653 gVirtualX->GetWindowSize(wid, xy, xy, w, h);
6654 }
6655
6656 if ((x >= (Int_t)w) || (y >= (Int_t)h)) {
6657 return;
6658 }
6659
6660 if (!InitVisual()) {
6661 Warning("FromWindow", "Visual not initiated");
6662 return;
6663 }
6664
6665 DestroyImage();
6666 delete fScaledImage;
6667 fScaledImage = 0;
6668
6669 static int x11 = -1;
6670 if (x11 < 0) x11 = gVirtualX->InheritsFrom("TGX11");
6671
6672 if (x11) { //use built-in optimized version
6673 fImage = pixmap2asimage(fgVisual, wid, x, y, w, h, kAllPlanes, 0, 0);
6674 } else {
6675 unsigned char *bits = gVirtualX->GetColorBits(wid, 0, 0, w, h);
6676
6677 if (!bits) { // error
6678 return;
6679 }
6680 fImage = bitmap2asimage(bits, w, h, 0, 0);
6681 delete [] bits;
6682 }
6683}
6684
6685////////////////////////////////////////////////////////////////////////////////
6686/// Creates an image (screenshot) from a RGBA buffer.
6687
6689{
6690 DestroyImage();
6691 delete fScaledImage;
6692 fScaledImage = 0;
6693
6694 UChar_t* xx = new UChar_t[4*w];
6695 for (UInt_t i = 0; i < h/2; ++i) {
6696 memcpy(xx, buf + 4*w*i, 4*w);
6697 memcpy(buf + 4*w*i, buf + 4*w*(h-i-1), 4*w);
6698 memcpy(buf + 4*w*(h-i-1), xx, 4*w);
6699 }
6700 delete [] xx;
6701
6702 fImage = bitmap2asimage(buf, w, h, 0, 0);
6703}
6704
6705////////////////////////////////////////////////////////////////////////////////
6706/// Switch on/off the image palette.
6707/// That also invokes calling vectorization of image.
6708
6710{
6711 if (!fImage) {
6712 return;
6713 }
6714
6715 if (!fImage->alt.vector && on) {
6716 Vectorize();
6717 }
6718 fPaletteEnabled = on;
6719
6720 if (on) {
6721 Double_t left = gPad->GetLeftMargin();
6722 Double_t right = gPad->GetRightMargin();
6723 Double_t top = gPad->GetTopMargin();
6724 Double_t bottom = gPad->GetBottomMargin();
6725
6726 gPad->Range(-left / (1.0 - left - right),
6727 -bottom / (1.0 - top - bottom),
6728 1 + right / (1.0 - left - right),
6729 1 + top / ( 1.0 - top - bottom));
6730 gPad->RangeAxis(0, 0, 1, 1);
6731 }
6732
6733}
6734
6735////////////////////////////////////////////////////////////////////////////////
6736/// Save a primitive as a C++ statement(s) on output stream "out".
6737
6738void TASImage::SavePrimitive(std::ostream &out, Option_t * /*= ""*/)
6739{
6740 char *buf = 0;
6741 int sz;
6742
6743 UInt_t w = GetWidth();
6744 UInt_t h = GetHeight();
6745
6746 if (w > 500) { // workaround CINT limitations
6747 w = 500;
6748 Double_t scale = 500./GetWidth();
6749 h = TMath::Nint(GetHeight()*scale);
6750 Scale(w, h);
6751 }
6752
6753 GetImageBuffer(&buf, &sz, TImage::kXpm);
6754
6755 TString name = GetName();
6756 name.ReplaceAll(".", "_");
6757 TString str = buf;
6758 static int ii = 0;
6759 ii++;
6760
6761 str.ReplaceAll("static", "const");
6762 TString xpm = "xpm_";
6763 xpm += name;
6764 xpm += ii;
6765 str.ReplaceAll("asxpm", xpm.Data());
6766 out << std::endl << str << std::endl << std::endl;
6767
6768 out << " TImage *";
6769 out << xpm << "_img = TImage::Create();" << std::endl;
6770 out << " " << xpm << "_img->SetImageBuffer( (char **)" << xpm << ", TImage::kXpm);" << std::endl;
6771 out << " " << xpm << "_img->Draw();" << std::endl;
6772}
6773
6774////////////////////////////////////////////////////////////////////////////////
6775/// Set an image printing resolution in Dots Per Inch units.
6776///
6777/// \param[in] name - the name of jpeg file.
6778/// \param[in] set - dpi resolution.
6779///
6780/// Returns kFALSE in case of error.
6781
6783{
6784 static char buf[32];
6785 FILE *fp = fopen(name, "rb+");
6786
6787 if (!fp) {
6788 printf("file %s : failed to open\n", name);
6789 return kFALSE;
6790 }
6791
6792 if (!fread(buf, 1, 20, fp)) {
6793 fclose(fp);
6794 return kFALSE;
6795 }
6796
6797 char dpi1 = (set & 0xffff) >> 8;
6798 char dpi2 = set & 0xff;
6799
6800 int i = 0;
6801
6802 int dpi = 0; // start of dpi data
6803 for (i = 0; i < 20; i++) {
6804 if ((buf[i] == 0x4a) && (buf[i+1] == 0x46) && (buf[i+2] == 0x49) &&
6805 (buf[i+3] == 0x46) && (buf[i+4] == 0x00) ) {
6806 dpi = i + 7;
6807 break;
6808 }
6809 }
6810
6811 if (i == 20 || dpi+4 >= 20) { // jpeg maker was not found
6812 fclose(fp);
6813 printf("file %s : wrong JPEG format\n", name);
6814 return kFALSE;
6815 }
6816
6817 buf[dpi] = 1; // format specified in dots per inch
6818
6819 // set x density in dpi units
6820 buf[dpi + 1] = dpi1;
6821 buf[dpi + 2] = dpi2;
6822
6823 // set y density in dpi units
6824 buf[dpi + 3] = dpi1;
6825 buf[dpi + 4] = dpi2;
6826
6827 rewind(fp);
6828 fwrite(buf, 1, 20, fp);
6829 fclose(fp);
6830
6831 return kTRUE;
6832}
6833
6834////////////////////////////////////////////////////////////////////////////////
6835/// Return a valid index in fImage tables to avoid seg-fault by accessing out of
6836/// indices out of array's ranges.
6837
6839{
6840 // The size of arrays like fImage->alt.argb32 is fImage->width*fImage->height
6841 return TMath::Min(idx,(Int_t)(fImage->width*fImage->height));
6842}
6843
@ kButton1Motion
Definition: Buttons.h:20
@ kButton1Up
Definition: Buttons.h:19
@ kButton1Down
Definition: Buttons.h:17
void Class()
Definition: Class.C:29
SVector< double, 2 > v
Definition: Dict.h:5
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:82
#define ClassImp(name)
Definition: Rtypes.h:363
#define SETBIT(n, i)
Definition: Rtypes.h:83
#define CLRBIT(n, i)
Definition: Rtypes.h:84
static ARGB32 GetShadow(ARGB32 background)
Calculate shadow color.
Definition: TASImage.cxx:3211
static const UInt_t kBrushCacheSize
Definition: TASImage.cxx:5658
static CARD32 gBrushCache[kBrushCacheSize *kBrushCacheSize]
Definition: TASImage.cxx:5659
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:3220
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:5174
static CARD8 MakeComponentHilite(int cmp)
Make component hilite.
Definition: TASImage.cxx:3185
static ARGB32 GetHilite(ARGB32 background)
Calculate highlite color.
Definition: TASImage.cxx:3199
static const UInt_t NUMPTSTOBUFFER
Definition: TASImage.cxx:5425
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:3717
#define FillSpansInternal(npt, ppt, widths, color)
Definition: TASImage.cxx:3722
static ASDrawContext * create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
Create draw context.
Definition: TASImage.cxx:5633
#define _alphaBlend(bot, top)
Definition: TASImage.cxx:154
static void destroy_asdraw_context32(ASDrawContext *ctx)
Destroy asdraw context32.
Definition: TASImage.cxx:5650
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:213
include TDocParser_001 C image html pict1_TDocParser_001 png width
Definition: TDocParser.cxx:121
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
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:410
R__EXTERN TRandom * gRandom
Definition: TRandom.h:62
char * Form(const char *fmt,...)
R__EXTERN TStyle * gStyle
Definition: TStyle.h:406
R__EXTERN const char * gProgName
Definition: TSystem.h:224
@ kReadPermission
Definition: TSystem.h:48
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
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:5348
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:6782
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:3919
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:5012
Bool_t SetImageBuffer(char **buffer, EImageFileTypes type=TImage::kPng)
Create image from compressed buffer.
Definition: TASImage.cxx:6039
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:3873
@ kZoom
Definition: TASImage.h:34
@ kNoZoom
Definition: TASImage.h:34
@ kZoomOps
Definition: TASImage.h:34
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:4809
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:3490
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:6395
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:5126
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:3413
void CropSpans(UInt_t npt, TPoint *ppt, UInt_t *widths)
Crop spans.
Definition: TASImage.cxx:4924
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:3664
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:3563
void DrawVLine(UInt_t x, UInt_t y1, UInt_t y2, UInt_t col, UInt_t thick)
Draw a vertical line.
Definition: TASImage.cxx:3838
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:3008
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:6355
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:6838
void DrawSegments(UInt_t nseg, Segment_t *seg, const char *col="#000000", UInt_t thick=1)
Draw segments.
Definition: TASImage.cxx:4786
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:4666
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:5664
void CropPolygon(UInt_t npt, TPoint *ppt)
Crop a convex polygon.
Definition: TASImage.cxx:5404
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:3248
void SavePrimitive(std::ostream &out, Option_t *option="")
Save a primitive as a C++ statement(s) on output stream "out".
Definition: TASImage.cxx:6738
UInt_t * GetRgbaArray()
Return a pointer to an array[width x height] of RGBA32 values.
Definition: TASImage.cxx:3618
void PolyPoint(UInt_t npt, TPoint *ppt, const char *col="#000000", TImage::ECoordMode mode=kCoordModeOrigin)
Draw a poly point.
Definition: TASImage.cxx:4726
Pixmap_t GetMask()
Returns image mask pixmap (alpha channel).
Definition: TASImage.cxx:2300
static const ASVisual * GetVisual()
Return visual.
Definition: TASImage.cxx:5166
const char * GetTitle() const
Title is used to keep 32x32 xpm image's thumbnail.
Definition: TASImage.cxx:6275
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:6709
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:3734
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:4622
void DrawGlyph(void *bitmap, UInt_t color, Int_t x, Int_t y)
Draw glyph bitmap.
Definition: TASImage.cxx:5711
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:3812
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:3908
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:6636
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:5430
void GetImageBuffer(char **buffer, int *size, EImageFileTypes type=TImage::kPng)
Return in-memory buffer compressed according image type.
Definition: TASImage.cxx:5987
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:6262
void Gray(Bool_t on=kTRUE)
Convert RGB image to Gray image and vice versa.
Definition: TASImage.cxx:6522
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:5155
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:5952
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:3531
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:4464
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:6435
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:6514
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:2945
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:6475
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:4223
UInt_t * GetArgbArray()
Return a pointer to internal array[width x height] of ARGB32 values This array is directly accessible...
Definition: TASImage.cxx:3590
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:4169
void PutPixel(Int_t x, Int_t y, const char *col="#000000")
Draw a point at the specified position.
Definition: TASImage.cxx:4691
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:6314
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:4280
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:6688
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:5203
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:4080
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:3364
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:4120
void SetTitle(const char *title="")
Set a title for an image.
Definition: TASImage.cxx:6293
Bool_t fIsGray
! kTRUE if image is gray
Definition: TASImage.h:69
void CreateThumbnail()
Create image thumbnail.
Definition: TASImage.cxx:6086
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:180
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:40
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:2035
const char * AsHexString() const
Return color as hexadecimal string.
Definition: TColor.cxx:1203
Int_t GetNumber() const
Definition: TColor.h:54
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:3147
static const TString & GetIconPath()
Get the icon path in the installation. Static utility function.
Definition: TROOT.cxx:3126
virtual UInt_t Integer(UInt_t imax)
Returns a random integer on [ 0, imax-1 ].
Definition: TRandom.cxx:341
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:1100
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1896
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2152
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1081
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:487
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:1738
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:876
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2172
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:464
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
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:243
Float_t GetImageScaling() const
Definition: TStyle.h:226
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1264
virtual const char * HomeDirectory(const char *userName=0)
Return the user's home directory.
Definition: TSystem.cxx:894
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1071
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:941
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition: TSystem.cxx:446
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1536
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition: TSystem.cxx:425
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:605
static void PrepareString(const char *string)
Put the characters in "string" in the "glyphs" array.
Definition: TTF.cxx:247
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:339
static void SetTextFont(Font_t fontnumber)
Set specified font.
Definition: TTF.cxx:488
static Int_t GetAscent()
Definition: TTF.cxx:619
static TTGlyph * GetGlyphs()
Definition: TTF.cxx:647
static Int_t GetNumGlyphs()
Definition: TTF.cxx:626
static Int_t GetWidth()
Definition: TTF.cxx:612
static const FT_BBox & GetBox()
Definition: TTF.cxx:640
static void SetTextSize(Float_t textsize)
Set current text size.
Definition: TTF.cxx:559
static FT_Matrix * GetRotMatrix()
Definition: TTF.cxx:633
Base class for several text objects.
Definition: TText.h:23
const void * GetWcsTitle(void) const
Returns the text as UNICODE.
Definition: TText.cxx:131
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:49
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:701
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
Double_t ATan2(Double_t, Double_t)
Definition: TMath.h:667
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
Double_t Cos(Double_t)
Definition: TMath.h:629
Double_t Sin(Double_t)
Definition: TMath.h:625
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