text:
/*!
  \class SoOffscreenRenderer SoOffscreenRenderer.h Inventor/SoOffscreenRenderer.h
  \brief The SoOffscreenRenderer class is used for rendering scenes in offscreen buffers.
  \ingroup general

  If you want to render to a memory buffer instead of an on-screen
  OpenGL context, use this class. Rendering to a memory buffer can be
  used to generate texture maps on-the-fly, or for saving snapshots of
  the scene to disk files (as pixel bitmaps or as Postscript files for
  sending to a Postscript-capable printer).

  Here's a dead simple usage example, just the code directly related
  to the SoOffscreenRenderer:

  \code
  SoOffscreenRenderer myRenderer(vpregion);
  SoNode * root = myViewer->getSceneManager()->getSceneGraph();
  SbBool ok = myRenderer.render(root);
  unsigned char * imgbuffer = myRenderer.getBuffer();
  // [then use image buffer in a texture, or write it to file, or whatever]
  \endcode

  And here a complete stand-alone example with a moving camera saving multiple
  frames to disk as JPGs:

  \code
  #include <Inventor/SoDB.h>
  #include <Inventor/SoOffscreenRenderer.h>
  #include <Inventor/engines/SoInterpolateVec3f.h>
  #include <Inventor/nodes/SoCube.h>
  #include <Inventor/nodes/SoDirectionalLight.h>
  #include <Inventor/nodes/SoPerspectiveCamera.h>
  #include <Inventor/nodes/SoSeparator.h>

  #include <iostream>

  int main()
  {
    // Init Coin
    SoDB::init();

    // The root node
    SoSeparator * root = new SoSeparator;
    root->ref();

    // It is mandatory to have at least one light for the offscreen renderer
    SoDirectionalLight * light = new SoDirectionalLight;
    root->addChild(light);

    // It is mandatory to have at least one camera for the offscreen renderer
    SoPerspectiveCamera * camera = new SoPerspectiveCamera;
    SbRotation cameraRotation = SbRotation::identity();
    cameraRotation *= SbRotation(SbVec3f(1, 0, 0), -0.4f);
    cameraRotation *= SbRotation(SbVec3f(0, 1, 0), 0.4f);
    camera->orientation = cameraRotation;
    root->addChild(camera);

    // Something to show... A box
    SoCube * cube = new SoCube;
    root->addChild(cube);

    // Set up the two camera positions we want to move the camera between
    SoInterpolateVec3f * interpolate = new SoInterpolateVec3f;
    interpolate->input0 = SbVec3f(2, 2, 9);
    interpolate->input1 = SbVec3f(2, 2, 5);
    camera->position.connectFrom(&interpolate->output);

    // Set up the offscreen renderer
    SbViewportRegion vpRegion(400, 300);
    SoOffscreenRenderer offscreenRenderer(vpRegion);

    // How many frames to render for the video
    int frames = 5;
    std::cout << "Writing " << frames << " frames..." << std::endl;

    for (int i = 0; i < frames; i++) {
      // Update the camera position
      interpolate->alpha = float(i) / (frames - 1);

      // Render the scene
      SbBool ok = offscreenRenderer.render(root);

      // Save the image to disk
      SbString filename = SbString("coinvideo-") + (i + 1) + ".jpg";
      if (ok) {
        offscreenRenderer.writeToFile(filename.getString(), "jpg");
      } else {
        std::cout << "Error saving image: " << filename.getString() << std::endl;
        break;
      }
    }

    std::cout << "Done!" << std::endl;

    root->unref();
    return 0;
  }
  \endcode

  Note that the SoOffscreenRenderer potentially allocates a fairly
  large amount of resources, both OpenGL and general system resources,
  for each instance. You will therefore be well adviced to try to
  reuse SoOffscreenRenderer instances, instead of constructing and
  destructing a new instance e.g. for each frame when generating
  pictures for video.

  Offscreen rendering is internally done through either a GLX
  offscreen context (i.e. OpenGL on X11), WGL (i.e. OpenGL on
  Win32), AGL (old-style OpenGL on the Mac OS X) or CGL (new-style Mac OS X).

  If the OpenGL driver supports the pbuffer extension, it is detected
  and used to provide hardware-accelerated offscreen rendering.

  The pixeldata is fetched from the OpenGL buffer with glReadPixels(),
  with the format and type arguments set to GL_RGBA and
  GL_UNSIGNED_BYTE, respectively. This means that the maximum
  resolution is 32 bits, 8 bits for each of the R/G/B/A components.

  One particular usage of the SoOffscreenRenderer is to make it render
  frames to be used for the construction of movies. The general
  technique for doing this is to iterate over the following actions:

move camera to correct position for frame

update the \c realTime global field (see explanation below)

invoke the SoOffscreenRenderer

dump rendered scene to file

  ..then you use some external tool or library to construct the movie
  file, for instance in MPEG format, from the set of files dumped to
  disk from the iterative process above.

  The code would go something like the following (pseudo-code
  style). First we need to stop the Coin library itself from doing any
  automatic updating of the \c realTime field, so your application
  initialization for Coin should look something like:

  \code
   [...] = SoQt::init([...]); // or SoWin::init() or SoDB::init()
   // ..and then immediately:

   // Control realTime field ourselves, so animations within the scene
   // follows "movie-time" and not "wallclock-time".
   SoDB::enableRealTimeSensor(FALSE);
   SoSceneManager::enableRealTimeUpdate(FALSE);
   SoSFTime * realtime = SoDB::getGlobalField("realTime");
   realtime->setValue(0.0);
  \endcode

  Note that it is important that the \c realTime field is initialized
  to \e your start-time \e before setting up any engines or other
  entities in the system that uses the \c realTime field.

  Then for the rendering loop, something like:

  \code
   for (int i=0; i < NRFRAMES; i++) {
     // [...reposition camera here, if necessary...]

     // render
     offscreenrend->render(root);

     // dump to file
     SbString framefile;
     framefile.sprintf("frame%06d.rgb", i);
     offscreenrend->writeToRGB(framefile.getString());

     // advance "current time" by the frames-per-second value, which
     // is 24 fps in this example
     realtime->setValue(realtime.getValue() + 1/24.0);
   }
  \endcode

  When making movies you need to write your application control code
  to take care of moving the camera along the correct trajectory
  yourself, and to explicitly control the global \c realTime field.
  The latter is so you're able to "step" with appropriate time units
  for each render operation (e.g. if you want a movie that has a 24
  FPS refresh rate, first render with \c realTime=0.0, then add 1/24s
  to the \c realTime field, render again to a new frame, add another
  1/24s to the \c realTime field, render, and so on).

  For further information about how to control the \c realTime field,
  see documentation of SoDB::getGlobalField(),
  SoDB::enableRealTimeSensor(), and
  SoSceneManager::enableRealTimeUpdate().

  If you want to use this class to create snapshots of your current
  viewer's view, but want to control the size of the snapshot, you
  need to modify the camera a bit while rendering to be sure that
  everything you see in the current view is visible in the snapshot.

  Below you'll find some pseude-code that does this. There are
  probably other ways to do this as well.

  \code
  void render_offscreen(const SbVec2s size)
  {
    SbVec2s glsize = this->getGLSize(); // size of your normal viewer
    float glar = float(glsize[0] / float(glsize[1]));
    float ar = float(size[0]) / float(size[1]);
    SoCamera * camera = this->getCamera(); // the camera you're using
    SoCamera::ViewportMapping oldmap = (SoCamera::ViewportMapping)
      camera->viewportMapping.getValue();
    float oldar = camera->aspectRatio.getValue();

    camera->viewportMapping = SoCamera::LEAVE_ALONE;
    camera->aspectRatio = ar;

    float scaleheight = 1.0f;
    if (glar > ar) {
      scaleheight = glar / ar;
      camera->scaleHeight(scaleheight);
    }
    else {
      scaleheight = ar / glar;
      camera->scaleHeight(scaleheight);
    }
    SoOffscreenRenderer * renderer = new SoOffscreenRenderer(size);
    renderer->render(root);

    // ... save image

    // restore camera
    camera->viewportMapping = oldmap;
    camera->aspectRatio = oldar;

    if (scaleheight != 1.0f) {
      camera->scaleHeight(1.0f / scaleheight);
    }
  }
  \endcode

*/

// As first mentioned to me by kyrah, the functionality of this class
// should really have been outside the core Coin library, seeing how
// it makes heavy use of window-system specifics. To be SGI Inventor
// compatible we need it to be part of the Coin API, though.
//
// mortene.

// *************************************************************************

// FIXME: we don't set up and render to RGBA-capable OpenGL-contexts,
// even when the requested format from the app-programmer is
// RGBA.
//
// I think this is what we should do:
//
//        1) first, try to get hold of a p-buffer with destination
//        alpha (p-buffers are faster to render into, as they can take
//        advantage of hardware acceleration)
//
//        2) failing that, try to make WGL/GLX/AGL/CGL set up a buffer
//        with destination alpha
//
//        3) failing that, get hold of either a p-buffer or a straight
//        WGL buffer with only RGB (no destination alpha -- this
//        should never fail), and do post-processing on the rendered
//        scene pixel-by-pixel to convert it into an RGBA texture
//
// 20020604 mortene.
//
// UPDATE 20041111 mortene: TGS Inventor has a new set of classes,
// e.g. "SoGLGraphicConfigTemplate", which makes it possible to set up
// wanted attributes with GL contexts. Audit their interface and
// implement, if well designed.

// *************************************************************************

#include <Inventor/SoOffscreenRenderer.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H

#include <assert.h>
#include <string.h> // memset(), memcpy()
#include <math.h> // for ceil()
#include <limits.h> // SHRT_MAX

#include <Inventor/C/glue/gl.h>
#include <Inventor/C/tidbits.h>
#include <Inventor/SbMatrix.h>
#include <Inventor/SbVec2f.h>
#include <Inventor/SbViewportRegion.h>
#include <Inventor/SoPath.h>
#include <Inventor/actions/SoGLRenderAction.h>
#include <Inventor/elements/SoCullElement.h>
#include <Inventor/elements/SoGLCacheContextElement.h>
#include <Inventor/elements/SoModelMatrixElement.h>
#include <Inventor/elements/SoProjectionMatrixElement.h>
#include <Inventor/elements/SoViewVolumeElement.h>
#include <Inventor/elements/SoViewingMatrixElement.h>
#include <Inventor/elements/SoCacheElement.h>
#include <Inventor/errors/SoDebugError.h>
#include <Inventor/misc/SoContextHandler.h>
#include <Inventor/misc/SoGLBigImage.h>
#include <Inventor/nodes/SoCallback.h>
#include <Inventor/nodes/SoCamera.h>
#include <Inventor/nodes/SoNode.h>
#include <Inventor/system/gl.h>
#include <Inventor/SbTime.h>

#include "glue/simage_wrapper.h"
#include "tidbitsp.h"
#include "coindefs.h" // COIN_STUB()

#include <boost/current_function.hpp>

// *************************************************************************

#include "CoinOffscreenGLCanvas.h"

#ifdef HAVE_GLX
#include "SoOffscreenGLXData.h"
#endif // HAVE_GLX

#ifdef COIN_MACOS_10
#include "SoOffscreenCGData.h"
#endif // COIN_MACOS_10

#ifdef HAVE_WGL
#include "SoOffscreenWGLData.h"
#endif // HAVE_WGL

// *************************************************************************

/*!
  \enum SoOffscreenRenderer::Components

  Enumerated values for the available image formats.

  \sa setComponents()
*/

// *************************************************************************

class SoOffscreenRendererP {
public:
  SoOffscreenRendererP(SoOffscreenRenderer * masterptr,
                       const SbViewportRegion & vpr,
                       SoGLRenderAction * glrenderaction = NULL)
  {
    this->master = masterptr;
    this->didreadbuffer = TRUE;

    this->backgroundcolor.setValue(0,0,0);
    this->components = SoOffscreenRenderer::RGB;
    this->buffer = NULL;
    this->bufferbytesize = 0;
    this->lastnodewasacamera = FALSE;

    if (glrenderaction) {
      this->renderaction = glrenderaction;
    }
    else {
      this->renderaction = new SoGLRenderAction(vpr);
      this->renderaction->setCacheContext(SoGLCacheContextElement::getUniqueCacheContext());
      this->renderaction->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_BLEND);
    }

