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

  Program:   Visualization Toolkit
  Module:    vtkImageDifference.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkImageDifference.h"
#include "stdlib.h"

// Description:
// Construct object to extract all of the input data.
vtkImageDifference::vtkImageDifference()
{
  this->Error = 0;
  this->ThresholdedError = 0.0;
  this->Image = NULL;
  this->Threshold = 51;
  this->AllowShift = 1;
}

// simple macro for calculating error
#define vtkImageDifferenceComputeError(c1,c2) \
  r1 = abs(c1[0] - c2[0]); g1 = abs(c1[1] - c2[1]); b1 = abs(c1[2] - c2[2]); \
  if ((r1+g1+b1) < (tr+tg+tb)) { tr = r1; tg = g1; tb = b1; }

void vtkImageDifference::Execute()
{
  vtkStructuredPoints *input = (vtkStructuredPoints *)this->Input;
  vtkPointData *pd1 = input->GetPointData();
  vtkPointData *pd2 = this->Image->GetPointData();
  vtkStructuredPoints *output=(vtkStructuredPoints *)this->Output;
  vtkPointData *outPD=output->GetPointData();
  int *dims1, *dims2, sliceSize;
  int row, col, idx;
  vtkScalars *s1, *s2;
  float color1[4], color2[4], outColor[4];
  int tr, tg, tb, r1, g1, b1;
  vtkScalars *outScalars = vtkScalars::New(VTK_UNSIGNED_CHAR,3);

  vtkDebugMacro(<< "Comparing Images");

  dims1 = input->GetDimensions();
  dims2 = this->Image->GetDimensions();
  if ((dims1[0] != dims2[0]) ||
      (dims1[1] != dims2[1]) ||
      (dims1[2] != dims2[2]))
    {
    vtkWarningMacro(<< "Images are not the same size: " <<
	dims1[0] << ", " << dims1[1] << ", " << dims1[2] << " != " <<
	dims2[0] << ", " << dims2[1] << ", " << dims2[2] );
    this->Error = 1;
    this->ThresholdedError = 1;
    return;
    }

  // make sure the images are of the correct type
  s1 = pd1->GetScalars();
  s2 = pd2->GetScalars();

  //
  // Allocate necessary objects
  //
  output->SetDimensions(dims1);
  sliceSize = dims1[0]*dims1[1];

  this->Error = 0;
  this->ThresholdedError = 0;

  for (row = 0; row < dims1[1]; row++)
    {
    idx = row*dims1[0];
    for (col = 0; col < dims1[0]; col++)
      {
      tr = 1000;
      tg = 1000;
      tb = 1000;
      s2->GetData()->GetTuple(idx+col,color2);

      /* check the exact match pixel */
      s1->GetData()->GetTuple(idx+col,color1);
      vtkImageDifferenceComputeError(color1,color2);

      /* If AllowShift, then we examine neighboring pixels to
         find the least difference.  This feature is used to
	 allow images to shift slightly between different graphics
	 systems, like between opengl and starbase. */

      if (this->AllowShift)
        {
	/* check the pixel to the left */
	if (col)
	  {
	  s1->GetData()->GetTuple(idx + col - 1, color1);
	  vtkImageDifferenceComputeError(color1,color2);
	  }

	  /* check the pixel to the right */
	if (col < (dims1[0] -1))
	  {
	  s1->GetData()->GetTuple(idx + col + 1, color1);
	  vtkImageDifferenceComputeError(color1,color2);
	  }

	/* check the line above if there is one */
	if (row)
	  {
	  /* check the exact match pixel */
	  s1->GetData()->GetTuple(idx - dims1[0] + col, color1);
	  vtkImageDifferenceComputeError(color1,color2);

	  /* check the pixel to the left */
	  if (col)
	    {
	    s1->GetData()->GetTuple(idx - dims1[0] + col - 1, color1);
	    vtkImageDifferenceComputeError(color1,color2);
	    }

	  /* check the pixel to the right */
	  if (col < (dims1[0] -1))
	    {
	    s1->GetData()->GetTuple(idx - dims1[0] + col + 1, color1);
	    vtkImageDifferenceComputeError(color1,color2);
	    }
	  }

	/* check the line below if there is one */
	if (row < (dims1[1] - 1))
	  {
	  /* check the exact match pixel */
	  s1->GetData()->GetTuple(idx + dims1[0] + col, color1);
	  vtkImageDifferenceComputeError(color1,color2);

	  /* check the pixel to the left */
	  if (col)
	    {
	    s1->GetData()->GetTuple(idx + dims1[0] + col - 1, color1);
	    vtkImageDifferenceComputeError(color1,color2);
	    }

	  /* check the pixel to the right */
	  if (col < (dims1[0] -1))
	    {
	    s1->GetData()->GetTuple(idx + dims1[0] + col + 1, color1);
	    vtkImageDifferenceComputeError(color1,color2);
	    }
	  }
	}

      this->Error = this->Error + (tr + tg + tb)/(3.0*255);
      tr -= this->Threshold;
      if (tr < 0) tr = 0;
      tg -= this->Threshold;
      if (tg < 0) tg = 0;
      tb -= this->Threshold;
      if (tb < 0) tb = 0;
      outColor[0] = tr;
      outColor[1] = tg;
      outColor[2] = tb;
      this->ThresholdedError =
	this->ThresholdedError + (tr + tg + tb)/(3.0*255.0);
      outScalars->GetData()->InsertNextTuple(outColor);
      }
    }

  outPD->SetScalars(outScalars);
  outScalars->Delete();
}

void vtkImageDifference::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkStructuredPointsFilter::PrintSelf(os,indent);

  os << indent << "Error: " << this->Error << "\n";
  os << indent << "ThresholdedError: " << this->ThresholdedError << "\n";
  os << indent << "Threshold: " << this->Threshold << "\n";
  os << indent << "AllowShift: " << this->AllowShift << "\n";
}

// Description:
// Override update method because execution can branch two ways (Input
// and Image)
void vtkImageDifference::Update()
{
  // make sure input is available
  if ( this->Input == NULL || this->Image == NULL)
    {
    vtkErrorMacro(<< "No input...can't execute!");
    return;
    }

  // prevent chasing our tail
  if (this->Updating) return;

  this->Updating = 1;
  this->Input->Update();
  this->Image->Update();
  this->Updating = 0;

  if (this->Input->GetMTime() > this->ExecuteTime ||
      this->Image->GetMTime() > this->ExecuteTime ||
      this->GetMTime() > this->ExecuteTime || this->GetDataReleased() )
    {
    if ( this->StartMethod ) (*this->StartMethod)(this->StartMethodArg);
    this->Output->Initialize(); //clear output
    // reset AbortExecute flag and Progress
    this->AbortExecute = 0;
    this->Progress = 0.0;
    this->Execute();
    this->ExecuteTime.Modified();
    this->SetDataReleased(0);
    if ( !this->AbortExecute ) this->UpdateProgress(1.0);
    if ( this->EndMethod ) (*this->EndMethod)(this->EndMethodArg);
    }

  if ( this->Input->ShouldIReleaseData() ) this->Input->ReleaseData();
  if ( this->Image->ShouldIReleaseData() ) this->Image->ReleaseData();
}
<commit_msg>BUG: minor compile bug<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkImageDifference.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-1998 Ken Martin, Will Schroeder, Bill Lorensen.

This software is copyrighted by Ken Martin, Will Schroeder and Bill Lorensen.
The following terms apply to all files associated with the software unless
explicitly disclaimed in individual files. This copyright specifically does
not apply to the related textbook "The Visualization Toolkit" ISBN
013199837-4 published by Prentice Hall which is covered by its own copyright.

The authors hereby grant permission to use, copy, and distribute this
software and its documentation for any purpose, provided that existing
copyright notices are retained in all copies and that this notice is included
verbatim in any distributions. Additionally, the authors grant permission to
modify this software and its documentation for any purpose, provided that
such modifications are not distributed without the explicit consent of the
authors and that existing copyright notices are retained in all copies. Some
of the algorithms implemented by this software are patented, observe all
applicable patent law.

IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS SOFTWARE IS PROVIDED ON AN
"AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

=========================================================================*/
#include "vtkImageDifference.h"
#include "stdlib.h"

// Description:
// Construct object to extract all of the input data.
vtkImageDifference::vtkImageDifference()
{
  this->Error = 0;
  this->ThresholdedError = 0.0;
  this->Image = NULL;
  this->Threshold = 51;
  this->AllowShift = 1;
}

// simple macro for calculating error
#define vtkImageDifferenceComputeError(c1,c2) \
  r1 = abs((int)(c1[0] - c2[0])); g1 = abs((int)(c1[1] - c2[1])); b1 = abs((int)(c1[2] - c2[2])); \
  if ((r1+g1+b1) < (tr+tg+tb)) { tr = r1; tg = g1; tb = b1; }

