<commit_before>// @(#)root/base:$Id$
// Author: Rene Brun   12/12/94

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "Strlen.h"
#include "TROOT.h"
#include "TAttText.h"
#include "TVirtualPad.h"
#include "TStyle.h"
#include "TVirtualX.h"
#include "TError.h"
#include "TVirtualPadEditor.h"
#include "TColor.h"

ClassImp(TAttText);

/** \class TAttText
\ingroup Base
\ingroup GraphicsAtt

Text Attributes class.

This class is used (in general by secondary inheritance)
by many other classes (graphics, histograms). It holds all the text attributes.

## Text attributes
Text attributes are:

  - [Text Alignment](#T1)
  - [Text Angle](#T2)
  - [Text Color](#T3)
  - [Text Size](#T4)
  - [Text Font and Precision](#T5)
     - [Font quality and speed](#T51)
     - [How to use True Type Fonts](#T52)
     - [List of the currently supported fonts](#T53)

##  Text Alignment

The text alignment is an integer number (`align`) allowing to control
the horizontal and vertical position of the text string with respect
to the text position.
The text alignment of any class inheriting from `TAttText` can
be changed using the method `SetTextAlign` and retrieved using the
method `GetTextAlign`.

~~~ {.cpp}
   align = 10*HorizontalAlign + VerticalAlign
~~~

For horizontal alignment the following convention applies:

~~~ {.cpp}
   1=left adjusted, 2=centered, 3=right adjusted
~~~

For vertical alignment the following convention applies:

~~~ {.cpp}
   1=bottom adjusted, 2=centered, 3=top adjusted
~~~

For example:

~~~ {.cpp}
   align = 11 = left adjusted and bottom adjusted
   align = 32 = right adjusted and vertically centered
~~~

Begin_Macro(source)
textalign.C
End_Macro

Mnemonic constants are available:

~~~ {.cpp}
kHAlignLeft   = 10, kHAlignCenter = 20, kHAlignRight = 30,
kVAlignBottom = 1,  kVAlignCenter = 2,  kVAlignTop   = 3
~~~

They allow to write:

~~~ {.cpp}
object->SetTextAlign(kHAlignLeft+kVAlignTop);
~~~

##  Text Angle

Text angle in degrees.
The text angle of any class inheriting from `TAttText` can
be changed using the method `SetTextAngle` and retrieved using the
method `GetTextAngle`.
The following picture shows the text angle:

Begin_Macro(source)
textangle.C
End_Macro

##  Text Color

The text color is a color index (integer) pointing in the ROOT
color table.
The text color of any class inheriting from `TAttText` can
be changed using the method `SetTextColor` and retrieved using the
method `GetTextColor`.
The following table shows the first 50 default colors.

Begin_Macro
{
   TCanvas *c = new TCanvas("c","Text colors",0,0,500,200);
   c->DrawColorTable();
}
End_Macro

### Color transparency
`SetTextColorAlpha()`, allows to set a transparent color.
In the following example the text color of the text `text`
is set to blue with a transparency of 35%. The color `kBlue`
itself remains fully opaque.

~~~ {.cpp}
text->SetTextColorAlpha(kBlue, 0.35);
~~~

The transparency is available on all platforms when the `flagOpenGL.CanvasPreferGL` is set to `1`
in `$ROOTSYS/etc/system.rootrc`, or on Mac with the Cocoa backend. On the file output
it is visible with PDF, PNG, Gif, JPEG, SVG ... but not PostScript.

##  Text Size

If the text precision (see next paragraph) is smaller than 3, the text
size (`textsize`) is a fraction of the current pad size. Therefore the
same `textsize` value can generate text outputs with different absolute
sizes in two different pads.
The text size in pixels (`charheight`) is computed the following way:

~~~ {.cpp}
   pad_width  = gPad->XtoPixel(gPad->GetX2());
   pad_height = gPad->YtoPixel(gPad->GetY1());
   if (pad_width < pad_height)  charheight = textsize*pad_width;
   else                         charheight = textsize*pad_height;
~~~

If the text precision is equal to 3, the text size doesn't depend on the pad's
dimensions. A given `textsize` value always generates the same absolute
size. The text size (`charheight`) is given in pixels:

~~~ {.cpp}
   charheight = textsize;
~~~

Note that to scale fonts to the same size as the old True Type package a
scale factor of `0.93376068` is apply to the text size before drawing.

The text size of any class inheriting from `TAttText` can
be changed using the method `SetTextSize` and retrieved using the
method `GetTextSize`.

##  Text Font and Precision

The text font code is combination of the font number and the precision.
~~~ {.cpp}
   Text font code = 10*fontnumber + precision
~~~
Font numbers must be between 1 and 14.

The precision can be:

  - `precision = 0` fast hardware fonts (steps in the size)
  - `precision = 1` scalable and rotatable hardware fonts (see below)
  - `precision = 2` scalable and rotatable hardware fonts
  - `precision = 3` scalable and rotatable hardware fonts. Text size
                           is given in pixels.

The text font and precision of any class inheriting from `TAttText` can
be changed using the method `SetTextFont` and retrieved using the
method `GetTextFont`.

###  Font quality and speed

When precision 0 is used, only the original non-scaled system fonts are
used. The fonts have a minimum (4) and maximum (37) size in pixels. These
fonts are fast and are of good quality. Their size varies with large steps
and they cannot be rotated.
Precision 1 and 2 fonts have a different behaviour depending if the
True Type Fonts (TTF) are used or not. If TTF are used, you always get very good
quality scalable and rotatable fonts. However TTF are slow.

###  How to use True Type Fonts

One can activate the TTF by adding (or activating) the following line
in the `.rootrc` file:

~~~ {.cpp}
   Unix.*.Root.UseTTFonts:     true
~~~

It is possible to check the TTF are in use in a Root session
with the command:

~~~ {.cpp}
   gEnv->Print();
~~~

If the TTF are in use the following line will appear at the beginning of the
printout given by this command:

~~~ {.cpp}
   Unix.*.Root.UseTTFonts:   true                           [Global]
~~~

###  List of the currently supported fonts

~~~ {.cpp}
   Font number         X11 Names             Win32/TTF Names
       1 :       times-medium-i-normal      "Times New Roman"
       2 :       times-bold-r-normal        "Times New Roman"
       3 :       times-bold-i-normal        "Times New Roman"
       4 :       helvetica-medium-r-normal  "Arial"
       5 :       helvetica-medium-o-normal  "Arial"
       6 :       helvetica-bold-r-normal    "Arial"
       7 :       helvetica-bold-o-normal    "Arial"
       8 :       courier-medium-r-normal    "Courier New"
       9 :       courier-medium-o-normal    "Courier New"
      10 :       courier-bold-r-normal      "Courier New"
      11 :       courier-bold-o-normal      "Courier New"
      12 :       symbol-medium-r-normal     "Symbol"
      13 :       times-medium-r-normal      "Times New Roman"
      14 :                                  "Wingdings"
      15 :       Symbol italic (derived from Symbol)
~~~

The following picture shows how each font looks. The number on the left
is the "text font code". In this picture precision 2 was selected.

Begin_Macro
fonts.C
End_Macro
*/

////////////////////////////////////////////////////////////////////////////////
/// AttText default constructor.
///
/// Default text attributes are taken from the current style.

TAttText::TAttText()
{
   if (!gStyle) {
      ResetAttText();
      return;
   }
   fTextAlign = gStyle->GetTextAlign();
   fTextAngle = gStyle->GetTextAngle();
   fTextColor = gStyle->GetTextColor();
   fTextFont  = gStyle->GetTextFont();
   fTextSize  = gStyle->GetTextSize();
}

////////////////////////////////////////////////////////////////////////////////
/// AttText normal constructor.
///
/// Text attributes are taken from the argument list.

TAttText::TAttText(Int_t align, Float_t angle, Color_t color, Style_t font, Float_t tsize)
{
   fTextAlign = align;
   fTextAngle = angle;
   fTextColor = color;
   fTextFont  = font;
   fTextSize  = tsize;
}

////////////////////////////////////////////////////////////////////////////////
/// AttText destructor.

TAttText::~TAttText()
{
}

////////////////////////////////////////////////////////////////////////////////
/// Copy this text attributes to a new TAttText.

void TAttText::Copy(TAttText &atttext) const
{
   atttext.fTextAlign  = fTextAlign;
   atttext.fTextAngle  = fTextAngle;
   atttext.fTextColor  = fTextColor;
   atttext.fTextFont   = fTextFont;
   atttext.fTextSize   = fTextSize;
}

////////////////////////////////////////////////////////////////////////////////
/// Change current text attributes if necessary.

void TAttText::Modify()
{
   if (!gPad) return;

   // Do we need to change font?
   if (!gPad->IsBatch()) {
      gVirtualX->SetTextAngle(fTextAngle);
      Float_t wh = (Float_t)gPad->XtoPixel(gPad->GetX2());
      Float_t hh = (Float_t)gPad->YtoPixel(gPad->GetY1());
      Float_t tsize;
      if (wh < hh)  tsize = fTextSize*wh;
      else          tsize = fTextSize*hh;
      if (fTextFont%10 > 2) tsize = fTextSize;

      if (gVirtualX->GetTextFont() != fTextFont) {
            gVirtualX->SetTextFont(fTextFont);
            gVirtualX->SetTextSize(tsize);
      }
      if (gVirtualX->GetTextSize() != tsize)
            gVirtualX->SetTextSize(tsize);
      gVirtualX->SetTextAlign(fTextAlign);
      gVirtualX->SetTextColor(fTextColor);
   }
   gPad->SetAttTextPS(fTextAlign,fTextAngle,fTextColor,fTextFont,fTextSize);
}

////////////////////////////////////////////////////////////////////////////////
/// Reset this text attributes to default values.

void TAttText::ResetAttText(Option_t *)
{
   fTextAlign  = 11;
   fTextAngle  = 0;
   fTextColor  = 1;
   fTextFont   = 62;
   fTextSize   = 0.05;
}

////////////////////////////////////////////////////////////////////////////////
/// Save text attributes as C++ statement(s) on output stream out.

