aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/calp.c57
-rw-r--r--src/color.h1
-rw-r--r--src/draw.c117
-rw-r--r--src/draw.h8
4 files changed, 127 insertions, 56 deletions
diff --git a/src/calp.c b/src/calp.c
index 893b5f4..2d155cc 100644
--- a/src/calp.c
+++ b/src/calp.c
@@ -46,33 +46,40 @@ int main (void) {
// Leap year adjustment: increment February day count by one if
// it is a leap year.
- int year = 2026;
+ int year = 3043;
if (isleap(year)) {
days_in_month[1]++;
}
+ int verbose_output = 1;
+
// TBD: Add ability to choose filename
+ // Defaults to the year being generated
char filename[20];
snprintf(filename, sizeof(filename), "%d.pdf", year);
- //filename = "output.pdf";
+
// Initialization
// --------------
// Calculates measurements, stores them in dimensions struct. See "draw.h"
calculate_dimensions(width, height, &dim);
+ if (!CAIRO_HAS_PDF_SURFACE) {
+ printf("Error: PDF backend not available.\n");
+ return 1;
+ }
+
cairo_surface_t *surface = cairo_pdf_surface_create(filename, dim.paper_width, dim.paper_height);
cairo_t *paper = cairo_create(surface);
// Sub-surface for rendering content in day boxes
cairo_surface_t *day =
cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR_ALPHA, dim.day_width, dim.day_height);
+ // cd = context day
cairo_t *cd = cairo_create(day);
- // General rectangle struct for positioning. Used whenever dimensions need
- // to be passed to another function
- // PangoRectangle logical_extents;
+
// Fill background with white color
set_color(paper, WHITE);
@@ -84,7 +91,10 @@ int main (void) {
// Construction
// ------------
// Print dimensions, for debugging
- print_dimensions(&dim);
+
+ if (verbose_output) {
+ print_dimensions(&dim);
+ }
// Range of months to be rendered (Default: Full calendar year, 12 months)
@@ -97,32 +107,61 @@ int main (void) {
// Initialize month struct
month.first_day = day_of_week(1, i + 1, year);
month.num_of_days = days_in_month[i];
+ month.month_position = i;
+ month.minimum_rows = calculate_minimum_rows(&month, &dim);
+ printf("month.minimum_rows: %d\n", month.minimum_rows);
- //draw_image(paper, "assets/weather.png", 0, 0);
+ dim.header_width = dim.paper_width - (dim.margin * 2.0);
+ dim.header_height = dim.paper_height - (dim.margin * 3.0) - (month.minimum_rows * dim.day_height);
+ cairo_surface_t *header = cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR_ALPHA, dim.header_width, dim.header_height);
+ cairo_t *ch = cairo_create(header);
- set_color(paper, BLACK);
- draw_month_title(paper, &dim, months[i]);
+ //set_color(ch, BLUE);
+ //fill_bg(ch);
+
+ set_color(ch, BLACK);
+ draw_month_title(ch, &dim, "Sans", 40, months[i]);
+
+ printf("header width: %f\n", dim.header_width);
+ printf("header height: %f\n", dim.header_height);
char path[20];
snprintf(path, 20, "assets/%d.png", i + 1);
+ if (verbose_output) {
+ printf("Drawing month \'%s\'\n", months[i]);
+ }
draw_month_art(paper, &dim, path);
+
+
+ cairo_set_source_surface(paper, header, dim.margin, dim.margin);
+ cairo_paint(paper);
draw_month(paper, cd, day, &month, &dim);
draw_month_grid(paper, &month, &dim);
// Go to the next page in pdf
cairo_show_page(paper);
+
+ cairo_destroy(ch);
+ cairo_surface_destroy(header);
}
+ if (verbose_output) {
+ printf("Finished generating \'%s\'.\n", filename);
+ }
// Clean up
// --------
cairo_destroy(paper);
cairo_surface_destroy(surface);
+
+ cairo_destroy(cd);
+ cairo_surface_destroy(day);
+
return 0;
}
diff --git a/src/color.h b/src/color.h
index 2ce4995..ee42779 100644
--- a/src/color.h
+++ b/src/color.h
@@ -2,3 +2,4 @@
#define WHITE "FFFFFF"
#define GREEN "008000"
#define RED "FF2052"
+#define BLUE "4169e1"
diff --git a/src/draw.c b/src/draw.c
index d5dbe37..bdc62af 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -22,16 +22,21 @@ struct dimensions {
double day_width; /* day box width */
double day_height; /* day box height */
double margin; /* margin */
+ double header_width;
+ double header_height;
};
// struct to hold Month-specific info, like what day of the week the first
// day lands on, how many days are in the month, etc.
struct month_info {
+ int month_position;
int first_day;
int num_of_days;
+ int minimum_rows;
};
+// struct for defining RGB colors
struct RGB {
double r;
double g;
@@ -39,20 +44,16 @@ struct RGB {
};
+
// Convert Hex color strings to their RGB counterparts.
// IMO, hex strings are easier to work with, so this is
// a nice helper function.
struct RGB hex_to_rgb(char *str) {
- double r, g, b;
- unsigned int ri, gi, bi;
+ unsigned int r, g, b;
struct RGB color;
- sscanf(str, "%02x%02x%02x", &ri, &gi, &bi);
+ sscanf(str, "%02x%02x%02x", &r, &g, &b);
- r = ri;
- g = gi;
- b = bi;
-
color.r = (r / 255.0);
color.g = (g / 255.0);
color.b = (b / 255.0);
@@ -151,32 +152,35 @@ PangoRectangle get_logical_extents (cairo_t *c, char *font_family, int font_size
}
+
// Calculate dimenions for one page and stores it in the dimensions struct
// Used for determining where elements should be drawn on the page
int calculate_dimensions(double pw, double ph, struct dimensions *d) {
+ d->row_count = 6;
+ d->column_count = 7;
+
// Percentage of page that should be margin
double margin = 0.05 * pw;
+
+ // width of day is 1/7th of total width
+ double box_width = pw / 10.0;
// Everything other than margin
- double month_width = 0.9 * pw;
+ double month_width = box_width * d->column_count;
- // width of day is 1/7th of total width
- double box_width = month_width / 7.0;
// Width = Height; Day Box is a square
double box_height = box_width;
// Height is based on how tall # of weeks are
- double month_height = box_height * 6.0;
+ double month_height = box_height * d->row_count;
// Set items in struct to calculated values
- d->row_count = 6;
- d->column_count = 7;
d->paper_width = pw;
d->paper_height = ph;
d->margin = margin;
d->month_width = month_width;
- d->month_top_corner_x = margin;
+ d->month_top_corner_x = (pw - (month_width)) / 2.0;
d->month_top_corner_y = ph - margin - month_height;
d->month_height = month_height;
d->day_width = box_width;
@@ -199,6 +203,8 @@ int print_dimensions(struct dimensions *d) {
printf("month_top_corner_y: %f\n", d->month_top_corner_y);
printf("day width: %.2f\n", d->day_width);
printf("day height: %.2f\n", d->day_height);
+ printf("header width: %.2f\n", d->header_width);
+ printf("header height: %.2f\n", d->header_height);
return 0;
}
@@ -270,6 +276,27 @@ int draw_month_grid (cairo_t *c, struct month_info *m, struct dimensions *d) {
+int construct_day_box(cairo_t *cd, int month, int day, int week_day) {
+ char str[20];
+ double padding = 8.0;
+
+ set_color(cd, WHITE);
+ fill_bg(cd);
+
+ if ((month == 0) && (day == 1) && (week_day == 1)) {
+ }
+
+ // draw_text(), and therefore pango_layout_set_text(), needs a
+ // string as input, so the current day's date is converted.
+ snprintf(str, sizeof(str), "%d", day);
+
+ set_color(cd, BLACK);
+ draw_text(cd, padding, padding, "Monospace", 15, str);
+ return 0;
+}
+
+
+
// Draws one month using daybox sub-surface & context, main context, and dimension struct
int draw_month (cairo_t *c, cairo_t *cd, cairo_surface_t *s, struct month_info *m, struct dimensions *d) {
double cursor_x = d->month_top_corner_x;
@@ -284,7 +311,6 @@ int draw_month (cairo_t *c, cairo_t *cd, cairo_surface_t *s, struct month_info *
int increment = 0;
- char str[20];
for (int i = 0; i < d->row_count; i++) {
for (int k = current_day; k < d->column_count; k++) {
@@ -292,24 +318,11 @@ int draw_month (cairo_t *c, cairo_t *cd, cairo_surface_t *s, struct month_info *
// the function.
if (increment >= m->num_of_days) return 0;
- set_color(cd, WHITE);
- fill_bg(cd);
-
- // Change text color
- set_color(cd, BLACK);
-
-
- // draw_text(), and therefore pango_layout_set_text(), needs a
- // string as input, so the current day's date is converted.
- snprintf(str, sizeof(str), "%d", increment + 1);
-
- // Position within cd is arbitrary: (0,0) is too close to edge,
- // so the text is offset a little bit.
- draw_text(cd, 4.0, 4.0, "Sans", 10, str);
+ construct_day_box(cd, m->month_position, increment + 1, k);
- // Position sub-surface on main surface
+ // Position the constructed day box on main surface
cairo_set_source_surface (c, s, cursor_x, cursor_y);
cairo_paint(c);
@@ -331,27 +344,41 @@ int draw_month (cairo_t *c, cairo_t *cd, cairo_surface_t *s, struct month_info *
// Draws the month being drawn at the top of the page
-int draw_month_title(cairo_t *c, struct dimensions *d, char *name) {
- double height = d->paper_height - d->month_height - (d->margin * 2.0) - 40.0;
+int draw_month_title(cairo_t *c, struct dimensions *d, char *font_family, int font_size, char *name) {
PangoRectangle rect;
- char *font = "Serif";
- int font_size = 40;
+ rect = get_logical_extents(c, font_family, font_size, name);
- rect = get_logical_extents(c, font, font_size, name);
-
- double cursor_x = (d->paper_width / 2.0) - ((rect.width / 2.0));
- double cursor_y = height + d->margin;
- draw_text(c, cursor_x, cursor_y, font, font_size, name);
+ //double cursor_x = (d->header_height / 2.0) - ((rect.width / 2.0));
+ double cursor_x = ((d->header_width - rect.width) / 2.0);
+ //double cursor_y = height + d->margin;
+ double cursor_y = d->header_height - rect.height - d->margin;
+ draw_text(c, cursor_x, cursor_y, font_family, font_size, name);
return 0;
}
+
// Draw an image at a specified point
int draw_image(cairo_t *c, char *path, double x, double y) {
cairo_surface_t *image;
+
+ // Checks if the file exists. If it doesn't, warn the user that it was not found.
+ // A file not existing will not terminate the program, but simply not render the image.
+ FILE *file;
+ if((file = fopen(path, "r")) != NULL)
+ {
+ // file exists
+ fclose(file);
+ }
+ else
+ {
+ printf("Warning: image \'%s\' does not exist.\n", path);
+ return 1;
+ }
+
image = cairo_image_surface_create_from_png(path);
cairo_set_source_surface(c, image, x, y);
cairo_paint(c);
@@ -362,16 +389,16 @@ int draw_image(cairo_t *c, char *path, double x, double y) {
-// Draw month art, if specified, above the calendar but below the
-// month's name. Images are cropped if they are too big or don't fit
-// the dimensions
+
+// Draw month art
int draw_month_art(cairo_t *c, struct dimensions *d, char *path) {
cairo_save(c);
- double width = d->month_width;
- double height = d->paper_height - d->month_height - (d->margin * 2.0) - 40.0;
+ double width = d->header_width;
+ // TODO: Make this relative to text height
+ double height = d->header_height - (d->margin * 3.0);
+
double cursor_x = d->margin;
double cursor_y = d->margin;
- printf("drawing month...\n");
cairo_rectangle (c, d->margin, d->margin, width, height);
cairo_clip(c);
diff --git a/src/draw.h b/src/draw.h
index 5955e1e..40ca609 100644
--- a/src/draw.h
+++ b/src/draw.h
@@ -10,6 +10,8 @@ struct dimensions {
double day_width; /* day box width */
double day_height; /* day box height */
double margin; /* margin */
+ double header_width;
+ double header_height;
};
int fill_bg(cairo_t *c);
@@ -21,8 +23,10 @@ struct RGB {
};
struct month_info {
+ int month_position;
int first_day;
int num_of_days;
+ int minimum_rows;
};
struct RGB hex_to_rgb(char *str);
@@ -41,7 +45,7 @@ int draw_month (cairo_t *c, cairo_t *cd, cairo_surface_t *s, struct month_info *
int day_of_week (int d, int m, int y);
-int draw_month_title(cairo_t *c, struct dimensions *d, char *name);
+int draw_month_title(cairo_t *c, struct dimensions *d, char *font_family, int font_size, char *name);
PangoRectangle get_logical_extents (cairo_t *c, char *font_family, int font_size, char *text);
@@ -51,4 +55,4 @@ int draw_image(cairo_t *c, char *path, double x, double y);
int draw_month_art(cairo_t *c, struct dimensions *d, char *path);
-
+int construct_day_box(cairo_t *cd, int month, int day, int week_day);