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

  Program:   Visualization Toolkit
  Module:    vtkTkAppInit.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/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 notice for more information.

=========================================================================*/
/*
 * tkAppInit.c --
 *
 *      Provides a default version of the Tcl_AppInit procedure for
 *      use in wish and similar Tk-based applications.
 *
 * Copyright (c) 1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifdef VTK_COMPILED_USING_MPI
# include <mpi.h>
# include "vtkMPIController.h"
#endif // VTK_COMPILED_USING_MPI

#include "vtkSystemIncludes.h"
#include "vtkToolkits.h"
#include "Wrapping/Tcl/vtkTkAppInitConfigure.h"

#if defined(CMAKE_INTDIR)
# define VTK_TCL_PACKAGE_DIR VTK_TCL_PACKAGE_DIR_BUILD "/" CMAKE_INTDIR
#else
# define VTK_TCL_PACKAGE_DIR VTK_TCL_PACKAGE_DIR_BUILD
#endif

#ifdef VTK_USE_RENDERING
# include "vtkTk.h"
#else
# include "vtkTcl.h"
#endif

/*
 * Make sure all the kits register their classes with vtkInstantiator.
 */
#include "vtkCommonInstantiator.h"
#include "vtkFilteringInstantiator.h"
#include "vtkIOInstantiator.h"
#include "vtkImagingInstantiator.h"
#include "vtkGraphicsInstantiator.h"

#ifdef VTK_USE_RENDERING
#include "vtkRenderingInstantiator.h"
#endif

#ifdef VTK_USE_PATENTED
#include "vtkPatentedInstantiator.h"
#endif

#ifdef VTK_USE_HYBRID
#include "vtkHybridInstantiator.h"
#endif

#ifdef VTK_USE_PARALLEL
#include "vtkParallelInstantiator.h"
#endif

static void vtkTkAppInitEnableMSVCDebugHook();

/*
 *----------------------------------------------------------------------
 *
 * main --
 *
 *      This is the main program for the application.
 *
 * Results:
 *      None: Tk_Main never returns here, so this procedure never
 *      returns either.
 *
 * Side effects:
 *      Whatever the application does.
 *
 *----------------------------------------------------------------------
 */
#ifdef VTK_COMPILED_USING_MPI
class vtkMPICleanup {
public:
  vtkMPICleanup()
    {
      this->Controller = 0;
    }
  void Initialize(int *argc, char ***argv)
    {
      MPI_Init(argc, argv);
      this->Controller = vtkMPIController::New();
      this->Controller->Initialize(argc, argv, 1);
      vtkMultiProcessController::SetGlobalController(this->Controller);
    }
  ~vtkMPICleanup()
    {
      if ( this->Controller )
        {
        this->Controller->Finalize();
        this->Controller->Delete();
        }
    }
private:
  vtkMPIController *Controller;
};

static vtkMPICleanup VTKMPICleanup;

#endif // VTK_COMPILED_USING_MPI