void vtkImageDifference::Execute()
{
  vtkStructuredPoints *input = (vtkStructuredPoints *)this->Input;
  vtkPointData *pd1 = input->GetPointData();
  vtkPointData *pd2 = this->Image->GetPointData();
  vtkStructuredPoints *output=(vtkStructuredPoints *)this->Output;
  vtkPointData *outPD=output->GetPointData();
  int *dims1, *dims2, sliceSize;
  int row, col, idx;
  vtkScalars *s1, *s2;
  float color1[4], color2[4], outColor[4];
  int tr, tg, tb, r1, g1, b1;
  vtkScalars *outScalars = vtkScalars::New(VTK_UNSIGNED_CHAR,3);

  vtkDebugMacro(<< "Comparing Images");

  dims1 = input->GetDimensions();
  dims2 = this->Image->GetDimensions();
  if ((dims1[0] != dims2[0]) ||
      (dims1[1] != dims2[1]) ||
      (dims1[2] != dims2[2]))
    {
    vtkWarningMacro(<< "Images are not the same size: " <<
	dims1[0] << ", " << dims1[1] << ", " << dims1[2] << " != " <<
	dims2[0] << ", " << dims2[1] << ", " << dims2[2] );
    this->Error = 1;
    this->ThresholdedError = 1;
    return;
    }

  // make sure the images are of the correct type
  s1 = pd1->GetScalars();
  s2 = pd2->GetScalars();

  //
  // Allocate necessary objects
  //
  output->SetDimensions(dims1);
  sliceSize = dims1[0]*dims1[1];

  this->Error = 0;
  this->ThresholdedError = 0;

  for (row = 0; row < dims1[1]; row++)
    {
    idx = row*dims1[0];
    for (col = 0; col < dims1[0]; col++)
      {
      tr = 1000;
      tg = 1000;
      tb = 1000;
      s2->GetData()->GetTuple(idx+col,color2);

      /* check the exact match pixel */
      s1->GetData()->GetTuple(idx+col,color1);
      vtkImageDifferenceComputeError(color1,color2);

      /* If AllowShift, then we examine neighboring pixels to
         find the least difference.  This feature is used to
	 allow images to shift slightly between different graphics
	 systems, like between opengl and starbase. */

      if (this->AllowShift)
        {
	/* check the pixel to the left */
	if (col)
	  {
	  s1->GetData()->GetTuple(idx + col - 1, color1);
	  vtkImageDifferenceComputeError(color1,color2);
	  }

	  /* check the pixel to the right */
	if (col < (dims1[0] -1))
	  {
	  s1->GetData()->GetTuple(idx + col + 1, color1);
	  vtkImageDifferenceComputeError(color1,color2);
	  }

	/* check the line above if there is one */
	if (row)
	  {
	  /* check the exact match pixel */
	  s1->GetData()->GetTuple(idx - dims1[0] + col, color1);
	  vtkImageDifferenceComputeError(color1,color2);

	  /* check the pixel to the left */
	  if (col)
	    {
	    s1->GetData()->GetTuple(idx - dims1[0] + col - 1, color1);
	    vtkImageDifferenceComputeError(color1,color2);
	    }

	  /* check the pixel to the right */
	  if (col < (dims1[0] -1))
	    {
	    s1->GetData()->GetTuple(idx - dims1[0] + col + 1, color1);
	    vtkImageDifferenceComputeError(color1,color2);
	    }
	  }

	/* check the line below if there is one */
	if (row < (dims1[1] - 1))
	  {
	  /* check the exact match pixel */
	  s1->GetData()->GetTuple(idx + dims1[0] + col, color1);
	  vtkImageDifferenceComputeError(color1,color2);

	  /* check the pixel to the left */
	  if (col)
	    {
	    s1->GetData()->GetTuple(idx + dims1[0] + col - 1, color1);
	    vtkImageDifferenceComputeError(color1,color2);
	    }

	  /* check the pixel to the right */
	  if (col < (dims1[0] -1))
	    {
	    s1->GetData()->GetTuple(idx + dims1[0] + col + 1, color1);
	    vtkImageDifferenceComputeError(color1,color2);
	    }
	  }
	}

      this->Error = this->Error + (tr + tg + tb)/(3.0*255);
      tr -= this->Threshold;
      if (tr < 0) tr = 0;
      tg -= this->Threshold;
      if (tg < 0) tg = 0;
      tb -= this->Threshold;
      if (tb < 0) tb = 0;
      outColor[0] = tr;
      outColor[1] = tg;
      outColor[2] = tb;
      this->ThresholdedError =
	this->ThresholdedError + (tr + tg + tb)/(3.0*255.0);
      outScalars->GetData()->InsertNextTuple(outColor);
      }
    }

  outPD->SetScalars(outScalars);
  outScalars->Delete();
}

void vtkImageDifference::PrintSelf(ostream& os, vtkIndent indent)
{
  vtkStructuredPointsFilter::PrintSelf(os,indent);

  os << indent << "Error: " << this->Error << "\n";
  os << indent << "ThresholdedError: " << this->ThresholdedError << "\n";
  os << indent << "Threshold: " << this->Threshold << "\n";
  os << indent << "AllowShift: " << this->AllowShift << "\n";
}

// Description:
// Override update method because execution can branch two ways (Input
// and Image)
void vtkImageDifference::Update()
{
  // make sure input is available
  if ( this->Input == NULL || this->Image == NULL)
    {
    vtkErrorMacro(<< "No input...can't execute!");
    return;
    }

  // prevent chasing our tail
  if (this->Updating) return;

  this->Updating = 1;
  this->Input->Update();
  this->Image->Update();
  this->Updating = 0;

  if (this->Input->GetMTime() > this->ExecuteTime ||
      this->Image->GetMTime() > this->ExecuteTime ||
      this->GetMTime() > this->ExecuteTime || this->GetDataReleased() )
    {
    if ( this->StartMethod ) (*this->StartMethod)(this->StartMethodArg);
    this->Output->Initialize(); //clear output
    // reset AbortExecute flag and Progress
    this->AbortExecute = 0;
    this->Progress = 0.0;
    this->Execute();
    this->ExecuteTime.Modified();
    this->SetDataReleased(0);
    if ( !this->AbortExecute ) this->UpdateProgress(1.0);
    if ( this->EndMethod ) (*this->EndMethod)(this->EndMethodArg);
    }

  if ( this->Input->ShouldIReleaseData() ) this->Input->ReleaseData();
  if ( this->Image->ShouldIReleaseData() ) this->Image->ReleaseData();
}
<|endoftext|>


<commit_before>// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include <memory>
#include <vector>

#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_string.h"
#include "core/fpdfdoc/include/fpdf_doc.h"

CPDF_Bookmark CPDF_BookmarkTree::GetFirstChild(
    const CPDF_Bookmark& parent) const {
  if (!parent.GetDict()) {
    CPDF_Dictionary* pRoot = m_pDocument->GetRoot()->GetDictBy("Outlines");
    if (!pRoot)
      return CPDF_Bookmark();
    return CPDF_Bookmark(pRoot->GetDictBy("First"));
  }
  return CPDF_Bookmark(parent.GetDict()->GetDictBy("First"));
}

CPDF_Bookmark CPDF_BookmarkTree::GetNextSibling(
    const CPDF_Bookmark& bookmark) const {
  if (!bookmark.GetDict())
    return CPDF_Bookmark();

  CPDF_Dictionary* pNext = bookmark.GetDict()->GetDictBy("Next");
  return pNext == bookmark.GetDict() ? CPDF_Bookmark() : CPDF_Bookmark(pNext);
}