    this->didallocation = glrenderaction ? FALSE : TRUE;
    this->viewport = vpr;
	this->useDC = false;
  }

  ~SoOffscreenRendererP()
  {
    if (this->didallocation) { delete this->renderaction; }
  }

  static SbBool offscreenContextsNotSupported(void);

  static const char * debugTileOutputPrefix(void);

  static SoGLRenderAction::AbortCode GLRenderAbortCallback(void *userData);
  SbBool renderFromBase(SoBase * base);

  void setCameraViewvolForTile(SoCamera * cam);

  static SbBool writeToRGB(FILE * fp, unsigned int w, unsigned int h,
                           unsigned int nrcomponents, const uint8_t * imgbuf);

  SbViewportRegion viewport;
  SbColor backgroundcolor;
  SoOffscreenRenderer::Components components;
  SoGLRenderAction * renderaction;
  SbBool didallocation;

  void updateDCBitmap();
  SbBool useDC;

  unsigned char * buffer;
  size_t bufferbytesize;

  CoinOffscreenGLCanvas glcanvas;
  unsigned int glcanvassize[2];

  int numsubscreens[2];
  // The subscreen size of the current tile. (Less than max if it's a
  // right- or bottom-border tile.)
  unsigned int subsize[2];
  // Keeps track of the current tile to be rendered.
  SbVec2s currenttile;

  SbBool lastnodewasacamera;
  SoCamera * visitedcamera;

  // used for lazy readPixels()
  SbBool didreadbuffer;
private:
  SoOffscreenRenderer * master;
};

#define PRIVATE(p) (p->pimpl)
#define PUBLIC(p) (p->master)

// *************************************************************************

// Set the environment variable below to get the individual tiles
// written out for debugging purposes. E.g.
//
//   $ export COIN_DEBUG_SOOFFSCREENRENDERER_TILEPREFIX="/tmp/offscreentile_"
//
// Tile X and Y position, plus the ".rgb" suffix, will be added when
// writing.
const char *
SoOffscreenRendererP::debugTileOutputPrefix(void)
{
  return coin_getenv("COIN_DEBUG_SOOFFSCREENRENDERER_TILEPREFIX");
}

// *************************************************************************

/*!
  Constructor. Argument is the \a viewportregion we should use when
  rendering. An internal SoGLRenderAction will be constructed.
*/
SoOffscreenRenderer::SoOffscreenRenderer(const SbViewportRegion & viewportregion)
{
  PRIVATE(this) = new SoOffscreenRendererP(this, viewportregion);
}

/*!
  Constructor. Argument is the \a action we should apply to the
  scene graph when rendering the scene. Information about the
  viewport is extracted from the \a action.
*/
SoOffscreenRenderer::SoOffscreenRenderer(SoGLRenderAction * action)
{
  PRIVATE(this) = new SoOffscreenRendererP(this, action->getViewportRegion(),
                                           action);
}

/*!
  Destructor.
*/
SoOffscreenRenderer::~SoOffscreenRenderer()
{
  delete[] PRIVATE(this)->buffer;
  delete PRIVATE(this);
}

/*!
  Returns the screen pixels per inch resolution of your monitor.
*/
float
SoOffscreenRenderer::getScreenPixelsPerInch(void)
{
  SbVec2f pixmmres(72.0f / 25.4f, 72.0f / 25.4f);
#ifdef HAVE_GLX
  pixmmres = SoOffscreenGLXData::getResolution();
#elif defined(HAVE_WGL)
  pixmmres = SoOffscreenWGLData::getResolution();
#elif defined(COIN_MACOS_10)
  pixmmres = SoOffscreenCGData::getResolution();
#endif // COIN_MACOS_10

  // The API-signature of this method is not what it should be: it
  // assumes the same resolution in the vertical and horizontal
  // directions.
  float pixprmm = (pixmmres[0] + pixmmres[1]) / 2.0f; // find average

  return pixprmm * 25.4f; // an inch is 25.4 mm.
}

/*!
  Get maximum dimensions (width, height) of the offscreen buffer.

  Note that from Coin version 2 onwards, the returned value will
  always be (\c SHRT_MAX, \c SHRT_MAX), where \c SHRT_MAX on most
  systems is equal to 32767.

  This because the SoOffscreenRenderer can in principle generate
  unlimited size offscreen canvases by tiling together multiple
  renderings of the same scene.
*/
SbVec2s
SoOffscreenRenderer::getMaximumResolution(void)
{
  return SbVec2s(SHRT_MAX, SHRT_MAX);
}

/*!
  Sets the component format of the offscreen buffer.

  If set to \c LUMINANCE, a grayscale image is rendered, \c
  LUMINANCE_TRANSPARENCY gives us a grayscale image with transparency,
  \c RGB will give us a 24-bit image with 8 bits each for the red,
  green and blue component, and \c RGB_TRANSPARENCY yields a 32-bit
  image (\c RGB plus transparency).

  The default format to render to is \c RGB.

  This will invalidate the current buffer, if any. The buffer will not
  contain valid data until another call to
  SoOffscreenRenderer::render() happens.
*/
void
SoOffscreenRenderer::setComponents(const Components components)
{
  PRIVATE(this)->components = components;
}

/*!
  Returns the component format of the offscreen buffer.

  \sa setComponents()
 */
SoOffscreenRenderer::Components
SoOffscreenRenderer::getComponents(void) const
{
  return PRIVATE(this)->components;

}

/*!
  Sets the viewport region.

  This will invalidate the current buffer, if any. The buffer will not
  contain valid data until another call to
  SoOffscreenRenderer::render() happens.
*/
void
SoOffscreenRenderer::setViewportRegion(const SbViewportRegion & region)
{
  PRIVATE(this)->viewport = region;
}

/*!
  Returns the viewerport region.
*/
const SbViewportRegion &
SoOffscreenRenderer::getViewportRegion(void) const
{
  return PRIVATE(this)->viewport;
}

/*!
  Sets the background color. The buffer is cleared to this color
  before rendering.
*/
void
SoOffscreenRenderer::setBackgroundColor(const SbColor & color)
{
  PRIVATE(this)->backgroundcolor = color;
}

/*!
  Returns the background color.
*/
const SbColor &
SoOffscreenRenderer::getBackgroundColor(void) const
{
  return PRIVATE(this)->backgroundcolor;
}

/*!
  Sets the render action. Use this if you have special rendering needs.
*/
void
SoOffscreenRenderer::setGLRenderAction(SoGLRenderAction * action)
{
  if (action == PRIVATE(this)->renderaction) { return; }

  if (PRIVATE(this)->didallocation) { delete PRIVATE(this)->renderaction; }
  PRIVATE(this)->renderaction = action;
  PRIVATE(this)->didallocation = FALSE;
}

/*!
  Returns the rendering action currently used.
*/
SoGLRenderAction *
SoOffscreenRenderer::getGLRenderAction(void) const
{
  return PRIVATE(this)->renderaction;
}

// *************************************************************************

static void
pre_render_cb(void * COIN_UNUSED_ARG(userdata), SoGLRenderAction * action)
{
  glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
  action->setRenderingIsRemote(FALSE);
}

// *************************************************************************

// Callback when rendering scenegraph to subscreens. Detects when a
// camera has just been traversed, and then invokes the method which
// narrows the camera viewport according to the current tile we're
// rendering to.
//
// FIXME: if possible, it would be better to pick up from the state
// whatever data we're now grabbing directly from the SoCamera nodes.
// It'd be more robust, I believe, as the elements set by SoCamera can
// in principle also be set from other code. 20041006 mortene.
//
// UPDATE 20050711 mortene: on how to fix this properly, see item #121
// in Coin/BUGS.txt.
SoGLRenderAction::AbortCode
SoOffscreenRendererP::GLRenderAbortCallback(void *userData)
{
  SoOffscreenRendererP * thisp = (SoOffscreenRendererP *) userData;
  const SoFullPath * path = (const SoFullPath*) thisp->renderaction->getCurPath();
  SoNode * node = path->getTail();
  assert(node);

  if (thisp->lastnodewasacamera) {
    thisp->setCameraViewvolForTile(thisp->visitedcamera);
    thisp->lastnodewasacamera = FALSE;
  }

  if (node->isOfType(SoCamera::getClassTypeId())) {
    thisp->visitedcamera = (SoCamera *) node;
    thisp->lastnodewasacamera = TRUE;

    // FIXME: this is not really entirely sufficient. If a camera is
    // already within a cached list upon the first invocation of a
    // render pass, we'll never get a callback upon encountering it.
    //
    // This would be a fairly obscure case, though, as the glcache
    // would have to be set up in another context, compatible for
    // sharing GL data with the one set up internally by the
    // SoOffscreenRenderer -- which is very unlikely.
    //
    // 20050512 mortene.
    //
    // UPDATE 20050711 mortene: on how to fix this properly, see item
    // #121 in Coin/BUGS.txt. (The tile number should be in an
    // element, which the SoCamera would query (and thereby also make
    // the cache dependent on)).
    SoCacheElement::invalidate(thisp->renderaction->getState());
  }

  return SoGLRenderAction::CONTINUE;
}

