Blame lib/Xm/Draw.c

Packit b099d7
/* 
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
*/ 
Packit b099d7
/* 
Packit b099d7
 * HISTORY
Packit b099d7
*/ 
Packit b099d7
#ifdef REV_INFO
Packit b099d7
#ifndef lint
Packit b099d7
static char rcsid[] = "$XConsortium: Draw.c /main/12 1995/10/25 20:02:15 cde-sun $"
Packit b099d7
#endif
Packit b099d7
#endif
Packit b099d7
/* (c) Copyright 1989, DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. */
Packit b099d7
/* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */
Packit b099d7
Packit b099d7
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
#include "XmI.h"
Packit b099d7
#include <Xm/DrawP.h>
Packit b099d7
Packit b099d7
Packit b099d7
/*********************************************************************
Packit b099d7
 *    Only goes in this module the Draw API used by everybody in Xm.
Packit b099d7
 *    Anything specific to a class should go in its own Dr*.c module.
Packit b099d7
 *********************************************************************/
Packit b099d7
Packit b099d7
/********    Static Function Declarations    ********/
Packit b099d7
Packit b099d7
static void DrawSimpleShadow(Display *display,
Packit b099d7
			     Drawable d,
Packit b099d7
			     GC top_gc,
Packit b099d7
			     GC bottom_gc,
Packit b099d7
			     Position x,
Packit b099d7
			     Position y,
Packit b099d7
			     Dimension width,
Packit b099d7
			     Dimension height,
Packit b099d7
			     Dimension shadow_thick,
Packit b099d7
			     Dimension cor);
Packit b099d7
/********    End Static Function Declarations    ********/
Packit b099d7
Packit b099d7
Packit b099d7
/*-------------------- Private functions ----------------------*/
Packit b099d7
/*-------------------------------------------------------------*/
Packit b099d7

Packit b099d7
static void
Packit b099d7
DrawSimpleShadow (Display *display, 
Packit b099d7
		  Drawable d, 
Packit b099d7
		  GC top_gc, 
Packit b099d7
		  GC bottom_gc, 
Packit b099d7
		  Position x, 
Packit b099d7
		  Position y, 
Packit b099d7
		  Dimension width, 
Packit b099d7
		  Dimension height, 
Packit b099d7
		  Dimension shadow_thick, 
Packit b099d7
		  Dimension cor)
Packit b099d7
/* New implementation (1.2 vs 1.1) uses XSegments instead of XRectangles. */
Packit b099d7
/* Used for the simple shadow, the etched shadow and the separators */
Packit b099d7
/* Segment has been faster than Rectangles in all my benches, either
Packit b099d7
   on Hp, Sun or Pmax. Lines has been slower, that I don't understand... */