uint32_t CPDF_Bookmark::GetColorRef() const {
  if (!m_pDict) {
    return 0;
  }
  CPDF_Array* pColor = m_pDict->GetArrayBy("C");
  if (!pColor) {
    return FXSYS_RGB(0, 0, 0);
  }
  int r = FXSYS_round(pColor->GetNumberAt(0) * 255);
  int g = FXSYS_round(pColor->GetNumberAt(1) * 255);
  int b = FXSYS_round(pColor->GetNumberAt(2) * 255);
  return FXSYS_RGB(r, g, b);
}
uint32_t CPDF_Bookmark::GetFontStyle() const {
  if (!m_pDict) {
    return 0;
  }
  return m_pDict->GetIntegerBy("F");
}
CFX_WideString CPDF_Bookmark::GetTitle() const {
  if (!m_pDict) {
    return CFX_WideString();
  }
  CPDF_String* pString = ToString(m_pDict->GetDirectObjectBy("Title"));
  if (!pString)
    return CFX_WideString();

  CFX_WideString title = pString->GetUnicodeText();
  int len = title.GetLength();
  if (!len) {
    return CFX_WideString();
  }
  std::unique_ptr<FX_WCHAR[]> buf(new FX_WCHAR[len]);
  for (int i = 0; i < len; i++) {
    FX_WCHAR w = title[i];
    buf[i] = w > 0x20 ? w : 0x20;
  }
  return CFX_WideString(buf.get(), len);
}
CPDF_Dest CPDF_Bookmark::GetDest(CPDF_Document* pDocument) const {
  if (!m_pDict)
    return CPDF_Dest();

  CPDF_Object* pDest = m_pDict->GetDirectObjectBy("Dest");
  if (!pDest)
    return CPDF_Dest();
  if (pDest->IsString() || pDest->IsName()) {
    CPDF_NameTree name_tree(pDocument, "Dests");
    return CPDF_Dest(name_tree.LookupNamedDest(pDocument, pDest->GetString()));
  }
  if (CPDF_Array* pArray = pDest->AsArray())
    return CPDF_Dest(pArray);
  return CPDF_Dest();
}
CPDF_Action CPDF_Bookmark::GetAction() const {
  if (!m_pDict) {
    return CPDF_Action();
  }
  return CPDF_Action(m_pDict->GetDictBy("A"));
}
<commit_msg>Fix a nullptr deref in CPDF_BookmarkTree::GetFirstChild().<commit_after>// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include <memory>
#include <vector>

#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
#include "core/fpdfapi/fpdf_parser/include/cpdf_string.h"
#include "core/fpdfdoc/include/fpdf_doc.h"

CPDF_Bookmark CPDF_BookmarkTree::GetFirstChild(
    const CPDF_Bookmark& parent) const {
  CPDF_Dictionary* pParentDict = parent.GetDict();
  if (pParentDict)
    return CPDF_Bookmark(pParentDict->GetDictBy("First"));

  CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
  if (!pRoot)
    return CPDF_Bookmark();

  CPDF_Dictionary* pOutlines = pRoot->GetDictBy("Outlines");
  if (!pOutlines)
    return CPDF_Bookmark();

  return CPDF_Bookmark(pOutlines->GetDictBy("First"));
}

CPDF_Bookmark CPDF_BookmarkTree::GetNextSibling(
    const CPDF_Bookmark& bookmark) const {
  CPDF_Dictionary* pDict = bookmark.GetDict();
  if (!pDict)
    return CPDF_Bookmark();

  CPDF_Dictionary* pNext = pDict->GetDictBy("Next");
  return pNext == pDict ? CPDF_Bookmark() : CPDF_Bookmark(pNext);
}

uint32_t CPDF_Bookmark::GetColorRef() const {
  if (!m_pDict)
    return FXSYS_RGB(0, 0, 0);

  CPDF_Array* pColor = m_pDict->GetArrayBy("C");
  if (!pColor)
    return FXSYS_RGB(0, 0, 0);

  int r = FXSYS_round(pColor->GetNumberAt(0) * 255);
  int g = FXSYS_round(pColor->GetNumberAt(1) * 255);
  int b = FXSYS_round(pColor->GetNumberAt(2) * 255);
  return FXSYS_RGB(r, g, b);
}

uint32_t CPDF_Bookmark::GetFontStyle() const {
  return m_pDict ? m_pDict->GetIntegerBy("F") : 0;
}

CFX_WideString CPDF_Bookmark::GetTitle() const {
  if (!m_pDict) {
    return CFX_WideString();
  }
  CPDF_String* pString = ToString(m_pDict->GetDirectObjectBy("Title"));
  if (!pString)
    return CFX_WideString();

  CFX_WideString title = pString->GetUnicodeText();
  int len = title.GetLength();
  if (!len) {
    return CFX_WideString();
  }
  std::unique_ptr<FX_WCHAR[]> buf(new FX_WCHAR[len]);
  for (int i = 0; i < len; i++) {
    FX_WCHAR w = title[i];
    buf[i] = w > 0x20 ? w : 0x20;
  }
  return CFX_WideString(buf.get(), len);
}
CPDF_Dest CPDF_Bookmark::GetDest(CPDF_Document* pDocument) const {
  if (!m_pDict)
    return CPDF_Dest();

  CPDF_Object* pDest = m_pDict->GetDirectObjectBy("Dest");
  if (!pDest)
    return CPDF_Dest();
  if (pDest->IsString() || pDest->IsName()) {
    CPDF_NameTree name_tree(pDocument, "Dests");
    return CPDF_Dest(name_tree.LookupNamedDest(pDocument, pDest->GetString()));
  }
  if (CPDF_Array* pArray = pDest->AsArray())
    return CPDF_Dest(pArray);
  return CPDF_Dest();
}
CPDF_Action CPDF_Bookmark::GetAction() const {
  if (!m_pDict) {
    return CPDF_Action();
  }
  return CPDF_Action(m_pDict->GetDictBy("A"));
}
<|endoftext|>


<commit_before><commit_msg>Increase the % coverage for coalescing for paint rects.<commit_after><|endoftext|>


<commit_before>#include <atomic>

static int test()
{
    std::atomic<int> x;
    return x;
}

int main()
{
    return test();
}
<commit_msg>cmake: use 'long long' for atomic check<commit_after>#include <atomic>

static int test()
{
    std::atomic<long long> x;
    return x;
}

int main()
{
    return test();
}
<|endoftext|>


<commit_before>#include "precompiled.h"
//
// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations.

#include "libGLESv2/ProgramBinary.h"
#include "libGLESv2/VertexAttribute.h"
#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h"
#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"

namespace rx
{

VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
{
    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
    {
        mVertexDeclCache[i].vertexDeclaration = NULL;
        mVertexDeclCache[i].lruCount = 0;
    }

    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    {
        mAppliedVBs[i].serial = 0;
    }

    mLastSetVDecl = NULL;
    mInstancingEnabled = true;
}

VertexDeclarationCache::~VertexDeclarationCache()
{
    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
    {
        SafeRelease(mVertexDeclCache[i].vertexDeclaration);
    }
}

GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
{
    *repeatDraw = 1;

    int indexedAttribute = gl::MAX_VERTEX_ATTRIBS;
    int instancedAttribute = gl::MAX_VERTEX_ATTRIBS;

    if (instances > 0)
    {
        // Find an indexed attribute to be mapped to D3D stream 0
        for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
        {
            if (attributes[i].active)
            {
                if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0)
                {
                    indexedAttribute = i;
                }
                else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0)
                {
                    instancedAttribute = i;
                }
                if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS)
                    break;   // Found both an indexed and instanced attribute
            }
        }

        if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS)
        {
            return GL_INVALID_OPERATION;
        }
    }

    D3DCAPS9 caps;
    device->GetDeviceCaps(&caps);

    D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1];
    D3DVERTEXELEMENT9 *element = &elements[0];

    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    {
        if (attributes[i].active)
        {
            // Directly binding the storage buffer is not supported for d3d9
            ASSERT(attributes[i].storage == NULL);

            int stream = i;

            if (instances > 0)
            {
                // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced.
                if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
                {
                    *repeatDraw = instances;
                }
                else
                {
                    if (i == indexedAttribute)
                    {
                        stream = 0;
                    }
                    else if (i == 0)
                    {
                        stream = indexedAttribute;
                    }

                    UINT frequency = 1;

                    if (attributes[i].divisor == 0)
                    {
                        frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
                    }
                    else
                    {
                        frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
                    }

                    device->SetStreamSourceFreq(stream, frequency);
                    mInstancingEnabled = true;
                }
            }

            VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer);

            if (mAppliedVBs[stream].serial != attributes[i].serial ||
                mAppliedVBs[stream].stride != attributes[i].stride ||
                mAppliedVBs[stream].offset != attributes[i].offset)
            {
                device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride);
                mAppliedVBs[stream].serial = attributes[i].serial;
                mAppliedVBs[stream].stride = attributes[i].stride;
                mAppliedVBs[stream].offset = attributes[i].offset;
            }

            gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT);
            const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexFormat);

            element->Stream = stream;
            element->Offset = 0;
            element->Type = d3d9VertexInfo.nativeFormat;
            element->Method = D3DDECLMETHOD_DEFAULT;
            element->Usage = D3DDECLUSAGE_TEXCOORD;
            element->UsageIndex = programBinary->getSemanticIndex(i);
            element++;
        }
    }

    if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
    {
        if (mInstancingEnabled)
        {
            for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
            {
                device->SetStreamSourceFreq(i, 1);
            }

            mInstancingEnabled = false;
        }
    }

    static const D3DVERTEXELEMENT9 end = D3DDECL_END();
    *(element++) = end;

    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
    {
        VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
        if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
        {
            entry->lruCount = ++mMaxLru;
            if(entry->vertexDeclaration != mLastSetVDecl)
            {
                device->SetVertexDeclaration(entry->vertexDeclaration);
                mLastSetVDecl = entry->vertexDeclaration;
            }

            return GL_NO_ERROR;
        }
    }

    VertexDeclCacheEntry *lastCache = mVertexDeclCache;

    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
    {
        if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
        {
            lastCache = &mVertexDeclCache[i];
        }
    }

    if (lastCache->vertexDeclaration != NULL)
    {
        SafeRelease(lastCache->vertexDeclaration);
        // mLastSetVDecl is set to the replacement, so we don't have to worry
        // about it.
    }

    memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
    device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
    device->SetVertexDeclaration(lastCache->vertexDeclaration);
    mLastSetVDecl = lastCache->vertexDeclaration;
    lastCache->lruCount = ++mMaxLru;

    return GL_NO_ERROR;
}