void TAttText::SaveTextAttributes(std::ostream &out, const char *name, Int_t alidef,
                                  Float_t angdef, Int_t coldef, Int_t fondef,
                                  Float_t sizdef)
{
   if (fTextAlign != alidef) {
      out<<"   "<<name<<"->SetTextAlign("<<fTextAlign<<");"<<std::endl;
   }
   if (fTextColor != coldef) {
      if (fTextColor > 228) {
         TColor::SaveColor(out, fTextColor);
         out<<"   "<<name<<"->SetTextColor(ci);" << std::endl;
      } else
         out<<"   "<<name<<"->SetTextColor("<<fTextColor<<");"<<std::endl;
   }
   if (fTextFont != fondef) {
      out<<"   "<<name<<"->SetTextFont("<<fTextFont<<");"<<std::endl;
   }
   if (fTextSize != sizdef) {
      out<<"   "<<name<<"->SetTextSize("<<fTextSize<<");"<<std::endl;
   }
   if (fTextAngle != angdef) {
      out<<"   "<<name<<"->SetTextAngle("<<fTextAngle<<");"<<std::endl;
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Invoke the DialogCanvas Text attributes.

void TAttText::SetTextAttributes()
{
   TVirtualPadEditor::UpdateTextAttributes(fTextAlign,fTextAngle,fTextColor,
                                           fTextFont,fTextSize);
}

////////////////////////////////////////////////////////////////////////////////
/// Set a transparent marker color. talpha defines the percentage of
/// the color opacity from 0. (fully transparent) to 1. (fully opaque).

void TAttText::SetTextColorAlpha(Color_t tcolor, Float_t talpha)
{
   fTextColor = TColor::GetColorTransparent(tcolor, talpha);
}

////////////////////////////////////////////////////////////////////////////////
/// Set the text size in pixels.
///
/// If the font precision is greater than 2, the text size is set to npixels,
/// otherwise the text size is computed as a percent of the pad size.

void TAttText::SetTextSizePixels(Int_t npixels)
{
   if (fTextFont%10 > 2) {
      fTextSize = Float_t(npixels);
   } else {
      TVirtualPad *pad = gROOT->GetSelectedPad();
      if (!pad) return;
      Float_t dy = pad->AbsPixeltoY(0) - pad->AbsPixeltoY(npixels);
      fTextSize = dy/(pad->GetY2() - pad->GetY1());
   }
}
<commit_msg>High def images<commit_after>// @(#)root/base:$Id$
// Author: Rene Brun   12/12/94

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Riostream.h"
#include "Strlen.h"
#include "TROOT.h"
#include "TAttText.h"
#include "TVirtualPad.h"
#include "TStyle.h"
#include "TVirtualX.h"
#include "TError.h"
#include "TVirtualPadEditor.h"
#include "TColor.h"

ClassImp(TAttText);

/** \class TAttText
\ingroup Base
\ingroup GraphicsAtt

Text Attributes class.

This class is used (in general by secondary inheritance)
by many other classes (graphics, histograms). It holds all the text attributes.

## Text attributes
Text attributes are:

  - [Text Alignment](#T1)
  - [Text Angle](#T2)
  - [Text Color](#T3)
  - [Text Size](#T4)
  - [Text Font and Precision](#T5)
     - [Font quality and speed](#T51)
     - [How to use True Type Fonts](#T52)
     - [List of the currently supported fonts](#T53)

##  Text Alignment

The text alignment is an integer number (`align`) allowing to control
the horizontal and vertical position of the text string with respect
to the text position.
The text alignment of any class inheriting from `TAttText` can
be changed using the method `SetTextAlign` and retrieved using the
method `GetTextAlign`.

~~~ {.cpp}
   align = 10*HorizontalAlign + VerticalAlign
~~~

For horizontal alignment the following convention applies:

~~~ {.cpp}
   1=left adjusted, 2=centered, 3=right adjusted
~~~

For vertical alignment the following convention applies:

~~~ {.cpp}
   1=bottom adjusted, 2=centered, 3=top adjusted
~~~

For example:

~~~ {.cpp}
   align = 11 = left adjusted and bottom adjusted
   align = 32 = right adjusted and vertically centered
~~~

Begin_Macro(source)
textalign.C
End_Macro

Mnemonic constants are available:

~~~ {.cpp}
kHAlignLeft   = 10, kHAlignCenter = 20, kHAlignRight = 30,
kVAlignBottom = 1,  kVAlignCenter = 2,  kVAlignTop   = 3
~~~

They allow to write:

~~~ {.cpp}
object->SetTextAlign(kHAlignLeft+kVAlignTop);
~~~

##  Text Angle

Text angle in degrees.
The text angle of any class inheriting from `TAttText` can
be changed using the method `SetTextAngle` and retrieved using the
method `GetTextAngle`.
The following picture shows the text angle:

Begin_Macro(source)
textangle.C
End_Macro

##  Text Color

The text color is a color index (integer) pointing in the ROOT
color table.
The text color of any class inheriting from `TAttText` can
be changed using the method `SetTextColor` and retrieved using the
method `GetTextColor`.
The following table shows the first 50 default colors.

Begin_Macro("width=500")
{
   TCanvas *c = new TCanvas("c","Fill Area colors",0,0,1500,600);
   c->DrawColorTable();
   return c;
}
End_Macro

### Color transparency
`SetTextColorAlpha()`, allows to set a transparent color.
In the following example the text color of the text `text`
is set to blue with a transparency of 35%. The color `kBlue`
itself remains fully opaque.

~~~ {.cpp}
text->SetTextColorAlpha(kBlue, 0.35);
~~~

The transparency is available on all platforms when the `flagOpenGL.CanvasPreferGL` is set to `1`
in `$ROOTSYS/etc/system.rootrc`, or on Mac with the Cocoa backend. On the file output
it is visible with PDF, PNG, Gif, JPEG, SVG ... but not PostScript.

##  Text Size

If the text precision (see next paragraph) is smaller than 3, the text
size (`textsize`) is a fraction of the current pad size. Therefore the
same `textsize` value can generate text outputs with different absolute
sizes in two different pads.
The text size in pixels (`charheight`) is computed the following way:

~~~ {.cpp}
   pad_width  = gPad->XtoPixel(gPad->GetX2());
   pad_height = gPad->YtoPixel(gPad->GetY1());
   if (pad_width < pad_height)  charheight = textsize*pad_width;
   else                         charheight = textsize*pad_height;
~~~

If the text precision is equal to 3, the text size doesn't depend on the pad's
dimensions. A given `textsize` value always generates the same absolute
size. The text size (`charheight`) is given in pixels:

~~~ {.cpp}
   charheight = textsize;
~~~

Note that to scale fonts to the same size as the old True Type package a
scale factor of `0.93376068` is apply to the text size before drawing.

The text size of any class inheriting from `TAttText` can
be changed using the method `SetTextSize` and retrieved using the
method `GetTextSize`.

##  Text Font and Precision

The text font code is combination of the font number and the precision.
~~~ {.cpp}
   Text font code = 10*fontnumber + precision
~~~
Font numbers must be between 1 and 14.

The precision can be:

  - `precision = 0` fast hardware fonts (steps in the size)
  - `precision = 1` scalable and rotatable hardware fonts (see below)
  - `precision = 2` scalable and rotatable hardware fonts
  - `precision = 3` scalable and rotatable hardware fonts. Text size
                           is given in pixels.

The text font and precision of any class inheriting from `TAttText` can
be changed using the method `SetTextFont` and retrieved using the
method `GetTextFont`.

###  Font quality and speed

When precision 0 is used, only the original non-scaled system fonts are
used. The fonts have a minimum (4) and maximum (37) size in pixels. These
fonts are fast and are of good quality. Their size varies with large steps
and they cannot be rotated.
Precision 1 and 2 fonts have a different behaviour depending if the
True Type Fonts (TTF) are used or not. If TTF are used, you always get very good
quality scalable and rotatable fonts. However TTF are slow.

###  How to use True Type Fonts

One can activate the TTF by adding (or activating) the following line
in the `.rootrc` file:

~~~ {.cpp}
   Unix.*.Root.UseTTFonts:     true
~~~

It is possible to check the TTF are in use in a Root session
with the command:

~~~ {.cpp}
   gEnv->Print();
~~~

If the TTF are in use the following line will appear at the beginning of the
printout given by this command:

~~~ {.cpp}
   Unix.*.Root.UseTTFonts:   true                           [Global]
~~~

###  List of the currently supported fonts

~~~ {.cpp}
   Font number         X11 Names             Win32/TTF Names
       1 :       times-medium-i-normal      "Times New Roman"
       2 :       times-bold-r-normal        "Times New Roman"
       3 :       times-bold-i-normal        "Times New Roman"
       4 :       helvetica-medium-r-normal  "Arial"
       5 :       helvetica-medium-o-normal  "Arial"
       6 :       helvetica-bold-r-normal    "Arial"
       7 :       helvetica-bold-o-normal    "Arial"
       8 :       courier-medium-r-normal    "Courier New"
       9 :       courier-medium-o-normal    "Courier New"
      10 :       courier-bold-r-normal      "Courier New"
      11 :       courier-bold-o-normal      "Courier New"
      12 :       symbol-medium-r-normal     "Symbol"
      13 :       times-medium-r-normal      "Times New Roman"
      14 :                                  "Wingdings"
      15 :       Symbol italic (derived from Symbol)
~~~

The following picture shows how each font looks. The number on the left
is the "text font code". In this picture precision 2 was selected.

Begin_Macro
fonts.C
End_Macro
*/

////////////////////////////////////////////////////////////////////////////////
/// AttText default constructor.
///
/// Default text attributes are taken from the current style.

TAttText::TAttText()
{
   if (!gStyle) {
      ResetAttText();
      return;
   }
   fTextAlign = gStyle->GetTextAlign();
   fTextAngle = gStyle->GetTextAngle();
   fTextColor = gStyle->GetTextColor();
   fTextFont  = gStyle->GetTextFont();
   fTextSize  = gStyle->GetTextSize();
}

////////////////////////////////////////////////////////////////////////////////
/// AttText normal constructor.
///
/// Text attributes are taken from the argument list.

TAttText::TAttText(Int_t align, Float_t angle, Color_t color, Style_t font, Float_t tsize)
{
   fTextAlign = align;
   fTextAngle = angle;
   fTextColor = color;
   fTextFont  = font;
   fTextSize  = tsize;
}

////////////////////////////////////////////////////////////////////////////////
/// AttText destructor.

TAttText::~TAttText()
{
}

////////////////////////////////////////////////////////////////////////////////
/// Copy this text attributes to a new TAttText.

void TAttText::Copy(TAttText &atttext) const
{
   atttext.fTextAlign  = fTextAlign;
   atttext.fTextAngle  = fTextAngle;
   atttext.fTextColor  = fTextColor;
   atttext.fTextFont   = fTextFont;
   atttext.fTextSize   = fTextSize;
}

////////////////////////////////////////////////////////////////////////////////
/// Change current text attributes if necessary.

void TAttText::Modify()
{
   if (!gPad) return;

   // Do we need to change font?
   if (!gPad->IsBatch()) {
      gVirtualX->SetTextAngle(fTextAngle);
      Float_t wh = (Float_t)gPad->XtoPixel(gPad->GetX2());
      Float_t hh = (Float_t)gPad->YtoPixel(gPad->GetY1());
      Float_t tsize;
      if (wh < hh)  tsize = fTextSize*wh;
      else          tsize = fTextSize*hh;
      if (fTextFont%10 > 2) tsize = fTextSize;

      if (gVirtualX->GetTextFont() != fTextFont) {
            gVirtualX->SetTextFont(fTextFont);
            gVirtualX->SetTextSize(tsize);
      }
      if (gVirtualX->GetTextSize() != tsize)
            gVirtualX->SetTextSize(tsize);
      gVirtualX->SetTextAlign(fTextAlign);
      gVirtualX->SetTextColor(fTextColor);
   }
   gPad->SetAttTextPS(fTextAlign,fTextAngle,fTextColor,fTextFont,fTextSize);
}

////////////////////////////////////////////////////////////////////////////////
/// Reset this text attributes to default values.

void TAttText::ResetAttText(Option_t *)
{
   fTextAlign  = 11;
   fTextAngle  = 0;
   fTextColor  = 1;
   fTextFont   = 62;
   fTextSize   = 0.05;
}

////////////////////////////////////////////////////////////////////////////////
/// Save text attributes as C++ statement(s) on output stream out.

void TAttText::SaveTextAttributes(std::ostream &out, const char *name, Int_t alidef,
                                  Float_t angdef, Int_t coldef, Int_t fondef,
                                  Float_t sizdef)
{
   if (fTextAlign != alidef) {
      out<<"   "<<name<<"->SetTextAlign("<<fTextAlign<<");"<<std::endl;
   }
   if (fTextColor != coldef) {
      if (fTextColor > 228) {
         TColor::SaveColor(out, fTextColor);
         out<<"   "<<name<<"->SetTextColor(ci);" << std::endl;
      } else
         out<<"   "<<name<<"->SetTextColor("<<fTextColor<<");"<<std::endl;
   }
   if (fTextFont != fondef) {
      out<<"   "<<name<<"->SetTextFont("<<fTextFont<<");"<<std::endl;
   }
   if (fTextSize != sizdef) {
      out<<"   "<<name<<"->SetTextSize("<<fTextSize<<");"<<std::endl;
   }
   if (fTextAngle != angdef) {
      out<<"   "<<name<<"->SetTextAngle("<<fTextAngle<<");"<<std::endl;
   }
}

////////////////////////////////////////////////////////////////////////////////
/// Invoke the DialogCanvas Text attributes.

void TAttText::SetTextAttributes()
{
   TVirtualPadEditor::UpdateTextAttributes(fTextAlign,fTextAngle,fTextColor,
                                           fTextFont,fTextSize);
}

////////////////////////////////////////////////////////////////////////////////
/// Set a transparent marker color. talpha defines the percentage of
/// the color opacity from 0. (fully transparent) to 1. (fully opaque).

void TAttText::SetTextColorAlpha(Color_t tcolor, Float_t talpha)
{
   fTextColor = TColor::GetColorTransparent(tcolor, talpha);
}

////////////////////////////////////////////////////////////////////////////////
/// Set the text size in pixels.
///
/// If the font precision is greater than 2, the text size is set to npixels,
/// otherwise the text size is computed as a percent of the pad size.

void TAttText::SetTextSizePixels(Int_t npixels)
{
   if (fTextFont%10 > 2) {
      fTextSize = Float_t(npixels);
   } else {
      TVirtualPad *pad = gROOT->GetSelectedPad();
      if (!pad) return;
      Float_t dy = pad->AbsPixeltoY(0) - pad->AbsPixeltoY(npixels);
      fTextSize = dy/(pad->GetY2() - pad->GetY1());
   }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMetaImageIO.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include <string>
#include "itkMetaImageIO.h"
#include "itkExceptionObject.h"

namespace itk
{

MetaImageIO::MetaImageIO()
  {
  if(MET_SystemByteOrderMSB())
    m_ByteOrder = BigEndian;
  else
    m_ByteOrder = LittleEndian;
  }

MetaImageIO::~MetaImageIO()
  {
  m_Ifstream.close();
  }

void MetaImageIO::PrintSelf(std::ostream& os, Indent indent) const
  {
  Superclass::PrintSelf(os, indent);
  m_MetaImage.PrintInfo();
  }

void MetaImageIO::SetDataFileName( const char* filename )
  {
  m_MetaImage.ElementDataFileName( filename );
  }

// This method will only test if the header looks like a
// MetaImage.  Some code is redundant with ReadImageInformation
// a StateMachine could provide a better implementation
bool MetaImageIO::CanReadFile( const char* filename )
  {

  std::ifstream inputStream;

  inputStream.open( filename, std::ios::in | std::ios::binary );

  if( inputStream.fail() )
  {
    return false;
  }

  char key[8000];

  inputStream >> key;

  if( inputStream.eof() )
    {
    inputStream.close();
    return false;
    }

  if( strcmp(key,"NDims")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"ObjectType")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"TransformType")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"ID")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"ParentID")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"BinaryData")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"Comment")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"AcquisitionDate")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"Modality")==0 )
    {
    inputStream.close();
    return true;
    }

  inputStream.close();
  return false;

  }

