diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/calp.c | 57 | ||||
| -rw-r--r-- | src/color.h | 1 | ||||
| -rw-r--r-- | src/draw.c | 117 | ||||
| -rw-r--r-- | src/draw.h | 8 |
4 files changed, 127 insertions, 56 deletions
@@ -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" @@ -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); @@ -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); |