void VertexDeclarationCache::markStateDirty()
{
    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    {
        mAppliedVBs[i].serial = 0;
    }

    mLastSetVDecl = NULL;
    mInstancingEnabled = true;   // Forces it to be disabled when not used
}

}
<commit_msg>Fix application of vertex divisor for non-instanced draws in D3D9<commit_after>#include "precompiled.h"
//
// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations.

#include "libGLESv2/ProgramBinary.h"
#include "libGLESv2/VertexAttribute.h"
#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h"
#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"

namespace rx
{

VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
{
    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
    {
        mVertexDeclCache[i].vertexDeclaration = NULL;
        mVertexDeclCache[i].lruCount = 0;
    }

    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    {
        mAppliedVBs[i].serial = 0;
    }

    mLastSetVDecl = NULL;
    mInstancingEnabled = true;
}

VertexDeclarationCache::~VertexDeclarationCache()
{
    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
    {
        SafeRelease(mVertexDeclCache[i].vertexDeclaration);
    }
}

GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
{
    *repeatDraw = 1;

    int indexedAttribute = gl::MAX_VERTEX_ATTRIBS;
    int instancedAttribute = gl::MAX_VERTEX_ATTRIBS;

    if (instances == 0)
    {
        for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i)
        {
            if (attributes[i].divisor != 0)
            {
                // If a divisor is set, it still applies even if an instanced draw was not used, so treat
                // as a single-instance draw.
                instances = 1;
                break;
            }
        }
    }

    if (instances > 0)
    {
        // Find an indexed attribute to be mapped to D3D stream 0
        for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
        {
            if (attributes[i].active)
            {
                if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0)
                {
                    indexedAttribute = i;
                }
                else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0)
                {
                    instancedAttribute = i;
                }
                if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS)
                    break;   // Found both an indexed and instanced attribute
            }
        }

        if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS)
        {
            return GL_INVALID_OPERATION;
        }
    }

    D3DCAPS9 caps;
    device->GetDeviceCaps(&caps);

    D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1];
    D3DVERTEXELEMENT9 *element = &elements[0];

    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    {
        if (attributes[i].active)
        {
            // Directly binding the storage buffer is not supported for d3d9
            ASSERT(attributes[i].storage == NULL);

            int stream = i;

            if (instances > 0)
            {
                // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced.
                if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
                {
                    *repeatDraw = instances;
                }
                else
                {
                    if (i == indexedAttribute)
                    {
                        stream = 0;
                    }
                    else if (i == 0)
                    {
                        stream = indexedAttribute;
                    }

                    UINT frequency = 1;

                    if (attributes[i].divisor == 0)
                    {
                        frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
                    }
                    else
                    {
                        frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
                    }

                    device->SetStreamSourceFreq(stream, frequency);
                    mInstancingEnabled = true;
                }
            }

            VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer);

            if (mAppliedVBs[stream].serial != attributes[i].serial ||
                mAppliedVBs[stream].stride != attributes[i].stride ||
                mAppliedVBs[stream].offset != attributes[i].offset)
            {
                device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride);
                mAppliedVBs[stream].serial = attributes[i].serial;
                mAppliedVBs[stream].stride = attributes[i].stride;
                mAppliedVBs[stream].offset = attributes[i].offset;
            }

            gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT);
            const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexFormat);

            element->Stream = stream;
            element->Offset = 0;
            element->Type = d3d9VertexInfo.nativeFormat;
            element->Method = D3DDECLMETHOD_DEFAULT;
            element->Usage = D3DDECLUSAGE_TEXCOORD;
            element->UsageIndex = programBinary->getSemanticIndex(i);
            element++;
        }
    }

    if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS)
    {
        if (mInstancingEnabled)
        {
            for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
            {
                device->SetStreamSourceFreq(i, 1);
            }

            mInstancingEnabled = false;
        }
    }

    static const D3DVERTEXELEMENT9 end = D3DDECL_END();
    *(element++) = end;

    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
    {
        VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
        if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
        {
            entry->lruCount = ++mMaxLru;
            if(entry->vertexDeclaration != mLastSetVDecl)
            {
                device->SetVertexDeclaration(entry->vertexDeclaration);
                mLastSetVDecl = entry->vertexDeclaration;
            }

            return GL_NO_ERROR;
        }
    }

    VertexDeclCacheEntry *lastCache = mVertexDeclCache;

    for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
    {
        if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
        {
            lastCache = &mVertexDeclCache[i];
        }
    }

    if (lastCache->vertexDeclaration != NULL)
    {
        SafeRelease(lastCache->vertexDeclaration);
        // mLastSetVDecl is set to the replacement, so we don't have to worry
        // about it.
    }

    memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
    device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
    device->SetVertexDeclaration(lastCache->vertexDeclaration);
    mLastSetVDecl = lastCache->vertexDeclaration;
    lastCache->lruCount = ++mMaxLru;

    return GL_NO_ERROR;
}

void VertexDeclarationCache::markStateDirty()
{
    for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
    {
        mAppliedVBs[i].serial = 0;
    }

    mLastSetVDecl = NULL;
    mInstancingEnabled = true;   // Forces it to be disabled when not used
}

}
<|endoftext|>


<commit_before>// @(#)root/gui:$Id$
// Author: Fons Rademakers   15/07/98