void MetaImageIO::ReadImageInformation()
  {
  if(!m_MetaImage.Read(m_FileName.c_str()), false)
    {
    ExceptionObject exception(__FILE__, __LINE__);
    exception.SetDescription("File cannot be read");
    throw exception;
    }

  if(m_MetaImage.BinaryData())
    {
    this->SetFileType(Binary);
    }
  else
    {
    this->SetFileType(ASCII);
    }

  this->SetNumberOfComponents(m_MetaImage.ElementNumberOfChannels());

  switch(m_MetaImage.ElementType())
    {
    default:
    case MET_OTHER:
    case MET_NONE:
      this->SetPixelType( UNKNOWN );
      this->SetComponentType( UNKNOWN );
      break;
    case MET_CHAR:
    case MET_CHAR_ARRAY:
    case MET_STRING:
    case MET_ASCII_CHAR:
      this->SetPixelType( CHAR );
      this->SetComponentType( CHAR );
      break;
    case MET_UCHAR:
    case MET_UCHAR_ARRAY:
      this->SetPixelType( UCHAR );
      this->SetComponentType( UCHAR );
      break;
    case MET_SHORT:
    case MET_SHORT_ARRAY:
      this->SetPixelType( SHORT );
      this->SetComponentType( SHORT );
      break;
    case MET_USHORT:
    case MET_USHORT_ARRAY:
      this->SetPixelType( USHORT );
      this->SetComponentType( USHORT );
      break;
    case MET_INT:
    case MET_INT_ARRAY:
      this->SetPixelType( INT );
      this->SetComponentType( INT );
      break;
    case MET_UINT:
    case MET_UINT_ARRAY:
      this->SetPixelType( UINT );
      this->SetComponentType( UINT );
      break;
    case MET_FLOAT:
    case MET_FLOAT_ARRAY:
      this->SetPixelType( FLOAT );
      this->SetComponentType( FLOAT );
      break;
    case MET_DOUBLE:
    case MET_DOUBLE_ARRAY:
      this->SetPixelType( DOUBLE );
      this->SetComponentType( DOUBLE );
      break;
    case MET_FLOAT_MATRIX:
      this->SetPixelType( FLOAT );
      this->SetComponentType( FLOAT );
      this->SetNumberOfComponents(m_NumberOfComponents * m_NumberOfComponents);
      break;
    }

  this->SetNumberOfDimensions(m_MetaImage.NDims());

  int i;
  for(i=0; i<(int)m_NumberOfDimensions; i++)
    {
    this->SetDimensions(i, m_MetaImage.DimSize(i));
    this->SetSpacing(i, m_MetaImage.ElementSpacing(i));
    this->SetOrigin(i, m_MetaImage.Position(i));
    }
  }

void MetaImageIO::Read(void* buffer)
  {
  if(!m_MetaImage.Read(m_FileName.c_str(), true, buffer))
    {
    ExceptionObject exception(__FILE__, __LINE__);
    exception.SetDescription("File cannot be read");
    throw exception;
    }

  m_MetaImage.ElementByteOrderFix();
  }

MetaImage * MetaImageIO::GetMetaImagePointer(void)
  {
  return & m_MetaImage;
  }

bool MetaImageIO::CanWriteFile(const char*)
  {
  return true;
  }

void
MetaImageIO
::WriteImageInformation(void)
  {
  }

/**
 *
 */
void
MetaImageIO
::Write( const void* buffer)
  {
  int nDims = this->GetNumberOfDimensions();

  bool binaryData = false;
  if(this->GetFileType() == Binary)
    {
    binaryData = true;
    }

  int nChannels = this->GetNumberOfComponents();

  MET_ValueEnumType eType = MET_OTHER;
  switch(m_PixelType)
    {
    default:
    case UNKNOWN:
          eType = MET_OTHER;
          break;
    case CHAR:
          eType = MET_CHAR;
          break;
    case UCHAR:
          eType = MET_UCHAR;
          break;
    case SHORT:
          eType = MET_SHORT;
          break;
    case USHORT:
          eType = MET_USHORT;
          break;
    case INT:
          eType = MET_INT;
          break;
    case UINT:
          eType = MET_UINT;
          break;
    case FLOAT:
          eType = MET_FLOAT;
          break;
    case DOUBLE:
          eType = MET_DOUBLE;
          break;
    }

  int i;
  int * dSize = new int[nDims];
  float * eSpacing = new float[nDims];
  float * eOrigin = new float[nDims];
  for(i=0; i<nDims; i++)
    {
    dSize[i] = this->GetDimensions(i);
    eSpacing[i] = this->GetSpacing(i);
    eOrigin[i] = this->GetOrigin(i);
    }

  m_MetaImage.InitializeEssential(nDims, dSize, eSpacing, eType, nChannels,
                                  (void *)buffer);
  m_MetaImage.Position(eOrigin);
  m_MetaImage.BinaryData(binaryData);

  std::string dataName;
  dataName = m_FileName + ".raw";
  std::cout << "dataName = " << dataName << std::endl;
  m_MetaImage.Write(m_FileName.c_str(), dataName.c_str());

  delete dSize;
  delete eSpacing;
  delete eOrigin;
  }

} // end namespace itk
<commit_msg>ENH: Removed an extra cout<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkMetaImageIO.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include <string>
#include "itkMetaImageIO.h"
#include "itkExceptionObject.h"

namespace itk
{

MetaImageIO::MetaImageIO()
  {
  if(MET_SystemByteOrderMSB())
    m_ByteOrder = BigEndian;
  else
    m_ByteOrder = LittleEndian;
  }

MetaImageIO::~MetaImageIO()
  {
  m_Ifstream.close();
  }

void MetaImageIO::PrintSelf(std::ostream& os, Indent indent) const
  {
  Superclass::PrintSelf(os, indent);
  m_MetaImage.PrintInfo();
  }

void MetaImageIO::SetDataFileName( const char* filename )
  {
  m_MetaImage.ElementDataFileName( filename );
  }

// This method will only test if the header looks like a
// MetaImage.  Some code is redundant with ReadImageInformation
// a StateMachine could provide a better implementation
bool MetaImageIO::CanReadFile( const char* filename )
  {

  std::ifstream inputStream;

  inputStream.open( filename, std::ios::in | std::ios::binary );

  if( inputStream.fail() )
  {
    return false;
  }

  char key[8000];

  inputStream >> key;

  if( inputStream.eof() )
    {
    inputStream.close();
    return false;
    }

  if( strcmp(key,"NDims")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"ObjectType")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"TransformType")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"ID")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"ParentID")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"BinaryData")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"Comment")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"AcquisitionDate")==0 )
    {
    inputStream.close();
    return true;
    }
  if( strcmp(key,"Modality")==0 )
    {
    inputStream.close();
    return true;
    }

  inputStream.close();
  return false;

  }