// Collects common code from the two render() functions.
SbBool
SoOffscreenRendererP::renderFromBase(SoBase * base)
{
  if (SoOffscreenRendererP::offscreenContextsNotSupported()) {
    static SbBool first = TRUE;
    if (first) {
      SoDebugError::post("SoOffscreenRenderer::renderFromBase",
                         "SoOffscreenRenderer not compiled against any "
                         "window-system binding, it is defunct for this build.");
      first = FALSE;
    }
    return FALSE;
  }

  const SbVec2s fullsize = this->viewport.getViewportSizePixels();
  this->glcanvas.setWantedSize(fullsize);

  // check if no possible canvas size was found
  if (this->glcanvas.getActualSize() == SbVec2s(0, 0)) { return FALSE; }

  const uint32_t newcontext = this->glcanvas.activateGLContext();
  if (newcontext == 0) {
    SoDebugError::postWarning("SoOffscreenRenderer::renderFromBase",
                              "Could not set up an offscreen OpenGL context.");
    return FALSE;
  }

  const SbVec2s glsize = this->glcanvas.getActualSize();

  // We need to know the actual GL viewport size for tiled rendering,
  // in calculations when narrowing the camera view volume -- so we
  // store away this value for the "found a camera"-callback.
  //
  // FIXME: seems unnecessary now, should be able to just query
  // glcanvas.getActualSize() XXX
  this->glcanvassize[0] = glsize[0];
  this->glcanvassize[1] = glsize[1];

  if (CoinOffscreenGLCanvas::debug()) {
    SoDebugError::postInfo("SoOffscreenRendererP::renderFromBase",
                           "fullsize==<%d, %d>, glsize==<%d, %d>",
                           fullsize[0], fullsize[1], glsize[0], glsize[1]);
  }

  // oldcontext is used to restore the previous context id, in case
  // the render action is not allocated by us.
  const uint32_t oldcontext = this->renderaction->getCacheContext();
  this->renderaction->setCacheContext(newcontext);

  if (CoinOffscreenGLCanvas::debug()) {
    GLint colbits[4];
    glGetIntegerv(GL_RED_BITS, &colbits[0]);
    glGetIntegerv(GL_GREEN_BITS, &colbits[1]);
    glGetIntegerv(GL_BLUE_BITS, &colbits[2]);
    glGetIntegerv(GL_ALPHA_BITS, &colbits[3]);
    SoDebugError::postInfo("SoOffscreenRenderer::renderFromBase",
                           "GL context GL_[RED|GREEN|BLUE|ALPHA]_BITS=="
                           "[%d, %d, %d, %d]",
                           colbits[0], colbits[1], colbits[2], colbits[3]);
  }

  glEnable(GL_DEPTH_TEST);
  glClearColor(this->backgroundcolor[0],
               this->backgroundcolor[1],
               this->backgroundcolor[2],
               0.0f);

  // Make this large to get best possible quality on any "big-image"
  // textures (from using SoTextureScalePolicy).
  //
  // FIXME: this doesn't seem to be working, according to a report by
  // Colin Dunlop. See bug item #108. 20050509 mortene.
  //
  // UPDATE 20050711 mortene: the bug report referred to above may not
  // be correct. We should anyway fix this in a more appropriate
  // manner, for instance by setting up a new element with a boolean
  // value to indicate whether or not stuff should be rendered in
  // maximum quality. That would be generally useful for having better
  // control from the offscreenrenderer.
  const int bigimagechangelimit = SoGLBigImage::setChangeLimit(INT_MAX);

  // Deallocate old and allocate new target buffer, if necessary.
  //
  // If we need more space:
  const size_t bufsize =
    fullsize[0] * fullsize[1] * PUBLIC(this)->getComponents();
  SbBool alloc = (bufsize > this->bufferbytesize);
  // or if old buffer was much larger, free up the memory by fitting
  // to smaller size:
  alloc = alloc || (bufsize <= (this->bufferbytesize / 8));

  if (alloc) {
    delete[] this->buffer;
    this->buffer = new unsigned char[bufsize];
    this->bufferbytesize = bufsize;
  }

  if (SoOffscreenRendererP::debugTileOutputPrefix()) {
    (void)memset(this->buffer, 0x00, bufsize);
  }

  // needed to clear viewport after glViewport() is called from
  // SoGLRenderAction
  this->renderaction->addPreRenderCallback(pre_render_cb, NULL);

  // For debugging purposes, it has been made possible to use an
  // envvar to *force* tiled rendering even when it can be done in a
  // single chunk.
  //
  // (Note: don't use this envvar when using SoExtSelection nodes, for
  // the reason noted below.)
  static int forcetiled = -1;
  if (forcetiled == -1) {
    const char * env = coin_getenv("COIN_FORCE_TILED_OFFSCREENRENDERING");
    forcetiled = (env && (atoi(env) > 0)) ? 1 : 0;
    if (forcetiled) {
      SoDebugError::postInfo("SoOffscreenRendererP::renderFromBase",
                             "Forcing tiled rendering.");
    }
  }

  // FIXME: tiled rendering should be decided on the exact same
  // criteria as is used in SoExtSelection to decide which size to use
  // for its offscreen-buffer, as that node fails in VISIBLE_SHAPE
  // mode with tiled rendering. This is a weakness with SoExtSelection
  // which should be improved upon, if possible (i.e. fix
  // SoExtSelection, rather than adding some kind of "semi-private"
  // API to let SoExtSelection find out whether or not tiled rendering
  // is used). 20041028 mortene.
  const SbBool tiledrendering =
    forcetiled || (fullsize[0] > glsize[0]) || (fullsize[1] > glsize[1]);

  // Shall we use subscreen rendering or regular one-screen renderer?
  if (tiledrendering) {
    // we need to copy from GL to system memory if we're doing tiled rendering
    this->didreadbuffer = TRUE;

    for (int i=0; i < 2; i++) {
      this->numsubscreens[i] = (fullsize[i] + (glsize[i] - 1)) / glsize[i];
    }

    // We have to grab cameras using this callback during rendering
    this->visitedcamera = NULL;
    this->renderaction->setAbortCallback(SoOffscreenRendererP::GLRenderAbortCallback, this);

    // Render entire scenegraph for each subscreen.
    for (int y=0; y < this->numsubscreens[1]; y++) {
      for (int x=0; x < this->numsubscreens[0]; x++) {
        this->currenttile = SbVec2s(x, y);

        // Find current "active" tilesize.
        this->subsize[0] = glsize[0];
        this->subsize[1] = glsize[1];
        if (x == (this->numsubscreens[0] - 1)) {
          this->subsize[0] = fullsize[0] % glsize[0];
          if (this->subsize[0] == 0) { this->subsize[0] = glsize[0]; }
        }
        if (y == (this->numsubscreens[1] - 1)) {
          this->subsize[1] = fullsize[1] % glsize[1];
          if (this->subsize[1] == 0) { this->subsize[1] = glsize[1]; }
        }

        SbViewportRegion subviewport = SbViewportRegion(SbVec2s(this->subsize[0], this->subsize[1]));
        this->renderaction->setViewportRegion(subviewport);

        if (base->isOfType(SoNode::getClassTypeId()))
          this->renderaction->apply((SoNode *)base);
        else if (base->isOfType(SoPath::getClassTypeId()))
          this->renderaction->apply((SoPath *)base);
        else {
          assert(FALSE && "Cannot apply to anything else than an SoNode or an SoPath");
        }

        const unsigned int nrcomp = PUBLIC(this)->getComponents();

        const int MAINBUF_OFFSET =
          (glsize[1] * y * fullsize[0] + glsize[0] * x) * nrcomp;

        const SbVec2s vpsize = subviewport.getViewportSizePixels();
        this->glcanvas.readPixels(this->buffer + MAINBUF_OFFSET,
                                  vpsize, fullsize[0], nrcomp);

        // Debug option to dump the (full) buffer after each
        // iteration.
        if (SoOffscreenRendererP::debugTileOutputPrefix()) {
          SbString s;
          s.sprintf("%s_%03d_%03d.rgb",
                    SoOffscreenRendererP::debugTileOutputPrefix(), x, y);

          FILE * f = fopen(s.getString(), "wb");
          assert(f);
          SbBool w = SoOffscreenRendererP::writeToRGB(f, fullsize[0], fullsize[1],
                                                      nrcomp, this->buffer);
          assert(w);
          const int r = fclose(f);
          assert(r == 0);

          // This is sometimes useful to enable during debugging to
          // see the exact order and position of the tiles. Not
          // enabled by default because it makes the final buffer
          // completely blank.
#if 0 // debug
          (void)memset(this->buffer, 0x00, bufsize);
#endif // debug
        }
      }
    }

    this->renderaction->setAbortCallback(NULL, this);

    if (!this->visitedcamera) {
      SoDebugError::postWarning("SoOffscreenRenderer::renderFromBase",
                                "No camera node found in scenegraph while rendering offscreen image. "
                                "The result will most likely be incorrect.");
    }

  }
  // Regular, non-tiled rendering.
  else {
    // do lazy buffer read (GL context is read in getBuffer())
    this->didreadbuffer = FALSE;

	SbViewportRegion region;

	region.setViewportPixels(0,glsize[0]-fullsize[0],fullsize[0],fullsize[1]);

    this->renderaction->setViewportRegion(region);

    SbTime t = SbTime::getTimeOfDay(); // for profiling

    if (base->isOfType(SoNode::getClassTypeId()))
      this->renderaction->apply((SoNode *)base);
    else if (base->isOfType(SoPath::getClassTypeId()))
      this->renderaction->apply((SoPath *)base);
    else  {
      assert(FALSE && "Cannot apply to anything else than an SoNode or an SoPath");
    }

    if (CoinOffscreenGLCanvas::debug()) {
      SoDebugError::postInfo("SoOffscreenRendererP::renderFromBase",
                             "*TIMING* SoGLRenderAction::apply() took %f msecs",
                             (SbTime::getTimeOfDay() - t).getValue() * 1000);
      t = SbTime::getTimeOfDay();
    }

    if (CoinOffscreenGLCanvas::debug()) {
      SoDebugError::postInfo("SoOffscreenRendererP::renderFromBase",
                             "*TIMING* glcanvas.readPixels() took %f msecs",
                             (SbTime::getTimeOfDay() - t).getValue() * 1000);
    }
  }

  this->renderaction->removePreRenderCallback(pre_render_cb, NULL);

  // Restore old value.
  (void)SoGLBigImage::setChangeLimit(bigimagechangelimit);

  this->glcanvas.deactivateGLContext();
  this->renderaction->setCacheContext(oldcontext); // restore old

  if(this->useDC)
	this->updateDCBitmap();

  return TRUE;
}

/*!
  Render the scenegraph rooted at \a scene into our internal pixel
  buffer.

  Important note: make sure you pass in a \a scene node pointer which
  has both a camera and at least one lightsource below it -- otherwise
  you are likely to end up with just a blank or black image buffer.

  This mistake is easily made if you use an SoOffscreenRenderer on a
  scenegraph from one of the standard viewer components, as you will
  often just leave the addition of a camera and a headlight
  lightsource to the viewer to set up. This camera and lightsource are
  then part of the viewer's private "super-graph" outside of the scope
  of the scenegraph passed in by the application programmer. To make
  sure the complete scenegraph (including the viewer's "private parts"
  (*snicker*)) are passed to this method, you can get the scenegraph
  root from the viewer's internal SoSceneManager instance instead of
  from the viewer's own getSceneGraph() method, like this:

  \code
  SoOffscreenRenderer * myRenderer = new SoOffscreenRenderer(vpregion);
  SoNode * root = myViewer->getSceneManager()->getSceneGraph();
  SbBool ok = myRenderer->render(root);
  // [then use image buffer in a texture, or write it to file, or whatever]
  \endcode

  If you do this and still get a blank buffer, another common problem
  is to have a camera which is not actually pointing at the scene
  geometry you want a snapshot of. If you suspect that could be the
  cause of problems on your end, take a look at SoCamera::pointAt()
  and SoCamera::viewAll() to see how you can make a camera node
  guaranteed to be directed at the scene geometry.

  Yet another common mistake when setting up the camera is to specify
  values for the SoCamera::nearDistance and SoCamera::farDistance
  fields which doesn't not enclose the full scene. This will result in
  either just the background color, or that parts at the front or the
  back of the scene will not be visible in the rendering.

  \sa writeToRGB()
*/
SbBool
SoOffscreenRenderer::render(SoNode * scene)
{
  return PRIVATE(this)->renderFromBase(scene);
}

/*!
  Render the \a scene path into our internal memory buffer.
*/
SbBool
SoOffscreenRenderer::render(SoPath * scene)
{
  return PRIVATE(this)->renderFromBase(scene);
}

// *************************************************************************

/*!
  Returns the offscreen memory buffer.
*/
unsigned char *
SoOffscreenRenderer::getBuffer(void) const
{
  if (!PRIVATE(this)->didreadbuffer) {
    const SbVec2s dims = this->getViewportRegion().getViewportSizePixels();
    //fprintf(stderr,"reading pixels: %d %d\n", dims[0], dims[1]);

    PRIVATE(this)->glcanvas.activateGLContext();
    PRIVATE(this)->glcanvas.readPixels(PRIVATE(this)->buffer, dims, dims[0],
                                       (unsigned int) this->getComponents());
    PRIVATE(this)->glcanvas.deactivateGLContext();
    PRIVATE(this)->didreadbuffer = TRUE;
  }
  return PRIVATE(this)->buffer;
}

/*!
  Win32 only:

  returns a direct handle to the internal DC of the offscreen
  context.

  Useful for efficient access to the raw image under certain special
  circumstances. getBuffer() might be too slow, for instance due to
  pixel format conversion (Windows DCs are usually BGRA, while the
  32-bit buffers returned from getBuffer() are RGBA).

  Notes:

  The return value is a reference to a HDC. The HDC typedef has been
  unwound to a native C++ type for multiplatform compatibility
  reasons.

  Returned reference will contain a NULL value on other platforms.

  Important limitation: if the current dimensions of the
  SoOffscreenRenderer instance are larger than what can be rendered
  with a single offscreen buffer, tiling will be used by the
  SoOffscreenRenderer, and the returned HDC will contain only part of
  the full rendered image.

  \sa getBuffer()
  \since Coin 3.1
*/
const void * const &
SoOffscreenRenderer::getDC(void) const
{
  if(!PRIVATE(this)->useDC)
  {
	PRIVATE(this)->useDC = true;
	PRIVATE(this)->updateDCBitmap();
  }

  return PRIVATE(this)->glcanvas.getHDC();
}

void SoOffscreenRendererP::updateDCBitmap()
{
  this->glcanvas.updateDCBitmap();
}
// *************************************************************************

//
// avoid endian problems (little endian sucks, right? :)
//
static size_t
write_short(FILE * fp, unsigned short val)
{
  unsigned char tmp[2];
  tmp[0] = (unsigned char)(val >> 8);
  tmp[1] = (unsigned char)(val & 0xff);
  return fwrite(&tmp, 2, 1, fp);
}