/*************************************************************************
 * 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.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootEmbeddedCanvas                                                  //
//                                                                      //
// This class creates a TGCanvas in which a TCanvas is created. Use     //
// GetCanvas() to get a pointer to the TCanvas.                         //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TRootEmbeddedCanvas.h"
#include "TCanvas.h"
#include "TROOT.h"
#include "Riostream.h"
#include "TStyle.h"
#include "TPluginManager.h"
#include "TVirtualGL.h"
#include "TGDNDManager.h"
#include "TBufferFile.h"
#include "TImage.h"
#include "TClass.h"
#include "TUrl.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootEmbeddedContainer                                               //
//                                                                      //
// Utility class used by TRootEmbeddedCanvas. The TRootEmbeddedContainer//
// is the frame embedded in the TGCanvas widget. The ROOT graphics goes //
// into this frame. This class is used to enable input events on this   //
// graphics frame and forward the events to the TRootEmbeddedCanvas     //
// handlers.                                                            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TRootEmbeddedContainer : public TGCompositeFrame {
private:
   TRootEmbeddedCanvas  *fCanvas;    // pointer back to embedded canvas
public:
   TRootEmbeddedContainer(TRootEmbeddedCanvas *c, Window_t id, const TGWindow *parent);

   Bool_t  HandleButton(Event_t *ev)
               { return fCanvas->HandleContainerButton(ev); }
   Bool_t  HandleDoubleClick(Event_t *ev)
               { return fCanvas->HandleContainerDoubleClick(ev); }
   Bool_t  HandleConfigureNotify(Event_t *ev)
               { TGFrame::HandleConfigureNotify(ev);
                  return fCanvas->HandleContainerConfigure(ev); }
   Bool_t  HandleKey(Event_t *ev)
               { return fCanvas->HandleContainerKey(ev); }
   Bool_t  HandleMotion(Event_t *ev)
               { return fCanvas->HandleContainerMotion(ev); }
   Bool_t  HandleExpose(Event_t *ev)
               { return fCanvas->HandleContainerExpose(ev); }
   Bool_t  HandleCrossing(Event_t *ev)
               { return fCanvas->HandleContainerCrossing(ev); }
   void    SetEditable(Bool_t) { }
};

//______________________________________________________________________________
TRootEmbeddedContainer::TRootEmbeddedContainer(TRootEmbeddedCanvas *c, Window_t id,
   const TGWindow *p) : TGCompositeFrame(gClient, id, p)
{
   // Create a canvas container.

   fCanvas = c;

   gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
                         kButtonPressMask | kButtonReleaseMask |
                         kPointerMotionMask, kNone, kNone);

   AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask |
            kExposureMask | kStructureNotifyMask | kLeaveWindowMask);

   fEditDisabled = kEditDisableGrab;
}

ClassImp(TRootEmbeddedCanvas)

//______________________________________________________________________________
TRootEmbeddedCanvas::TRootEmbeddedCanvas(const char *name, const TGWindow *p,
            UInt_t w, UInt_t h, UInt_t options, ULong_t back)
   : TGCanvas(p, w, h, options, back)
{
   // Create an TCanvas embedded in a TGFrame. A pointer to the TCanvas can
   // be obtained via the GetCanvas() member function. To embed a canvas
   // derived from a TCanvas do the following:
   // TRootEmbeddedCanvas *embedded = new TRootEmbeddedCanvas(0, p, w, h);
   //      [note name must be 0, not null string ""]
   // Int_t wid = embedded->GetCanvasWindowId();
   // TMyCanvas *myc = new TMyCanvas("myname", 10, 10, wid);
   // embedded->AdoptCanvas(myc);
   //      [ the MyCanvas is adopted by the embedded canvas and will be
   //        destroyed by it ]

   fCanvas  = 0;
   fButton  = 0;
   fAutoFit = kTRUE;
   fEditDisabled = kEditDisableLayout;

   fCWinId = -1;

   if (gStyle->GetCanvasPreferGL()) {
      //first, initialize GL (if not yet)
      if (!gGLManager) {
         TString x = "win32";
         if (gVirtualX->InheritsFrom("TGX11"))
            x = "x11";

         TPluginHandler *ph = gROOT->GetPluginManager()->FindHandler("TGLManager", x);

         if (ph && ph->LoadPlugin() != -1) {
            if (!ph->ExecPlugin(0))
               Warning("CreateCanvas",
                       "Cannot load GL, will use default canvas imp instead\n");
         }
      }
      if (gGLManager) {
         fCWinId = gGLManager->InitGLWindow((ULong_t)GetViewPort()->GetId());
      }
   }

   if (fCWinId == -1)
      fCWinId = gVirtualX->InitWindow((ULong_t)GetViewPort()->GetId());

   Window_t win = gVirtualX->GetWindowID(fCWinId);
   fCanvasContainer = new TRootEmbeddedContainer(this, win, GetViewPort());
   SetContainer(fCanvasContainer);

   fCanvas = new TCanvas(name ? name : Form("%s_canvas", GetName()), w, h, fCWinId);

   // define DND types
   fDNDTypeList = new Atom_t[3];
   fDNDTypeList[0] = gVirtualX->InternAtom("application/root", kFALSE);
   fDNDTypeList[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
   fDNDTypeList[2] = 0;
   gVirtualX->SetDNDAware(fId, fDNDTypeList);
   SetDNDTarget(kTRUE);

   if (!p) {
      fCanvas->SetBorderMode(0);
      MapSubwindows();
      Resize(100, 100);
   }
}

//______________________________________________________________________________
TRootEmbeddedCanvas::~TRootEmbeddedCanvas()
{
   // Delete embedded ROOT canvas.

   if (!MustCleanup()) {
      delete fCanvas;
      delete fCanvasContainer;
   }
   delete [] fDNDTypeList;
}

//______________________________________________________________________________
void TRootEmbeddedCanvas::AdoptCanvas(TCanvas *c)
{
   // Canvas c is adopted from this embedded canvas.

   if(c == 0) return;
   c->EmbedInto(fCWinId, fWidth, fHeight);
   fCanvas = c;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerButton(Event_t *event)
{
   // Handle mouse button events in the canvas container.

   if (!fCanvas) return kTRUE;

   Int_t button = event->fCode;
   Int_t x = event->fX;
   Int_t y = event->fY;

   if (event->fType == kButtonPress) {
      fButton = button;
      if (button == kButton1)
         fCanvas->HandleInput(kButton1Down, x, y);
      if (button == kButton2)
         fCanvas->HandleInput(kButton2Down, x, y);
      if (button == kButton3) {
         fCanvas->HandleInput(kButton3Down, x, y);
         fButton = 0;  // button up is consumed by TContextMenu
      }

   } else if (event->fType == kButtonRelease) {
      if (button == kButton1)
         fCanvas->HandleInput(kButton1Up, x, y);
      if (button == kButton2)
         fCanvas->HandleInput(kButton2Up, x, y);
      if (button == kButton3)
         fCanvas->HandleInput(kButton3Up, x, y);

      fButton = 0;
   }

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerDoubleClick(Event_t *event)
{
   // Handle mouse button double click events in the canvas container.

   if (!fCanvas) return kTRUE;

   Int_t button = event->fCode;
   Int_t x = event->fX;
   Int_t y = event->fY;

   if (button == kButton1)
      fCanvas->HandleInput(kButton1Double, x, y);
   if (button == kButton2)
      fCanvas->HandleInput(kButton2Double, x, y);
   if (button == kButton3)
      fCanvas->HandleInput(kButton3Double, x, y);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerConfigure(Event_t *)
{
   // Handle configure (i.e. resize) event.

   if (fAutoFit && fCanvas) {
      fCanvas->Resize();
      fCanvas->Update();
   }
   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerKey(Event_t *event)
{
   // Handle keyboard events in the canvas container.

   if (!fCanvas) return kTRUE;

   if (event->fType == kGKeyPress) {
      fButton = event->fCode;
      UInt_t keysym;
      char str[2];
      gVirtualX->LookupString(event, str, sizeof(str), keysym);
      if (str[0] == 3)   // ctrl-c sets the interrupt flag
         gROOT->SetInterrupt();
      fCanvas->HandleInput(kKeyPress, str[0], keysym);
   } else if (event->fType == kKeyRelease)
      fButton = 0;

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerMotion(Event_t *event)
{
   // Handle mouse motion event in the canvas container.

   if (!fCanvas) return kTRUE;

   Int_t x = event->fX;
   Int_t y = event->fY;

   if (fButton == 0)
      fCanvas->HandleInput(kMouseMotion, x, y);
   if (fButton == kButton1)
      fCanvas->HandleInput(kButton1Motion, x, y);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerExpose(Event_t *event)
{
   // Handle expose events.

   if (!fCanvas) return kTRUE;

   if (event->fCount == 0)
      fCanvas->Flush();

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerCrossing(Event_t *event)
{
   // Handle enter/leave events. Only leave is activated at the moment.

   if (!fCanvas) return kTRUE;

   Int_t x = event->fX;
   Int_t y = event->fY;

   // pointer grabs create also an enter and leave event but with fCode
   // either kNotifyGrab or kNotifyUngrab, don't propagate these events
   if (event->fType == kLeaveNotify && event->fCode == kNotifyNormal)
      fCanvas->HandleInput(kMouseLeave, x, y);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleDNDdrop(TDNDdata *data)
{
   // Handle drop events.

   static Atom_t rootObj  = gVirtualX->InternAtom("application/root", kFALSE);
   static Atom_t uriObj  = gVirtualX->InternAtom("text/uri-list", kFALSE);

   if (data->fDataType == rootObj) {
      TBufferFile buf(TBuffer::kRead, data->fDataLength, (void *)data->fData);
      buf.SetReadMode();
      TObject *obj = (TObject *)buf.ReadObjectAny(TObject::Class());
      gPad->Clear();
      if (obj->InheritsFrom("TGraph"))
         obj->Draw("ACP");
      else if (obj->IsA()->GetMethodAllAny("Draw"))
         obj->Draw();
      gPad->Modified();
      gPad->Update();
      return kTRUE;
   }
   else if (data->fDataType == uriObj) {
      TString sfname((char *)data->fData);
      if (sfname.Length() > 7) {
         sfname.ReplaceAll("\r\n", "");
         TUrl uri(sfname.Data());
         if (sfname.EndsWith(".bmp") ||
            sfname.EndsWith(".gif") ||
            sfname.EndsWith(".jpg") ||
            sfname.EndsWith(".png") ||
            sfname.EndsWith(".tiff") ||
            sfname.EndsWith(".xpm")) {
            TImage *img = TImage::Open(uri.GetFile());
            if (img) {
               img->Draw("xxx");
               img->SetEditable(kTRUE);
            }
         }
         gPad->Modified();
         gPad->Update();
      }
   }
   return kFALSE;
}

//______________________________________________________________________________
Atom_t TRootEmbeddedCanvas::HandleDNDposition(Int_t /*x*/, Int_t /*y*/, Atom_t action,
                                              Int_t xroot, Int_t yroot)
{
   // Handle dragging position events.

   Int_t    px = 0, py = 0;
   Window_t wtarget;

   gVirtualX->TranslateCoordinates(gClient->GetDefaultRoot()->GetId(),
                                   gVirtualX->GetWindowID(fCanvas->GetCanvasID()),
                                   xroot, yroot, px, py, wtarget);

   TPad *pad = fCanvas->Pick(px, py, 0);
   if (pad) {
      pad->cd();
      gROOT->SetSelectedPad(pad);
   }
   return action;
}