int
main(int argc, char **argv)
{
  ios::sync_with_stdio();
  vtkTkAppInitEnableMSVCDebugHook();

#ifdef VTK_COMPILED_USING_MPI
  VTKMPICleanup.Initialize(&argc, &argv);
#endif // VTK_COMPILED_USING_MPI

#ifdef VTK_USE_RENDERING
  Tk_Main(argc, argv, Tcl_AppInit);
#else
  Tcl_Main(argc, argv, Tcl_AppInit);
#endif

  return 0;                  /* Needed only to prevent compiler warning. */
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AppInit --
 *
 *      This procedure performs application-specific initialization.
 *      Most applications, especially those that incorporate additional
 *      packages, will have their own version of this procedure.
 *
 * Results:
 *      Returns a standard Tcl completion code, and leaves an error
 *      message in interp->result if an error occurs.
 *
 * Side effects:
 *      Depends on the startup script.
 *
 *----------------------------------------------------------------------
 */

extern "C" int Vtkcommontcl_Init(Tcl_Interp *interp);
extern "C" int Vtkfilteringtcl_Init(Tcl_Interp *interp);
extern "C" int Vtkimagingtcl_Init(Tcl_Interp *interp);
extern "C" int Vtkgraphicstcl_Init(Tcl_Interp *interp);
extern "C" int Vtkiotcl_Init(Tcl_Interp *interp);

#ifdef VTK_USE_RENDERING
extern "C" int Vtkrenderingtcl_Init(Tcl_Interp *interp);
#if defined(VTK_DISABLE_TK_INIT) && !defined(VTK_USE_COCOA)
extern "C" int Vtktkrenderwidget_Init(Tcl_Interp *interp);
extern "C" int Vtktkimageviewerwidget_Init(Tcl_Interp *interp);
#endif
#endif

#ifdef VTK_USE_PATENTED
extern "C" int Vtkpatentedtcl_Init(Tcl_Interp *interp);
#endif

#ifdef VTK_USE_HYBRID
extern "C" int Vtkhybridtcl_Init(Tcl_Interp *interp);
#endif

#ifdef VTK_USE_PARALLEL
extern "C" int Vtkparalleltcl_Init(Tcl_Interp *interp);
#endif

void help() {

}

int Tcl_AppInit(Tcl_Interp *interp)
{
#ifdef __CYGWIN__
  Tcl_SetVar(interp, "tclDefaultLibrary", "/usr/share/tcl" TCL_VERSION, TCL_GLOBAL_ONLY);
#endif
  if (Tcl_Init(interp) == TCL_ERROR) {
  return TCL_ERROR;
  }
#ifdef VTK_USE_RENDERING
  if (Tk_Init(interp) == TCL_ERROR) {
  return TCL_ERROR;
  }
#endif
  /* init the core vtk stuff */
  if (Vtkcommontcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
  if (Vtkfilteringtcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
  if (Vtkimagingtcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
  if (Vtkgraphicstcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
  if (Vtkiotcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }

#ifdef VTK_USE_RENDERING
  if (Vtkrenderingtcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#if defined(VTK_DISABLE_TK_INIT) && !defined(VTK_USE_COCOA)
  // Need to init here because rendering did not when this option is on
  if (Vtktkrenderwidget_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
  if (Vtktkimageviewerwidget_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#endif
#endif

#ifdef VTK_USE_PATENTED
  if (Vtkpatentedtcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#endif

#ifdef VTK_USE_HYBRID
  if (Vtkhybridtcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#endif

#ifdef VTK_USE_PARALLEL
  if (Vtkparalleltcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#endif

  /*
   * Append path to VTK packages to auto_path
   */
  static char script[] =
    "foreach dir [list {" VTK_TCL_PACKAGE_DIR "} {" VTK_TCL_INSTALL_DIR "}"
    " [file join [file dirname [file dirname [info nameofexecutable]]] Wrapping Tcl]"
    " [file join [file dirname [file dirname [info nameofexecutable]]] lib vtk tcl]"
    " ] {\n"
    "  if {[file isdirectory $dir]} {\n"
    "    lappend auto_path $dir\n"
    "  }\n"
    "}\n"
    "rename package package.orig\n"
    "proc package {args} {\n"
    "  if {[catch {set package_res [eval package.orig $args]} catch_res]} {\n"
    "    global errorInfo env\n"
    "    if {[lindex $args 0] == \"require\"} {\n"
    "      set expecting {can\'t find package vtk}\n"
    "      if {![string compare -length [string length $expecting] $catch_res $expecting]} {\n"
    "        set msg {The Tcl interpreter was probably not able to find the"
    " VTK packages.  Please check that your TCLLIBPATH environment variable"
    " includes the path to your VTK Tcl directory.  You might find it under"
    " your VTK binary directory in Wrapping/Tcl, or under your"
    " site-specific {CMAKE_INSTALL_PREFIX}/lib/vtk/tcl directory.}\n"
    "        if {[info exists env(TCLLIBPATH)]} {\n"
    "          append msg \"  The TCLLIBPATH current value is: $env(TCLLIBPATH).\"\n"
    "        }\n"
    "        set errorInfo \"$msg  The TCLLIBPATH variable is a set of"
    " space separated paths (hence, path containing spaces should be"
    " surrounded by quotes first). Windows users should use forward"
    " (Unix-style) slashes \'/\' instead of the usual backward slashes. "
    " More informations can be found in the Wrapping/Tcl/README source"
    " file (also available online at"
    " http://www.vtk.org/cgi-bin/cvsweb.cgi/~checkout~/VTK/Wrapping/Tcl/README).\n"
    "$errorInfo\"\n"
    "      }\n"
    "    }\n"
    "  error $catch_res $errorInfo\n"
    "  }\n"
    "  return $package_res\n"
    "}\n";

  Tcl_Eval(interp, script);

  /*
   * Specify a user-specific startup file to invoke if the application
   * is run interactively.  Typically the startup file is "~/.apprc"
   * where "app" is the name of the application.  If this line is deleted
   * then no user-specific startup file will be run under any conditions.
   */

  Tcl_SetVar(interp,
             (char *) "tcl_rcFileName",
             (char *) "~/.vtkrc",
             TCL_GLOBAL_ONLY);
  return TCL_OK;
}

// For a DEBUG build on MSVC, add a hook to prevent error dialogs when
// being run from DART.
#if defined(_MSC_VER) && defined(_DEBUG)
# include <crtdbg.h>
static int vtkTkAppInitDebugReport(int, char* message, int*)
{
  fprintf(stderr, message);
  exit(1);
}
void vtkTkAppInitEnableMSVCDebugHook()
{
  if(getenv("DART_TEST_FROM_DART"))
    {
    _CrtSetReportHook(vtkTkAppInitDebugReport);
    }
}
#else
void vtkTkAppInitEnableMSVCDebugHook()
{
}
#endif
<commit_msg>FIX: help Tcl/Tk finding its support files when building VTK against Tcl/Tk *static*. If TCL_LIBRARY or TK_LIBRARY are not defined, search inside [path to vtk.exe]/TclTk/lib, which will be populated in the future (or right now by ParaViewComplete)<commit_after>/*=========================================================================

Program:   Visualization Toolkit
Module:    vtkTkAppInit.cxx

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/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 notice for more information.

=========================================================================*/
/*
 * tkAppInit.c --
 *
 *      Provides a default version of the Tcl_AppInit procedure for
 *      use in wish and similar Tk-based applications.
 *
 * Copyright (c) 1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#ifdef VTK_COMPILED_USING_MPI
# include <mpi.h>
# include "vtkMPIController.h"
#endif // VTK_COMPILED_USING_MPI

#include "vtkSystemIncludes.h"
#include "vtkToolkits.h"
#include "Wrapping/Tcl/vtkTkAppInitConfigure.h"

#ifdef VTK_TCL_TK_STATIC
#include <sys/stat.h>
#endif

#if defined(CMAKE_INTDIR)
# define VTK_TCL_PACKAGE_DIR VTK_TCL_PACKAGE_DIR_BUILD "/" CMAKE_INTDIR
#else
# define VTK_TCL_PACKAGE_DIR VTK_TCL_PACKAGE_DIR_BUILD
#endif

#ifdef VTK_USE_RENDERING
# include "vtkTk.h"
#else
# include "vtkTcl.h"
#endif

/*
 * Make sure all the kits register their classes with vtkInstantiator.
 */
#include "vtkCommonInstantiator.h"
#include "vtkFilteringInstantiator.h"
#include "vtkIOInstantiator.h"
#include "vtkImagingInstantiator.h"
#include "vtkGraphicsInstantiator.h"

#ifdef VTK_USE_RENDERING
#include "vtkRenderingInstantiator.h"
#endif

#ifdef VTK_USE_PATENTED
#include "vtkPatentedInstantiator.h"
#endif

#ifdef VTK_USE_HYBRID
#include "vtkHybridInstantiator.h"
#endif

#ifdef VTK_USE_PARALLEL
#include "vtkParallelInstantiator.h"
#endif

static void vtkTkAppInitEnableMSVCDebugHook();

/*
 *----------------------------------------------------------------------
 *
 * main --
 *
 *      This is the main program for the application.
 *
 * Results:
 *      None: Tk_Main never returns here, so this procedure never
 *      returns either.
 *
 * Side effects:
 *      Whatever the application does.
 *
 *----------------------------------------------------------------------
 */
#ifdef VTK_COMPILED_USING_MPI
class vtkMPICleanup {
public:
  vtkMPICleanup()
    {
      this->Controller = 0;
    }
  void Initialize(int *argc, char ***argv)
    {
      MPI_Init(argc, argv);
      this->Controller = vtkMPIController::New();
      this->Controller->Initialize(argc, argv, 1);
      vtkMultiProcessController::SetGlobalController(this->Controller);
    }
  ~vtkMPICleanup()
    {
      if ( this->Controller )
        {
        this->Controller->Finalize();
        this->Controller->Delete();
        }
    }
private:
  vtkMPIController *Controller;
};

static vtkMPICleanup VTKMPICleanup;

#endif // VTK_COMPILED_USING_MPI

int
main(int argc, char **argv)
{
  ios::sync_with_stdio();
  vtkTkAppInitEnableMSVCDebugHook();

#ifdef VTK_COMPILED_USING_MPI
  VTKMPICleanup.Initialize(&argc, &argv);
#endif // VTK_COMPILED_USING_MPI

  // This is mandatory *now*, it does more than just finding the executable
  // (like finding the encodings, setting variables depending on the value
  // of TCL_LIBRARY, TK_LIBRARY

  Tcl_FindExecutable(argv[0]);

#ifdef VTK_USE_RENDERING
  Tk_Main(argc, argv, Tcl_AppInit);
#else
  Tcl_Main(argc, argv, Tcl_AppInit);
#endif

  return 0;                  /* Needed only to prevent compiler warning. */
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_AppInit --
 *
 *      This procedure performs application-specific initialization.
 *      Most applications, especially those that incorporate additional
 *      packages, will have their own version of this procedure.
 *
 * Results:
 *      Returns a standard Tcl completion code, and leaves an error
 *      message in interp->result if an error occurs.
 *
 * Side effects:
 *      Depends on the startup script.
 *
 *----------------------------------------------------------------------
 */

extern "C" int Vtkcommontcl_Init(Tcl_Interp *interp);
extern "C" int Vtkfilteringtcl_Init(Tcl_Interp *interp);
extern "C" int Vtkimagingtcl_Init(Tcl_Interp *interp);
extern "C" int Vtkgraphicstcl_Init(Tcl_Interp *interp);
extern "C" int Vtkiotcl_Init(Tcl_Interp *interp);

#ifdef VTK_USE_RENDERING
extern "C" int Vtkrenderingtcl_Init(Tcl_Interp *interp);
#if defined(VTK_DISABLE_TK_INIT) && !defined(VTK_USE_COCOA)
extern "C" int Vtktkrenderwidget_Init(Tcl_Interp *interp);
extern "C" int Vtktkimageviewerwidget_Init(Tcl_Interp *interp);
#endif
#endif

#ifdef VTK_USE_PATENTED
extern "C" int Vtkpatentedtcl_Init(Tcl_Interp *interp);
#endif

#ifdef VTK_USE_HYBRID
extern "C" int Vtkhybridtcl_Init(Tcl_Interp *interp);
#endif

#ifdef VTK_USE_PARALLEL
extern "C" int Vtkparalleltcl_Init(Tcl_Interp *interp);
#endif

void help()
{
}

#ifdef VTK_TCL_TK_STATIC
int vtkTkAppInitFileExists(const char *filename)
{
  struct stat fs;
  return (filename && !stat(filename, &fs)) ? 1 : 0;
}

const char* vtkTkAppInitGetFilenamePath(const char *filename, char *path)
{
  if (!path)
    {
    return path;
    }

  if (!filename || !strlen(filename))
    {
    path[0] = '\0';
    return path;
    }

  const char *ptr = filename + strlen(filename) - 1;
  while (ptr > filename && *ptr != '/' && *ptr != '\\')
    {
    ptr--;
    }

  size_t length = ptr - filename;
  if (length)
    {
    strncpy(path, filename, length);
    }
  path[length] = '\0';

  return path;
}

const char* vtkTkAppInitConvertToUnixSlashes(const char* path, char *unix_path)
{
  if (!unix_path)
    {
    return unix_path;
    }

  unix_path[0] = '\0';
  if (!path)
    {
    return unix_path;
    }

  if (path[0] == '~')
    {
    const char* home = getenv("HOME");
    if(home)
      {
      strcpy(unix_path, home);
      }
    }
  strcat(unix_path, path);

  size_t length = strlen(unix_path);
  if (length < 1)
    {
    return unix_path;
    }

  size_t i;
  for (i = 0; i < length; ++i)
    {
    if(unix_path[i] == '\\')
      {
      unix_path[i] = '/';
      }
    }

  if (unix_path[length - 1] == '/')
    {
    unix_path[length - 1] = '\0';
    }

  return unix_path;
}
#endif

int Tcl_AppInit(Tcl_Interp *interp)
{
#ifdef __CYGWIN__
  Tcl_SetVar(interp, "tclDefaultLibrary", "/usr/share/tcl" TCL_VERSION, TCL_GLOBAL_ONLY);
#endif

  /*
    Tcl/Tk requires support files to work (set of tcl files).
    When an app is linked against Tcl/Tk shared libraries, the path to
    the libraries is used by Tcl/Tk to search for its support files.
    For example, on Windows, if bin/tcl84.dll is the shared lib, support
    files will be searched in bin/../lib/tcl8.4, which is where they are
    usually installed.
    If an app is linked against Tcl/Tk *static* libraries, there is no
    way for Tcl/Tk to find its support files. In that case, it will
    use the TCL_LIBRARY and TK_LIBRARY environment variable (those should
    point to the support files dir, ex: c:/tcl/lib/tcl8.4, c:/tk/lib/tcl8.4).

    The above code will also make Tcl/Tk search inside VTK's build/install
    directory, more precisely inside a TclTk/lib sub dir.
    ex: [path to vtk.exe]/TclTk/lib/tcl8.4, [path to vtk.exe]/TclTk/lib/tk8.4
    If we provide support files in the future, or if they are provided
    by turn-key apps (ParaView or VolView), this is where they are going to
    be copied.
  */

#ifdef VTK_TCL_TK_STATIC
  int has_tcllibpath_env = getenv("TCL_LIBRARY") ? 1 : 0;
  int has_tklibpath_env = getenv("TK_LIBRARY") ? 1 : 0;
  if (!has_tcllibpath_env || !has_tklibpath_env)
    {
    const char *nameofexec = Tcl_GetNameOfExecutable();
    if (nameofexec && vtkTkAppInitFileExists(nameofexec))
      {
      char dir[1024], dir_unix[1024], buffer[1024];
      vtkTkAppInitGetFilenamePath(nameofexec, dir);
      vtkTkAppInitConvertToUnixSlashes(dir, dir_unix);
      sprintf(buffer, "%s/TclTk", dir_unix);
      if (vtkTkAppInitFileExists(buffer))
        {
        if (!has_tcllibpath_env)
          {
          char tcl_library[1024] = "";
          sprintf(tcl_library, "%s/lib/tcl%s", buffer, TCL_VERSION);
          if (vtkTkAppInitFileExists(tcl_library))
            {
            // Setting TCL_LIBRARY won't do the trick, it's too late
            Tcl_SetVar(interp, "tcl_library", tcl_library,
                       TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
            }
          }
#ifdef VTK_USE_RENDERING
        if (!has_tklibpath_env)
          {
          char tk_library[1024] = "";
          sprintf(tk_library, "%s/lib/tk%s", buffer, TK_VERSION);
          if (vtkTkAppInitFileExists(tk_library))
            {
            // Setting TK_LIBRARY won't do the trick, it's too late
            Tcl_SetVar(interp, "tk_library", tk_library,
                       TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG);
            }
          }
#endif
        }
      }
    }
#endif

  if (Tcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }

#ifdef VTK_USE_RENDERING
  if (Tk_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#endif

  /* init the core vtk stuff */
  if (Vtkcommontcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
  if (Vtkfilteringtcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
  if (Vtkimagingtcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
  if (Vtkgraphicstcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
  if (Vtkiotcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }

#ifdef VTK_USE_RENDERING
  if (Vtkrenderingtcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#if defined(VTK_DISABLE_TK_INIT) && !defined(VTK_USE_COCOA)
  // Need to init here because rendering did not when this option is on
  if (Vtktkrenderwidget_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
  if (Vtktkimageviewerwidget_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#endif
#endif

#ifdef VTK_USE_PATENTED
  if (Vtkpatentedtcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#endif

#ifdef VTK_USE_HYBRID
  if (Vtkhybridtcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#endif

#ifdef VTK_USE_PARALLEL
  if (Vtkparalleltcl_Init(interp) == TCL_ERROR)
    {
    return TCL_ERROR;
    }
#endif

  /*
   * Append path to VTK packages to auto_path
   */
  static char script[] =
    "foreach dir [list {" VTK_TCL_PACKAGE_DIR "} {" VTK_TCL_INSTALL_DIR "}"
    " [file join [file dirname [file dirname [info nameofexecutable]]] Wrapping Tcl]"
    " [file join [file dirname [file dirname [info nameofexecutable]]] lib vtk tcl]"
    " ] {\n"
    "  if {[file isdirectory $dir]} {\n"
    "    lappend auto_path $dir\n"
    "  }\n"
    "}\n"
    "rename package package.orig\n"
    "proc package {args} {\n"
    "  if {[catch {set package_res [eval package.orig $args]} catch_res]} {\n"
    "    global errorInfo env\n"
    "    if {[lindex $args 0] == \"require\"} {\n"
    "      set expecting {can\'t find package vtk}\n"
    "      if {![string compare -length [string length $expecting] $catch_res $expecting]} {\n"
    "        set msg {The Tcl interpreter was probably not able to find the"
    " VTK packages.  Please check that your TCLLIBPATH environment variable"
    " includes the path to your VTK Tcl directory.  You might find it under"
    " your VTK binary directory in Wrapping/Tcl, or under your"
    " site-specific {CMAKE_INSTALL_PREFIX}/lib/vtk/tcl directory.}\n"
    "        if {[info exists env(TCLLIBPATH)]} {\n"
    "          append msg \"  The TCLLIBPATH current value is: $env(TCLLIBPATH).\"\n"
    "        }\n"
    "        set errorInfo \"$msg  The TCLLIBPATH variable is a set of"
    " space separated paths (hence, path containing spaces should be"
    " surrounded by quotes first). Windows users should use forward"
    " (Unix-style) slashes \'/\' instead of the usual backward slashes. "
    " More informations can be found in the Wrapping/Tcl/README source"
    " file (also available online at"
    " http://www.vtk.org/cgi-bin/cvsweb.cgi/~checkout~/VTK/Wrapping/Tcl/README).\n"
    "$errorInfo\"\n"
    "      }\n"
    "    }\n"
    "  error $catch_res $errorInfo\n"
    "  }\n"
    "  return $package_res\n"
    "}\n";

  Tcl_Eval(interp, script);

  /*
   * Specify a user-specific startup file to invoke if the application
   * is run interactively.  Typically the startup file is "~/.apprc"
   * where "app" is the name of the application.  If this line is deleted
   * then no user-specific startup file will be run under any conditions.
   */

  Tcl_SetVar(interp,
             (char *) "tcl_rcFileName",
             (char *) "~/.vtkrc",
             TCL_GLOBAL_ONLY);
  return TCL_OK;
}

// For a DEBUG build on MSVC, add a hook to prevent error dialogs when
// being run from DART.
#if defined(_MSC_VER) && defined(_DEBUG)
# include <crtdbg.h>
static int vtkTkAppInitDebugReport(int, char* message, int*)
{
  fprintf(stderr, message);
  exit(1);
}
void vtkTkAppInitEnableMSVCDebugHook()
{
  if(getenv("DART_TEST_FROM_DART"))
    {
    _CrtSetReportHook(vtkTkAppInitDebugReport);
    }
}
#else
void vtkTkAppInitEnableMSVCDebugHook()
{
}
#endif
<|endoftext|>


<commit_before>#include <YCommon/Headers/stdincludes.h>
#include "StringTable.h"

#include <YCommon/YContainers/AtomicHashTable.h>

namespace YEngine { namespace YCore {

namespace {
  YCommon::YContainers::AtomicHashTable gHashTable;
  size_t max_string_size = 0;
}

size_t GetAllocationSize(size_t max_string_size, size_t table_size) {
  return YCommon::YContainers::AtomicHashTable::GetAllocationSize(
      table_size, max_string_size);
}

void StringTable::Initialize(size_t max_string_size, size_t table_size,
                             void* buffer, size_t buffer_size) {
  gHashTable.Init(buffer, buffer_size, table_size, max_string_size);
  max_string_size = max_string_size;
}

void StringTable::Terminate() {
  gHashTable.Reset();
  max_string_size = 0;
}

uint64_t StringTable::AddString(const char* string, size_t string_size) {
  YDEBUG_CHECK(string_size <= max_string_size,
               "Cannot exceed maximum string size: %u > %u",
               static_cast<uint32_t>(string_size),
               static_cast<uint32_t>(max_string_size));
  uint64_t hash_key = 0;
  gHashTable.Insert(string, string_size, string, string_size, &hash_key);
  return hash_key;
}

const char* StringTable::StringLookup(uint64_t string_hash) {
  const void* value = gHashTable.GetValue(string_hash);
  YDEBUG_CHECK(value != NULL, "Cannot lookup string which does not exist!");
  return static_cast<const char*>(value);
}

}} // namespace YEngine { namespace YCore {
<commit_msg>Fixed string table initialization.<commit_after>#include <YCommon/Headers/stdincludes.h>
#include "StringTable.h"

#include <YCommon/YContainers/AtomicHashTable.h>

namespace YEngine { namespace YCore {

namespace {
  YCommon::YContainers::AtomicHashTable gHashTable;
  size_t gMaxStringSize = 0;
}

size_t GetAllocationSize(size_t max_string_size, size_t table_size) {
  return YCommon::YContainers::AtomicHashTable::GetAllocationSize(
      table_size, max_string_size);
}

void StringTable::Initialize(size_t max_string_size, size_t table_size,
                             void* buffer, size_t buffer_size) {
  YDEBUG_CHECK(max_string_size > 0 && table_size > 0,
               "Invalid StringTable initialization values.");
  gHashTable.Init(buffer, buffer_size, table_size, max_string_size);
  gMaxStringSize = max_string_size;
}

void StringTable::Terminate() {
  gHashTable.Reset();
  gMaxStringSize = 0;
}

uint64_t StringTable::AddString(const char* string, size_t string_size) {
  YDEBUG_CHECK(string_size <= gMaxStringSize,
               "Cannot exceed maximum string size: %u > %u",
               static_cast<uint32_t>(string_size),
               static_cast<uint32_t>(gMaxStringSize));
  uint64_t hash_key = 0;
  gHashTable.Insert(string, string_size, string, string_size, &hash_key);
  return hash_key;
}

const char* StringTable::StringLookup(uint64_t string_hash) {
  const void* value = gHashTable.GetValue(string_hash);
  YDEBUG_CHECK(value != NULL, "Cannot lookup string which does not exist!");
  return static_cast<const char*>(value);
}

}} // namespace YEngine { namespace YCore {
<|endoftext|>


<commit_before>#include "CSourceParser.h"

#include <iostream>
#include <antlr3.h>
#include <CLexer.h>
#include <CParser.h>
#include <stdio.h>

CSourceParser::CSourceParser()
{

}

CSourceParser::~CSourceParser()
{
}

void CSourceParser::Parse(std::string fileName)
{
    ANTLR3_UINT8 *fName = (pANTLR3_UINT8)fileName.c_str();

    ANTLR3_INPUT_STREAM  *input  = antlr3FileStreamNew(fName, ANTLR3_ENC_UTF8);
    if (input == NULL)
    {
        ANTLR3_FPRINTF(stderr, "Unable to open file %s.\n", (char *)fName);
        exit(ANTLR3_ERR_NOMEM);    }

    CLexer *lxr  = CLexerNew(input);      // CLexerNew is generated by ANTLR
    if (lxr == NULL)
    {
        ANTLR3_FPRINTF(stderr, "Unable to create the lexer due to malloc() failure1\n");
        exit(ANTLR3_ERR_NOMEM);
    }

    ANTLR3_COMMON_TOKEN_STREAM  *tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr));
    if (tstream == NULL)
    {
        ANTLR3_FPRINTF(stderr, "Out of memory trying to allocate token stream\n");
        exit(ANTLR3_ERR_NOMEM);
    }

    CParser *psr = CParserNew(tstream);
    CompilationContext::GetInstance()->CurrentParser = psr->pParser;

    CompilationContext::GetInstance()->CodeDom = psr->translation_unit(psr);

    CompilationContext::GetInstance()->CurrentParser = NULL;

    psr     ->free(psr);
    psr     = NULL;
    tstream ->free(tstream);
    tstream = NULL;
    lxr     ->free(lxr);
    lxr     = NULL;
    input   ->close(input);
    input   = NULL;
}

<commit_msg>add option to print more information if -g is enabled<commit_after>#include "CSourceParser.h"

#include <iostream>
#include <antlr3.h>
#include <CLexer.h>
#include <CParser.h>
#include <stdio.h>

CSourceParser::CSourceParser()
{

}

CSourceParser::~CSourceParser()
{
}

void CSourceParser::Parse(std::string fileName)
{

    ANTLR3_UINT8 *fName = (pANTLR3_UINT8)fileName.c_str();

    ANTLR3_INPUT_STREAM  *input  = antlr3FileStreamNew(fName, ANTLR3_ENC_UTF8);
    if (input == NULL)
    {
        ANTLR3_FPRINTF(stderr, "Unable to open file %s.\n", (char *)fName);
        exit(ANTLR3_ERR_NOMEM);    }

    CLexer *lxr  = CLexerNew(input);      // CLexerNew is generated by ANTLR
    if (lxr == NULL)
    {
        ANTLR3_FPRINTF(stderr, "Unable to create the lexer due to malloc() failure1\n");
        exit(ANTLR3_ERR_NOMEM);
    }

    if(CompilationContext::GetInstance()->Debug)
        std::cout << "Calling altlr3CommonTokenStreamSourceNew..." << std::endl;

    ANTLR3_COMMON_TOKEN_STREAM  *tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT, TOKENSOURCE(lxr));
    if (tstream == NULL)
    {
        ANTLR3_FPRINTF(stderr, "Out of memory trying to allocate token stream\n");
        exit(ANTLR3_ERR_NOMEM);
    }

    if(CompilationContext::GetInstance()->Debug)
        std::cout << "Called altlr3CommonTokenStreamSourceNew..." << std::endl;

    CParser *psr = CParserNew(tstream);

    CompilationContext::GetInstance()->CurrentParser = psr->pParser;

    if(CompilationContext::GetInstance()->Debug)
    {
        printf("Parse: calling translation_unit...\n");
    }

    CompilationContext::GetInstance()->CodeDom = psr->translation_unit(psr);

    CompilationContext::GetInstance()->CurrentParser = NULL;

    if(CompilationContext::GetInstance()->Debug)
    {
        printf("Parse: cleanup\n");
    }

    psr     ->free(psr);
    psr     = NULL;
    tstream ->free(tstream);
    tstream = NULL;
    lxr     ->free(lxr);
    lxr     = NULL;
    input   ->close(input);
    input   = NULL;

    if(CompilationContext::GetInstance()->Debug)
    {
        printf("finished Parse\n");
    }

}

<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "PolycrystalVariablesAction.h"
#include "AddVariableAction.h"
#include "Conversion.h"
#include "Factory.h"
#include "FEProblem.h"

#include "libmesh/string_to_enum.h"

registerMooseAction("PhaseFieldApp", PolycrystalVariablesAction, "add_variable");

template <>
InputParameters
validParams<PolycrystalVariablesAction>()
{
  InputParameters params = validParams<Action>();
  params.addClassDescription("Set up order parameter variables for a polycrystal simulation");
  // Get MooseEnums for the possible order/family options for this variable
  MooseEnum families(AddVariableAction::getNonlinearVariableFamilies());
  MooseEnum orders(AddVariableAction::getNonlinearVariableOrders());
  params.addParam<MooseEnum>("family",
                             families,
                             "Specifies the family of FE "
                             "shape function to use for the order parameters");
  params.addParam<MooseEnum>("order",
                             orders,
                             "Specifies the order of the FE "
                             "shape function to use for the order parameters");
  params.addParam<Real>("scaling", 1.0, "Specifies a scaling factor to apply to this variable");
  params.addRequiredParam<unsigned int>("op_num",
                                        "specifies the number of order parameters to create");
  params.addRequiredParam<std::string>("var_name_base", "specifies the base name of the variables");
  return params;
}

PolycrystalVariablesAction::PolycrystalVariablesAction(const InputParameters & params)
  : Action(params),
    _op_num(getParam<unsigned int>("op_num")),
    _var_name_base(getParam<std::string>("var_name_base"))
{
}

void
PolycrystalVariablesAction::act()
{
  // Loop through the number of order parameters
  for (unsigned int op = 0; op < _op_num; op++)
  {
    // Create variable names
    std::string var_name = _var_name_base + Moose::stringify(op);

    // Add the variable
    _problem->addVariable(var_name,
                          FEType(Utility::string_to_enum<Order>(getParam<MooseEnum>("order")),
                                 Utility::string_to_enum<FEFamily>(getParam<MooseEnum>("family"))),
                          getParam<Real>("scaling"));
  }
}
<commit_msg>Add initial from file option (#12294)<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "PolycrystalVariablesAction.h"
#include "AddVariableAction.h"
#include "Conversion.h"
#include "Factory.h"
#include "FEProblem.h"
#include "NonlinearSystemBase.h"

#include "libmesh/string_to_enum.h"

registerMooseAction("PhaseFieldApp", PolycrystalVariablesAction, "add_variable");
registerMooseAction("PhaseFieldApp", PolycrystalVariablesAction, "copy_nodal_vars");
registerMooseAction("PhaseFieldApp", PolycrystalVariablesAction, "check_copy_nodal_vars");

template <>
InputParameters
validParams<PolycrystalVariablesAction>()
{
  InputParameters params = validParams<Action>();
  params.addClassDescription("Set up order parameter variables for a polycrystal simulation");
  // Get MooseEnums for the possible order/family options for this variable
  MooseEnum families(AddVariableAction::getNonlinearVariableFamilies());
  MooseEnum orders(AddVariableAction::getNonlinearVariableOrders());
  params.addParam<MooseEnum>("family",
                             families,
                             "Specifies the family of FE "
                             "shape function to use for the order parameters");
  params.addParam<MooseEnum>("order",
                             orders,
                             "Specifies the order of the FE "
                             "shape function to use for the order parameters");
  params.addParam<bool>(
      "initial_from_file",
      false,
      "Take the initial condition of all polycrystal variables from the mesh file");
  params.addParam<Real>("scaling", 1.0, "Specifies a scaling factor to apply to this variable");
  params.addRequiredParam<unsigned int>("op_num",
                                        "specifies the number of order parameters to create");
  params.addRequiredParam<std::string>("var_name_base", "specifies the base name of the variables");
  return params;
}

PolycrystalVariablesAction::PolycrystalVariablesAction(const InputParameters & params)
  : Action(params),
    _op_num(getParam<unsigned int>("op_num")),
    _var_name_base(getParam<std::string>("var_name_base"))
{
}

void
PolycrystalVariablesAction::act()
{
  // take initial values from file?
  bool initial_from_file = getParam<bool>("initial_from_file");

  // Loop through the number of order parameters
  for (unsigned int op = 0; op < _op_num; op++)
  {
    // Create variable names
    std::string var_name = _var_name_base + Moose::stringify(op);

    // Add the variable
    if (_current_task == "add_variable")
    {
      _problem->addVariable(
          var_name,
          FEType(Utility::string_to_enum<Order>(getParam<MooseEnum>("order")),
                 Utility::string_to_enum<FEFamily>(getParam<MooseEnum>("family"))),
          getParam<Real>("scaling"));
    }

    // Setup initial from file if requested
    if (initial_from_file)
    {
      if (_current_task == "check_copy_nodal_vars")
        _app.setFileRestart() = true;

      if (_current_task == "copy_nodal_vars")
      {
        auto * system = &_problem->getNonlinearSystemBase();
        system->addVariableToCopy(var_name, var_name, "LATEST");
      }
    }
  }
}
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed 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.
 *****************************************************************************/

/**
 * @file trajectory_stitcher.cc
 **/

#include "modules/planning/trajectory_stitcher/trajectory_stitcher.h"

#include <algorithm>

#include "modules/common/log.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/math/double.h"

namespace apollo {
namespace planning {

using VehicleState = apollo::common::VehicleState;

namespace {

std::vector<common::TrajectoryPoint> compute_reinit_stitching_trajectory() {
  common::TrajectoryPoint init_point;
  init_point.mutable_path_point()->set_x(VehicleState::instance()->x());
  init_point.mutable_path_point()->set_y(VehicleState::instance()->y());
  init_point.mutable_path_point()->set_z(VehicleState::instance()->z());
  init_point.mutable_path_point()->set_theta(
      VehicleState::instance()->heading());
  init_point.mutable_path_point()->set_kappa(VehicleState::instance()->kappa());

  init_point.set_v(VehicleState::instance()->linear_velocity());
  init_point.set_a(VehicleState::instance()->linear_acceleration());
  init_point.set_relative_time(0.0);

  DCHECK(!std::isnan(init_point.path_point().x()));
  DCHECK(!std::isnan(init_point.path_point().y()));
  DCHECK(!std::isnan(init_point.path_point().z()));
  DCHECK(!std::isnan(init_point.path_point().theta()));
  DCHECK(!std::isnan(init_point.path_point().kappa()));
  DCHECK(!std::isnan(init_point.v()));
  DCHECK(!std::isnan(init_point.a()));

  return std::vector<common::TrajectoryPoint>(1, init_point);
}
}

// Planning from current vehicle state:
// if 1. the auto-driving mode is off or
//    2. we don't have the trajectory from last planning cycle or
//    3. the position deviation from actual and target is too high
std::vector<common::TrajectoryPoint>
TrajectoryStitcher::ComputeStitchingTrajectory(
    const bool is_on_auto_mode, const double current_timestamp,
    const double planning_cycle_time,
    const PublishableTrajectory& prev_trajectory) {
  if (!is_on_auto_mode) {
    return compute_reinit_stitching_trajectory();
  }

  std::size_t prev_trajectory_size = prev_trajectory.NumOfPoints();

  if (prev_trajectory_size == 0) {
    AWARN << "Projected trajectory at time [" << prev_trajectory.header_time()
          << "] size is zero! Previous planning not exist or failed. Use "
             "origin car status instead.";
    return compute_reinit_stitching_trajectory();
  }

  const double veh_rel_time = current_timestamp - prev_trajectory.header_time();

  std::size_t matched_index = prev_trajectory.QueryNearestPoint(veh_rel_time);

  if (matched_index == prev_trajectory_size) {
    AWARN << "The previous trajectory is not long enough, something is wrong";
    return compute_reinit_stitching_trajectory();
  }

  if (matched_index == 0 &&
      veh_rel_time < prev_trajectory.StartPoint().relative_time()) {
    AWARN << "the previous trajectory doesn't cover current time";
    return compute_reinit_stitching_trajectory();
  }

  auto matched_point = prev_trajectory.TrajectoryPointAt(matched_index);
  const double position_diff =
      common::math::Vec2d(
          matched_point.path_point().x() - VehicleState::instance()->x(),
          matched_point.path_point().y() - VehicleState::instance()->y())
          .Length();

  if (position_diff > FLAGS_replan_distance_threshold) {
    AWARN << "the distance between matched point and actual position is too "
             "large";
    return compute_reinit_stitching_trajectory();
  }

  double forward_rel_time = veh_rel_time + planning_cycle_time;
  std::size_t forward_index =
      prev_trajectory.QueryNearestPoint(forward_rel_time);

  std::vector<common::TrajectoryPoint> stitching_trajectory(
      prev_trajectory.trajectory_points().begin() + matched_index,
      prev_trajectory.trajectory_points().begin() + forward_index + 1);

  double zero_time =
      prev_trajectory.TrajectoryPointAt(matched_index).relative_time();

  std::for_each(stitching_trajectory.begin(), stitching_trajectory.end(),
                [&zero_time](common::TrajectoryPoint& tp) {
                  tp.set_relative_time(tp.relative_time() - zero_time);
                });

  double zero_s =
      prev_trajectory.TrajectoryPointAt(forward_index).path_point().s();
  std::for_each(stitching_trajectory.begin(), stitching_trajectory.end(),
                [&zero_s](common::TrajectoryPoint& tp) {
                  double s = tp.path_point().s();
                  tp.mutable_path_point()->set_s(s - zero_s);
                });

  return stitching_trajectory;
}

}  // namespace planning
}  // namespace apollo
<commit_msg>planning: trajectory stitcher coding style fix.<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed 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.
 *****************************************************************************/

/**
 * @file trajectory_stitcher.cc
 **/

#include "modules/planning/trajectory_stitcher/trajectory_stitcher.h"

#include <algorithm>

#include "modules/common/log.h"
#include "modules/planning/common/planning_gflags.h"
#include "modules/planning/math/double.h"

namespace apollo {
namespace planning {

using VehicleState = apollo::common::VehicleState;

namespace {

std::vector<common::TrajectoryPoint> ComputeReinitStitchingTrajectory() {
  common::TrajectoryPoint init_point;
  init_point.mutable_path_point()->set_x(VehicleState::instance()->x());
  init_point.mutable_path_point()->set_y(VehicleState::instance()->y());
  init_point.mutable_path_point()->set_z(VehicleState::instance()->z());
  init_point.mutable_path_point()->set_theta(
      VehicleState::instance()->heading());
  init_point.mutable_path_point()->set_kappa(VehicleState::instance()->kappa());

  init_point.set_v(VehicleState::instance()->linear_velocity());
  init_point.set_a(VehicleState::instance()->linear_acceleration());
  init_point.set_relative_time(0.0);

  DCHECK(!std::isnan(init_point.path_point().x()));
  DCHECK(!std::isnan(init_point.path_point().y()));
  DCHECK(!std::isnan(init_point.path_point().z()));
  DCHECK(!std::isnan(init_point.path_point().theta()));
  DCHECK(!std::isnan(init_point.path_point().kappa()));
  DCHECK(!std::isnan(init_point.v()));
  DCHECK(!std::isnan(init_point.a()));

  return std::vector<common::TrajectoryPoint>(1, init_point);
}
}

// Planning from current vehicle state:
// if 1. the auto-driving mode is off or
//    2. we don't have the trajectory from last planning cycle or
//    3. the position deviation from actual and target is too high
std::vector<common::TrajectoryPoint>
TrajectoryStitcher::ComputeStitchingTrajectory(
    const bool is_on_auto_mode, const double current_timestamp,
    const double planning_cycle_time,
    const PublishableTrajectory& prev_trajectory) {
  if (!is_on_auto_mode) {
    return ComputeReinitStitchingTrajectory();
  }

  std::size_t prev_trajectory_size = prev_trajectory.NumOfPoints();

  if (prev_trajectory_size == 0) {
    AWARN << "Projected trajectory at time [" << prev_trajectory.header_time()
          << "] size is zero! Previous planning not exist or failed. Use "
             "origin car status instead.";
    return ComputeReinitStitchingTrajectory();
  }

  const double veh_rel_time = current_timestamp - prev_trajectory.header_time();

  std::size_t matched_index = prev_trajectory.QueryNearestPoint(veh_rel_time);

  if (matched_index == prev_trajectory_size) {
    AWARN << "The previous trajectory is not long enough, something is wrong";
    return ComputeReinitStitchingTrajectory();
  }

  if (matched_index == 0 &&
      veh_rel_time < prev_trajectory.StartPoint().relative_time()) {
    AWARN << "the previous trajectory doesn't cover current time";
    return ComputeReinitStitchingTrajectory();
  }

  auto matched_point = prev_trajectory.TrajectoryPointAt(matched_index);
  const double position_diff =
      common::math::Vec2d(
          matched_point.path_point().x() - VehicleState::instance()->x(),
          matched_point.path_point().y() - VehicleState::instance()->y())
          .Length();

  if (position_diff > FLAGS_replan_distance_threshold) {
    AWARN << "the distance between matched point and actual position is too "
             "large";
    return ComputeReinitStitchingTrajectory();
  }

  double forward_rel_time = veh_rel_time + planning_cycle_time;
  std::size_t forward_index =
      prev_trajectory.QueryNearestPoint(forward_rel_time);

  std::vector<common::TrajectoryPoint> stitching_trajectory(
      prev_trajectory.trajectory_points().begin() + matched_index,
      prev_trajectory.trajectory_points().begin() + forward_index + 1);

  double zero_time =
      prev_trajectory.TrajectoryPointAt(matched_index).relative_time();

  std::for_each(stitching_trajectory.begin(), stitching_trajectory.end(),
                [&zero_time](common::TrajectoryPoint& tp) {
                  tp.set_relative_time(tp.relative_time() - zero_time);
                });

  double zero_s =
      prev_trajectory.TrajectoryPointAt(forward_index).path_point().s();
  std::for_each(stitching_trajectory.begin(), stitching_trajectory.end(),
                [&zero_s](common::TrajectoryPoint& tp) {
                  double s = tp.path_point().s();
                  tp.mutable_path_point()->set_s(s - zero_s);
                });

  return stitching_trajectory;
}

}  // namespace planning
}  // namespace apollo
<|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed 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 "modules/prediction/predictor/sequence/sequence_predictor.h"

#include <cmath>
#include <limits>
#include <memory>
#include <utility>

#include "modules/common/adapters/proto/adapter_config.pb.h"

#include "modules/common/math/vec2d.h"
#include "modules/prediction/common/prediction_gflags.h"
#include "modules/prediction/common/prediction_map.h"
#include "modules/prediction/common/road_graph.h"
#include "modules/prediction/container/adc_trajectory/adc_trajectory_container.h"
#include "modules/prediction/container/container_manager.h"
#include "modules/prediction/container/pose/pose_container.h"

namespace apollo {
namespace prediction {

using ::apollo::common::PathPoint;
using ::apollo::common::TrajectoryPoint;
using ::apollo::common::adapter::AdapterConfig;
using ::apollo::common::math::Vec2d;
using ::apollo::hdmap::LaneInfo;

void SequencePredictor::Predict(Obstacle* obstacle) {
  Clear();

  CHECK_NOTNULL(obstacle);
  CHECK_GT(obstacle->history_size(), 0);
}

void SequencePredictor::Clear() { Predictor::Clear(); }

std::string SequencePredictor::ToString(const LaneSequence& sequence) {
  std::string str_lane_sequence = "";
  if (sequence.lane_segment_size() > 0) {
    str_lane_sequence += sequence.lane_segment(0).lane_id();
  }
  for (int i = 1; i < sequence.lane_segment_size(); ++i) {
    str_lane_sequence += ("->" + sequence.lane_segment(i).lane_id());
  }
  return str_lane_sequence;
}

void SequencePredictor::FilterLaneSequences(
    const LaneGraph& lane_graph, const std::string& lane_id,
    std::vector<bool>* enable_lane_sequence) {
  int num_lane_sequence = lane_graph.lane_sequence_size();
  std::vector<LaneChangeType> lane_change_type(num_lane_sequence,
                                               LaneChangeType::INVALID);
  std::pair<int, double> change(-1, -1.0);
  std::pair<int, double> all(-1, -1.0);

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);
    lane_change_type[i] = GetLaneChangeType(lane_id, sequence);

    if (lane_change_type[i] != LaneChangeType::LEFT &&
        lane_change_type[i] != LaneChangeType::RIGHT &&
        lane_change_type[i] != LaneChangeType::ONTO_LANE) {
      ADEBUG "Ignore lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    // The obstacle has interference with ADC within a small distance
    double distance = GetLaneChangeDistanceWithADC(sequence);
    ADEBUG << "Distance to ADC " << std::fixed << std::setprecision(6)
           << distance;
    if (distance < FLAGS_lane_change_dist) {
      (*enable_lane_sequence)[i] = false;
      ADEBUG << "Filter trajectory [" << ToString(sequence)
             << "] due to small distance " << distance << ".";
    }
  }

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);

    if (!(*enable_lane_sequence)[i]) {
      ADEBUG << "Disabled lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    double probability = sequence.probability();
    if (LaneSequenceWithMaxProb(lane_change_type[i], probability, all.second)) {
      all.first = i;
      all.second = probability;
    }
    if (LaneChangeWithMaxProb(lane_change_type[i], probability,
                              change.second)) {
      change.first = i;
      change.second = probability;
    }
  }

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);

    if (!(*enable_lane_sequence)[i]) {
      ADEBUG << "Disabled lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    double probability = sequence.probability();
    if (probability < FLAGS_lane_sequence_threshold && i != all.first) {
      (*enable_lane_sequence)[i] = false;
    } else if (change.first >= 0 && change.first < num_lane_sequence &&
               (lane_change_type[i] == LaneChangeType::LEFT ||
                lane_change_type[i] == LaneChangeType::RIGHT) &&
               lane_change_type[i] != lane_change_type[change.first]) {
      (*enable_lane_sequence)[i] = false;
    }
  }
}

SequencePredictor::LaneChangeType SequencePredictor::GetLaneChangeType(
    const std::string& lane_id, const LaneSequence& lane_sequence) {
  PredictionMap* map = PredictionMap::instance();

  if (lane_id.empty()) {
    return LaneChangeType::ONTO_LANE;
  }

  std::string lane_change_id = lane_sequence.lane_segment(0).lane_id();
  if (lane_id == lane_change_id) {
    return LaneChangeType::STRAIGHT;
  } else {
    if (map->IsLeftNeighborLane(map->LaneById(lane_change_id),
                                map->LaneById(lane_id))) {
      return LaneChangeType::LEFT;
    } else if (map->IsRightNeighborLane(map->LaneById(lane_change_id),
                                        map->LaneById(lane_id))) {
      return LaneChangeType::RIGHT;
    }
  }
  return LaneChangeType::INVALID;
}

double SequencePredictor::GetLaneChangeDistanceWithADC(
    const LaneSequence& lane_sequence) {
  PoseContainer* pose_container = dynamic_cast<PoseContainer*>(
      ContainerManager::instance()->GetContainer(AdapterConfig::LOCALIZATION));
  ADCTrajectoryContainer* adc_container = dynamic_cast<ADCTrajectoryContainer*>(
      ContainerManager::instance()->GetContainer(
          AdapterConfig::PLANNING_TRAJECTORY));
  CHECK_NOTNULL(pose_container);
  CHECK_NOTNULL(adc_container);

  Eigen::Vector2d adc_position;
  if (pose_container->ToPerceptionObstacle() != nullptr) {
    adc_position[0] = pose_container->ToPerceptionObstacle()->position().x();
    adc_position[1] = pose_container->ToPerceptionObstacle()->position().y();

    PredictionMap* map = PredictionMap::instance();
    std::string obstacle_lane_id = lane_sequence.lane_segment(0).lane_id();
    double obstacle_lane_s = lane_sequence.lane_segment(0).start_s();
    double lane_s = 0.0;
    double lane_l = 0.0;
    ADEBUG << "Obstacle lane " << obstacle_lane_id << " and s "
           << obstacle_lane_s;
    if (map->GetProjection(adc_position, map->LaneById(obstacle_lane_id),
                           &lane_s, &lane_l)) {
      ADEBUG << "ADC on lane s " << lane_s;
      return std::fabs(lane_s - obstacle_lane_s);
    }
  }
  return std::numeric_limits<double>::max();
}

bool SequencePredictor::LaneSequenceWithMaxProb(const LaneChangeType& type,
                                                const double& probability,
                                                const double& max_prob) {
  if (probability > max_prob) {
    return true;
  } else {
    double prob_diff = std::abs(probability - max_prob);
    if (prob_diff <= std::numeric_limits<double>::epsilon() &&
        type == LaneChangeType::STRAIGHT) {
      return true;
    }
  }
  return false;
}

bool SequencePredictor::LaneChangeWithMaxProb(const LaneChangeType& type,
                                              const double& probability,
                                              const double& max_prob) {
  if (type == LaneChangeType::LEFT || type == LaneChangeType::RIGHT) {
    if (probability > max_prob) {
      return true;
    }
  }
  return false;
}

}  // namespace prediction
}  // namespace apollo
<commit_msg>Prediction: fix adc trajectory overlap<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed 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 "modules/prediction/predictor/sequence/sequence_predictor.h"

#include <cmath>
#include <limits>
#include <memory>
#include <utility>

#include "modules/common/adapters/proto/adapter_config.pb.h"

#include "modules/common/math/vec2d.h"
#include "modules/prediction/common/prediction_gflags.h"
#include "modules/prediction/common/prediction_map.h"
#include "modules/prediction/common/road_graph.h"
#include "modules/prediction/container/adc_trajectory/adc_trajectory_container.h"
#include "modules/prediction/container/container_manager.h"
#include "modules/prediction/container/pose/pose_container.h"

namespace apollo {
namespace prediction {

using ::apollo::common::PathPoint;
using ::apollo::common::TrajectoryPoint;
using ::apollo::common::adapter::AdapterConfig;
using ::apollo::common::math::Vec2d;
using ::apollo::hdmap::LaneInfo;

void SequencePredictor::Predict(Obstacle* obstacle) {
  Clear();

  CHECK_NOTNULL(obstacle);
  CHECK_GT(obstacle->history_size(), 0);
}

void SequencePredictor::Clear() { Predictor::Clear(); }

std::string SequencePredictor::ToString(const LaneSequence& sequence) {
  std::string str_lane_sequence = "";
  if (sequence.lane_segment_size() > 0) {
    str_lane_sequence += sequence.lane_segment(0).lane_id();
  }
  for (int i = 1; i < sequence.lane_segment_size(); ++i) {
    str_lane_sequence += ("->" + sequence.lane_segment(i).lane_id());
  }
  return str_lane_sequence;
}

void SequencePredictor::FilterLaneSequences(
    const LaneGraph& lane_graph, const std::string& lane_id,
    std::vector<bool>* enable_lane_sequence) {
  int num_lane_sequence = lane_graph.lane_sequence_size();
  std::vector<LaneChangeType> lane_change_type(num_lane_sequence,
                                               LaneChangeType::INVALID);
  std::pair<int, double> change(-1, -1.0);
  std::pair<int, double> all(-1, -1.0);

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);
    lane_change_type[i] = GetLaneChangeType(lane_id, sequence);

    if (lane_change_type[i] != LaneChangeType::LEFT &&
        lane_change_type[i] != LaneChangeType::RIGHT &&
        lane_change_type[i] != LaneChangeType::ONTO_LANE) {
      ADEBUG "Ignore lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    // The obstacle has interference with ADC within a small distance
    double distance = GetLaneChangeDistanceWithADC(sequence);
    ADEBUG << "Distance to ADC " << std::fixed << std::setprecision(6)
           << distance;
    if (distance < FLAGS_lane_change_dist) {
      (*enable_lane_sequence)[i] = false;
      ADEBUG << "Filter trajectory [" << ToString(sequence)
             << "] due to small distance " << distance << ".";
    }
  }

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);

    if (!(*enable_lane_sequence)[i]) {
      ADEBUG << "Disabled lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    double probability = sequence.probability();
    if (LaneSequenceWithMaxProb(lane_change_type[i], probability, all.second)) {
      all.first = i;
      all.second = probability;
    }
    if (LaneChangeWithMaxProb(lane_change_type[i], probability,
                              change.second)) {
      change.first = i;
      change.second = probability;
    }
  }

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);

    if (!(*enable_lane_sequence)[i]) {
      ADEBUG << "Disabled lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    double probability = sequence.probability();
    if (probability < FLAGS_lane_sequence_threshold && i != all.first) {
      (*enable_lane_sequence)[i] = false;
    } else if (change.first >= 0 && change.first < num_lane_sequence &&
               (lane_change_type[i] == LaneChangeType::LEFT ||
                lane_change_type[i] == LaneChangeType::RIGHT) &&
               lane_change_type[i] != lane_change_type[change.first]) {
      (*enable_lane_sequence)[i] = false;
    }
  }
}

SequencePredictor::LaneChangeType SequencePredictor::GetLaneChangeType(
    const std::string& lane_id, const LaneSequence& lane_sequence) {
  PredictionMap* map = PredictionMap::instance();

  if (lane_id.empty()) {
    return LaneChangeType::ONTO_LANE;
  }

  std::string lane_change_id = lane_sequence.lane_segment(0).lane_id();
  if (lane_id == lane_change_id) {
    return LaneChangeType::STRAIGHT;
  } else {
    if (map->IsLeftNeighborLane(map->LaneById(lane_change_id),
                                map->LaneById(lane_id))) {
      return LaneChangeType::LEFT;
    } else if (map->IsRightNeighborLane(map->LaneById(lane_change_id),
                                        map->LaneById(lane_id))) {
      return LaneChangeType::RIGHT;
    }
  }
  return LaneChangeType::INVALID;
}

double SequencePredictor::GetLaneChangeDistanceWithADC(
    const LaneSequence& lane_sequence) {
  PoseContainer* pose_container = dynamic_cast<PoseContainer*>(
      ContainerManager::instance()->GetContainer(AdapterConfig::LOCALIZATION));
  ADCTrajectoryContainer* adc_container = dynamic_cast<ADCTrajectoryContainer*>(
      ContainerManager::instance()->GetContainer(
          AdapterConfig::PLANNING_TRAJECTORY));
  CHECK_NOTNULL(pose_container);
  CHECK_NOTNULL(adc_container);

  if (!adc_container->HasOverlap(lane_sequence)) {
    return std::numeric_limits<double>::max();
  }

  Eigen::Vector2d adc_position;
  if (pose_container->ToPerceptionObstacle() != nullptr) {
    adc_position[0] = pose_container->ToPerceptionObstacle()->position().x();
    adc_position[1] = pose_container->ToPerceptionObstacle()->position().y();

    PredictionMap* map = PredictionMap::instance();
    std::string obstacle_lane_id = lane_sequence.lane_segment(0).lane_id();
    double obstacle_lane_s = lane_sequence.lane_segment(0).start_s();
    double lane_s = 0.0;
    double lane_l = 0.0;
    ADEBUG << "Obstacle lane " << obstacle_lane_id << " and s "
           << obstacle_lane_s;
    if (map->GetProjection(adc_position, map->LaneById(obstacle_lane_id),
                           &lane_s, &lane_l)) {
      ADEBUG << "ADC on lane s " << lane_s;
      return std::fabs(lane_s - obstacle_lane_s);
    }
  }
  return std::numeric_limits<double>::max();
}

bool SequencePredictor::LaneSequenceWithMaxProb(const LaneChangeType& type,
                                                const double& probability,
                                                const double& max_prob) {
  if (probability > max_prob) {
    return true;
  } else {
    double prob_diff = std::abs(probability - max_prob);
    if (prob_diff <= std::numeric_limits<double>::epsilon() &&
        type == LaneChangeType::STRAIGHT) {
      return true;
    }
  }
  return false;
}

bool SequencePredictor::LaneChangeWithMaxProb(const LaneChangeType& type,
                                              const double& probability,
                                              const double& max_prob) {
  if (type == LaneChangeType::LEFT || type == LaneChangeType::RIGHT) {
    if (probability > max_prob) {
      return true;
    }
  }
  return false;
}

}  // namespace prediction
}  // namespace apollo
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 The WebRTC 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 in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "video_x11_channel.h"

#include "critical_section_wrapper.h"
#include "trace.h"

namespace webrtc {

#define DISP_MAX 128

static Display *dispArray[DISP_MAX];
static int dispCount = 0;

VideoX11Channel::VideoX11Channel(WebRtc_Word32 id) :
    _crit(*CriticalSectionWrapper::CreateCriticalSection()),
            _videoInterpolator(NULL), _display(NULL), _xvport(), _shminfo(),
            _image(NULL), _window(NULL), _width(DEFAULT_RENDER_FRAME_WIDTH),
            _height(DEFAULT_RENDER_FRAME_HEIGHT), _outWidth(0), _outHeight(0),
            _xPos(0), _yPos(0), _prepared(false), _dispCount(0), _buffer(NULL),
            _Id(id)
{
}

VideoX11Channel::~VideoX11Channel()
{
    if (_prepared)
    {
        _crit.Enter();
        RemoveRenderer();
        _crit.Leave();
    }
    delete &_crit;

    if (_videoInterpolator)
    {
        delete _videoInterpolator;
    }
}

WebRtc_Word32 VideoX11Channel::RenderFrame(const WebRtc_UWord32 streamId,
                                               VideoFrame& videoFrame)
{
    CriticalSectionScoped cs(_crit);
    if (_width != (WebRtc_Word32) videoFrame.Width() || _height
            != (WebRtc_Word32) videoFrame.Height())
    {
        if (FrameSizeChange(videoFrame.Width(), videoFrame.Height(), 1) == -1)
        {
            return -1;
        }
    }
    return DeliverFrame(videoFrame.Buffer(), videoFrame.Length(),
                        videoFrame.TimeStamp());
}

WebRtc_Word32 VideoX11Channel::FrameSizeChange(WebRtc_Word32 width,
                                                   WebRtc_Word32 height,
                                                   WebRtc_Word32 /*numberOfStreams */)
{
    CriticalSectionScoped cs(_crit);
    if (_prepared)
    {
        RemoveRenderer();
    }

    if (CreateLocalRenderer(width, height) == -1)
    {
        return -1;
    }

    return 0;
}

WebRtc_Word32 VideoX11Channel::DeliverFrame(unsigned char* buffer,
                                                WebRtc_Word32 bufferSize,
                                                unsigned WebRtc_Word32 /*timeStamp90kHz*/)
{
    CriticalSectionScoped cs(_crit);
    if (!_prepared)
    {
        return 0;
    }

    if (!dispArray[_dispCount])
    {
        return -1;
    }

    unsigned char *pBuf = buffer;
    // convert to RGB32
    ConvertI420ToARGB(pBuf, _buffer, _width, _height, 0);

    // put image in window
    XShmPutImage(_display, _window, _gc, _image, 0, 0, _xPos, _yPos, _width,
                 _height, True);

    // very important for the image to update properly!
    XSync(_display, false);

    return 0;

}

WebRtc_Word32 VideoX11Channel::GetFrameSize(WebRtc_Word32& width,
                                                WebRtc_Word32& height)
{
    width = _width;
    height = _height;

    return 0;
}

WebRtc_Word32 VideoX11Channel::Init(Window window, float left, float top,
                                        float right, float bottom)
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);
    CriticalSectionScoped cs(_crit);

    _window = window;
    _left = left;
    _right = _right;
    _top = top;
    _bottom = _bottom;

    _display = XOpenDisplay(NULL); // Use default display
    if (!_window || !_display)
    {
        return -1;
    }

    if (dispCount < DISP_MAX)
    {
        dispArray[dispCount] = _display;
        _dispCount = dispCount;
        dispCount++;
    }
    else
    {
        return -1;
    }

    if ((1 < left || left < 0) || (1 < top || top < 0) || (1 < right || right
            < 0) || (1 < bottom || bottom < 0))
    {
        return -1;
    }

    // calculate position and size of rendered video
    int x, y;
    unsigned int winWidth, winHeight, borderwidth, depth;
    Window rootret;
    if (XGetGeometry(_display, _window, &rootret, &x, &y, &winWidth,
                     &winHeight, &borderwidth, &depth) == 0)
    {
        return -1;
    }

    _xPos = (WebRtc_Word32) (winWidth * left);
    _yPos = (WebRtc_Word32) (winHeight * top);
    _outWidth = (WebRtc_Word32) (winWidth * (right - left));
    _outHeight = (WebRtc_Word32) (winHeight * (bottom - top));
    if (_outWidth % 2)
        _outWidth++; // the renderer want's sizes that are multiples of two
    if (_outHeight % 2)
        _outHeight++;

    if (CreateLocalRenderer(winWidth, winHeight) == -1)
    {
        return -1;
    }
    return 0;

}

WebRtc_Word32 VideoX11Channel::ChangeWindow(Window window)
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);
    CriticalSectionScoped cs(_crit);

    // Stop the rendering, if we are rendering...
    RemoveRenderer();
    _window = window;

    // calculate position and size of rendered video
    int x, y;
    unsigned int winWidth, winHeight, borderwidth, depth;
    Window rootret;
    if (XGetGeometry(_display, _window, &rootret, &x, &y, &winWidth,
                     &winHeight, &borderwidth, &depth) == -1)
    {
        return -1;
    }
    _xPos = (int) (winWidth * _left);
    _yPos = (int) (winHeight * _top);
    _outWidth = (int) (winWidth * (_right - _left));
    _outHeight = (int) (winHeight * (_bottom - _top));
    if (_outWidth % 2)
        _outWidth++; // the renderer want's sizes that are multiples of two
    if (_outHeight % 2)
        _outHeight++;

    // Prepare rendering using the
    if (CreateLocalRenderer(_width, _height) == -1)
    {
        return -1;
    }
    return 0;
}

WebRtc_Word32 VideoX11Channel::ReleaseWindow()
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);
    CriticalSectionScoped cs(_crit);

    RemoveRenderer();
    if (_display)
    {
        XCloseDisplay(_display);
        _display = NULL;
    }
    return 0;
}

WebRtc_Word32 VideoX11Channel::CreateLocalRenderer(WebRtc_Word32 width,
                                                       WebRtc_Word32 height)
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);
    CriticalSectionScoped cs(_crit);

    if (!_window || !_display)
    {
        return -1;
    }

    if (_prepared)
    {
        WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _Id,
                     "Renderer already prepared, exits.");
        return -1;
    }

    _width = width;
    _height = height;

    // create a graphics context in the window
    _gc = XCreateGC(_display, _window, 0, 0);

    // create shared memory image
    _image = XShmCreateImage(_display, CopyFromParent, 24, ZPixmap, NULL,
                             &_shminfo, _width, _height); // this parameter needs to be the same for some reason.
    _shminfo.shmid = shmget(IPC_PRIVATE, (_image->bytes_per_line
            * _image->height), IPC_CREAT | 0777);
    _shminfo.shmaddr = _image->data = (char*) shmat(_shminfo.shmid, 0, 0);
    _buffer = (unsigned char*) _image->data;
    _shminfo.readOnly = False;

    // attach image to display
    if (!XShmAttach(_display, &_shminfo))
    {
        //printf("XShmAttach failed !\n");
        return -1;
    }

    _prepared = true;
    return 0;
}

WebRtc_Word32 VideoX11Channel::RemoveRenderer()
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);

    if (!_prepared)
    {
        return 0;
    }
    _prepared = false;

    // free and closse Xwindow and XShm
    XShmDetach(_display, &_shminfo);
    XDestroyImage( _image );
    shmdt(_shminfo.shmaddr);
    XFreeGC(_display, _gc);

    return 0;
}

WebRtc_Word32 VideoX11Channel::GetStreamProperties(WebRtc_UWord32& zOrder,
                                                       float& left, float& top,
                                                       float& right,
                                                       float& bottom) const
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);

    zOrder = 0; // no z-order support yet
    left = _left;
    top = _top;
    right = _right;
    bottom = _bottom;

    return 0;
}

} //namespace webrtc

<commit_msg>Fix Issue 59. Fix a constructor cast warning in video_X11_channel.cc. http://code.google.com/p/webrtc/issues/detail?id=59. Review URL: http://webrtc-codereview.appspot.com/122002<commit_after>/*
 *  Copyright (c) 2011 The WebRTC 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 in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "video_x11_channel.h"

#include "critical_section_wrapper.h"
#include "trace.h"

namespace webrtc {

#define DISP_MAX 128

static Display *dispArray[DISP_MAX];
static int dispCount = 0;

VideoX11Channel::VideoX11Channel(WebRtc_Word32 id) :
    _crit(*CriticalSectionWrapper::CreateCriticalSection()),
            _videoInterpolator(NULL), _display(NULL), _xvport(), _shminfo(),
            _image(NULL), _window(0L), _width(DEFAULT_RENDER_FRAME_WIDTH),
            _height(DEFAULT_RENDER_FRAME_HEIGHT), _outWidth(0), _outHeight(0),
            _xPos(0), _yPos(0), _prepared(false), _dispCount(0), _buffer(NULL),
            _Id(id)
{
}

VideoX11Channel::~VideoX11Channel()
{
    if (_prepared)
    {
        _crit.Enter();
        RemoveRenderer();
        _crit.Leave();
    }
    delete &_crit;

    if (_videoInterpolator)
    {
        delete _videoInterpolator;
    }
}

WebRtc_Word32 VideoX11Channel::RenderFrame(const WebRtc_UWord32 streamId,
                                               VideoFrame& videoFrame)
{
    CriticalSectionScoped cs(_crit);
    if (_width != (WebRtc_Word32) videoFrame.Width() || _height
            != (WebRtc_Word32) videoFrame.Height())
    {
        if (FrameSizeChange(videoFrame.Width(), videoFrame.Height(), 1) == -1)
        {
            return -1;
        }
    }
    return DeliverFrame(videoFrame.Buffer(), videoFrame.Length(),
                        videoFrame.TimeStamp());
}

WebRtc_Word32 VideoX11Channel::FrameSizeChange(WebRtc_Word32 width,
                                                   WebRtc_Word32 height,
                                                   WebRtc_Word32 /*numberOfStreams */)
{
    CriticalSectionScoped cs(_crit);
    if (_prepared)
    {
        RemoveRenderer();
    }

    if (CreateLocalRenderer(width, height) == -1)
    {
        return -1;
    }

    return 0;
}

WebRtc_Word32 VideoX11Channel::DeliverFrame(unsigned char* buffer,
                                                WebRtc_Word32 bufferSize,
                                                unsigned WebRtc_Word32 /*timeStamp90kHz*/)
{
    CriticalSectionScoped cs(_crit);
    if (!_prepared)
    {
        return 0;
    }

    if (!dispArray[_dispCount])
    {
        return -1;
    }

    unsigned char *pBuf = buffer;
    // convert to RGB32
    ConvertI420ToARGB(pBuf, _buffer, _width, _height, 0);

    // put image in window
    XShmPutImage(_display, _window, _gc, _image, 0, 0, _xPos, _yPos, _width,
                 _height, True);

    // very important for the image to update properly!
    XSync(_display, false);

    return 0;

}

WebRtc_Word32 VideoX11Channel::GetFrameSize(WebRtc_Word32& width,
                                                WebRtc_Word32& height)
{
    width = _width;
    height = _height;

    return 0;
}

WebRtc_Word32 VideoX11Channel::Init(Window window, float left, float top,
                                        float right, float bottom)
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);
    CriticalSectionScoped cs(_crit);

    _window = window;
    _left = left;
    _right = _right;
    _top = top;
    _bottom = _bottom;

    _display = XOpenDisplay(NULL); // Use default display
    if (!_window || !_display)
    {
        return -1;
    }

    if (dispCount < DISP_MAX)
    {
        dispArray[dispCount] = _display;
        _dispCount = dispCount;
        dispCount++;
    }
    else
    {
        return -1;
    }

    if ((1 < left || left < 0) || (1 < top || top < 0) || (1 < right || right
            < 0) || (1 < bottom || bottom < 0))
    {
        return -1;
    }

    // calculate position and size of rendered video
    int x, y;
    unsigned int winWidth, winHeight, borderwidth, depth;
    Window rootret;
    if (XGetGeometry(_display, _window, &rootret, &x, &y, &winWidth,
                     &winHeight, &borderwidth, &depth) == 0)
    {
        return -1;
    }

    _xPos = (WebRtc_Word32) (winWidth * left);
    _yPos = (WebRtc_Word32) (winHeight * top);
    _outWidth = (WebRtc_Word32) (winWidth * (right - left));
    _outHeight = (WebRtc_Word32) (winHeight * (bottom - top));
    if (_outWidth % 2)
        _outWidth++; // the renderer want's sizes that are multiples of two
    if (_outHeight % 2)
        _outHeight++;

    if (CreateLocalRenderer(winWidth, winHeight) == -1)
    {
        return -1;
    }
    return 0;

}

WebRtc_Word32 VideoX11Channel::ChangeWindow(Window window)
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);
    CriticalSectionScoped cs(_crit);

    // Stop the rendering, if we are rendering...
    RemoveRenderer();
    _window = window;

    // calculate position and size of rendered video
    int x, y;
    unsigned int winWidth, winHeight, borderwidth, depth;
    Window rootret;
    if (XGetGeometry(_display, _window, &rootret, &x, &y, &winWidth,
                     &winHeight, &borderwidth, &depth) == -1)
    {
        return -1;
    }
    _xPos = (int) (winWidth * _left);
    _yPos = (int) (winHeight * _top);
    _outWidth = (int) (winWidth * (_right - _left));
    _outHeight = (int) (winHeight * (_bottom - _top));
    if (_outWidth % 2)
        _outWidth++; // the renderer want's sizes that are multiples of two
    if (_outHeight % 2)
        _outHeight++;

    // Prepare rendering using the
    if (CreateLocalRenderer(_width, _height) == -1)
    {
        return -1;
    }
    return 0;
}