SbBool
SoOffscreenRendererP::writeToRGB(FILE * fp, unsigned int w, unsigned int h,
                                 unsigned int nrcomponents,
                                 const uint8_t * imgbuf)
{
  // FIXME: add code to rle rows, pederb 2000-01-10

  (void)write_short(fp, 0x01da); // imagic
  (void)write_short(fp, 0x0001); // raw (no rle yet)

  if (nrcomponents == 1)
    (void)write_short(fp, 0x0002); // 2 dimensions (heightmap)
  else
    (void)write_short(fp, 0x0003); // 3 dimensions

  (void)write_short(fp, (unsigned short) w);
  (void)write_short(fp, (unsigned short) h);
  (void)write_short(fp, (unsigned short) nrcomponents);

  const size_t BUFSIZE = 500;
  unsigned char buf[BUFSIZE];
  (void)memset(buf, 0, BUFSIZE);
  buf[7] = 255; // set maximum pixel value to 255
  strcpy((char *)buf+8, "http://www.coin3d.org");
  const size_t wrote = fwrite(buf, 1, BUFSIZE, fp);
  assert(wrote == BUFSIZE);

  unsigned char * tmpbuf = new unsigned char[w];

  SbBool writeok = TRUE;
  for (unsigned int c = 0; c < nrcomponents; c++) {
    for (unsigned int y = 0; y < h; y++) {
      for (unsigned int x = 0; x < w; x++) {
        tmpbuf[x] = imgbuf[(x + y * w) * nrcomponents + c];
      }
      writeok = writeok && (fwrite(tmpbuf, 1, w, fp) == w);
    }
  }

  if (!writeok) {
    SoDebugError::postWarning("SoOffscreenRendererP::writeToRGB",
                              "error when writing RGB file");
  }

  delete [] tmpbuf;
  return writeok;
}

/*!
  Writes the buffer in SGI RGB format by appending it to the already
  open file. Returns \c FALSE if writing fails.

  Important note: do \e not use this method when the Coin library has
  been compiled as an MSWindows DLL, as passing FILE* instances back
  or forth to DLLs is dangerous and will most likely cause a
  crash. This is an intrinsic limitation for MSWindows DLLs.
*/
SbBool
SoOffscreenRenderer::writeToRGB(FILE * fp) const
{
  if (SoOffscreenRendererP::offscreenContextsNotSupported()) { return FALSE; }

  SbVec2s size = PRIVATE(this)->viewport.getViewportSizePixels();

  return SoOffscreenRendererP::writeToRGB(fp, size[0], size[1],
                                          this->getComponents(),
                                          this->getBuffer());
}

/*!
  Opens a file with the given name and writes the offscreen buffer in
  SGI RGB format to the new file. If the file already exists, it will
  be overwritten (if permitted by the filesystem).

  Returns \c TRUE if all went ok, otherwise \c FALSE.
*/
SbBool
SoOffscreenRenderer::writeToRGB(const char * filename) const
{
  FILE * rgbfp = fopen(filename, "wb");
  if (!rgbfp) {
    SoDebugError::postWarning("SoOffscreenRenderer::writeToRGB",
                              "couldn't open file '%s'", filename);
    return FALSE;
  }
  SbBool result = this->writeToRGB(rgbfp);
  (void)fclose(rgbfp);
  return result;
}

/*!
  Writes the buffer in Postscript format by appending it to the
  already open file. Returns \c FALSE if writing fails.

  Important note: do \e not use this method when the Coin library has
  been compiled as an MSWindows DLL, as passing FILE* instances back
  or forth to DLLs is dangerous and will most likely cause a
  crash. This is an intrinsic limitation for MSWindows DLLs.
*/
SbBool
SoOffscreenRenderer::writeToPostScript(FILE * fp) const
{
  // just choose a page size of 8.5 x 11 inches (A4)
  return this->writeToPostScript(fp, SbVec2f(8.5f, 11.0f));
}

/*!
  Opens a file with the given name and writes the offscreen buffer in
  Postscript format to the new file. If the file already exists, it
  will be overwritten (if permitted by the filesystem).

  Returns \c TRUE if all went ok, otherwise \c FALSE.
*/
SbBool
SoOffscreenRenderer::writeToPostScript(const char * filename) const
{
  FILE * psfp = fopen(filename, "wb");
  if (!psfp) {
    SoDebugError::postWarning("SoOffscreenRenderer::writeToPostScript",
                              "couldn't open file '%s'", filename);
    return FALSE;
  }
  SbBool result = this->writeToPostScript(psfp);
  (void)fclose(psfp);
  return result;
}