//______________________________________________________________________________
Atom_t TRootEmbeddedCanvas::HandleDNDenter(Atom_t *typelist)
{
   // Handle drag enter events.

   static Atom_t rootObj  = gVirtualX->InternAtom("application/root", kFALSE);
   static Atom_t uriObj  = gVirtualX->InternAtom("text/uri-list", kFALSE);
   Atom_t ret = kNone;
   for (int i = 0; typelist[i] != kNone; ++i) {
      if (typelist[i] == rootObj)
         ret = rootObj;
      if (typelist[i] == uriObj)
         ret = uriObj;
   }
   return ret;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleDNDleave()
{
   // Handle drag leave events.

   return kTRUE;
}

//______________________________________________________________________________
void TRootEmbeddedCanvas::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
{
   // Save an embedded canvas as a C++ statement(s) on output stream out.

   if (!GetCanvas()) return;

   if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);

   char quote ='"';

   out << endl << "   // embedded canvas" << endl;
   out << "   TRootEmbeddedCanvas *";
   out << GetName() << " = new TRootEmbeddedCanvas(0" << "," << fParent->GetName()
       << "," << GetWidth() << "," << GetHeight();

   if (fBackground == GetDefaultFrameBackground()) {
      if (GetOptions() == (kSunkenFrame | kDoubleBorder)) {
         out <<");" << endl;
      } else {
         out << "," << GetOptionString() <<");" << endl;
      }
   } else {
      out << "," << GetOptionString() << ",ucolor);" << endl;
   }

   out << "   Int_t w" << GetName() << " = " << GetName()
       << "->GetCanvasWindowId();" << endl;

   static int n = 123;
   TString cname = Form("c%d", n);

   out << "   TCanvas *";
   out <<  cname << " = new TCanvas(";
   out << quote << cname.Data() << quote << ", 10, 10, w"
       << GetName() << ");" << endl;
   out << "   " << GetName() << "->AdoptCanvas(" << cname
       << ");" << endl;

   n++;
   //Next line is a connection to TCanvas::SavePrimitives()
   //GetCanvas()->SavePrimitive(out,option);
}
<commit_msg>From Bertrand: Added handling TKey objects in HandleDNDdrop.<commit_after>// @(#)root/gui:$Id$
// Author: Fons Rademakers   15/07/98

