// 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); }