void MetaImageIO::ReadImageInformation()
  {
  if(!m_MetaImage.Read(m_FileName.c_str()), false)
    {
    ExceptionObject exception(__FILE__, __LINE__);
    exception.SetDescription("File cannot be read");
    throw exception;
    }

  if(m_MetaImage.BinaryData())
    {
    this->SetFileType(Binary);
    }
  else
    {
    this->SetFileType(ASCII);
    }

  this->SetNumberOfComponents(m_MetaImage.ElementNumberOfChannels());

  switch(m_MetaImage.ElementType())
    {
    default:
    case MET_OTHER:
    case MET_NONE:
      this->SetPixelType( UNKNOWN );
      this->SetComponentType( UNKNOWN );
      break;
    case MET_CHAR:
    case MET_CHAR_ARRAY:
    case MET_STRING:
    case MET_ASCII_CHAR:
      this->SetPixelType( CHAR );
      this->SetComponentType( CHAR );
      break;
    case MET_UCHAR:
    case MET_UCHAR_ARRAY:
      this->SetPixelType( UCHAR );
      this->SetComponentType( UCHAR );
      break;
    case MET_SHORT:
    case MET_SHORT_ARRAY:
      this->SetPixelType( SHORT );
      this->SetComponentType( SHORT );
      break;
    case MET_USHORT:
    case MET_USHORT_ARRAY:
      this->SetPixelType( USHORT );
      this->SetComponentType( USHORT );
      break;
    case MET_INT:
    case MET_INT_ARRAY:
      this->SetPixelType( INT );
      this->SetComponentType( INT );
      break;
    case MET_UINT:
    case MET_UINT_ARRAY:
      this->SetPixelType( UINT );
      this->SetComponentType( UINT );
      break;
    case MET_FLOAT:
    case MET_FLOAT_ARRAY:
      this->SetPixelType( FLOAT );
      this->SetComponentType( FLOAT );
      break;
    case MET_DOUBLE:
    case MET_DOUBLE_ARRAY:
      this->SetPixelType( DOUBLE );
      this->SetComponentType( DOUBLE );
      break;
    case MET_FLOAT_MATRIX:
      this->SetPixelType( FLOAT );
      this->SetComponentType( FLOAT );
      this->SetNumberOfComponents(m_NumberOfComponents * m_NumberOfComponents);
      break;
    }

  this->SetNumberOfDimensions(m_MetaImage.NDims());

  int i;
  for(i=0; i<(int)m_NumberOfDimensions; i++)
    {
    this->SetDimensions(i, m_MetaImage.DimSize(i));
    this->SetSpacing(i, m_MetaImage.ElementSpacing(i));
    this->SetOrigin(i, m_MetaImage.Position(i));
    }
  }

void MetaImageIO::Read(void* buffer)
  {
  if(!m_MetaImage.Read(m_FileName.c_str(), true, buffer))
    {
    ExceptionObject exception(__FILE__, __LINE__);
    exception.SetDescription("File cannot be read");
    throw exception;
    }

  m_MetaImage.ElementByteOrderFix();
  }

MetaImage * MetaImageIO::GetMetaImagePointer(void)
  {
  return & m_MetaImage;
  }

bool MetaImageIO::CanWriteFile(const char*)
  {
  return true;
  }

void
MetaImageIO
::WriteImageInformation(void)
  {
  }

/**
 *
 */
void
MetaImageIO
::Write( const void* buffer)
  {
  int nDims = this->GetNumberOfDimensions();

  bool binaryData = false;
  if(this->GetFileType() == Binary)
    {
    binaryData = true;
    }

  int nChannels = this->GetNumberOfComponents();

  MET_ValueEnumType eType = MET_OTHER;
  switch(m_PixelType)
    {
    default:
    case UNKNOWN:
          eType = MET_OTHER;
          break;
    case CHAR:
          eType = MET_CHAR;
          break;
    case UCHAR:
          eType = MET_UCHAR;
          break;
    case SHORT:
          eType = MET_SHORT;
          break;
    case USHORT:
          eType = MET_USHORT;
          break;
    case INT:
          eType = MET_INT;
          break;
    case UINT:
          eType = MET_UINT;
          break;
    case FLOAT:
          eType = MET_FLOAT;
          break;
    case DOUBLE:
          eType = MET_DOUBLE;
          break;
    }

  int i;
  int * dSize = new int[nDims];
  float * eSpacing = new float[nDims];
  float * eOrigin = new float[nDims];
  for(i=0; i<nDims; i++)
    {
    dSize[i] = this->GetDimensions(i);
    eSpacing[i] = this->GetSpacing(i);
    eOrigin[i] = this->GetOrigin(i);
    }

  m_MetaImage.InitializeEssential(nDims, dSize, eSpacing, eType, nChannels,
                                  (void *)buffer);
  m_MetaImage.Position(eOrigin);
  m_MetaImage.BinaryData(binaryData);

  std::string dataName;
  dataName = m_FileName + ".raw";
  m_MetaImage.Write(m_FileName.c_str(), dataName.c_str());

  delete dSize;
  delete eSpacing;
  delete eOrigin;
  }

} // end namespace itk
<|endoftext|>


<commit_before>/*
	This file is part of the E_GUI library.
	Copyright (C) 2008-2012 Benjamin Eikel <benjamin@eikel.org>
	Copyright (C) 2008-2012 Claudius Jähn <claudius@uni-paderborn.de>
	Copyright (C) 2008-2012 Ralf Petring <ralf@petring.net>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "E_Connector.h"

#include <EScript/EScript.h>
#include <EScript/Utils/DeprecatedMacros.h>
#include "../ELibGUI.h"

namespace E_GUI {

//! [static] initMembers
void E_Connector::init(EScript::Namespace & lib) {
	EScript::Type * typeObject = getTypeObject();
	declareConstant(&lib,getClassName(),typeObject);
	addFactory<GUI::Connector,E_Connector>();

	using namespace GUI;

	//! [ESF] (static) Array GUI.findConnectors( container,endpoint )
	ES_FUNCTION2(&lib,"findConnectors",2,2,{
		EScript::Array * a = EScript::Array::create();
		std::list<GUI::Connector *> connectors;
		GUI::Connector::findConnectors(	parameter[0].to<Container*>(rt),
										parameter[1].to<Component*>(rt),connectors);

		for(const auto & connector : connectors)
			a->pushBack(EScript::create(connector));
		return a;
	})

	//! [ESMF] Component Connector.getFirstComponent()
	ES_MFUN(typeObject,Connector,"getFirstComponent",0,0,	EScript::create(thisObj->getFirstComponent()))

	//! [ESMF] Number Connector.getLength()
	ES_MFUN(typeObject,const Connector,"getLength",0,0,		thisObj->getLength())

	//! [ESMF] Component Connector.getSecondComponent()
	ES_MFUN(typeObject,Connector,"getSecondComponent",0,0,	EScript::create(thisObj->getSecondComponent()))

	//! [ESMF] self Connector.setFirstComponent(Component|nullptr)
	ES_MFUN(typeObject,Connector,"setFirstComponent",1,1,(
			thisObj->setFirstComponent(
				parameter[0].toType<E_Component>() == nullptr ?
								nullptr :
								(**parameter[0].toType<E_Component>())),thisEObj))

	//! [ESMF] self Connector.setSecondComponent(Component|nullptr)
	ES_MFUN(typeObject,Connector,"setSecondComponent",1,1,(
			thisObj->setSecondComponent(
				parameter[0].toType<E_Component>() == nullptr ?
								nullptr :
								(**parameter[0].toType<E_Component>())),thisEObj))

}

}
<commit_msg>Replace deprecated macros.<commit_after>/*
	This file is part of the E_GUI library.
	Copyright (C) 2008-2012 Benjamin Eikel <benjamin@eikel.org>
	Copyright (C) 2008-2012 Claudius Jähn <claudius@uni-paderborn.de>
	Copyright (C) 2008-2012 Ralf Petring <ralf@petring.net>

	This library is subject to the terms of the Mozilla Public License, v. 2.0.
	You should have received a copy of the MPL along with this library; see the
	file LICENSE. If not, you can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "E_Connector.h"

#include <EScript/EScript.h>
#include "../ELibGUI.h"

namespace E_GUI {

//! [static] initMembers
void E_Connector::init(EScript::Namespace & lib) {
	EScript::Type * typeObject = getTypeObject();
	declareConstant(&lib,getClassName(),typeObject);
	addFactory<GUI::Connector,E_Connector>();

	using namespace GUI;

	//! [ESF] (static) Array GUI.findConnectors( container,endpoint )
	ES_FUNCTION(&lib,"findConnectors",2,2,{
		EScript::Array * a = EScript::Array::create();
		std::list<GUI::Connector *> connectors;
		GUI::Connector::findConnectors(	parameter[0].to<Container*>(rt),
										parameter[1].to<Component*>(rt),connectors);

		for(const auto & connector : connectors)
			a->pushBack(EScript::create(connector));
		return a;
	})

	//! [ESMF] Component Connector.getFirstComponent()
	ES_MFUN(typeObject,Connector,"getFirstComponent",0,0,	EScript::create(thisObj->getFirstComponent()))

	//! [ESMF] Number Connector.getLength()
	ES_MFUN(typeObject,const Connector,"getLength",0,0,		thisObj->getLength())

	//! [ESMF] Component Connector.getSecondComponent()
	ES_MFUN(typeObject,Connector,"getSecondComponent",0,0,	EScript::create(thisObj->getSecondComponent()))

	//! [ESMF] self Connector.setFirstComponent(Component|nullptr)
	ES_MFUN(typeObject,Connector,"setFirstComponent",1,1,(
			thisObj->setFirstComponent(
				parameter[0].toType<E_Component>() == nullptr ?
								nullptr :
								(**parameter[0].toType<E_Component>())),thisEObj))

	//! [ESMF] self Connector.setSecondComponent(Component|nullptr)
	ES_MFUN(typeObject,Connector,"setSecondComponent",1,1,(
			thisObj->setSecondComponent(
				parameter[0].toType<E_Component>() == nullptr ?
								nullptr :
								(**parameter[0].toType<E_Component>())),thisEObj))

}

}
<|endoftext|>


<commit_before>#include "anki/scene/ParticleEmitter.h"
#include "anki/scene/Scene.h"
#include "anki/resource/Model.h"
#include "anki/util/Functions.h"
#include "anki/physics/PhysWorld.h"
#include <limits>

namespace anki {

//==============================================================================
// Misc                                                                        =
//==============================================================================

//==============================================================================
F32 getRandom(F32 initial, F32 deviation)
{
	return (deviation == 0.0) ? initial
		: initial + randFloat(deviation) * 2.0 - deviation;
}

//==============================================================================
Vec3 getRandom(const Vec3& initial, const Vec3& deviation)
{
	if(deviation == Vec3(0.0))
	{
		return initial;
	}
	else
	{
		Vec3 out;
		for(U i = 0; i < 3; i++)
		{
			out[i] = getRandom(initial[i], deviation[i]);
		}
		return out;
	}
}

//==============================================================================
// ParticleBase                                                                =
//==============================================================================

//==============================================================================
ParticleBase::ParticleBase(
	ParticleType type_,
	// SceneNode
	const char* name, Scene* scene,
	// Movable
	U32 movableFlags, Movable* movParent)
	: SceneNode(name, scene), Movable(movableFlags, movParent, *this),
		type(type_)
{}

//==============================================================================
ParticleBase::~ParticleBase()
{}

//==============================================================================
void ParticleBase::revive(const ParticleEmitter& pe,
	F32 /*prevUpdateTime*/, F32 crntTime)
{
	ANKI_ASSERT(isDead());
	const ParticleEmitterProperties& props = pe;

	// life
	timeOfDeath = getRandom(crntTime + props.particle.life,
		props.particle.lifeDeviation);
	timeOfBirth = crntTime;
}

//==============================================================================
// ParticleSimple                                                              =
//==============================================================================

//==============================================================================
ParticleSimple::ParticleSimple(
	// SceneNode
	const char* name, Scene* scene,
	// Movable
	U32 movableFlags, Movable* movParent)
	: ParticleBase(PT_SIMPLE, name, scene, movableFlags, movParent)
{}

