diff --git a/SOURCES/tigervnc-region-handling.patch b/SOURCES/tigervnc-region-handling.patch new file mode 100644 index 0000000..2c17d24 --- /dev/null +++ b/SOURCES/tigervnc-region-handling.patch @@ -0,0 +1,3365 @@ +diff --git a/BUILDING.txt b/BUILDING.txt +index 9449810..99c8698 100644 +--- a/BUILDING.txt ++++ b/BUILDING.txt +@@ -11,6 +11,8 @@ Build Requirements (All Systems) + + -- zlib + ++-- pixman ++ + -- FLTK 1.3.3 or later + + -- If building TLS support: +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 94ec2ef..dfdf197 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -134,6 +134,9 @@ endif() + # Check for zlib + find_package(ZLIB REQUIRED) + ++# Check for pixman ++find_package(Pixman REQUIRED) ++ + # Check for gettext + option(ENABLE_NLS "Enable translation of program messages" ON) + if(ENABLE_NLS) +diff --git a/cmake/Modules/FindPixman.cmake b/cmake/Modules/FindPixman.cmake +new file mode 100644 +index 0000000..7bfca77 +--- /dev/null ++++ b/cmake/Modules/FindPixman.cmake +@@ -0,0 +1,40 @@ ++# - Find Pixman ++# Find the Pixman libraries ++# ++# This module defines the following variables: ++# PIXMAN_FOUND - true if PIXMAN_INCLUDE_DIR & PIXMAN_LIBRARY are found ++# PIXMAN_LIBRARIES - Set when PIXMAN_LIBRARY is found ++# PIXMAN_INCLUDE_DIRS - Set when PIXMAN_INCLUDE_DIR is found ++# ++# PIXMAN_INCLUDE_DIR - where to find pixman.h, etc. ++# PIXMAN_LIBRARY - the Pixman library ++# ++ ++#============================================================================= ++# Copyright 2013 Marc-Andre Moreau ++# ++# Licensed under the Apache License, Version 2.0 (the "License"); ++# you may not use this file except in compliance with the License. ++# You may obtain a copy of the License at ++# ++# http://www.apache.org/licenses/LICENSE-2.0 ++# ++# Unless required by applicable law or agreed to in writing, software ++# distributed under the License is distributed on an "AS IS" BASIS, ++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++# See the License for the specific language governing permissions and ++# limitations under the License. ++#============================================================================= ++ ++find_path(PIXMAN_INCLUDE_DIR NAMES pixman.h PATH_SUFFIXES pixman-1) ++ ++find_library(PIXMAN_LIBRARY NAMES pixman-1) ++ ++find_package_handle_standard_args(pixman-1 DEFAULT_MSG PIXMAN_LIBRARY PIXMAN_INCLUDE_DIR) ++ ++if(PIXMAN-1_FOUND) ++ set(PIXMAN_LIBRARIES ${PIXMAN_LIBRARY}) ++ set(PIXMAN_INCLUDE_DIRS ${PIXMAN_INCLUDE_DIR}) ++endif() ++ ++mark_as_advanced(PIXMAN_INCLUDE_DIR PIXMAN_LIBRARY) +diff --git a/cmake/StaticBuild.cmake b/cmake/StaticBuild.cmake +index 6db0e14..db30c5c 100644 +--- a/cmake/StaticBuild.cmake ++++ b/cmake/StaticBuild.cmake +@@ -19,6 +19,7 @@ if(BUILD_STATIC) + set(BUILD_STATIC_GCC 1) + + set(JPEG_LIBRARIES "-Wl,-Bstatic -ljpeg -Wl,-Bdynamic") ++ set(PIXMAN_LIBRARY "-Wl,-Bstatic -lpixman-1 -Wl,-Bdynamic") + + if(WIN32) + set(ZLIB_LIBRARIES "-Wl,-Bstatic -lz -Wl,-Bdynamic") +@@ -133,7 +134,7 @@ if(BUILD_STATIC_GCC) + # these things again + set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -lmingw32 -lgcc_eh -lgcc -lmoldname -lmingwex -lmsvcrt") + else() +- set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -lgcc -lgcc_eh -lc") ++ set(STATIC_BASE_LIBRARIES "${STATIC_BASE_LIBRARIES} -lm -lgcc -lgcc_eh -lc") + endif() + set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} ${STATIC_BASE_LIBRARIES}") + endif() +diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt +index e4489f6..6fd1e10 100644 +--- a/common/CMakeLists.txt ++++ b/common/CMakeLists.txt +@@ -1,7 +1,6 @@ + add_subdirectory(os) + add_subdirectory(rdr) + add_subdirectory(network) +-add_subdirectory(Xregion) + add_subdirectory(rfb) + + # For any convenience libraries that are linked into libvnc.so, we need to +@@ -10,6 +9,6 @@ add_subdirectory(rfb) + # is passed (additionally, libvnc is not used on Windows.) + + if(NOT WIN32) +- set_target_properties(os rdr network Xregion rfb ++ set_target_properties(os rdr network rfb + PROPERTIES COMPILE_FLAGS -fPIC) + endif() +diff --git a/common/Xregion/CMakeLists.txt b/common/Xregion/CMakeLists.txt +deleted file mode 100644 +index 40ca97e..0000000 +--- a/common/Xregion/CMakeLists.txt ++++ /dev/null +@@ -1,6 +0,0 @@ +-add_library(Xregion STATIC +- Region.c) +- +-if(UNIX) +- libtool_create_control_file(Xregion) +-endif() +diff --git a/common/Xregion/Region.c b/common/Xregion/Region.c +deleted file mode 100644 +index 1acf581..0000000 +--- a/common/Xregion/Region.c ++++ /dev/null +@@ -1,1612 +0,0 @@ +-/************************************************************************ +- +-Copyright 1987, 1988, 1998 The Open Group +- +-Permission to use, copy, modify, distribute, and sell this software and its +-documentation for any purpose is hereby granted without fee, provided that +-the above copyright notice appear in all copies and that both that +-copyright notice and this permission notice appear in supporting +-documentation. +- +-The above copyright notice and this permission notice shall be included in +-all copies or substantial portions of the Software. +- +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +- +-Except as contained in this notice, the name of The Open Group shall not be +-used in advertising or otherwise to promote the sale, use or other dealings +-in this Software without prior written authorization from The Open Group. +- +- +-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. +- +- All Rights Reserved +- +-Permission to use, copy, modify, and distribute this software and its +-documentation for any purpose and without fee is hereby granted, +-provided that the above copyright notice appear in all copies and that +-both that copyright notice and this permission notice appear in +-supporting documentation, and that the name of Digital not be +-used in advertising or publicity pertaining to distribution of the +-software without specific, written prior permission. +- +-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +-SOFTWARE. +- +-************************************************************************/ +-/* +- * The functions in this file implement the Region abstraction, similar to one +- * used in the X11 sample server. A Region is simply an area, as the name +- * implies, and is implemented as a "y-x-banded" array of rectangles. To +- * explain: Each Region is made up of a certain number of rectangles sorted +- * by y coordinate first, and then by x coordinate. +- * +- * Furthermore, the rectangles are banded such that every rectangle with a +- * given upper-left y coordinate (y1) will have the same lower-right y +- * coordinate (y2) and vice versa. If a rectangle has scanlines in a band, it +- * will span the entire vertical distance of the band. This means that some +- * areas that could be merged into a taller rectangle will be represented as +- * several shorter rectangles to account for shorter rectangles to its left +- * or right but within its "vertical scope". +- * +- * An added constraint on the rectangles is that they must cover as much +- * horizontal area as possible. E.g. no two rectangles in a band are allowed +- * to touch. +- * +- * Whenever possible, bands will be merged together to cover a greater vertical +- * distance (and thus reduce the number of rectangles). Two bands can be merged +- * only if the bottom of one touches the top of the other and they have +- * rectangles in the same places (of the same width, of course). This maintains +- * the y-x-banding that's so nice to have... +- */ +- +-#include +- +-#include "Xlibint.h" +-#include "Xutil.h" +-#include "Xregion.h" +- +-#ifndef min +-#define min(a,b) (((a) < (b)) ? (a) : (b)) +-#endif +-#ifndef max +-#define max(a,b) (((a) > (b)) ? (a) : (b)) +-#endif +- +-#ifdef DEBUG +-#include +-#define assert(expr) {if (!(expr)) fprintf(stderr,\ +-"Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__); } +-#else +-#define assert(expr) +-#endif +- +-typedef int (*overlapProcp)( +- register Region pReg, +- register BoxPtr r1, +- BoxPtr r1End, +- register BoxPtr r2, +- BoxPtr r2End, +- short y1, +- short y2); +- +-typedef int (*nonOverlapProcp)( +- register Region pReg, +- register BoxPtr r, +- BoxPtr rEnd, +- register short y1, +- register short y2); +- +-static void miRegionOp( +- register Region newReg, /* Place to store result */ +- Region reg1, /* First region in operation */ +- Region reg2, /* 2d region in operation */ +- int (*overlapFunc)( +- register Region pReg, +- register BoxPtr r1, +- BoxPtr r1End, +- register BoxPtr r2, +- BoxPtr r2End, +- short y1, +- short y2), /* Function to call for over- +- * lapping bands */ +- int (*nonOverlap1Func)( +- register Region pReg, +- register BoxPtr r, +- BoxPtr rEnd, +- register short y1, +- register short y2), /* Function to call for non- +- * overlapping bands in region +- * 1 */ +- int (*nonOverlap2Func)( +- register Region pReg, +- register BoxPtr r, +- BoxPtr rEnd, +- register short y1, +- register short y2)); /* Function to call for non- +- * overlapping bands in region +- * 2 */ +- +- +-/* Create a new empty region */ +-Region +-XCreateRegion(void) +-{ +- Region temp; +- +- if (! (temp = Xmalloc(sizeof( REGION )))) +- return (Region) NULL; +- if (! (temp->rects = Xmalloc(sizeof( BOX )))) { +- Xfree(temp); +- return (Region) NULL; +- } +- temp->numRects = 0; +- temp->extents.x1 = 0; +- temp->extents.y1 = 0; +- temp->extents.x2 = 0; +- temp->extents.y2 = 0; +- temp->size = 1; +- return( temp ); +-} +- +-int +-XClipBox( +- Region r, +- XRectangle *rect) +-{ +- rect->x = r->extents.x1; +- rect->y = r->extents.y1; +- rect->width = r->extents.x2 - r->extents.x1; +- rect->height = r->extents.y2 - r->extents.y1; +- return 1; +-} +- +-int +-XUnionRectWithRegion( +- register XRectangle *rect, +- Region source, Region dest) +-{ +- REGION region; +- +- if (!rect->width || !rect->height) +- return 0; +- region.rects = ®ion.extents; +- region.numRects = 1; +- region.extents.x1 = rect->x; +- region.extents.y1 = rect->y; +- region.extents.x2 = rect->x + rect->width; +- region.extents.y2 = rect->y + rect->height; +- region.size = 1; +- +- return XUnionRegion(®ion, source, dest); +-} +- +-/*- +- *----------------------------------------------------------------------- +- * miSetExtents -- +- * Reset the extents of a region to what they should be. Called by +- * miSubtract and miIntersect b/c they can't figure it out along the +- * way or do so easily, as miUnion can. +- * +- * Results: +- * None. +- * +- * Side Effects: +- * The region's 'extents' structure is overwritten. +- * +- *----------------------------------------------------------------------- +- */ +-static void +-miSetExtents ( +- Region pReg) +-{ +- register BoxPtr pBox, +- pBoxEnd, +- pExtents; +- +- if (pReg->numRects == 0) +- { +- pReg->extents.x1 = 0; +- pReg->extents.y1 = 0; +- pReg->extents.x2 = 0; +- pReg->extents.y2 = 0; +- return; +- } +- +- pExtents = &pReg->extents; +- pBox = pReg->rects; +- pBoxEnd = &pBox[pReg->numRects - 1]; +- +- /* +- * Since pBox is the first rectangle in the region, it must have the +- * smallest y1 and since pBoxEnd is the last rectangle in the region, +- * it must have the largest y2, because of banding. Initialize x1 and +- * x2 from pBox and pBoxEnd, resp., as good things to initialize them +- * to... +- */ +- pExtents->x1 = pBox->x1; +- pExtents->y1 = pBox->y1; +- pExtents->x2 = pBoxEnd->x2; +- pExtents->y2 = pBoxEnd->y2; +- +- assert(pExtents->y1 < pExtents->y2); +- while (pBox <= pBoxEnd) +- { +- if (pBox->x1 < pExtents->x1) +- { +- pExtents->x1 = pBox->x1; +- } +- if (pBox->x2 > pExtents->x2) +- { +- pExtents->x2 = pBox->x2; +- } +- pBox++; +- } +- assert(pExtents->x1 < pExtents->x2); +-} +- +-#if 0 +-int +-XSetRegion( +- Display *dpy, +- GC gc, +- register Region r) +-{ +- register int i; +- register XRectangle *xr, *pr; +- register BOX *pb; +- unsigned long total; +- +- LockDisplay (dpy); +- total = r->numRects * sizeof (XRectangle); +- if ((xr = (XRectangle *) _XAllocTemp(dpy, total))) { +- for (pr = xr, pb = r->rects, i = r->numRects; --i >= 0; pr++, pb++) { +- pr->x = pb->x1; +- pr->y = pb->y1; +- pr->width = pb->x2 - pb->x1; +- pr->height = pb->y2 - pb->y1; +- } +- } +- if (xr || !r->numRects) +- _XSetClipRectangles(dpy, gc, 0, 0, xr, r->numRects, YXBanded); +- if (xr) +- _XFreeTemp(dpy, (char *)xr, total); +- UnlockDisplay(dpy); +- SyncHandle(); +- return 1; +-} +-#endif +- +-int +-XDestroyRegion( +- Region r) +-{ +- Xfree( (char *) r->rects ); +- Xfree( (char *) r ); +- return 1; +-} +- +- +-/* TranslateRegion(pRegion, x, y) +- translates in place +- added by raymond +-*/ +- +-int +-XOffsetRegion( +- register Region pRegion, +- register int x, +- register int y) +-{ +- register int nbox; +- register BOX *pbox; +- +- pbox = pRegion->rects; +- nbox = pRegion->numRects; +- +- while(nbox--) +- { +- pbox->x1 += x; +- pbox->x2 += x; +- pbox->y1 += y; +- pbox->y2 += y; +- pbox++; +- } +- pRegion->extents.x1 += x; +- pRegion->extents.x2 += x; +- pRegion->extents.y1 += y; +- pRegion->extents.y2 += y; +- return 1; +-} +- +-/* +- Utility procedure Compress: +- Replace r by the region r', where +- p in r' iff (Quantifer m <= dx) (p + m in r), and +- Quantifier is Exists if grow is TRUE, For all if grow is FALSE, and +- (x,y) + m = (x+m,y) if xdir is TRUE; (x,y+m) if xdir is FALSE. +- +- Thus, if xdir is TRUE and grow is FALSE, r is replaced by the region +- of all points p such that p and the next dx points on the same +- horizontal scan line are all in r. We do this using by noting +- that p is the head of a run of length 2^i + k iff p is the head +- of a run of length 2^i and p+2^i is the head of a run of length +- k. Thus, the loop invariant: s contains the region corresponding +- to the runs of length shift. r contains the region corresponding +- to the runs of length 1 + dxo & (shift-1), where dxo is the original +- value of dx. dx = dxo & ~(shift-1). As parameters, s and t are +- scratch regions, so that we don't have to allocate them on every +- call. +-*/ +- +-#define ZOpRegion(a,b,c) if (grow) XUnionRegion(a,b,c); \ +- else XIntersectRegion(a,b,c) +-#define ZShiftRegion(a,b) if (xdir) XOffsetRegion(a,b,0); \ +- else XOffsetRegion(a,0,b) +-#define ZCopyRegion(a,b) XUnionRegion(a,a,b) +- +-static void +-Compress( +- Region r, Region s, Region t, +- register unsigned dx, +- register int xdir, register int grow) +-{ +- register unsigned shift = 1; +- +- ZCopyRegion(r, s); +- while (dx) { +- if (dx & shift) { +- ZShiftRegion(r, -(int)shift); +- ZOpRegion(r, s, r); +- dx -= shift; +- if (!dx) break; +- } +- ZCopyRegion(s, t); +- ZShiftRegion(s, -(int)shift); +- ZOpRegion(s, t, s); +- shift <<= 1; +- } +-} +- +-#undef ZOpRegion +-#undef ZShiftRegion +-#undef ZCopyRegion +- +-int +-XShrinkRegion( +- Region r, +- int dx, int dy) +-{ +- Region s, t; +- int grow; +- +- if (!dx && !dy) return 0; +- if (! (s = XCreateRegion()) ) +- return 0; +- if (! (t = XCreateRegion()) ) { +- XDestroyRegion(s); +- return 0; +- } +- if ((grow = (dx < 0))) dx = -dx; +- if (dx) Compress(r, s, t, (unsigned) 2*dx, TRUE, grow); +- if ((grow = (dy < 0))) dy = -dy; +- if (dy) Compress(r, s, t, (unsigned) 2*dy, FALSE, grow); +- XOffsetRegion(r, dx, dy); +- XDestroyRegion(s); +- XDestroyRegion(t); +- return 0; +-} +- +- +-/*====================================================================== +- * Region Intersection +- *====================================================================*/ +-/*- +- *----------------------------------------------------------------------- +- * miIntersectO -- +- * Handle an overlapping band for miIntersect. +- * +- * Results: +- * None. +- * +- * Side Effects: +- * Rectangles may be added to the region. +- * +- *----------------------------------------------------------------------- +- */ +-/* static void*/ +-static int +-miIntersectO ( +- register Region pReg, +- register BoxPtr r1, +- BoxPtr r1End, +- register BoxPtr r2, +- BoxPtr r2End, +- short y1, +- short y2) +-{ +- register short x1; +- register short x2; +- register BoxPtr pNextRect; +- +- pNextRect = &pReg->rects[pReg->numRects]; +- +- while ((r1 != r1End) && (r2 != r2End)) +- { +- x1 = max(r1->x1,r2->x1); +- x2 = min(r1->x2,r2->x2); +- +- /* +- * If there's any overlap between the two rectangles, add that +- * overlap to the new region. +- * There's no need to check for subsumption because the only way +- * such a need could arise is if some region has two rectangles +- * right next to each other. Since that should never happen... +- */ +- if (x1 < x2) +- { +- assert(y1rects); +- pNextRect->x1 = x1; +- pNextRect->y1 = y1; +- pNextRect->x2 = x2; +- pNextRect->y2 = y2; +- pReg->numRects += 1; +- pNextRect++; +- assert(pReg->numRects <= pReg->size); +- } +- +- /* +- * Need to advance the pointers. Shift the one that extends +- * to the right the least, since the other still has a chance to +- * overlap with that region's next rectangle, if you see what I mean. +- */ +- if (r1->x2 < r2->x2) +- { +- r1++; +- } +- else if (r2->x2 < r1->x2) +- { +- r2++; +- } +- else +- { +- r1++; +- r2++; +- } +- } +- return 0; /* lint */ +-} +- +-int +-XIntersectRegion( +- Region reg1, +- Region reg2, /* source regions */ +- register Region newReg) /* destination Region */ +-{ +- /* check for trivial reject */ +- if ( (!(reg1->numRects)) || (!(reg2->numRects)) || +- (!EXTENTCHECK(®1->extents, ®2->extents))) +- newReg->numRects = 0; +- else +- miRegionOp (newReg, reg1, reg2, +- miIntersectO, NULL, NULL); +- +- /* +- * Can't alter newReg's extents before we call miRegionOp because +- * it might be one of the source regions and miRegionOp depends +- * on the extents of those regions being the same. Besides, this +- * way there's no checking against rectangles that will be nuked +- * due to coalescing, so we have to examine fewer rectangles. +- */ +- miSetExtents(newReg); +- return 1; +-} +- +-static int +-miRegionCopy( +- register Region dstrgn, +- register Region rgn) +- +-{ +- if (dstrgn != rgn) /* don't want to copy to itself */ +- { +- if (dstrgn->size < rgn->numRects) +- { +- if (dstrgn->rects) +- { +- BOX *prevRects = dstrgn->rects; +- +- dstrgn->rects = Xrealloc(dstrgn->rects, +- rgn->numRects * (sizeof(BOX))); +- if (! dstrgn->rects) { +- Xfree(prevRects); +- dstrgn->size = 0; +- return 0; +- } +- } +- dstrgn->size = rgn->numRects; +- } +- dstrgn->numRects = rgn->numRects; +- dstrgn->extents.x1 = rgn->extents.x1; +- dstrgn->extents.y1 = rgn->extents.y1; +- dstrgn->extents.x2 = rgn->extents.x2; +- dstrgn->extents.y2 = rgn->extents.y2; +- +- memcpy((char *) dstrgn->rects, (char *) rgn->rects, +- (int) (rgn->numRects * sizeof(BOX))); +- } +- return 1; +-} +- +-/*====================================================================== +- * Generic Region Operator +- *====================================================================*/ +- +-/*- +- *----------------------------------------------------------------------- +- * miCoalesce -- +- * Attempt to merge the boxes in the current band with those in the +- * previous one. Used only by miRegionOp. +- * +- * Results: +- * The new index for the previous band. +- * +- * Side Effects: +- * If coalescing takes place: +- * - rectangles in the previous band will have their y2 fields +- * altered. +- * - pReg->numRects will be decreased. +- * +- *----------------------------------------------------------------------- +- */ +-/* static int*/ +-static int +-miCoalesce( +- register Region pReg, /* Region to coalesce */ +- int prevStart, /* Index of start of previous band */ +- int curStart) /* Index of start of current band */ +-{ +- register BoxPtr pPrevBox; /* Current box in previous band */ +- register BoxPtr pCurBox; /* Current box in current band */ +- register BoxPtr pRegEnd; /* End of region */ +- int curNumRects; /* Number of rectangles in current +- * band */ +- int prevNumRects; /* Number of rectangles in previous +- * band */ +- int bandY1; /* Y1 coordinate for current band */ +- +- pRegEnd = &pReg->rects[pReg->numRects]; +- +- pPrevBox = &pReg->rects[prevStart]; +- prevNumRects = curStart - prevStart; +- +- /* +- * Figure out how many rectangles are in the current band. Have to do +- * this because multiple bands could have been added in miRegionOp +- * at the end when one region has been exhausted. +- */ +- pCurBox = &pReg->rects[curStart]; +- bandY1 = pCurBox->y1; +- for (curNumRects = 0; +- (pCurBox != pRegEnd) && (pCurBox->y1 == bandY1); +- curNumRects++) +- { +- pCurBox++; +- } +- +- if (pCurBox != pRegEnd) +- { +- /* +- * If more than one band was added, we have to find the start +- * of the last band added so the next coalescing job can start +- * at the right place... (given when multiple bands are added, +- * this may be pointless -- see above). +- */ +- pRegEnd--; +- while (pRegEnd[-1].y1 == pRegEnd->y1) +- { +- pRegEnd--; +- } +- curStart = pRegEnd - pReg->rects; +- pRegEnd = pReg->rects + pReg->numRects; +- } +- +- if ((curNumRects == prevNumRects) && (curNumRects != 0)) { +- pCurBox -= curNumRects; +- /* +- * The bands may only be coalesced if the bottom of the previous +- * matches the top scanline of the current. +- */ +- if (pPrevBox->y2 == pCurBox->y1) +- { +- /* +- * Make sure the bands have boxes in the same places. This +- * assumes that boxes have been added in such a way that they +- * cover the most area possible. I.e. two boxes in a band must +- * have some horizontal space between them. +- */ +- do +- { +- if ((pPrevBox->x1 != pCurBox->x1) || +- (pPrevBox->x2 != pCurBox->x2)) +- { +- /* +- * The bands don't line up so they can't be coalesced. +- */ +- return (curStart); +- } +- pPrevBox++; +- pCurBox++; +- prevNumRects -= 1; +- } while (prevNumRects != 0); +- +- pReg->numRects -= curNumRects; +- pCurBox -= curNumRects; +- pPrevBox -= curNumRects; +- +- /* +- * The bands may be merged, so set the bottom y of each box +- * in the previous band to that of the corresponding box in +- * the current band. +- */ +- do +- { +- pPrevBox->y2 = pCurBox->y2; +- pPrevBox++; +- pCurBox++; +- curNumRects -= 1; +- } while (curNumRects != 0); +- +- /* +- * If only one band was added to the region, we have to backup +- * curStart to the start of the previous band. +- * +- * If more than one band was added to the region, copy the +- * other bands down. The assumption here is that the other bands +- * came from the same region as the current one and no further +- * coalescing can be done on them since it's all been done +- * already... curStart is already in the right place. +- */ +- if (pCurBox == pRegEnd) +- { +- curStart = prevStart; +- } +- else +- { +- do +- { +- *pPrevBox++ = *pCurBox++; +- } while (pCurBox != pRegEnd); +- } +- +- } +- } +- return (curStart); +-} +- +-/*- +- *----------------------------------------------------------------------- +- * miRegionOp -- +- * Apply an operation to two regions. Called by miUnion, miInverse, +- * miSubtract, miIntersect... +- * +- * Results: +- * None. +- * +- * Side Effects: +- * The new region is overwritten. +- * +- * Notes: +- * The idea behind this function is to view the two regions as sets. +- * Together they cover a rectangle of area that this function divides +- * into horizontal bands where points are covered only by one region +- * or by both. For the first case, the nonOverlapFunc is called with +- * each the band and the band's upper and lower extents. For the +- * second, the overlapFunc is called to process the entire band. It +- * is responsible for clipping the rectangles in the band, though +- * this function provides the boundaries. +- * At the end of each band, the new region is coalesced, if possible, +- * to reduce the number of rectangles in the region. +- * +- *----------------------------------------------------------------------- +- */ +-/* static void*/ +-static void +-miRegionOp( +- register Region newReg, /* Place to store result */ +- Region reg1, /* First region in operation */ +- Region reg2, /* 2d region in operation */ +- int (*overlapFunc)( +- register Region pReg, +- register BoxPtr r1, +- BoxPtr r1End, +- register BoxPtr r2, +- BoxPtr r2End, +- short y1, +- short y2), /* Function to call for over- +- * lapping bands */ +- int (*nonOverlap1Func)( +- register Region pReg, +- register BoxPtr r, +- BoxPtr rEnd, +- register short y1, +- register short y2), /* Function to call for non- +- * overlapping bands in region +- * 1 */ +- int (*nonOverlap2Func)( +- register Region pReg, +- register BoxPtr r, +- BoxPtr rEnd, +- register short y1, +- register short y2)) /* Function to call for non- +- * overlapping bands in region +- * 2 */ +-{ +- register BoxPtr r1; /* Pointer into first region */ +- register BoxPtr r2; /* Pointer into 2d region */ +- BoxPtr r1End; /* End of 1st region */ +- BoxPtr r2End; /* End of 2d region */ +- register short ybot; /* Bottom of intersection */ +- register short ytop; /* Top of intersection */ +- BoxPtr oldRects; /* Old rects for newReg */ +- int prevBand; /* Index of start of +- * previous band in newReg */ +- int curBand; /* Index of start of current +- * band in newReg */ +- register BoxPtr r1BandEnd; /* End of current band in r1 */ +- register BoxPtr r2BandEnd; /* End of current band in r2 */ +- short top; /* Top of non-overlapping +- * band */ +- short bot; /* Bottom of non-overlapping +- * band */ +- +- /* +- * Initialization: +- * set r1, r2, r1End and r2End appropriately, preserve the important +- * parts of the destination region until the end in case it's one of +- * the two source regions, then mark the "new" region empty, allocating +- * another array of rectangles for it to use. +- */ +- r1 = reg1->rects; +- r2 = reg2->rects; +- r1End = r1 + reg1->numRects; +- r2End = r2 + reg2->numRects; +- +- oldRects = newReg->rects; +- +- EMPTY_REGION(newReg); +- +- /* +- * Allocate a reasonable number of rectangles for the new region. The idea +- * is to allocate enough so the individual functions don't need to +- * reallocate and copy the array, which is time consuming, yet we don't +- * have to worry about using too much memory. I hope to be able to +- * nuke the Xrealloc() at the end of this function eventually. +- */ +- newReg->size = max(reg1->numRects,reg2->numRects) * 2; +- +- if (! (newReg->rects = Xmalloc (sizeof(BoxRec) * newReg->size))) { +- newReg->size = 0; +- return; +- } +- +- /* +- * Initialize ybot and ytop. +- * In the upcoming loop, ybot and ytop serve different functions depending +- * on whether the band being handled is an overlapping or non-overlapping +- * band. +- * In the case of a non-overlapping band (only one of the regions +- * has points in the band), ybot is the bottom of the most recent +- * intersection and thus clips the top of the rectangles in that band. +- * ytop is the top of the next intersection between the two regions and +- * serves to clip the bottom of the rectangles in the current band. +- * For an overlapping band (where the two regions intersect), ytop clips +- * the top of the rectangles of both regions and ybot clips the bottoms. +- */ +- if (reg1->extents.y1 < reg2->extents.y1) +- ybot = reg1->extents.y1; +- else +- ybot = reg2->extents.y1; +- +- /* +- * prevBand serves to mark the start of the previous band so rectangles +- * can be coalesced into larger rectangles. qv. miCoalesce, above. +- * In the beginning, there is no previous band, so prevBand == curBand +- * (curBand is set later on, of course, but the first band will always +- * start at index 0). prevBand and curBand must be indices because of +- * the possible expansion, and resultant moving, of the new region's +- * array of rectangles. +- */ +- prevBand = 0; +- +- do +- { +- curBand = newReg->numRects; +- +- /* +- * This algorithm proceeds one source-band (as opposed to a +- * destination band, which is determined by where the two regions +- * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the +- * rectangle after the last one in the current band for their +- * respective regions. +- */ +- r1BandEnd = r1; +- while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1)) +- { +- r1BandEnd++; +- } +- +- r2BandEnd = r2; +- while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1)) +- { +- r2BandEnd++; +- } +- +- /* +- * First handle the band that doesn't intersect, if any. +- * +- * Note that attention is restricted to one band in the +- * non-intersecting region at once, so if a region has n +- * bands between the current position and the next place it overlaps +- * the other, this entire loop will be passed through n times. +- */ +- if (r1->y1 < r2->y1) +- { +- top = max(r1->y1,ybot); +- bot = min(r1->y2,r2->y1); +- +- if ((top != bot) && (nonOverlap1Func != NULL)) +- { +- (* nonOverlap1Func) (newReg, r1, r1BandEnd, top, bot); +- } +- +- ytop = r2->y1; +- } +- else if (r2->y1 < r1->y1) +- { +- top = max(r2->y1,ybot); +- bot = min(r2->y2,r1->y1); +- +- if ((top != bot) && (nonOverlap2Func != NULL)) +- { +- (* nonOverlap2Func) (newReg, r2, r2BandEnd, top, bot); +- } +- +- ytop = r1->y1; +- } +- else +- { +- ytop = r1->y1; +- } +- +- /* +- * If any rectangles got added to the region, try and coalesce them +- * with rectangles from the previous band. Note we could just do +- * this test in miCoalesce, but some machines incur a not +- * inconsiderable cost for function calls, so... +- */ +- if (newReg->numRects != curBand) +- { +- prevBand = miCoalesce (newReg, prevBand, curBand); +- } +- +- /* +- * Now see if we've hit an intersecting band. The two bands only +- * intersect if ybot > ytop +- */ +- ybot = min(r1->y2, r2->y2); +- curBand = newReg->numRects; +- if (ybot > ytop) +- { +- (* overlapFunc) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot); +- +- } +- +- if (newReg->numRects != curBand) +- { +- prevBand = miCoalesce (newReg, prevBand, curBand); +- } +- +- /* +- * If we've finished with a band (y2 == ybot) we skip forward +- * in the region to the next band. +- */ +- if (r1->y2 == ybot) +- { +- r1 = r1BandEnd; +- } +- if (r2->y2 == ybot) +- { +- r2 = r2BandEnd; +- } +- } while ((r1 != r1End) && (r2 != r2End)); +- +- /* +- * Deal with whichever region still has rectangles left. +- */ +- curBand = newReg->numRects; +- if (r1 != r1End) +- { +- if (nonOverlap1Func != NULL) +- { +- do +- { +- r1BandEnd = r1; +- while ((r1BandEnd < r1End) && (r1BandEnd->y1 == r1->y1)) +- { +- r1BandEnd++; +- } +- (* nonOverlap1Func) (newReg, r1, r1BandEnd, +- max(r1->y1,ybot), r1->y2); +- r1 = r1BandEnd; +- } while (r1 != r1End); +- } +- } +- else if ((r2 != r2End) && (nonOverlap2Func != NULL)) +- { +- do +- { +- r2BandEnd = r2; +- while ((r2BandEnd < r2End) && (r2BandEnd->y1 == r2->y1)) +- { +- r2BandEnd++; +- } +- (* nonOverlap2Func) (newReg, r2, r2BandEnd, +- max(r2->y1,ybot), r2->y2); +- r2 = r2BandEnd; +- } while (r2 != r2End); +- } +- +- if (newReg->numRects != curBand) +- { +- (void) miCoalesce (newReg, prevBand, curBand); +- } +- +- /* +- * A bit of cleanup. To keep regions from growing without bound, +- * we shrink the array of rectangles to match the new number of +- * rectangles in the region. This never goes to 0, however... +- * +- * Only do this stuff if the number of rectangles allocated is more than +- * twice the number of rectangles in the region (a simple optimization...). +- */ +- if (newReg->numRects < (newReg->size >> 1)) +- { +- if (REGION_NOT_EMPTY(newReg)) +- { +- BoxPtr prev_rects = newReg->rects; +- newReg->rects = Xrealloc (newReg->rects, +- sizeof(BoxRec) * newReg->numRects); +- if (! newReg->rects) +- newReg->rects = prev_rects; +- else +- newReg->size = newReg->numRects; +- } +- else +- { +- /* +- * No point in doing the extra work involved in an Xrealloc if +- * the region is empty +- */ +- newReg->size = 1; +- Xfree(newReg->rects); +- newReg->rects = Xmalloc(sizeof(BoxRec)); +- } +- } +- Xfree (oldRects); +- return; +-} +- +- +-/*====================================================================== +- * Region Union +- *====================================================================*/ +- +-/*- +- *----------------------------------------------------------------------- +- * miUnionNonO -- +- * Handle a non-overlapping band for the union operation. Just +- * Adds the rectangles into the region. Doesn't have to check for +- * subsumption or anything. +- * +- * Results: +- * None. +- * +- * Side Effects: +- * pReg->numRects is incremented and the final rectangles overwritten +- * with the rectangles we're passed. +- * +- *----------------------------------------------------------------------- +- */ +-/* static void*/ +-static int +-miUnionNonO ( +- register Region pReg, +- register BoxPtr r, +- BoxPtr rEnd, +- register short y1, +- register short y2) +-{ +- register BoxPtr pNextRect; +- +- pNextRect = &pReg->rects[pReg->numRects]; +- +- assert(y1 < y2); +- +- while (r != rEnd) +- { +- assert(r->x1 < r->x2); +- MEMCHECK(pReg, pNextRect, pReg->rects); +- pNextRect->x1 = r->x1; +- pNextRect->y1 = y1; +- pNextRect->x2 = r->x2; +- pNextRect->y2 = y2; +- pReg->numRects += 1; +- pNextRect++; +- +- assert(pReg->numRects<=pReg->size); +- r++; +- } +- return 0; /* lint */ +-} +- +- +-/*- +- *----------------------------------------------------------------------- +- * miUnionO -- +- * Handle an overlapping band for the union operation. Picks the +- * left-most rectangle each time and merges it into the region. +- * +- * Results: +- * None. +- * +- * Side Effects: +- * Rectangles are overwritten in pReg->rects and pReg->numRects will +- * be changed. +- * +- *----------------------------------------------------------------------- +- */ +- +-/* static void*/ +-static int +-miUnionO ( +- register Region pReg, +- register BoxPtr r1, +- BoxPtr r1End, +- register BoxPtr r2, +- BoxPtr r2End, +- register short y1, +- register short y2) +-{ +- register BoxPtr pNextRect; +- +- pNextRect = &pReg->rects[pReg->numRects]; +- +-#define MERGERECT(r) \ +- if ((pReg->numRects != 0) && \ +- (pNextRect[-1].y1 == y1) && \ +- (pNextRect[-1].y2 == y2) && \ +- (pNextRect[-1].x2 >= r->x1)) \ +- { \ +- if (pNextRect[-1].x2 < r->x2) \ +- { \ +- pNextRect[-1].x2 = r->x2; \ +- assert(pNextRect[-1].x1rects); \ +- pNextRect->y1 = y1; \ +- pNextRect->y2 = y2; \ +- pNextRect->x1 = r->x1; \ +- pNextRect->x2 = r->x2; \ +- pReg->numRects += 1; \ +- pNextRect += 1; \ +- } \ +- assert(pReg->numRects<=pReg->size);\ +- r++; +- +- assert (y1x1 < r2->x1) +- { +- MERGERECT(r1); +- } +- else +- { +- MERGERECT(r2); +- } +- } +- +- if (r1 != r1End) +- { +- do +- { +- MERGERECT(r1); +- } while (r1 != r1End); +- } +- else while (r2 != r2End) +- { +- MERGERECT(r2); +- } +- return 0; /* lint */ +-} +- +-int +-XUnionRegion( +- Region reg1, +- Region reg2, /* source regions */ +- Region newReg) /* destination Region */ +-{ +- /* checks all the simple cases */ +- +- /* +- * Region 1 and 2 are the same or region 1 is empty +- */ +- if ( (reg1 == reg2) || (!(reg1->numRects)) ) +- { +- if (newReg != reg2) +- return miRegionCopy(newReg, reg2); +- return 1; +- } +- +- /* +- * if nothing to union (region 2 empty) +- */ +- if (!(reg2->numRects)) +- { +- if (newReg != reg1) +- return miRegionCopy(newReg, reg1); +- return 1; +- } +- +- /* +- * Region 1 completely subsumes region 2 +- */ +- if ((reg1->numRects == 1) && +- (reg1->extents.x1 <= reg2->extents.x1) && +- (reg1->extents.y1 <= reg2->extents.y1) && +- (reg1->extents.x2 >= reg2->extents.x2) && +- (reg1->extents.y2 >= reg2->extents.y2)) +- { +- if (newReg != reg1) +- return miRegionCopy(newReg, reg1); +- return 1; +- } +- +- /* +- * Region 2 completely subsumes region 1 +- */ +- if ((reg2->numRects == 1) && +- (reg2->extents.x1 <= reg1->extents.x1) && +- (reg2->extents.y1 <= reg1->extents.y1) && +- (reg2->extents.x2 >= reg1->extents.x2) && +- (reg2->extents.y2 >= reg1->extents.y2)) +- { +- if (newReg != reg2) +- return miRegionCopy(newReg, reg2); +- return 1; +- } +- +- miRegionOp (newReg, reg1, reg2, miUnionO, +- miUnionNonO, miUnionNonO); +- +- newReg->extents.x1 = min(reg1->extents.x1, reg2->extents.x1); +- newReg->extents.y1 = min(reg1->extents.y1, reg2->extents.y1); +- newReg->extents.x2 = max(reg1->extents.x2, reg2->extents.x2); +- newReg->extents.y2 = max(reg1->extents.y2, reg2->extents.y2); +- +- return 1; +-} +- +- +-/*====================================================================== +- * Region Subtraction +- *====================================================================*/ +- +-/*- +- *----------------------------------------------------------------------- +- * miSubtractNonO -- +- * Deal with non-overlapping band for subtraction. Any parts from +- * region 2 we discard. Anything from region 1 we add to the region. +- * +- * Results: +- * None. +- * +- * Side Effects: +- * pReg may be affected. +- * +- *----------------------------------------------------------------------- +- */ +-/* static void*/ +-static int +-miSubtractNonO1 ( +- register Region pReg, +- register BoxPtr r, +- BoxPtr rEnd, +- register short y1, +- register short y2) +-{ +- register BoxPtr pNextRect; +- +- pNextRect = &pReg->rects[pReg->numRects]; +- +- assert(y1x1x2); +- MEMCHECK(pReg, pNextRect, pReg->rects); +- pNextRect->x1 = r->x1; +- pNextRect->y1 = y1; +- pNextRect->x2 = r->x2; +- pNextRect->y2 = y2; +- pReg->numRects += 1; +- pNextRect++; +- +- assert(pReg->numRects <= pReg->size); +- +- r++; +- } +- return 0; /* lint */ +-} +- +-/*- +- *----------------------------------------------------------------------- +- * miSubtractO -- +- * Overlapping band subtraction. x1 is the left-most point not yet +- * checked. +- * +- * Results: +- * None. +- * +- * Side Effects: +- * pReg may have rectangles added to it. +- * +- *----------------------------------------------------------------------- +- */ +-/* static void*/ +-static int +-miSubtractO ( +- register Region pReg, +- register BoxPtr r1, +- BoxPtr r1End, +- register BoxPtr r2, +- BoxPtr r2End, +- register short y1, +- register short y2) +-{ +- register BoxPtr pNextRect; +- register int x1; +- +- x1 = r1->x1; +- +- assert(y1rects[pReg->numRects]; +- +- while ((r1 != r1End) && (r2 != r2End)) +- { +- if (r2->x2 <= x1) +- { +- /* +- * Subtrahend missed the boat: go to next subtrahend. +- */ +- r2++; +- } +- else if (r2->x1 <= x1) +- { +- /* +- * Subtrahend preceds minuend: nuke left edge of minuend. +- */ +- x1 = r2->x2; +- if (x1 >= r1->x2) +- { +- /* +- * Minuend completely covered: advance to next minuend and +- * reset left fence to edge of new minuend. +- */ +- r1++; +- if (r1 != r1End) +- x1 = r1->x1; +- } +- else +- { +- /* +- * Subtrahend now used up since it doesn't extend beyond +- * minuend +- */ +- r2++; +- } +- } +- else if (r2->x1 < r1->x2) +- { +- /* +- * Left part of subtrahend covers part of minuend: add uncovered +- * part of minuend to region and skip to next subtrahend. +- */ +- assert(x1x1); +- MEMCHECK(pReg, pNextRect, pReg->rects); +- pNextRect->x1 = x1; +- pNextRect->y1 = y1; +- pNextRect->x2 = r2->x1; +- pNextRect->y2 = y2; +- pReg->numRects += 1; +- pNextRect++; +- +- assert(pReg->numRects<=pReg->size); +- +- x1 = r2->x2; +- if (x1 >= r1->x2) +- { +- /* +- * Minuend used up: advance to new... +- */ +- r1++; +- if (r1 != r1End) +- x1 = r1->x1; +- } +- else +- { +- /* +- * Subtrahend used up +- */ +- r2++; +- } +- } +- else +- { +- /* +- * Minuend used up: add any remaining piece before advancing. +- */ +- if (r1->x2 > x1) +- { +- MEMCHECK(pReg, pNextRect, pReg->rects); +- pNextRect->x1 = x1; +- pNextRect->y1 = y1; +- pNextRect->x2 = r1->x2; +- pNextRect->y2 = y2; +- pReg->numRects += 1; +- pNextRect++; +- assert(pReg->numRects<=pReg->size); +- } +- r1++; +- if (r1 != r1End) +- x1 = r1->x1; +- } +- } +- +- /* +- * Add remaining minuend rectangles to region. +- */ +- while (r1 != r1End) +- { +- assert(x1x2); +- MEMCHECK(pReg, pNextRect, pReg->rects); +- pNextRect->x1 = x1; +- pNextRect->y1 = y1; +- pNextRect->x2 = r1->x2; +- pNextRect->y2 = y2; +- pReg->numRects += 1; +- pNextRect++; +- +- assert(pReg->numRects<=pReg->size); +- +- r1++; +- if (r1 != r1End) +- { +- x1 = r1->x1; +- } +- } +- return 0; /* lint */ +-} +- +-/*- +- *----------------------------------------------------------------------- +- * miSubtract -- +- * Subtract regS from regM and leave the result in regD. +- * S stands for subtrahend, M for minuend and D for difference. +- * +- * Results: +- * TRUE. +- * +- * Side Effects: +- * regD is overwritten. +- * +- *----------------------------------------------------------------------- +- */ +- +-int +-XSubtractRegion( +- Region regM, +- Region regS, +- register Region regD) +-{ +- /* check for trivial reject */ +- if ( (!(regM->numRects)) || (!(regS->numRects)) || +- (!EXTENTCHECK(®M->extents, ®S->extents)) ) +- { +- return miRegionCopy(regD, regM); +- } +- +- miRegionOp (regD, regM, regS, miSubtractO, +- miSubtractNonO1, NULL); +- +- /* +- * Can't alter newReg's extents before we call miRegionOp because +- * it might be one of the source regions and miRegionOp depends +- * on the extents of those regions being the unaltered. Besides, this +- * way there's no checking against rectangles that will be nuked +- * due to coalescing, so we have to examine fewer rectangles. +- */ +- miSetExtents (regD); +- return 1; +-} +- +-int +-XXorRegion(Region sra, Region srb, Region dr) +-{ +- Region tra, trb; +- +- if (! (tra = XCreateRegion()) ) +- return 0; +- if (! (trb = XCreateRegion()) ) { +- XDestroyRegion(tra); +- return 0; +- } +- (void) XSubtractRegion(sra,srb,tra); +- (void) XSubtractRegion(srb,sra,trb); +- (void) XUnionRegion(tra,trb,dr); +- XDestroyRegion(tra); +- XDestroyRegion(trb); +- return 0; +-} +- +-/* +- * Check to see if the region is empty. Assumes a region is passed +- * as a parameter +- */ +-int +-XEmptyRegion( +- Region r) +-{ +- if( r->numRects == 0 ) return TRUE; +- else return FALSE; +-} +- +-/* +- * Check to see if two regions are equal +- */ +-int +-XEqualRegion(Region r1, Region r2) +-{ +- int i; +- +- if( r1->numRects != r2->numRects ) return FALSE; +- else if( r1->numRects == 0 ) return TRUE; +- else if ( r1->extents.x1 != r2->extents.x1 ) return FALSE; +- else if ( r1->extents.x2 != r2->extents.x2 ) return FALSE; +- else if ( r1->extents.y1 != r2->extents.y1 ) return FALSE; +- else if ( r1->extents.y2 != r2->extents.y2 ) return FALSE; +- else for( i=0; i < r1->numRects; i++ ) { +- if ( r1->rects[i].x1 != r2->rects[i].x1 ) return FALSE; +- else if ( r1->rects[i].x2 != r2->rects[i].x2 ) return FALSE; +- else if ( r1->rects[i].y1 != r2->rects[i].y1 ) return FALSE; +- else if ( r1->rects[i].y2 != r2->rects[i].y2 ) return FALSE; +- } +- return TRUE; +-} +- +-int +-XPointInRegion( +- Region pRegion, +- int x, int y) +-{ +- int i; +- +- if (pRegion->numRects == 0) +- return FALSE; +- if (!INBOX(pRegion->extents, x, y)) +- return FALSE; +- for (i=0; inumRects; i++) +- { +- if (INBOX (pRegion->rects[i], x, y)) +- return TRUE; +- } +- return FALSE; +-} +- +-int +-XRectInRegion( +- register Region region, +- int rx, int ry, +- unsigned int rwidth, unsigned int rheight) +-{ +- register BoxPtr pbox; +- register BoxPtr pboxEnd; +- Box rect; +- register BoxPtr prect = ▭ +- int partIn, partOut; +- +- prect->x1 = rx; +- prect->y1 = ry; +- prect->x2 = rwidth + rx; +- prect->y2 = rheight + ry; +- +- /* this is (just) a useful optimization */ +- if ((region->numRects == 0) || !EXTENTCHECK(®ion->extents, prect)) +- return(RectangleOut); +- +- partOut = FALSE; +- partIn = FALSE; +- +- /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */ +- for (pbox = region->rects, pboxEnd = pbox + region->numRects; +- pbox < pboxEnd; +- pbox++) +- { +- +- if (pbox->y2 <= ry) +- continue; /* getting up to speed or skipping remainder of band */ +- +- if (pbox->y1 > ry) +- { +- partOut = TRUE; /* missed part of rectangle above */ +- if (partIn || (pbox->y1 >= prect->y2)) +- break; +- ry = pbox->y1; /* x guaranteed to be == prect->x1 */ +- } +- +- if (pbox->x2 <= rx) +- continue; /* not far enough over yet */ +- +- if (pbox->x1 > rx) +- { +- partOut = TRUE; /* missed part of rectangle to left */ +- if (partIn) +- break; +- } +- +- if (pbox->x1 < prect->x2) +- { +- partIn = TRUE; /* definitely overlap */ +- if (partOut) +- break; +- } +- +- if (pbox->x2 >= prect->x2) +- { +- ry = pbox->y2; /* finished with this band */ +- if (ry >= prect->y2) +- break; +- rx = prect->x1; /* reset x out to left again */ +- } else +- { +- /* +- * Because boxes in a band are maximal width, if the first box +- * to overlap the rectangle doesn't completely cover it in that +- * band, the rectangle must be partially out, since some of it +- * will be uncovered in that band. partIn will have been set true +- * by now... +- */ +- break; +- } +- +- } +- +- return(partIn ? ((ry < prect->y2) ? RectanglePart : RectangleIn) : +- RectangleOut); +-} +diff --git a/common/Xregion/Xlib.h b/common/Xregion/Xlib.h +deleted file mode 100644 +index ba6f281..0000000 +--- a/common/Xregion/Xlib.h ++++ /dev/null +@@ -1,50 +0,0 @@ +-/* +- +-Copyright 1985, 1986, 1987, 1991, 1998 The Open Group +- +-Permission to use, copy, modify, distribute, and sell this software and its +-documentation for any purpose is hereby granted without fee, provided that +-the above copyright notice appear in all copies and that both that +-copyright notice and this permission notice appear in supporting +-documentation. +- +-The above copyright notice and this permission notice shall be included in +-all copies or substantial portions of the Software. +- +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +- +-Except as contained in this notice, the name of The Open Group shall not be +-used in advertising or otherwise to promote the sale, use or other dealings +-in this Software without prior written authorization from The Open Group. +- +-*/ +- +- +-/* +- * Xlib.h - Header definition and support file for the C subroutine +- * interface library (Xlib) to the X Window System Protocol (V11). +- * Structures and symbols starting with "_" are private to the library. +- */ +-#ifndef _X11_XLIB_H_ +-#define _X11_XLIB_H_ +- +-#define NeedFunctionPrototypes 1 +- +-#define Bool int +- +-typedef struct { +- short x, y; +-} XPoint; +- +-typedef struct { +- short x, y; +- unsigned short width, height; +-} XRectangle; +- +- +-#endif /* _X11_XLIB_H_ */ +diff --git a/common/Xregion/Xlibint.h b/common/Xregion/Xlibint.h +deleted file mode 100644 +index 9b9ae28..0000000 +--- a/common/Xregion/Xlibint.h ++++ /dev/null +@@ -1,48 +0,0 @@ +- +-/* +- +-Copyright 1984, 1985, 1987, 1989, 1998 The Open Group +- +-Permission to use, copy, modify, distribute, and sell this software and its +-documentation for any purpose is hereby granted without fee, provided that +-the above copyright notice appear in all copies and that both that +-copyright notice and this permission notice appear in supporting +-documentation. +- +-The above copyright notice and this permission notice shall be included +-in all copies or substantial portions of the Software. +- +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +-OTHER DEALINGS IN THE SOFTWARE. +- +-Except as contained in this notice, the name of The Open Group shall +-not be used in advertising or otherwise to promote the sale, use or +-other dealings in this Software without prior written authorization +-from The Open Group. +- +-*/ +- +-#ifndef _X11_XLIBINT_H_ +-#define _X11_XLIBINT_H_ 1 +- +-/* +- * Xlibint.h - Header definition and support file for the internal +- * support routines used by the C subroutine interface +- * library (Xlib) to the X Window System. +- * +- * Warning, there be dragons here.... +- */ +- +-#include +- +-#define Xfree(ptr) free((ptr)) +-#define Xmalloc(size) malloc((size)) +-#define Xrealloc(ptr, size) realloc((ptr), (size)) +-#define Xcalloc(nelem, elsize) calloc((nelem), (elsize)) +- +-#endif /* _X11_XLIBINT_H_ */ +diff --git a/common/Xregion/Xregion.h b/common/Xregion/Xregion.h +deleted file mode 100644 +index cf10f86..0000000 +--- a/common/Xregion/Xregion.h ++++ /dev/null +@@ -1,190 +0,0 @@ +-/************************************************************************ +- +-Copyright 1987, 1998 The Open Group +- +-Permission to use, copy, modify, distribute, and sell this software and its +-documentation for any purpose is hereby granted without fee, provided that +-the above copyright notice appear in all copies and that both that +-copyright notice and this permission notice appear in supporting +-documentation. +- +-The above copyright notice and this permission notice shall be included in +-all copies or substantial portions of the Software. +- +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +- +-Except as contained in this notice, the name of The Open Group shall not be +-used in advertising or otherwise to promote the sale, use or other dealings +-in this Software without prior written authorization from The Open Group. +- +- +-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. +- +- All Rights Reserved +- +-Permission to use, copy, modify, and distribute this software and its +-documentation for any purpose and without fee is hereby granted, +-provided that the above copyright notice appear in all copies and that +-both that copyright notice and this permission notice appear in +-supporting documentation, and that the name of Digital not be +-used in advertising or publicity pertaining to distribution of the +-software without specific, written prior permission. +- +-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +-SOFTWARE. +- +-************************************************************************/ +- +-#ifndef _X11_XREGION_H_ +-#define _X11_XREGION_H_ +- +-typedef struct { +- short x1, x2, y1, y2; +-} Box, BOX, BoxRec, *BoxPtr; +- +-typedef struct { +- short x, y, width, height; +-}RECTANGLE, RectangleRec, *RectanglePtr; +- +-#define TRUE 1 +-#define FALSE 0 +-#define MAXSHORT 32767 +-#define MINSHORT -MAXSHORT +-#ifndef MAX +-#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +-#endif +-#ifndef MIN +-#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +-#endif +- +- +-/* +- * clip region +- */ +- +-typedef struct _XRegion { +- long size; +- long numRects; +- BOX *rects; +- BOX extents; +-} REGION; +- +-/* Xutil.h contains the declaration: +- * typedef struct _XRegion *Region; +- */ +- +-/* 1 if two BOXs overlap. +- * 0 if two BOXs do not overlap. +- * Remember, x2 and y2 are not in the region +- */ +-#define EXTENTCHECK(r1, r2) \ +- ((r1)->x2 > (r2)->x1 && \ +- (r1)->x1 < (r2)->x2 && \ +- (r1)->y2 > (r2)->y1 && \ +- (r1)->y1 < (r2)->y2) +- +-/* +- * update region extents +- */ +-#define EXTENTS(r,idRect){\ +- if((r)->x1 < (idRect)->extents.x1)\ +- (idRect)->extents.x1 = (r)->x1;\ +- if((r)->y1 < (idRect)->extents.y1)\ +- (idRect)->extents.y1 = (r)->y1;\ +- if((r)->x2 > (idRect)->extents.x2)\ +- (idRect)->extents.x2 = (r)->x2;\ +- if((r)->y2 > (idRect)->extents.y2)\ +- (idRect)->extents.y2 = (r)->y2;\ +- } +- +-/* +- * Check to see if there is enough memory in the present region. +- */ +-#define MEMCHECK(reg, rect, firstrect){\ +- if ((reg)->numRects >= ((reg)->size - 1)){\ +- BoxPtr tmpRect = Xrealloc ((firstrect), \ +- (2 * (sizeof(BOX)) * ((reg)->size))); \ +- if (tmpRect == NULL) \ +- return(0);\ +- (firstrect) = tmpRect; \ +- (reg)->size *= 2;\ +- (rect) = &(firstrect)[(reg)->numRects];\ +- }\ +- } +- +-/* this routine checks to see if the previous rectangle is the same +- * or subsumes the new rectangle to add. +- */ +- +-#define CHECK_PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\ +- (!(((Reg)->numRects > 0)&&\ +- ((R-1)->y1 == (Ry1)) &&\ +- ((R-1)->y2 == (Ry2)) &&\ +- ((R-1)->x1 <= (Rx1)) &&\ +- ((R-1)->x2 >= (Rx2)))) +- +-/* add a rectangle to the given Region */ +-#define ADDRECT(reg, r, rx1, ry1, rx2, ry2){\ +- if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&\ +- CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ +- (r)->x1 = (rx1);\ +- (r)->y1 = (ry1);\ +- (r)->x2 = (rx2);\ +- (r)->y2 = (ry2);\ +- EXTENTS((r), (reg));\ +- (reg)->numRects++;\ +- (r)++;\ +- }\ +- } +- +- +- +-/* add a rectangle to the given Region */ +-#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\ +- if ((rx1 < rx2) && (ry1 < ry2) &&\ +- CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ +- (r)->x1 = (rx1);\ +- (r)->y1 = (ry1);\ +- (r)->x2 = (rx2);\ +- (r)->y2 = (ry2);\ +- (reg)->numRects++;\ +- (r)++;\ +- }\ +- } +- +-#define EMPTY_REGION(pReg) pReg->numRects = 0 +- +-#define REGION_NOT_EMPTY(pReg) pReg->numRects +- +-#define INBOX(r, x, y) \ +- ( ( ((r).x2 > x)) && \ +- ( ((r).x1 <= x)) && \ +- ( ((r).y2 > y)) && \ +- ( ((r).y1 <= y)) ) +- +-/* +- * number of points to buffer before sending them off +- * to scanlines() : Must be an even number +- */ +-#define NUMPTSTOBUFFER 200 +- +-/* +- * used to allocate buffers for points and link +- * the buffers together +- */ +-typedef struct _POINTBLOCK { +- XPoint pts[NUMPTSTOBUFFER]; +- struct _POINTBLOCK *next; +-} POINTBLOCK; +- +-#endif /* _X11_XREGION_H_ */ +diff --git a/common/Xregion/Xutil.h b/common/Xregion/Xutil.h +deleted file mode 100644 +index 4da56a5..0000000 +--- a/common/Xregion/Xutil.h ++++ /dev/null +@@ -1,167 +0,0 @@ +- +-/*********************************************************** +- +-Copyright 1987, 1998 The Open Group +- +-Permission to use, copy, modify, distribute, and sell this software and its +-documentation for any purpose is hereby granted without fee, provided that +-the above copyright notice appear in all copies and that both that +-copyright notice and this permission notice appear in supporting +-documentation. +- +-The above copyright notice and this permission notice shall be included in +-all copies or substantial portions of the Software. +- +-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +- +-Except as contained in this notice, the name of The Open Group shall not be +-used in advertising or otherwise to promote the sale, use or other dealings +-in this Software without prior written authorization from The Open Group. +- +- +-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. +- +- All Rights Reserved +- +-Permission to use, copy, modify, and distribute this software and its +-documentation for any purpose and without fee is hereby granted, +-provided that the above copyright notice appear in all copies and that +-both that copyright notice and this permission notice appear in +-supporting documentation, and that the name of Digital not be +-used in advertising or publicity pertaining to distribution of the +-software without specific, written prior permission. +- +-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +-SOFTWARE. +- +-******************************************************************/ +- +-#ifndef _X11_XUTIL_H_ +-#define _X11_XUTIL_H_ +- +-/* You must include before including this file */ +-#include "Xlib.h" +- +-/****** Avoid symbol clash with "real" libX11 ******/ +-#define XClipBox vncXClipBox +-#define XCreateRegion vncXCreateRegion +-#define XDestroyRegion vncXDestroyRegion +-#define XEmptyRegion vncXEmptyRegion +-#define XEqualRegion vncXEqualRegion +-#define XIntersectRegion vncXIntersectRegion +-#define XOffsetRegion vncXOffsetRegion +-#define XPointInRegion vncXPointInRegion +-#define XPolygonRegion vncXPolygonRegion +-#define XRectInRegion vncXRectInRegion +-#define XShrinkRegion vncXShrinkRegion +-#define XSubtractRegion vncXSubtractRegion +-#define XUnionRectWithRegion vncXUnionRectWithRegion +-#define XUnionRegion vncXUnionRegion +-#define XXorRegion vncXXorRegion +- +-/* +- * opaque reference to Region data type +- */ +-typedef struct _XRegion *Region; +- +-/* Return values from XRectInRegion() */ +- +-#define RectangleOut 0 +-#define RectangleIn 1 +-#define RectanglePart 2 +- +-extern int XClipBox( +- Region /* r */, +- XRectangle* /* rect_return */ +-); +- +-extern Region XCreateRegion( +- void +-); +- +-extern int XDestroyRegion( +- Region /* r */ +-); +- +-extern int XEmptyRegion( +- Region /* r */ +-); +- +-extern int XEqualRegion( +- Region /* r1 */, +- Region /* r2 */ +-); +- +-extern int XIntersectRegion( +- Region /* sra */, +- Region /* srb */, +- Region /* dr_return */ +-); +- +-extern int XOffsetRegion( +- Region /* r */, +- int /* dx */, +- int /* dy */ +-); +- +-extern Bool XPointInRegion( +- Region /* r */, +- int /* x */, +- int /* y */ +-); +- +-extern Region XPolygonRegion( +- XPoint* /* points */, +- int /* n */, +- int /* fill_rule */ +-); +- +-extern int XRectInRegion( +- Region /* r */, +- int /* x */, +- int /* y */, +- unsigned int /* width */, +- unsigned int /* height */ +-); +- +-extern int XShrinkRegion( +- Region /* r */, +- int /* dx */, +- int /* dy */ +-); +- +-extern int XSubtractRegion( +- Region /* sra */, +- Region /* srb */, +- Region /* dr_return */ +-); +- +-extern int XUnionRectWithRegion( +- XRectangle* /* rectangle */, +- Region /* src_region */, +- Region /* dest_region_return */ +-); +- +-extern int XUnionRegion( +- Region /* sra */, +- Region /* srb */, +- Region /* dr_return */ +-); +- +-extern int XXorRegion( +- Region /* sra */, +- Region /* srb */, +- Region /* dr_return */ +-); +- +-#endif /* _X11_XUTIL_H_ */ +diff --git a/common/rfb/CMakeLists.txt b/common/rfb/CMakeLists.txt +index 5047e5e..ecfcb03 100644 +--- a/common/rfb/CMakeLists.txt ++++ b/common/rfb/CMakeLists.txt +@@ -1,4 +1,4 @@ +-include_directories(${CMAKE_SOURCE_DIR}/common ${JPEG_INCLUDE_DIR}) ++include_directories(${CMAKE_SOURCE_DIR}/common ${JPEG_INCLUDE_DIR} ${PIXMAN_INCLUDE_DIR}) + + set(RFB_SOURCES + Blacklist.cxx +@@ -72,7 +72,7 @@ if(WIN32) + set(RFB_SOURCES ${RFB_SOURCES} WinPasswdValidator.cxx) + endif(WIN32) + +-set(RFB_LIBRARIES ${JPEG_LIBRARIES} os rdr Xregion) ++set(RFB_LIBRARIES ${JPEG_LIBRARIES} ${PIXMAN_LIBRARY} os rdr) + + if(HAVE_PAM) + set(RFB_SOURCES ${RFB_SOURCES} UnixPasswordValidator.cxx +diff --git a/common/rfb/ComparingUpdateTracker.cxx b/common/rfb/ComparingUpdateTracker.cxx +index 237adc4..d565120 100644 +--- a/common/rfb/ComparingUpdateTracker.cxx ++++ b/common/rfb/ComparingUpdateTracker.cxx +@@ -120,8 +120,6 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) + rdr::U8* oldData = oldFb.getBufferRW(r, &oldStride); + int oldStrideBytes = oldStride * bytesPerPixel; + +- std::vector changedBlocks; +- + for (int blockTop = r.tl.y; blockTop < r.br.y; blockTop += BLOCK_SIZE) + { + // Get a strip of the source buffer +@@ -146,8 +144,8 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) + if (memcmp(oldPtr, newPtr, blockWidthInBytes) != 0) + { + // A block has changed - copy the remainder to the oldFb +- changedBlocks.push_back(Rect(blockLeft, blockTop, +- blockRight, blockBottom)); ++ newChanged->assign_union(Region(Rect(blockLeft, blockTop, ++ blockRight, blockBottom))); + for (int y2 = y; y2 < blockBottom; y2++) + { + memcpy(oldPtr, newPtr, blockWidthInBytes); +@@ -169,12 +167,6 @@ void ComparingUpdateTracker::compareRect(const Rect& r, Region* newChanged) + } + + oldFb.commitBufferRW(r); +- +- if (!changedBlocks.empty()) { +- Region temp; +- temp.setOrderedRects(changedBlocks); +- newChanged->assign_union(temp); +- } + } + + void ComparingUpdateTracker::logStats() +diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx +index 0cd5206..6a153a8 100644 +--- a/common/rfb/EncodeManager.cxx ++++ b/common/rfb/EncodeManager.cxx +@@ -273,7 +273,7 @@ void EncodeManager::writeUpdate(const UpdateInfo& ui, const PixelBuffer* pb, + * We start by searching for solid rects, which are then removed + * from the changed region. + */ +- changed.copyFrom(ui.changed); ++ changed = ui.changed; + + if (conn->cp.supportsLastRect) + writeSolidRects(&changed, pb); +diff --git a/common/rfb/Region.cxx b/common/rfb/Region.cxx +index 995f8c5..2b5d0cf 100644 +--- a/common/rfb/Region.cxx ++++ b/common/rfb/Region.cxx +@@ -1,4 +1,5 @@ + /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. ++ * Copyright 2016-2020 Pierre Ossman for Cendio AB + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -16,190 +17,110 @@ + * USA. + */ + +-// Cross-platform Region class based on the X11 region implementation. Note +-// that for efficiency this code manipulates the Xlib region structure +-// directly. Apart from the layout of the structure, there is one other key +-// assumption made: a Region returned from XCreateRegion must always have its +-// rects member allocated so that there is space for at least one rectangle. +-// +- + #include +-#include +-#include + + extern "C" { +-#include +-#include +-#include +-} +- +-// A _RectRegion must never be passed as a return parameter to the Xlib region +-// operations. This is because for efficiency its "rects" member has not been +-// allocated with Xmalloc. It is however safe to pass it as an input +-// parameter. +- +-class _RectRegion { +-public: +- _RectRegion(const rfb::Rect& r) { +- region.rects = ®ion.extents; +- region.numRects = 1; +- region.extents.x1 = r.tl.x; +- region.extents.y1 = r.tl.y; +- region.extents.x2 = r.br.x; +- region.extents.y2 = r.br.y; +- region.size = 1; +- if (r.is_empty()) +- region.numRects = 0; +- } +- REGION region; +-}; +- ++#include ++#include ++} + + rfb::Region::Region() { +- xrgn = XCreateRegion(); +- assert(xrgn); ++ rgn = new struct pixman_region16; ++ pixman_region_init(rgn); + } + + rfb::Region::Region(const Rect& r) { +- xrgn = XCreateRegion(); +- assert(xrgn); +- reset(r); ++ rgn = new struct pixman_region16; ++ pixman_region_init_rect(rgn, r.tl.x, r.tl.y, r.width(), r.height()); + } + + rfb::Region::Region(const rfb::Region& r) { +- xrgn = XCreateRegion(); +- assert(xrgn); +- XUnionRegion(xrgn, r.xrgn, xrgn); ++ rgn = new struct pixman_region16; ++ pixman_region_init(rgn); ++ pixman_region_copy(rgn, r.rgn); + } + + rfb::Region::~Region() { +- XDestroyRegion(xrgn); ++ pixman_region_fini(rgn); ++ delete rgn; + } + + rfb::Region& rfb::Region::operator=(const rfb::Region& r) { +- clear(); +- XUnionRegion(xrgn, r.xrgn, xrgn); ++ pixman_region_copy(rgn, r.rgn); + return *this; + } + + void rfb::Region::clear() { +- xrgn->numRects = 0; +- xrgn->extents.x1 = 0; +- xrgn->extents.y1 = 0; +- xrgn->extents.x2 = 0; +- xrgn->extents.y2 = 0; ++ // pixman_region_clear() isn't available on some older systems ++ pixman_region_fini(rgn); ++ pixman_region_init(rgn); + } + + void rfb::Region::reset(const Rect& r) { +- if (r.is_empty()) { +- clear(); +- } else { +- xrgn->numRects = 1; +- xrgn->rects[0].x1 = xrgn->extents.x1 = r.tl.x; +- xrgn->rects[0].y1 = xrgn->extents.y1 = r.tl.y; +- xrgn->rects[0].x2 = xrgn->extents.x2 = r.br.x; +- xrgn->rects[0].y2 = xrgn->extents.y2 = r.br.y; +- } ++ pixman_region_fini(rgn); ++ pixman_region_init_rect(rgn, r.tl.x, r.tl.y, r.width(), r.height()); + } + + void rfb::Region::translate(const Point& delta) { +- XOffsetRegion(xrgn, delta.x, delta.y); +-} +- +-void rfb::Region::setOrderedRects(const std::vector& rects) { +- clear(); +- std::vector::const_iterator i; +- for (i=rects.begin(); i != rects.end(); i++) { +- _RectRegion rr(*i); +- XUnionRegion(xrgn, &rr.region, xrgn); +- } +-} +- +-void rfb::Region::setExtentsAndOrderedRects(const ShortRect* extents, +- int nRects, const ShortRect* rects) +-{ +- if (xrgn->size < nRects) +- { +- BOX* prevRects = xrgn->rects; +- xrgn->rects = (BOX*)Xrealloc((char*)xrgn->rects, nRects * sizeof(BOX)); +- if (!xrgn->rects) { +- fprintf(stderr,"Xrealloc failed\n"); +- Xfree(prevRects); +- return; +- } +- xrgn->size = nRects; +- } +- +- xrgn->numRects = nRects; +- xrgn->extents.x1 = extents->x1; +- xrgn->extents.y1 = extents->y1; +- xrgn->extents.x2 = extents->x2; +- xrgn->extents.y2 = extents->y2; +- for (int i = 0; i < nRects; i++) { +- xrgn->rects[i].x1 = rects[i].x1; +- xrgn->rects[i].y1 = rects[i].y1; +- xrgn->rects[i].x2 = rects[i].x2; +- xrgn->rects[i].y2 = rects[i].y2; +- } +-} +- +-void rfb::Region::copyFrom(const rfb::Region& r) { +- XUnionRegion(r.xrgn, r.xrgn, xrgn); ++ pixman_region_translate(rgn, delta.x, delta.y); + } + + void rfb::Region::assign_intersect(const rfb::Region& r) { +- XIntersectRegion(xrgn, r.xrgn, xrgn); ++ pixman_region_intersect(rgn, rgn, r.rgn); + } + + void rfb::Region::assign_union(const rfb::Region& r) { +- XUnionRegion(xrgn, r.xrgn, xrgn); ++ pixman_region_union(rgn, rgn, r.rgn); + } + + void rfb::Region::assign_subtract(const rfb::Region& r) { +- XSubtractRegion(xrgn, r.xrgn, xrgn); +++ pixman_region_subtract(rgn, rgn, r.rgn); + } + + rfb::Region rfb::Region::intersect(const rfb::Region& r) const { + rfb::Region ret; +- XIntersectRegion(xrgn, r.xrgn, ret.xrgn); ++ pixman_region_intersect(ret.rgn, rgn, r.rgn); + return ret; + } + + rfb::Region rfb::Region::union_(const rfb::Region& r) const { + rfb::Region ret; +- XUnionRegion(xrgn, r.xrgn, ret.xrgn); ++ pixman_region_union(ret.rgn, rgn, r.rgn); + return ret; + } + + rfb::Region rfb::Region::subtract(const rfb::Region& r) const { + rfb::Region ret; +- XSubtractRegion(xrgn, r.xrgn, ret.xrgn); ++ pixman_region_subtract(ret.rgn, rgn, r.rgn); + return ret; + } + + bool rfb::Region::equals(const rfb::Region& r) const { +- return XEqualRegion(xrgn, r.xrgn); ++ return pixman_region_equal(rgn, r.rgn); + } + + int rfb::Region::numRects() const { +- return xrgn->numRects; ++ return pixman_region_n_rects(rgn); + } + + bool rfb::Region::get_rects(std::vector* rects, + bool left2right, bool topdown, int maxArea) const + { +- int nRects = xrgn->numRects; +- int xInc = left2right ? 1 : -1; +- int yInc = topdown ? 1 : -1; +- int i = topdown ? 0 : nRects-1; +- rects->clear(); +- rects->reserve(nRects); ++ int nRects; ++ const pixman_box16_t* boxes; ++ int xInc, yInc, i; ++ ++ boxes = pixman_region_rectangles(rgn, &nRects); ++ ++ xInc = left2right ? 1 : -1; ++ yInc = topdown ? 1 : -1; ++ i = topdown ? 0 : nRects-1; + + while (nRects > 0) { + int firstInNextBand = i; + int nRectsInBand = 0; + +- while (nRects > 0 && xrgn->rects[firstInNextBand].y1 == xrgn->rects[i].y1) ++ while (nRects > 0 && boxes[firstInNextBand].y1 == boxes[i].y1) + { + firstInNextBand += yInc; + nRects--; +@@ -210,18 +131,10 @@ bool rfb::Region::get_rects(std::vector* rects, + i = firstInNextBand - yInc; + + while (nRectsInBand > 0) { +- int y = xrgn->rects[i].y1; +- int h = maxArea / (xrgn->rects[i].x2 - xrgn->rects[i].x1); +- if (!h) h = xrgn->rects[i].y2 - y; +- do { +- if (h > xrgn->rects[i].y2 - y) +- h = xrgn->rects[i].y2 - y; +- Rect r(xrgn->rects[i].x1, y, xrgn->rects[i].x2, y+h); +- rects->push_back(r); +- y += h; +- } while (y < xrgn->rects[i].y2); +- i += xInc; +- nRectsInBand--; ++ Rect r(boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2); ++ rects->push_back(r); ++ i += xInc; ++ nRectsInBand--; + } + + i = firstInNextBand; +@@ -231,22 +144,28 @@ bool rfb::Region::get_rects(std::vector* rects, + } + + rfb::Rect rfb::Region::get_bounding_rect() const { +- return Rect(xrgn->extents.x1, xrgn->extents.y1, +- xrgn->extents.x2, xrgn->extents.y2); ++ const pixman_box16_t* extents; ++ extents = pixman_region_extents(rgn); ++ return Rect(extents->x1, extents->y1, extents->x2, extents->y2); + } + + + void rfb::Region::debug_print(const char* prefix) const + { ++ Rect extents; ++ std::vector rects; ++ std::vector::const_iterator iter; ++ ++ extents = get_bounding_rect(); ++ get_rects(&rects); ++ + fprintf(stderr,"%s num rects %3ld extents %3d,%3d %3dx%3d\n", +- prefix, xrgn->numRects, xrgn->extents.x1, xrgn->extents.y1, +- xrgn->extents.x2-xrgn->extents.x1, +- xrgn->extents.y2-xrgn->extents.y1); ++ prefix, (long)rects.size(), extents.tl.x, extents.tl.y, ++ extents.width(), extents.height()); + +- for (int i = 0; i < xrgn->numRects; i++) { ++ for (iter = rects.begin(); iter != rects.end(); ++iter) { + fprintf(stderr," rect %3d,%3d %3dx%3d\n", +- xrgn->rects[i].x1, xrgn->rects[i].y1, +- xrgn->rects[i].x2-xrgn->rects[i].x1, +- xrgn->rects[i].y2-xrgn->rects[i].y1); ++ iter->tl.x, iter->tl.y, iter->width(), iter->height()); ++ + } + } +diff --git a/common/rfb/Region.h b/common/rfb/Region.h +index 9337556..c12beed 100644 +--- a/common/rfb/Region.h ++++ b/common/rfb/Region.h +@@ -1,4 +1,5 @@ + /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. ++ * Copyright 2016-2020 Pierre Ossman for Cendio AB + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -16,7 +17,7 @@ + * USA. + */ + +-// Cross-platform Region class based on the X11 region implementation ++// Region class wrapper around pixman's region operations + + #ifndef __RFB_REGION_INCLUDED__ + #define __RFB_REGION_INCLUDED__ +@@ -24,14 +25,10 @@ + #include + #include + +-struct _XRegion; ++struct pixman_region16; + + namespace rfb { + +- struct ShortRect { +- short x1, y1, x2, y2; +- }; +- + class Region { + public: + // Create an empty region +@@ -49,10 +46,6 @@ namespace rfb { + void clear(); + void reset(const Rect& r); + void translate(const rfb::Point& delta); +- void setOrderedRects(const std::vector& rects); +- void setExtentsAndOrderedRects(const ShortRect* extents, int nRects, +- const ShortRect* rects); +- void copyFrom(const Region& r); + + void assign_intersect(const Region& r); + void assign_union(const Region& r); +@@ -76,7 +69,7 @@ namespace rfb { + + protected: + +- struct _XRegion* xrgn; ++ struct pixman_region16* rgn; + }; + + }; +diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx +index d2206f9..d1c7709 100644 +--- a/common/rfb/VNCSConnectionST.cxx ++++ b/common/rfb/VNCSConnectionST.cxx +@@ -1028,7 +1028,7 @@ void VNCSConnectionST::writeDataUpdate() + if (!ui.copied.is_empty() && !damagedCursorRegion.is_empty()) { + Region bogusCopiedCursor; + +- bogusCopiedCursor.copyFrom(damagedCursorRegion); ++ bogusCopiedCursor = damagedCursorRegion; + bogusCopiedCursor.translate(ui.copy_delta); + bogusCopiedCursor.assign_intersect(server->pb->getRect()); + if (!ui.copied.intersect(bogusCopiedCursor).is_empty()) { +diff --git a/unix/xserver/hw/vnc/Makefile.am b/unix/xserver/hw/vnc/Makefile.am +index 0d6a4ac..9a26e45 100644 +--- a/unix/xserver/hw/vnc/Makefile.am ++++ b/unix/xserver/hw/vnc/Makefile.am +@@ -5,8 +5,7 @@ RFB_LIB=$(LIB_DIR)/rfb/librfb.la + RDR_LIB=$(LIB_DIR)/rdr/librdr.la + OS_LIB=$(LIB_DIR)/os/libos.la + NETWORK_LIB=$(LIB_DIR)/network/libnetwork.la +-XREGION_LIB=$(LIB_DIR)/Xregion/libXregion.la +-COMMON_LIBS=$(NETWORK_LIB) $(RFB_LIB) $(RDR_LIB) $(XREGION_LIB) $(OS_LIB) ++COMMON_LIBS=$(NETWORK_LIB) $(RFB_LIB) $(RDR_LIB) $(OS_LIB) + + noinst_LTLIBRARIES = libvnccommon.la + +diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc +index 57bf6d8..b369ec3 100644 +--- a/unix/xserver/hw/vnc/vncExtInit.cc ++++ b/unix/xserver/hw/vnc/vncExtInit.cc +@@ -149,11 +149,6 @@ void vncExtensionInit(void) + return; + } + +- if (sizeof(ShortRect) != sizeof(struct UpdateRect)) { +- vlog.error("vncExtensionInit: Incompatible ShortRect size"); +- return; +- } +- + ret = vncAddExtension(); + if (ret == -1) + return; +@@ -358,25 +353,24 @@ void vncBell() + } + } + +-void vncAddChanged(int scrIdx, const struct UpdateRect *extents, +- int nRects, const struct UpdateRect *rects) ++void vncAddChanged(int scrIdx, int nRects, ++ const struct UpdateRect *rects) + { +- Region reg; +- +- reg.setExtentsAndOrderedRects((const ShortRect*)extents, +- nRects, (const ShortRect*)rects); +- desktop[scrIdx]->add_changed(reg); ++ for (int i = 0;i < nRects;i++) { ++ desktop[scrIdx]->add_changed(Region(Rect(rects[i].x1, rects[i].y1, ++ rects[i].x2, rects[i].y2))); ++ } + } + +-void vncAddCopied(int scrIdx, const struct UpdateRect *extents, +- int nRects, const struct UpdateRect *rects, ++void vncAddCopied(int scrIdx, int nRects, ++ const struct UpdateRect *rects, + int dx, int dy) + { +- Region reg; +- +- reg.setExtentsAndOrderedRects((const ShortRect*)extents, +- nRects, (const ShortRect*)rects); +- desktop[scrIdx]->add_copied(reg, rfb::Point(dx, dy)); ++ for (int i = 0;i < nRects;i++) { ++ desktop[scrIdx]->add_copied(Region(Rect(rects[i].x1, rects[i].y1, ++ rects[i].x2, rects[i].y2)), ++ Point(dx, dy)); ++ } + } + + void vncSetCursor(int width, int height, int hotX, int hotY, +diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h +index 9f8d9e7..0d7d691 100644 +--- a/unix/xserver/hw/vnc/vncExtInit.h ++++ b/unix/xserver/hw/vnc/vncExtInit.h +@@ -76,10 +76,10 @@ struct UpdateRect { + short x1, y1, x2, y2; + }; + +-void vncAddChanged(int scrIdx, const struct UpdateRect *extents, +- int nRects, const struct UpdateRect *rects); +-void vncAddCopied(int scrIdx, const struct UpdateRect *extents, +- int nRects, const struct UpdateRect *rects, ++void vncAddChanged(int scrIdx, int nRects, ++ const struct UpdateRect *rects); ++void vncAddCopied(int scrIdx, int nRects, ++ const struct UpdateRect *rects, + int dx, int dy); + + void vncSetCursor(int width, int height, int hotX, int hotY, +diff --git a/unix/xserver/hw/vnc/vncHooks.c b/unix/xserver/hw/vnc/vncHooks.c +index 5b90f53..498ee3d 100644 +--- a/unix/xserver/hw/vnc/vncHooks.c ++++ b/unix/xserver/hw/vnc/vncHooks.c +@@ -369,9 +369,8 @@ static inline void add_changed(ScreenPtr pScreen, RegionPtr reg) + if (vncHooksScreen->ignoreHooks) + return; + vncAddChanged(pScreen->myNum, +- (const struct UpdateRect*)REGION_EXTENTS(pScreen, reg), +- REGION_NUM_RECTS(reg), +- (const struct UpdateRect*)REGION_RECTS(reg)); ++ RegionNumRects(reg), ++ (const struct UpdateRect*)RegionRects(reg)); + } + + static inline void add_copied(ScreenPtr pScreen, RegionPtr dst, +@@ -381,9 +380,8 @@ static inline void add_copied(ScreenPtr pScreen, RegionPtr dst, + if (vncHooksScreen->ignoreHooks) + return; + vncAddCopied(pScreen->myNum, +- (const struct UpdateRect*)REGION_EXTENTS(pScreen, dst), +- REGION_NUM_RECTS(dst), +- (const struct UpdateRect*)REGION_RECTS(dst), dx, dy); ++ RegionNumRects(dst), ++ (const struct UpdateRect*)RegionRects(dst), dx, dy); + } + + static inline Bool is_visible(DrawablePtr drawable) +@@ -515,15 +513,15 @@ static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + + SCREEN_PROLOGUE(pWin->drawable.pScreen, CopyWindow); + +- REGION_NULL(pScreen, &copied); +- REGION_COPY(pScreen, &copied, pOldRegion); ++ RegionNull(&copied); ++ RegionCopy(&copied, pOldRegion); + + screen_box.x1 = 0; + screen_box.y1 = 0; + screen_box.x2 = pScreen->width; + screen_box.y2 = pScreen->height; + +- REGION_INIT(pScreen, &screen_rgn, &screen_box, 1); ++ RegionInitBoxes(&screen_rgn, &screen_box, 1); + + dx = pWin->drawable.x - ptOldOrg.x; + dy = pWin->drawable.y - ptOldOrg.y; +@@ -532,18 +530,18 @@ static void vncHooksCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + // We also need to copy with changes to the Window's clipping region. + // Finally, make sure we don't get copies to or from regions outside + // the framebuffer. +- REGION_INTERSECT(pScreen, &copied, &copied, &screen_rgn); +- REGION_TRANSLATE(pScreen, &copied, dx, dy); +- REGION_INTERSECT(pScreen, &copied, &copied, &screen_rgn); +- REGION_INTERSECT(pScreen, &copied, &copied, &pWin->borderClip); ++ RegionIntersect(&copied, &copied, &screen_rgn); ++ RegionTranslate(&copied, dx, dy); ++ RegionIntersect(&copied, &copied, &screen_rgn); ++ RegionIntersect(&copied, &copied, &pWin->borderClip); + + (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion); + + if (REGION_NOTEMPTY(pScreen, &copied)) + add_copied(pScreen, &copied, dx, dy); + +- REGION_UNINIT(pScreen, &copied); +- REGION_UNINIT(pScreen, &screen_rgn); ++ RegionUninit(&copied); ++ RegionUninit(&screen_rgn); + + SCREEN_EPILOGUE(CopyWindow); + } +@@ -564,8 +562,8 @@ static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w, + box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width); + box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height); + +- REGION_INIT(pScreen, ®, &box, 0); +- REGION_INTERSECT(pScreen, ®, ®, &pWin->clipList); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, &pWin->clipList); + + (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures); + +@@ -573,7 +571,7 @@ static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w, + add_changed(pScreen, ®); + } + +- REGION_UNINIT(pScreen, ®); ++ RegionUninit(®); + + SCREEN_EPILOGUE(ClearToBackground); + } +@@ -765,19 +763,19 @@ static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + box.y1 = max(pDst->pDrawable->y + yDst, 0); + box.x2 = box.x1 + width; + box.y2 = box.y1 + height; +- REGION_INIT(pScreen, &changed, &box, 0); ++ RegionInitBoxes(&changed, &box, 1); + + box.x1 = 0; + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; +- REGION_INIT(pScreen, &fbreg, &box, 0); ++ RegionInitBoxes(&fbreg, &box, 1); + +- REGION_INTERSECT(pScreen, &changed, &changed, &fbreg); ++ RegionIntersect(&changed, &changed, &fbreg); + +- REGION_UNINIT(pScreen, &fbreg); ++ RegionUninit(&fbreg); + } else { +- REGION_NULL(pScreen, &changed); ++ RegionNull(&changed); + } + + +@@ -787,7 +785,7 @@ static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, + if (REGION_NOTEMPTY(pScreen, &changed)) + add_changed(pScreen, &changed); + +- REGION_UNINIT(pScreen, &changed); ++ RegionUninit(&changed); + + RENDER_EPILOGUE(Composite); + } +@@ -855,20 +853,20 @@ static void vncHooksGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + RegionRec fbreg; + + changed = GlyphsToRegion(pScreen, nlists, lists, glyphs); +- REGION_TRANSLATE(pScreen, changed, ++ RegionTranslate(changed, + pDst->pDrawable->x, pDst->pDrawable->y); + + fbbox.x1 = 0; + fbbox.y1 = 0; + fbbox.x2 = pScreen->width; + fbbox.y2 = pScreen->height; +- REGION_INIT(pScreen, &fbreg, &fbbox, 0); ++ RegionInitBoxes(&fbreg, &fbbox, 1); + +- REGION_INTERSECT(pScreen, changed, changed, &fbreg); ++ RegionIntersect(changed, changed, &fbreg); + +- REGION_UNINIT(pScreen, &fbreg); ++ RegionUninit(&fbreg); + } else { +- changed = REGION_CREATE(pScreen, NullBox, 0); ++ changed = RegionCreate(NullBox, 0); + } + + (*ps->Glyphs)(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlists, lists, glyphs); +@@ -876,7 +874,7 @@ static void vncHooksGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, + if (REGION_NOTEMPTY(pScreen, changed)) + add_changed(pScreen, changed); + +- REGION_DESTROY(pScreen, changed); ++ RegionDestroy(changed); + + RENDER_EPILOGUE(Glyphs); + } +@@ -1067,17 +1065,17 @@ static void vncHooksFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nInit, + + GC_OP_PROLOGUE(pGC, FillSpans); + +- REGION_NULL(pGC->pScreen, ®); +- REGION_COPY(pGC->pScreen, ®, pGC->pCompositeClip); ++ RegionNull(®); ++ RegionCopy(®, pGC->pCompositeClip); + + if (pDrawable->type == DRAWABLE_WINDOW) +- REGION_INTERSECT(pScreen, ®, ®, &((WindowPtr)pDrawable)->borderClip); ++ RegionIntersect(®, ®, &((WindowPtr)pDrawable)->borderClip); + + (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + GC_OP_EPILOGUE(pGC); + } +@@ -1093,17 +1091,17 @@ static void vncHooksSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc, + + GC_OP_PROLOGUE(pGC, SetSpans); + +- REGION_NULL(pGC->pScreen, ®); +- REGION_COPY(pGC->pScreen, ®, pGC->pCompositeClip); ++ RegionNull(®); ++ RegionCopy(®, pGC->pCompositeClip); + + if (pDrawable->type == DRAWABLE_WINDOW) +- REGION_INTERSECT(pScreen, ®, ®, &((WindowPtr)pDrawable)->borderClip); ++ RegionIntersect(®, ®, &((WindowPtr)pDrawable)->borderClip); + + (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + GC_OP_EPILOGUE(pGC); + } +@@ -1124,15 +1122,15 @@ static void vncHooksPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth, + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h, leftPad, format, + pBits); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + GC_OP_EPILOGUE(pGC); + } +@@ -1153,7 +1151,7 @@ static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst, + + // Apparently this happens now and then... + if ((w == 0) || (h == 0)) +- REGION_NULL(pGC->pScreen, &dst); ++ RegionNull(&dst); + else { + BoxRec box; + +@@ -1162,10 +1160,10 @@ static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst, + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + +- REGION_INIT(pGC->pScreen, &dst, &box, 0); ++ RegionInitBoxes(&dst, &box, 1); + } + +- REGION_INTERSECT(pGC->pScreen, &dst, &dst, pGC->pCompositeClip); ++ RegionIntersect(&dst, &dst, pGC->pCompositeClip); + + // The source of the data has to be something that's on screen. + if (is_visible(pSrc)) { +@@ -1176,24 +1174,24 @@ static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst, + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + +- REGION_INIT(pGC->pScreen, &src, &box, 0); ++ RegionInitBoxes(&src, &box, 1); + + if ((pSrc->type == DRAWABLE_WINDOW) && +- REGION_NOTEMPTY(pScreen, &((WindowPtr)pSrc)->clipList)) { +- REGION_INTERSECT(pScreen, &src, &src, &((WindowPtr)pSrc)->clipList); ++ RegionNotEmpty(&((WindowPtr)pSrc)->clipList)) { ++ RegionIntersect(&src, &src, &((WindowPtr)pSrc)->clipList); + } + +- REGION_TRANSLATE(pScreen, &src, ++ RegionTranslate(&src, + dstx + pDst->x - srcx - pSrc->x, + dsty + pDst->y - srcy - pSrc->y); + } else { +- REGION_NULL(pGC->pScreen, &src); ++ RegionNull(&src); + } + +- REGION_NULL(pGC->pScreen, &changed); ++ RegionNull(&changed); + +- REGION_SUBTRACT(pScreen, &changed, &dst, &src); +- REGION_INTERSECT(pScreen, &dst, &dst, &src); ++ RegionSubtract(&changed, &dst, &src); ++ RegionIntersect(&dst, &dst, &src); + + ret = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty); + +@@ -1205,9 +1203,9 @@ static RegionPtr vncHooksCopyArea(DrawablePtr pSrc, DrawablePtr pDst, + if (REGION_NOTEMPTY(pScreen, &changed)) + add_changed(pGC->pScreen, &changed); + +- REGION_UNINIT(pGC->pScreen, &dst); +- REGION_UNINIT(pGC->pScreen, &src); +- REGION_UNINIT(pGC->pScreen, &changed); ++ RegionUninit(&dst); ++ RegionUninit(&src); ++ RegionUninit(&changed); + + GC_OP_EPILOGUE(pGC); + +@@ -1234,15 +1232,15 @@ static RegionPtr vncHooksCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + ret = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h, + dstx, dsty, plane); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + GC_OP_EPILOGUE(pGC); + +@@ -1298,14 +1296,14 @@ static void vncHooksPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, + box.x2 = maxX + 1 + pDrawable->x; + box.y2 = maxY + 1 + pDrawable->y; + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + out: + GC_OP_EPILOGUE(pGC); +@@ -1425,13 +1423,13 @@ static void vncHooksPolylines(DrawablePtr pDrawable, GCPtr pGC, int mode, + } + + reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE); +- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip); ++ RegionIntersect(reg, reg, pGC->pCompositeClip); + + (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts); + + add_changed(pGC->pScreen, reg); + +- REGION_DESTROY(pGC->pScreen, reg); ++ RegionDestroy(reg); + + out: + GC_OP_EPILOGUE(pGC); +@@ -1510,13 +1508,13 @@ static void vncHooksPolySegment(DrawablePtr pDrawable, GCPtr pGC, int nseg, + } + + reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE); +- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip); ++ RegionIntersect(reg, reg, pGC->pCompositeClip); + + (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs); + + add_changed(pGC->pScreen, reg); + +- REGION_DESTROY(pGC->pScreen, reg); ++ RegionDestroy(reg); + + out: + GC_OP_EPILOGUE(pGC); +@@ -1599,13 +1597,13 @@ static void vncHooksPolyRectangle(DrawablePtr pDrawable, GCPtr pGC, int nrects, + } + + reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE); +- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip); ++ RegionIntersect(reg, reg, pGC->pCompositeClip); + + (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects); + + add_changed(pGC->pScreen, reg); + +- REGION_DESTROY(pGC->pScreen, reg); ++ RegionDestroy(reg); + + out: + GC_OP_EPILOGUE(pGC); +@@ -1674,13 +1672,13 @@ static void vncHooksPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, + } + + reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE); +- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip); ++ RegionIntersect(reg, reg, pGC->pCompositeClip); + + (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs); + + add_changed(pGC->pScreen, reg); + +- REGION_DESTROY(pGC->pScreen, reg); ++ RegionDestroy(reg); + + out: + GC_OP_EPILOGUE(pGC); +@@ -1737,14 +1735,14 @@ static void vncHooksFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape, + box.x2 = maxX + 1 + pDrawable->x; + box.y2 = maxY + 1 + pDrawable->y; + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + out: + GC_OP_EPILOGUE(pGC); +@@ -1803,13 +1801,13 @@ static void vncHooksPolyFillRect(DrawablePtr pDrawable, GCPtr pGC, int nrects, + } + + reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE); +- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip); ++ RegionIntersect(reg, reg, pGC->pCompositeClip); + + (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects); + + add_changed(pGC->pScreen, reg); + +- REGION_DESTROY(pGC->pScreen, reg); ++ RegionDestroy(reg); + + out: + GC_OP_EPILOGUE(pGC); +@@ -1878,13 +1876,13 @@ static void vncHooksPolyFillArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, + } + + reg = RECTS_TO_REGION(pGC->pScreen, nRegRects, regRects, CT_NONE); +- REGION_INTERSECT(pGC->pScreen, reg, reg, pGC->pCompositeClip); ++ RegionIntersect(reg, reg, pGC->pCompositeClip); + + (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs); + + add_changed(pGC->pScreen, reg); + +- REGION_DESTROY(pGC->pScreen, reg); ++ RegionDestroy(reg); + + out: + GC_OP_EPILOGUE(pGC); +@@ -1929,14 +1927,14 @@ static int vncHooksPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + + GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box); + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + out: + GC_OP_EPILOGUE(pGC); +@@ -1963,14 +1961,14 @@ static int vncHooksPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + + GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box); + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + out: + GC_OP_EPILOGUE(pGC); +@@ -1996,14 +1994,14 @@ static void vncHooksImageText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + + GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box); + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + out: + GC_OP_EPILOGUE(pGC); +@@ -2027,14 +2025,14 @@ static void vncHooksImageText16(DrawablePtr pDrawable, GCPtr pGC, int x, int y, + + GetTextBoundingRect(pDrawable, pGC->font, x, y, count, &box); + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + out: + GC_OP_EPILOGUE(pGC); +@@ -2059,14 +2057,14 @@ static void vncHooksImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, + + GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box); + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + out: + GC_OP_EPILOGUE(pGC); +@@ -2091,14 +2089,14 @@ static void vncHooksPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, + + GetTextBoundingRect(pDrawable, pGC->font, x, y, nglyph, &box); + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + out: + GC_OP_EPILOGUE(pGC); +@@ -2121,14 +2119,14 @@ static void vncHooksPushPixels(GCPtr pGC, PixmapPtr pBitMap, + box.x2 = box.x1 + w; + box.y2 = box.y1 + h; + +- REGION_INIT(pGC->pScreen, ®, &box, 0); +- REGION_INTERSECT(pGC->pScreen, ®, ®, pGC->pCompositeClip); ++ RegionInitBoxes(®, &box, 1); ++ RegionIntersect(®, ®, pGC->pCompositeClip); + + (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y); + + add_changed(pGC->pScreen, ®); + +- REGION_UNINIT(pGC->pScreen, ®); ++ RegionUninit(®); + + GC_OP_EPILOGUE(pGC); + } +diff --git a/unix/xserver/hw/vnc/xvnc.c b/unix/xserver/hw/vnc/xvnc.c +index 93d8af4..dccea9c 100644 +--- a/unix/xserver/hw/vnc/xvnc.c ++++ b/unix/xserver/hw/vnc/xvnc.c +@@ -1000,8 +1000,8 @@ xf86SetRootClip (ScreenPtr pScreen, Bool enable) + { + RegionPtr borderVisible; + +- borderVisible = REGION_CREATE(pScreen, NullBox, 1); +- REGION_SUBTRACT(pScreen, borderVisible, ++ borderVisible = RegionCreate(NullBox, 1); ++ RegionSubtract(borderVisible, + &pWin->borderClip, &pWin->winSize); + pWin->valdata->before.borderVisible = borderVisible; + } +@@ -1010,7 +1010,7 @@ xf86SetRootClip (ScreenPtr pScreen, Bool enable) + } + + /* +- * Use REGION_BREAK to avoid optimizations in ValidateTree ++ * Use RegionBreak to avoid optimizations in ValidateTree + * that assume the root borderClip can't change well, normally + * it doesn't...) + */ +@@ -1020,18 +1020,18 @@ xf86SetRootClip (ScreenPtr pScreen, Bool enable) + box.y1 = 0; + box.x2 = pScreen->width; + box.y2 = pScreen->height; +- REGION_INIT (pScreen, &pWin->winSize, &box, 1); +- REGION_INIT (pScreen, &pWin->borderSize, &box, 1); ++ RegionInit(&pWin->winSize, &box, 1); ++ RegionInit(&pWin->borderSize, &box, 1); + if (WasViewable) +- REGION_RESET(pScreen, &pWin->borderClip, &box); ++ RegionReset(&pWin->borderClip, &box); + pWin->drawable.width = pScreen->width; + pWin->drawable.height = pScreen->height; +- REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); ++ RegionBreak(&pWin->clipList); + } + else + { +- REGION_EMPTY(pScreen, &pWin->borderClip); +- REGION_BREAK (pWin->drawable.pScreen, &pWin->clipList); ++ RegionEmpty(&pWin->borderClip); ++ RegionBreak(&pWin->clipList); + } + + ResizeChildrenWinSize (pWin, 0, 0, 0, 0); diff --git a/SPECS/tigervnc.spec b/SPECS/tigervnc.spec index 34a3e48..fcc66f5 100644 --- a/SPECS/tigervnc.spec +++ b/SPECS/tigervnc.spec @@ -1,6 +1,6 @@ Name: tigervnc Version: 1.8.0 -Release: 21%{?dist} +Release: 22%{?dist} Summary: A TigerVNC remote display system Group: User Interface/Desktops @@ -65,6 +65,7 @@ Patch16: tigervnc-fix-rendering-on-big-endian-systems.patch Patch17: tigervnc-xvnc-update-manpage.patch Patch18: tigervnc-release-pointer-grab-when-cursor-leaves-window.patch Patch19: tigervnc-provide-correct-dimensions-for-xshm-setup.patch +Patch20: tigervnc-region-handling.patch # This is tigervnc-%{version}/unix/xserver116.patch rebased on the latest xorg Patch100: tigervnc-xserver120.patch @@ -227,6 +228,8 @@ popd %patch18 -p1 -b .release-pointer-grab-when-cursor-leaves-window +%patch20 -p1 -b .region-handling + # Security fixes %patch200 -p1 -b .CVE-2019-15691 %patch201 -p1 -b .encapsulate-pixelbuffer-internal-details @@ -409,6 +412,10 @@ fi %{_datadir}/icons/hicolor/*/apps/* %changelog +* Thu Jul 09 2020 Jan Grulich - 1.8.0-22 +- Region handling refresh + Resolves: bz#1753158 + * Wed Apr 22 2020 Jan Grulich - 1.8.0-21 - Add upstream patch needed because of previous security fixes Resolves: bz#1826822