diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2eee5cc --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*~ +*.o +*.d +Tags +Tags.ezc diff --git a/Double.c b/Double.c new file mode 100644 index 0000000..40de740 --- /dev/null +++ b/Double.c @@ -0,0 +1,6 @@ +// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#include "Double.h" + +// Any *Double* support code goes here. + diff --git a/Double.h b/Double.h new file mode 100644 index 0000000..bfe5f68 --- /dev/null +++ b/Double.h @@ -0,0 +1,10 @@ +// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#if !defined(DOUBLE_H_INCLUDED) +#define DOUBLE_H_INCLUDED 1 + +/// @brief *Double* is a double precision (64-bits) floating point number. +typedef double Double; + +#endif // !defined(DOUBLE_H_INCLUDED) + diff --git a/File.c b/File.c new file mode 100644 index 0000000..b4571a6 --- /dev/null +++ b/File.c @@ -0,0 +1,46 @@ +// Copyright (c) 2013 by Wayne C. Gramlich all rights reserved. + +#include + +#include "File.h" +#include "String.h" + +// *File* routines: + +/// @brief Closes *file*. +/// @param file to close. +/// +/// *File__close*() will close *file*. + +void File__close(File file) { + assert (fclose(file) == 0); +} + +/// @brief will write *format* out to *file* with all patterns that +/// start with "%" replaced by formatted versions of its arguments. +/// @param file to output to. +/// @parma format is the formatting string. +/// +/// *File__format*() will write *format* out to *file* with all patterns that +/// start with "%" replaced by formatted versions of its arguments. + +void File__format(File file, String format, ...) { + // Set up *variadic_arguments to start after *format*: + va_list variadic_arguments; + va_start(variadic_arguments, format); + + // Perform the format: + Unsigned formatted_size = vfprintf(file, format, variadic_arguments); +} + +/// @brief will open *file_name* using *flags* to specify read/write options. +/// @param file_name is the file name to open. +/// @param flags specify the read/write options. +/// +/// *File__open*() will open *file_name* using *flags* to read/write options. +/// An open *File* object is returned or (*File)0 if the open failed. + +File File__open(String file_name, String flags) { + return fopen(file_name, flags); +} + diff --git a/File.h b/File.h new file mode 100644 index 0000000..8fecfaf --- /dev/null +++ b/File.h @@ -0,0 +1,19 @@ +// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#if !defined(FILE_H_INCLUDED) +#define FILE_H_INCLUDED 1 + +#include +#include + +#include "String.h" + +/// @brief *FILE* is a file I/O object. +typedef FILE *File; + +// External declarations: +extern void File__close(File file); +extern void File__format(File file, String format, ...); +extern File File__open(String file_name, String flags); + +#endif // !defined(FILE_H_INCLUDED) diff --git a/Integer.c b/Integer.c new file mode 100644 index 0000000..e69de29 diff --git a/Integer.h b/Integer.h new file mode 100644 index 0000000..88da12c --- /dev/null +++ b/Integer.h @@ -0,0 +1,10 @@ +// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#if !defined(INTEGER_H_INCLUDED) +#define INTEGER_H_INCLUDED 1 + +/// @brief *Integer* is a 32-bit signed integer. +typedef int Integer; + +#endif // !defined(INTEGER_H_INCLUDED) + diff --git a/Logical.c b/Logical.c new file mode 100644 index 0000000..9b2c7fd --- /dev/null +++ b/Logical.c @@ -0,0 +1,5 @@ +// Copyright (c) by Wayne C. Gramlich. All rights reserved. + +#include "Logical.h" + +// Any *Logical* support code goes here. diff --git a/Logical.h b/Logical.h new file mode 100644 index 0000000..3af6050 --- /dev/null +++ b/Logical.h @@ -0,0 +1,9 @@ +/// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#if !defined(LOGICAL_H_INCLUDED) +#define LOGICAL_H_INCLUDED 1 + +/// @brief *Logical* is a true/false value. +typedef int Logical; + +#endif // !defined(LOGICAL_H_INCLUDED) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5da51ed --- /dev/null +++ b/Makefile @@ -0,0 +1,79 @@ +# Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + + +C_WARNING_OPTIONS := \ + -Wreturn-type \ + -Wno-missing-braces \ + -Wextra \ + -Wno-missing-field-initializers \ + -Wformat=2 \ + -Wswitch-default \ + -Wcast-align \ + -Wpointer-arith \ + -Wbad-function-cast \ + -Wstrict-overflow=5 \ + -Wstrict-prototypes \ + -Winline \ + -Wundef \ + -Wcast-qual \ + -Wshadow \ + -Wunreachable-code \ + -Wlogical-op \ + -Wfloat-equal \ + -Wstrict-aliasing=2 \ + -Wold-style-definition \ + -Werror \ + +C_OPTIONS := \ + -std=c11 \ + -g \ + -MMD \ + ${C_WARNING_OPTIONS} \ + +CC := gcc ${C_OPTIONS} + +COMMON_O_FILES := \ + Double.o \ + File.o \ + Integer.o \ + Logical.o \ + Memory.o \ + String.o \ + SVG.o \ + Unsigned.o \ + +TAGS_O_FILES := \ + Tags.o \ + +ALL_O_FILES := \ + ${COMMON_O_FILES} \ + ${TAGS_O_FILES} \ + +ALL_C_BACKUPS := ${ALL_O_FILES:%.o=%.c~} +ALL_D_FILES := ${ALL_O_FILES:%.o=%.d} +ALL_H_BACKUPS := ${ALL_O_FILES:%.o=%.h~} + +PROGRAMS := \ + Tags \ + +all: ${PROGRAMS} + +Tags: ${COMMON_O_FILES} ${TAGS_O_FILES} + $(CC) -o $@ ${TAGS_O_FILES} ${COMMON_O_FILES} + +clean: + rm -f ${ALL_C_BACKUPS} + rm -f ${ALL_D_FILES} + rm -f ${ALL_H_BACKUPS} + rm -f ${ALL_O_FILES} + rm -f ${PROGRAMS} + rm Makefile~ Tags.ezc~ + +%.o: %c + $(CC) -c -o $@ $< + + +# Used with gcc -MMD option to force automagic dependency checking: +-include ${ALL_D_FILES} + + diff --git a/Memory.c b/Memory.c new file mode 100644 index 0000000..4b6ca03 --- /dev/null +++ b/Memory.c @@ -0,0 +1,28 @@ +// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#include +#include +#include "Unsigned.h" +#include "Memory.h" + +/// @brief Allocates *bytes* of memory and returns a pointer to it. +/// @param bytes is the number of bytes to allocate. +/// @returns a pointer to the allocated memory chunk. +/// +/// *Memory__allocate*() will allocated and return a pointer to a chunk +/// of *bytes* memory. + +Memory Memory__allocate(Unsigned bytes) { + Memory memory = (Memory)malloc(bytes); + assert (memory != (Memory)0); + return memory; +} + +/// @brief Releases the storage associated with *memory*. +/// @param memory to release. +/// +/// *Memory__free*() will release the storage associated with *memory*. + +void Memory__free(Memory memory) { + free(memory); +} diff --git a/Memory.h b/Memory.h new file mode 100644 index 0000000..78824ec --- /dev/null +++ b/Memory.h @@ -0,0 +1,35 @@ +// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#if !defined(MEMORY_H_INCLUDED) +#define MEMORY_H_INCLUDED 1 + +/// @brief Allocate a *Type* object from the heap. +/// +/// The type must be a pointer type where the underlying type defintion +/// is available to the compiler. +/// +/// This allocates an object of type *Type* by doing "Memory_new(Type)". +/// This macro when expanded works as follows: +/// +/// Type zilch = (Type)0; +/// UInteger type_size = sizeof(*zilch); +/// Type type = (Type)Memory_allocate(type_size); +/// +/// "sizeof(*((Type)0))" does not generate any code. The compiler +/// evaluates it to get the number of bytes associated with "Type": + +#define Memory__new(Type) ((Type)Memory__allocate(sizeof(*((Type)0)))) + +/// @brief *Memory* is a pointer to memory. +typedef void *Memory; + +#include "Unsigned.h" + +// Extern declarations: + +extern Memory Memory__allocate(Unsigned bytes); +extern void Memory__free(Memory memory); + + +#endif // !defined(MEMORY_H_INCLUDED) + diff --git a/SVG.c b/SVG.c new file mode 100644 index 0000000..5bf3dfe --- /dev/null +++ b/SVG.c @@ -0,0 +1,163 @@ +// Copyright (c) by Wayne C. Gramlich. All rights reserved. + +#include "SVG.h" + +/// @brief Close SVG object. +/// @param svg object to close +/// +/// *SVG__close*() will close *svg*. + +void SVG__close(SVG svg) { + // Close *svg*: + File svg_stream = svg->stream; + File__format(svg_stream, "\n"); + File__close(svg_stream); + svg->stream = (File)0; +} + +/// @brief Draw a line from (*x1*, *y1*) to (*x2*, *y2*) using *stroke*. +/// @param svg is the *SVG* object to draw line to. +/// @param x1 is X coordinate of first point. +/// @param y1 is Y coordinate of first point. +/// @param x2 is X coordinate of second point. +/// @param y2 is Y coordinate of second point. +/// @param stroke is stroke string. +/// +/// *SVG__line*() will draw a line to *svg* from (*x1*, *y1*) to (*x2*, *y2*) +/// using *stroke*. + +void SVG__line(SVG svg, + Double x1, Double y1, Double x2, Double y2, String stroke) { + // Extract some values from *svg*: + File svg_stream = svg->stream; + Double x_offset = svg->x_offset; + Double y_offset = svg->y_offset; + Double x_scale = svg->x_scale; + Double y_scale = svg->y_scale; + String units = svg->units; + + // Output "" to *svg_stream*: + File__format(svg_stream, + "\n", stroke); +} + +/// @brief Open an SVG object: +/// @param base_name is the base name of the file name without the .svg. +/// @param width is the width of the SVG. +/// @param height is the height of the SVG. +/// @param x_scale is the amount is scale in X. +/// @param y_scale is the amount to scale in Y. +/// @param units is the units to use. +/// @returns a new *SVG* object. +/// +/// *SVG__open*() will create and return a new *SVG* for writing out +/// scable vector graphics. + +SVG SVG__open(String base_name, + Double width, Double height, Double x_scale, Double y_scale, String units) { + // Get *svg_stream* opened: + SVG svg = (SVG)0; + String file_name = String__format("%s.svg", base_name); + File svg_stream = File__open(file_name, "r"); + if (svg_stream == (File)0) { + File__format(stderr, "Unable to open %s.svg\n", base_name); + } else { + // Allocate and load up *svg*: + svg = Memory__new(SVG); + svg->height = height; + svg->stream = svg_stream; + svg->width = width; + svg->units = units; + svg->x_scale = x_scale; + svg->y_scale = y_scale; + svg->x_offset = 0.0; + svg->y_offset = 0.0; + + // Ouput the header for *svg*: + File__format(svg_stream, + "\n\n"); + File__format(svg_stream, + "\n\n"); + File__format(svg_stream, + "\n\n"); + } + + // Clean up and return: + String__free(file_name); + return svg; +} + +/// @brief Draw a *width* by *height* rectangle at (*x*, *y*). +/// @param svg is the *SVG* object to draw rectangle to. +/// @param x is the upper left X coordinate. +/// @param y is the uppper left Y coordinate. +/// @param width is the rectangle width. +/// @param height is the rectangle height. +/// @param stroke_color is the exterior line color. +/// @param fill_color is the interior fill color. +/// +/// *SVG__rectangle* will draw a *width* by *height* rectangle at (*x*, *y*) +/// with *stroke_color* and *fill_color* specifying the external line color +/// and internal fill color respectivily. + +void SVG__rectangle(SVG svg, Double x, Double y, + Double width, Double height, String stroke_color, String fill_color) { + // Grab some values from svg: + File svg_stream = svg->stream; + Double x_offset = svg->x_offset; + Double y_offset = svg->y_offset; + Double x_scale = svg->x_scale; + Double y_scale = svg->y_scale; + String units = svg->units; + + // Output "" to *svg_stream*: + Double x_final = (x + x_offset) * x_scale; + Double y_final = (y + y_offset) * y_scale; + File__format(svg_stream, + "\n", stroke_color, fill_color); +} + +/// @brief draw *message* at (*x*, *y*). +/// @param x is the X coordinate to draw text at. +/// @param y is the Y coordinate of draw text at. +/// @param font_size is the font size. +/// @param font_family is the font family to use. +/// +/// *SVG__text*() will draw *message* at (*x*, *y*) with *font_size* font +/// of type *font_family*. + +void SVG__text(SVG svg, + String message, Double x, Double y, String font_family, Unsigned font_size) { + // Grab some values from *svg*: + File svg_stream = svg->stream; + Double x_offset = svg->x_offset; + Double y_offset = svg->y_offset; + Double x_scale = svg->x_scale; + Double y_scale = svg->y_scale; + String units = svg->units; + + File__format(svg_stream, + "", font_family, font_size); + File__format(svg_stream, "%s%\n", message); +} diff --git a/SVG.h b/SVG.h new file mode 100644 index 0000000..40806a4 --- /dev/null +++ b/SVG.h @@ -0,0 +1,60 @@ +// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#if !defined(SVG_H_INCLUDED) +#define SVG_H_INCLUDED 1 + +#include + +/// @brief *SVG* is a Scalable Vector Graphics object. +typedef struct SVG__Struct *SVG; + +#include "Double.h" +#include "File.h" +#include "Integer.h" +#include "Logical.h" +#include "Memory.h" +#include "Unsigned.h" + +/// @brief *SVG_Struct* is the data structure for representing Scalable +/// Vector Graphics. + +struct SVG__Struct { + /// @brief The output stream. + File stream; + + /// @brief Hight of SVG image. + Double height; + + /// @brief Width of SVG image. + Double width; + + /// @brief Units to use for SVG values. + String units; + + /// @brief Amount to offset X by. + Double x_offset; + + /// @brief Amount to scale X by. + Double x_scale; + + /// @brief Amount to offset Y by. + Double y_offset; + + /// @brief Amount to scale Y by. + Double y_scale; +}; + +// External declarations: + +extern void SVG__close(SVG svg); +extern void SVG__line(SVG svg, + Double x1, Double y1, Double x2, Double y2, String stroke); +extern SVG SVG__open(String base_name, + Double width, Double height, Double x_scale, Double y_scale, String units); +extern void SVG__rectangle(SVG svg, Double x, Double y, + Double width, Double height, String stroke_color, String fill_color); +extern void SVG__text(SVG svg, + String message, Double x, Double y, String font_family, Unsigned font_size); + + +#endif // !defined(SVG_H_INCLUDED) diff --git a/String.c b/String.c new file mode 100644 index 0000000..ff459e9 --- /dev/null +++ b/String.c @@ -0,0 +1,53 @@ +// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#include +#include +#include + +#include "String.h" +#include "Memory.h" +#include "Unsigned.h" + +/// @brief Allocate and return for *size* characters. +/// @param size is the maximum string size excluding trailing null. +/// @returns allocated *String* object. +/// +/// *String__allocate*() will return a string that can conatain +/// *size* characters excluding trailing null. + +String String__allocate(Unsigned size) { + return (String)Memory__allocate(size + 1); +} + +/// @brief Return a formatted version of *format*. +/// @param format is the string to format. +/// @param ... are the addition arguments to be formatted. +/// @returns the formatted string. +/// +/// *String__format*() will a formatted version of *format* using the +/// additional variadic arguements. + +String String__format(String format, ...) { + // Set up *variadic_arguments to start after *format*: + va_list variadic_arguments; + va_start(variadic_arguments, format); + + // Compute *formatted_size*: + char buffer[2]; + Unsigned formatted_size = vsnprintf(buffer, 0, format, variadic_arguments); + // Allocated *formatted*: + String formatted = (String)Memory__allocate(formatted_size + 1); + + // Format *formatted*: + (void)vsnprintf(formatted, formatted_size, format, variadic_arguments); + + return formatted; +} + +/// @brief will free memory assciated with *string*. +/// @param string to free. + +void String__free(String string) { + Memory__free((Memory)string); +} + diff --git a/String.h b/String.h new file mode 100644 index 0000000..ddecbe9 --- /dev/null +++ b/String.h @@ -0,0 +1,18 @@ +/// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#if !defined(STRING_H_INCLUDED) +#define STRING_H_INCLUDED 1 + +/// @brief *String* is a null-terminated string. +typedef char *String; + +#include "Unsigned.h" + +// External declarations: + +extern String String__allocate(Unsigned size); +extern String String__format(String format, ...); +extern void String__free(String string); + +#endif // !defined(STRING_H_INCLUDED) + diff --git a/Tags.c b/Tags.c new file mode 100644 index 0000000..0401436 --- /dev/null +++ b/Tags.c @@ -0,0 +1,79 @@ +// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +#include +#include +#include + +#include "SVG.h" + +Integer main(void) { + File__format(stdout, "Hello!\n"); + return 0; +} + +/// @brief Draw a rectangular section of bits: +/// @param cell_width is the cell width and height. +/// @param first_column is the first column of rectantle. +/// @param first_row is the first column of rectantle. +/// @param last_column is the last row to draw the bit at. +/// @param last_row is the last column to draw the bit at. +/// @param border is true if the tag has a border. +/// +/// *SVG__tag_bits*() will draw a row or column of black bits from +/// (*first_column*, *first_row*) to (*last_column*, *last_row*) +/// the 12 x 12 matrix that makes up a tag to *svg*. If *border* +/// *false*, the matrix is offset by the left by one. + +void SVG__tag_bits(SVG svg, Double cell_width, Unsigned first_column, + Unsigned first_row, Unsigned last_column, Unsigned last_row, Logical border) { + + // Deal with *border*: + Unsigned delta = 0; + if (!border) { + delta = 1; + } + + // Deal with SVG using left-hand (rather than right-hand) Cartesian + // coordinate system: + first_row = 11 - first_row; + last_row = 11 - last_row; + + // Make sure *first_column* < *last_column*: + if (first_column > last_column) { + Unsigned temporary_column = first_column; + first_column = last_column; + last_column = temporary_column; + } + + // Make sure *first_row* < *last_row*: + if (first_row > last_row) { + Unsigned temporary_row = first_row; + first_row = last_row; + last_row = temporary_row; + } + + // Output the appropriate rectangle to *svg*: + String color = "black"; + SVG__rectangle(svg, + (Double)(first_column - delta) * cell_width, + (Double)(first_row - delta) * cell_width, + (Double)(last_column - first_column + 1) * cell_width, + (Double)(last_row - first_row + 1) * cell_width, + color, color); +} + +/// @brief Draw a bit at *row* and *column*. +/// @param cell_width is the cell width and height. +/// @param row is the row to draw the bit at. +/// @param column is the column to draw the bit at. +/// @param border is true if the tag has a border. +/// +/// *SVG__tag_bit* draw a black bit at *row* and *column* in the 12 x 12 +/// matrix that makes up a tag and output it to *svg*. If *border* is *false* +/// the matrix is offset to the left by one. + +void SVG__tag_bit(SVG svg, + Double cell_width, Unsigned row, Unsigned column, Logical border) { + SVG__tag_bits(svg, cell_width, row, column, row, column, border); +} + diff --git a/Unsigned.c b/Unsigned.c new file mode 100644 index 0000000..95c4812 --- /dev/null +++ b/Unsigned.c @@ -0,0 +1,5 @@ +// Copyright (c) by Wayne C. Gramlich. All rights reserved. + +#include "Unsigned.h" + +// Any *Unsigned* support code goes here. diff --git a/Unsigned.h b/Unsigned.h new file mode 100644 index 0000000..f3fd58e --- /dev/null +++ b/Unsigned.h @@ -0,0 +1,5 @@ +// Copyright (c) 2013 by Wayne C. Gramlich. All rights reserved. + +/// @brief *Unsigned* is a 32-bit unsigned integer. +typedef unsigned int Unsigned; +