summaryrefslogtreecommitdiff
path: root/Clock.c
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:58 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:58 +0000
commitf994ad01956aa98c99d6efd85df83fc59493c6ff (patch)
tree425895187659ae880f42110fcc9f404ba6200cba /Clock.c
parent7fa20e0899cf53cbb6d386d0688127df8b6fb0c7 (diff)
Diffstat (limited to 'Clock.c')
-rw-r--r--Clock.c1197
1 files changed, 1065 insertions, 132 deletions
diff --git a/Clock.c b/Clock.c
index 1a01b1b..d312871 100644
--- a/Clock.c
+++ b/Clock.c
@@ -46,34 +46,23 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
+/* $XFree86: xc/programs/xclock/Clock.c,v 3.24 2002/10/21 13:33:07 alanh Exp $ */
#include <X11/Xlib.h>
#include <X11/StringDefs.h>
#include <X11/IntrinsicP.h>
#include "ClockP.h"
#include <X11/Xosdefs.h>
+#include <stdio.h>
+#include <X11/Xos.h>
-#if defined(__STDC__) && !defined(AIXV3) /* AIX is broken */
-#define Const const
-#else
-#define Const /**/
-#endif
-
-#ifdef X_NOT_STDC_ENV
-extern struct tm *localtime();
-#define Time_t long
-extern Time_t time ();
-#else
#include <time.h>
#define Time_t time_t
-#endif
#ifdef XKB
#include <X11/extensions/XKBbells.h>
#endif
-static void clock_tic(), DrawHand(), DrawSecond(), SetSeg(), DrawClockFace();
-static erase_hands(), round();
/* Private Definitions */
@@ -81,6 +70,7 @@ static erase_hands(), round();
#define PI 3.14159265358979
#define TWOPI (2. * PI)
+#define MINOR_TICK_FRACT 95
#define SECOND_HAND_FRACT 90
#define MINUTE_HAND_FRACT 70
#define HOUR_HAND_FRACT 40
@@ -107,14 +97,24 @@ static XtResource resources[] = {
goffset(height), XtRImmediate, (XtPointer) 0},
{XtNupdate, XtCInterval, XtRInt, sizeof(int),
offset(update), XtRImmediate, (XtPointer) 60 },
+#ifndef XRENDER
{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
offset(fgpixel), XtRString, XtDefaultForeground},
+#endif
{XtNhand, XtCForeground, XtRPixel, sizeof(Pixel),
offset(Hdpixel), XtRString, XtDefaultForeground},
{XtNhighlight, XtCForeground, XtRPixel, sizeof(Pixel),
offset(Hipixel), XtRString, XtDefaultForeground},
+ {XtNutime, XtCBoolean, XtRBoolean, sizeof(Boolean),
+ offset(utime), XtRImmediate, (XtPointer) FALSE},
{XtNanalog, XtCBoolean, XtRBoolean, sizeof(Boolean),
offset(analog), XtRImmediate, (XtPointer) TRUE},
+ {XtNtwentyfour, XtCBoolean, XtRBoolean, sizeof(Boolean),
+ offset(twentyfour), XtRImmediate, (XtPointer) TRUE},
+ {XtNbrief, XtCBoolean, XtRBoolean, sizeof(Boolean),
+ offset(brief), XtRImmediate, (XtPointer) FALSE},
+ {XtNstrftime, XtCString, XtRString, sizeof(String),
+ offset(strftime), XtRString, ""},
{XtNchime, XtCBoolean, XtRBoolean, sizeof(Boolean),
offset(chime), XtRImmediate, (XtPointer) FALSE },
{XtNpadding, XtCMargin, XtRInt, sizeof(int),
@@ -123,14 +123,55 @@ static XtResource resources[] = {
offset(font), XtRString, XtDefaultFont},
{XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
offset (backing_store), XtRString, "default"},
+#ifdef XRENDER
+ {XtNrender, XtCBoolean, XtRBoolean, sizeof(Boolean),
+ offset(render), XtRImmediate, (XtPointer) TRUE },
+ {XtNbuffer, XtCBoolean, XtRBoolean, sizeof(Boolean),
+ offset(buffer), XtRImmediate, (XtPointer) TRUE },
+ {XtNsharp, XtCBoolean, XtRBoolean, sizeof(Boolean),
+ offset(sharp), XtRImmediate, (XtPointer) FALSE },
+ {XtNforeground, XtCForeground, XtRXftColor, sizeof(XftColor),
+ offset(fg_color), XtRString, XtDefaultForeground},
+ {XtNhourColor, XtCForeground, XtRXftColor, sizeof(XftColor),
+ offset(hour_color), XtRString, "rgba:7f/00/00/c0"},
+ {XtNminuteColor, XtCForeground, XtRXftColor, sizeof(XftColor),
+ offset(min_color), XtRString, "rgba:00/7f/7f/c0"},
+ {XtNsecondColor, XtCForeground, XtRXftColor, sizeof(XftColor),
+ offset(sec_color), XtRString, "rgba:00/00/ff/80"},
+ {XtNmajorColor, XtCForeground, XtRXftColor, sizeof(XftColor),
+ offset(major_color), XtRString, "rgba:7f/00/00/c0"},
+ {XtNminorColor, XtCForeground, XtRXftColor, sizeof(XftColor),
+ offset(minor_color), XtRString, "rgba:00/7f/7f/c0"},
+ {XtNface, XtCFace, XtRXftFont, sizeof (XftFont *),
+ offset (face), XtRString, ""},
+#endif
};
#undef offset
#undef goffset
-static void ClassInitialize();
-static void Initialize(), Realize(), Destroy(), Resize(), Redisplay();
-static Boolean SetValues();
+static void ClassInitialize ( void );
+static void Initialize ( Widget request, Widget new, ArgList args,
+ Cardinal *num_args );
+static void Realize ( Widget gw, XtValueMask *valueMask,
+ XSetWindowAttributes *attrs );
+static void Destroy ( Widget gw );
+static void Resize ( Widget gw );
+static void Redisplay ( Widget gw, XEvent *event, Region region );
+static void clock_tic ( XtPointer client_data, XtIntervalId *id );
+static void erase_hands ( ClockWidget w, struct tm *tm );
+static void ClockAngle ( int tick_units, double *sinp, double *cosp );
+static void DrawLine ( ClockWidget w, Dimension blank_length,
+ Dimension length, int tick_units );
+static void DrawHand ( ClockWidget w, Dimension length, Dimension width,
+ int tick_units );
+static void DrawSecond ( ClockWidget w, Dimension length, Dimension width,
+ Dimension offset, int tick_units );
+static void SetSeg ( ClockWidget w, int x1, int y1, int x2, int y2 );
+static void DrawClockFace ( ClockWidget w );
+static int clock_round ( double x );
+static Boolean SetValues ( Widget gcurrent, Widget grequest, Widget gnew,
+ ArgList args, Cardinal *num_args );
ClockClassRec clockClassRec = {
{ /* core fields */
@@ -149,7 +190,7 @@ ClockClassRec clockClassRec = {
/* resource_count */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
- /* compress_exposure */ TRUE,
+ /* compress_exposure */ XtExposeCompressMaximal,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ Destroy,
@@ -183,17 +224,247 @@ WidgetClass clockWidgetClass = (WidgetClass) &clockClassRec;
*
****************************************************************/
-static void ClassInitialize()
+#ifdef XRENDER
+XtConvertArgRec xftColorConvertArgs[] = {
+ {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
+ sizeof(Screen *)},
+ {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap),
+ sizeof(Colormap)}
+};
+
+#define donestr(type, value, tstr) \
+ { \
+ if (toVal->addr != NULL) { \
+ if (toVal->size < sizeof(type)) { \
+ toVal->size = sizeof(type); \
+ XtDisplayStringConversionWarning(dpy, \
+ (char*) fromVal->addr, tstr); \
+ return False; \
+ } \
+ *(type*)(toVal->addr) = (value); \
+ } \
+ else { \
+ static type static_val; \
+ static_val = (value); \
+ toVal->addr = (XPointer)&static_val; \
+ } \
+ toVal->size = sizeof(type); \
+ return True; \
+ }
+
+static void
+XmuFreeXftColor (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
+ XrmValuePtr args, Cardinal *num_args)
+{
+ Screen *screen;
+ Colormap colormap;
+ XftColor *color;
+
+ if (*num_args != 2)
+ {
+ XtAppErrorMsg (app,
+ "freeXftColor", "wrongParameters",
+ "XtToolkitError",
+ "Freeing an XftColor requires screen and colormap arguments",
+ (String *) NULL, (Cardinal *)NULL);
+ return;
+ }
+
+ screen = *((Screen **) args[0].addr);
+ colormap = *((Colormap *) args[1].addr);
+ color = (XftColor *) toVal->addr;
+ XftColorFree (DisplayOfScreen (screen),
+ DefaultVisual (DisplayOfScreen (screen),
+ XScreenNumberOfScreen (screen)),
+ colormap, color);
+}
+
+static Boolean
+XmuCvtStringToXftColor(Display *dpy,
+ XrmValue *args, Cardinal *num_args,
+ XrmValue *fromVal, XrmValue *toVal,
+ XtPointer *converter_data)
+{
+ char *spec;
+ XRenderColor renderColor;
+ XftColor xftColor;
+ Screen *screen;
+ Colormap colormap;
+
+ if (*num_args != 2)
+ {
+ XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
+ "cvtStringToXftColor", "wrongParameters",
+ "XtToolkitError",
+ "String to render color conversion needs screen and colormap arguments",
+ (String *) NULL, (Cardinal *)NULL);
+ return False;
+ }
+
+ screen = *((Screen **) args[0].addr);
+ colormap = *((Colormap *) args[1].addr);
+
+ spec = (char *) fromVal->addr;
+ if (strcasecmp (spec, XtDefaultForeground) == 0)
+ {
+ renderColor.red = 0;
+ renderColor.green = 0;
+ renderColor.blue = 0;
+ renderColor.alpha = 0xffff;
+ }
+ else if (strcasecmp (spec, XtDefaultBackground) == 0)
+ {
+ renderColor.red = 0xffff;
+ renderColor.green = 0xffff;
+ renderColor.blue = 0xffff;
+ renderColor.alpha = 0xffff;
+ }
+ else if (!XRenderParseColor (dpy, spec, &renderColor))
+ return False;
+ if (!XftColorAllocValue (dpy,
+ DefaultVisual (dpy,
+ XScreenNumberOfScreen (screen)),
+ colormap,
+ &renderColor,
+ &xftColor))
+ return False;
+
+ donestr (XftColor, xftColor, XtRXftColor);
+}
+
+static void
+XmuFreeXftFont (XtAppContext app, XrmValuePtr toVal, XtPointer closure,
+ XrmValuePtr args, Cardinal *num_args)
+{
+ Screen *screen;
+ XftFont *font;
+
+ if (*num_args != 1)
+ {
+ XtAppErrorMsg (app,
+ "freeXftFont", "wrongParameters",
+ "XtToolkitError",
+ "Freeing an XftFont requires screen argument",
+ (String *) NULL, (Cardinal *)NULL);
+ return;
+ }
+
+ screen = *((Screen **) args[0].addr);
+ font = *((XftFont **) toVal->addr);
+ if (font)
+ XftFontClose (DisplayOfScreen (screen), font);
+}
+
+static Boolean
+XmuCvtStringToXftFont(Display *dpy,
+ XrmValue *args, Cardinal *num_args,
+ XrmValue *fromVal, XrmValue *toVal,
+ XtPointer *converter_data)
+{
+ char *name;
+ XftFont *font;
+ Screen *screen;
+
+ if (*num_args != 1)
+ {
+ XtAppErrorMsg (XtDisplayToApplicationContext (dpy),
+ "cvtStringToXftFont", "wrongParameters",
+ "XtToolkitError",
+ "String to XftFont conversion needs screen argument",
+ (String *) NULL, (Cardinal *)NULL);
+ return False;
+ }
+
+ screen = *((Screen **) args[0].addr);
+ name = (char *) fromVal->addr;
+
+ font = XftFontOpenName (dpy,
+ XScreenNumberOfScreen (screen),
+ name);
+ if (font)
+ {
+ donestr (XftFont *, font, XtRXftFont);
+ }
+ XtDisplayStringConversionWarning(dpy, (char *) fromVal->addr, XtRXftFont);
+ return False;
+}
+
+XtConvertArgRec xftFontConvertArgs[] = {
+ {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen),
+ sizeof(Screen *)},
+};
+
+#endif
+
+static void
+ClassInitialize(void)
{
XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
NULL, 0 );
+#ifdef XRENDER
+ XtSetTypeConverter (XtRString, XtRXftColor,
+ XmuCvtStringToXftColor,
+ xftColorConvertArgs, XtNumber(xftColorConvertArgs),
+ XtCacheByDisplay, XmuFreeXftColor);
+ XtSetTypeConverter (XtRString, XtRXftFont,
+ XmuCvtStringToXftFont,
+ xftFontConvertArgs, XtNumber(xftFontConvertArgs),
+ XtCacheByDisplay, XmuFreeXftFont);
+#endif
+}
+
+static char *
+TimeString (ClockWidget w, struct tm *tm)
+{
+ if (w->clock.brief)
+ {
+ if (w->clock.twentyfour)
+ {
+ static char brief[6];
+ sprintf (brief, "%02d:%02d", tm->tm_hour, tm->tm_min);
+ return brief;
+ }
+ else
+ {
+ static char brief[9];
+ int hour = tm->tm_hour % 12;
+ if (!hour) hour = 12;
+ sprintf (brief, "%02d:%02d %cM", hour, tm->tm_min,
+ tm->tm_hour >= 12 ? 'P' : 'A');
+ return brief;
+ }
+ }
+ else if (w->clock.utime)
+ {
+ static char utime[35];
+ Time_t tsec;
+ tsec = time(NULL);
+ sprintf (utime, "%10lu seconds since Epoch", (unsigned long)tsec);
+ return utime;
+ } else if (*w->clock.strftime) {
+ /*Note: this code is probably excessively paranoid
+ about buffer overflow. The extra size 10 padding
+ is also meant as a further guard against programmer
+ error, although it is a little controversial*/
+ static char ctime[STRFTIME_BUFF_SIZE+10];
+ ctime[0] = ctime[STRFTIME_BUFF_SIZE] = '\0';
+ strftime (ctime, STRFTIME_BUFF_SIZE-1,w->clock.strftime, tm);
+ ctime[STRFTIME_BUFF_SIZE-1] = '\0';
+ return ctime;
+ }
+ else if (w->clock.twentyfour)
+ return asctime (tm);
+ else
+ {
+ static char long12[28];
+ strftime(long12, sizeof long12, "%a %b %d %I:%M:%S %p %Y", tm);
+ return long12;
+ }
}
/* ARGSUSED */
-static void Initialize (request, new, args, num_args)
- Widget request, new;
- ArgList args;
- Cardinal *num_args;
+static void
+Initialize (Widget request, Widget new, ArgList args, Cardinal *num_args)
{
ClockWidget w = (ClockWidget)new;
XtGCMask valuemask;
@@ -214,22 +485,36 @@ static void Initialize (request, new, args, num_args)
(void) time(&time_value);
tm = *localtime(&time_value);
- str = asctime(&tm);
+ str = TimeString (w, &tm);
if (w->clock.font == NULL)
w->clock.font = XQueryFont( XtDisplay(w),
XGContextFromGC(
DefaultGCOfScreen(XtScreen(w))) );
+#ifdef XRENDER
+ if (w->clock.render)
+ {
+ XGlyphInfo extents;
+ XftTextExtents8 (XtDisplay (w), w->clock.face,
+ (FcChar8 *) str, strlen (str), &extents);
+ min_width = extents.xOff + 2 * w->clock.padding;
+ min_height = w->clock.face->ascent + w->clock.face->descent +
+ 2 * w->clock.padding;
+ }
+ else
+#endif
+ {
min_width = XTextWidth(w->clock.font, str, strlen(str)) +
2 * w->clock.padding;
min_height = w->clock.font->ascent +
w->clock.font->descent + 2 * w->clock.padding;
+ }
}
if (w->core.width == 0)
w->core.width = min_width;
if (w->core.height == 0)
w->core.height = min_height;
- myXGCV.foreground = w->clock.fgpixel;
+ myXGCV.foreground = ClockFgPixel (w);
myXGCV.background = w->core.background_pixel;
if (w->clock.font != NULL)
myXGCV.font = w->clock.font->fid;
@@ -238,8 +523,9 @@ static void Initialize (request, new, args, num_args)
myXGCV.line_width = 0;
w->clock.myGC = XtGetGC((Widget)w, valuemask, &myXGCV);
- valuemask = GCForeground | GCLineWidth ;
+ valuemask = GCForeground | GCLineWidth | GCGraphicsExposures;
myXGCV.foreground = w->core.background_pixel;
+ myXGCV.graphics_exposures = False;
w->clock.EraseGC = XtGetGC((Widget)w, valuemask, &myXGCV);
myXGCV.foreground = w->clock.Hipixel;
@@ -254,12 +540,396 @@ static void Initialize (request, new, args, num_args)
w->clock.show_second_hand = (w->clock.update <= SECOND_HAND_TIME);
w->clock.numseg = 0;
w->clock.interval_id = 0;
+ memset (&w->clock.otm, '\0', sizeof (w->clock.otm));
+#ifdef XRENDER
+ {
+ int major, minor;
+
+ if (XRenderQueryVersion (XtDisplay (w), &major, &minor) &&
+ (major > 0 ||
+ (major == 0 && minor >= 4)))
+ {
+ w->clock.can_polygon = True;
+ }
+ else
+ w->clock.can_polygon = False;
+ }
+ w->clock.pixmap = 0;
+ w->clock.draw = 0;
+ w->clock.damage.x = 0;
+ w->clock.damage.y = 0;
+ w->clock.damage.height = 0;
+ w->clock.damage.width = 0;
+#endif
+}
+
+#if XRENDER
+static void
+RenderPrepare (ClockWidget w, XftColor *color)
+{
+ if (!w->clock.draw)
+ {
+ Drawable d = XtWindow (w);
+ if (w->clock.buffer)
+ {
+ if (!w->clock.pixmap)
+ {
+ Arg arg[1];
+ w->clock.pixmap = XCreatePixmap (XtDisplay (w), d,
+ w->core.width,
+ w->core.height,
+ w->core.depth);
+ arg[0].name = XtNbackgroundPixmap;
+ arg[0].value = 0;
+ XtSetValues ((Widget) w, arg, 1);
+ }
+ d = w->clock.pixmap;
+ }
+
+ w->clock.draw = XftDrawCreate (XtDisplay (w), d,
+ DefaultVisual (XtDisplay (w),
+ DefaultScreen(XtDisplay (w))),
+ w->core.colormap);
+ w->clock.picture = XftDrawPicture (w->clock.draw);
+ }
+ if (color)
+ w->clock.fill_picture = XftDrawSrcPicture (w->clock.draw, color);
+}
+
+static void
+RenderClip (ClockWidget w)
+{
+ Region r;
+ Drawable d;
+
+ RenderPrepare (w, 0);
+ if (w->clock.buffer)
+ d = w->clock.pixmap;
+ else
+ d = XtWindow (w);
+ XFillRectangle (XtDisplay (w), d, w->clock.EraseGC,
+ w->clock.damage.x,
+ w->clock.damage.y,
+ w->clock.damage.width,
+ w->clock.damage.height);
+ r = XCreateRegion ();
+ XUnionRectWithRegion (&w->clock.damage,
+ r, r);
+ XftDrawSetClip (w->clock.draw, r);
+ XDestroyRegion (r);
+}
+
+static void
+RenderTextBounds (ClockWidget w, char *str, int off, int len,
+ XRectangle *bounds, int *xp, int *yp)
+{
+ XGlyphInfo head, tail;
+ int x, y;
+
+ XftTextExtents8 (XtDisplay (w), w->clock.face, (FcChar8 *) str,
+ off, &head);
+ XftTextExtents8 (XtDisplay (w), w->clock.face, (FcChar8 *) str + off,
+ len - off, &tail);
+ /*
+ * Compute position of tail
+ */
+ x = w->clock.padding + head.xOff;
+ y = w->clock.face->ascent + w->clock.padding + head.yOff;
+ /*
+ * Compute bounds of tail, pad a bit as the bounds aren't exact
+ */
+ bounds->x = x - tail.x - 1;
+ bounds->y = y - tail.y - 1;
+ bounds->width = tail.width + 2;
+ bounds->height = tail.height + 2;
+ if (xp) *xp = x;
+ if (yp) *yp = y;
+}
+
+static void
+RenderUpdateRectBounds (XRectangle *damage, XRectangle *bounds)
+{
+ int x1 = bounds->x;
+ int y1 = bounds->y;
+ int x2 = bounds->x + bounds->width;
+ int y2 = bounds->y + bounds->height;
+ int d_x1 = damage->x;
+ int d_y1 = damage->y;
+ int d_x2 = damage->x + damage->width;
+ int d_y2 = damage->y + damage->height;
+
+ if (x1 == x2)
+ {
+ x1 = d_x1;
+ x2 = d_x2;
+ }
+ else
+ {
+ if (d_x1 < x1) x1 = d_x1;
+ if (d_x2 > x2) x2 = d_x2;
+ }
+ if (y1 == y2)
+ {
+ y1 = d_y1;
+ y2 = d_y2;
+ }
+ else
+ {
+ if (d_y1 < y1) y1 = d_y1;
+ if (d_y2 > y2) y2 = d_y2;
+ }
+
+ bounds->x = x1;
+ bounds->y = y1;
+ bounds->width = x2 - x1;
+ bounds->height = y2 - y1;
+}
+
+static Boolean
+RenderRectIn (XRectangle *rect, XRectangle *bounds)
+{
+ int x1 = bounds->x;
+ int y1 = bounds->y;
+ int x2 = bounds->x + bounds->width;
+ int y2 = bounds->y + bounds->height;
+ int r_x1 = rect->x;
+ int r_y1 = rect->y;
+ int r_x2 = rect->x + rect->width;
+ int r_y2 = rect->y + rect->height;
+
+ return r_x1 < x2 && x1 < r_x2 && r_y1 < y2 && y1 < r_y2;
+}
+
+#define LINE_WIDTH 0.01
+#include <math.h>
+
+#define XCoord(x,w) ((x) * (w)->clock.x_scale + (w)->clock.x_off)
+#define YCoord(y,w) ((y) * (w)->clock.y_scale + (w)->clock.y_off)
+
+static void
+RenderUpdateBounds (XPointDouble *points, int npoints, XRectangle *bounds)
+{
+ int x1 = bounds->x;
+ int y1 = bounds->y;
+ int x2 = bounds->x + bounds->width;
+ int y2 = bounds->y + bounds->height;
+
+ while (npoints--)
+ {
+ int r_x1 = points[0].x;
+ int r_y1 = points[0].y;
+ int r_x2 = points[0].x + 1;
+ int r_y2 = points[0].y + 1;
+
+ if (x1 == x2)
+ x2 = x1 = r_x1;
+ if (y1 == y2)
+ y2 = y1 = r_y1;
+ if (r_x1 < x1) x1 = r_x1;
+ if (r_y1 < y1) y1 = r_y1;
+ if (r_x2 > x2) x2 = r_x2;
+ if (r_y2 > y2) y2 = r_y2;
+ points++;
+ }
+ bounds->x = x1;
+ bounds->y = y1;
+ bounds->width = x2 - x1;
+ bounds->height = y2 - y1;
+}
+
+static Boolean
+RenderCheckBounds (XPointDouble *points, int npoints, XRectangle *bounds)
+{
+ int x1 = bounds->x;
+ int y1 = bounds->y;
+ int x2 = bounds->x + bounds->width;
+ int y2 = bounds->y + bounds->height;
+
+ while (npoints--)
+ {
+ if (x1 <= points->x && points->x <= x2 &&
+ y1 <= points->y && points->y <= y2)
+ return True;
+ points++;
+ }
+ return False;
+}
+
+static void
+RenderUpdate (ClockWidget w)
+{
+ if (w->clock.buffer && w->clock.pixmap)
+ {
+ XCopyArea (XtDisplay (w), w->clock.pixmap,
+ XtWindow (w), w->clock.EraseGC,
+ w->clock.damage.x, w->clock.damage.y,
+ w->clock.damage.width, w->clock.damage.height,
+ w->clock.damage.x, w->clock.damage.y);
+ }
+}
+
+static void
+RenderResetBounds (XRectangle *bounds)
+{
+ bounds->x = 0;
+ bounds->y = 0;
+ bounds->width = 0;
+ bounds->height = 0;
+}
+
+static void
+RenderLine (ClockWidget w, XDouble x1, XDouble y1, XDouble x2, XDouble y2,
+ XftColor *color,
+ Boolean draw)
+{
+ XPointDouble poly[4];
+ XDouble dx = (x2 - x1);
+ XDouble dy = (y2 - y1);
+ XDouble len = sqrt (dx*dx + dy*dy);
+ XDouble ldx = (LINE_WIDTH/2.0) * dy / len;
+ XDouble ldy = (LINE_WIDTH/2.0) * dx / len;
+
+ poly[0].x = XCoord (x1 + ldx, w);
+ poly[0].y = YCoord (y1 - ldy, w);
+
+ poly[1].x = XCoord (x2 + ldx, w);
+ poly[1].y = YCoord (y2 - ldy, w);
+
+ poly[2].x = XCoord (x2 - ldx, w);
+ poly[2].y = YCoord (y2 + ldy, w);
+
+ poly[3].x = XCoord (x1 - ldx, w);
+ poly[3].y = YCoord (y1 + ldy, w);
+
+ RenderUpdateBounds (poly, 4, &w->clock.damage);
+ if (draw)
+ {
+ if (RenderCheckBounds (poly, 4, &w->clock.damage))
+ {
+ RenderPrepare (w, color);
+ XRenderCompositeDoublePoly (XtDisplay (w),
+ PictOpOver,
+ w->clock.fill_picture,
+ w->clock.picture,
+ w->clock.mask_format,
+ 0, 0, 0, 0, poly, 4, EvenOddRule);
+ }
+ }
+ else
+ RenderUpdateBounds (poly, 4, &w->clock.damage);
+}
+
+static void
+RenderRotate (ClockWidget w, XPointDouble *out, double x, double y, double s, double c)
+{
+ out->x = XCoord (x * c - y * s, w);
+ out->y = YCoord (y * c + x * s, w);
+}
+
+static void
+RenderHand (ClockWidget w, int tick_units, int size, XftColor *color,
+ Boolean draw)
+{
+ double c, s;
+ XPointDouble poly[3];
+ double outer_x;
+ double inner_y;
+
+ ClockAngle (tick_units, &c, &s);
+ s = -s;
+
+ /* compute raw positions */
+ outer_x = size / 100.0;
+ inner_y = HAND_WIDTH_FRACT / 100.0;
+
+ /* rotate them into position */
+ RenderRotate (w, &poly[0], outer_x, 0.0, s, c);
+ RenderRotate (w, &poly[1], -inner_y, inner_y, s, c);
+ RenderRotate (w, &poly[2], -inner_y, -inner_y, s, c);
+
+ if (draw)
+ {
+ if (RenderCheckBounds (poly, 3, &w->clock.damage))
+ {
+ RenderPrepare (w, color);
+ XRenderCompositeDoublePoly (XtDisplay (w),
+ PictOpOver,
+ w->clock.fill_picture,
+ w->clock.picture,
+ w->clock.mask_format,
+ 0, 0, 0, 0, poly, 3, EvenOddRule);
+ }
+ }
+ RenderUpdateBounds (poly, 3, &w->clock.damage);
+}
+
+static void
+RenderHands (ClockWidget w, struct tm *tm, Boolean draw)
+{
+ RenderHand (w, tm->tm_hour * 300 + tm->tm_min*5, HOUR_HAND_FRACT, &w->clock.hour_color, draw);
+ RenderHand (w, tm->tm_min * 60 + tm->tm_sec, MINUTE_HAND_FRACT, &w->clock.min_color, draw);
+}
+
+static void
+RenderSec (ClockWidget w, struct tm *tm, Boolean draw)
+{
+ double c, s;
+ XPointDouble poly[10];
+ double inner_x, middle_x, outer_x, far_x;
+ double middle_y;
+ double line_y;
+
+ ClockAngle (tm->tm_sec * 60, &c, &s);
+
+ s = -s;
+
+ /*
+ * Compute raw positions
+ */
+ line_y = LINE_WIDTH;
+ inner_x = (MINUTE_HAND_FRACT / 100.0);
+ middle_x = ((SECOND_HAND_FRACT + MINUTE_HAND_FRACT) / 200.0);
+ outer_x = (SECOND_HAND_FRACT / 100.0);
+ far_x = (MINOR_TICK_FRACT / 100.0);
+ middle_y = (SECOND_WIDTH_FRACT / 100.0);
+
+ /*
+ * Rotate them into position
+ */
+ RenderRotate (w, &poly[0], -line_y, line_y, s, c);
+ RenderRotate (w, &poly[1], inner_x, line_y, s, c);
+ RenderRotate (w, &poly[2], middle_x, middle_y, s, c);
+ RenderRotate (w, &poly[3], outer_x, line_y, s, c);
+ RenderRotate (w, &poly[4], far_x, line_y, s, c);
+ RenderRotate (w, &poly[5], far_x, -line_y, s, c);
+ RenderRotate (w, &poly[6], outer_x, -line_y, s, c);
+ RenderRotate (w, &poly[7], middle_x, -middle_y, s, c);
+ RenderRotate (w, &poly[8], inner_x, -line_y, s, c);
+ RenderRotate (w, &poly[9], -line_y, -line_y, s, c);
+
+ if (draw)
+ {
+ if (RenderCheckBounds (poly, 10, &w->clock.damage))
+ {
+ RenderPrepare (w, &w->clock.sec_color);
+ XRenderCompositeDoublePoly (XtDisplay (w),
+ PictOpOver,
+ w->clock.fill_picture,
+ w->clock.picture,
+ w->clock.mask_format,
+ 0, 0, 0, 0, poly, 10, EvenOddRule);
+ }
+ }
+ else
+ {
+ RenderUpdateBounds (poly, 10, &w->clock.damage);
+ }
}
-static void Realize (gw, valueMask, attrs)
- Widget gw;
- XtValueMask *valueMask;
- XSetWindowAttributes *attrs;
+#endif
+
+static void
+Realize(Widget gw, XtValueMask *valueMask, XSetWindowAttributes *attrs)
{
ClockWidget w = (ClockWidget) gw;
#ifdef notdef
@@ -279,19 +949,25 @@ static void Realize (gw, valueMask, attrs)
Resize(gw);
}
-static void Destroy (gw)
- Widget gw;
+static void
+Destroy(Widget gw)
{
ClockWidget w = (ClockWidget) gw;
if (w->clock.interval_id) XtRemoveTimeOut (w->clock.interval_id);
+#ifdef RENDER
+ if (w->clock.picture)
+ XRenderFreePicture (dpy, w->clock.picture);
+ if (w->clock.fill_picture)
+ XRenderFreePicture (dpy, w->clock.fill_picture);
+#endif
XtReleaseGC (gw, w->clock.myGC);
XtReleaseGC (gw, w->clock.HighGC);
XtReleaseGC (gw, w->clock.HandGC);
XtReleaseGC (gw, w->clock.EraseGC);
}
-static void Resize (gw)
- Widget gw;
+static void
+Resize(Widget gw)
{
ClockWidget w = (ClockWidget) gw;
/* don't do this computation if window hasn't been realized yet. */
@@ -309,42 +985,69 @@ static void Resize (gw)
w->clock.centerX = w->core.width / 2;
w->clock.centerY = w->core.height / 2;
}
+#ifdef XRENDER
+ w->clock.x_scale = 0.45 * w->core.width;
+ w->clock.y_scale = 0.45 * w->core.height;
+ w->clock.x_off = 0.5 * w->core.width;
+ w->clock.y_off = 0.5 * w->core.height;
+ if (w->clock.pixmap)
+ {
+ XFreePixmap (XtDisplay (w), w->clock.pixmap);
+ w->clock.pixmap = 0;
+ if (w->clock.draw)
+ {
+ XftDrawDestroy (w->clock.draw);
+ w->clock.draw = 0;
+ }
+ w->clock.picture = 0;
+ }
+#endif
}
/* ARGSUSED */
-static void Redisplay (gw, event, region)
- Widget gw;
- XEvent *event; /* unused */
- Region region; /* unused */
+static void
+Redisplay(Widget gw, XEvent *event, Region region)
{
ClockWidget w = (ClockWidget) gw;
if (w->clock.analog) {
- if (w->clock.numseg != 0)
- erase_hands (w, (struct tm *) 0);
- DrawClockFace(w);
+#ifdef XRENDER
+ if (w->clock.render && w->clock.can_polygon)
+ XClipBox (region, &w->clock.damage);
+ else
+#endif
+ {
+ if (w->clock.numseg != 0)
+ erase_hands (w, (struct tm *) 0);
+ DrawClockFace(w);
+ }
} else {
+#ifdef XRENDER
+ if (w->clock.render)
+ XClipBox (region, &w->clock.damage);
+#endif
w->clock.prev_time_string[0] = '\0';
}
clock_tic((XtPointer)w, (XtIntervalId)0);
}
/* ARGSUSED */
-static void clock_tic(client_data, id)
- XtPointer client_data;
- XtIntervalId *id;
+static void
+clock_tic(XtPointer client_data, XtIntervalId *id)
{
ClockWidget w = (ClockWidget)client_data;
struct tm tm;
Time_t time_value;
+ struct timeval tv;
char *time_ptr;
register Display *dpy = XtDisplay(w);
register Window win = XtWindow(w);
+ X_GETTIMEOFDAY (&tv);
if (id || !w->clock.interval_id)
w->clock.interval_id =
XtAppAddTimeOut( XtWidgetToApplicationContext( (Widget) w),
- w->clock.update*1000, clock_tic, (XtPointer)w );
- (void) time(&time_value);
+ (w->clock.update - 1) * 1000 + (1000000 - tv.tv_usec)/1000, clock_tic, (XtPointer)w );
+ time_value = tv.tv_sec;
tm = *localtime(&time_value);
/*
* Beep on the half hour; double-beep on the hour.
@@ -375,18 +1078,51 @@ static void clock_tic(client_data, id)
int clear_from;
int i, len, prev_len;
- time_ptr = asctime(&tm);
+ time_ptr = TimeString (w, &tm);
len = strlen (time_ptr);
if (time_ptr[len - 1] == '\n') time_ptr[--len] = '\0';
prev_len = strlen (w->clock.prev_time_string);
for (i = 0; ((i < len) && (i < prev_len) &&
(w->clock.prev_time_string[i] == time_ptr[i])); i++);
- strcpy (w->clock.prev_time_string+i, time_ptr+i);
+#ifdef XRENDER
+ if (w->clock.render)
+ {
+ XRectangle old_tail, new_tail, head;
+ int x, y;
+
+ RenderTextBounds (w, w->clock.prev_time_string, i, prev_len,
+ &old_tail, 0, 0);
+ RenderUpdateRectBounds (&old_tail, &w->clock.damage);
+ RenderTextBounds (w, time_ptr, i, len,
+ &new_tail, 0, 0);
+ RenderUpdateRectBounds (&new_tail, &w->clock.damage);
+
+ while (i)
+ {
+ RenderTextBounds (w, time_ptr, 0, i, &head, 0, 0);
+ if (!RenderRectIn (&head, &w->clock.damage))
+ break;
+ i--;
+ }
+ RenderTextBounds (w, time_ptr, i, len, &new_tail, &x, &y);
+ RenderClip (w);
+ RenderPrepare (w, 0);
+ XftDrawString8 (w->clock.draw,
+ &w->clock.fg_color,
+ w->clock.face,
+ x, y,
+ (FcChar8 *) time_ptr + i, len - i);
+ RenderUpdate (w);
+ RenderResetBounds (&w->clock.damage);
+ }
+ else
+#endif
+ {
XDrawImageString (dpy, win, w->clock.myGC,
- (2+w->clock.padding +
+ (1+w->clock.padding +
XTextWidth (w->clock.font, time_ptr, i)),
- 2+w->clock.font->ascent+w->clock.padding,
+ w->clock.font->ascent+w->clock.padding,
time_ptr + i, len - i);
/*
* Clear any left over bits
@@ -396,6 +1132,8 @@ static void clock_tic(client_data, id)
if (clear_from < (int)w->core.width)
XFillRectangle (dpy, win, w->clock.EraseGC,
clear_from, 0, w->core.width - clear_from, w->core.height);
+ }
+ strcpy (w->clock.prev_time_string+i, time_ptr+i);
} else {
/*
* The second (or minute) hand is sec (or min)
@@ -411,6 +1149,45 @@ static void clock_tic(client_data, id)
if(tm.tm_hour >= 12)
tm.tm_hour -= 12;
+#ifdef XRENDER
+ if (w->clock.render && w->clock.can_polygon)
+ {
+ w->clock.mask_format = XRenderFindStandardFormat (XtDisplay (w),
+ w->clock.sharp ?
+ PictStandardA1 :
+ PictStandardA8);
+ /*
+ * Compute repaint area
+ */
+ if (tm.tm_min != w->clock.otm.tm_min ||
+ tm.tm_hour != w->clock.otm.tm_hour ||
+ tm.tm_sec != w->clock.otm.tm_sec)
+ {
+ RenderHands (w, &w->clock.otm, False);
+ RenderHands (w, &tm, False);
+ }
+ if (w->clock.show_second_hand &&
+ tm.tm_sec != w->clock.otm.tm_sec)
+ {
+ RenderSec (w, &w->clock.otm, False);
+ RenderSec (w, &tm, False);
+ }
+ if (w->clock.damage.width &&
+ w->clock.damage.height)
+ {
+ RenderClip (w);
+ DrawClockFace (w);
+ RenderHands (w, &tm, True);
+ if (w->clock.show_second_hand == TRUE)
+ RenderSec (w, &tm, True);
+ }
+ w->clock.otm = tm;
+ RenderUpdate (w);
+ RenderResetBounds (&w->clock.damage);
+ return;
+ }
+#endif
+
erase_hands (w, &tm);
if (w->clock.numseg == 0 ||
@@ -426,7 +1203,7 @@ static void clock_tic(client_data, id)
*/
DrawHand(w,
w->clock.minute_hand_length, w->clock.hand_width,
- tm.tm_min * 12
+ tm.tm_min * 60
);
if(w->clock.Hdpixel != w->core.background_pixel)
XFillPolygon( dpy,
@@ -441,7 +1218,7 @@ static void clock_tic(client_data, id)
w->clock.hour = w->clock.segbuffptr;
DrawHand(w,
w->clock.hour_hand_length, w->clock.hand_width,
- tm.tm_hour * 60 + tm.tm_min
+ tm.tm_hour * 300 + tm.tm_min * 5
);
if(w->clock.Hdpixel != w->core.background_pixel) {
XFillPolygon(dpy,
@@ -464,7 +1241,7 @@ static void clock_tic(client_data, id)
w->clock.second_hand_length - 2,
w->clock.second_hand_width,
w->clock.minute_hand_length + 2,
- tm.tm_sec * 12
+ tm.tm_sec * 60
);
if(w->clock.Hdpixel != w->core.background_pixel)
XFillPolygon( dpy,
@@ -485,9 +1262,8 @@ static void clock_tic(client_data, id)
}
}
-static erase_hands (w, tm)
-ClockWidget w;
-struct tm *tm;
+static void
+erase_hands(ClockWidget w, struct tm *tm)
{
/*
* Erase old hands.
@@ -541,46 +1317,134 @@ struct tm *tm;
}
}
-static float Const Sines[] = {
-.000000, .008727, .017452, .026177, .034899, .043619, .052336, .061049,
-.069756, .078459, .087156, .095846, .104528, .113203, .121869, .130526,
-.139173, .147809, .156434, .165048, .173648, .182236, .190809, .199368,
-.207912, .216440, .224951, .233445, .241922, .250380, .258819, .267238,
-.275637, .284015, .292372, .300706, .309017, .317305, .325568, .333807,
-.342020, .350207, .358368, .366501, .374607, .382683, .390731, .398749,
-.406737, .414693, .422618, .430511, .438371, .446198, .453990, .461749,
-.469472, .477159, .484810, .492424, .500000, .507538, .515038, .522499,
-.529919, .537300, .544639, .551937, .559193, .566406, .573576, .580703,
-.587785, .594823, .601815, .608761, .615661, .622515, .629320, .636078,
-.642788, .649448, .656059, .662620, .669131, .675590, .681998, .688355,
-.694658, .700909, .707107
+static float const Sines[] = {
+0.000000, 0.001745, 0.003490, 0.005235, 0.006981, 0.008726, 0.010471, 0.012217,
+0.013962, 0.015707, 0.017452, 0.019197, 0.020942, 0.022687, 0.024432, 0.026176,
+0.027921, 0.029666, 0.031410, 0.033155, 0.034899, 0.036643, 0.038387, 0.040131,
+0.041875, 0.043619, 0.045362, 0.047106, 0.048849, 0.050592, 0.052335, 0.054078,
+0.055821, 0.057564, 0.059306, 0.061048, 0.062790, 0.064532, 0.066273, 0.068015,
+0.069756, 0.071497, 0.073238, 0.074978, 0.076719, 0.078459, 0.080198, 0.081938,
+0.083677, 0.085416, 0.087155, 0.088894, 0.090632, 0.092370, 0.094108, 0.095845,
+0.097582, 0.099319, 0.101056, 0.102792, 0.104528, 0.106264, 0.107999, 0.109734,
+0.111468, 0.113203, 0.114937, 0.116670, 0.118403, 0.120136, 0.121869, 0.123601,
+0.125333, 0.127064, 0.128795, 0.130526, 0.132256, 0.133986, 0.135715, 0.137444,
+0.139173, 0.140901, 0.142628, 0.144356, 0.146083, 0.147809, 0.149535, 0.151260,
+0.152985, 0.154710, 0.156434, 0.158158, 0.159881, 0.161603, 0.163325, 0.165047,
+0.166768, 0.168489, 0.170209, 0.171929, 0.173648, 0.175366, 0.177084, 0.178802,
+0.180519, 0.182235, 0.183951, 0.185666, 0.187381, 0.189095, 0.190808, 0.192521,
+0.194234, 0.195946, 0.197657, 0.199367, 0.201077, 0.202787, 0.204496, 0.206204,
+0.207911, 0.209618, 0.211324, 0.213030, 0.214735, 0.216439, 0.218143, 0.219846,
+0.221548, 0.223250, 0.224951, 0.226651, 0.228350, 0.230049, 0.231747, 0.233445,
+0.235142, 0.236838, 0.238533, 0.240228, 0.241921, 0.243615, 0.245307, 0.246999,
+0.248689, 0.250380, 0.252069, 0.253757, 0.255445, 0.257132, 0.258819, 0.260504,
+0.262189, 0.263873, 0.265556, 0.267238, 0.268919, 0.270600, 0.272280, 0.273959,
+0.275637, 0.277314, 0.278991, 0.280666, 0.282341, 0.284015, 0.285688, 0.287360,
+0.289031, 0.290702, 0.292371, 0.294040, 0.295708, 0.297374, 0.299040, 0.300705,
+0.302369, 0.304033, 0.305695, 0.307356, 0.309016, 0.310676, 0.312334, 0.313992,
+0.315649, 0.317304, 0.318959, 0.320612, 0.322265, 0.323917, 0.325568, 0.327217,
+0.328866, 0.330514, 0.332161, 0.333806, 0.335451, 0.337095, 0.338737, 0.340379,
+0.342020, 0.343659, 0.345298, 0.346935, 0.348572, 0.350207, 0.351841, 0.353474,
+0.355106, 0.356737, 0.358367, 0.359996, 0.361624, 0.363251, 0.364876, 0.366501,
+0.368124, 0.369746, 0.371367, 0.372987, 0.374606, 0.376224, 0.377840, 0.379456,
+0.381070, 0.382683, 0.384295, 0.385906, 0.387515, 0.389123, 0.390731, 0.392337,
+0.393941, 0.395545, 0.397147, 0.398749, 0.400349, 0.401947, 0.403545, 0.405141,
+0.406736, 0.408330, 0.409923, 0.411514, 0.413104, 0.414693, 0.416280, 0.417867,
+0.419452, 0.421035, 0.422618, 0.424199, 0.425779, 0.427357, 0.428935, 0.430511,
+0.432085, 0.433659, 0.435231, 0.436801, 0.438371, 0.439939, 0.441505, 0.443071,
+0.444635, 0.446197, 0.447759, 0.449318, 0.450877, 0.452434, 0.453990, 0.455544,
+0.457097, 0.458649, 0.460199, 0.461748, 0.463296, 0.464842, 0.466386, 0.467929,
+0.469471, 0.471011, 0.472550, 0.474088, 0.475624, 0.477158, 0.478691, 0.480223,
+0.481753, 0.483282, 0.484809, 0.486335, 0.487859, 0.489382, 0.490903, 0.492423,
+0.493941, 0.495458, 0.496973, 0.498487, 0.499999, 0.501510, 0.503019, 0.504527,
+0.506033, 0.507538, 0.509041, 0.510542, 0.512042, 0.513541, 0.515038, 0.516533,
+0.518027, 0.519519, 0.521009, 0.522498, 0.523985, 0.525471, 0.526955, 0.528438,
+0.529919, 0.531398, 0.532876, 0.534352, 0.535826, 0.537299, 0.538770, 0.540240,
+0.541708, 0.543174, 0.544639, 0.546101, 0.547563, 0.549022, 0.550480, 0.551936,
+0.553391, 0.554844, 0.556295, 0.557745, 0.559192, 0.560638, 0.562083, 0.563526,
+0.564967, 0.566406, 0.567843, 0.569279, 0.570713, 0.572145, 0.573576, 0.575005,
+0.576432, 0.577857, 0.579281, 0.580702, 0.582122, 0.583541, 0.584957, 0.586372,
+0.587785, 0.589196, 0.590605, 0.592013, 0.593418, 0.594822, 0.596224, 0.597625,
+0.599023, 0.600420, 0.601815, 0.603207, 0.604599, 0.605988, 0.607375, 0.608761,
+0.610145, 0.611527, 0.612907, 0.614285, 0.615661, 0.617035, 0.618408, 0.619779,
+0.621147, 0.622514, 0.623879, 0.625242, 0.626603, 0.627963, 0.629320, 0.630675,
+0.632029, 0.633380, 0.634730, 0.636078, 0.637423, 0.638767, 0.640109, 0.641449,
+0.642787, 0.644123, 0.645457, 0.646789, 0.648119, 0.649448, 0.650774, 0.652098,
+0.653420, 0.654740, 0.656059, 0.657375, 0.658689, 0.660001, 0.661311, 0.662620,
+0.663926, 0.665230, 0.666532, 0.667832, 0.669130, 0.670426, 0.671720, 0.673012,
+0.674302, 0.675590, 0.676875, 0.678159, 0.679441, 0.680720, 0.681998, 0.683273,
+0.684547, 0.685818, 0.687087, 0.688354, 0.689619, 0.690882, 0.692143, 0.693401,
+0.694658, 0.695912, 0.697165, 0.698415, 0.699663, 0.700909, 0.702153, 0.703394,
+0.704634, 0.705871, 0.707106,
};
-
-static float Const Cosines[] = {
-1.00000, .999962, .999848, .999657, .999391, .999048, .998630, .998135,
-.997564, .996917, .996195, .995396, .994522, .993572, .992546, .991445,
-.990268, .989016, .987688, .986286, .984808, .983255, .981627, .979925,
-.978148, .976296, .974370, .972370, .970296, .968148, .965926, .963630,
-.961262, .958820, .956305, .953717, .951057, .948324, .945519, .942641,
-.939693, .936672, .933580, .930418, .927184, .923880, .920505, .917060,
-.913545, .909961, .906308, .902585, .898794, .894934, .891007, .887011,
-.882948, .878817, .874620, .870356, .866025, .861629, .857167, .852640,
-.848048, .843391, .838671, .833886, .829038, .824126, .819152, .814116,
-.809017, .803857, .798636, .793353, .788011, .782608, .777146, .771625,
-.766044, .760406, .754710, .748956, .743145, .737277, .731354, .725374,
-.719340, .713250, .707107
+static float const Cosines[] = {
+1.000000, 0.999998, 0.999993, 0.999986, 0.999975, 0.999961, 0.999945, 0.999925,
+0.999902, 0.999876, 0.999847, 0.999815, 0.999780, 0.999742, 0.999701, 0.999657,
+0.999610, 0.999559, 0.999506, 0.999450, 0.999390, 0.999328, 0.999262, 0.999194,
+0.999122, 0.999048, 0.998970, 0.998889, 0.998806, 0.998719, 0.998629, 0.998536,
+0.998440, 0.998341, 0.998239, 0.998134, 0.998026, 0.997915, 0.997801, 0.997684,
+0.997564, 0.997440, 0.997314, 0.997185, 0.997052, 0.996917, 0.996778, 0.996637,
+0.996492, 0.996345, 0.996194, 0.996041, 0.995884, 0.995724, 0.995561, 0.995396,
+0.995227, 0.995055, 0.994880, 0.994702, 0.994521, 0.994337, 0.994150, 0.993960,
+0.993767, 0.993571, 0.993372, 0.993170, 0.992965, 0.992757, 0.992546, 0.992331,
+0.992114, 0.991894, 0.991671, 0.991444, 0.991215, 0.990983, 0.990747, 0.990509,
+0.990268, 0.990023, 0.989776, 0.989525, 0.989272, 0.989015, 0.988756, 0.988493,
+0.988228, 0.987959, 0.987688, 0.987413, 0.987136, 0.986855, 0.986572, 0.986285,
+0.985996, 0.985703, 0.985407, 0.985109, 0.984807, 0.984503, 0.984195, 0.983885,
+0.983571, 0.983254, 0.982935, 0.982612, 0.982287, 0.981958, 0.981627, 0.981292,
+0.980955, 0.980614, 0.980271, 0.979924, 0.979575, 0.979222, 0.978867, 0.978508,
+0.978147, 0.977783, 0.977415, 0.977045, 0.976672, 0.976296, 0.975916, 0.975534,
+0.975149, 0.974761, 0.974370, 0.973975, 0.973578, 0.973178, 0.972775, 0.972369,
+0.971961, 0.971549, 0.971134, 0.970716, 0.970295, 0.969872, 0.969445, 0.969015,
+0.968583, 0.968147, 0.967709, 0.967267, 0.966823, 0.966376, 0.965925, 0.965472,
+0.965016, 0.964557, 0.964095, 0.963630, 0.963162, 0.962691, 0.962217, 0.961741,
+0.961261, 0.960779, 0.960293, 0.959805, 0.959313, 0.958819, 0.958322, 0.957822,
+0.957319, 0.956813, 0.956304, 0.955793, 0.955278, 0.954760, 0.954240, 0.953716,
+0.953190, 0.952661, 0.952129, 0.951594, 0.951056, 0.950515, 0.949972, 0.949425,
+0.948876, 0.948323, 0.947768, 0.947210, 0.946649, 0.946085, 0.945518, 0.944948,
+0.944376, 0.943800, 0.943222, 0.942641, 0.942057, 0.941470, 0.940880, 0.940288,
+0.939692, 0.939094, 0.938493, 0.937888, 0.937281, 0.936672, 0.936059, 0.935444,
+0.934825, 0.934204, 0.933580, 0.932953, 0.932323, 0.931691, 0.931055, 0.930417,
+0.929776, 0.929132, 0.928485, 0.927836, 0.927183, 0.926528, 0.925870, 0.925209,
+0.924546, 0.923879, 0.923210, 0.922538, 0.921863, 0.921185, 0.920504, 0.919821,
+0.919135, 0.918446, 0.917754, 0.917060, 0.916362, 0.915662, 0.914959, 0.914253,
+0.913545, 0.912834, 0.912120, 0.911403, 0.910683, 0.909961, 0.909236, 0.908508,
+0.907777, 0.907044, 0.906307, 0.905568, 0.904827, 0.904082, 0.903335, 0.902585,
+0.901832, 0.901077, 0.900318, 0.899557, 0.898794, 0.898027, 0.897258, 0.896486,
+0.895711, 0.894934, 0.894154, 0.893371, 0.892585, 0.891797, 0.891006, 0.890212,
+0.889416, 0.888617, 0.887815, 0.887010, 0.886203, 0.885393, 0.884580, 0.883765,
+0.882947, 0.882126, 0.881303, 0.880477, 0.879648, 0.878817, 0.877982, 0.877146,
+0.876306, 0.875464, 0.874619, 0.873772, 0.872922, 0.872069, 0.871213, 0.870355,
+0.869494, 0.868631, 0.867765, 0.866896, 0.866025, 0.865151, 0.864274, 0.863395,
+0.862513, 0.861629, 0.860742, 0.859852, 0.858959, 0.858064, 0.857167, 0.856267,
+0.855364, 0.854458, 0.853550, 0.852640, 0.851726, 0.850811, 0.849892, 0.848971,
+0.848048, 0.847121, 0.846193, 0.845261, 0.844327, 0.843391, 0.842452, 0.841510,
+0.840566, 0.839619, 0.838670, 0.837718, 0.836764, 0.835807, 0.834847, 0.833885,
+0.832921, 0.831954, 0.830984, 0.830012, 0.829037, 0.828060, 0.827080, 0.826098,
+0.825113, 0.824126, 0.823136, 0.822144, 0.821149, 0.820151, 0.819152, 0.818149,
+0.817144, 0.816137, 0.815127, 0.814115, 0.813100, 0.812083, 0.811063, 0.810041,
+0.809016, 0.807989, 0.806960, 0.805928, 0.804893, 0.803856, 0.802817, 0.801775,
+0.800731, 0.799684, 0.798635, 0.797583, 0.796529, 0.795473, 0.794414, 0.793353,
+0.792289, 0.791223, 0.790155, 0.789084, 0.788010, 0.786935, 0.785856, 0.784776,
+0.783693, 0.782608, 0.781520, 0.780430, 0.779337, 0.778243, 0.777145, 0.776046,
+0.774944, 0.773840, 0.772733, 0.771624, 0.770513, 0.769399, 0.768283, 0.767165,
+0.766044, 0.764921, 0.763796, 0.762668, 0.761538, 0.760405, 0.759271, 0.758134,
+0.756995, 0.755853, 0.754709, 0.753563, 0.752414, 0.751264, 0.750111, 0.748955,
+0.747798, 0.746638, 0.745475, 0.744311, 0.743144, 0.741975, 0.740804, 0.739631,
+0.738455, 0.737277, 0.736097, 0.734914, 0.733729, 0.732542, 0.731353, 0.730162,
+0.728968, 0.727772, 0.726574, 0.725374, 0.724171, 0.722967, 0.721760, 0.720551,
+0.719339, 0.718126, 0.716910, 0.715692, 0.714472, 0.713250, 0.712026, 0.710799,
+0.709570, 0.708339, 0.707106,
};
-static void ClockAngle(tick_units, sinp, cosp)
- int tick_units;
- double *sinp, *cosp;
+static void
+ClockAngle(int tick_units, double *sinp, double *cosp)
{
int reduced, upper;
- reduced = tick_units % 90;
- upper = tick_units / 90;
+ reduced = tick_units % 450;
+ upper = tick_units / 450;
if (upper & 1)
- reduced = 90 - reduced;
+ reduced = 450 - reduced;
if ((upper + 1) & 2) {
*sinp = Cosines[reduced];
*cosp = Sines[reduced];
@@ -607,11 +1471,9 @@ static void ClockAngle(tick_units, sinp, cosp)
* to the perimeter, then erasing all but the outside most pixels doesn't
* work because of round-off error (sigh).
*/
-static void DrawLine(w, blank_length, length, tick_units)
-ClockWidget w;
-Dimension blank_length;
-Dimension length;
-int tick_units;
+static void
+DrawLine(ClockWidget w, Dimension blank_length, Dimension length,
+ int tick_units)
{
double dblank_length = (double)blank_length, dlength = (double)length;
double cosangle, sinangle;
@@ -644,10 +1506,8 @@ int tick_units;
* how far around the circle (clockwise) from high noon.
*
*/
-static void DrawHand(w, length, width, tick_units)
-ClockWidget w;
-Dimension length, width;
-int tick_units;
+static void
+DrawHand(ClockWidget w, Dimension length, Dimension width, int tick_units)
{
double cosangle, sinangle;
@@ -675,14 +1535,14 @@ int tick_units;
wc = width * cosangle;
ws = width * sinangle;
SetSeg(w,
- x = w->clock.centerX + round(length * sinangle),
- y = w->clock.centerY - round(length * cosangle),
- x1 = w->clock.centerX - round(ws + wc),
- y1 = w->clock.centerY + round(wc - ws)); /* 1 ---- 2 */
+ x = w->clock.centerX + clock_round(length * sinangle),
+ y = w->clock.centerY - clock_round(length * cosangle),
+ x1 = w->clock.centerX - clock_round(ws + wc),
+ y1 = w->clock.centerY + clock_round(wc - ws)); /* 1 ---- 2 */
/* 2 */
SetSeg(w, x1, y1,
- x2 = w->clock.centerX - round(ws - wc),
- y2 = w->clock.centerY + round(wc + ws)); /* 2 ----- 3 */
+ x2 = w->clock.centerX - clock_round(ws - wc),
+ y2 = w->clock.centerY + clock_round(wc + ws)); /* 2 ----- 3 */
SetSeg(w, x2, y2, x, y); /* 3 ----- 1(4) */
}
@@ -697,10 +1557,9 @@ int tick_units;
* how far around the circle (clockwise) from high noon.
*
*/
-static void DrawSecond(w, length, width, offset, tick_units)
-ClockWidget w;
-Dimension length, width, offset;
-int tick_units;
+static void
+DrawSecond(ClockWidget w, Dimension length, Dimension width,
+ Dimension offset, int tick_units)
{
double cosangle, sinangle;
@@ -744,22 +1603,21 @@ int tick_units;
ws = width * sinangle;
/*1 ---- 2 */
SetSeg(w,
- x = w->clock.centerX + round(length * sinangle),
- y = w->clock.centerY - round(length * cosangle),
- w->clock.centerX + round(ms - wc),
- w->clock.centerY - round(mc + ws) );
- SetSeg(w, w->clock.centerX + round(offset *sinangle),
- w->clock.centerY - round(offset * cosangle), /* 2-----3 */
- w->clock.centerX + round(ms + wc),
- w->clock.centerY - round(mc - ws));
+ x = w->clock.centerX + clock_round(length * sinangle),
+ y = w->clock.centerY - clock_round(length * cosangle),
+ w->clock.centerX + clock_round(ms - wc),
+ w->clock.centerY - clock_round(mc + ws) );
+ SetSeg(w, w->clock.centerX + clock_round(offset *sinangle),
+ w->clock.centerY - clock_round(offset * cosangle), /* 2-----3 */
+ w->clock.centerX + clock_round(ms + wc),
+ w->clock.centerY - clock_round(mc - ws));
w->clock.segbuffptr->x = x;
w->clock.segbuffptr++->y = y;
w->clock.numseg ++;
}
-static void SetSeg(w, x1, y1, x2, y2)
-ClockWidget w;
-int x1, y1, x2, y2;
+static void
+SetSeg(ClockWidget w, int x1, int y1, int x2, int y2)
{
w->clock.segbuffptr->x = x1;
w->clock.segbuffptr++->y = y1;
@@ -772,8 +1630,8 @@ int x1, y1, x2, y2;
* Draw the clock face (every fifth tick-mark is longer
* than the others).
*/
-static void DrawClockFace(w)
-ClockWidget w;
+static void
+DrawClockFace(ClockWidget w)
{
register int i;
register int delta = (int)(w->clock.radius - w->clock.second_hand_length) / 3;
@@ -781,10 +1639,43 @@ ClockWidget w;
w->clock.segbuffptr = w->clock.segbuff;
w->clock.numseg = 0;
for (i = 0; i < 60; i++)
+ {
+#ifdef XRENDER
+ if (w->clock.render && w->clock.can_polygon)
+ {
+ double s, c;
+ XDouble x1, y1, x2, y2;
+ XftColor *color;
+ ClockAngle (i * 60, &s, &c);
+ x1 = c;
+ y1 = s;
+ if (i % 5)
+ {
+ x2 = c * (MINOR_TICK_FRACT / 100.0);
+ y2 = s * (MINOR_TICK_FRACT / 100.0);
+ color = &w->clock.minor_color;
+ }
+ else
+ {
+ x2 = c * (SECOND_HAND_FRACT / 100.0);
+ y2 = s * (SECOND_HAND_FRACT / 100.0);
+ color = &w->clock.major_color;
+ }
+ RenderLine (w, x1, y1, x2, y2, color, True);
+ }
+ else
+#endif
+ {
DrawLine(w, ( (i % 5) == 0 ?
w->clock.second_hand_length :
(w->clock.radius - delta) ),
- w->clock.radius, i * 12);
+ w->clock.radius, i * 60);
+ }
+ }
+#ifdef XRENDER
+ if (w->clock.render && w->clock.can_polygon)
+ return;
+#endif
/*
* Go ahead and draw it.
*/
@@ -796,17 +1687,28 @@ ClockWidget w;
w->clock.numseg = 0;
}
-static int round(x)
-double x;
+static int
+clock_round(double x)
{
return(x >= 0.0 ? (int)(x + .5) : (int)(x - .5));
}
+#ifdef XRENDER
+static Boolean
+sameColor (XftColor *old, XftColor *new)
+{
+ if (old->color.red != new->color.red) return False;
+ if (old->color.green != new->color.green) return False;
+ if (old->color.blue != new->color.blue) return False;
+ if (old->color.alpha != new->color.alpha) return False;
+ return True;
+}
+#endif
+
/* ARGSUSED */
-static Boolean SetValues (gcurrent, grequest, gnew, args, num_args)
- Widget gcurrent, grequest, gnew;
- ArgList args;
- Cardinal *num_args;
+static Boolean
+SetValues(Widget gcurrent, Widget grequest, Widget gnew,
+ ArgList args, Cardinal *num_args)
{
ClockWidget current = (ClockWidget) gcurrent;
ClockWidget new = (ClockWidget) gnew;
@@ -827,6 +1729,8 @@ static Boolean SetValues (gcurrent, grequest, gnew, args, num_args)
clock_tic, (XtPointer)gnew);
new->clock.show_second_hand =(new->clock.update <= SECOND_HAND_TIME);
+ if (new->clock.show_second_hand != current->clock.show_second_hand)
+ redisplay = TRUE;
}
if (new->clock.padding != current->clock.padding)
@@ -838,10 +1742,10 @@ static Boolean SetValues (gcurrent, grequest, gnew, args, num_args)
if (new->clock.font != current->clock.font)
redisplay = TRUE;
- if ((new->clock.fgpixel != current->clock.fgpixel)
+ if ((ClockFgPixel(new) != ClockFgPixel (current))
|| (new->core.background_pixel != current->core.background_pixel)) {
valuemask = GCForeground | GCBackground | GCFont | GCLineWidth;
- myXGCV.foreground = new->clock.fgpixel;
+ myXGCV.foreground = ClockFgPixel (new);
myXGCV.background = new->core.background_pixel;
myXGCV.font = new->clock.font->fid;
myXGCV.line_width = 0;
@@ -869,14 +1773,43 @@ static Boolean SetValues (gcurrent, grequest, gnew, args, num_args)
}
if (new->core.background_pixel != current->core.background_pixel) {
- valuemask = GCForeground | GCLineWidth;
+ valuemask = GCForeground | GCLineWidth | GCGraphicsExposures;
myXGCV.foreground = new->core.background_pixel;
myXGCV.line_width = 0;
+ myXGCV.graphics_exposures = False;
XtReleaseGC (gcurrent, current->clock.EraseGC);
new->clock.EraseGC = XtGetGC((Widget)gcurrent, valuemask, &myXGCV);
redisplay = TRUE;
}
-
+#ifdef XRENDER
+ if (new->clock.face != current->clock.face)
+ redisplay = TRUE;
+ if (!sameColor (&new->clock.hour_color, &current->clock.fg_color) ||
+ !sameColor (&new->clock.hour_color, &current->clock.hour_color) ||
+ !sameColor (&new->clock.min_color, &current->clock.min_color) ||
+ !sameColor (&new->clock.sec_color, &current->clock.sec_color) ||
+ !sameColor (&new->clock.major_color, &current->clock.major_color) ||
+ !sameColor (&new->clock.minor_color, &current->clock.minor_color))
+ redisplay = True;
+ if (new->clock.sharp != current->clock.sharp)
+ redisplay = True;
+ if (new->clock.render != current->clock.render)
+ redisplay = True;
+ if (new->clock.buffer != current->clock.buffer)
+ {
+ if (new->clock.pixmap)
+ {
+ XFreePixmap (XtDisplay (new), new->clock.pixmap);
+ new->clock.pixmap = 0;
+ }
+ if (new->clock.draw)
+ {
+ XftDrawDestroy (new->clock.draw);
+ new->clock.draw = 0;
+ }
+ new->clock.picture = 0;
+ }
+#endif
return (redisplay);
}