207 lines
4.7 KiB
C++
207 lines
4.7 KiB
C++
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
|
|
//
|
|
// This file is part of the VNC system.
|
|
//
|
|
// The VNC system is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
// USA.
|
|
//
|
|
// TightVNC distribution homepage on the Web: http://www.tightvnc.com/
|
|
//
|
|
// If the source code for the VNC system is not available from the place
|
|
// whence you received this file, check http://www.uk.research.att.com/vnc or contact
|
|
// the authors on vnc@uk.research.att.com for information on obtaining it.
|
|
|
|
|
|
// vncRegion implementation
|
|
// This implementation uses the system region handling routines
|
|
// to speed things up and give the best results
|
|
|
|
#include "stdhdrs.h"
|
|
|
|
// Header
|
|
|
|
#include "vncRegion.h"
|
|
|
|
// Implementation
|
|
|
|
vncRegion::vncRegion()
|
|
{
|
|
region = NULL;
|
|
}
|
|
|
|
vncRegion::~vncRegion()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void vncRegion::AddRect(const RECT &new_rect)
|
|
{
|
|
HRGN newregion;
|
|
|
|
if (region == NULL)
|
|
{
|
|
// Create the region and set it to contain this rectangle
|
|
region = CreateRectRgnIndirect(&new_rect);
|
|
}
|
|
else
|
|
{
|
|
// Create a new region containing the appropriate rectangle
|
|
newregion = CreateRectRgnIndirect(&new_rect);
|
|
|
|
// Merge it into the existing region
|
|
if (CombineRgn(region, region, newregion, RGN_OR) == NULLREGION)
|
|
Clear();
|
|
|
|
// Now delete the temporary region
|
|
DeleteObject(newregion);
|
|
}
|
|
}
|
|
|
|
void vncRegion::AddRect(RECT R, int xoffset, int yoffset)
|
|
{
|
|
R.left += xoffset;
|
|
R.top += yoffset;
|
|
R.right += xoffset;
|
|
R.bottom += yoffset;
|
|
AddRect(R);
|
|
}
|
|
|
|
void vncRegion::SubtractRect(RECT &new_rect)
|
|
{
|
|
HRGN newregion;
|
|
|
|
if (region == NULL)
|
|
return;
|
|
|
|
// Create a new region containing the appropriate rectangle
|
|
newregion = CreateRectRgnIndirect(&new_rect);
|
|
|
|
// Remove it from the existing region
|
|
if (CombineRgn(region, region, newregion, RGN_DIFF) == NULLREGION)
|
|
Clear();
|
|
|
|
// Now delete the temporary region
|
|
DeleteObject(newregion);
|
|
}
|
|
|
|
void vncRegion::Clear()
|
|
{
|
|
// Set the region to be empty
|
|
if (region != NULL)
|
|
{
|
|
DeleteObject(region);
|
|
region = NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
vncRegion::Combine(vncRegion &rgn)
|
|
{
|
|
if (rgn.region == NULL)
|
|
return;
|
|
if (region == NULL)
|
|
{
|
|
region = CreateRectRgn(0, 0, 0, 0);
|
|
if (region == NULL)
|
|
return;
|
|
|
|
// Copy the specified region into this one...
|
|
if (CombineRgn(region, rgn.region, 0, RGN_COPY) == NULLREGION)
|
|
Clear();
|
|
return;
|
|
}
|
|
|
|
// Otherwise, combine the two
|
|
if (CombineRgn(region, region, rgn.region, RGN_OR) == NULLREGION)
|
|
Clear();
|
|
}
|
|
|
|
void
|
|
vncRegion::Intersect(vncRegion &rgn)
|
|
{
|
|
if (rgn.region == NULL)
|
|
return;
|
|
if (region == NULL)
|
|
return;
|
|
|
|
// Otherwise, intersect the two
|
|
if (CombineRgn(region, region, rgn.region, RGN_AND) == NULLREGION)
|
|
Clear();
|
|
}
|
|
|
|
void
|
|
vncRegion::Subtract(vncRegion &rgn)
|
|
{
|
|
if (rgn.region == NULL)
|
|
return;
|
|
if (region == NULL)
|
|
return;
|
|
|
|
// Otherwise, intersect the two
|
|
if (CombineRgn(region, region, rgn.region, RGN_DIFF) == NULLREGION)
|
|
Clear();
|
|
}
|
|
|
|
|
|
|
|
// Return all the rectangles
|
|
BOOL vncRegion::Rectangles(rectlist &rects)
|
|
{
|
|
int buffsize;
|
|
DWORD x;
|
|
RGNDATA *buff;
|
|
|
|
// If the region is empty then return empty rectangle list
|
|
if (region == NULL)
|
|
return FALSE;
|
|
|
|
// Get the size of buffer required
|
|
buffsize = GetRegionData(region, NULL, 0);
|
|
buff = (RGNDATA *) new BYTE [buffsize];
|
|
if (buff == NULL)
|
|
return FALSE;
|
|
|
|
// Now get the region data
|
|
if (GetRegionData(region, buffsize, buff))
|
|
{
|
|
for (x=0; x<(buff->rdh.nCount); x++)
|
|
{
|
|
// Obtain the rectangles from the list
|
|
RECT *rect = (RECT *) (((BYTE *) buff) + sizeof(RGNDATAHEADER) + x * sizeof(RECT));
|
|
rects.push_front(*rect);
|
|
}
|
|
}
|
|
|
|
// Delete the temporary buffer
|
|
delete [] buff;
|
|
|
|
// Return whether there are any rects!
|
|
return !rects.empty();
|
|
}
|
|
|
|
// Return rectangles clipped to a certain area
|
|
BOOL vncRegion::Rectangles(rectlist &rects, RECT &cliprect)
|
|
{
|
|
vncRegion cliprgn;
|
|
|
|
// Create the clip-region
|
|
cliprgn.AddRect(cliprect);
|
|
|
|
// Calculate the intersection with this region
|
|
cliprgn.Intersect(*this);
|
|
|
|
return cliprgn.Rectangles(rects);
|
|
}
|