WebRtc_Word32 VideoX11Channel::ReleaseWindow()
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);
    CriticalSectionScoped cs(_crit);

    RemoveRenderer();
    if (_display)
    {
        XCloseDisplay(_display);
        _display = NULL;
    }
    return 0;
}

WebRtc_Word32 VideoX11Channel::CreateLocalRenderer(WebRtc_Word32 width,
                                                       WebRtc_Word32 height)
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);
    CriticalSectionScoped cs(_crit);

    if (!_window || !_display)
    {
        return -1;
    }

    if (_prepared)
    {
        WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _Id,
                     "Renderer already prepared, exits.");
        return -1;
    }

    _width = width;
    _height = height;

    // create a graphics context in the window
    _gc = XCreateGC(_display, _window, 0, 0);

    // create shared memory image
    _image = XShmCreateImage(_display, CopyFromParent, 24, ZPixmap, NULL,
                             &_shminfo, _width, _height); // this parameter needs to be the same for some reason.
    _shminfo.shmid = shmget(IPC_PRIVATE, (_image->bytes_per_line
            * _image->height), IPC_CREAT | 0777);
    _shminfo.shmaddr = _image->data = (char*) shmat(_shminfo.shmid, 0, 0);
    _buffer = (unsigned char*) _image->data;
    _shminfo.readOnly = False;

    // attach image to display
    if (!XShmAttach(_display, &_shminfo))
    {
        //printf("XShmAttach failed !\n");
        return -1;
    }

    _prepared = true;
    return 0;
}

