//Author: Timur Pocheptsov, 19/03/2014 //This macro requires OS X and ROOT //compiled with --enable-cocoa to run. //Features: //1. Radial and linear gradients //2. Transparent/semitransparent colours. //3. Shadows. //Includes for ACLiC: #include "TColorGradient.h" #include "TVirtualX.h" #include "TCanvas.h" #include "TError.h" #include "TText.h" #include "TPie.h" //Cocoa aux. functions. #include "customcolor.h" void gradients() { //Find free colour indices in the ROOT's palette for: //1. A radial gradient for TPie; //2. A linear gradient for TCanvas //3. A fully transparent fill color for a nested pad. Color_t colorIndices[3] = {}; if (ROOT::CocoaTutorials::FindFreeCustomColorIndices(colorIndices) != 3) { ::Error("grad", "failed to create new custom colors"); return; } //Better names: const Color_t &radialFill = colorIndices[0]; const Color_t &linearFill = colorIndices[1]; const Color_t &transparentFill = colorIndices[2]; //Create a canvas to check if we have a right back-end which supports gradients: TCanvas * const c = new TCanvas("cpie","Gradient colours demo", 700, 700); //Before we allocated any new colour or created any object: if (gVirtualX && !gVirtualX->InheritsFrom("TGCocoa")) { ::Error("gradients", "This macro requires OS X and ROOT built with --enable-cocoa"); delete c; return; } //Linear gradient is defined by: 1) colors (to interpolate between them), //2) coordinates for these colors along the gradient axis [0., 1.] (must be sorted!). //3) Start and end points for a gradient, you specify them in some NDC rect ([0,0 - 1,1]), //and this rect is either: bounding rect of your polygon/object to fill //(gradient->SetCoordinateMode(TColorGradient::kObjectBoundingMode)) //or bounding rect of a pad (gradient->SetCoordinateMode(TColorGradient::kPadMode)). //kObjectBoundingMode is the default one. //Colour positions in the gradient's palette (here I place colors at the //ends of 0-1): const Double_t locations[] = {0., 1.}; //Linear gradient fill (with an axis angle == 45): const Double_t rgbaData1[] = {0.2, 0.2, 0.2, 1.,/*gray*/ 0.8, 1., 0.9, 1. /*pale green*/}; TLinearGradient * const gradientFill1 = new TLinearGradient(linearFill, 2, locations, rgbaData1); //45 degrees: gradientFill1->SetStartEnd(TColorGradient::Point(0., 0.), TColorGradient::Point(1., 1.)); //Set as a background color in the canvas: c->SetFillColor(linearFill); //Draw a text in the canvas (the object above the text will be //semi-transparent): TText * const t = new TText(0.05, 0.7, "Can you see the text?"); t->Draw(); //We create a nested pad on top to render a TPie in, //this way we still have a text (below) + TPie with //a fancy colour on top. TPad * const pad = new TPad("p", "p", 0., 0., 1., 1.); //TPad itself is fully transparent: new TColor(transparentFill, 1., 1., 1., "transparent_fill_color", 0.); pad->SetFillColor(transparentFill); //Add our pad into the canvas: pad->Draw(); pad->cd(); //Radial gradient fill for a TPie object: const Double_t rgbaData2[] = {/*opaque orange at the start:*/1., 0.8, 0., 1., /*transparent red at the end:*/1., 0.2, 0., 0.8}; // //With Quartz/Cocoa we support the "extended" radial gradient: //you can specify two centers and two radiuses - the start and //the end of your radial gradient (+ colors/positions as with a linear //gradient). // TRadialGradient * const gradientFill2 = new TRadialGradient(radialFill, 2, locations, rgbaData2); //Parameters for a gradient fill: //the gradient is 'pad-related' - we calculate everything in a pad's //space and consider it as a NDC (so pad's rect is (0,0), (1,1)). gradientFill2->SetCoordinateMode(TColorGradient::kPadMode); //Centers for both circles are the same point. gradientFill2->SetStartEndR1R2(TColorGradient::Point(0.5, 0.5), 0.1, TColorGradient::Point(0.5, 0.5), 0.4); const UInt_t nSlices = 5; //Values for a TPie (non-const, that's how TPie's ctor is declared): Double_t values[nSlices] = {0.8, 1.2, 1.2, 0.8, 1.}; Int_t colors[nSlices] = {radialFill, radialFill, radialFill, radialFill, radialFill}; TPie * const pie = new TPie("pie", "TPie:", nSlices, values, colors); //One slice is slightly shifted: pie->SetEntryRadiusOffset(2, 0.05); //Move labels to the center (to fit the pad's space): pie->SetLabelsOffset(-0.08); // pie->SetRadius(0.4); pie->Draw("rsc"); }