/*************************************************************************
 * 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.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootEmbeddedCanvas                                                  //
//                                                                      //
// This class creates a TGCanvas in which a TCanvas is created. Use     //
// GetCanvas() to get a pointer to the TCanvas.                         //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TRootEmbeddedCanvas.h"
#include "TCanvas.h"
#include "TROOT.h"
#include "Riostream.h"
#include "TStyle.h"
#include "TPluginManager.h"
#include "TVirtualGL.h"
#include "TGDNDManager.h"
#include "TBufferFile.h"
#include "TImage.h"
#include "TClass.h"
#include "TUrl.h"

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TRootEmbeddedContainer                                               //
//                                                                      //
// Utility class used by TRootEmbeddedCanvas. The TRootEmbeddedContainer//
// is the frame embedded in the TGCanvas widget. The ROOT graphics goes //
// into this frame. This class is used to enable input events on this   //
// graphics frame and forward the events to the TRootEmbeddedCanvas     //
// handlers.                                                            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

class TRootEmbeddedContainer : public TGCompositeFrame {
private:
   TRootEmbeddedCanvas  *fCanvas;    // pointer back to embedded canvas
public:
   TRootEmbeddedContainer(TRootEmbeddedCanvas *c, Window_t id, const TGWindow *parent);

   Bool_t  HandleButton(Event_t *ev)
               { return fCanvas->HandleContainerButton(ev); }
   Bool_t  HandleDoubleClick(Event_t *ev)
               { return fCanvas->HandleContainerDoubleClick(ev); }
   Bool_t  HandleConfigureNotify(Event_t *ev)
               { TGFrame::HandleConfigureNotify(ev);
                  return fCanvas->HandleContainerConfigure(ev); }
   Bool_t  HandleKey(Event_t *ev)
               { return fCanvas->HandleContainerKey(ev); }
   Bool_t  HandleMotion(Event_t *ev)
               { return fCanvas->HandleContainerMotion(ev); }
   Bool_t  HandleExpose(Event_t *ev)
               { return fCanvas->HandleContainerExpose(ev); }
   Bool_t  HandleCrossing(Event_t *ev)
               { return fCanvas->HandleContainerCrossing(ev); }
   void    SetEditable(Bool_t) { }
};

//______________________________________________________________________________
TRootEmbeddedContainer::TRootEmbeddedContainer(TRootEmbeddedCanvas *c, Window_t id,
   const TGWindow *p) : TGCompositeFrame(gClient, id, p)
{
   // Create a canvas container.

   fCanvas = c;

   gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
                         kButtonPressMask | kButtonReleaseMask |
                         kPointerMotionMask, kNone, kNone);

   AddInput(kKeyPressMask | kKeyReleaseMask | kPointerMotionMask |
            kExposureMask | kStructureNotifyMask | kLeaveWindowMask);

   fEditDisabled = kEditDisableGrab;
}

ClassImp(TRootEmbeddedCanvas)

//______________________________________________________________________________
TRootEmbeddedCanvas::TRootEmbeddedCanvas(const char *name, const TGWindow *p,
            UInt_t w, UInt_t h, UInt_t options, ULong_t back)
   : TGCanvas(p, w, h, options, back)
{
   // Create an TCanvas embedded in a TGFrame. A pointer to the TCanvas can
   // be obtained via the GetCanvas() member function. To embed a canvas
   // derived from a TCanvas do the following:
   // TRootEmbeddedCanvas *embedded = new TRootEmbeddedCanvas(0, p, w, h);
   //      [note name must be 0, not null string ""]
   // Int_t wid = embedded->GetCanvasWindowId();
   // TMyCanvas *myc = new TMyCanvas("myname", 10, 10, wid);
   // embedded->AdoptCanvas(myc);
   //      [ the MyCanvas is adopted by the embedded canvas and will be
   //        destroyed by it ]

   fCanvas  = 0;
   fButton  = 0;
   fAutoFit = kTRUE;
   fEditDisabled = kEditDisableLayout;

   fCWinId = -1;

   if (gStyle->GetCanvasPreferGL()) {
      //first, initialize GL (if not yet)
      if (!gGLManager) {
         TString x = "win32";
         if (gVirtualX->InheritsFrom("TGX11"))
            x = "x11";

         TPluginHandler *ph = gROOT->GetPluginManager()->FindHandler("TGLManager", x);

         if (ph && ph->LoadPlugin() != -1) {
            if (!ph->ExecPlugin(0))
               Warning("CreateCanvas",
                       "Cannot load GL, will use default canvas imp instead\n");
         }
      }
      if (gGLManager) {
         fCWinId = gGLManager->InitGLWindow((ULong_t)GetViewPort()->GetId());
      }
   }

   if (fCWinId == -1)
      fCWinId = gVirtualX->InitWindow((ULong_t)GetViewPort()->GetId());

   Window_t win = gVirtualX->GetWindowID(fCWinId);
   fCanvasContainer = new TRootEmbeddedContainer(this, win, GetViewPort());
   SetContainer(fCanvasContainer);

   fCanvas = new TCanvas(name ? name : Form("%s_canvas", GetName()), w, h, fCWinId);

   // define DND types
   fDNDTypeList = new Atom_t[3];
   fDNDTypeList[0] = gVirtualX->InternAtom("application/root", kFALSE);
   fDNDTypeList[1] = gVirtualX->InternAtom("text/uri-list", kFALSE);
   fDNDTypeList[2] = 0;
   gVirtualX->SetDNDAware(fId, fDNDTypeList);
   SetDNDTarget(kTRUE);

   if (!p) {
      fCanvas->SetBorderMode(0);
      MapSubwindows();
      Resize(100, 100);
   }
}

//______________________________________________________________________________
TRootEmbeddedCanvas::~TRootEmbeddedCanvas()
{
   // Delete embedded ROOT canvas.

   if (!MustCleanup()) {
      delete fCanvas;
      delete fCanvasContainer;
   }
   delete [] fDNDTypeList;
}

//______________________________________________________________________________
void TRootEmbeddedCanvas::AdoptCanvas(TCanvas *c)
{
   // Canvas c is adopted from this embedded canvas.

   if(c == 0) return;
   c->EmbedInto(fCWinId, fWidth, fHeight);
   fCanvas = c;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerButton(Event_t *event)
{
   // Handle mouse button events in the canvas container.

   if (!fCanvas) return kTRUE;

   Int_t button = event->fCode;
   Int_t x = event->fX;
   Int_t y = event->fY;

   if (event->fType == kButtonPress) {
      fButton = button;
      if (button == kButton1)
         fCanvas->HandleInput(kButton1Down, x, y);
      if (button == kButton2)
         fCanvas->HandleInput(kButton2Down, x, y);
      if (button == kButton3) {
         fCanvas->HandleInput(kButton3Down, x, y);
         fButton = 0;  // button up is consumed by TContextMenu
      }

   } else if (event->fType == kButtonRelease) {
      if (button == kButton1)
         fCanvas->HandleInput(kButton1Up, x, y);
      if (button == kButton2)
         fCanvas->HandleInput(kButton2Up, x, y);
      if (button == kButton3)
         fCanvas->HandleInput(kButton3Up, x, y);

      fButton = 0;
   }

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerDoubleClick(Event_t *event)
{
   // Handle mouse button double click events in the canvas container.

   if (!fCanvas) return kTRUE;

   Int_t button = event->fCode;
   Int_t x = event->fX;
   Int_t y = event->fY;

   if (button == kButton1)
      fCanvas->HandleInput(kButton1Double, x, y);
   if (button == kButton2)
      fCanvas->HandleInput(kButton2Double, x, y);
   if (button == kButton3)
      fCanvas->HandleInput(kButton3Double, x, y);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerConfigure(Event_t *)
{
   // Handle configure (i.e. resize) event.

   if (fAutoFit && fCanvas) {
      fCanvas->Resize();
      fCanvas->Update();
   }
   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerKey(Event_t *event)
{
   // Handle keyboard events in the canvas container.

   if (!fCanvas) return kTRUE;

   if (event->fType == kGKeyPress) {
      fButton = event->fCode;
      UInt_t keysym;
      char str[2];
      gVirtualX->LookupString(event, str, sizeof(str), keysym);
      if (str[0] == 3)   // ctrl-c sets the interrupt flag
         gROOT->SetInterrupt();
      fCanvas->HandleInput(kKeyPress, str[0], keysym);
   } else if (event->fType == kKeyRelease)
      fButton = 0;

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerMotion(Event_t *event)
{
   // Handle mouse motion event in the canvas container.

   if (!fCanvas) return kTRUE;

   Int_t x = event->fX;
   Int_t y = event->fY;

   if (fButton == 0)
      fCanvas->HandleInput(kMouseMotion, x, y);
   if (fButton == kButton1)
      fCanvas->HandleInput(kButton1Motion, x, y);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerExpose(Event_t *event)
{
   // Handle expose events.

   if (!fCanvas) return kTRUE;

   if (event->fCount == 0)
      fCanvas->Flush();

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleContainerCrossing(Event_t *event)
{
   // Handle enter/leave events. Only leave is activated at the moment.

   if (!fCanvas) return kTRUE;

   Int_t x = event->fX;
   Int_t y = event->fY;

   // pointer grabs create also an enter and leave event but with fCode
   // either kNotifyGrab or kNotifyUngrab, don't propagate these events
   if (event->fType == kLeaveNotify && event->fCode == kNotifyNormal)
      fCanvas->HandleInput(kMouseLeave, x, y);

   return kTRUE;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleDNDdrop(TDNDdata *data)
{
   // Handle drop events.

   static Atom_t rootObj  = gVirtualX->InternAtom("application/root", kFALSE);
   static Atom_t uriObj  = gVirtualX->InternAtom("text/uri-list", kFALSE);

   if (data->fDataType == rootObj) {
      TBufferFile buf(TBuffer::kRead, data->fDataLength, (void *)data->fData);
      buf.SetReadMode();
      TObject *obj = (TObject *)buf.ReadObjectAny(TObject::Class());
      gPad->Clear();
      if (obj->InheritsFrom("TGraph"))
         obj->Draw("ACP");
      else if (obj->InheritsFrom("TKey")) {
         TObject *object = (TObject *)gROOT->ProcessLine(Form("((TKey *)0x%lx)->ReadObj();", obj));
         if (object && object->IsA()->GetMethodAllAny("Draw"))
            object->Draw();
      }
      else if (obj->IsA()->GetMethodAllAny("Draw"))
         obj->Draw();
      gPad->Modified();
      gPad->Update();
      return kTRUE;
   }
   else if (data->fDataType == uriObj) {
      TString sfname((char *)data->fData);
      if (sfname.Length() > 7) {
         sfname.ReplaceAll("\r\n", "");
         TUrl uri(sfname.Data());
         if (sfname.EndsWith(".bmp") ||
            sfname.EndsWith(".gif") ||
            sfname.EndsWith(".jpg") ||
            sfname.EndsWith(".png") ||
            sfname.EndsWith(".tiff") ||
            sfname.EndsWith(".xpm")) {
            TImage *img = TImage::Open(uri.GetFile());
            if (img) {
               img->Draw("xxx");
               img->SetEditable(kTRUE);
            }
         }
         gPad->Modified();
         gPad->Update();
      }
   }
   return kFALSE;
}

//______________________________________________________________________________
Atom_t TRootEmbeddedCanvas::HandleDNDposition(Int_t /*x*/, Int_t /*y*/, Atom_t action,
                                              Int_t xroot, Int_t yroot)
{
   // Handle dragging position events.

   Int_t    px = 0, py = 0;
   Window_t wtarget;

   gVirtualX->TranslateCoordinates(gClient->GetDefaultRoot()->GetId(),
                                   gVirtualX->GetWindowID(fCanvas->GetCanvasID()),
                                   xroot, yroot, px, py, wtarget);

   TPad *pad = fCanvas->Pick(px, py, 0);
   if (pad) {
      pad->cd();
      gROOT->SetSelectedPad(pad);
   }
   return action;
}

//______________________________________________________________________________
Atom_t TRootEmbeddedCanvas::HandleDNDenter(Atom_t *typelist)
{
   // Handle drag enter events.

   static Atom_t rootObj  = gVirtualX->InternAtom("application/root", kFALSE);
   static Atom_t uriObj  = gVirtualX->InternAtom("text/uri-list", kFALSE);
   Atom_t ret = kNone;
   for (int i = 0; typelist[i] != kNone; ++i) {
      if (typelist[i] == rootObj)
         ret = rootObj;
      if (typelist[i] == uriObj)
         ret = uriObj;
   }
   return ret;
}

//______________________________________________________________________________
Bool_t TRootEmbeddedCanvas::HandleDNDleave()
{
   // Handle drag leave events.

   return kTRUE;
}

//______________________________________________________________________________
void TRootEmbeddedCanvas::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
{
   // Save an embedded canvas as a C++ statement(s) on output stream out.

   if (!GetCanvas()) return;

   if (fBackground != GetDefaultFrameBackground()) SaveUserColor(out, option);

   char quote ='"';

   out << endl << "   // embedded canvas" << endl;
   out << "   TRootEmbeddedCanvas *";
   out << GetName() << " = new TRootEmbeddedCanvas(0" << "," << fParent->GetName()
       << "," << GetWidth() << "," << GetHeight();

   if (fBackground == GetDefaultFrameBackground()) {
      if (GetOptions() == (kSunkenFrame | kDoubleBorder)) {
         out <<");" << endl;
      } else {
         out << "," << GetOptionString() <<");" << endl;
      }
   } else {
      out << "," << GetOptionString() << ",ucolor);" << endl;
   }

   out << "   Int_t w" << GetName() << " = " << GetName()
       << "->GetCanvasWindowId();" << endl;

   static int n = 123;
   TString cname = Form("c%d", n);

   out << "   TCanvas *";
   out <<  cname << " = new TCanvas(";
   out << quote << cname.Data() << quote << ", 10, 10, w"
       << GetName() << ");" << endl;
   out << "   " << GetName() << "->AdoptCanvas(" << cname
       << ");" << endl;

   n++;
   //Next line is a connection to TCanvas::SavePrimitives()
   //GetCanvas()->SavePrimitive(out,option);
}
<|endoftext|>


<commit_before>#include "pointLight.h"

#include "glm/gtx/string_cast.hpp"
#include "platform.h"
#include "gl/shaderProgram.h"
#include "view/view.h"