WebRtc_Word32 VideoX11Channel::RemoveRenderer()
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);

    if (!_prepared)
    {
        return 0;
    }
    _prepared = false;

    // free and closse Xwindow and XShm
    XShmDetach(_display, &_shminfo);
    XDestroyImage( _image );
    shmdt(_shminfo.shmaddr);
    XFreeGC(_display, _gc);

    return 0;
}

WebRtc_Word32 VideoX11Channel::GetStreamProperties(WebRtc_UWord32& zOrder,
                                                       float& left, float& top,
                                                       float& right,
                                                       float& bottom) const
{
    WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, _Id, "%s",
                 __FUNCTION__);

    zOrder = 0; // no z-order support yet
    left = _left;
    top = _top;
    right = _right;
    bottom = _bottom;

    return 0;
}

} //namespace webrtc

<|endoftext|>


<commit_before>/*
 * Copyright 2013 Google Inc.
 *
 * Licensed 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.
 */

// Author: morlovich@google.com (Maksim Orlovich)
// Unit tests for GoogleFontCssInlineFilter

#include "net/instaweb/http/public/ua_sensitive_test_fetcher.h"
#include "net/instaweb/rewriter/public/domain_lawyer.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/rewrite_test_base.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_message_handler.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/http/content_type.h"
#include "pagespeed/kernel/http/response_headers.h"

