home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / region.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  8.3 KB  |  326 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* 
  19.  *   region.cpp --- FE specific region operations
  20.  */
  21.  
  22.  
  23. #include "mozilla.h"
  24. #include "xfe.h"
  25. #include "fe_rgn.h"
  26. #include "region.h"  /* Internal X region structures.  We need these to      */
  27.                      /* iterate over rect lists in FE_ForEachRectInRegion(). */
  28.  
  29. /* Creates an empty region. Returns NULL if region can't be created */
  30. FE_Region
  31. FE_CreateRegion()
  32. {
  33.   return (FE_Region)XCreateRegion();
  34. }
  35.  
  36. /* Creates a region from a rectangle. Returns NULL if region can't be created */
  37. FE_Region
  38. FE_CreateRectRegion(XP_Rect *rect)
  39. {
  40.   XPoint points[4];
  41.  
  42.   points[0].x = points[3].x = (short)rect->left;  /* points[] corresponds to */
  43.   points[0].y = points[1].y = (short)rect->top;   /* top-left, top-right,    */
  44.   points[1].x = points[2].x = (short)rect->right; /* bot-left and bot-right  */
  45.   points[3].y = points[2].y = (short)rect->bottom;/* respectively.           */
  46.  
  47.   return (FE_Region)XPolygonRegion(points, 4, EvenOddRule);
  48.                                 /* Fill rule is irrelevant since there */
  49.                                 /* should be no self overlap.          */
  50. }
  51.  
  52. /* Set an existing region to a rectangle.                                  */
  53. /* The purpose of this routine is to avoid the overhead of destroying and  */
  54. /* recreating a region on the Windows platform.  Unfortunately, it doesn't */
  55. /* do much for X.                                                          */
  56. FE_Region 
  57. FE_SetRectRegion(FE_Region region, XP_Rect *rect)
  58. {
  59.   XRectangle rectangle;
  60.  
  61.   XP_ASSERT(region);
  62.  
  63.   if (!XEmptyRegion((Region)region))    /* If region is not empty.      */
  64.     XSubtractRegion((Region)region, (Region)region, (Region)region);
  65.                                         /* Subtract region from itself. */
  66.   XP_ASSERT(XEmptyRegion((Region)region));
  67.  
  68.   rectangle.x = (short)rect->left;
  69.   rectangle.y = (short)rect->top;
  70.   rectangle.width = (unsigned short)(rect->right - rect->left);
  71.   rectangle.height = (unsigned short)(rect->bottom - rect->top);
  72.  
  73.   return (FE_Region)XUnionRectWithRegion(&rectangle, (Region)region,
  74.                                          (Region)region);
  75. }
  76.  
  77. /* Destroys region */
  78. void
  79. FE_DestroyRegion(FE_Region region)
  80. {
  81.   XP_ASSERT(region);
  82.   XDestroyRegion((Region)region);
  83. }
  84.  
  85. /* Make a copy of a region */
  86. FE_Region
  87. FE_CopyRegion(FE_Region src, FE_Region dst)
  88. {
  89.   Region copyRegion;
  90.  
  91.   XP_ASSERT(src);
  92.  
  93.   if (dst != NULL) {
  94.     copyRegion = (Region)dst;
  95.   }
  96.   else {
  97.     /* Create an empty region */
  98.     copyRegion = XCreateRegion();
  99.     
  100.     if (copyRegion == NULL)
  101.       return NULL;
  102.   }
  103.  
  104.   /* Copy the region */
  105.   XUnionRegion((Region)src, (Region)src, (Region)copyRegion);
  106.  
  107.   return (FE_Region)copyRegion;
  108. }
  109.  
  110. /* dst = src1 intersect sr2       */
  111. /* dst can be one of src1 or src2 */
  112. void
  113. FE_IntersectRegion(FE_Region src1, FE_Region src2, FE_Region dst)
  114. {
  115.   XP_ASSERT(src1);
  116.   XP_ASSERT(src2);
  117.   XP_ASSERT(dst);
  118.  
  119.   XIntersectRegion((Region)src1, (Region)src2, (Region)dst);
  120. }
  121.  
  122. /* dst = src1 union src2          */
  123. /* dst can be one of src1 or src2 */
  124. void
  125. FE_UnionRegion(FE_Region src1, FE_Region src2, FE_Region dst)
  126. {
  127.   XP_ASSERT(src1);
  128.   XP_ASSERT(src2);
  129.   XP_ASSERT(dst);
  130.  
  131.   XUnionRegion((Region)src1, (Region)src2, (Region)dst);
  132. }
  133.  
  134. /* dst = src1 - src2              */
  135. /* dst can be one of src1 or src2 */
  136. void
  137. FE_SubtractRegion(FE_Region src1, FE_Region src2, FE_Region dst)
  138. {
  139.   XP_ASSERT(src1);
  140.   XP_ASSERT(src2);
  141.   XP_ASSERT(dst);
  142.  
  143.   XSubtractRegion((Region)src1, (Region)src2, (Region)dst);
  144. }
  145.  
  146. /* Returns TRUE if the region contains no pixels */
  147. XP_Bool
  148. FE_IsEmptyRegion(FE_Region region)
  149. {
  150.   XP_ASSERT(region);
  151.  
  152.   return (XP_Bool)XEmptyRegion((Region)region);
  153. }
  154.  
  155. /* Returns the bounding rectangle of the region */
  156. void
  157. FE_GetRegionBoundingBox(FE_Region region, XP_Rect *bbox)
  158. {
  159.   XRectangle rect;
  160.  
  161.   XP_ASSERT(region);
  162.   XP_ASSERT(bbox);
  163.  
  164.   XClipBox((Region)region, &rect);
  165.  
  166.   bbox->left = (int32)rect.x;
  167.   bbox->top = (int32)rect.y;
  168.   bbox->right = (int32)(rect.x + rect.width);
  169.   bbox->bottom = (int32)(rect.y + rect.height);
  170. }
  171.  
  172. /* TRUE if rgn1 == rgn2 */
  173. XP_Bool
  174. FE_IsEqualRegion(FE_Region rgn1, FE_Region rgn2)
  175. {
  176.   XP_ASSERT(rgn1);
  177.   XP_ASSERT(rgn2);
  178.  
  179.   return (XP_Bool)XEqualRegion((Region)rgn1, (Region)rgn2);
  180. }
  181.  
  182. /* Moves a region by the specified offsets */
  183. void
  184. FE_OffsetRegion(FE_Region region, int32 x_offset, int32 y_offset)
  185. {
  186.   XOffsetRegion((Region)region, x_offset, y_offset);
  187. }
  188.  
  189. /* Returns TRUE if any part of the rectangle is in the specified region */
  190. XP_Bool
  191. FE_RectInRegion(FE_Region region, XP_Rect *rect)
  192. {
  193.   int result;
  194.   XRectangle box;
  195.  
  196.   XP_ASSERT(region);
  197.   XP_ASSERT(rect);
  198.  
  199.   box.x = (short)rect->left;
  200.   box.y = (short)rect->top;
  201.   box.width = (unsigned short)(rect->right - rect->left);
  202.   box.height = (unsigned short)(rect->bottom - rect->top);
  203.  
  204.   result = XRectInRegion((Region)region, box.x, box.y, box.width, box.height);
  205.  
  206.   if (result == RectangleOut)
  207.     return FALSE;
  208.   else                /* result == RectangleIn || result == RectanglePart */
  209.     return TRUE;
  210. }
  211.  
  212.  
  213. /* Calls the specified function for each rectangle that makes up the region */
  214. void
  215. FE_ForEachRectInRegion(FE_Region region, FE_RectInRegionFunc func,
  216.                        void *closure)
  217. {
  218.     Region pRegion;
  219.     register int nbox;
  220.     register BOX *pbox;
  221.     XP_Rect rect;
  222.  
  223.     XP_ASSERT(region);
  224.     XP_ASSERT(func);
  225.  
  226.     pRegion = (Region)region;
  227.     pbox = pRegion->rects;
  228.     nbox = pRegion->numRects;
  229.  
  230.     while(nbox--)
  231.         {
  232.             rect.left = pbox->x1;
  233.             rect.right = pbox->x2;
  234.             rect.top = pbox->y1;
  235.             rect.bottom = pbox->y2;
  236.             (*func)(closure, &rect);
  237.             pbox++;
  238.         }
  239. }
  240.  
  241. #ifdef DEBUG
  242. #include "X11/X.h"
  243. #include <sys/time.h>
  244.  
  245. static void
  246. wait_usec(long usec)
  247. {
  248.     struct timeval timeout;
  249.  
  250.     timeout.tv_sec = 0;
  251.     timeout.tv_usec = usec;
  252.     select(0, NULL, NULL, NULL, &timeout);
  253. }
  254.  
  255. static void
  256. fe_InvertRect(MWContext *context, XP_Rect *rect)
  257. {
  258.     Widget wid;
  259.     Display *dpy;
  260.     Window win;
  261.     Screen *screen;
  262.     XGCValues gcv;
  263.     GC gc;
  264.  
  265.     uint32 x, y, w, h;
  266.     
  267.     x = rect->left;
  268.     y = rect->top;
  269.     w = rect->right  - rect->left;
  270.     h = rect->bottom - rect->top;
  271.     
  272.     wid = CONTEXT_DATA (context)->drawing_area;
  273.     if (wid == NULL) return;
  274.     XtVaGetValues (wid, XmNscreen, &screen, 0);
  275.  
  276.     dpy = XtDisplay (wid);
  277.     win = XtWindow (wid);
  278.  
  279.     gcv.function = GXxor;
  280.     gcv.foreground = 0xFFFFFF;
  281.  
  282.     gc = XCreateGC (dpy, win, GCForeground | GCFunction, &gcv);
  283.     XFillRectangle (dpy, win, gc, x, y, w, h);
  284.     XFreeGC (dpy, gc);
  285. }
  286.  
  287. void
  288. FE_HighlightRect(void *c, XP_Rect *rect, int how_much)
  289. {
  290.     MWContext *context = (MWContext*)c;
  291.     while (how_much--) {
  292.         fe_InvertRect(context, rect);
  293.         wait_usec(1000 * how_much);
  294.         fe_InvertRect(context, rect);
  295.     }
  296. }
  297.  
  298. void
  299. fe_HighlightRegion(MWContext *context, FE_Region region)
  300. {
  301.     FE_ForEachRectInRegion(region, 
  302.                            (FE_RectInRegionFunc)fe_InvertRect,
  303.                            (void *)context);
  304. }
  305.  
  306. void
  307. FE_HighlightRegion(void *c, FE_Region region, int how_much)
  308. {
  309.     Widget wid;
  310.     Display *dpy;
  311.     MWContext *context = (MWContext*)c;
  312.     
  313.     wid = CONTEXT_DATA (context)->drawing_area;
  314.     if (wid == NULL) return;
  315.     dpy = XtDisplay (wid);
  316.  
  317.     fe_HighlightRegion(context, region);
  318.     XSync(dpy, 0);
  319.     wait_usec(1000 * how_much);
  320.     fe_HighlightRegion(context, region);
  321.     XSync(dpy, 0);
  322. }
  323.     
  324. #endif /* DEBUG */
  325.  
  326.