/* $XConsortium: DrTog.c /main/6 1995/10/25 20:00:29 cde-sun $ */ /* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * */ /* * HISTORY */ #include "XmI.h" #include /**************************** DrTog module *************************** * * Draw API used by Toggle Button only. * ***************************************************************************/ /******** Static Function Declarations ********/ static void DrawCheckMark(Display *display, Drawable d, GC gc, Position x, Position y, Dimension width, Dimension height, Dimension margin); static void DrawCross(Display *display, Drawable d, GC gc, Position x, Position y, Dimension width, Dimension height, Dimension margin); /******** End Static Function Declarations ********/ #define CHECK_TEMPLATE_WIDTH 32 #define CHECK_TEMPLATE_HEIGHT 32 static XmConst XPoint check_template[] = { { 0, 15 }, { 6, 9 }, { 14, 17 }, { 31, 0 }, { 31, 3 }, { 21, 17 }, { 16, 31 }, { 0, 15 } }; static void DrawCheckMark(Display *display, Drawable d, GC gc, Position x, Position y, Dimension width, Dimension height, Dimension margin) { XGCValues old_values, new_values; XtGCMask mask; XPoint check[XtNumber(check_template)]; float scale_x = (width - 2 * margin - 1) / (float)CHECK_TEMPLATE_WIDTH; float scale_y = (height - 2 * margin - 1) / (float)CHECK_TEMPLATE_HEIGHT; int npoints = XtNumber(check_template); int i; /* Scale and translate the glyph to the desired area. */ for (i = 0; i < npoints; i++) { check[i].x = (Position)(check_template[i].x*scale_x + 0.5) + x + margin; check[i].y = (Position)(check_template[i].y*scale_y + 0.5) + y + margin; } /* CR 9656: Force line_width so test results are not platform-dependent. */ mask = 0; new_values.line_width = 1, mask |= GCLineWidth; XGetGCValues(display, gc, mask, &old_values); XChangeGC(display, gc, mask, &new_values); /* Draw the check mark. */ XFillPolygon(display, d, gc, check, npoints - 1, Nonconvex, CoordModeOrigin); XDrawLines(display, d, gc, check, npoints, CoordModeOrigin); XChangeGC(display, gc, mask, &old_values); } static void DrawCross(Display *display, Drawable d, GC gc, Position x, Position y, Dimension width, Dimension height, Dimension margin) { Position left = x + margin; Position right = x + width - margin - 1; Position top = y + margin; Position bottom = y + height - margin - 1; XSegment segs[6]; Cardinal nsegs = 0; segs[nsegs].x1 = left; segs[nsegs].y1 = top + 1; segs[nsegs].x2 = right - 1; segs[nsegs].y2 = bottom; nsegs++; segs[nsegs].x1 = left; segs[nsegs].y1 = top; segs[nsegs].x2 = right; segs[nsegs].y2 = bottom; nsegs++; segs[nsegs].x1 = left + 1; segs[nsegs].y1 = top; segs[nsegs].x2 = right; segs[nsegs].y2 = bottom - 1; nsegs++; segs[nsegs].x1 = left; segs[nsegs].y1 = bottom - 1; segs[nsegs].x2 = right - 1; segs[nsegs].y2 = top; nsegs++; segs[nsegs].x1 = left; segs[nsegs].y1 = bottom; segs[nsegs].x2 = right; segs[nsegs].y2 = top; nsegs++; segs[nsegs].x1 = left + 1; segs[nsegs].y1 = bottom; segs[nsegs].x2 = right; segs[nsegs].y2 = top + 1; nsegs++; assert(nsegs <= XtNumber(segs)); XDrawSegments(display, d, gc, segs, nsegs); } /***********************XmeDrawDiamond**********************************/ /*ARGSUSED*/ void XmeDrawDiamond(Display *display, Drawable d, GC top_gc, GC bottom_gc, GC center_gc, #if NeedWidePrototypes int x, int y, int width, int height, /* unused */ int shadow_thick, int margin) #else Position x, Position y, Dimension width, Dimension height, /* unused */ Dimension shadow_thick, Dimension margin) #endif /* NeedWidePrototypes */ { XSegment seg[12]; XPoint pt[4]; int midX, midY; int delta; _XmDisplayToAppContext(display); if (!d || !width) return ; _XmAppLock(app); if (width % 2 == 0) width--; if (width == 1) { XDrawPoint(display, d, top_gc, x,y); _XmAppUnlock(app); return ; } else if (width == 3) { seg[0].x1 = x; seg[0].y1 = seg[0].y2 = y + 1; seg[0].x2 = x + 2; seg[1].x1 = seg[1].x2 = x + 1; seg[1].y1 = y ; seg[1].y2 = y + 2; XDrawSegments (display, d, top_gc, seg, 2); _XmAppUnlock(app); return ; } else { /* NORMAL SIZED ToggleButtonS : initial width >= 5 */ midX = x + (width + 1) / 2; midY = y + (width + 1) / 2; /* The top shadow segments */ seg[0].x1 = x; /* 1 */ seg[0].y1 = midY - 1; seg[0].x2 = midX - 1; /* 2 */ seg[0].y2 = y; seg[1].x1 = x + 1; /* 3 */ seg[1].y1 = midY - 1; seg[1].x2 = midX - 1; /* 4 */ seg[1].y2 = y + 1; seg[2].x1 = x + 2; /* 3 */ seg[2].y1 = midY - 1; seg[2].x2 = midX - 1; /* 4 */ seg[2].y2 = y + 2; seg[3].x1 = midX - 1; /* 5 */ seg[3].y1 = y; seg[3].x2 = x + width - 1; /* 6 */ seg[3].y2 = midY - 1; seg[4].x1 = midX - 1; /* 7 */ seg[4].y1 = y + 1; seg[4].x2 = x + width - 2; /* 8 */ seg[4].y2 = midY - 1; seg[5].x1 = midX - 1; /* 7 */ seg[5].y1 = y + 2; seg[5].x2 = x + width - 3; /* 8 */ seg[5].y2 = midY - 1; /* The bottom shadow segments */ seg[6].x1 = x; /* 9 */ seg[6].y1 = midY - 1; seg[6].x2 = midX - 1; /* 10 */ seg[6].y2 = y + width - 1; seg[7].x1 = x + 1; /* 11 */ seg[7].y1 = midY - 1; seg[7].x2 = midX - 1; /* 12 */ seg[7].y2 = y + width - 2; seg[8].x1 = x + 2; /* 11 */ seg[8].y1 = midY - 1; seg[8].x2 = midX - 1; /* 12 */ seg[8].y2 = y + width - 3; seg[9].x1 = midX - 1; /* 13 */ seg[9].y1 = y + width - 1; seg[9].x2 = x + width - 1; /* 14 */ seg[9].y2 = midY - 1; seg[10].x1 = midX - 1; /* 15 */ seg[10].y1 = y + width - 2; seg[10].x2 = x + width - 2; /* 16 */ seg[10].y2 = midY - 1; seg[11].x1 = midX - 1; /* 15 */ seg[11].y1 = y + width - 3; seg[11].x2 = x + width - 3; /* 16 */ seg[11].y2 = midY - 1; } XDrawSegments (display, d, top_gc, &seg[3], 3); XDrawSegments (display, d, bottom_gc, &seg[6], 6); XDrawSegments (display, d, top_gc, &seg[0], 3); if (width == 5 || !center_gc) { _XmAppUnlock(app); return ; } /* <= 5 in fact */ if (shadow_thick == 0) delta = -3 ; else if (shadow_thick == 1) delta = -1 ; else delta = margin; pt[0].x = x + 3 + delta; pt[0].y = pt[2].y = midY - 1; pt[1].x = pt[3].x = midX - 1 ; pt[1].y = y + 2 + delta; pt[2].x = x + width - 3 - delta; pt[3].y = y + width - 3 - delta; XFillPolygon (display, d, center_gc, pt, 4, Convex, CoordModeOrigin); _XmAppUnlock(app); } /******************************XmeDrawIndicator**********************/ void XmeDrawIndicator(Display *display, Drawable d, GC gc, #if NeedWidePrototypes int x, int y, int width, int height, int margin, int type) #else Position x, Position y, Dimension width, Dimension height, Dimension margin, XtEnum type) #endif /* NeedWidePrototypes */ { _XmDisplayToAppContext(display); _XmAppLock(app); switch(type & 0xf0) { case XmINDICATOR_CHECK: DrawCheckMark(display, d, gc, x, y, width, height, margin); break; case XmINDICATOR_CROSS: DrawCross(display, d, gc, x, y, width, height, margin); break; } _XmAppUnlock(app); } void XmeDrawCircle(Display *display, Drawable d, GC top_gc, GC bottom_gc, GC center_gc, #if NeedWidePrototypes int x, int y, int width, int height, int shadow_thick, int margin) #else Position x, Position y, Dimension width, Dimension height, Dimension shadow_thick, Dimension margin) #endif /* NeedWidePrototypes */ { int line_width = MIN(shadow_thick, MIN(width, height) / 2); _XmDisplayToAppContext(display); if ((width <= 0) || (height <= 0)) return; _XmAppLock(app); if (shadow_thick > 0) { /* Force the GCs to use our values. */ XGCValues top_values, bottom_values, new_values; XtGCMask mask; mask = 0; new_values.line_width = line_width, mask |= GCLineWidth; XGetGCValues(display, top_gc, mask, &top_values); XGetGCValues(display, bottom_gc, mask, &bottom_values); XChangeGC(display, top_gc, mask, &new_values); XChangeGC(display, bottom_gc, mask, &new_values); XDrawArc(display, d, top_gc, x + line_width/2, y + line_width/2, MAX(width - line_width, 1), MAX(height - line_width, 1), 45 * 64, 180 * 64); XDrawArc(display, d, bottom_gc, x + line_width/2, y + line_width/2, MAX(width - line_width, 1), MAX(height - line_width, 1), 45 * 64, -180 * 64); XChangeGC(display, top_gc, mask, &top_values); XChangeGC(display, bottom_gc, mask, &bottom_values); } if (center_gc != NULL) { /* Fill the center of the circle. */ int delta = MIN(line_width + margin, MIN(width, height) / 2); XFillArc(display, d, center_gc, x + delta, y + delta, MAX(width - 2 * delta, 1), MAX(height - 2 * delta, 1), 0, 360 * 64); } _XmAppUnlock(app); }