//==============================================================================
void ParticleSimple::simulate(const ParticleEmitter& pe,
	F32 prevUpdateTime, F32 crntTime)
{
	F32 dt = crntTime - prevUpdateTime;

	ANKI_ASSERT(props.particle.gravity.getLength() > 0.0);

	Transform trf = getWorldTransform();
	Vec3 xp = trf.getOrigin();
	Vec3 xc = acceleration * (dt * dt) + velocity * dt + xp;

	trf.setOrigin(xc);

	setLocalTransform(trf);

	velocity += acceleration * dt;
}

//==============================================================================
void ParticleSimple::revive(const ParticleEmitter& pe,
	F32 prevUpdateTime, F32 crntTime)
{
	ParticleBase::revive(pe, prevUpdateTime, crntTime);
	velocity = Vec3(0.0);

	const ParticleEmitterProperties& props = pe;

	acceleration = getRandom(props.particle.gravity,
			props.particle.gravityDeviation);

	// Set the initial position
	Vec3 pos = getRandom(props.particle.startingPos,
		props.particle.startingPosDeviation);

	pos += pe.getWorldTransform().getOrigin();

	Transform trf;
	trf.setIdentity();
	trf.setOrigin(pos);
	setLocalTransform(trf);
}

//==============================================================================
// Particle                                                                    =
//==============================================================================

//==============================================================================
Particle::Particle(
	// Scene
	const char* name, Scene* scene,
	// Movable
	U32 movableFlags, Movable* movParent,
	// RigidBody
	PhysWorld* masterContainer, const Initializer& init)
	: ParticleBase(PT_PHYSICS, name, scene, movableFlags, movParent),
		RigidBody(masterContainer, init, this)
{}

//==============================================================================
Particle::~Particle()
{}

//==============================================================================
void Particle::revive(const ParticleEmitter& pe,
	F32 prevUpdateTime, F32 crntTime)
{
	ParticleBase::revive(pe, prevUpdateTime, crntTime);

	const ParticleEmitterProperties& props = pe;

	RigidBody& body = *this;

	// pre calculate
	Bool forceFlag = props.forceEnabled;
	Bool worldGravFlag = props.wordGravityEnabled;

	// activate it (Bullet stuff)
	body.forceActivationState(ACTIVE_TAG);
	body.activate();
	body.clearForces();
	body.setLinearVelocity(btVector3(0.0, 0.0, 0.0));
	body.setAngularVelocity(btVector3(0.0, 0.0, 0.0));

	// force
	if(forceFlag)
	{
		Vec3 forceDir = getRandom(props.particle.forceDirection,
			props.particle.forceDirectionDeviation);
		forceDir.normalize();

		if(!pe.identityRotation)
		{
			// the forceDir depends on the particle emitter rotation
			forceDir = pe.getWorldTransform().getRotation() * forceDir;
		}

		F32 forceMag = getRandom(props.particle.forceMagnitude,
			props.particle.forceMagnitudeDeviation);

		body.applyCentralForce(toBt(forceDir * forceMag));
	}

	// gravity
	if(!worldGravFlag)
	{
		body.setGravity(toBt(getRandom(props.particle.gravity,
			props.particle.gravityDeviation)));
	}

	// Starting pos. In local space
	Vec3 pos = getRandom(props.particle.startingPos,
		props.particle.startingPosDeviation);

	if(pe.identityRotation)
	{
		pos += pe.getWorldTransform().getOrigin();
	}
	else
	{
		pos.transform(pe.getWorldTransform());
	}

	btTransform trf(
		toBt(Transform(pos, pe.getWorldTransform().getRotation(), 1.0)));
	body.setWorldTransform(trf);
}

//==============================================================================
// ParticleEmitter                                                             =
//==============================================================================

//==============================================================================
ParticleEmitter::ParticleEmitter(
	const char* filename,
	// SceneNode
	const char* name, Scene* scene,
	// Movable
	U32 movableFlags, Movable* movParent)
	: SceneNode(name, scene), Spatial(this, &aabb),
		Movable(movableFlags, movParent, *this)
{
	// Load resource
	particleEmitterResource.load(filename);

	// copy the resource to me
	ParticleEmitterProperties& me = *this;
	const ParticleEmitterProperties& other =
		particleEmitterResource->getProperties();
	me = other;

	if(usePhysicsEngine)
	{
		createParticlesSimulation(scene);
	}
	else
	{
		createParticlesSimpleSimulation(scene);
	}

	timeLeftForNextEmission = 0.0;
	instancesCount = particles.size();
	Renderable::init(*this);

	// Find the "alpha" material variable
	for(auto it = Renderable::getVariablesBegin();
		it != Renderable::getVariablesEnd(); ++it)
	{
		if((*it)->getName() == "alpha")
		{
			alphaRenderableVar = *it;
		}
	}
}

//==============================================================================
ParticleEmitter::~ParticleEmitter()
{}

//==============================================================================
const ModelPatchBase& ParticleEmitter::getRenderableModelPatchBase() const
{
	return *particleEmitterResource->getModel().getModelPatches()[0];
}

//==============================================================================
const Material& ParticleEmitter::getRenderableMaterial() const
{
	return
		particleEmitterResource->getModel().getModelPatches()[0]->getMaterial();
}

//==============================================================================
void ParticleEmitter::movableUpdate()
{
	identityRotation =
		getWorldTransform().getRotation() == Mat3::getIdentity();
}

//==============================================================================
void ParticleEmitter::createParticlesSimulation(Scene* scene)
{
	// create the particles
	collShape.reset(new btSphereShape(particle.size));

	RigidBody::Initializer binit;
	binit.shape = collShape.get();
	binit.group = PhysWorld::CG_PARTICLE;
	binit.mask = PhysWorld::CG_MAP;

	for(U i = 0; i < maxNumOfParticles; i++)
	{
		binit.mass = getRandom(particle.mass, particle.massDeviation);

		Particle* part = new Particle(
			(getName() + std::to_string(i)).c_str(), scene,
			Movable::MF_NONE, nullptr,
			&scene->getPhysics(), binit);

		particles.push_back(part);

		part->forceActivationState(DISABLE_SIMULATION);
	}
}

//==============================================================================
void ParticleEmitter::createParticlesSimpleSimulation(Scene* scene)
{
	for(U i = 0; i < maxNumOfParticles; i++)
	{
		ParticleSimple* p = new ParticleSimple(
			(getName() + std::to_string(i)).c_str(),
			scene, Movable::MF_NONE, nullptr);

		particles.push_back(p);
	}
}

//==============================================================================
void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
{
	SceneNode::frameUpdate(prevUpdateTime, crntTime, frame);

	// - Deactivate the dead particles
	// - Calc the AABB
	// - Calc the instancing stuff
	//
	Vec3 aabbmin(std::numeric_limits<F32>::max());
	Vec3 aabbmax(std::numeric_limits<F32>::min());
	instancingTransformations.clear();
	Vector<F32> alpha;
	for(ParticleBase* p : particles)
	{
		if(p->isDead())
		{
			// if its already dead so dont deactivate it again
			continue;
		}

		if(p->getTimeOfDeath() < crntTime)
		{
			// Just died
			p->kill();
		}
		else
		{
			// This will calculate a new world transformation
			p->simulate(*this, prevUpdateTime, crntTime);

			// An alive
			const Vec3& origin = p->Movable::getWorldTransform().getOrigin();

			for(U i = 0; i < 3; i++)
			{
				aabbmin[i] = std::min(aabbmin[i], origin[i]);
				aabbmax[i] = std::max(aabbmax[i], origin[i]);
			}

			F32 lifePercent = (crntTime - p->getTimeOfBirth())
				/ (p->getTimeOfDeath() - p->getTimeOfBirth());

			Transform trf = p->Movable::getWorldTransform();
			// XXX set a flag for scale
			trf.setScale(
				particle.size + (lifePercent * particle.sizeAnimation));

			instancingTransformations.push_back(trf);

			// Set alpha
			if(alphaRenderableVar)
			{
				alpha.push_back((1.0 - lifePercent) * particle.alpha);
			}
		}
	}

	instancesCount = instancingTransformations.size();
	if(instancesCount != 0)
	{
		aabb = Aabb(aabbmin - particle.size, aabbmax + particle.size);
	}
	else
	{
		aabb = Aabb(Vec3(0.0), Vec3(0.01));
	}
	spatialMarkUpdated();

	if(alphaRenderableVar)
	{
		alphaRenderableVar->setValues(&alpha[0], alpha.size());
	}

	//
	// Emit new particles
	//
	if(timeLeftForNextEmission <= 0.0)
	{
		U particlesCount = 0; // How many particles I am allowed to emmit
		for(ParticleBase* pp : particles)
		{
			ParticleBase& p = *pp;
			if(!p.isDead())
			{
				// its alive so skip it
				continue;
			}

			p.revive(*this, prevUpdateTime, crntTime);

			// do the rest
			++particlesCount;
			if(particlesCount >= particlesPerEmittion)
			{
				break;
			}
		} // end for all particles

		timeLeftForNextEmission = emissionPeriod;
	} // end if can emit
	else
	{
		timeLeftForNextEmission -= crntTime - prevUpdateTime;
	}
}

} // end namespace anki
<commit_msg>Particles: Making the alpha transition better<commit_after>#include "anki/scene/ParticleEmitter.h"
#include "anki/scene/Scene.h"
#include "anki/resource/Model.h"
#include "anki/util/Functions.h"
#include "anki/physics/PhysWorld.h"
#include <limits>

