Imported Upstream version 1.1.1
[platform/upstream/libXmu.git] / src / ShapeWidg.c
1 /*
2
3 Copyright 1988, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25 */
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30 #include <X11/IntrinsicP.h>
31 #include <X11/extensions/shape.h>
32 #include "Converters.h"
33 #include "Drawing.h"
34 #include "Misc.h"
35
36 /*
37  * Prototypes
38  */
39 static void ShapeEllipseOrRoundedRectangle(Widget, Bool, int, int);
40 static void ShapeError(Widget);
41 static void ShapeOval(Widget);
42 static void ShapeRectangle(Widget);
43
44 /*
45  * Implementation
46  */
47 Boolean
48 XmuReshapeWidget(Widget w, int shape_style,
49                  int corner_width, int corner_height)
50 {
51   switch (shape_style)
52     {
53       case XmuShapeRectangle:
54         ShapeRectangle(w);
55         break;
56       case XmuShapeOval:
57         ShapeOval(w);
58         break;
59       case XmuShapeEllipse:
60       case XmuShapeRoundedRectangle:
61       ShapeEllipseOrRoundedRectangle(w, shape_style == XmuShapeEllipse,
62                                      corner_width, corner_height);
63         break;
64       default:
65         ShapeError(w);
66       return (False);
67     }
68   return (True);
69 }
70
71 static void
72 ShapeError(Widget w)
73 {
74     String params[1];
75     Cardinal num_params = 1;
76
77     params[0] = XtName(w);
78   XtAppWarningMsg(XtWidgetToApplicationContext(w),
79                      "shapeUnknown", "xmuReshapeWidget", "XmuLibrary",
80                      "Unsupported shape style for Command widget \"%s\"",
81                   params, &num_params);
82 }
83
84 static void
85 ShapeRectangle(Widget w)
86 {
87   XShapeCombineMask(XtDisplay(w), XtWindow(w),
88                     ShapeBounding, 0, 0, None, ShapeSet);
89   XShapeCombineMask(XtDisplay(w), XtWindow(w),
90                     ShapeClip, 0, 0, None, ShapeSet);
91 }
92
93 /*
94  * Function:
95  *      ShapeOval
96  *
97  * Parameters:
98  *      w - widget to be reshaped
99  *
100  * Description:
101  *      Reshapes a widget to a oval format.
102  *
103  * Notes:
104  *        X11R6.3 behaviour changed. Now if the height is larger than the
105  *      width, this function inverts the sense of the oval, instead of
106  *      fallbacking to ellipse.
107  */
108 static void
109 ShapeOval(Widget w)
110 {
111     Display *dpy = XtDisplay(w);
112     int width = w->core.width;
113     int height = w->core.height;
114     Pixmap p;
115     XGCValues values;
116     GC gc;
117     int rad;
118
119     if (width < 3 || height < 3)
120       return;
121     width += w->core.border_width << 1;
122     height += w->core.border_width << 1;
123
124     p = XCreatePixmap(dpy, XtWindow(w), width, height, 1);
125     values.foreground = 0;
126     values.background = 1;
127     values.cap_style = CapRound;
128     values.line_width = Min(width, height);
129     gc = XCreateGC(dpy, p,
130                     GCForeground | GCBackground | GCLineWidth | GCCapStyle,
131                     &values);
132     XFillRectangle(dpy, p, gc, 0, 0, width, height);
133     XSetForeground(dpy, gc, 1);
134
135     if (width < height)
136       {
137         rad = width >> 1;
138         XDrawLine(dpy, p, gc, rad, rad, rad, height - rad - 1);
139       }
140     else
141       {
142         rad = height >> 1;
143         XDrawLine(dpy, p, gc, rad, rad, width - rad - 1, rad);
144     }
145     XShapeCombineMask(dpy, XtWindow(w), ShapeBounding,
146                       -(int)w->core.border_width, -(int)w->core.border_width,
147                       p, ShapeSet);
148     if (w->core.border_width)
149       {
150         XSetForeground(dpy, gc, 0);
151         XFillRectangle(dpy, p, gc, 0, 0, width, height);
152         values.line_width = Min(w->core.width, w->core.height);
153         values.foreground = 1;
154         XChangeGC(dpy, gc, GCLineWidth | GCForeground, &values);
155         if (w->core.width < w->core.height)
156           {
157             rad = w->core.width >> 1;
158             XDrawLine(dpy, p, gc, rad, rad, rad, w->core.height - rad - 1);
159           }
160         else
161           {
162             rad = w->core.height >> 1;
163             XDrawLine(dpy, p, gc, rad, rad, w->core.width - rad - 1, rad);
164         }
165         XShapeCombineMask(dpy, XtWindow(w), ShapeClip, 0, 0, p, ShapeSet);
166     }
167     else
168       XShapeCombineMask(XtDisplay(w), XtWindow(w),
169                         ShapeClip, 0, 0, None, ShapeSet);
170
171     XFreePixmap(dpy, p);
172     XFreeGC(dpy, gc);
173 }
174
175 /*
176  * Function:
177  *      ShapeEllipseOrRoundedRectangle
178  *
179  * Parameters:
180  *      w       - widget to be reshaped
181  *      ellipse - True if shape to ellise, rounded rectangle otherwise
182  *      ew      - horizontal radius of rounded rectangle
183  *      eh      - vertical radius of rouded rectangle
184  *
185  * Description:
186  *        Based on the ellipse parameter, gives the widget a elliptical
187  *      shape, or rounded rectangle shape.
188  *
189  * Notes:
190  *        The GC is created with a line width of 2, what seens to draw the
191  *      widget border correctly, if the width - height is not proportional.
192  */
193 static void
194 ShapeEllipseOrRoundedRectangle(Widget w, Bool ellipse, int ew, int eh)
195 {
196     Display *dpy = XtDisplay(w);
197   unsigned width = w->core.width;
198   unsigned height = w->core.height;
199   Pixmap p;
200     XGCValues values;
201     GC gc;
202   unsigned long mask;
203
204   if (width < 3 || width < 3)
205     return;
206   width += w->core.border_width << 1;
207   height += w->core.border_width << 1;
208
209   mask = GCForeground | GCLineWidth;
210   p = XCreatePixmap(dpy, XtWindow(w), width, height, 1);
211
212     values.foreground = 0;
213   values.line_width = 2;
214
215   gc = XCreateGC(dpy, p, mask, &values);
216   XFillRectangle(dpy, p, gc, 0, 0, width, height);
217   XSetForeground(dpy, gc, 1);
218     if (!ellipse)
219     XmuFillRoundedRectangle(dpy, p, gc, 1, 1, width - 2, height - 2, ew, eh);
220     else
221     {
222       XDrawArc(dpy, p, gc, 1, 1, width - 2, height - 2, 0, 360 * 64);
223       XFillArc(dpy, p, gc, 2, 2, width - 4, height - 4, 0, 360 * 64);
224     }
225   XShapeCombineMask(dpy, XtWindow(w), ShapeBounding,
226                     -(int)w->core.border_width, -(int)w->core.border_width,
227                     p, ShapeSet);
228   if (w->core.border_width)
229     {
230       XSetForeground(dpy, gc, 0);
231       XFillRectangle(dpy, p, gc, 0, 0, width, height);
232       XSetForeground(dpy, gc, 1);
233         if (!ellipse)
234         XmuFillRoundedRectangle(dpy, p, gc, 1, 1,
235                                 w->core.width - 2, w->core.height - 2,
236                                 ew, eh);
237       else
238         XFillArc(dpy, p, gc, 0, 0, w->core.width, w->core.height,
239                  0, 360 * 64);
240       XShapeCombineMask(dpy, XtWindow(w), ShapeClip, 0, 0, p, ShapeSet);
241     }
242   else
243     XShapeCombineMask(XtDisplay(w), XtWindow(w),
244                       ShapeClip, 0, 0, None, ShapeSet);
245
246   XFreePixmap(dpy, p);
247   XFreeGC(dpy, gc);
248 }