#include #include #include #include #include #include #include //--- // 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); }