namespace anki {

//==============================================================================
// Misc                                                                        =
//==============================================================================

//==============================================================================
F32 getRandom(F32 initial, F32 deviation)
{
	return (deviation == 0.0) ? initial
		: initial + randFloat(deviation) * 2.0 - deviation;
}

//==============================================================================
Vec3 getRandom(const Vec3& initial, const Vec3& deviation)
{
	if(deviation == Vec3(0.0))
	{
		return initial;
	}
	else
	{
		Vec3 out;
		for(U i = 0; i < 3; i++)
		{
			out[i] = getRandom(initial[i], deviation[i]);
		}
		return out;
	}
}

//==============================================================================
// ParticleBase                                                                =
//==============================================================================

//==============================================================================
ParticleBase::ParticleBase(
	ParticleType type_,
	// SceneNode
	const char* name, Scene* scene,
	// Movable
	U32 movableFlags, Movable* movParent)
	: SceneNode(name, scene), Movable(movableFlags, movParent, *this),
		type(type_)
{}

//==============================================================================
ParticleBase::~ParticleBase()
{}

//==============================================================================
void ParticleBase::revive(const ParticleEmitter& pe,
	F32 /*prevUpdateTime*/, F32 crntTime)
{
	ANKI_ASSERT(isDead());
	const ParticleEmitterProperties& props = pe;

	// life
	timeOfDeath = getRandom(crntTime + props.particle.life,
		props.particle.lifeDeviation);
	timeOfBirth = crntTime;
}

//==============================================================================
// ParticleSimple                                                              =
//==============================================================================

//==============================================================================
ParticleSimple::ParticleSimple(
	// SceneNode
	const char* name, Scene* scene,
	// Movable
	U32 movableFlags, Movable* movParent)
	: ParticleBase(PT_SIMPLE, name, scene, movableFlags, movParent)
{}

//==============================================================================
void ParticleSimple::simulate(const ParticleEmitter& pe,
	F32 prevUpdateTime, F32 crntTime)
{
	F32 dt = crntTime - prevUpdateTime;

	ANKI_ASSERT(props.particle.gravity.getLength() > 0.0);

	Transform trf = getWorldTransform();
	Vec3 xp = trf.getOrigin();
	Vec3 xc = acceleration * (dt * dt) + velocity * dt + xp;

	trf.setOrigin(xc);

	setLocalTransform(trf);

	velocity += acceleration * dt;
}

//==============================================================================
void ParticleSimple::revive(const ParticleEmitter& pe,
	F32 prevUpdateTime, F32 crntTime)
{
	ParticleBase::revive(pe, prevUpdateTime, crntTime);
	velocity = Vec3(0.0);

	const ParticleEmitterProperties& props = pe;

	acceleration = getRandom(props.particle.gravity,
			props.particle.gravityDeviation);

	// Set the initial position
	Vec3 pos = getRandom(props.particle.startingPos,
		props.particle.startingPosDeviation);

	pos += pe.getWorldTransform().getOrigin();

	Transform trf;
	trf.setIdentity();
	trf.setOrigin(pos);
	setLocalTransform(trf);
}

//==============================================================================
// Particle                                                                    =
//==============================================================================

//==============================================================================
Particle::Particle(
	// Scene
	const char* name, Scene* scene,
	// Movable
	U32 movableFlags, Movable* movParent,
	// RigidBody
	PhysWorld* masterContainer, const Initializer& init)
	: ParticleBase(PT_PHYSICS, name, scene, movableFlags, movParent),
		RigidBody(masterContainer, init, this)
{}

//==============================================================================
Particle::~Particle()
{}

//==============================================================================
void Particle::revive(const ParticleEmitter& pe,
	F32 prevUpdateTime, F32 crntTime)
{
	ParticleBase::revive(pe, prevUpdateTime, crntTime);

	const ParticleEmitterProperties& props = pe;

	RigidBody& body = *this;

	// pre calculate
	Bool forceFlag = props.forceEnabled;
	Bool worldGravFlag = props.wordGravityEnabled;

	// activate it (Bullet stuff)
	body.forceActivationState(ACTIVE_TAG);
	body.activate();
	body.clearForces();
	body.setLinearVelocity(btVector3(0.0, 0.0, 0.0));
	body.setAngularVelocity(btVector3(0.0, 0.0, 0.0));

	// force
	if(forceFlag)
	{
		Vec3 forceDir = getRandom(props.particle.forceDirection,
			props.particle.forceDirectionDeviation);
		forceDir.normalize();

		if(!pe.identityRotation)
		{
			// the forceDir depends on the particle emitter rotation
			forceDir = pe.getWorldTransform().getRotation() * forceDir;
		}

		F32 forceMag = getRandom(props.particle.forceMagnitude,
			props.particle.forceMagnitudeDeviation);

		body.applyCentralForce(toBt(forceDir * forceMag));
	}

	// gravity
	if(!worldGravFlag)
	{
		body.setGravity(toBt(getRandom(props.particle.gravity,
			props.particle.gravityDeviation)));
	}

	// Starting pos. In local space
	Vec3 pos = getRandom(props.particle.startingPos,
		props.particle.startingPosDeviation);

	if(pe.identityRotation)
	{
		pos += pe.getWorldTransform().getOrigin();
	}
	else
	{
		pos.transform(pe.getWorldTransform());
	}

	btTransform trf(
		toBt(Transform(pos, pe.getWorldTransform().getRotation(), 1.0)));
	body.setWorldTransform(trf);
}

//==============================================================================
// ParticleEmitter                                                             =
//==============================================================================

//==============================================================================
ParticleEmitter::ParticleEmitter(
	const char* filename,
	// SceneNode
	const char* name, Scene* scene,
	// Movable
	U32 movableFlags, Movable* movParent)
	: SceneNode(name, scene), Spatial(this, &aabb),
		Movable(movableFlags, movParent, *this)
{
	// Load resource
	particleEmitterResource.load(filename);

	// copy the resource to me
	ParticleEmitterProperties& me = *this;
	const ParticleEmitterProperties& other =
		particleEmitterResource->getProperties();
	me = other;

	if(usePhysicsEngine)
	{
		createParticlesSimulation(scene);
	}
	else
	{
		createParticlesSimpleSimulation(scene);
	}

	timeLeftForNextEmission = 0.0;
	instancesCount = particles.size();
	Renderable::init(*this);

	// Find the "alpha" material variable
	for(auto it = Renderable::getVariablesBegin();
		it != Renderable::getVariablesEnd(); ++it)
	{
		if((*it)->getName() == "alpha")
		{
			alphaRenderableVar = *it;
		}
	}
}

//==============================================================================
ParticleEmitter::~ParticleEmitter()
{}

//==============================================================================
const ModelPatchBase& ParticleEmitter::getRenderableModelPatchBase() const
{
	return *particleEmitterResource->getModel().getModelPatches()[0];
}

//==============================================================================
const Material& ParticleEmitter::getRenderableMaterial() const
{
	return
		particleEmitterResource->getModel().getModelPatches()[0]->getMaterial();
}

//==============================================================================
void ParticleEmitter::movableUpdate()
{
	identityRotation =
		getWorldTransform().getRotation() == Mat3::getIdentity();
}

//==============================================================================
void ParticleEmitter::createParticlesSimulation(Scene* scene)
{
	// create the particles
	collShape.reset(new btSphereShape(particle.size));

	RigidBody::Initializer binit;
	binit.shape = collShape.get();
	binit.group = PhysWorld::CG_PARTICLE;
	binit.mask = PhysWorld::CG_MAP;

	for(U i = 0; i < maxNumOfParticles; i++)
	{
		binit.mass = getRandom(particle.mass, particle.massDeviation);

		Particle* part = new Particle(
			(getName() + std::to_string(i)).c_str(), scene,
			Movable::MF_NONE, nullptr,
			&scene->getPhysics(), binit);

		particles.push_back(part);

		part->forceActivationState(DISABLE_SIMULATION);
	}
}

//==============================================================================
void ParticleEmitter::createParticlesSimpleSimulation(Scene* scene)
{
	for(U i = 0; i < maxNumOfParticles; i++)
	{
		ParticleSimple* p = new ParticleSimple(
			(getName() + std::to_string(i)).c_str(),
			scene, Movable::MF_NONE, nullptr);

		particles.push_back(p);
	}
}

//==============================================================================
void ParticleEmitter::frameUpdate(F32 prevUpdateTime, F32 crntTime, I frame)
{
	SceneNode::frameUpdate(prevUpdateTime, crntTime, frame);

	// - Deactivate the dead particles
	// - Calc the AABB
	// - Calc the instancing stuff
	//
	Vec3 aabbmin(std::numeric_limits<F32>::max());
	Vec3 aabbmax(std::numeric_limits<F32>::min());
	instancingTransformations.clear();
	Vector<F32> alpha;
	for(ParticleBase* p : particles)
	{
		if(p->isDead())
		{
			// if its already dead so dont deactivate it again
			continue;
		}

		if(p->getTimeOfDeath() < crntTime)
		{
			// Just died
			p->kill();
		}
		else
		{
			// This will calculate a new world transformation
			p->simulate(*this, prevUpdateTime, crntTime);

			// An alive
			const Vec3& origin = p->Movable::getWorldTransform().getOrigin();

			for(U i = 0; i < 3; i++)
			{
				aabbmin[i] = std::min(aabbmin[i], origin[i]);
				aabbmax[i] = std::max(aabbmax[i], origin[i]);
			}

			F32 lifePercent = (crntTime - p->getTimeOfBirth())
				/ (p->getTimeOfDeath() - p->getTimeOfBirth());

			Transform trf = p->Movable::getWorldTransform();
			// XXX set a flag for scale
			trf.setScale(
				particle.size + (lifePercent * particle.sizeAnimation));

			instancingTransformations.push_back(trf);

			// Set alpha
			if(alphaRenderableVar)
			{
				alpha.push_back(
					sin((lifePercent) * getPi<F32>())
					* particle.alpha);
			}
		}
	}

	instancesCount = instancingTransformations.size();
	if(instancesCount != 0)
	{
		aabb = Aabb(aabbmin - particle.size, aabbmax + particle.size);
	}
	else
	{
		aabb = Aabb(Vec3(0.0), Vec3(0.01));
	}
	spatialMarkUpdated();

	if(alphaRenderableVar)
	{
		alphaRenderableVar->setValues(&alpha[0], alpha.size());
	}

	//
	// Emit new particles
	//
	if(timeLeftForNextEmission <= 0.0)
	{
		U particlesCount = 0; // How many particles I am allowed to emmit
		for(ParticleBase* pp : particles)
		{
			ParticleBase& p = *pp;
			if(!p.isDead())
			{
				// its alive so skip it
				continue;
			}

			p.revive(*this, prevUpdateTime, crntTime);

			// do the rest
			++particlesCount;
			if(particlesCount >= particlesPerEmittion)
			{
				break;
			}
		} // end for all particles

		timeLeftForNextEmission = emissionPeriod;
	} // end if can emit
	else
	{
		timeLeftForNextEmission -= crntTime - prevUpdateTime;
	}
}

} // end namespace anki
<|endoftext|>


<commit_before>/*******************************************************************************
 *
 * X testing environment - Google Test environment feat. dummy x server
 *
 * Copyright (C) 2011, 2012 Canonical Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 ******************************************************************************/

#include <getopt.h>

#include <csignal>

#include <gtest/gtest.h>

#include "xorg/gtest/xorg-gtest-environment.h"
#include "defines.h"

namespace {

int help = false;
int no_dummy_server = false;
int xorg_conf_specified = false;
int xorg_display_specified = false;
int xorg_logfile_specified = false;
int server_specified = false;

const struct option longopts[] = {
  { "help", no_argument, &help, true, },
  { "no-dummy-server", no_argument, &no_dummy_server, true, },
  { "xorg-conf", required_argument, &xorg_conf_specified, true, },
  { "xorg-display", required_argument, &xorg_display_specified, true, },
  { "xorg-logfile", required_argument, &xorg_logfile_specified, true, },
  { "server", required_argument, &server_specified, true, },
  { NULL, 0, NULL, 0 }
};

} // namespace

xorg::testing::Environment* environment = NULL;

static void signal_handler(int signum) {
  if (environment)
    environment->Kill();

  /* This will call the default handler because we used SA_RESETHAND */
  raise(signum);
}

static void setup_signal_handlers() {
  static const int signals[] = {
    SIGHUP,
    SIGTERM,
    SIGQUIT,
    SIGILL,
    SIGABRT,
    SIGFPE,
    SIGSEGV,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGUSR1,
    SIGUSR2,
    SIGBUS,
    SIGPOLL,
    SIGPROF,
    SIGSYS,
    SIGTRAP,
    SIGVTALRM,
    SIGXCPU,
    SIGXFSZ,
    SIGIOT,
    SIGSTKFLT,
    SIGIO,
    SIGPWR,
    SIGUNUSED,
  };

  struct sigaction action;
  action.sa_handler = signal_handler;
  sigemptyset(&action.sa_mask);
  action.sa_flags = SA_RESETHAND;

  for (unsigned i = 0; i < sizeof(signals) / sizeof(signals[0]); ++i)
    if (sigaction(signals[i], &action, NULL))
      std::cerr << "Warning: Failed to set signal handler for signal "
                << signals[i] << "\n";
}