namespace net_instaweb {

namespace {

const char kRoboto[] = "http://fonts.googleapis.com/css?family=Roboto";

class GoogleFontCssInlineFilterTestBase : public RewriteTestBase {
 protected:
  virtual void SetUp() {
    RewriteTestBase::SetUp();
  }

  void SetUpForFontFilterTest(RewriteOptions::Filter filter_to_enable) {
    AddFilter(filter_to_enable);

    // We want to enable debug after AddFilters, since we don't want the
    // standard debug filter output, just that from the font filter.
    options()->ClearSignatureForTesting();
    options()->EnableFilter(RewriteOptions::kDebug);
    server_context()->ComputeSignature(options());

    rewrite_driver()->SetSessionFetcher(
        new UserAgentSensitiveTestFetcher(rewrite_driver()->async_fetcher()));

    // Font loader CSS gets Cache-Control:private, max-age=86400
    ResponseHeaders response_headers;
    SetDefaultLongCacheHeaders(&kContentTypeCss, &response_headers);
    response_headers.SetDateAndCaching(
        timer()->NowMs(), 86400 * Timer::kSecondMs, ", private");

    // Now upload some UA-specific CSS where UaSensitiveFetcher will find it,
    // for two fake UAs: Chromezilla and Safieri, used since they are short,
    // unlike real UA strings.
    SetFetchResponse(StrCat(kRoboto, "&UA=Chromezilla"),
                     response_headers, "font_chromezilla");

    SetFetchResponse(StrCat(kRoboto, "&UA=Safieri"),
                     response_headers, "font_safieri");
  }
};

class GoogleFontCssInlineFilterTest : public GoogleFontCssInlineFilterTestBase {
 protected:
  virtual void SetUp() {
    GoogleFontCssInlineFilterTestBase::SetUp();
    SetUpForFontFilterTest(RewriteOptions::kInlineGoogleFontCss);
  }
};

TEST_F(GoogleFontCssInlineFilterTest, BasicOperation) {
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected("simple",
                   CssLinkHref(kRoboto),
                   "<style>font_chromezilla</style>");

  // Different UAs get different cache entries
  rewrite_driver()->SetUserAgent("Safieri");
  ValidateExpected("simple2",
                   CssLinkHref(kRoboto),
                   "<style>font_safieri</style>");
}

TEST_F(GoogleFontCssInlineFilterTest, UsageRestrictions) {
  rewrite_driver()->SetUserAgent("Chromezilla");

  options()->ClearSignatureForTesting();
  options()->set_modify_caching_headers(false);
  server_context()->ComputeSignature(options());
  ValidateExpected("incompat1",
                   CssLinkHref(kRoboto),
                   StrCat(CssLinkHref(kRoboto),
                          "<!--Cannot inline font loader CSS when "
                          "ModifyCachingHeaders is off-->"));

  options()->ClearSignatureForTesting();
  options()->set_modify_caching_headers(true);
  options()->set_downstream_cache_purge_location_prefix("foo");
  server_context()->ComputeSignature(options());
  ValidateExpected("incompat2",
                   CssLinkHref(kRoboto),
                   StrCat(CssLinkHref(kRoboto),
                          "<!--Cannot inline font loader CSS when "
                          "using downstream cache-->"));
}

TEST_F(GoogleFontCssInlineFilterTest, ProtocolRelative) {
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected("proto_rel",
                   CssLinkHref("//fonts.googleapis.com/css?family=Roboto"),
                   "<style>font_chromezilla</style>");
}

class GoogleFontCssInlineFilterSizeLimitTest
    : public GoogleFontCssInlineFilterTestBase {
 protected:
  virtual void SetUp() {
    GoogleFontCssInlineFilterTestBase::SetUp();
    // GoogleFontCssInlineFilter uses google_font_css_inline_max_bytes.
    // Set a threshold at font_safieri, which should prevent longer
    // font_chromezilla from inlining.
    options()->set_google_font_css_inline_max_bytes(
        STATIC_STRLEN("font_safieri"));
    SetUpForFontFilterTest(RewriteOptions::kInlineGoogleFontCss);
  }
};

TEST_F(GoogleFontCssInlineFilterSizeLimitTest, SizeLimit) {
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected(
      "slightly_long",
      CssLinkHref(kRoboto),
      StrCat(CssLinkHref(kRoboto),
             "<!--CSS not inlined since it's bigger than 12 bytes-->"));

  rewrite_driver()->SetUserAgent("Safieri");
  ValidateExpected("short",
                   CssLinkHref(kRoboto),
                   "<style>font_safieri</style>");
}

class GoogleFontCssInlineFilterAndImportTest
    : public GoogleFontCssInlineFilterTest {
 protected:
  virtual void SetUp() {
    RewriteTestBase::SetUp();  // skipped base on purpose
    options()->EnableFilter(
        RewriteOptions::RewriteOptions::kInlineImportToLink);
    SetUpForFontFilterTest(RewriteOptions::kInlineGoogleFontCss);
  }
};

TEST_F(GoogleFontCssInlineFilterAndImportTest, ViaInlineImport) {
  // Tests to make sure that if InlineImportToLink filter is on we
  // convert a <style>@import'ing </style> this as well.
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected("import",
                   StringPrintf("<style>@import \"%s\";</style>", kRoboto),
                   "<style>font_chromezilla</style>");

  rewrite_driver()->SetUserAgent("Safieri");
  ValidateExpected("import",
                   StringPrintf("<style>@import \"%s\";</style>", kRoboto),
                   "<style>font_safieri</style>");
}

class GoogleFontCssInlineFilterAndWidePermissionsTest
    : public GoogleFontCssInlineFilterTestBase {
  virtual void SetUp() {
    GoogleFontCssInlineFilterTestBase::SetUp();
    // Check that we don't rely solely on authorization to properly
    // dispatch the URL to us.
    options()->WriteableDomainLawyer()->AddDomain("*", message_handler());
    options()->EnableFilter(RewriteOptions::kInlineCss);
    SetUpForFontFilterTest(RewriteOptions::kInlineGoogleFontCss);
  }
};

TEST_F(GoogleFontCssInlineFilterAndWidePermissionsTest, WithWideAuthorization) {
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected("with_domain_*",
                   CssLinkHref(kRoboto),
                   "<style>font_chromezilla</style>");
}

// Negative test for the above, with font filter off, to make sure
// it's not inline_css doing stuff.
class NoGoogleFontCssInlineFilterAndWidePermissionsTest
    : public GoogleFontCssInlineFilterTestBase {
  virtual void SetUp() {
    GoogleFontCssInlineFilterTestBase::SetUp();
    // Check that we don't rely solely on authorization to properly
    // dispatch the URL to us.
    options()->WriteableDomainLawyer()->AddDomain("*", message_handler());
    SetUpForFontFilterTest(RewriteOptions::kInlineCss);
  }
};

TEST_F(NoGoogleFontCssInlineFilterAndWidePermissionsTest,
       WithWideAuthorization) {
  // Since font inlining isn't on, the regular inliner complains. This isn't
  // ideal, but doing otherwise requires inline_css to know about
  // inline_google_font_css, which also seems suboptimal.
  // TODO(morlovich): Figure out why this is 4xx.
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected("with_domain_*_without_font_filter", CssLinkHref(kRoboto),
                   StrCat(CssLinkHref(kRoboto),
                          "<!--4xx status code, preventing rewriting of "
                          "http://fonts.googleapis.com/css?family=Roboto-->"));
}

}  // namespace

}  // namespace net_instaweb
<commit_msg>Make NoGoogleFontCssInlineFilterAndWidePermissionsTest.WideAuthorization actually test what it was supposed to test.<commit_after>/*
 * Copyright 2013 Google Inc.
 *
 * Licensed 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.
 */

