Vec2f CSMViewport::translateWindowViewportAbs(Real32 rX,
                                              Real32 rY) const
{
    Viewport *pViewport = this->getViewport(0);

    if(pViewport != NULL)
    {
        return Vec2f(rX - pViewport->calcPixelLeft  (),
                     rY - pViewport->calcPixelBottom());
    }
    else
    {
        return Vec2f(rX, rY);
    }

}
bool CSMViewport::pointInside(Real32 x, Real32 y) const
{
    if(_vViewports.size() == 0)
        return false;

    Viewport *pPort = _vViewports[0];

    if(pPort == NULL)
        return false;

    if(x >= pPort->calcPixelLeft  () &&
       x <= pPort->calcPixelRight () &&
       y >= pPort->calcPixelBottom() &&
       y <= pPort->calcPixelTop   ()  )
    {
        return true;
    }

    return false;
}
void MultiDisplayWindow::serverRender(Window           *window,
                                      UInt32            id,
                                      RenderActionBase *action)
{
    TileCameraDecoratorUnrecPtr deco;
    ViewportUnrecPtr serverPort;
    Viewport * clientPort;
    UInt32 sv,cv;
    Int32 l,r,t,b;
    Int32 cleft,cright,ctop,cbottom;

    if(!getHServers())
    {
        setHServers(getMFServers()->size32());
    }
    if(!getVServers())
    {
        setVServers(1);
    }

    UInt32 row   =id/getHServers();
    UInt32 column=id%getHServers();

    // calculate width and height from local width and height
    UInt32 width  = window->getWidth() ;
    UInt32 height = window->getHeight();

    if(getWidth()==0)
    {
        setWidth( width*getHServers() );
    }
    if(getHeight()==0)
    {
        setHeight( height*getVServers() );
    }

    Int32 left   = column * width  - column * getXOverlap();
    Int32 bottom = row    * height - row    * getYOverlap();
    Int32 right  = left   + width  - 1;
    Int32 top    = bottom + height - 1;
    Real64 scaleCWidth  =
        ((width - getXOverlap()) * (getHServers() - 1) + width) /
        float(getWidth());
    Real64 scaleCHeight =
        ((height - getYOverlap())* (getVServers() - 1) + height)/
        float(getHeight());

    // duplicate viewports
    for(cv=0,sv=0;cv<getMFPort()->size();cv++)
    {
        clientPort = getPort(cv);

        cleft   = Int32(clientPort->calcPixelLeft()      * scaleCWidth)   ;
        cbottom = Int32(clientPort->calcPixelBottom()    * scaleCHeight)  ;
        cright  = Int32((clientPort->calcPixelRight()+1) * scaleCWidth) -1;
        ctop    = Int32((clientPort->calcPixelTop()+1)   * scaleCHeight)-1;

        if(cright  < left   ||
           cleft   > right  ||
           ctop    < bottom ||
           cbottom > top      )
        {
            // invisible on this server screen
            continue;
        }

        // calculate overlapping viewport
        l = osgMax(cleft  ,left  ) - left;
        b = osgMax(cbottom,bottom) - bottom;
        r = osgMin(cright ,right ) - left;
        t = osgMin(ctop   ,top   ) - bottom;

        if(window->getMFPort()->size() <= sv)
        {
            serverPort = dynamic_pointer_cast<Viewport>(
                clientPort->shallowCopy());

            deco = TileCameraDecorator::create();

            window->addPort(serverPort);

            serverPort->setCamera(deco);
        }
        else
        {
            serverPort = window->getPort(sv);

            deco = dynamic_cast<TileCameraDecorator *>(
                serverPort->getCamera());

            if(window->getPort(sv)->getType() != clientPort->getType())
            {
                // there is a viewport with the wrong type
                serverPort =
                    dynamic_pointer_cast<Viewport>(clientPort->shallowCopy());

                window->replacePort(sv, 
                                    serverPort);//[sv] = serverPort;
                serverPort->setCamera(deco);
            }
            else
            {
                deco = dynamic_cast<TileCameraDecorator *>(
                    serverPort->getCamera());
            }
        }

        // update changed viewport fields
        updateViewport(serverPort, clientPort);

        // set viewport size
        serverPort->setSize(Real32(l),Real32(b),Real32(r),Real32(t));

        // use pixel even if pixel = 1
        if(serverPort->getLeft() == 1.0)
            serverPort->setLeft(1.0001f);

        if(serverPort->getRight() == 1.0)
            serverPort->setRight(1.0001f);

        if(serverPort->getTop() == 1.0)
            serverPort->setTop(1.0001f);

        if(serverPort->getBottom() == 1.0)
            serverPort->setBottom(1.0001f);

        // calculate tile parameters
        deco->setFullWidth ( cright-cleft );
        deco->setFullHeight( ctop-cbottom );
        deco->setSize( ( l+left-cleft     ) / float( cright-cleft ),
                       ( b+bottom-cbottom ) / float( ctop-cbottom ),
                       ( r+left-cleft     ) / float( cright-cleft ),
                       ( t+bottom-cbottom ) / float( ctop-cbottom ) );
        deco->setDecoratee( clientPort->getCamera() );

        sv++;
    }

    // remove unused ports
    while(window->getMFPort()->size()>sv)
    {
        window->subPort(sv);
    }

    Inherited::serverRender(window,id,action);
}
void SortLastWindow::serverRender(Window           *serverWindow,
                                  UInt32            id,
                                  RenderActionBase *action      )
{
    ViewportUnrecPtr  serverPort  = NULL;
    Viewport         *clientPort  = NULL;
    UInt32            sv          = 0;
    UInt32            cv          = 0;

    // duplicate viewports
    for(cv = 0, sv = 0; cv < getMFPort()->size(); ++cv)
    {
        clientPort = getPort(cv);

        if(serverWindow->getMFPort()->size() <= sv)
        {
            // create new port
            serverPort = Viewport::create();

            serverWindow->addPort(serverPort);
        }
        else
        {
            serverPort = serverWindow->getPort(sv);
        }

        // duplicate values

        if(getWidth() && getHeight())
        {
           serverPort->setSize(clientPort->calcPixelLeft  (),
                               clientPort->calcPixelBottom(),
                               clientPort->calcPixelRight (),
                               clientPort->calcPixelTop   ());
        }
        else
        {
            serverPort->setSize(0,0,0,0); 
        }
  
        serverPort->setCamera    (clientPort->getCamera    ());
        serverPort->setRoot      (clientPort->getRoot      ());
        serverPort->setBackground(clientPort->getBackground());

        // ignore statistics foreground
        serverPort->clearForegrounds();

        for(UInt32 f = 0 ; f < serverPort->getMFForegrounds()->size(); ++f)
        {
            Foreground *fg = clientPort->getForegrounds(f);

            StatisticsForeground *sfg = 
                dynamic_cast<StatisticsForeground *>(fg);

            if(sfg == NULL)
            {
                serverPort->addForeground(fg);
            }
        }

        serverPort->setTravMask(clientPort->getTravMask());

        sv++;
    }

    // remove unused ports
    while(serverWindow->getMFPort()->size() > sv)
    {
        serverWindow->subPort(sv);
    }

    // setup visible nodes
    setupNodes(id);

    // render the viewports
    serverWindow->activate();
    serverWindow->frameInit();

    action->setWindow(serverWindow);

    if(getComposer() != NULL)
        getComposer()->startFrame();

    for(sv = 0; sv < serverWindow->getMFPort()->size(); ++sv)
    {
        Viewport *vp = serverWindow->getPort(sv);

        if(getComposer() != NULL)
            getComposer()->startViewport(vp);

        // render
        vp->render(action);

        // compose single viewport
        if(getComposer() != NULL)
            getComposer()->composeViewport(vp);
    }

    // compose whole window
    if(getComposer() != NULL)
        getComposer()->composeWindow();
}