static int usage(int exitcode) {
  std::cout << "\nAdditional options:\n";
  std::cout << "    --no-dummy-server: Use the currently running X server "
               "for testing\n";
  std::cout << "    --xorg-conf: Path to xorg configuration file\n";
  std::cout << "    --server: Path to X server executable\n";
  std::cout << "    --xorg-display: xorg display port\n";
  std::cout << "    --xorg-logfile: xorg logfile filename. See -logfile in \"man Xorg\".\n"
               "                    Its default value is " DEFAULT_XORG_LOGFILE ".\n";
  return exitcode;
}

int main(int argc, char *argv[]) {
  std::string xorg_conf_path;
  std::string xorg_log_file_path;
  int xorg_display = -1;
  std::string server;

  setup_signal_handlers();

  testing::InitGoogleTest(&argc, argv);

  /* Reset getopt state */
  optind = 0;

  while (true) {
    int ret;
    int index;
    ret = getopt_long(argc, argv, "", longopts, &index);

    if (ret == -1)
      break;

    if (ret == '?')
      exit(-1);

    switch (index) {
      case 2:
        xorg_conf_path = optarg;
        break;

      case 3:
        xorg_display = atoi(optarg);
        break;

      case 4:
        xorg_log_file_path = optarg;
        break;

      case 5:
        server = optarg;
        break;

      default:
        break;
    }
  }

  if (help)
    return usage(-1);

  if (!no_dummy_server) {
    environment = new xorg::testing::Environment;

    if (xorg_conf_specified)
      environment->SetConfigFile(xorg_conf_path);

    if (server_specified)
      environment->SetServerPath(server);

    if (xorg_display_specified)
      environment->SetDisplayNumber(xorg_display);

    if (xorg_logfile_specified)
      environment->SetLogFile(xorg_log_file_path);

    testing::AddGlobalTestEnvironment(environment);
  }

  return RUN_ALL_TESTS();
}
<commit_msg>xorg-gtest-main: fix trailing whitespace<commit_after>/*******************************************************************************
 *
 * X testing environment - Google Test environment feat. dummy x server
 *
 * Copyright (C) 2011, 2012 Canonical Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 ******************************************************************************/

#include <getopt.h>

#include <csignal>

#include <gtest/gtest.h>

#include "xorg/gtest/xorg-gtest-environment.h"
#include "defines.h"

namespace {

int help = false;
int no_dummy_server = false;
int xorg_conf_specified = false;
int xorg_display_specified = false;
int xorg_logfile_specified = false;
int server_specified = false;

const struct option longopts[] = {
  { "help", no_argument, &help, true, },
  { "no-dummy-server", no_argument, &no_dummy_server, true, },
  { "xorg-conf", required_argument, &xorg_conf_specified, true, },
  { "xorg-display", required_argument, &xorg_display_specified, true, },
  { "xorg-logfile", required_argument, &xorg_logfile_specified, true, },
  { "server", required_argument, &server_specified, true, },
  { NULL, 0, NULL, 0 }
};

} // namespace

xorg::testing::Environment* environment = NULL;

static void signal_handler(int signum) {
  if (environment)
    environment->Kill();

  /* This will call the default handler because we used SA_RESETHAND */
  raise(signum);
}

static void setup_signal_handlers() {
  static const int signals[] = {
    SIGHUP,
    SIGTERM,
    SIGQUIT,
    SIGILL,
    SIGABRT,
    SIGFPE,
    SIGSEGV,
    SIGPIPE,
    SIGALRM,
    SIGTERM,
    SIGUSR1,
    SIGUSR2,
    SIGBUS,
    SIGPOLL,
    SIGPROF,
    SIGSYS,
    SIGTRAP,
    SIGVTALRM,
    SIGXCPU,
    SIGXFSZ,
    SIGIOT,
    SIGSTKFLT,
    SIGIO,
    SIGPWR,
    SIGUNUSED,
  };

  struct sigaction action;
  action.sa_handler = signal_handler;
  sigemptyset(&action.sa_mask);
  action.sa_flags = SA_RESETHAND;

  for (unsigned i = 0; i < sizeof(signals) / sizeof(signals[0]); ++i)
    if (sigaction(signals[i], &action, NULL))
      std::cerr << "Warning: Failed to set signal handler for signal "
                << signals[i] << "\n";
}

static int usage(int exitcode) {
  std::cout << "\nAdditional options:\n";
  std::cout << "    --no-dummy-server: Use the currently running X server "
               "for testing\n";
  std::cout << "    --xorg-conf: Path to xorg configuration file\n";
  std::cout << "    --server: Path to X server executable\n";
  std::cout << "    --xorg-display: xorg display port\n";
  std::cout << "    --xorg-logfile: xorg logfile filename. See -logfile in \"man Xorg\".\n"
               "                    Its default value is " DEFAULT_XORG_LOGFILE ".\n";
  return exitcode;
}

int main(int argc, char *argv[]) {
  std::string xorg_conf_path;
  std::string xorg_log_file_path;
  int xorg_display = -1;
  std::string server;

  setup_signal_handlers();

  testing::InitGoogleTest(&argc, argv);

  /* Reset getopt state */
  optind = 0;

  while (true) {
    int ret;
    int index;
    ret = getopt_long(argc, argv, "", longopts, &index);

    if (ret == -1)
      break;

    if (ret == '?')
      exit(-1);

    switch (index) {
      case 2:
        xorg_conf_path = optarg;
        break;

      case 3:
        xorg_display = atoi(optarg);
        break;

      case 4:
        xorg_log_file_path = optarg;
        break;

      case 5:
        server = optarg;
        break;

      default:
        break;
    }
  }

  if (help)
    return usage(-1);

  if (!no_dummy_server) {
    environment = new xorg::testing::Environment;

    if (xorg_conf_specified)
      environment->SetConfigFile(xorg_conf_path);

    if (server_specified)
      environment->SetServerPath(server);

    if (xorg_display_specified)
      environment->SetDisplayNumber(xorg_display);

    if (xorg_logfile_specified)
      environment->SetLogFile(xorg_log_file_path);

    testing::AddGlobalTestEnvironment(environment);
  }

  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/** @file

  traffic_ctl

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "traffic_ctl.h"

#include "ts/I_Layout.h"
#include "I_RecProcess.h"
#include "RecordsConfig.h"
#include "ts/runroot.h"

AppVersionInfo CtrlVersionInfo;

const char *
CtrlMgmtRecord::name() const
{
  return this->ele->rec_name;
}

TSRecordT
CtrlMgmtRecord::type() const
{
  return this->ele->rec_type;
}

int
CtrlMgmtRecord::rclass() const
{
  return this->ele->rec_class;
}

int64_t
CtrlMgmtRecord::as_int() const
{
  switch (this->ele->rec_type) {
  case TS_REC_INT:
    return this->ele->valueT.int_val;
  case TS_REC_COUNTER:
    return this->ele->valueT.counter_val;
  default:
    return 0;
  }
}

TSMgmtError
CtrlMgmtRecord::fetch(const char *name)
{
  return TSRecordGet(name, this->ele);
}

TSMgmtError
CtrlMgmtRecordList::match(const char *name)
{
  return TSRecordGetMatchMlt(name, this->list);
}

CtrlMgmtRecordValue::CtrlMgmtRecordValue(const CtrlMgmtRecord &rec)
{
  this->init(rec.ele->rec_type, rec.ele->valueT);
}

CtrlMgmtRecordValue::CtrlMgmtRecordValue(const TSRecordEle *ele)
{
  this->init(ele->rec_type, ele->valueT);
}

CtrlMgmtRecordValue::CtrlMgmtRecordValue(TSRecordT _t, TSRecordValueT _v)
{
  this->init(_t, _v);
}

void
CtrlMgmtRecordValue::init(TSRecordT _t, TSRecordValueT _v)
{
  this->rec_type = _t;
  switch (this->rec_type) {
  case TS_REC_INT:
    snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%" PRId64, _v.int_val);
    break;
  case TS_REC_COUNTER:
    snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%" PRId64, _v.counter_val);
    break;
  case TS_REC_FLOAT:
    snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%f", _v.float_val);
    break;
  case TS_REC_STRING:
    if (strcmp(_v.string_val, "") == 0) {
      this->fmt.str = "\"\"";
    } else {
      this->fmt.str = _v.string_val;
    }
    break;
  default:
    rec_type      = TS_REC_STRING;
    this->fmt.str = "(invalid)";
  }
}

const char *
CtrlMgmtRecordValue::c_str() const
{
  switch (this->rec_type) {
  case TS_REC_STRING:
    return this->fmt.str;
  default:
    return this->fmt.nbuf;
  }
}

void
CtrlMgmtError(TSMgmtError err, const char *fmt, ...)
{
  ats_scoped_str msg(TSGetErrorMessage(err));

  if (fmt) {
    va_list ap;

    fprintf(stderr, "%s: ", program_name);
    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    va_end(ap);

    fprintf(stderr, ": %s\n", (const char *)msg);
  } else {
    fprintf(stderr, "%s: %s\n", program_name, (const char *)msg);
  }
}

int
CtrlSubcommandUsage(const char *name, const subcommand *cmds, unsigned ncmds, const ArgumentDescription *desc, unsigned ndesc)
{
  const char *opt = ndesc ? "[OPTIONS]" : "";
  const char *sep = (ndesc && name) ? " " : "";

  fprintf(stderr, "Usage: traffic_ctl %s%s%s CMD [ARGS ...]\n\nSubcommands:\n", name ? name : "", sep, opt);

  for (unsigned i = 0; i < ncmds; ++i) {
    fprintf(stderr, "    %-16s%s\n", cmds[i].name, cmds[i].help);
  }

  if (ndesc) {
    usage(desc, ndesc, "\nOptions:");
  }

  return CTRL_EX_USAGE;
}

int
CtrlCommandUsage(const char *msg, const ArgumentDescription *desc, unsigned ndesc)
{
  fprintf(stderr, "Usage: traffic_ctl %s\n", msg);

  if (ndesc) {
    usage(desc, ndesc, "\nOptions:");
  }

  return CTRL_EX_USAGE;
}

bool
CtrlProcessArguments(int /* argc */, const char **argv, const ArgumentDescription *desc, unsigned ndesc)
{
  n_file_arguments = 0;
  return process_args_ex(&CtrlVersionInfo, desc, ndesc, argv);
}

int
CtrlUnimplementedCommand(unsigned /* argc */, const char **argv)
{
  CtrlDebug("the '%s' command is not implemented", *argv);
  return CTRL_EX_UNIMPLEMENTED;
}

int
CtrlGenericSubcommand(const char *name, const subcommand *cmds, unsigned ncmds, unsigned argc, const char **argv)
{
  CtrlCommandLine cmdline;

  // Process command line arguments and dump into variables
  if (!CtrlProcessArguments(argc, argv, nullptr, 0) || n_file_arguments < 1) {
    return CtrlSubcommandUsage(name, cmds, ncmds, nullptr, 0);
  }

  cmdline.init(n_file_arguments, file_arguments);

  for (unsigned i = 0; i < ncmds; ++i) {
    if (strcmp(file_arguments[0], cmds[i].name) == 0) {
      return cmds[i].handler(cmdline.argc(), cmdline.argv());
    }
  }

  return CtrlSubcommandUsage(name, cmds, ncmds, nullptr, 0);
}