// Author: morlovich@google.com (Maksim Orlovich)
// Unit tests for GoogleFontCssInlineFilter

#include "net/instaweb/http/public/ua_sensitive_test_fetcher.h"
#include "net/instaweb/rewriter/public/domain_lawyer.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/rewrite_test_base.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_message_handler.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/http/content_type.h"
#include "pagespeed/kernel/http/response_headers.h"

namespace net_instaweb {

namespace {

const char kRoboto[] = "http://fonts.googleapis.com/css?family=Roboto";

class GoogleFontCssInlineFilterTestBase : public RewriteTestBase {
 protected:
  virtual void SetUp() {
    RewriteTestBase::SetUp();
  }

  void SetUpForFontFilterTest(RewriteOptions::Filter filter_to_enable) {
    AddFilter(filter_to_enable);

    // We want to enable debug after AddFilters, since we don't want the
    // standard debug filter output, just that from the font filter.
    options()->ClearSignatureForTesting();
    options()->EnableFilter(RewriteOptions::kDebug);
    server_context()->ComputeSignature(options());

    rewrite_driver()->SetSessionFetcher(
        new UserAgentSensitiveTestFetcher(rewrite_driver()->async_fetcher()));

    // Font loader CSS gets Cache-Control:private, max-age=86400
    ResponseHeaders response_headers;
    SetDefaultLongCacheHeaders(&kContentTypeCss, &response_headers);
    response_headers.SetDateAndCaching(
        timer()->NowMs(), 86400 * Timer::kSecondMs, ", private");

    // Now upload some UA-specific CSS where UaSensitiveFetcher will find it,
    // for two fake UAs: Chromezilla and Safieri, used since they are short,
    // unlike real UA strings.
    SetFetchResponse(StrCat(kRoboto, "&UA=Chromezilla"),
                     response_headers, "font_chromezilla");

    SetFetchResponse(StrCat(kRoboto, "&UA=Safieri"),
                     response_headers, "font_safieri");

    // If other filters will try to fetch this, they won't have a UA.
    SetFetchResponse(StrCat(kRoboto, "&UA=unknown"),
                     response_headers, "font_huh");
  }
};

class GoogleFontCssInlineFilterTest : public GoogleFontCssInlineFilterTestBase {
 protected:
  virtual void SetUp() {
    GoogleFontCssInlineFilterTestBase::SetUp();
    SetUpForFontFilterTest(RewriteOptions::kInlineGoogleFontCss);
  }
};

TEST_F(GoogleFontCssInlineFilterTest, BasicOperation) {
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected("simple",
                   CssLinkHref(kRoboto),
                   "<style>font_chromezilla</style>");

  // Different UAs get different cache entries
  rewrite_driver()->SetUserAgent("Safieri");
  ValidateExpected("simple2",
                   CssLinkHref(kRoboto),
                   "<style>font_safieri</style>");
}

TEST_F(GoogleFontCssInlineFilterTest, UsageRestrictions) {
  rewrite_driver()->SetUserAgent("Chromezilla");

  options()->ClearSignatureForTesting();
  options()->set_modify_caching_headers(false);
  server_context()->ComputeSignature(options());
  ValidateExpected("incompat1",
                   CssLinkHref(kRoboto),
                   StrCat(CssLinkHref(kRoboto),
                          "<!--Cannot inline font loader CSS when "
                          "ModifyCachingHeaders is off-->"));

  options()->ClearSignatureForTesting();
  options()->set_modify_caching_headers(true);
  options()->set_downstream_cache_purge_location_prefix("foo");
  server_context()->ComputeSignature(options());
  ValidateExpected("incompat2",
                   CssLinkHref(kRoboto),
                   StrCat(CssLinkHref(kRoboto),
                          "<!--Cannot inline font loader CSS when "
                          "using downstream cache-->"));
}

TEST_F(GoogleFontCssInlineFilterTest, ProtocolRelative) {
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected("proto_rel",
                   CssLinkHref("//fonts.googleapis.com/css?family=Roboto"),
                   "<style>font_chromezilla</style>");
}

class GoogleFontCssInlineFilterSizeLimitTest
    : public GoogleFontCssInlineFilterTestBase {
 protected:
  virtual void SetUp() {
    GoogleFontCssInlineFilterTestBase::SetUp();
    // GoogleFontCssInlineFilter uses google_font_css_inline_max_bytes.
    // Set a threshold at font_safieri, which should prevent longer
    // font_chromezilla from inlining.
    options()->set_google_font_css_inline_max_bytes(
        STATIC_STRLEN("font_safieri"));
    SetUpForFontFilterTest(RewriteOptions::kInlineGoogleFontCss);
  }
};

TEST_F(GoogleFontCssInlineFilterSizeLimitTest, SizeLimit) {
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected(
      "slightly_long",
      CssLinkHref(kRoboto),
      StrCat(CssLinkHref(kRoboto),
             "<!--CSS not inlined since it's bigger than 12 bytes-->"));

  rewrite_driver()->SetUserAgent("Safieri");
  ValidateExpected("short",
                   CssLinkHref(kRoboto),
                   "<style>font_safieri</style>");
}

class GoogleFontCssInlineFilterAndImportTest
    : public GoogleFontCssInlineFilterTest {
 protected:
  virtual void SetUp() {
    RewriteTestBase::SetUp();  // skipped base on purpose
    options()->EnableFilter(
        RewriteOptions::RewriteOptions::kInlineImportToLink);
    SetUpForFontFilterTest(RewriteOptions::kInlineGoogleFontCss);
  }
};

TEST_F(GoogleFontCssInlineFilterAndImportTest, ViaInlineImport) {
  // Tests to make sure that if InlineImportToLink filter is on we
  // convert a <style>@import'ing </style> this as well.
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected("import",
                   StringPrintf("<style>@import \"%s\";</style>", kRoboto),
                   "<style>font_chromezilla</style>");

  rewrite_driver()->SetUserAgent("Safieri");
  ValidateExpected("import",
                   StringPrintf("<style>@import \"%s\";</style>", kRoboto),
                   "<style>font_safieri</style>");
}

class GoogleFontCssInlineFilterAndWidePermissionsTest
    : public GoogleFontCssInlineFilterTestBase {
  virtual void SetUp() {
    GoogleFontCssInlineFilterTestBase::SetUp();
    // Check that we don't rely solely on authorization to properly
    // dispatch the URL to us.
    options()->WriteableDomainLawyer()->AddDomain("*", message_handler());
    rewrite_driver()->request_context()->AddSessionAuthorizedFetchOrigin(
        "http://fonts.googleapis.com");
    options()->EnableFilter(RewriteOptions::kInlineCss);
    SetUpForFontFilterTest(RewriteOptions::kInlineGoogleFontCss);
  }
};

TEST_F(GoogleFontCssInlineFilterAndWidePermissionsTest, WithWideAuthorization) {
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected("with_domain_*",
                   CssLinkHref(kRoboto),
                   "<style>font_chromezilla</style>");
}

// Negative test for the above, with font filter off, to make sure
// it's not inline_css doing stuff.
class NoGoogleFontCssInlineFilterAndWidePermissionsTest
    : public GoogleFontCssInlineFilterTestBase {
  virtual void SetUp() {
    GoogleFontCssInlineFilterTestBase::SetUp();
    // Check that we don't rely solely on authorization to properly
    // dispatch the URL to us. Note that we can't only use DomainLawyer here
    // since UserAgentSensitiveTestFetcher is at http layer so is simply
    // unaware of it.
    options()->WriteableDomainLawyer()->AddDomain("*", message_handler());
    rewrite_driver()->request_context()->AddSessionAuthorizedFetchOrigin(
        "http://fonts.googleapis.com");
    SetUpForFontFilterTest(RewriteOptions::kInlineCss);
  }
};

TEST_F(NoGoogleFontCssInlineFilterAndWidePermissionsTest,
       WithWideAuthorization) {
  // Since font inlining isn't on, the regular inliner complains. This isn't
  // ideal, but doing otherwise requires inline_css to know about
  // inline_google_font_css, which also seems suboptimal.
  rewrite_driver()->SetUserAgent("Chromezilla");
  ValidateExpected("with_domain_*_without_font_filter", CssLinkHref(kRoboto),
                   StrCat(CssLinkHref(kRoboto),
                          "<!--Uncacheable content, preventing rewriting of "
                          "http://fonts.googleapis.com/css?family=Roboto-->"));
}

}  // namespace

}  // namespace net_instaweb
<|endoftext|>