home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / liblayer / src / cl_util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  5.6 KB  |  186 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.  *  cl_paint.c - The default layer creation routine
  20.  */
  21.  
  22.  
  23. #include "prtypes.h"
  24. #include "layers.h"
  25. #include "cl_priv.h"
  26.  
  27. /* Convert rectangle from window to document coordinate system */
  28. void
  29. CL_WindowToDocumentRect(CL_Compositor *compositor, XP_Rect *rect)
  30. {
  31.     XP_OffsetRect(rect, compositor->x_offset, compositor->y_offset);
  32. }
  33.  
  34. /* Convert rectangle from document to window coordinate system */
  35. void
  36. CL_DocumentToWindowRect(CL_Compositor *compositor, XP_Rect *rect)
  37. {
  38.     XP_OffsetRect(rect, -compositor->x_offset, -compositor->y_offset);
  39. }
  40.  
  41. /* Convert a rect from window to layer coordinate system */
  42. void
  43. CL_WindowToLayerRect(CL_Compositor *compositor, CL_Layer *layer,
  44.                      XP_Rect *rect)
  45. {
  46.     int32 x_offset = compositor->x_offset - layer->x_origin;
  47.     int32 y_offset = compositor->y_offset - layer->y_origin;
  48.  
  49.     XP_OffsetRect(rect, x_offset, y_offset);
  50. }
  51.  
  52. /* Convert a rect from window to layer coordinate system */
  53. void
  54. CL_LayerToWindowRect(CL_Compositor *compositor, CL_Layer *layer,
  55.                      XP_Rect *rect)
  56. {
  57.     int32 x_offset = compositor->x_offset - layer->x_origin;
  58.     int32 y_offset = compositor->y_offset - layer->y_origin;
  59.  
  60.     XP_OffsetRect(rect, -x_offset, -y_offset);
  61. }
  62.  
  63. /* 
  64.  * The assumption for the next two routines is that the layer is
  65.  * visible within the window i.e. translating to and from layer
  66.  * coordinates won't result in a 16-bit overflow.
  67.  */
  68. /* Convert a region from layer to window coordinate system */
  69. void
  70. CL_LayerToWindowRegion(CL_Compositor *compositor, CL_Layer *layer,
  71.                        FE_Region region)
  72. {
  73.     int32 x_offset = layer->x_origin - compositor->x_offset;
  74.     int32 y_offset = layer->y_origin - compositor->y_offset;
  75.  
  76.     if ((x_offset <= FE_MAX_REGION_COORDINATE) &&
  77.         (y_offset <= FE_MAX_REGION_COORDINATE))
  78.         FE_OffsetRegion(region, x_offset, y_offset);
  79. }
  80.  
  81. /* Convert a region from window to layer coordinate system */
  82. void
  83. CL_WindowToLayerRegion(CL_Compositor *compositor, CL_Layer *layer,
  84.                        FE_Region region)
  85. {
  86.     int32 x_offset = compositor->x_offset - layer->x_origin;
  87.     int32 y_offset = compositor->y_offset - layer->y_origin;
  88.  
  89.     if ((x_offset <= FE_MAX_REGION_COORDINATE) &&
  90.         (y_offset <= FE_MAX_REGION_COORDINATE))
  91.         FE_OffsetRegion(region, x_offset, y_offset);
  92. }
  93.  
  94. typedef struct {
  95.     int num_rects;
  96.     uint32 covered_area;
  97. } cl_entropy_closure;
  98.  
  99. static void
  100. cl_region_entropy_rect_func(cl_entropy_closure *closure,
  101.                    XP_Rect *rect)
  102. {
  103.     uint32 rect_area;
  104.  
  105.     rect_area = (rect->right - rect->left) * (rect->bottom - rect->top); 
  106.  
  107.     /* Small areas cause higher entropy, since they tend to do 
  108.        lots of clipping when overdraw occurs. */
  109.     if (rect_area > 1000)
  110.         closure->covered_area += rect_area;
  111.     closure->num_rects++;
  112.  
  113. /* Return a number between 0 and 1.0 indicating the "entropy" of a
  114.    region.  (For now, returns something approximating the fraction of
  115.    uncovered area in the region's bounding box.)  */
  116. float
  117. CL_RegionEntropy(FE_Region region)
  118. {
  119.     uint32 bbox_area;
  120.     XP_Rect bbox;
  121.     cl_entropy_closure closure;
  122.  
  123.  
  124.     FE_GetRegionBoundingBox(region, &bbox);
  125.     bbox_area = (bbox.right - bbox.left) * (bbox.bottom - bbox.top);
  126.  
  127.     closure.num_rects = 0;
  128.     closure.covered_area = 0;
  129.     FE_ForEachRectInRegion(region, 
  130.                            (FE_RectInRegionFunc)cl_region_entropy_rect_func,
  131.                            (void *)&closure);
  132.  
  133.     if (closure.num_rects <= 1)
  134.     return 0.0F;
  135.  
  136.     return 1.0F - (float)closure.covered_area / (float)bbox_area;
  137. }
  138.  
  139.  
  140. /* Like FE_ForEachRectInRegion(), except that there is no guarantee
  141.    that the individual rects delivered to the callback function
  142.    *exactly* cover the region.  (They may cover more than the region).
  143.    This may be used for more efficient painting because it is faster
  144.    to paint fewer large rects than many small rects.) */
  145. void
  146. CL_ForEachRectCoveringRegion(FE_Region region, FE_RectInRegionFunc func,
  147.                  void *closure)
  148. {
  149. #   define ENTROPY_THRESHOLD 0.85
  150.  
  151.     float entropy = CL_RegionEntropy(region);
  152.     
  153.     if (entropy < ENTROPY_THRESHOLD) {
  154.     XP_Rect bbox;
  155.     FE_GetRegionBoundingBox(region, &bbox);
  156.     (*func)(closure, &bbox);
  157.     } else {
  158.     FE_ForEachRectInRegion(region, func, closure);
  159.     }
  160. }
  161.  
  162. void
  163. cl_XorRegion(FE_Region src1, FE_Region src2, FE_Region dst)
  164. {
  165.     FE_Region tmp = FE_CreateRegion();
  166.     
  167.     if (tmp == FE_NULL_REGION)  /* OOM */
  168.         return;
  169.  
  170.     FE_SubtractRegion(src1, src2, tmp);
  171.     FE_SubtractRegion(src2, src1, dst);
  172.     FE_UnionRegion(tmp, dst, dst);
  173.     FE_DestroyRegion(tmp);
  174. }
  175.  
  176. void 
  177. cl_sanitize_bbox(XP_Rect *bbox)
  178. {
  179.     if (bbox->left > bbox->right)
  180.         bbox->right = bbox->left;
  181.     
  182.     if (bbox->top > bbox->bottom)
  183.         bbox->bottom = bbox->top;
  184. }
  185.