namespace Tangram {

std::string PointLight::s_classBlock;
std::string PointLight::s_typeName = "PointLight";

PointLight::PointLight(const std::string& _name, bool _dynamic) :
    Light(_name, _dynamic),
    m_position(0.0),
    m_attenuation(0.0),
    m_innerRadius(0.0),
    m_outerRadius(0.0) {

    m_type = LightType::point;

}

PointLight::~PointLight() {}

void PointLight::setPosition(const glm::vec3 &_pos) {
    m_position.x = _pos.x;
    m_position.y = _pos.y;
    m_position.z = _pos.z;
    m_position.w = 0.0;
}

void PointLight::setAttenuation(float _att){
    m_attenuation = _att;
}

void PointLight::setRadius(float _outer){
    m_innerRadius = 0.0;
    m_outerRadius = _outer;
}

void PointLight::setRadius(float _inner, float _outer){
    m_innerRadius = _inner;
    m_outerRadius = _outer;
}

std::unique_ptr<LightUniforms> PointLight::injectOnProgram(ShaderProgram& _shader) {
    injectSourceBlocks(_shader);

    if (!m_dynamic) { return nullptr; }

    return std::make_unique<Uniforms>(_shader, getUniformName());
}

void PointLight::setupProgram(const View& _view, LightUniforms& _uniforms) {
    Light::setupProgram(_view, _uniforms);

    glm::vec4 position = m_position;

    if (m_origin == LightOrigin::world) {
        // For world origin, format is: [longitude, latitude, meters (default) or pixels w/px units]

        // Move light's world position into camera space
        glm::dvec2 camSpace = _view.getMapProjection().LonLatToMeters(glm::dvec2(m_position.x, m_position.y));
        position.x = camSpace.x - (_view.getPosition().x + _view.getEye().x);
        position.y = camSpace.y - (_view.getPosition().y + _view.getEye().y);
        position.z = position.z - _view.getEye().z;

    } else if (m_origin == LightOrigin::ground) {
        // Leave light's xy in camera space, but z needs to be moved relative to ground plane
        position.z = position.z - _view.getPosition().z;
    }

    if (m_origin == LightOrigin::world || m_origin == LightOrigin::ground) {
        // Light position is a vector from the camera to the light in world space;
        // we can transform this vector into camera space the same way we would with normals
        position = _view.getViewMatrix() * position;
    }

    auto& u = static_cast<Uniforms&>(_uniforms);

    u.shader.setUniformf(u.position, position);

    if (m_attenuation != 0.0) {
        u.shader.setUniformf(u.attenuation, m_attenuation);
    }

    if (m_innerRadius != 0.0) {
        u.shader.setUniformf(u.innerRadius, m_innerRadius);
    }

    if (m_outerRadius != 0.0) {
        u.shader.setUniformf(u.outerRadius, m_outerRadius);
    }
}

std::string PointLight::getClassBlock() {
    if (s_classBlock.empty()) {
        s_classBlock = stringFromFile("shaders/pointLight.glsl", PathType::internal)+"\n";
    }
    return s_classBlock;
}

std::string PointLight::getInstanceDefinesBlock() {
    std::string defines = "";

    if (m_attenuation!=0.0) {
        defines += "#define TANGRAM_POINTLIGHT_ATTENUATION_EXPONENT\n";
    }

    if (m_innerRadius!=0.0) {
        defines += "#define TANGRAM_POINTLIGHT_ATTENUATION_INNER_RADIUS\n";
    }

    if (m_outerRadius!=0.0) {
        defines += "#define TANGRAM_POINTLIGHT_ATTENUATION_OUTER_RADIUS\n";
    }
    return defines;
}

std::string PointLight::getInstanceAssignBlock() {
    std::string block = Light::getInstanceAssignBlock();
    if (!m_dynamic) {
        block += ", " + glm::to_string(m_position);
        if (m_attenuation!=0.0) {
            block += ", " + std::to_string(m_attenuation);
        }
        if (m_innerRadius!=0.0) {
            block += ", " + std::to_string(m_innerRadius);
        }
        if (m_outerRadius!=0.0) {
            block += ", " + std::to_string(m_outerRadius);
        }
        block += ")";
    }
    return block;
}

const std::string& PointLight::getTypeName() {

    return s_typeName;

}

}
<commit_msg>core/Fix point light ground attachment on tilted view<commit_after>#include "pointLight.h"

#include "glm/gtx/string_cast.hpp"
#include "platform.h"
#include "gl/shaderProgram.h"
#include "view/view.h"

namespace Tangram {

std::string PointLight::s_classBlock;
std::string PointLight::s_typeName = "PointLight";

PointLight::PointLight(const std::string& _name, bool _dynamic) :
    Light(_name, _dynamic),
    m_position(0.0),
    m_attenuation(0.0),
    m_innerRadius(0.0),
    m_outerRadius(0.0) {

    m_type = LightType::point;

}

PointLight::~PointLight() {}

void PointLight::setPosition(const glm::vec3 &_pos) {
    m_position.x = _pos.x;
    m_position.y = _pos.y;
    m_position.z = _pos.z;
    m_position.w = 0.0;
}

void PointLight::setAttenuation(float _att){
    m_attenuation = _att;
}

void PointLight::setRadius(float _outer){
    m_innerRadius = 0.0;
    m_outerRadius = _outer;
}

void PointLight::setRadius(float _inner, float _outer){
    m_innerRadius = _inner;
    m_outerRadius = _outer;
}

std::unique_ptr<LightUniforms> PointLight::injectOnProgram(ShaderProgram& _shader) {
    injectSourceBlocks(_shader);

    if (!m_dynamic) { return nullptr; }

    return std::make_unique<Uniforms>(_shader, getUniformName());
}

void PointLight::setupProgram(const View& _view, LightUniforms& _uniforms) {
    Light::setupProgram(_view, _uniforms);

    glm::vec4 position = m_position;

    if (m_origin == LightOrigin::world) {
        // For world origin, format is: [longitude, latitude, meters (default) or pixels w/px units]

        // Move light's world position into camera space
        glm::dvec2 camSpace = _view.getMapProjection().LonLatToMeters(glm::dvec2(m_position.x, m_position.y));
        position.x = camSpace.x - (_view.getPosition().x + _view.getEye().x);
        position.y = camSpace.y - (_view.getPosition().y + _view.getEye().y);
        position.z = position.z - _view.getEye().z;

    } else if (m_origin == LightOrigin::ground) {
        // Move light position relative to the eye position in world space
        position -= glm::vec4(_view.getEye(), 0.0);
    }

    if (m_origin == LightOrigin::world || m_origin == LightOrigin::ground) {
        // Light position is a vector from the camera to the light in world space;
        // we can transform this vector into camera space the same way we would with normals
        position = _view.getViewMatrix() * position;
    }

    auto& u = static_cast<Uniforms&>(_uniforms);

    u.shader.setUniformf(u.position, position);

    if (m_attenuation != 0.0) {
        u.shader.setUniformf(u.attenuation, m_attenuation);
    }

    if (m_innerRadius != 0.0) {
        u.shader.setUniformf(u.innerRadius, m_innerRadius);
    }

    if (m_outerRadius != 0.0) {
        u.shader.setUniformf(u.outerRadius, m_outerRadius);
    }
}

std::string PointLight::getClassBlock() {
    if (s_classBlock.empty()) {
        s_classBlock = stringFromFile("shaders/pointLight.glsl", PathType::internal)+"\n";
    }
    return s_classBlock;
}

std::string PointLight::getInstanceDefinesBlock() {
    std::string defines = "";

    if (m_attenuation!=0.0) {
        defines += "#define TANGRAM_POINTLIGHT_ATTENUATION_EXPONENT\n";
    }

    if (m_innerRadius!=0.0) {
        defines += "#define TANGRAM_POINTLIGHT_ATTENUATION_INNER_RADIUS\n";
    }

    if (m_outerRadius!=0.0) {
        defines += "#define TANGRAM_POINTLIGHT_ATTENUATION_OUTER_RADIUS\n";
    }
    return defines;
}

std::string PointLight::getInstanceAssignBlock() {
    std::string block = Light::getInstanceAssignBlock();
    if (!m_dynamic) {
        block += ", " + glm::to_string(m_position);
        if (m_attenuation!=0.0) {
            block += ", " + std::to_string(m_attenuation);
        }
        if (m_innerRadius!=0.0) {
            block += ", " + std::to_string(m_innerRadius);
        }
        if (m_outerRadius!=0.0) {
            block += ", " + std::to_string(m_outerRadius);
        }
        block += ")";
    }
    return block;
}

const std::string& PointLight::getTypeName() {

    return s_typeName;

}

}
<|endoftext|>