TeX/src/TeX.c

148 lines
3.2 KiB
C

#include <TeX/TeX.h>
#include <TeX/defs.h>
#include <TeX/structure.h>
#include <TeX/parser.h>
#include <TeX/render.h>
#include <stdlib.h>
#include <string.h>
//---
// Interface functions
//---
/* Rendering-related interface functions */
void (*TeX_pixel)(int x, int y, int color) = NULL;
void (*TeX_line)(int x1, int y1, int x2, int y2, int color) = NULL;
void (*TeX_size)(char const *str, int *width, int *height) = NULL;
void (*TeX_text)(char const *str, int x, int y, int color) = NULL;
/* TeX_intf_pixel() - Set a single pixel */
void TeX_intf_pixel(void (*draw_pixel)(int x, int y, int color))
{
TeX_pixel = draw_pixel;
}
/* TeX_intf_line() - Draw a line */
void TeX_intf_line(void (*draw_line)(int x1, int y1, int x2, int y2,
int color))
{
TeX_line = draw_line;
}
/* TeX_intf_size() - Get the dimensions of a string */
void TeX_intf_size(void (*text_size)(const char *str, int *width,int *height))
{
TeX_size = text_size;
}
/* TeX_intf_text() - Draw variable-width text */
void TeX_intf_text(void (*draw_text)(const char *str, int x, int y,int color))
{
TeX_text = draw_text;
}
//---
// Object management
//---
/* TeX_free_node() - Free TeX_Node objects
@node Node to free. Its parameters will also be freed */
static void TeX_free_node(struct TeX_Node *node)
{
/* Text nodes: free the allocated string */
if(node->type == TEX_NODECLASS_TEXT) free(node->text);
/* Class nodes: recursively free children */
else for(int i = 0; i < TEX_MAX_CHILDREN; i++)
{
if(node->args[i]) TeX_free(node->args[i]);
}
free(node);
}
/* TeX_free() - Free an allocated TeX formula */
void TeX_free(struct TeX_Flow *flow)
{
if(!flow) return;
struct TeX_Node *node, *next = NULL;
for(node = flow->first; node; node = next)
{
next = node->next;
TeX_free_node(node);
}
free(flow);
}
//---
// Node operations: size computation and rendering
//---
/* size_node() - Calculate the size of node */
void size_node(struct TeX_Node *node)
{
/* Text nodes */
if(node->type == TEX_NODECLASS_TEXT)
{
int w, h;
TeX_size((char const *)node->text, &w, &h);
node->width = w;
node->height = h;
node->line = h >> 1;
return;
}
/* For other classes, first compute the size of children */
for(int i = 0; i < TEX_MAX_CHILDREN && node->args[i]; i++)
size_flow(node->args[i]);
/* Then use the class' special size computation function */
if(TeX_table[node->type - 1].size)
TeX_table[node->type - 1].size(node);
}
/* render_node() - Recursively render a node */
void render_node(struct TeX_Node const * node, int x, int y, int color)
{
/* Don't render hidden or invalid elements */
if(node->hidden) return;
if(node->type == TEX_NODECLASS_TEXT)
{
TeX_text((void *)node->text, x, y, color);
return;
}
/* For non trivial classes, use the class' special function */
if(TeX_table[node->type - 1].render)
TeX_table[node->type - 1].render(node, x, y, color);
}
//---
// Module functions
//---
/* TeX_parse() - Parse a TeX formula */
struct TeX_Flow *TeX_parse(const char *formula)
{
struct TeX_Flow *flow;
parse_start(formula);
flow = parse();
if(!flow) return NULL;
size_flow(flow);
return flow;
}
/* TeX_draw() - Render a parsed formula */
void TeX_draw(struct TeX_Flow *formula, int x, int y, int color)
{
render_flow(formula, x, y, color);
}