148 lines
3.2 KiB
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) >> 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);
|
|
}
|