int
main(int argc, const char **argv)
{
  CtrlCommandLine cmdline;
  int debug = false;

  CtrlVersionInfo.setup(PACKAGE_NAME, "traffic_ctl", PACKAGE_VERSION, __DATE__, __TIME__, BUILD_MACHINE, BUILD_PERSON, "");
  program_name = CtrlVersionInfo.AppStr;

  ArgumentDescription argument_descriptions[] = {
    {"debug", '-', "Enable debugging output", "F", &debug, nullptr, nullptr},
    HELP_ARGUMENT_DESCRIPTION(),
    VERSION_ARGUMENT_DESCRIPTION(),
    RUNROOT_ARGUMENT_DESCRIPTION(),
  };

  const subcommand commands[] = {
    {subcommand_alarm, "alarm", "Manipulate alarms"},
    {subcommand_config, "config", "Manipulate configuration records"},
    {subcommand_metric, "metric", "Manipulate performance metrics"},
    {subcommand_server, "server", "Stop, restart and examine the server"},
    {subcommand_storage, "storage", "Manipulate cache storage"},
    {subcommand_plugin, "plugin", "Interact with plugins"},
  };

  BaseLogFile *base_log_file = new BaseLogFile("stderr");
  diags                      = new Diags(program_name, "" /* tags */, "" /* actions */, base_log_file);

  // Process command line arguments and dump into variables
  if (!CtrlProcessArguments(argc, argv, argument_descriptions, countof(argument_descriptions))) {
    return CtrlSubcommandUsage(nullptr, commands, countof(commands), argument_descriptions, countof(argument_descriptions));
  }

  if (debug) {
    diags->activate_taglist("traffic_ctl", DiagsTagType_Debug);
    diags->config.enabled[DiagsTagType_Debug] = true;
    diags->show_location                      = SHOW_LOCATION_DEBUG;
  }

  if (n_file_arguments < 1) {
    return CtrlSubcommandUsage(nullptr, commands, countof(commands), argument_descriptions, countof(argument_descriptions));
  }

  runroot_handler(argv);
  Layout::create();
  RecProcessInit(RECM_STAND_ALONE, diags);
  LibRecordsConfigInit();

  ats_scoped_str rundir(RecConfigReadRuntimeDir());

  // Make a best effort to connect the control socket. If it turns out we are just displaying help or something then it
  // doesn't matter that we failed. If we end up performing some operation then that operation will fail and display the
  // error.
  TSInit(rundir, static_cast<TSInitOptionT>(TS_MGMT_OPT_NO_EVENTS | TS_MGMT_OPT_NO_SOCK_TESTS));

  for (unsigned i = 0; i < countof(commands); ++i) {
    if (strcmp(file_arguments[0], commands[i].name) == 0) {
      CtrlCommandLine cmdline;

      cmdline.init(n_file_arguments, file_arguments);
      return commands[i].handler(cmdline.argc(), cmdline.argv());
    }
  }

  // Done with the mgmt API.
  TSTerminate();
  return CtrlSubcommandUsage(nullptr, commands, countof(commands), argument_descriptions, countof(argument_descriptions));
}
<commit_msg>add custom --help and -h flag to traffic_ctl<commit_after>/** @file

  traffic_ctl

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
 */

#include "traffic_ctl.h"

#include "I_RecProcess.h"
#include "RecordsConfig.h"
#include "ts/I_Layout.h"
#include "ts/runroot.h"

AppVersionInfo CtrlVersionInfo;

const char *CtrlMgmtRecord::name() const { return this->ele->rec_name; }

TSRecordT CtrlMgmtRecord::type() const { return this->ele->rec_type; }

int CtrlMgmtRecord::rclass() const { return this->ele->rec_class; }

int64_t CtrlMgmtRecord::as_int() const {
  switch (this->ele->rec_type) {
  case TS_REC_INT:
    return this->ele->valueT.int_val;
  case TS_REC_COUNTER:
    return this->ele->valueT.counter_val;
  default:
    return 0;
  }
}

TSMgmtError CtrlMgmtRecord::fetch(const char *name) {
  return TSRecordGet(name, this->ele);
}

TSMgmtError CtrlMgmtRecordList::match(const char *name) {
  return TSRecordGetMatchMlt(name, this->list);
}

CtrlMgmtRecordValue::CtrlMgmtRecordValue(const CtrlMgmtRecord &rec) {
  this->init(rec.ele->rec_type, rec.ele->valueT);
}

CtrlMgmtRecordValue::CtrlMgmtRecordValue(const TSRecordEle *ele) {
  this->init(ele->rec_type, ele->valueT);
}

CtrlMgmtRecordValue::CtrlMgmtRecordValue(TSRecordT _t, TSRecordValueT _v) {
  this->init(_t, _v);
}

void CtrlMgmtRecordValue::init(TSRecordT _t, TSRecordValueT _v) {
  this->rec_type = _t;
  switch (this->rec_type) {
  case TS_REC_INT:
    snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%" PRId64, _v.int_val);
    break;
  case TS_REC_COUNTER:
    snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%" PRId64,
             _v.counter_val);
    break;
  case TS_REC_FLOAT:
    snprintf(this->fmt.nbuf, sizeof(this->fmt.nbuf), "%f", _v.float_val);
    break;
  case TS_REC_STRING:
    if (strcmp(_v.string_val, "") == 0) {
      this->fmt.str = "\"\"";
    } else {
      this->fmt.str = _v.string_val;
    }
    break;
  default:
    rec_type = TS_REC_STRING;
    this->fmt.str = "(invalid)";
  }
}

const char *CtrlMgmtRecordValue::c_str() const {
  switch (this->rec_type) {
  case TS_REC_STRING:
    return this->fmt.str;
  default:
    return this->fmt.nbuf;
  }
}

void CtrlMgmtError(TSMgmtError err, const char *fmt, ...) {
  ats_scoped_str msg(TSGetErrorMessage(err));

  if (fmt) {
    va_list ap;

    fprintf(stderr, "%s: ", program_name);
    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    va_end(ap);

    fprintf(stderr, ": %s\n", (const char *)msg);
  } else {
    fprintf(stderr, "%s: %s\n", program_name, (const char *)msg);
  }
}

int CtrlSubcommandUsage(const char *name, const subcommand *cmds,
                        unsigned ncmds, const ArgumentDescription *desc,
                        unsigned ndesc) {
  const char *opt = ndesc ? "[OPTIONS]" : "";
  const char *sep = (ndesc && name) ? " " : "";

  fprintf(stderr, "Usage: traffic_ctl %s%s%s CMD [ARGS ...]\n\nSubcommands:\n",
          name ? name : "", sep, opt);

  for (unsigned i = 0; i < ncmds; ++i) {
    fprintf(stderr, "    %-16s%s\n", cmds[i].name, cmds[i].help);
  }

  if (ndesc) {
    usage(desc, ndesc, "\nOptions:");
  }

  return CTRL_EX_USAGE;
}

int CtrlCommandUsage(const char *msg, const ArgumentDescription *desc,
                     unsigned ndesc) {
  fprintf(stderr, "Usage: traffic_ctl %s\n", msg);

  if (ndesc) {
    usage(desc, ndesc, "\nOptions:");
  }

  return CTRL_EX_USAGE;
}

bool CtrlProcessArguments(int /* argc */, const char **argv,
                          const ArgumentDescription *desc, unsigned ndesc) {
  n_file_arguments = 0;
  return process_args_ex(&CtrlVersionInfo, desc, ndesc, argv);
}

int CtrlUnimplementedCommand(unsigned /* argc */, const char **argv) {
  CtrlDebug("the '%s' command is not implemented", *argv);
  return CTRL_EX_UNIMPLEMENTED;
}

int CtrlGenericSubcommand(const char *name, const subcommand *cmds,
                          unsigned ncmds, unsigned argc, const char **argv) {
  CtrlCommandLine cmdline;

  // Process command line arguments and dump into variables
  if (!CtrlProcessArguments(argc, argv, nullptr, 0) || n_file_arguments < 1) {
    return CtrlSubcommandUsage(name, cmds, ncmds, nullptr, 0);
  }

  cmdline.init(n_file_arguments, file_arguments);

  for (unsigned i = 0; i < ncmds; ++i) {
    if (strcmp(file_arguments[0], cmds[i].name) == 0) {
      return cmds[i].handler(cmdline.argc(), cmdline.argv());
    }
  }

  return CtrlSubcommandUsage(name, cmds, ncmds, nullptr, 0);
}

static const subcommand commands[] = {
    {subcommand_alarm, "alarm", "Manipulate alarms"},
    {subcommand_config, "config", "Manipulate configuration records"},
    {subcommand_metric, "metric", "Manipulate performance metrics"},
    {subcommand_server, "server", "Stop, restart and examine the server"},
    {subcommand_storage, "storage", "Manipulate cache storage"},
    {subcommand_plugin, "plugin", "Interact with plugins"},
};

int main(int argc, const char **argv) {
  CtrlCommandLine cmdline;
  int debug = false;

  CtrlVersionInfo.setup(PACKAGE_NAME, "traffic_ctl", PACKAGE_VERSION, __DATE__,
                        __TIME__, BUILD_MACHINE, BUILD_PERSON, "");
  program_name = CtrlVersionInfo.AppStr;

  ArgumentDescription argument_descriptions[] = {
      {"debug", '-', "Enable debugging output", "F", &debug, nullptr, nullptr},
      {"help", 'h', "Print usage information", nullptr, nullptr, nullptr,
       [](const ArgumentDescription *args, unsigned nargs,
          const char *arg_unused) {
         CtrlSubcommandUsage(nullptr, commands, countof(commands), args, nargs);
       }},
      VERSION_ARGUMENT_DESCRIPTION(),
      RUNROOT_ARGUMENT_DESCRIPTION(),
  };

  BaseLogFile *base_log_file = new BaseLogFile("stderr");
  diags =
      new Diags(program_name, "" /* tags */, "" /* actions */, base_log_file);

  // Process command line arguments and dump into variables
  if (!CtrlProcessArguments(argc, argv, argument_descriptions,
                            countof(argument_descriptions))) {
    return CtrlSubcommandUsage(nullptr, commands, countof(commands),
                               argument_descriptions,
                               countof(argument_descriptions));
  }

  if (debug) {
    diags->activate_taglist("traffic_ctl", DiagsTagType_Debug);
    diags->config.enabled[DiagsTagType_Debug] = true;
    diags->show_location = SHOW_LOCATION_DEBUG;
  }

  if (n_file_arguments < 1) {
    return CtrlSubcommandUsage(nullptr, commands, countof(commands),
                               argument_descriptions,
                               countof(argument_descriptions));
  }

  runroot_handler(argv);
  Layout::create();
  RecProcessInit(RECM_STAND_ALONE, diags);
  LibRecordsConfigInit();

  ats_scoped_str rundir(RecConfigReadRuntimeDir());

  // Make a best effort to connect the control socket. If it turns out we are
  // just displaying help or something then it
  // doesn't matter that we failed. If we end up performing some operation then
  // that operation will fail and display the
  // error.
  TSInit(rundir, static_cast<TSInitOptionT>(TS_MGMT_OPT_NO_EVENTS |
                                            TS_MGMT_OPT_NO_SOCK_TESTS));

  for (unsigned i = 0; i < countof(commands); ++i) {
    if (strcmp(file_arguments[0], commands[i].name) == 0) {
      CtrlCommandLine cmdline;

      cmdline.init(n_file_arguments, file_arguments);
      return commands[i].handler(cmdline.argc(), cmdline.argv());
    }
  }

  // Done with the mgmt API.
  TSTerminate();
  return CtrlSubcommandUsage(nullptr, commands, countof(commands),
                             argument_descriptions,
                             countof(argument_descriptions));
}
<|endoftext|>