diff options
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | src/calp.c | 47 | ||||
| -rw-r--r-- | src/draw.c | 47 | ||||
| -rw-r--r-- | src/draw.h | 16 | ||||
| -rw-r--r-- | src/ezini.c | 1033 | ||||
| -rw-r--r-- | src/ezini.h | 121 | ||||
| -rw-r--r-- | src/image.c | 173 | ||||
| -rw-r--r-- | src/image.h | 10 |
8 files changed, 95 insertions, 1358 deletions
@@ -2,13 +2,13 @@ VERSION = 0.0 PREFIX = /usr/local CC = cc DIR = src -OBJS = $(DIR)/calp.o $(DIR)/draw.o $(DIR)/date.o $(DIR)/image.o $(DIR)/ezini.o +OBJS = $(DIR)/calp.o $(DIR)/draw.o $(DIR)/date.o $(DIR)/image.o .PHONY: clean all install TARGET = calp -CFLAGS = `pkgconf --cflags pangocairo MagickWand` -O2 -g -Wall -Werror -Wextra -Winit-self -Wuninitialized -pedantic -LFLAGS = `pkgconf --libs pangocairo MagickWand` -lm +CFLAGS = `pkgconf --cflags pangocairo` -O2 -g -Wall -Werror -Wextra -Winit-self -Wuninitialized -pedantic +LFLAGS = `pkgconf --libs pangocairo` -lm all: $(TARGET) @@ -12,7 +12,6 @@ #include "date.h" #include "color.h" #include "image.h" -#include "ezini.h" // Metric #define A4_WIDTH 210 @@ -32,6 +31,9 @@ int main (void) { double width = A4_WIDTH; double height = A4_HEIGHT; + const int row_count = 6; + const int column_count = 7; + // Convert to inches, then 1 unit = 1/72th inch width = (width / 25.4) * 72.0; height = (height / 25.4) * 72.0; @@ -43,16 +45,15 @@ int main (void) { char *months[num_of_months]; extern int days_in_month[12]; - const nl_item nl_abmons[12] = {ABMON_1, ABMON_2, ABMON_3, ABMON_4, - ABMON_5, ABMON_6, ABMON_7, ABMON_8, - ABMON_9, ABMON_10, ABMON_11, ABMON_12}; + //const nl_item nl_abmons[12] = {ABMON_1, ABMON_2, ABMON_3, ABMON_4, + // ABMON_5, ABMON_6, ABMON_7, ABMON_8, + // ABMON_9, ABMON_10, ABMON_11, ABMON_12}; const nl_item nl_months[12] = {MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, MON_7, MON_8, MON_9, MON_10, MON_11, MON_12}; int i; setlocale(LC_ALL, ""); for (i = 0; i < 12; i++) { - printf("%d\t%s\t%s\n", i+1, nl_langinfo(nl_abmons[i]), nl_langinfo(nl_months[i])); months[i] = nl_langinfo(nl_months[i]); } @@ -68,7 +69,7 @@ int main (void) { // Leap year adjustment: increment February day count by one if // it is a leap year. - int year = 14; + const int year = 2026; if (isleap(year)) { days_in_month[1]++; } @@ -87,17 +88,41 @@ int main (void) { // Calculates measurements, stores them in dimensions struct. See "draw.h" calculate_dimensions(width, height, &dim); + + + struct extents paper_extents = { + .width = width, + .height = height + }; + + const double margin = 0.05 * paper_extents.width; + + struct extents day_extents = { + .width = paper_extents.width / 10.0, + .height = paper_extents.width / 10.0 + }; + + struct extents month_extents = { + .x = (paper_extents.width - (day_extents.width * column_count)) / 2.0, + .y = paper_extents.height - margin - (day_extents.height * row_count), + .width = day_extents.width * column_count, + .height = day_extents.height * row_count, + }; + + printf("%f\n", month_extents.x); + + 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_surface_t *surface = cairo_pdf_surface_create(filename, paper_extents.width, paper_extents.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); + cairo_surface_create_similar(surface, CAIRO_CONTENT_COLOR_ALPHA, day_extents.width, day_extents.height); // cd = context day cairo_t *cd = cairo_create(day); @@ -119,7 +144,7 @@ int main (void) { 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); + month.minimum_rows = calculate_minimum_rows(&month); 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); @@ -137,8 +162,6 @@ int main (void) { snprintf(path, 20, "assets/%d.png", i + 1); - prepare_month_art(path, &dim); - if (verbose_output) { printf("Drawing month \'%s\'\n", months[i]); } @@ -149,7 +172,7 @@ int main (void) { cairo_paint(paper); draw_month(paper, cd, day, &month, &dim); - draw_month_grid(paper, &month, &dim); + draw_month_grid(paper, &month, &month_extents, &day_extents); // Go to the next page in pdf cairo_show_page(paper); @@ -47,6 +47,16 @@ RGB { }; +// Generic struct for storing where an object is and how +// it takes up space. +struct extents { + double x; + double y; + double width; + double height; +}; + + // Convert Hex color strings to their RGB counterparts. // IMO, hex strings are easier to work with, so this is @@ -58,6 +68,7 @@ RGB hex_to_rgb(char *str) { sscanf(str, "%02x%02x%02x", &r, &g, &b); + // R, G, B values are from 0.0 - 1.0, so needs to be divided by 255.0 color.r = (r / 255.0); color.g = (g / 255.0); color.b = (b / 255.0); @@ -223,10 +234,10 @@ print_dimensions(struct dimensions *d) { // Most months can fit within 4 or 5 rows instead of 6. // TBD: This can probably done in a more efficient way int -calculate_minimum_rows(struct month_info *m, struct dimensions *d) { +calculate_minimum_rows(struct month_info *m) { int extra_rows = 0; - int days_in_first_week = (d->column_count - m->first_day); + int days_in_first_week = (7 - m->first_day); if (m->first_day == 0) { days_in_first_week = m->first_day; @@ -253,32 +264,40 @@ calculate_minimum_rows(struct month_info *m, struct dimensions *d) { // Draws the grid lines for a month int -draw_month_grid (cairo_t *c, struct month_info *m, struct dimensions *d) { - double cursor_x = d->month_top_corner_x; +draw_month_grid (cairo_t *c, struct month_info *m, struct extents *me, struct extents *de) { + double cursor_x = me->x; - int row_offset = d->row_count - calculate_minimum_rows(m, d); - double cursor_y = d->month_top_corner_y + (row_offset * d->day_height); + int column_count = 7; + int row_count = 6; + // double cursor_x = month_grid_pos->x; + + // make d->row_count reside in month_info *m + int row_offset = row_count - calculate_minimum_rows(m); + // double cursor_y = month_grid_pos->y; + double cursor_y = me->y + (row_offset * de->height); double x = cursor_x; double y = cursor_y; set_color(c, BLACK); - cairo_set_line_width (c, 1.0); + cairo_set_line_width(c, 1.0); - for (int i = 0; i <= d->column_count; i++) { + // Vertical lines + for (int i = 0; i <= column_count; i++) { cairo_move_to(c, cursor_x, cursor_y); - cairo_line_to(c, cursor_x, cursor_y + (d->month_height - (row_offset * d->day_height))); - cursor_x = cursor_x + d->day_width; + cairo_line_to(c, cursor_x, cursor_y + (me->height - (row_offset * de->height))); + cursor_x = cursor_x + de->width; } // Recenter the cursor cursor_x = x; cursor_y = y; - for (int i = 0; i <= d->row_count; i++) { + // Horizontal lines + for (int i = 0; i <= row_count; i++) { cairo_move_to(c, cursor_x, cursor_y); - cairo_line_to(c, cursor_x + d->month_width, cursor_y); - cursor_y = cursor_y + d->day_height; + cairo_line_to(c, cursor_x + me->width, cursor_y); + cursor_y = cursor_y + de->height; } cairo_stroke(c); @@ -317,7 +336,7 @@ draw_month(cairo_t *c, cairo_t *cd, cairo_surface_t *s, struct month_info *m, st if (m->first_day != 0) cursor_x = cursor_x + (d->day_width * m->first_day); // Push bottom of month as far down the page as the margin allows - int row_offset = d->row_count - calculate_minimum_rows(m, d); + int row_offset = d->row_count - calculate_minimum_rows(m); double cursor_y = d->month_top_corner_y + (row_offset * d->day_height); int current_day = m->first_day; @@ -34,6 +34,15 @@ month_info { }; struct +extents { + double x; + double y; + double width; + double height; +}; + + +struct RGB hex_to_rgb(char *str); int @@ -48,8 +57,11 @@ calculate_dimensions(double pw, double ph, struct dimensions *d); int print_dimensions(struct dimensions *d); +//int +//draw_month_grid(cairo_t *c, struct month_info *m, struct dimensions *d); + int -draw_month_grid(cairo_t *c, struct month_info *m, struct dimensions *d); +draw_month_grid (cairo_t *c, struct month_info *m, struct extents *me, struct extents *de); int draw_month(cairo_t *c, cairo_t *cd, cairo_surface_t *s, struct month_info *m, struct dimensions *d); @@ -64,7 +76,7 @@ PangoRectangle get_logical_extents(cairo_t *c, char *font_family, int font_size, char *text); int -calculate_minimum_rows(struct month_info *m, struct dimensions *d); +calculate_minimum_rows(struct month_info *m); int construct_day_box(cairo_t *cd, int month, int day, int week_day); diff --git a/src/ezini.c b/src/ezini.c deleted file mode 100644 index ee1f79e..0000000 --- a/src/ezini.c +++ /dev/null @@ -1,1033 +0,0 @@ -/** - * \brief INI File handling library - * \file ezini.c - * \author Michael Dipperstein (mdipperstein@gmail.com) - * \date November 22, 2015 - * - * This file implements a set of library functions that maybe be used - * to create, update, and/or parse INI files. - * - * \copyright Copyright (C) 2015, 2019 by Michael Dipperstein - * (mdipperstein@gmail.com) - * - * \par - * This file is part of the ezini library. - * - * \license - * The ezini library is free software; you can redistribute it - * and/or modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either version 3 - * of the License, or (at your option) any later version. - * - * \par - * The ezini library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * \par - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -/** - * \defgroup library Library Code - * \brief This module contains the code for the ezini INI file handling - * library - * @{ - */ - -/*************************************************************************** -* INCLUDED FILES -***************************************************************************/ -#include <stdio.h> -#include <ctype.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include "ezini.h" - -/*************************************************************************** -* TYPE DEFINITIONS -***************************************************************************/ - -/** - * \struct ini_key_list_t - * \brief A structure used for creating linked lists of key/value pairs - * for a each section. - */ - -/** - * \typedef struct ini_key_list_t - * \brief A shortcut for struct ini_key_list_t - */ - -typedef struct ini_key_list_t -{ - char *key; /*!< pointer to a a NULL terminated string - containing key name for this entry */ - char *value; /*!< pointer to a NULL terminated string - containing key value for this entry Use - ASCII strings to represent numbers */ - struct ini_key_list_t *next;/*!< pointer to the next key/value pair in - in this section */ - -} ini_key_list_t; - - -/** - * \struct ini_section_list_t - * \brief A structure used for creating linked lists of sections, each - * maintaining its own list of key/value pairs. - */ - -/** - * \typedef struct ini_section_list_t - * \brief A shortcut for struct ini_section_list_t - */ - -typedef struct ini_section_list_t -{ - char *section; /*!< pointer to a NULL terminated string - containing the section name */ - ini_key_list_t *members; /*!< pointer to the list of all key/value - pairs in this section */ - struct ini_section_list_t *next; /*!< pointer to the next section in - the list of entries */ - -} ini_section_list_t; - - -/*************************************************************************** -* PROTOTYPES -***************************************************************************/ - -/* allocate */ -static ini_key_list_t *NewKeyList(const char *key, const char *value); -static ini_section_list_t *NewSectionList(const char *section, const char *key, - const char *value); - -/* free */ -static void FreeKeyList(ini_key_list_t *list); -static void FreeEntry(ini_entry_t *entry); - -/* utilities */ -static char *SkipWS(const char *str); -static char *DupStr(const char *src); -static char *GetLine(FILE *fp); - -/*************************************************************************** -* FUNCTIONS -***************************************************************************/ - -/** - * \fn int AddEntryToList(ini_entry_list_t *list, const char *section, - * const char *key, const char *value) - * - * \brief This function adds a (section, key, value) entry to an entry list. - * - * \param list A pointer to an ini_entry_list_t that points to the - * head of entry list being modified. Pass a pointer to an ini_entry_list_t - * pointing to NULL if the list needs to be created. - * - * \param section A NULL terminated string containing the name of the - * section for the entry being added. - * - * \param key A NULL terminated string containing the name of the key for - * the entry being added. - * - * \param value A NULL terminated string containing the value of the key for - * the entry being added. All values must be represented as strings. They may - * be converted to/from strings by the calling program. - * - * \effects - * Information used to generate an entry structure containing copies of - * the (section, key, value) entry is added to the list passed as a parameter. - * Memory will be dynamically allocated as needed. - * - * \returns 0 for success, Non-zero on error. Error type is contained in - * errno. - * - * This function adds information used to create a (section, key, value) entry - * to an entry list. - * - * If an entry containing the same section name and key already exists, - * the new value will overwrite the old value. - * - * If the entry is for an existing section, it will be added to the end of the - * list for that section. - * - * If the entry is for a new section, a new section will be added to the list of - * sections, and the key/value pair will be the first entry of the section. - */ -int AddEntryToList(ini_entry_list_t *list, const char *section, - const char *key, const char *value) -{ - ini_section_list_t *next; - int result; - - /* handle empty list */ - if (NULL == *list) - { - /* add the first entry to the list */ - *list = NewSectionList(section, key, value); - - if (NULL == *list) - { - return -1; - } - - return 0; - } - - next = *list; - result = 1; - - while (1) - { - result = strcmp(section, next->section); - - if (0 == result) - { - break; /* match, insert here */ - } - - if (NULL == next->next) - { - break; /* no match, create new section here */ - } - - next = next->next; - } - - if (0 == result) - { - ini_key_list_t *member; - - member = next->members; - - while (1) - { - result = strcmp(key, member->key); - - if (0 == result) - { - break; /* match, insert here */ - } - - if (NULL == member->next) - { - break; /* no match, create new section here */ - } - - member = member->next; - } - - if (0 == result) - { - /* key exists, change value */ - free(member->value); - member->value = DupStr(value); - - if (NULL == member->value) - { - return -1; - } - } - else - { - /* new key, add to list */ - member->next = NewKeyList(key, value); - - if (NULL == member->next) - { - return -1; - } - } - } - else - { - /* add the section to the list with this key and value */ - next->next = NewSectionList(section, key, value); - } - - return 0; -} - - -/** - * \fn void FreeList(ini_entry_list_t list) - * - * \brief This function frees all of the members of an entry list. - * - * \param list A pointer to the head of an ini_entry_list_t - * - * \effects - * All of the memory allocated for all of the entries in an entry - * list will be freed. - * - * \returns Nothing - * - * This function uses recursion to step to the tail of the list and deletes - * section entries on the way back up. - */ -void FreeList(ini_entry_list_t list) -{ - /* recurse to the end of the list and free everything on the way back */ - if (list->next != NULL) - { - FreeList(list->next); - } - - if (list->section != NULL) - { - /* free the section name */ - free(list->section); - } - - if (list->members != NULL) - { - FreeKeyList(list->members); - } - - free(list); -} - - -/** - * \fn int MakeINIFile(const char *iniFile, const ini_entry_list_t list) - * - * \brief This function creates the specified INI file from the list of - * entries passed as an argument. - * - * \param iniFile The name of the INI file to be created. stdout will be - * used if iniFile is NULL. - * - * \param list A pointer to a list of that will be used to construct - * (section, key, value) entries. - * - * \effects - * The specified file is created and the (section, key, value) - * triples generated from the entry list are written to the file. If the - * specified file already exists, it will be overwritten. - * - * \returns 0 for success, Non-zero on error. Error type is contained in - * errno. - * - * This function creates the specified INI file from the list of entries - * passed as an argument. Any existing INI file with the same name in the - * same path will be overwritten. - */ -int MakeINIFile(const char *iniFile, const ini_entry_list_t list) -{ - ini_entry_list_t section; - ini_key_list_t *members; - FILE *fp; - - if (NULL == list) - { - errno = EINVAL; - return -1; - } - - if (NULL == iniFile) - { - fp = stdout; - } - else - { - - fp = fopen(iniFile, "w"); - - if (NULL == fp) - { - return -1; - } - } - - section = list; - - while (section != NULL) - { - fprintf(fp, "[%s]\n", section->section); - - members = section->members; - - while (members != NULL) - { - fprintf(fp, "%s = %s\n", members->key, members->value); - members = members->next; - } - - fprintf(fp, "\n"); - section = section->next; - } - - if (fp != stdout) - { - fclose(fp); - } - - return 0; -} - - -/** - * \fn int AddEntryToFile(const char *iniFile, const ini_entry_list_t list) - * - * \brief This function adds (section, key, value) entries in an entry list - * to an INI file. - * - * \param iniFile The name of the INI file to be modified. - * - * \param list A pointer to a list of entries to be added to the INI file. - * - * \effects - * The INI file will be re-written containing the results of adding - * the entries in the entry list to the entries already contained in the INI - * file. - * - * \returns 0 for success, Non-zero on error. Error type is contained in - * errno. - * - * This function adds (section, key, value) entries in an entry list to an - * INI file. Section order will be maintained with new sections added to the - * end of the INI file. If an entry containing the same section name and key - * already exists, the new value will overwrite the old value. - */ -int AddEntryToFile(const char *iniFile, const ini_entry_list_t list) -{ - ini_entry_t entry; - ini_entry_list_t merged; - ini_entry_list_t here; - int result; - FILE *fp; - - if (NULL == iniFile) - { - errno = EINVAL; - return -1; - } - - if (NULL == list) - { - errno = EINVAL; - return -1; - } - - fp = fopen(iniFile, "r"); - - if (NULL == fp) - { - return -1; - } - - merged = NULL; - entry.section = NULL; - entry.key = NULL; - entry.value = NULL; - - /* read ini file back into an entry list */ - while ((result = GetEntryFromFile(fp, &entry)) > 0) - { - AddEntryToList(&merged, entry.section, entry.key, entry.value); - } - - fclose(fp); - - if (result < 0) - { - FreeList(merged); - return -1; - } - - /* add entries passed into this function to entries from INI file */ - here = list; - - while (here != NULL) - { - ini_key_list_t *members; - - members = here->members; - - while (members != NULL) - { - AddEntryToList(&merged, here->section, members->key, - members->value); - members = members->next; - } - - here = here->next; - } - - /* re-write INI file from merged entry list */ - result = MakeINIFile(iniFile, merged); - FreeList(merged); - - return result; -} - -/** - * \fn int DeleteEntryFromFile(const char *iniFile, const char *section, - * const char *key) - * - * \brief This function deletes all entries from an INI file that match the - * section and key passed as an argument. - * - * \param iniFile The name of the INI file containing the entry to be - * deleted. - * - * \param section A pointer to a NULL terminated string containing the name - * of the section of the entry to be deleted. - * - * \param key A pointer to a NULL terminated string containing the name of - * the key of the entry to be deleted. - * - * \effects - * The INI file will be re-written without any entries that match - * the section and key to be deleted. Empty sections will not be deleted. - * - * \returns 0 for success, Non-zero on error. Error type is contained in - * errno. - * - * This function deletes all entries from an INI file that match the section - * and key passed as an argument. Empty sections will not be deleted. - * - * \note There will never be more than one matching entry in INI files - * created by this library. - */ -int DeleteEntryFromFile(const char *iniFile, const char *section, - const char *key) -{ - ini_entry_t entry; - ini_entry_list_t list; - int result; - FILE *fp; - - if (NULL == iniFile) - { - errno = EINVAL; - return -1; - } - - if (NULL == section) - { - errno = EINVAL; - return -1; - } - - if (NULL == key) - { - errno = EINVAL; - return -1; - } - - fp = fopen(iniFile, "r"); - - if (NULL == fp) - { - return -1; - } - - list = NULL; - entry.section = NULL; - entry.key = NULL; - entry.value = NULL; - - /* read ini file back into a structure */ - while ((result = GetEntryFromFile(fp, &entry)) > 0) - { - if (0 != strcmp(entry.section, section)) - { - /* this isn't one we're supposed to delete */ - AddEntryToList(&list, entry.section, entry.key, entry.value); - } - else if (0 != strcmp(entry.key, key)) - { - /* this isn't one we're supposed to delete */ - AddEntryToList(&list, entry.section, entry.key, entry.value); - } - } - - fclose(fp); - - if (result < 0) - { - FreeList(list); - return -1; - } - - result = MakeINIFile(iniFile, list); - FreeList(list); - - return result; -} - -/** - * \fn int GetEntryFromFile(FILE *iniFile, ini_entry_t *entry) - * - * \brief This function parses an INI file stream passed as an input, - * searching for the next (section, key, value) triple. - * - * \param iniFile A pointer to the INI file to be parsed. It must be - * opened for reading. - * - * \param entry A pointer to the entry structure used to store the discovered - * (section, key, value) triple. - * - * \effects - * The specified file is read until it discovers an entry. - * - * \returns 1 when an entry is found\n - * 0 when no more entries can be found\n - * -1 for an error. Error type is contained in errno. - * - * This function parses an INI file stream passed as an input, searching for - * the next (section, key, value) triple. The resulting triple will be used - * to populate the entry structure passed as a parameter. - */ -int GetEntryFromFile(FILE *iniFile, ini_entry_t *entry) -{ - char *line; - char *ptr; - - if (NULL == iniFile) - { - errno = EINVAL; - return -1; - } - - if (NULL == entry) - { - errno = EINVAL; - return -1; - } - - /* handle section names, comments, and blank lines */ - while ((line = GetLine(iniFile)) != NULL) - { - /* skip leading spaces and blank lines */ - ptr = SkipWS(line); - - /* skip blank lines and lines starting with ';' or '#' */ - if (*ptr == '\0' || *ptr == ';' || *ptr == '#') - { - free(line); - continue; - } - else if (*ptr == '[') - { - /* possible new section */ - char *end; - - end = strchr(ptr, ']'); - - if (NULL == end) - { - FreeEntry(entry); - errno = EILSEQ; - return -1; - } - - /* we have the full string for a new section, trim white space */ - ptr = SkipWS(ptr + 1); - - while (isspace(*(end - 1))) - { - end--; - } - - *end = '\0'; - - free(entry->section); - entry->section = DupStr(ptr); - free(line); - } - else - { - /* this line should be key = value */ - break; - } - } - - /* we either have a non-section line or nothing left to get */ - if (NULL == line) - { - /* nothing left to get */ - FreeEntry(entry); - return 0; - } - - /* the only other allowable lines are of the form key = value */ - free(entry->key); /* free old key */ - entry->key = ptr; - ptr++; - - while (*ptr != '=') - { - if (*ptr == '\0') - { - /* didn't find '=' */ - entry->key = NULL; - FreeEntry(entry); - free(line); - errno = EILSEQ; - return -1; - } - - ptr++; - } - - /* we found the '=' separating key and value trim white space */ - free(entry->value); /* free old value */ - entry->value = ptr + 1; - ptr--; - - while (isspace(*ptr)) - { - ptr--; - } - - *(ptr + 1) = '\0'; - entry->key = DupStr(entry->key); - - ptr = entry->value; - - /* now skip white space after '=' */ - while (*ptr == ' ' || *ptr =='\t') - { - if (*ptr == '\0') - { - FreeEntry(entry); - free(line); - errno = EILSEQ; - return -1; - } - - ptr++; - } - - /* we found the start of value, trim trailing white space */ - entry->value = ptr; - ptr = entry->value + strlen(entry->value) - 1; - - while (isspace(*ptr)) - { - ptr--; - } - - *(ptr + 1) = '\0'; - entry->value = DupStr(entry->value); - - free(line); - return 1; -} - - -/** - * \fn ini_key_list_t *NewKeyList(const char *key, const char *value) - * - * \brief This function allocates memory for a new ini_key_list_t type - * variable and populates it with the data passed as parameters - * - * \param key A pointer to a NULL terminated string containing the key name - * - * \param key A pointer to a NULL terminated string containing the value of - * this key. Use ASCII strings to represent numbers. - * - * \effects - * Memory will be allocated for a new ini_key_list_t and copies - * of the key and value strings passed as a parameter. key and value are - * copied into the appropriate fields and the next pointer is set to NULL. - * - * \returns A pointer to the ini_key_list_t item that was allocated. The - * pointer will be NULL if an error occurs. - * - * This function allocates memory for a new ini_key_list_t and copies - * of the key and value strings passed as a parameter. The next pointer - * will be set to NULL. - */ -static ini_key_list_t *NewKeyList(const char *key, const char *value) -{ - ini_key_list_t *item; - - item = (ini_key_list_t *)malloc(sizeof(ini_key_list_t)); - - if (NULL == item) - { - return NULL; - } - - /* allocation succeeded copy key and value */ - item->next = NULL; - - item->key = DupStr(key); - - if (NULL == item->key) - { - free(item); - return NULL; - } - - item->value = DupStr(value); - - if (NULL == item->value) - { - free(item->key); - free(item); - return NULL; - } - - return item; -} - - -/** - * \fn ini_section_list_t *NewSectionList(const char *section, const char *key, - * const char *value) - * - * \brief This function allocates memory for a new ini_section_list_t type - * variable and populates it with the data passed as parameters - * - * \param section A pointer to a NULL terminated string containing the section - * name - - * \param key A pointer to a NULL terminated string containing the key name - * - * \param key A pointer to a NULL terminated string containing the value of - * this key. Use ASCII strings to represent numbers. - * - * \effects - * Memory will be allocated for a new ini_section_list_t and copies - * of the section, key, value strings passed as a parameter. section is - * copied to the appropriate field and a new key list items is created fo - * the key and value strings. The next pointer will be set to NULL. - * - * \returns A pointer to the ini_section_list_t item that was allocated. The - * pointer will be NULL if an error occurs. - * - * This function allocates memory for a new ini_section_list_t and copies - * of the section, key, value strings passed as a parameter. A ini_key_list_t - * is allocated for the key and value strings. The next pointer is set to NULL. - */ -static ini_section_list_t *NewSectionList(const char *section, const char *key, - const char *value) -{ - ini_section_list_t *item; - - item = (ini_section_list_t *)malloc(sizeof(ini_section_list_t)); - - if (NULL == item) - { - return NULL; - } - - /* now populate item */ - item->next = NULL; - item->section = DupStr(section); - - if (NULL == item->section) - { - free(item); - return NULL; - } - - /* start a member list with the current key and value */ - item->members = NewKeyList(key, value); - - if (NULL == item->members) - { - free(item->section); - free(item); - return NULL; - } - - return item; -} - - -/** - * \fn void FreeKeyList(ini_key_list_t *list) - * - * \brief This function frees all of the members of a key list. - * - * \param list A pointer to the head of an ini_key_list_t - * - * \effects All of the memory allocated for all of the key/value pairs in - * a key list will be freed. - * - * \returns Nothing - * - * This function uses recursion to step to the tail of the list and deletes - * key/value entries on the way back up. - */ -static void FreeKeyList(ini_key_list_t *list) -{ - /* recurse to the end of the list and free everything on the way back */ - if (list->next != NULL) - { - FreeKeyList(list->next); - } - - free(list->key); - free(list->value); - free(list); -} - - -/** - * \fn static void FreeEntry(ini_entry_t *entry) - * - * \brief This function frees the allocated memory that is pointed to by the - * members of an ini_entry_t structure. - * - * \param entry A pointer to the entry structure containing the members - * pointing to the memory to be freed. - * - * \effects Dynamically allocated memory is freed and entry data is set - * to NULL. - * - * \returns Nothing - */ -static void FreeEntry(ini_entry_t *entry) -{ - free(entry->section); - free(entry->key); - free(entry->value); - - entry->section = NULL; - entry->key = NULL; - entry->value = NULL; -} - -/** - * \fn static char *SkipWS(const char *str) - * - * \brief This function returns a pointer to the first non-space in the - * string passed as a parameter. - * - * \param str A pointer to the string being searched. - * - * \effects None - * - * \returns A pointer to the first non-space in str. - */ -static char *SkipWS(const char *str) -{ - char *c; - - c = (char *)str; - while(isspace(*c)) - { - c++; - } - - return c; -} - -/** - * \fn static char *DupStr(const char *src) - * - * \brief This function returns a copy of the string passed as a parameter. - * - * \param str A pointer to the string being being copied. - * - * \effects Memory is dynamically allocated to hold a duplicate of the - * input string. - * - * \returns A copy of str in malloced memory is returned on success. NULL - * is returned on failure. - * - * This function returns a copy of the string passed as a parameter. The - * memory for the copy is allocated by malloc() and must be freed by the caller. - */ -static char *DupStr(const char *src) -{ - char *dest; - - if (NULL == src) - { - return NULL; - } - - dest = (char *)malloc(strlen(src) + 1); - - if (NULL != dest) - { - strcpy(dest, src); - } - - return dest; -} - -/** - * \fn static char *GetLine(FILE *fp) - * - * \brief This function returns a NULL terminated array of char containing the - * next line in the file passed as an argument. - * - * \param fp A pointer to the file being read. - * - * \effects One line is read from fp and copied into a dynamically allocated - * string. - * - * \returns A NULL terminated array of char containing the next line in fp - * is retured. The array must be free by the caller. NULL is returned at end - * of file. - * - * This function returns a NULL terminated array of char containing the next - * line in the file passed as an argument. The memory for the string returned - * is allocated by malloc() and must be freed by the caller. - */ -static char *GetLine(FILE *fp) -{ - char *line; /* string to read line into */ - char *next; /* where to write the next characters into */ - const size_t chunkSize = 32; - size_t lineSize; - - if ((NULL == fp) || feof(fp)) - { - return NULL; - } - - lineSize = chunkSize; - line = (char *)malloc(lineSize * sizeof(char)); - - if (NULL == line) - { - /* allocation failed */ - return NULL; - } - - line[0] = '\0'; - next = line; - - while (NULL != fgets(next, lineSize - strlen(line), fp)) - { - if ('\n' == line[strlen(line) - 1]) - { - /* we got to the EOL strip off the trailing '\n' and exit */ - line[strlen(line) - 1] = '\0'; - break; - } - else - { - /* there's still more on this line */ - lineSize += chunkSize; - line = (char *)realloc(line, lineSize); - - if (NULL == line) - { - return NULL; - } - - next = line + strlen(line); - } - } - - return line; -} - -/**@}*/ diff --git a/src/ezini.h b/src/ezini.h deleted file mode 100644 index e563c7c..0000000 --- a/src/ezini.h +++ /dev/null @@ -1,121 +0,0 @@ -/** - * \brief INI File handling library header - * \file ezini.h - * \author Michael Dipperstein (mdipperstein@gmail.com) - * \date November 22, 2015 - * - * This file implements a set of library functions that maybe be used - * to create, update, and/or parse INI files. - * - * \copyright Copyright (C) 2015, 2019 by Michael Dipperstein - * (mdipperstein@gmail.com) - * - * \par - * This file is part of the ezini library. - * - * \license The ezini library is free software; you can redistribute it - * and/or modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either version 3 - * of the License, or (at your option) any later version. - * - * \par - * The ezini library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * \par - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ -#ifndef __EZINI_H -#define __EZINI_H - -/** - * \mainpage EZIni - INI File handling library - * - * These pages provide documentation for EZIni, an INI File handling library. - * - * \copyright Copyright (C) 2015, 2019 by Michael Dipperstein - * (mdipperstein@gmail.com) - * - * \license - * The ezini library is free software; you can redistribute it - * and/or modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either version 3 - * of the License, or (at your option) any later version. - * - * \par - * The ezini library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser - * General Public License for more details. - * - * \par - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/*************************************************************************** -* TYPE DEFINITIONS -***************************************************************************/ - -/** - * \struct ini_entry_t - * \brief A structure containing the section, key, and value of INI. - * file entry - */ -typedef struct -{ - char *section; /*!< pointer to a NULL terminated string containing the - section name */ - char *key; /*!< pointer to a a NULL terminated string containing - the key name */ - char *value; /*!< pointer to a NULL terminated string with entry - value. Use ASCII strings to represent numbers */ -} ini_entry_t; - -/** - * \typedef ini_entry_list_t - * \brief A shortcut for forward referenced struct ini_section_list_t* - */ -typedef struct ini_section_list_t* ini_entry_list_t; - -/*************************************************************************** -* PROTOTYPES -***************************************************************************/ - -/* add (section, key, value) to a list of INI entries */ -int AddEntryToList(ini_entry_list_t *list, const char *section, - const char *key, const char *value); - -/* free all of the entries in an entry list */ -void FreeList(ini_entry_list_t list); - -/* create/add entries to an INI file from a sorted entry list */ -int MakeINIFile(const char *iniFile, const ini_entry_list_t list); -int AddEntryToFile(const char *iniFile, const ini_entry_list_t list); - -/* remove a single entry from an INI file */ -int DeleteEntryFromFile(const char *iniFile, const char *section, - const char *key); - -/*************************************************************************** -* get the next entry in INI file. -* returns: 1 if an entry is found -* 0 if there are no more entries -* -1 on error -***************************************************************************/ -int GetEntryFromFile(FILE *iniFile, ini_entry_t *entry); - -#ifdef __cplusplus -} -#endif - -#endif /* ndef __EZINI_H */ diff --git a/src/image.c b/src/image.c index 4295ab1..6180631 100644 --- a/src/image.c +++ b/src/image.c @@ -2,26 +2,9 @@ #include <stdlib.h> #include <cairo/cairo.h> #include <pango/pangocairo.h> -#include <wand/MagickWand.h> #include "draw.h" -// Used for MagickWand -#define ThrowWandException(wand) \ -{ \ - char \ - *description; \ - \ - ExceptionType \ - severity; \ - \ - description=MagickGetException(wand,&severity); \ - (void) fprintf(stderr,"%s %s %lu %s\n",GetMagickModule(),description); \ - description=(char *) MagickRelinquishMemory(description); \ - exit(-1); \ -} - - // Draw an image at a specific point int draw_image(cairo_t *c, char *path, double x, double y) { @@ -42,163 +25,27 @@ int draw_image(cairo_t *c, char *path, double x, double y) { } image = cairo_image_surface_create_from_png(path); - cairo_set_source_surface(c, image, x, y); - cairo_paint(c); - - cairo_surface_destroy (image); - return 0; -} - - - - - - -unsigned long get_image_width(char *path) { - MagickBooleanType status; - MagickWand *wand; - - MagickWandGenesis(); - wand = NewMagickWand(); - status = MagickReadImage(wand, path); - - if (status == MagickFalse) { - ThrowWandException(wand); - } - - unsigned long width = MagickGetImageWidth(wand); - - wand = DestroyMagickWand(wand); - MagickWandTerminus(); - return width; -} - - - -unsigned long get_image_height(char *path) { - MagickBooleanType status; - MagickWand *wand; - - MagickWandGenesis(); - wand = NewMagickWand(); - status = MagickReadImage(wand, path); - - if (status == MagickFalse) { - ThrowWandException(wand); - } - - unsigned long height = MagickGetImageHeight(wand); - - wand = DestroyMagickWand(wand); - MagickWandTerminus(); - return height; -} + double width = cairo_image_surface_get_width(image); + double height = cairo_image_surface_get_height(image); + double fake_width = 100; + double fake_height = 100; + double width_scale = fake_width / width; + double height_scale = fake_height / height; + cairo_scale(c, width_scale, height_scale); -// Resize an image to a specific width and height. -// Optionally create a new file to preserve the source image. -int resize_image(char *path, double width, double height, bool create_new) { - MagickBooleanType status; - MagickWand *wand; - MagickWandGenesis(); - wand = NewMagickWand(); - status = MagickReadImage(wand, path); - - if (status == MagickFalse) { - ThrowWandException(wand); - } - - MagickResetIterator(wand); - - MagickResizeImage(wand, width, height, LanczosFilter, 1.0); - - if (create_new == true) { - char new_path[30]; - snprintf(new_path, sizeof(new_path), "%s.tmp", path); - status = MagickWriteImages(wand, new_path, MagickTrue); - } else { - status = MagickWriteImages(wand, path, MagickTrue); - } - - if (status == MagickFalse) { - ThrowWandException(wand); - } - wand = DestroyMagickWand(wand); - MagickWandTerminus(); - return 0; -} - - -// Create a cropped version of an image to a certain dimensions and position. -// Optionally create a new file to preserve the source image. -int crop_image(char *path, double width, double height, double x, double y, bool create_new) { - MagickBooleanType status; - MagickWand *wand; - - MagickWandGenesis(); - wand = NewMagickWand(); - status = MagickReadImage(wand, path); - - if (status == MagickFalse) { - ThrowWandException(wand); - } - - MagickResetIterator(wand); - - MagickCropImage(wand, width, height, x, y); - - if (create_new == true) { - char new_path[30]; - snprintf(new_path, sizeof(new_path), "%s.tmp", path); - status = MagickWriteImages(wand, new_path, MagickTrue); - } else { - status = MagickWriteImages(wand, path, MagickTrue); - } + cairo_set_source_surface(c, image, x, y); + cairo_paint(c); - if (status == MagickFalse) { - ThrowWandException(wand); - } - wand = DestroyMagickWand(wand); - MagickWandTerminus(); + cairo_surface_destroy (image); return 0; } -int prepare_month_art(char *path, struct dimensions *d) { - if (!d->header_width || !d->header_height) { - printf("Error: header_width and header_height unknown.\n"); - return 1; - } - - double desired_ratio = d->header_width / d->header_height; - - unsigned long width = get_image_width(path); - unsigned long height = get_image_height(path); - //double original_ratio = width / height; - - - // Landscape - if (desired_ratio > 1.0) { - } - - // Portrait - if (desired_ratio < 1.0) { - } - - - - printf("%lu x %lu\n", width, height); - - - return 0; - -} - - // Draw month art diff --git a/src/image.h b/src/image.h index 117efaa..edfdec3 100644 --- a/src/image.h +++ b/src/image.h @@ -1,13 +1,3 @@ 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 resize_image(char *path, double width, double height, bool create_new); - -int crop_image(char *path, double width, double height, double x, double y, bool create_new); - -unsigned long get_image_width(char *path); - -unsigned long get_image_height(char *path); - -int prepare_month_art(char *path, struct dimensions *d); |