/*!
  Writes the buffer to a file in Postscript format, with \a printsize
  dimensions.

  Important note: do \e not use this method when the Coin library has
  been compiled as an MSWindows DLL, as passing FILE* instances back
  or forth to DLLs is dangerous and will most likely cause a
  crash. This is an intrinsic limitation for MSWindows DLLs.
*/
SbBool
SoOffscreenRenderer::writeToPostScript(FILE * fp,
                                       const SbVec2f & printsize) const
{
  if (SoOffscreenRendererP::offscreenContextsNotSupported()) { return FALSE;}

  const SbVec2s size = PRIVATE(this)->viewport.getViewportSizePixels();
  const int nc = this->getComponents();
  const float defaultdpi = 72.0f; // we scale against this value
  const float dpi = this->getScreenPixelsPerInch();
  const SbVec2s pixelsize((short)(printsize[0]*defaultdpi),
                          (short)(printsize[1]*defaultdpi));

  const unsigned char * src = this->getBuffer();
  const int chan = nc <= 2 ? 1 : 3;
  const SbVec2s scaledsize((short) ceil(size[0]*defaultdpi/dpi),
                           (short) ceil(size[1]*defaultdpi/dpi));

  cc_string storedlocale;
  SbBool changed = coin_locale_set_portable(&storedlocale);

  fprintf(fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
  fprintf(fp, "%%%%BoundingBox: 0 %d %d %d\n",
          pixelsize[1]-scaledsize[1],
          scaledsize[0],
          pixelsize[1]);
  fprintf(fp, "%%%%Creator: Coin <http://www.coin3d.org>\n");
  fprintf(fp, "%%%%EndComments\n");

  fprintf(fp, "\n");
  fprintf(fp, "/origstate save def\n");
  fprintf(fp, "\n");
  fprintf(fp, "%% workaround for bug in some PS interpreters\n");
  fprintf(fp, "%% which doesn't skip the ASCII85 EOD marker.\n");
  fprintf(fp, "/~ {currentfile read pop pop} def\n\n");
  fprintf(fp, "/image_wd %d def\n", size[0]);
  fprintf(fp, "/image_ht %d def\n", size[1]);
  fprintf(fp, "/pos_wd %d def\n", size[0]);
  fprintf(fp, "/pos_ht %d def\n", size[1]);
  fprintf(fp, "/image_dpi %g def\n", dpi);
  fprintf(fp, "/image_scale %g image_dpi div def\n", defaultdpi);
  fprintf(fp, "/image_chan %d def\n", chan);
  fprintf(fp, "/xpos_offset 0 image_scale mul def\n");
  fprintf(fp, "/ypos_offset 0 image_scale mul def\n");
  fprintf(fp, "/pix_buf_size %d def\n\n", size[0]*chan);
  fprintf(fp, "/page_ht %g %g mul def\n", printsize[1], defaultdpi);
  fprintf(fp, "/page_wd %g %g mul def\n", printsize[0], defaultdpi);
  fprintf(fp, "/image_xpos 0 def\n");
  fprintf(fp, "/image_ypos page_ht pos_ht image_scale mul sub def\n");
  fprintf(fp, "image_xpos xpos_offset add image_ypos ypos_offset add translate\n");
  fprintf(fp, "\n");
  fprintf(fp, "/pix pix_buf_size string def\n");
  fprintf(fp, "image_wd image_scale mul image_ht image_scale mul scale\n");
  fprintf(fp, "\n");
  fprintf(fp, "image_wd image_ht 8\n");
  fprintf(fp, "[image_wd 0 0 image_ht 0 0]\n");
  fprintf(fp, "currentfile\n");
  fprintf(fp, "/ASCII85Decode filter\n");
  // fprintf(fp, "/RunLengthDecode filter\n"); // FIXME: add later. 2003???? pederb.
  if (chan == 3) fprintf(fp, "false 3\ncolorimage\n");
  else fprintf(fp,"image\n");

  const int rowlen = 72;
  int num = size[0] * size[1];
  unsigned char tuple[4];
  unsigned char linebuf[rowlen+5];
  int tuplecnt = 0;
  int linecnt = 0;
  int cnt = 0;
  while (cnt < num) {
    switch (nc) {
    default: // avoid warning
    case 1:
      coin_output_ascii85(fp, src[cnt], tuple, linebuf, &tuplecnt, &linecnt, rowlen, FALSE);
      break;
    case 2:
      coin_output_ascii85(fp, src[cnt*2], tuple, linebuf, &tuplecnt, &linecnt, rowlen, FALSE);
      break;
    case 3:
      coin_output_ascii85(fp, src[cnt*3], tuple, linebuf, &tuplecnt, &linecnt, rowlen, FALSE);
      coin_output_ascii85(fp, src[cnt*3+1], tuple, linebuf, &tuplecnt, &linecnt, rowlen, FALSE);
      coin_output_ascii85(fp, src[cnt*3+2], tuple, linebuf, &tuplecnt, &linecnt, rowlen, FALSE);
      break;
    case 4:
      coin_output_ascii85(fp, src[cnt*4], tuple, linebuf, &tuplecnt, &linecnt, rowlen, FALSE);
      coin_output_ascii85(fp, src[cnt*4+1], tuple, linebuf, &tuplecnt, &linecnt,rowlen, FALSE);
      coin_output_ascii85(fp, src[cnt*4+2], tuple, linebuf, &tuplecnt, &linecnt, rowlen, FALSE);
      break;
    }
    cnt++;
  }

  // flush data in ascii85 encoder
  coin_flush_ascii85(fp, tuple, linebuf, &tuplecnt, &linecnt, rowlen);

  fprintf(fp, "~>\n\n"); // ASCII85 EOD marker
  fprintf(fp, "origstate restore\n");
  fprintf(fp, "\n");
  fprintf(fp, "%%%%Trailer\n");
  fprintf(fp, "\n");
  fprintf(fp, "%%%%EOF\n");

  if (changed) { coin_locale_reset(&storedlocale); }

  return (SbBool) (ferror(fp) == 0);
}

/*!
  Opens a file with the given name and writes the offscreen buffer in
  Postscript format with \a printsize dimensions to the new file. If
  the file already exists, it will be overwritten (if permitted by the
  filesystem).

  Returns \c TRUE if all went ok, otherwise \c FALSE.
*/
SbBool
SoOffscreenRenderer::writeToPostScript(const char * filename,
                                       const SbVec2f & printsize) const
{
  FILE * psfp = fopen(filename, "wb");
  if (!psfp) {
    SoDebugError::postWarning("SoOffscreenRenderer::writeToPostScript",
                              "couldn't open file '%s'", filename);
    return FALSE;
  }
  SbBool result = this->writeToPostScript(psfp, printsize);
  (void)fclose(psfp);
  return result;
}

// FIXME: the file format support checking could have been done
// better, for instance by using MIME types. Consider fixing the API
// for later major releases. 20020206 mortene.
//
// UPDATE 20050711 mortene: it seems like TGS has extended their API
// in an even worse way; by adding separate writeToJPEG(),
// writeToPNG(), etc etc functions.

/*!
  Returns \c TRUE if the buffer can be saved as a file of type \a
  filetypeextension, using SoOffscreenRenderer::writeToFile().  This
  function needs simage v1.1 or newer.

  Examples of possibly supported extensions are: "jpg", "png", "tiff",
  "gif", "bmp", etc. The extension match is not case sensitive.

  Which formats are \e actually supported depends on the capabilities
  of Coin's support library for handling import and export of
  pixel-data files: the simage library. If the simage library is not
  installed on your system, no extension output formats will be
  supported.

  Also, note that it is possible to build and install a simage library
  that lacks support for most or all of the file formats it is \e
  capable of supporting. This is so because the simage library depends
  on other, external 3rd party libraries -- in the same manner as Coin
  depends on the simage library for added file format support.

  The two built-in formats that are supported through the
  SoOffscreenRenderer::writeToRGB() and
  SoOffscreenRenderer::writeToPostScript() methods (for SGI RGB format
  and for Adobe Postscript files, respectively) are \e not considered
  by this method, as those two formats are guaranteed to \e always be
  supported through those functions.

  So if you want to be guaranteed to be able to export a screenshot in
  your wanted format, you will have to use either one of the above
  mentioned method for writing SGI RGB or Adobe Postscript directly,
  or make sure the Coin library has been built and is running on top
  of a version of the simage library (that you have preferably built
  yourself) with the file format(s) you want support for.

  This method is an extension versus the original SGI Open Inventor
  API.

  \sa  getNumWriteFiletypes(), getWriteFiletypeInfo(), writeToFile()
*/
SbBool
SoOffscreenRenderer::isWriteSupported(const SbName & filetypeextension) const
{
  if (!simage_wrapper()->versionMatchesAtLeast(1,1,0)) {

    if (CoinOffscreenGLCanvas::debug()) {
      if (!simage_wrapper()->available) {
        SoDebugError::postInfo("SoOffscreenRenderer::isWriteSupported",
                               "simage library not available.");
      } else {
        SoDebugError::postInfo("SoOffscreenRenderer::isWriteSupported",
                               "You need simage v1.1 for this functionality.");
      }
    }
    return FALSE;
  }
  int ret = simage_wrapper()->simage_check_save_supported(filetypeextension.getString());
  return ret ? TRUE : FALSE;
}

/*!
  Returns the number of available exporters. Detailed information
  about the exporters can then be found using getWriteFiletypeInfo().

  See SoOffscreenRenderer::isWriteSupported() for information about
  which file formats you can expect to be present.

  Note that the two built-in export formats, SGI RGB and Adobe
  Postscript, are not counted.

  This method is an extension versus the original SGI Open Inventor
  API.

  \sa getWriteFiletypeInfo()
*/
int
SoOffscreenRenderer::getNumWriteFiletypes(void) const
{
  if (!simage_wrapper()->versionMatchesAtLeast(1,1,0)) {
#if COIN_DEBUG
    SoDebugError::postInfo("SoOffscreenRenderer::getNumWriteFiletypes",
                           "You need simage v1.1 for this functionality.");
#endif // COIN_DEBUG
    return 0;
  }
  return simage_wrapper()->simage_get_num_savers();
}

/*!
  Returns information about an image exporter. \a extlist is a list
  of filename extensions for a file format. E.g. for JPEG it is legal
  to use both jpg and jpeg. Extlist will contain const char * pointers
  (you need to cast the void * pointers to const char * before using
  them).

  \a fullname is the full name of the image format. \a description is
  an optional string with more information about the file format.

  See SoOffscreenRenderer::isWriteSupported() for information about
  which file formats you can expect to be present.

  This method is an extension versus the original SGI Open Inventor
  API.

  Here is a stand-alone, complete code example that shows how you can
  check exactly which output formats are supported:

  \code
  #include <Inventor/SoDB.h>
  #include <Inventor/SoOffscreenRenderer.h>

  int
  main(int argc, char **argv)
  {
    SoDB::init();
    SoOffscreenRenderer * r = new SoOffscreenRenderer(*(new SbViewportRegion));
    int num = r->getNumWriteFiletypes();

    if (num == 0) {
      (void)fprintf(stdout,
                    "No image formats supported by the "
                    "SoOffscreenRenderer except SGI RGB and Postscript.\n");
    }
    else {
      for (int i=0; i < num; i++) {
        SbPList extlist;
        SbString fullname, description;
        r->getWriteFiletypeInfo(i, extlist, fullname, description);
        (void)fprintf(stdout, "%s: %s (extension%s: ",
                      fullname.getString(), description.getString(),
                      extlist.getLength() > 1 ? "s" : "");
        for (int j=0; j < extlist.getLength(); j++) {
          (void)fprintf(stdout, "%s%s", j>0 ? ", " : "", (const char*) extlist[j]);
        }
        (void)fprintf(stdout, ")\n");
      }
    }

    delete r;
    return 0;
  }
  \endcode

  \sa getNumWriteFiletypes(), writeToFile()

  \since Coin 2.3
*/
void
SoOffscreenRenderer::getWriteFiletypeInfo(const int idx,
                                          SbPList & extlist,
                                          SbString & fullname,
                                          SbString & description)
{
  if (!simage_wrapper()->versionMatchesAtLeast(1,1,0)) {
#if COIN_DEBUG
    SoDebugError::postInfo("SoOffscreenRenderer::getNumWriteFiletypes",
                           "You need simage v1.1 for this functionality.");
#endif // COIN_DEBUG
    return;
  }
  extlist.truncate(0);
  assert(idx >= 0 && idx < this->getNumWriteFiletypes());
  void * saver = simage_wrapper()->simage_get_saver_handle(idx);
  SbString allext(simage_wrapper()->simage_get_saver_extensions(saver));
  const char * start = allext.getString();
  const char * curr = start;
  const char * end = strchr(curr, ',');
  while (end) {
    const ptrdiff_t offset_start = curr - start;
    const ptrdiff_t offset_end = end - start - 1;
    SbString ext = allext.getSubString((int)offset_start, (int)offset_end);
    SbName extname(ext.getString());
    extlist.append((void*)extname.getString());
    curr = end+1;
    end = strchr(curr, ',');
  }
  const ptrdiff_t offset = curr - start;
  SbString ext = allext.getSubString((int)offset);
  SbName extname(ext.getString());
  extlist.append((void*)extname.getString());
  const char * fullname_s = simage_wrapper()->simage_get_saver_fullname(saver);
  const char * desc_s = simage_wrapper()->simage_get_saver_description(saver);
  fullname = fullname_s ? SbString(fullname_s) : SbString("");
  description = desc_s ? SbString(desc_s) : SbString("");
}

/*!
  Saves the buffer to \a filename, in the filetype specified by \a
  filetypeextensions.

  Note that you must still specify the \e full \a filename for the
  first argument, i.e. the second argument will not automatically be
  attached to the filename -- it is only used to decide the filetype.

  This method is an extension versus the orignal SGI Open Inventor
  API.

  \sa isWriteSupported()
*/
SbBool
SoOffscreenRenderer::writeToFile(const SbString & filename, const SbName & filetypeextension) const
{
  if (!simage_wrapper()->versionMatchesAtLeast(1,1,0)) {
    //FIXME: Shouldn't use BOOST_CURRENT_FUNCTION here, the
    //HAVE_CPP_COMPILER_FUNCTION_NAME_VAR should be massaged correctly
    //to fit here. BFG 20090917
    if (!simage_wrapper()->available) {
      SoDebugError::post(BOOST_CURRENT_FUNCTION,
                             "simage library not available.");
    }
    else {
      int major, minor, micro;
      simage_wrapper()->simage_version(&major,&minor,&micro);
      SoDebugError::post(BOOST_CURRENT_FUNCTION,
                         "simage version is older than 1.1.0, available version is %d.%d.%d", major,minor,micro);
    }
    return FALSE;
  }
  if (SoOffscreenRendererP::offscreenContextsNotSupported()) {
    SoDebugError::post(BOOST_CURRENT_FUNCTION,
                       "Offscreen contexts not supported.");
    return FALSE;
  }

  SbVec2s size = PRIVATE(this)->viewport.getViewportSizePixels();
  int comp = (int) this->getComponents();
  unsigned char * bytes = this->getBuffer();
  int ret = simage_wrapper()->simage_save_image(filename.getString(),
                                                bytes,
                                                int(size[0]), int(size[1]), comp,
                                                filetypeextension.getString());
  return ret ? TRUE : FALSE;
}

// *************************************************************************

/*!
  Control whether or not SoOffscreenRenderer can use the "pbuffer"
  feature of OpenGL to render the scenes with hardware acceleration.

  This is a dummy function in Coin, provided for API compatibility
  reasons, as it is really superfluous:

  Coin has internal heuristics to figure out if pbuffers are available
  and can be allocated and used for the SoOffscreenRenderer.  The
  SoOffscreenRenderer will also automatically fall back on "soft"
  buffers if it can not use pbuffers (or any other hardware
  accelerated rendering technique).

  \since Coin 3.1
*/
void
SoOffscreenRenderer::setPbufferEnable(SbBool COIN_UNUSED_ARG(enable))
{
  // FIXME: change the semantics of this function from just ignoring
  // the input argument, to using it for shutting off pbuffers if
  // FALSE?
  //
  // not sure there's really any good reason to do that, however.
  //
  // mortene.
}

/*!
  See SoOffscreenRenderer::setPbufferEnable().

  \since Coin 3.1
*/
SbBool
SoOffscreenRenderer::getPbufferEnable(void) const
{
  // FIXME: should perhaps return a flag indicating whether or not the
  // system can use pbuffers. this depends on the GL context, however,
  // so the design of this Mercury Inventor API function is inherently
  // flawed.
  //
  // hardly any GL driver these days does *not* provide pbuffers,
  // though, so this is unlikely to be an important issue.
  //
  // mortene.

  return TRUE;
}

// *************************************************************************

// FIXME: this should really be done by SoCamera, on the basis of data
// from an "SoTileRenderingElement". See BUGS.txt, item #121. 20050712 mortene.
void
SoOffscreenRendererP::setCameraViewvolForTile(SoCamera * cam)
{
  SoState * state = (PUBLIC(this)->getGLRenderAction())->getState();

  // A small trick to change the aspect ratio without changing the
  // scenegraph camera.
  SbViewVolume vv;
  const float aspectratio = this->viewport.getViewportAspectRatio();
  const SbVec2s vporigin = this->viewport.getViewportOriginPixels();

  switch(cam->viewportMapping.getValue()) {
  case SoCamera::CROP_VIEWPORT_FILL_FRAME:
  case SoCamera::CROP_VIEWPORT_LINE_FRAME:
  case SoCamera::CROP_VIEWPORT_NO_FRAME:
    vv = cam->getViewVolume(0.0f);

    { // FIXME: should really fix this bug, not just warn that it is
      // there. See item #191 in Coin/BUGS.txt for more information.
      // 20050714 mortene.
      static SbBool first = TRUE;
      if (first) {
        SbString s;
        cam->viewportMapping.get(s);
        SoDebugError::postWarning("SoOffscreenRendererP::setCameraViewvolForTile",
                                  "The SoOffscreenRenderer does not yet work "
                                  "properly with the SoCamera::viewportMapping "
                                  "field set to '%s'", s.getString());
        first = FALSE;
      }
    }
    break;
  case SoCamera::ADJUST_CAMERA:
    vv = cam->getViewVolume(aspectratio);
    if (aspectratio < 1.0f) vv.scale(1.0f / aspectratio);
    break;
  case SoCamera::LEAVE_ALONE:
    vv = cam->getViewVolume(0.0f);
    break;
  default:
    assert(0 && "unknown viewport mapping");
    break;
  }

  const int LEFTINTPOS = (this->currenttile[0] * this->glcanvassize[0]) - vporigin[0];
  const int RIGHTINTPOS = LEFTINTPOS + this->subsize[0];
  const int TOPINTPOS = (this->currenttile[1] * this->glcanvassize[1]) - vporigin[1];
  const int BOTTOMINTPOS = TOPINTPOS + this->subsize[1];

  const SbVec2s fullsize = this->viewport.getViewportSizePixels();
  const float left = float(LEFTINTPOS) / float(fullsize[0]);
  const float right = float(RIGHTINTPOS) / float(fullsize[0]);
  // Swap top / bottom, to flip the coordinate system for the Y axis
  // the way we want it.
  const float top = float(BOTTOMINTPOS) / float(fullsize[1]);
  const float bottom = float(TOPINTPOS) / float(fullsize[1]);

  if (CoinOffscreenGLCanvas::debug()) {
    SoDebugError::postInfo("SoOffscreenRendererP::setCameraViewvolForTile",
                           "narrowing for tile <%d, %d>: <%f, %f> - <%f, %f>",
                           this->currenttile[0], this->currenttile[1],
                           left, bottom, right, top);
  }

  // Reshape view volume
  vv = vv.narrow(left, bottom, right, top);

  SbMatrix proj, affine;
  vv.getMatrices(affine, proj);

  // Support antialiasing if renderpasses > 1
  if (renderaction->getNumPasses() > 1) {
    SbVec3f jittervec;
    SbMatrix m;
    const int vpsize[2] = { this->glcanvassize[0], this->glcanvassize[1] };
    coin_viewvolume_jitter(renderaction->getNumPasses(), renderaction->getCurPass(),
                           vpsize, (float *)jittervec.getValue());
    m.setTranslate(jittervec);
    proj.multRight(m);
  }

  SoCullElement::setViewVolume(state, vv);
  SoViewVolumeElement::set(state, cam, vv);
  SoProjectionMatrixElement::set(state, cam, proj);
  SoViewingMatrixElement::set(state, cam, affine);
}

// *************************************************************************

SbBool
SoOffscreenRendererP::offscreenContextsNotSupported(void)
{
  // Returning FALSE means that offscreen rendering seems to be
  // generally supported on the system.
  //
  // (It is however important to be robust and handle cases where it
  // still fails, as this can happen due to e.g. lack of resources or
  // other causes that may change during run-time.)

#ifdef HAVE_GLX
  return FALSE;
#elif defined(HAVE_WGL)
  return FALSE;
#elif defined(COIN_MACOS_10)
  return FALSE;
#endif

  // No win-system GL binding was found, so we're sure that offscreen
  // rendering can *not* be done.
  return TRUE;
}

// *************************************************************************

#undef PRIVATE
#undef PUBLIC


text:
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using NamedPipeWrapper;
using NLog;

namespace Conic.Wormhole
{
    public class WormholeServiceMulti
    {
        private static readonly Logger _log = LogManager.GetCurrentClassLogger();
        //private static readonly Logger _log = LogManager.CreateNullLogger();
        private readonly string _pipeName;

        public WormholeServiceMulti(string pipeName)
        {
            _pipeName = pipeName;
        }

        public void StartServer()
        {
            var cts = new CancellationTokenSource();
            var token = cts.Token;

            token.ThrowIfCancellationRequested();

            var task = Task.Run(() =>
            {
                _log.Debug($"Start pipe server. Pipe name: '{_pipeName}'");
                var server = new NamedPipeServer<string>(_pipeName);

                Action end = () =>
                {
                    server.ClientConnected += OnClientConnected;
                    server.ClientDisconnected += OnClientDisconnected;
                    server.ClientMessage += OnClientMessage;
                };

                server.ClientConnected += OnClientConnected;
                server.ClientDisconnected += OnClientDisconnected;
                server.ClientMessage += OnClientMessage;

                try
                {
                    server.Start();
                }
                catch (Exception e)
                {
                    _log.Error(e);
                    end();
                    return;
                }
                while (true)
                {
                    try
                    {
                        if (token.IsCancellationRequested)
                        {
                            _log.Debug("Another thread decided to cancel");
                            break;
                        }
                        var r = Read();
                        if (r.ImputLength == 0) break;
                        server.PushMessage(r.Value);
                    }
                    catch (Exception e)
                    {
                        _log.Error(e);
                    }
                }
                server.Stop();
                end();
            }, token);

            task.Wait(token);
            _log.Debug($"Stop pipe server. Pipe name: {_pipeName}");
        }

        private void OnClientMessage(NamedPipeConnection<string, string> connection, string message)
        {
            _log.Trace(
                $"OnClientMessage; ConnectionName: {connection.Name}, ConnectionId: {connection.Id}, MessageLength: {message.Length}");
            Write(message);
        }

        private void OnClientDisconnected(NamedPipeConnection<string, string> connection)
        {
            _log.Trace($"Client {connection.Id} is now disconnected!");
        }

        private void OnClientConnected(NamedPipeConnection<string, string> conn)
        {
            _log.Debug($"Client {conn.Id} is now connected!");
        }

        /// <summary>
        /// Write message to standard output
        /// Remember: First 4 bytes contains message length
        /// </summary>
        /// <param name="message"></param>
        private void Write(string message)
        {
            _log.Trace($"Begin write to standardOutput message; Length: {message.Length}");
            var buff = Encoding.UTF8.GetBytes(message);
            using (var stdout = Console.OpenStandardOutput())
            {
                stdout.Write(BitConverter.GetBytes(buff.Length), 0, 4); //Write the length
                stdout.Write(buff, 0, buff.Length); //Write the message
                stdout.Flush();
            }
            _log.Trace("End write to standardOutput message");
        }

        /// <summary>
        /// Read  message from standard input
        /// Remember: First 4 bytes contains message length
        /// </summary>
        private ReadResult Read()
        {
            _log.Trace("Begin read from StandardInput");
            int length;
            string input;
            using (var stdin = Console.OpenStandardInput())
            {
                var buff = new byte[4];
                stdin.Read(buff, 0, 4);
                length = BitConverter.ToInt32(buff, 0);
                buff = new byte[length];
                stdin.Read(buff, 0, length);
                input = Encoding.UTF8.GetString(buff);
                _log.Trace($"End read from StandardInput. Message length: {input.Length}");
            }
            return new ReadResult(length, input);
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
package org.apache.sis.referencing.report;

import java.util.Deque;
import java.util.ArrayDeque;
import java.util.Locale;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.Closeable;
import org.opengis.util.InternationalString;
import org.apache.sis.internal.util.Constants;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.Deprecable;

/**
 * Base class of all classes used to generate HTML pages to be published on
 * the https://sis.apache.org/ web site.
 *
 *
This class creates files in the current default directory. It is user's responsibility
 * to move the files to the appropriate Apache SIS {@code "content/"} site directory.

 *
 * @author  Martin Desruisseaux (Geomatys)
 * @version 0.7
 * @since   0.6
 * @module
 */
abstract strictfp class HTMLGenerator implements Closeable {
    /**
     * The encoding of the files to generate.
     */
    private static final String ENCODING = "UTF-8";

    /**
     * The language to use for the reports to generate.
     *
     * @see #toLocalizedString(InternationalString)
     */
    static final Locale LOCALE = Locale.US;

    /**
     * The number of space to add or remove in the {@linkplain #margin}
     * when new HTML elements are opened or closed.
     */
    private static final int INDENTATION = Constants.DEFAULT_INDENTATION;

    /**
     * Where to write the HTML page.
     */
    private final BufferedWriter out;

    /**
     * The spaces to write in the margin before every new line.
     * The number of spaces will increase by the indentation amount when new elements are opened.
     *
     * @see #INDENTATION
     */
    private String margin = "";

    /**
     * HTML tags currently opened.
     */
    private final Deque<String> openedTags;

    /**
     * Creates a new instance which will write in the given file.
     * This constructor immediately writes the HTML header up to the {@code } line, inclusive.
     *
     * @param  filename  the name of the file where to write.
     * @param  title     the document title.
     * @param  css       path to the CSS file.
     * @throws IOException if the file cannot be created (e.g. because it already exists).
     */
    HTMLGenerator(final String filename, final String title, final String css) throws IOException {
        final File file = new File(filename);
        if (file.exists()) {
            throw new IOException("File " + file.getAbsolutePath() + " already exists.");
        }
        openedTags = new ArrayDeque<>();
        out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), ENCODING));
        out.write("<!DOCTYPE html>");
        out.newLine();
        out.write("");
        out.newLine();
        openTag("html");
        final int head = openTag("head");
        out.write(margin);
        out.write("<meta charset=\"" + ENCODING + "\"/>");
        out.newLine();
        println("title", title);
        openTag("style type=\"text/css\" media=\"all\"");
        out.write(margin);
        out.write("@import url(\"");
        out.write(css);
        out.write("\");");
        out.newLine();
        closeTags(head);
        openTag("body");
    }

    /**
     * Escapes the {@code &}, {@code <} and {@code >} characters.
     *
     * @param  text  the text to escape, or {@code null}.
     * @return the escaped text, or {@code null} if the given text was null.
     */
    static CharSequence escape(CharSequence text) {
        text = CharSequences.replace(text, "&", "&");
        text = CharSequences.replace(text, "<", "<");
        text = CharSequences.replace(text, ">", ">");
        return text;
    }

    /**
     * Return the given HTML tag without the attributes. For example if {@code tag} is
     * {@code "table class='param'"}, then this method returns only {@code "table"}.
     */
    private static String omitAttributes(String tag) {
        final int s = tag.indexOf(' ');
        if (s >= 0) {
            tag = tag.substring(0, s);
        }
        return tag;
    }

    /**
     * Opens a new HTML tag and increase the indentation.
     *
     * @param  tag  the HTML tag without brackets (e.g. {@code "h2"}).
     * @return the value to give to {@link #closeTags(int)} for closing the tags.
     * @throws IOException if an error occurred while writing to the file.
     */
    final int openTag(final String tag) throws IOException {
        return openTag(tag, null);
    }

    /**
     * Opens a new HTML tag of the given class and increase the indentation.
     *
     * @param  tag     the HTML tag without brackets (e.g. {@code "h2"}).
     * @param  classe  the CSS class, or {@code null} if none.
     * @return the value to give to {@link #closeTags(int)} for closing the tags.
     * @throws IOException if an error occurred while writing to the file.
     */
    final int openTag(final String tag, final String classe) throws IOException {
        out.write(margin);
        out.write('<');
        out.write(tag);
        if (classe != null) {
            out.write(" class=\"");
            out.write(classe);
            out.write('"');
        }
        out.write('>');
        out.newLine();
        margin = CharSequences.spaces(margin.length() + INDENTATION).toString();
        final int openedTag = openedTags.size();
        openedTags.add(omitAttributes(tag));
        return openedTag;
    }

    /**
     * Closes the last HTML tag if it is equal to the given element, and opens a new tag on the same line.
     *
     * @param  tag  the HTML tag without brackets (e.g. {@code "h2"}).
     * @throws IOException if an error occurred while writing to the file.
     */
    final void reopenTag(final String tag) throws IOException {
        final String tagWithoutAttributes = omitAttributes(tag);
        if (openedTags.getLast().equals(tagWithoutAttributes)) {
            out.write(CharSequences.spaces(margin.length() - INDENTATION).toString());
            out.write("</");
            out.write(tagWithoutAttributes);
            out.write("><");
            out.write(tag);
            out.write('>');
            out.newLine();
        } else {
            openTag(tag);
        }
    }

    /**
     * Closes the HTML tag identified by the given number, together will all child tags.
     *
     * @param  openedTag  the value returned by the {@link #openTag(String)} matching the tag to close.
     * @throws IOException if an error occurred while writing to the file.
     */
    final void closeTags(final int openedTag) throws IOException {
        while (openedTags.size() != openedTag) {
            margin = CharSequences.spaces(margin.length() - INDENTATION).toString();
            out.write(margin);
            out.write("</");
            out.write(openedTags.removeLast());
            out.write('>');
            out.newLine();
        }
    }

    /**
     * Writes the given text in the given HTML element.
     * The {@code &}, {@code <} and {@code >} characters are not escaped.
     * For escaping those characters, invoke println(tag, {@linkplain #escape(CharSequence) escape}(value)).
     *
     * @param  tag    the HTML tag without brackets (e.g. {@code "h1"}).
     * @param  value  the text to write, or {@code null} for none.
     * @throws IOException if an error occurred while writing to the file.
     */
    final void println(final String tag, final CharSequence value) throws IOException {
        out.write(margin);
        out.write('<');
        out.write(tag);
        out.write('>');
        if (value != null) {
            out.write(value.toString());
        }
        out.write("</");
        final int s = tag.indexOf(' ');
        out.write(tag, 0, (s >= 0) ? s : tag.length());
        out.write('>');
        out.newLine();
    }

    /**
     * Writes the given text on its own line, then write EOL sequence.
     * The {@code &}, {@code <} and {@code >} characters are not escaped.
     * For escaping those characters, invoke println({@linkplain #escape(CharSequence) escape}(value)).
     *
     * @param  value  the text to write, or {@code null} if none.
     * @throws IOException if an error occurred while writing to the file.
     */
    final void println(final CharSequence value) throws IOException {
        if (value != null) {
            out.write(margin);
            out.write(value.toString());
            out.newLine();
        }
    }

    /**
     * Closes the HTML generator.
     *
     * @throws IOException if an error occurred while closing the output file.
     */
    @Override
    public void close() throws IOException {
        closeTags(0);
        out.close();
    }

    /**
     * Returns the localized version of the given string, or {@code null} if none.
     *
     * @param  text  the text to localize, or {@code null}.
     * @return the localized test, or {@code null}.
     *
     * @see #LOCALE
     */
    static String toLocalizedString(final InternationalString text) {
        return (text != null) ? text.toString(LOCALE) : null;
    }

    /**
     * Returns {@code true} if the given object is deprecated.
     *
     * @param  object  the object to test.
     * @return {@code true} if the given object is deprecated.
     */
    static boolean isDeprecated(final Object object) {
        return (object instanceof Deprecable) && ((Deprecable) object).isDeprecated();
    }
}


text:
package org.hsqldb.test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;

import org.hsqldb.jdbc.jdbcDataSource;

public class TestBatchBug {

    static final int    DATASET_COUNT              = 2;
    static final int    DECIMAL_FIELDS_PER_DATASET = 2;
    static final String TABLE_ATTR_CACHED          = "CACHED";
    static final String IN_PROCESS_FILE_URL =
        "jdbc:hsqldb:/temp/hsqldb/perftest";
    static final String HSQLDB_LOCALHOST_URL =
        "jdbc:hsqldb:hsql://localhost/yourtest";
    ;
    static final String TEST_TABLE_NAME       = "CSBug";
    static String       FIELD_LIST_WITHOUT_ID = "Kennung, Last_Update ";

// wird in static {} erweitert:
    static String FIELD_LIST_WITH_ID    = "ID, ";
    static String SQL_SELECT_ALL_FIELDS = "SELECT ";

// wird in static {} erweitert:
    static {
        for (int i = 1; i <= DECIMAL_FIELDS_PER_DATASET; i++) {
            FIELD_LIST_WITHOUT_ID += ", Field_" + i;
        }

        FIELD_LIST_WITH_ID += FIELD_LIST_WITHOUT_ID;
        SQL_SELECT_ALL_FIELDS += FIELD_LIST_WITH_ID + " FROM "
                                 + TEST_TABLE_NAME;
    }

    static int ldfNrFuerKennung;

    public static void main(String[] arg) {

        try {
            String[] urls = {
                IN_PROCESS_FILE_URL, HSQLDB_LOCALHOST_URL,
            };

            for (int i = 0; i < urls.length; i++) {
                String   url        = urls[i];
                String[] tableAttrs = { TABLE_ATTR_CACHED };

                for (int iAttr = 0; iAttr < tableAttrs.length; iAttr++) {
                    testURL(url, "CACHED");
                }
            }

            System.out.println("bye");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static void testURL(String url, String tableAttr) throws SQLException {

        System.out.println(url);

        jdbcDataSource dataSource = new jdbcDataSource();

        dataSource.setDatabase(url);

        Connection con = dataSource.getConnection("sa", "");

        reCreateTable(con, "CACHED");
        populateTable(con);
        con.close();
    }

    static void reCreateTable(Connection con,
                              String tableAttr) throws SQLException {

        String cvsFileName = TEST_TABLE_NAME + ".csv";

// Create a statement object
        Statement stmt = con.createStatement();

// Try to drop the table
        try {

// stmt.executeUpdate("DROP TABLE " + TEST_TABLE_NAME + " IF EXISTS");
            stmt.executeUpdate("DROP TABLE " + TEST_TABLE_NAME);
        } catch (SQLException e) {    // Ignore Exception, because the table may not yet exist
            System.out.println(e.getMessage());
        }

        StringBuffer sql = new StringBuffer();

        sql.append("CREATE ");
        sql.append(tableAttr);    // z.B. "CACHED"
        sql.append(" TABLE ");
        sql.append(TEST_TABLE_NAME);
        sql.append(" (");
        sql.append("Id integer IDENTITY");
        sql.append(", ");
        sql.append("Kennung varchar(20) NOT NULL");

// etwas andere Schreibweise von CURRENT TIMESTAMP
        sql.append(", last_update TIMESTAMP ");
        sql.append("DEFAULT CURRENT_TIMESTAMP NOT NULL");

        for (int i = 1; i <= DECIMAL_FIELDS_PER_DATASET; i++) {
            sql.append(", Field_" + i + " decimal");
        }

        sql.append(", UNIQUE(Kennung)");
        sql.append(")");
        System.out.println(sql.toString());
        stmt.executeUpdate(sql.toString());

// CLEAR TABLE
        sql = new StringBuffer();

        sql.append("DELETE FROM ");
        sql.append(TEST_TABLE_NAME);
        System.out.println(sql.toString());
        stmt.executeUpdate(sql.toString());
        stmt.close();    // is no longer used
    }

// tries to enter 2 records
    static void populateTable(Connection con) throws SQLException {

        long      startTime = System.currentTimeMillis();
        Timestamp now       = new Timestamp(startTime);

        con.setAutoCommit(false);

        String            sql  = createInsertSQL(true, false);
        PreparedStatement prep = con.prepareStatement(sql);

        prep.clearParameters();
        prep.setString(1, "xxx");
        prep.setTimestamp(2, now);    // last_update

        for (int ii = 0; ii < DECIMAL_FIELDS_PER_DATASET; ii++) {
            prep.setDouble(ii + 3, 0.123456789);    // Wert
        }

        prep.addBatch();
        prep.setString(1, "yyy");
        prep.setTimestamp(2, now);    // last_update

        for (int ii = 0; ii < DECIMAL_FIELDS_PER_DATASET; ii++) {
            prep.setDouble(ii + 3, 0.123456789);    // Wert
        }

        prep.addBatch();

        int[] updateCounts = prep.executeBatch();

        con.setAutoCommit(true);
        prep.close();
    }

    static String createInsertSQL(boolean prepStmt, boolean getIdAfterInsert) {

        StringBuffer sql = new StringBuffer();

        sql.append("INSERT INTO ");
        sql.append(TEST_TABLE_NAME);
        sql.append(" (");
        sql.append(FIELD_LIST_WITHOUT_ID);
        sql.append(") VALUES (");

        Timestamp now = new Timestamp(System.currentTimeMillis());
        Object    val = "?";

        if (prepStmt) {
            sql.append(val + ", " + val);
        } else {
            long millis = System.currentTimeMillis();

            sql.append("'Ken");
            sql.append((++ldfNrFuerKennung) + "'");

            val = new Double(0.123456789) + "";

            sql.append(", '" + now.toString() + "'");
        }

        for (int i = 1; i <= DECIMAL_FIELDS_PER_DATASET; i++) {
            sql.append(", " + val);
        }

        sql.append(")");

        String ret = sql.toString();

        System.out.println(ret);

        return ret;
    }
}


text:
using Internal.TypeSystem;

namespace Internal.IL.Stubs
{
    // Functionality related to deterministic ordering of methods
    partial class DelegateMarshallingMethodThunk
    {
        protected internal override int ClassCode => 1018037605;

        protected internal override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
        {
            var otherMethod = (DelegateMarshallingMethodThunk)other;
            int result = (int)Kind - (int)otherMethod.Kind;
            if (result != 0)
                return result;

            return comparer.Compare(_delegateType, otherMethod._delegateType);
        }
    }
}


text:
using System;
using System.Linq.Expressions;
using System.Reflection;
using FluentNHibernate.Conventions.Inspections;
using FluentNHibernate.MappingModel;
using FluentNHibernate.Utils;
using NUnit.Framework;

namespace FluentNHibernate.Testing.ConventionsTests.Inspection
{
    [TestFixture, Category("Inspection DSL")]
    public class HibernateMappingInspectorMapsToHibernateMapping
    {
        private HibernateMapping mapping;
        private IHibernateMappingInspector inspector;

        [SetUp]
        public void CreateDsl()
        {
            mapping = new HibernateMapping();
            inspector = new HibernateMappingInspector(mapping);
        }

        [Test]
        public void CatalogMapped()
        {
            mapping.Catalog = "cat";
            inspector.Catalog.ShouldEqual("cat");
        }

        [Test]
        public void CatalogIsSet()
        {
            mapping.Catalog = "cat";
            inspector.IsSet(Prop(x => x.Catalog))
                .ShouldBeTrue();
        }

        [Test]
        public void CatalogIsNotSet()
        {
            inspector.IsSet(Prop(x => x.Catalog))
                .ShouldBeFalse();
        }

        [Test]
        public void DefaultAccessMapped()
        {
            mapping.DefaultAccess = "field";
            inspector.DefaultAccess.ShouldEqual(Access.Field);
        }

        [Test]
        public void DefaultAccessIsSet()
        {
            mapping.DefaultAccess = "field";
            inspector.IsSet(Prop(x => x.DefaultAccess))
                .ShouldBeTrue();
        }

        [Test]
        public void DefaultAccessIsNotSet()
        {
            inspector.IsSet(Prop(x => x.DefaultAccess))
                .ShouldBeFalse();
        }

        [Test]
        public void DefaultCascadeMapped()
        {
            mapping.DefaultCascade = "all";
            inspector.DefaultCascade.ShouldEqual(Cascade.All);
        }

        [Test]
        public void DefaultCascadeIsSet()
        {
            mapping.DefaultCascade = "all";
            inspector.IsSet(Prop(x => x.DefaultCascade))
                .ShouldBeTrue();
        }

        [Test]
        public void DefaultCascadeIsNotSet()
        {
            inspector.IsSet(Prop(x => x.DefaultCascade))
                .ShouldBeFalse();
        }

        [Test]
        public void DefaultLazyMapped()
        {
            mapping.DefaultLazy = true;
            inspector.DefaultLazy.ShouldEqual(true);
        }

        [Test]
        public void DefaultLazyIsSet()
        {
            mapping.DefaultLazy = true;
            inspector.IsSet(Prop(x => x.DefaultLazy))
                .ShouldBeTrue();
        }

        [Test]
        public void DefaultLazyIsNotSet()
        {
            inspector.IsSet(Prop(x => x.DefaultLazy))
                .ShouldBeFalse();
        }

        [Test]
        public void SchemaMapped()
        {
            mapping.Schema = "dbo";
            inspector.Schema.ShouldEqual("dbo");
        }

        [Test]
        public void SchemaIsSet()
        {
            mapping.Schema = "dbo";
            inspector.IsSet(Prop(x => x.Schema))
                .ShouldBeTrue();
        }

        [Test]
        public void SchemaIsNotSet()
        {
            inspector.IsSet(Prop(x => x.Schema))
                .ShouldBeFalse();
        }

        #region Helpers

        private PropertyInfo Prop(Expression<Func<IHibernateMappingInspector, object>> propertyExpression)
        {
            return ReflectionHelper.GetProperty(propertyExpression);
        }

        #endregion
    }
}


text:
<?php

    namespace Dez\Micro;

    /**
     * Class ApplicationException
     * @package Dez\Micro
     */
    class ApplicationException extends \Exception {}


text:
import { bindActionCreators } from "redux";
import { connect } from "react-redux";

import HomePage from "../components/HomePage";
import * as PollActions from "../actions/poll";

function mapStateToProps(state) {
  return state.homepage;
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(PollActions, dispatch);
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(HomePage);


text:
var EventPublisher = require("./event-publisher"),
  _ = require("underscore")._,
  inherits = require("inherits"),
  isArray = Array.isArray,
  redis = require("redis"),
  uuid = require('node-uuid');

module.exports = RedisEventPublisher;

var defaultConfig = {
  pub: {},
  sub: {}
};

function RedisEventPublisher(options) {
  options = options || {};

  var me = this,
    redisConfig = options.redis || defaultConfig,
    pubConfig = redisConfig.pub || defaultConfig.pub,
    subConfig = redisConfig.sub || defaultConfig.sub;

  RedisEventPublisher.super.call(this, options);

  //setup the redis pub/sub clients
  this.pubClient = redis.createClient(
    pubConfig.port, //default = 6379
    pubConfig.host, //default = 127.0.0.1
    pubConfig.options //default = see https://github.com/mranney/node_redis#rediscreateclientport-host-options
  );

  this.subClient = redis.createClient(
    subConfig.port, //default = 6379
    subConfig.host, //default = 127.0.0.1
    subConfig.options //default = see https://github.com/mranney/node_redis#rediscreateclientport-host-options
  );

  this.channelId = 'redis-events::' + this.id;

  this.subClient.subscribe(this.channelId);
  this.subClient.on('message', function(channel, message) {
    //when we receive an event from another process, only re-fire it locally...
    var args = JSON.parse(message);
    //don't fire events that originated from this instance
    var uuid = args.shift();
    if (uuid !== me.uuid) {
      RedisEventPublisher.prototype.fireLocalOnly.apply(me, args);
      //also fire the same event with a '.d' suffix to denote this was a distributed event (makes it easier to write code that only responds to distributed events, if desired)
      args[0] = args[0] + '.d';
      RedisEventPublisher.prototype.fireLocalOnly.apply(me, args);
    }
  });

  //make distributed dispose work properly
  this.on('disposed.d', function() {
    if (!me.disposing) {
      //this means dispose is being distributed from another process
      me.suppress('disposed'); //make sure local dispose() doesn't fire/distribute disposed event again
      me.dispose();
    }
  });

  //need a local uuid to filter out own events from distributed stream
  this.uuid = uuid();
};

//public setter method to set global REDIS pub/sub server config defaults
RedisEventPublisher.__defineSetter__('config', function(config) {
  defaultConfig = config;
});

//NOTE: add to this array as needed.
var nonDistributableEvents = ['newListener'];

RedisEventPublisher.prototype.emit = RedisEventPublisher.prototype.fire = function (eventName) {
  var args = _.toArray(arguments);

  //local behavior inherited from EventPublisher/EventEmitter
  RedisEventPublisher.super.prototype.emit.apply(this, args);

  //blacklist events from attempting to be distributed
  if (nonDistributableEvents.indexOf(eventName) > -1) return;

  //now distribute the event via REDIS
  //all arguments must be JSON serializable for this class
  try {
    args.unshift(this.uuid); //key the event to this instance to make sure it doesn't get repeated locally
    var pubArgs = JSON.stringify(args);
    this.pubClient.publish(this.channelId, pubArgs);
  } catch (ex) {
    throw new Error('All arguments to RedisEventPublisher.fire/emit must be JSON serializable');
  }

};

RedisEventPublisher.prototype.emitLocalOnly = RedisEventPublisher.prototype.fireLocalOnly = function() {
  //only perform local ops
  //local behavior inherited from EventPublisher/EventEmitter
  RedisEventPublisher.super.prototype.emit.apply(this, arguments);
};

RedisEventPublisher.prototype.dispose = function() {
  this.disposing = true;

  var subClient = this.subClient,
    pubClient = this.pubClient;

  subClient.unsubscribe();

  //need to disconnect the clients on the next tick because the EventPublisher class fires 'disposed'
  //which we still need the pub client to distribute to support distributed dispose,
  //note: needed to grab local var references because base dispose will nullify all instance members
  process.nextTick(function() {
    subClient.end();
    pubClient.end();
  });

  RedisEventPublisher.super.prototype.dispose.apply(this, arguments);
};

inherits(RedisEventPublisher, EventPublisher);


text:
package org.springframework.core.io;

import java.io.IOException;
import java.io.InputStream;

/**
 * 输入流源接口,只有一个getInputStream方法

 * Simple interface for objects that are sources for an {@link InputStream}.
 *
 *
This is the base interface for Spring's more extensive {@link Resource} interface.
 *
 *
For single-use streams, {@link InputStreamResource} can be used for any
 * given {@code InputStream}. Spring's {@link ByteArrayResource} or any
 * file-based {@code Resource} implementation can be used as a concrete
 * instance, allowing one to read the underlying content stream multiple times.
 * This makes this interface useful as an abstract content source for mail
 * attachments, for example.
 *
 * @author Juergen Hoeller
 * @since 20.01.2004
 * @see java.io.InputStream
 * @see Resource
 * @see InputStreamResource
 * @see ByteArrayResource
 */
public interface InputStreamSource {

	/**
	 * 获取输入流

	 * Return an {@link InputStream}.
	 *
It is expected that each call creates a fresh stream.
	 *
This requirement is particularly important when you consider an API such
	 * as JavaMail, which needs to be able to read the stream multiple times when
	 * creating mail attachments. For such a use case, it is required
	 * that each {@code getInputStream()} call returns a fresh stream.
	 * @return the input stream for the underlying resource (must not be {@code null})
	 * @throws IOException if the stream could not be opened
	 * @see org.springframework.mail.javamail.MimeMessageHelper#addAttachment(String, InputStreamSource)
	 */
	InputStream getInputStream() throws IOException;

}


text:
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">PandoraTheBoxer</string>

</resources>


text:
Quick hack that converts monophonic MIDI tracks to proprietary code that plays sounds on an Electric Imp. Simply fails if any polyphonic content is found.

Example usage:

    npm install
    ./convert.js smb1-Theme.mid


text: <title>DOM 2 HTML HRElement - Interactive</title>


text:
namespace LH.TestObjects.Compare.ValueComparators.KnownTypes
{
    using System;
    using System.Collections;
    using System.Linq;

    internal class DictionaryValueComparator : IValueComparator
    {
        public bool CanHandle(Type type)
        {
            return typeof(IDictionary).IsAssignableFrom(type);
        }

        public bool Compare(ComparisonContext comparisonContext, ValueComparison valueComparison)
        {
            var actual = (IDictionary)valueComparison.ActualValue;
            var expected = (IDictionary)valueComparison.ExpectedValue;

            if (!this.AreKeysEqual(expected, actual, comparisonContext, valueComparison))
            {
                return false;
            }

            foreach (var key in expected.Keys)
            {
                var actualValue = actual[key];
                var expectedValue = expected[key];

                // TODO: Why is this immediately picked up by the recursive comparator
                // TODO: Create a valid use case test for the recursive comparator
                // TODO: Both values null in the dictionary
                // TODO: Comple objects in the dictionary

                var propertyPath = new PropertyPathItem(key.ToString(), valueComparison.PropertyPathItem);
                comparisonContext.CompareItem(expectedValue, actualValue, propertyPath);
            }

            return true;
        }

        private bool AreKeysEqual(IDictionary expected, IDictionary actual, ComparisonContext comparisonContext, ValueComparison valueComparison)
        {
            var notInExpected = actual.Keys
                .Cast<object>()
                .Where(x => !expected.Contains(x));

            var notInActual = expected.Keys
                .Cast<object>()
                .Where(x => !actual.Contains(x));

            var result = true;

            foreach (var key in notInActual)
            {
                var keyComparison = this.CreateKeyNamedComparison(
                    valueComparison,
                    key.ToString(),
                    "The dictionaries differ, the key '{0}' is missing in the actual value.");

                comparisonContext.AddDifference(keyComparison);
                result = false;
            }

            foreach (var key in notInExpected)
            {
                var keyComparison = this.CreateKeyNamedComparison(
                    valueComparison,
                    key.ToString(),
                    "The dictionaries differ, there is an extra key '{0}' in the actual value.");

                comparisonContext.AddDifference(keyComparison);
                result = false;
            }

            return result;
        }

        private ValueComparison CreateKeyNamedComparison(ValueComparison comparison, string key, string messageFormat)
        {
            var itemPropPath = new PropertyPathItem(key, comparison.PropertyPathItem);

            var result = new ValueComparison(
                itemPropPath,
                comparison.ExpectedValue,
                comparison.ActualValue);

            result.Message = string.Format(messageFormat, key);
            return result;
        }
    }
}


text:
import os

def gc_init(api_url='https://girder.hub.yt/api/v1', api_key=None):
  from girder_client import GirderClient
  if api_key is None:
    try:
      api_key = os.environ['GIRDER_API_KEY']
    except KeyError as err:
      msg = 'please define GIRDER_API_KEY environment variable\n'
      msg += ' or pass api_key kwargs.'
      raise KeyError(msg)
  gc = GirderClient(apiUrl=api_url)
  gc.authenticate(apiKey=api_key)
  return gc

def find_folder(gc, path, root, verbose=False):
  tokens = path.split('/')
  # initialize
  target = None
  folder_id = root
  new_path = []  # track search path
  # perform search
  for tok in tokens:
    folders = gc.listFolder(folder_id)
    for folder in folders:
      name = folder['name']
      folder_id = folder['_id']
      if name == tok:
        target = folder
        new_path.append(folder['name'])
        break
  # check search
  if len(new_path) != len(tokens):
    target = None
    msg = 'search ended at %s\n' % '/'.join(new_path)
    msg += ' expected %s' % path
    raise RuntimeError(msg)
  return target

def ls(gc, folder_id):
  from itertools import chain
  gen = chain(gc.listItem(folder_id), gc.listFolder(folder_id))
  return gen

def same_atoms(atoms0, atoms1, atol=1e-8, verbose=False):
  import numpy as np
  same_natom = len(atoms0) == len(atoms1)
  same_cell = np.allclose(atoms0.get_cell(), atoms1.get_cell(), atol=atol)
  same_pbc = np.allclose(atoms0.get_pbc(), atoms1.get_pbc(), atol=atol)
  same_pos = np.allclose(atoms0.get_positions(), atoms1.get_positions(), atol=atol)
  same = same_natom and same_cell and same_pbc and same_pos
  if (not same) and verbose:
    names = ['natom', 'cell', 'pbc', 'pos']
    sames = [same_natom, same_cell, same_pbc, same_pos]
    msg = ''
    for name, s1 in zip(names, sames):
      msg += '%s=%d; ' % (name, s1)
    print(msg)
  return same


text:
<?php
/**
 * Message translations.
 *
 * This file is automatically generated by 'yii message/extract' command.
 * It contains the localizable messages extracted from source code.
 * You may modify this file by translating the extracted messages.
 *
 * Each array element represents the translation (value) of a message (key).
 * If the value is empty, the message is considered as not translated.
 * Messages that no longer need translation will have their translations
 * enclosed between a pair of '@@' marks.
 *
 * Message string can be used with plural forms format. Check i18n section
 * of the guide for details.
 *
 * NOTE: this file must be saved in UTF-8 encoding.
 */
return [
    'A TLS/SSL is strongly favored in production environments to prevent passwords from be transmitted in clear text.' => 'A TLS/SSL é fortemente favorecido em ambientes de produção para evitar senhas de ser transmitida em texto puro.',
    'Defines the filter to apply, when login is attempted. %s replaces the username in the login action. Example: "(sAMAccountName=%s)" or "(uid=%s)"' => 'Define o filtro a ser aplicado, quando o login é feito. %s substitui o nome de usuário no processo de login. Exemplo: "sAMAccountName=%s)" or "(uid=%s)"',
    'LDAP Attribute for E-Mail Address. Default: &quotmail"' => 'Atributo LDAP para e-mail. Padrão: &quotmail"',
    'LDAP Attribute for Username. Example: &quotuid" or "sAMAccountName"' => 'Atributo LDAP para usuário. Exemplo:  &quotuid" or "sAMAccountName"',
    'Limit access to users meeting this criteria. Example: &quot(objectClass=posixAccount)" or "(&(objectClass=person)(memberOf=CN=Workers,CN=Users,DC=myDomain,DC=com))"' => 'Limitar o acesso aos utilizadores que cumpram esse critério. Exemplo: &quot(objectClass=posixAccount)" or "(&(objectClass=person)(memberOf=CN=Workers,CN=Users,DC=myDomain,DC=com))"',
    'Save' => 'Salvar',
    'Status: Error! (Message: {message})' => 'Status: Erro! (Mensagem: {message})',
    'Status: OK! ({userCount} Users)' => 'Status: OK! ({userCount} Usuários)',
    'The default base DN used for searching for accounts.' => 'A base padrão DN utilizado para a busca de contas.',
    'The default credentials password (used only with username above).' => 'A senha padrão (usada apenas com nome de usuário acima).',
    'The default credentials username. Some servers require that this be in DN form. This must be given in DN form if the LDAP server requires a DN to bind and binding should be possible with simple usernames.' => 'O Username  padrão. Alguns servidores exigem que este seja em forma DN. Isso deve ser dada de forma DN se o servidor LDAP requer uma DN para ligar e deve ser possível com usernames simples.',
];