Packit b099d7
{
Packit b099d7
  static XSegment * segms = NULL;
Packit b099d7
  static int segm_count = 0;
Packit b099d7
Packit b099d7
  register int i, size2, size3;
Packit b099d7
  
Packit b099d7
  if (!d) return;
Packit b099d7
  ASSIGN_MIN(shadow_thick, (width >> 1));
Packit b099d7
  ASSIGN_MIN(shadow_thick, (height >> 1));
Packit b099d7
  if (shadow_thick <= 0) return;
Packit b099d7
  
Packit b099d7
  size2 = (shadow_thick << 1);
Packit b099d7
  size3 = size2 + shadow_thick;
Packit b099d7
  
Packit b099d7
  _XmProcessLock();
Packit b099d7
  if (segm_count < shadow_thick) {
Packit b099d7
    segms = (XSegment *) XtRealloc((char*)segms, 
Packit b099d7
				   sizeof (XSegment) * (size2 << 1));
Packit b099d7
    segm_count = shadow_thick;
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  for (i = 0; i < shadow_thick; i++) {
Packit b099d7
    /*  Top segments  */
Packit b099d7
    segms[i].x1 = x;
Packit b099d7
    segms[i].y2 = segms[i].y1 = y + i;
Packit b099d7
    segms[i].x2 = x + width - i - 1;
Packit b099d7
    /*  Left segments  */
Packit b099d7
    segms[i + shadow_thick].x2 = segms[i + shadow_thick].x1 = x + i;
Packit b099d7
    segms[i + shadow_thick].y1 = y + shadow_thick;
Packit b099d7
    segms[i + shadow_thick].y2 = y + height - i - 1;
Packit b099d7
    
Packit b099d7
    /*  Bottom segments  */
Packit b099d7
    segms[i + size2].x1 = x + i + ((cor)?0:1) ;
Packit b099d7
    segms[i + size2].y2 = segms[i + size2].y1 = y + height - i - 1;
Packit b099d7
    segms[i + size2].x2 = x + width - 1 ;
Packit b099d7
    /*  Right segments  */
Packit b099d7
    segms[i + size3].x2 = segms[i + size3].x1 = x + width - i - 1;
Packit b099d7
    segms[i + size3].y1 = y + i + 1 - cor;
Packit b099d7
    segms[i + size3].y2 = y + height - 1 ;
Packit b099d7
  }
Packit b099d7
  
Packit b099d7
  XDrawSegments (display, d, top_gc, &segms[0], size2);
Packit b099d7
  XDrawSegments (display, d, bottom_gc, &segms[size2], size2);
Packit b099d7
  _XmProcessUnlock();
Packit b099d7
}
Packit b099d7
Packit b099d7
    
Packit b099d7
/**************************** Public functions *************************/
Packit b099d7
/***********************************************************************/
Packit b099d7
Packit b099d7
/****************************XmeDrawShadows****************************/
Packit b099d7
void XmeDrawShadows(Display *display, Drawable d, 
Packit b099d7
                  GC top_gc, GC bottom_gc, 
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
                                           int x, int y, 
Packit b099d7
                  int width, int height, int shad_thick, 
Packit b099d7
#else
Packit b099d7
                                           Position x, Position y, 
Packit b099d7
                  Dimension width, Dimension height, Dimension shad_thick, 
Packit b099d7
#endif
Packit b099d7
                  unsigned int shad_type)
Packit b099d7
{
Packit b099d7
    GC  tmp_gc ;
Packit b099d7
    XtAppContext app;
Packit b099d7
Packit b099d7
    if(!d) return ;
Packit b099d7
Packit b099d7
    app = XtDisplayToApplicationContext(display);
Packit b099d7
Packit b099d7
    _XmAppLock(app);
Packit b099d7
Packit b099d7
    if ((shad_type == XmSHADOW_IN) || (shad_type == XmSHADOW_ETCHED_IN)) {
Packit b099d7
        tmp_gc = top_gc ;
Packit b099d7
        top_gc = bottom_gc ;  /* switch top and bottom shadows */
Packit b099d7
        bottom_gc = tmp_gc ;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    if ((shad_type == XmSHADOW_ETCHED_IN || 
Packit b099d7
         shad_type == XmSHADOW_ETCHED_OUT) && (shad_thick != 1)) {
Packit b099d7
        DrawSimpleShadow (display, d, top_gc, bottom_gc, x, y, 
Packit b099d7
                            width, height, shad_thick/2, 1);
Packit b099d7
        DrawSimpleShadow (display, d, bottom_gc, top_gc, 
Packit b099d7
                            x + shad_thick/2, y + shad_thick/2, 
Packit b099d7
                            width - (shad_thick/2)*2, 
Packit b099d7
                            height - (shad_thick/2)*2, shad_thick/2, 1);
Packit b099d7
    } else
Packit b099d7
        DrawSimpleShadow (display, d, top_gc, bottom_gc, x, y, 
Packit b099d7
                            width, height, shad_thick, 0);
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
} 
Packit b099d7
Packit b099d7
Packit b099d7
/*****************************XmeClearBorder*********************************/
Packit b099d7
void XmeClearBorder (Display *display, Window w, 
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
                                                 int x, int y, 
Packit b099d7
                    int width, int height, int shadow_thick)
Packit b099d7
#else
Packit b099d7
                                                 Position x, Position y, 
Packit b099d7
                    Dimension width, Dimension height, Dimension shadow_thick)
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
{
Packit b099d7
    XtAppContext app;
Packit b099d7
Packit b099d7
    if (!w || !shadow_thick || !width || !height) return ;
Packit b099d7
Packit b099d7
    app = XtDisplayToApplicationContext(display);
Packit b099d7
    _XmAppLock(app);
Packit b099d7
Packit b099d7
    XClearArea (display, w, x, y, width, shadow_thick, FALSE);
Packit b099d7
    XClearArea (display, w, x, y + height - shadow_thick, width, 
Packit b099d7
                shadow_thick, FALSE);
Packit b099d7
    XClearArea (display, w, x, y, shadow_thick, height, FALSE);
Packit b099d7
    XClearArea (display, w, x + width - shadow_thick, y, shadow_thick, 
Packit b099d7
                height, FALSE);
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
Packit b099d7
Packit b099d7
Packit b099d7
/****************************XmeDrawHighlight*************************/
Packit b099d7
void XmeDrawHighlight(Display *display, Drawable d, 
Packit b099d7
			    GC gc, 
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
			    int x, int y, 
Packit b099d7
			    int width, int height,
Packit b099d7
			    int highlight_thickness)
Packit b099d7
#else
Packit b099d7
                            Position x, Position y, 
Packit b099d7
                            Dimension width, Dimension height,
Packit b099d7
                            Dimension highlight_thickness)
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
{
Packit b099d7
    XRectangle rect[4] ;
Packit b099d7
    XtAppContext app;
Packit b099d7
Packit b099d7
    if (!d || !highlight_thickness || !width || !height) return ;
Packit b099d7
Packit b099d7
    app = XtDisplayToApplicationContext(display);
Packit b099d7
Packit b099d7
    _XmAppLock(app);
Packit b099d7
Packit b099d7
    rect[0].x = rect[1].x = rect[2].x = x ;
Packit b099d7
    rect[3].x = x + width - highlight_thickness ;
Packit b099d7
    rect[0].y = rect[2].y = rect[3].y = y ;
Packit b099d7
    rect[1].y = y + height - highlight_thickness ;
Packit b099d7
    rect[0].width = rect[1].width = width ;
Packit b099d7
    rect[2].width = rect[3].width = highlight_thickness ;
Packit b099d7
    rect[0].height = rect[1].height = highlight_thickness ;
Packit b099d7
    rect[2].height = rect[3].height = height ;
Packit b099d7
    
Packit b099d7
    XFillRectangles (display, d, gc, rect, 4);
Packit b099d7
Packit b099d7
    _XmAppUnlock(app);
Packit b099d7
Packit b099d7
}
Packit b099d7
Packit b099d7
 
Packit b099d7
Packit b099d7
/******************************XmeDrawSeparator**********************/
Packit b099d7
void XmeDrawSeparator(Display *display, Drawable d, 
Packit b099d7
                     GC top_gc, GC bottom_gc, GC separator_gc, 
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
                     int x, int y, 
Packit b099d7
                     int width, int height, 
Packit b099d7
                     int shadow_thick, 
Packit b099d7
                     int margin, unsigned int orientation, 
Packit b099d7
                     unsigned int separator_type)
Packit b099d7
#else
Packit b099d7
                     Position x, Position y, 
Packit b099d7
                     Dimension width, Dimension height, 
Packit b099d7
                     Dimension shadow_thick, 
Packit b099d7
                     Dimension margin, unsigned char orientation, 
Packit b099d7
                     unsigned char separator_type)
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
Packit b099d7
{
Packit b099d7
   Position center;
Packit b099d7
   XSegment segs[2];
Packit b099d7
   GC   tmp_gc;
Packit b099d7
   int i, ndash, shadow_dash_size ;
Packit b099d7
   XtAppContext app;
Packit b099d7
Packit b099d7
   if (!d || (separator_type == XmNO_LINE)) return ;
Packit b099d7
Packit b099d7
   app = XtDisplayToApplicationContext(display);
Packit b099d7
   _XmAppLock(app);
Packit b099d7
Packit b099d7
   if (orientation == XmHORIZONTAL) {
Packit b099d7
       center = y + height / 2;
Packit b099d7
   } else {
Packit b099d7
       center = x + width / 2;
Packit b099d7
   }
Packit b099d7
           
Packit b099d7
   if (separator_type == XmSINGLE_LINE ||
Packit b099d7
       separator_type == XmSINGLE_DASHED_LINE) {
Packit b099d7
       if (orientation == XmHORIZONTAL) {
Packit b099d7
           segs[0].x1 = x + margin;
Packit b099d7
           segs[0].y1 = segs[0].y2 = center;
Packit b099d7
           segs[0].x2 = x + width - margin - 1;
Packit b099d7
       } else {
Packit b099d7
           segs[0].y1 = y + margin;
Packit b099d7
           segs[0].x1 = segs[0].x2 = center;
Packit b099d7
           segs[0].y2 = y + height - margin - 1;
Packit b099d7
       }
Packit b099d7
       XDrawSegments (display, d, separator_gc, segs, 1);
Packit b099d7
       _XmAppUnlock(app);
Packit b099d7
       return;
Packit b099d7
   }
Packit b099d7
Packit b099d7
   if (separator_type == XmDOUBLE_LINE ||
Packit b099d7
       separator_type == XmDOUBLE_DASHED_LINE) {
Packit b099d7
       if (orientation == XmHORIZONTAL) {
Packit b099d7
           segs[0].x1 = segs[1].x1 = x + margin;
Packit b099d7
           segs[0].x2 = segs[1].x2 = x + width - margin - 1;
Packit b099d7
           segs[0].y1 = segs[0].y2 = center - 1;
Packit b099d7
           segs[1].y1 = segs[1].y2 = center + 1;
Packit b099d7
       } else {
Packit b099d7
           segs[0].y1 = segs[1].y1 = y + margin;
Packit b099d7
           segs[0].y2 = segs[1].y2 = y + height - margin - 1;
Packit b099d7
           segs[0].x1 = segs[0].x2 = center - 1;
Packit b099d7
           segs[1].x1 = segs[1].x2 = center + 1;
Packit b099d7
       }
Packit b099d7
       XDrawSegments (display, d, separator_gc, segs, 2);
Packit b099d7
       _XmAppUnlock(app);
Packit b099d7
       return;
Packit b099d7
   }
Packit b099d7
Packit b099d7
   /* only shadowed stuff in the following, so shadowThickness has to be
Packit b099d7
      something real */
Packit b099d7
   if (!shadow_thick) { _XmAppUnlock(app); return ; }
Packit b099d7
   
Packit b099d7
   /* do the in/out effect now */
Packit b099d7
   if (separator_type == XmSHADOW_ETCHED_IN || 
Packit b099d7
       separator_type == XmSHADOW_ETCHED_IN_DASH) {
Packit b099d7
       tmp_gc = top_gc ;
Packit b099d7
       top_gc = bottom_gc ;
Packit b099d7
       bottom_gc = tmp_gc ;
Packit b099d7
   }
Packit b099d7
Packit b099d7
   /* In the following, we need to special case the shadow_thick = 2 or 3 case,
Packit b099d7
      since : it's the default and we don't like changes in visual here, 
Packit b099d7
      and also it looks non symetrical the way it is without special code:
Packit b099d7
                                    ......
Packit b099d7
	                            .,,,,,
Packit b099d7
Packit b099d7
	and you really want to have ......
Packit b099d7
                                    ,,,,,,
Packit b099d7
      So we won't use DrawSimpleShadow in this case, painful but hey..
Packit b099d7
   */
Packit b099d7
Packit b099d7
Packit b099d7
   /* Now the regular shadowed cases, in one pass with one looong dash 
Packit b099d7
      for the non dashed case */
Packit b099d7
Packit b099d7
   if (separator_type == XmSHADOW_ETCHED_IN_DASH ||
Packit b099d7
       separator_type == XmSHADOW_ETCHED_OUT_DASH)
Packit b099d7
   /* for now, shadowed dash use three time the shadow thickness as a 
Packit b099d7
      dash size, and worried about the shadow_thick odd values as well */
Packit b099d7
       shadow_dash_size = (shadow_thick/2)*2*3 ;
Packit b099d7
   else
Packit b099d7
Packit b099d7
   /* regular case, only one dash, the length of the separator */
Packit b099d7
       shadow_dash_size = (orientation == XmHORIZONTAL)?
Packit b099d7
           (width - 2*margin):(height - 2*margin) ;
Packit b099d7
Packit b099d7
   /* special case for shadowThickness = 1 */
Packit b099d7
   if (shadow_dash_size == 0) shadow_dash_size = 5 ;
Packit b099d7
Packit b099d7
   /* ndash value will be 1 for the regular shadow case (not dashed) */
Packit b099d7
   if (orientation == XmHORIZONTAL) {
Packit b099d7
       ndash = ((width - 2*margin)/shadow_dash_size + 1)/2 ;       
Packit b099d7
       for (i=0; i
Packit b099d7
           if (shadow_thick < 4) {
Packit b099d7
	       XDrawLine(display, d, top_gc, 
Packit b099d7
			 x + margin + 2*i*shadow_dash_size, 
Packit b099d7
			 center - shadow_thick/2, 
Packit b099d7
			 x + margin + (2*i + 1)*shadow_dash_size -1, 
Packit b099d7
			 center - shadow_thick/2); 
Packit b099d7
	       if (shadow_thick > 1)
Packit b099d7
		   XDrawLine(display, d, bottom_gc, 
Packit b099d7
			 x + margin + 2*i*shadow_dash_size, 
Packit b099d7
			 center, 
Packit b099d7
			 x + margin + (2*i + 1)*shadow_dash_size -1, 
Packit b099d7
			 center); 
Packit b099d7
	   } else {
Packit b099d7
	       DrawSimpleShadow(display, d, top_gc, bottom_gc, 
Packit b099d7
				  x + margin + i*2*shadow_dash_size, 
Packit b099d7
				  center - shadow_thick/2, 
Packit b099d7
				  shadow_dash_size, (shadow_thick/2)*2, 
Packit b099d7
				  shadow_thick/2, 0);
Packit b099d7
	   }
Packit b099d7
       /* draw the last dash, with possibly a different size */
Packit b099d7
       if (i*2*shadow_dash_size < (width - 2*margin))
Packit b099d7
       {
Packit b099d7
           if (shadow_thick < 4) 
Packit b099d7
           {
Packit b099d7
	       XDrawLine(display, d, top_gc, 
Packit b099d7
			 x + margin + 2*i*shadow_dash_size, 
Packit b099d7
			 center - shadow_thick/2, 
Packit b099d7
			 x + (width - 2*margin), 
Packit b099d7
			 center - shadow_thick/2); 
Packit b099d7
	       if (shadow_thick > 1)
Packit b099d7
               {
Packit b099d7
		   XDrawLine(display, d, bottom_gc, 
Packit b099d7
			 x + margin + 2*i*shadow_dash_size, 
Packit b099d7
			 center, 
Packit b099d7
			 x + (width - 2*margin), 
Packit b099d7
			 center); 
Packit b099d7
               }
Packit b099d7
	   } else {
Packit b099d7
	       DrawSimpleShadow(display, d, top_gc, bottom_gc, 
Packit b099d7
				  x + margin + i*2*shadow_dash_size, 
Packit b099d7
				  center - shadow_thick/2, 
Packit b099d7
				  (width - 2*margin) - i*2*shadow_dash_size, 
Packit b099d7
				  (shadow_thick/2)*2, 
Packit b099d7
				  shadow_thick/2, 0);
Packit b099d7
	   }
Packit b099d7
       }
Packit b099d7
   } else {
Packit b099d7
       ndash = ((height - 2*margin)/shadow_dash_size + 1)/2 ;
Packit b099d7
       for (i=0; i
Packit b099d7
           if (shadow_thick < 4) {
Packit b099d7
	       XDrawLine(display, d, top_gc, 
Packit b099d7
			 center - shadow_thick/2, 
Packit b099d7
			 y + margin + 2*i*shadow_dash_size, 
Packit b099d7
			 center - shadow_thick/2,
Packit b099d7
			 y + margin + (2*i + 1)*shadow_dash_size -1); 
Packit b099d7
	       if (shadow_thick > 1)
Packit b099d7
		   XDrawLine(display, d, bottom_gc, 
Packit b099d7
			 center, 
Packit b099d7
			 y + margin + 2*i*shadow_dash_size, 
Packit b099d7
			 center, 
Packit b099d7
			 y + margin + (2*i + 1)*shadow_dash_size -1); 
Packit b099d7
	   } else {
Packit b099d7
	       DrawSimpleShadow(display, d, top_gc, bottom_gc, 
Packit b099d7
				  center - shadow_thick/2, 
Packit b099d7
				  y + margin + i*2*shadow_dash_size, 
Packit b099d7
				  (shadow_thick/2)*2, shadow_dash_size, 
Packit b099d7
				  shadow_thick/2, 0);
Packit b099d7
	   }
Packit b099d7
       if (i*2*shadow_dash_size < (height - 2*margin))
Packit b099d7
       {
Packit b099d7
           if (shadow_thick < 4) 
Packit b099d7
           {
Packit b099d7
	       XDrawLine(display, d, top_gc, 
Packit b099d7
			 center - shadow_thick/2, 
Packit b099d7
			 y + margin + 2*i*shadow_dash_size, 
Packit b099d7
			 center - shadow_thick/2,
Packit b099d7
			 y + (height - 2*margin)); 
Packit b099d7
	       if (shadow_thick > 1)
Packit b099d7
		   XDrawLine(display, d, bottom_gc, 
Packit b099d7
			 center, 
Packit b099d7
			 y + margin + 2*i*shadow_dash_size, 
Packit b099d7
			 center, 
Packit b099d7
			 y + (height - 2*margin)); 
Packit b099d7
	   } else {
Packit b099d7
	       DrawSimpleShadow(display, d, top_gc, bottom_gc, 
Packit b099d7
				  center - shadow_thick/2, 
Packit b099d7
				  y + margin + i*2*shadow_dash_size, 
Packit b099d7
				  (shadow_thick/2)*2, 
Packit b099d7
				  (height - 2*margin) - i*2*shadow_dash_size, 
Packit b099d7
				  shadow_thick/2, 0);
Packit b099d7
           }
Packit b099d7
        }
Packit b099d7
   }
Packit b099d7
   _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7