teckk |
03-14-2024 08:36 PM |
Quote:
I'm trying to teach myself basic cairo programming but I have got stuck on arcs
|
Did that a while back hazel. Here is a working example that you can pick apart. I updated to current gtk3 syntax, and compiled with no errors.
clock.c
Code:
//gcc -lm clock.c -o clock $(pkg-config --cflags --libs gtk+-3.0)
#include <math.h>
#include <cairo.h>
#include <gtk/gtk.h>
#include <time.h>
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 800
#define WHITE 255, 255, 255
#define RED 255, 0, 0
#define CYAN 0, 255, 255
#define WIDTH 3
static char buffer[256];
static time_t curtime;
static struct tm *loctime;
static int seconds;
static int minutes;
static int hours;
static int radius;
static int movingSecondsEffect = FALSE;
static void quit_application(gpointer app) {
g_application_quit (G_APPLICATION (app));
}
static void clicked(GtkWindow *window, GdkEventButton *event, gpointer user_data) {
gtk_window_set_decorated(window, !gtk_window_get_decorated(window));
}
//Hours ticks
void HourTick (GtkWidget *widget, cairo_t *cr, int nHour, int cx, int cy) {
double dRadians = nHour * 3.14 / 6.0;
int x1 = cx+(int) ((0.9 * radius * sin (dRadians)));
int y1 = cy-(int) ((0.9 * radius * cos (dRadians)));
int x2 = cx+(int) ((1.0 * radius * sin (dRadians)));
int y2 = cy-(int) ((1.0 * radius * cos (dRadians)));
cairo_set_source_rgb(cr, CYAN);
cairo_set_line_width(cr, WIDTH);
cairo_move_to(cr, x1, y1);
cairo_line_to(cr, x2, y2);
cairo_stroke(cr);
}
//Minute ticks
void MinTick (GtkWidget *widget, cairo_t *cr, int nHour, int cx, int cy) {
double dRadians2 = nHour * 3.14 / 30.0;
int a1 = cx+(int) ((0.97 * radius * sin (dRadians2)));
int b1 = cy-(int) ((0.97 * radius * cos (dRadians2)));
int a2 = cx+(int) ((1.0 * radius * sin (dRadians2)));
int b2 = cy-(int) ((1.0 * radius * cos (dRadians2)));
cairo_set_source_rgb(cr, CYAN);
cairo_set_line_width(cr, WIDTH);
cairo_move_to(cr, a1, b1);
cairo_line_to(cr, a2, b2);
cairo_stroke(cr);
}
void DrawSeconds (GtkWidget *widget, cairo_t *cr, int cx, int cy) {
/* --- Get radians from seconds --- */
float dRadians = seconds * 3.14 / 30.0;
/* --- Draw seconds --- */
cairo_set_source_rgb(cr, RED);
cairo_set_line_width(cr, WIDTH);
cairo_move_to(cr, cx, cy);
cairo_line_to(cr, cx + (0.9 * radius * sin (dRadians)),
cy - (0.9 * radius * cos (dRadians)));
cairo_stroke(cr);
}
void DrawMinutes (GtkWidget *widget, cairo_t *cr, int cx, int cy) {
/* --- Get radians from seconds --- */
float dRadians = (minutes * 3.14 / 30.0) + (seconds * 3.14 / 1800.0);
/* --- Draw seconds --- */
cairo_set_source_rgb(cr, CYAN);
cairo_set_line_width(cr, WIDTH * 2);
cairo_move_to(cr, cx, cy);
cairo_line_to(cr, cx + (0.8 * radius * sin (dRadians)),
cy - (0.8 * radius * cos (dRadians)));
cairo_stroke(cr);
}
void DrawHours (GtkWidget *widget, cairo_t *cr, int cx, int cy) {
/* --- Get radians from seconds --- */
float dRadians = ((hours % 12) * 3.14 / 6.0) + (minutes * 3.14 / 360.0);
/* --- Draw seconds --- */
cairo_set_source_rgb(cr, CYAN);
cairo_set_line_width(cr, WIDTH * 3);
cairo_move_to(cr, cx, cy);
cairo_line_to(cr, cx + (0.6 * radius * sin (dRadians)),
cy - (0.6 * radius * cos (dRadians)));
cairo_stroke(cr);
}
static gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data) {
int midx = gtk_widget_get_allocated_width(widget)/2;
int midy = gtk_widget_get_allocated_height(widget)/2;
int nHour;
/* --- Draw Tickmarks at each hour/ minute --- */
for (nHour = 1; nHour <= 60; nHour++) {
MinTick(widget, cr, nHour, midx, midy);
if(nHour <= 12) {
HourTick(widget, cr, nHour, midx, midy);
}
}
cairo_set_source_rgb(cr, WHITE);
cairo_set_font_size (cr, 50);
cairo_move_to(cr, midx/1.4, midy/2);
cairo_show_text(cr, buffer);
radius = MIN (midx, midy) -2 ;
cairo_move_to(cr, midx , 0);
DrawSeconds (widget, cr, midx, midy);
DrawMinutes (widget, cr, midx, midy);
DrawHours (widget, cr, midx, midy);
return FALSE;
}
static gint time_handler (GtkWidget *widget) {
curtime = time(NULL);
loctime = localtime(&curtime);
seconds = loctime->tm_sec;
minutes = loctime->tm_min;
hours = loctime->tm_hour;
strftime(buffer, 256, "%T", loctime);
gtk_widget_queue_draw(widget);
return TRUE;
}
static void activate (GtkApplication* app, gpointer user_data) {
GtkWidget *window;
GtkWidget *frame;
GtkWidget *drawing_area;
GtkWidget *ebox;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Hazels' Cairo Clock");
gtk_window_set_default_size (GTK_WINDOW (window), WINDOW_WIDTH, WINDOW_HEIGHT);
gtk_container_set_border_width (GTK_CONTAINER (window), 0);
gtk_widget_set_app_paintable(window, TRUE);
GdkScreen *screen = gtk_widget_get_screen(window);
GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
gtk_widget_set_visual(window, visual);
ebox = gtk_event_box_new();
gtk_container_add(GTK_CONTAINER(window), ebox);
drawing_area = gtk_drawing_area_new();
gtk_widget_set_size_request (drawing_area, WINDOW_WIDTH - 20 , WINDOW_HEIGHT - 20);
gtk_container_add (GTK_CONTAINER (ebox), drawing_area);
g_signal_connect (drawing_area, "draw", G_CALLBACK (draw_cb), NULL);
g_signal_connect (drawing_area, "delete-event", G_CALLBACK (gtk_main_quit), NULL);
gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);
g_signal_connect(window, "button-press-event", G_CALLBACK(clicked), NULL);
g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(quit_application), app);
g_timeout_add (1000, (GSourceFunc) time_handler, drawing_area);
gtk_widget_show_all (window);
}
int main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new("org.cairo.clock", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run(G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
Edit: Removed 3 functions that werent needed.
|