diff -urN aa/conglomerate-0.7.14/src/fo-parser-result.c conglomerate-0.7.14/src/fo-parser-result.c --- aa/conglomerate-0.7.14/src/fo-parser-result.c 1970-01-01 01:00:00.000000000 +0100 +++ conglomerate-0.7.14/src/fo-parser-result.c 2004-07-05 01:04:20.552876008 +0200 @@ -0,0 +1,588 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* + * fo-parser-result.c + * + * Copyright (C) 2002 David Malcolm + * + * FIXME: This file is currently licensed under the GPL, but I intend it to eventually become part of a library licensed under the LGPL + * + * Authors: David Malcolm + */ + +#include "global.h" +#include "fo.h" + +#if 0 +/* FoParserResult internals: */ +static FoUnit get_distance_property(xmlNodePtr node, const xmlChar *property) +{ + xmlChar *value = xmlGetProp(node, property); + float number = 0.0f; + int len; + xmlChar *units; + + if (NULL==value) { + g_message("missing property \"%s\"", property); + return 0; + } + + /* + How to parse? + + Units might be "in", "pt", "mm", "pc", "px"... other units? + + My initial implementation just used sscanf and didn't work. + */ + + /* FIXME: bad char type */ + len = strlen(value); + + if (len>2) { + units = value+len-2; + + if (0==xmlStrcmp(units,"mm")) { + if (1==sscanf(value,"%fmm", &number)) { + /* Millimeters */ + /* No conversion required */ + g_message("fubar"); + } + } else if (0==xmlStrcmp(units,"in")) { + if (1==sscanf(value, "%fin", &number)) { + /* Inches */ + number *=25.4f; /* convert from inches to millimetres */ + /* FIXME: is this accurate enough? */ + } + } else if (0==xmlStrcmp(units,"pt")) { + if (1==sscanf(value, "%fpt", &number)) { + /* Points */ + number *=1.0f; /* convert from points to millimetres */ + /* FIXME */ + } + } else if (0==xmlStrcmp(units,"pc")) { + if (1==sscanf(value, "%fpc", &number)) { + /* Picas; a pica is equal to 12 points */ + number *=1.0f; /* convert from picas to millimetres */ + /* FIXME */ + } + } else if (0==xmlStrcmp(units,"px")) { + if (1==sscanf(value, "%fpx", &number)) { + /* Pixels */ + number *=1.0f; /* convert from pixels to millimetres */ + /* FIXME */ + } + } else { + g_message("Failed to parse distance \"%s\"\n", value); + } + } + + + g_message("%s =\"%s\" (interpreted as %fmm)\n", property, value, number); + + xmlFree(value); + return number; +} + +static void process_region(FoParserResult *result, FoSimplePageMaster *spm, xmlNodePtr node, enum FoRegionID region_id) +{ + FoRegion *region; + + region = spm->regions[region_id] = g_new0(FoRegion,1); + FO_PARSER_OBJECT(region)->node = node; + + region->name = xmlGetProp(node, "region-name"); + +} + +static FoSimplePageMaster *simple_page_master_get_master_for_next_page(FoPageSequenceGenerator *psg, + int page_number, + gboolean is_first_of_sequence, + gboolean is_last_of_sequence, + gboolean is_blank) +{ + /* SImple page masters return themselves when asked to generate a page */ + return FO_SIMPLE_PAGE_MASTER(psg); +} + +struct FoPageSequenceGeneratorClass simple_page_master_class = { + + { + {"simple_page_master_class"}, /* FoParserClass base; */ + }, + simple_page_master_get_master_for_next_page +}; + +static void process_simple_page_master(FoParserResult *result, xmlNodePtr node) +{ + xmlNodePtr iter; + FoSimplePageMaster *simple_page_master; + + g_message("process_simple_page_master\n"); + + simple_page_master = g_new0(FoSimplePageMaster,1); + FO_OBJECT(simple_page_master)->klass = FO_CLASS(&simple_page_master_class); + FO_PARSER_OBJECT(simple_page_master)->node = node; + + result->list_of_simple_page_master = g_list_append(result->list_of_simple_page_master, simple_page_master); + + simple_page_master->base.name = xmlGetProp(node, "master-name"); + simple_page_master->page_height = get_distance_property(node, "page-height"); + simple_page_master->page_width = get_distance_property(node, "page-width"); + simple_page_master->margin_top = get_distance_property(node, "margin-top"); + simple_page_master->margin_bottom = get_distance_property(node, "margin-bottom"); + simple_page_master->margin_left = get_distance_property(node, "margin-left"); + simple_page_master->margin_right = get_distance_property(node, "margin-right"); + +#if 0 + { + xmlAttrPtr attr; + + for (attr = node->properties; attr; attr = attr->next) { + g_message("%s = \"%s\"\n", attr->name, attr->children->content); + } + } +#endif + + for (iter = node->children; iter; iter = iter->next) { + g_message("got <%s>\n", iter->name); + + if (0==xmlStrcmp(iter->name,"region-body") ) { + process_region(result, simple_page_master, iter, FO_REGION_BODY); + } + if (0==xmlStrcmp(iter->name,"region-before") ) { + process_region(result, simple_page_master, iter, FO_REGION_BEFORE); + } + if (0==xmlStrcmp(iter->name,"region-after") ) { + process_region(result, simple_page_master, iter, FO_REGION_AFTER); + } + if (0==xmlStrcmp(iter->name,"region-start") ) { + process_region(result, simple_page_master, iter, FO_REGION_START); + } + if (0==xmlStrcmp(iter->name,"region-end") ) { + process_region(result, simple_page_master, iter, FO_REGION_END); + } + } + +} + +FoSubsequenceSpecifier *process_single_page_master_reference(FoParserResult *result, xmlNodePtr node) +{ + xmlChar* master_name; + FoSS_SinglePageMasterReference *foss = g_new0(FoSS_SinglePageMasterReference, 1); + FO_PARSER_OBJECT(foss)->node = node; + + master_name = xmlGetProp(node, "master-name"); + + foss->spm = fo_parser_result_lookup_simple_page_master(result, master_name); + + xmlFree(master_name); + + return FO_SUBSEQUENCE_SPECIFIER(foss); +} + +FoSubsequenceSpecifier *process_repeatable_page_master_reference(FoParserResult *result, xmlNodePtr node) +{ + xmlChar* master_name; + FoSS_RepeatablePageMasterReference *foss = g_new0(FoSS_RepeatablePageMasterReference, 1); + FO_PARSER_OBJECT(foss)->node = node; + + master_name = xmlGetProp(node, "master-name"); + + foss->spm = fo_parser_result_lookup_simple_page_master(result, master_name); + + xmlFree(master_name); + + return FO_SUBSEQUENCE_SPECIFIER(foss); +} + +FoConditionalPageMasterReference *process_conditional_page_master_reference(FoParserResult *result, xmlNodePtr node) +{ + xmlChar* master_reference; + FoConditionalPageMasterReference *alternative = g_new0(FoConditionalPageMasterReference,1); + FO_PARSER_OBJECT(alternative)->node = node; + + master_reference = xmlGetProp(node, "master-reference"); + + alternative->spm = fo_parser_result_lookup_simple_page_master(result, master_reference); + + xmlFree(master_reference); + + return alternative; +} + +FoSubsequenceSpecifier *process_repeatable_page_master_alternatives(FoParserResult *result, xmlNodePtr node) +{ + xmlNodePtr iter; + FoSS_RepeatablePageMasterAlternatives *foss = g_new0(FoSS_RepeatablePageMasterAlternatives, 1); + + /* Iterate through child tree, building up a list of alternatives: */ + for (iter = node->children; iter; iter = iter->next) { + if (0==xmlStrcmp(iter->name, "conditional-page-master-reference")) { + FoConditionalPageMasterReference *alternative = process_conditional_page_master_reference(result, iter); + + g_message("got alternative: <%s>\n", iter->name); + + foss->list_of_alternatives = g_list_append(foss->list_of_alternatives, alternative); + } + } + + return FO_SUBSEQUENCE_SPECIFIER(foss); +} + +static FoSimplePageMaster *page_sequence_master_get_master_for_next_page(FoPageSequenceGenerator *psg, + int page_number, + int index_within_page_sequence, + gboolean is_first_of_sequence, + gboolean is_last_of_sequence, + gboolean is_blank) +{ + FoPageSequenceMaster *psm = FO_PAGE_SEQUENCE_MASTER(psg); + + /* Use the indexed subsequence specifier: */ + FoSubsequenceSpecifier *foss = g_list_nth_data(psm->list_of_subsequence_specifier, index_within_page_sequence); + + if (foss) { +/* #error see pages 48-49 */ + } + g_assert(0); + /* unwritten */ + + return NULL; +} + +struct FoPageSequenceGeneratorClass page_sequence_master_class = { + + { + {"page_sequence_master_class"}, /* FoParserClass base; */ + }, + page_sequence_master_get_master_for_next_page +}; + +static FoPageSequenceMaster *process_page_sequence_master(FoParserResult *result, xmlNodePtr node) +{ + FoPageSequenceMaster *psm; + xmlNodePtr iter; + + psm = g_new0(FoPageSequenceMaster,1); + FO_OBJECT(psm)->klass = FO_CLASS(&page_sequence_master_class); + FO_PARSER_OBJECT(psm)->node = node; + + psm->base.name = xmlGetProp(node, "master-name"); + + g_message("process_page_sequence_master, name=\"%s\"\n", psm->base.name); + + /* Iterate through child tree, building up a list of subsequence specifiers: */ + for (iter = node->children; iter; iter = iter->next) { + FoSubsequenceSpecifier *foss = NULL; + + g_message("got subsequence specifier: <%s>\n", iter->name); + + if (0==xmlStrcmp(iter->name, "single-page-master-reference")) { + foss = process_single_page_master_reference(result, iter); + } else if (0==xmlStrcmp(iter->name, "repeatable-page-master-reference")) { + foss = process_repeatable_page_master_reference(result, iter); + } else if (0==xmlStrcmp(iter->name, "repeatable-page-master-alternatives")) { + foss = process_repeatable_page_master_alternatives(result, iter); + } + + if (foss) { + psm->list_of_subsequence_specifier = g_list_append(psm->list_of_subsequence_specifier, foss); + } + } + + return psm; +} + +static void process_layout_master_set(FoParserResult *result, xmlNodePtr node) +{ + xmlNodePtr iter; + + g_message("process_layout_master_set\n"); + + result->node_layout_master_set = iter; + + for (iter = node->children; iter; iter = iter->next) { + + g_message("got <%s>\n", iter->name); + if (0==xmlStrcmp(iter->name,"simple-page-master") ) { + process_simple_page_master(result, iter); + } + if (0==xmlStrcmp(iter->name,"page-sequence-master") ) { + FoPageSequenceMaster *psm = process_page_sequence_master(result, iter); + + result->list_of_page_sequence_master = g_list_append(result->list_of_page_sequence_master, psm); + } + } + +} + +static void process_fo_recursive(FoParserResult *result, xmlNodePtr node) +{ + xmlNodePtr iter; + +#if 0 + g_message("process_fo_recursive <%s>\n", node->name); + + if (node->type==XML_TEXT_NODE) { + g_message("(text =\"%s\")\n", node->content); + } + + if ( 0==xmlStrcmp(node->name,"block") ) { + xmlAttrPtr attr; + + for (attr = node->properties; attr; attr = attr->next) { + g_message("%s = \"%s\"\n", attr->name, attr->children->content); + } + } +#endif + + for (iter = node->children; iter; iter = iter->next) { + process_fo_recursive(result, iter); + } +} + +static FoFlow *process_flow(FoParserResult *result, xmlNodePtr node) +{ + FoFlow *flow; + xmlNodePtr iter; + + g_message("process flow\n"); + + flow = g_new0(FoFlow,1); + FO_PARSER_OBJECT(flow)->node = node; + + for (iter = node->children; iter; iter = iter->next) { + process_fo_recursive(result, iter); + } + + return flow; +} + +static FoPageSequence *process_page_sequence(FoParserResult *result, xmlNodePtr node) +{ + FoPageSequence *page_sequence; + xmlNodePtr iter; + + g_message("page_sequence\n"); + + page_sequence = g_new0(FoPageSequence,1); + FO_PARSER_OBJECT(page_sequence)->node = node; + + /* Generate pages either directly from a simple-page-master, or indirectly using page-sequence-master: */ + { + xmlChar *master_name = xmlGetProp(node, "master-name"); + + if (master_name) { + g_message("Got master-name \"%s\"\n", master_name); + + page_sequence->psg = FO_PAGE_SEQUENCE_GENERATOR( fo_parser_result_lookup_simple_page_master(result, master_name) ); + + g_free(master_name); + + } else { + + xmlChar *master_reference = xmlGetProp(node, "master-reference"); + + if (master_reference) { + g_message("Got master-reference \"%s\"\n", master_reference); + + page_sequence->psg = FO_PAGE_SEQUENCE_GENERATOR( fo_parser_result_lookup_page_sequence_master(result, master_reference) ); + + g_free(master_reference); + + } else { + g_message("Cannot determine how to generate page sequences\n"); + } + + } + } + + g_assert(page_sequence->psg); /* for now */ + + for (iter = node->children; iter; iter = iter->next) { + if (0==xmlStrcmp(iter->name,"title") ) { + g_message("title\n"); + } + if (0==xmlStrcmp(iter->name,"static-content") ) { + g_message("static_content\n"); + } + if (0==xmlStrcmp(iter->name,"flow") ) { + FoFlow *flow = process_flow(result, iter); + page_sequence->flow = flow; + } + } + + return page_sequence; + +} + +static void locate_elements(FoParserResult *result) +{ + xmlNodePtr iter; + + g_message("locate_elements\n"); + + result->node_root = result->xml_doc->children; + + for (iter = result->node_root->children; iter; iter = iter->next) { + + g_message("got <%s>\n", iter->name); + if (0==xmlStrcmp(iter->name,"layout-master-set") ) { + process_layout_master_set(result, iter); + } + if (0==xmlStrcmp(iter->name,"declarations") ) { + result->node_declarations = iter; + } + if (0==xmlStrcmp(iter->name,"page-sequence") ) { + FoPageSequence *page_sequence = process_page_sequence(result, iter); + g_assert(page_sequence); + g_assert(page_sequence->psg); /* for now */ + + result->list_of_page_sequence = g_list_append(result->list_of_page_sequence, page_sequence); + } + } + +} + +#if 0 +FoSimplePageMaster *fo_page_sequence_generator_get_master_for_next_page(FoPageSequenceGenerator *psg, + int page_number, + gboolean is_first_of_sequence, + gboolean is_last_of_sequence, + gboolean is_blank) +{ + struct FoPageSequenceGeneratorClass *klass; + + g_return_val_if_fail(psg, NULL); + + klass = (struct FoPageSequenceGeneratorClass*)(FO_PARSER_OBJECT(psg)->klass); + g_assert(klass); + g_assert(klass->get_master_for_next_page); + + return klass->get_master_for_next_page(psg, + page_number, + is_first_of_sequence, + is_last_of_sequence, + is_blank); +} +#endif + +/* FoParserResult methods: */ +FoParserResult *fo_parser_result_new_from_xmldoc(xmlDocPtr xml_doc) +{ + FoParserResult *result; + + g_return_val_if_fail(xml_doc, NULL); + + result = g_new0(FoParserResult,1); + + result->xml_doc = xml_doc; + + locate_elements(result); + + return result; +} + +void fo_parser_result_delete(FoParserResult *result) +{ + /* FIXME: cleanup */ + + g_free(result); +} + +/* + Handy test method to render the result of parsing. + + Currently it outputs schematic versions of the various page descriptions. +*/ +void fo_parser_result_test_render(FoParserResult *result, FoPrintContext *fpc) +{ + FoRect rect; + GList *iter; +#if 1 + /* Render pages for each simple-page-master */ + for (iter = result->list_of_simple_page_master; iter; iter = iter->next) { + FoSimplePageMaster *spm = iter->data; + + fo_print_context_beginpage(fpc, spm->base.name); + + /* Page width/height: */ + fo_rect_set_xywh(&rect, 0.0, 0.0, spm->page_width, spm->page_height); + fo_rect_test_render(&rect, fpc, spm->base.name); + + /* Margin/the "content rectangle": */ + fo_rect_set_xyxy(&rect, spm->margin_bottom, spm->margin_left, spm->page_width-spm->margin_right, spm->page_height-spm->margin_top); + fo_rect_test_render(&rect, fpc, "margin/content rectangle"); + + + /* Display regions: */ + { + int i; + for (i=0;iregions[i]; + + if (region) { + fo_rect_set_xywh(&rect, 100.0, 250.0 + (i*50.0), 50.0, 50.0); + fo_rect_test_render(&rect, fpc, region->name); + } + } + } + + fo_print_context_showpage (fpc); + } +#else + gnome_print_beginpage (gpc, "1"); + + fo_rect_set(&rect, 100.0, 100.0, 500.0, 400.0); + fo_rect_test_render(&rect, gpc, "Test area 1"); + + fo_rect_set(&rect, 500.0, 100.0, 200.0, 200.0); + fo_rect_test_render(&rect, gpc, "Test area 2"); + + fo_rect_set(&rect, 100.0, 500.0, 100.0, 300.0); + fo_rect_test_render(&rect, gpc, "Test area 3"); + + gnome_print_showpage (gpc); +#endif +} + +FoSimplePageMaster *fo_parser_result_lookup_simple_page_master(FoParserResult *result, xmlChar *name) +{ + GList *iter; + + g_return_val_if_fail(result, NULL); + g_return_val_if_fail(name, NULL); + + for (iter = result->list_of_simple_page_master; iter; iter=iter->next) { + FoSimplePageMaster *spm = iter->data; + + if (0==xmlStrcmp(spm->base.name, name)) { + return spm; + } + } + + g_message("Failed to find called \"%s\"\n", name); + + return NULL; +} + +FoPageSequenceMaster *fo_parser_result_lookup_page_sequence_master(FoParserResult *result, xmlChar *name) +{ + GList *iter; + + g_return_val_if_fail(result, NULL); + g_return_val_if_fail(name, NULL); + + for (iter = result->list_of_page_sequence_master; iter; iter=iter->next) { + FoPageSequenceMaster *psm = iter->data; + + if (0==xmlStrcmp(psm->base.name, name)) { + return psm; + } + } + + g_message("Failed to find called \"%s\"\n", name); + + return NULL; +} +#endif diff -urN aa/conglomerate-0.7.14/src/fo-print-context.c conglomerate-0.7.14/src/fo-print-context.c --- aa/conglomerate-0.7.14/src/fo-print-context.c 1970-01-01 01:00:00.000000000 +0100 +++ conglomerate-0.7.14/src/fo-print-context.c 2004-07-05 01:04:04.568306032 +0200 @@ -0,0 +1,174 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* + * fo-print-context.c + * + * Copyright (C) 2002 David Malcolm + * + * FIXME: This file is currently licensed under the GPL, but I intend it to eventually become part of a library licensed under the LGPL + * + * Authors: David Malcolm + */ + +#include "global.h" +#include "fo.h" + +struct FoPrintContext +{ + GnomePrintContext *gpc; +}; + +/* FoPrintContext internals: */ + +/* FoPrintContext methods: */ +/** + * fo_print_context_new_from_gnome_print: + * @gpc: + * + * TODO: Write me + * Returns: + */ +FoPrintContext * +fo_print_context_new_from_gnome_print(GnomePrintContext *gpc) +{ + FoPrintContext *fpc; + + g_return_val_if_fail(gpc, NULL); + + fpc = g_new0(FoPrintContext, 1); + + fpc->gpc = gpc; + + return fpc; +} + +/** + * fo_print_context_delete: + * @fpc: + * + * TODO: Write me + */ +void +fo_print_context_delete(FoPrintContext *fpc) +{ + g_return_if_fail(fpc); + + g_free(fpc); + + /* (No other cleanup required) */ +} + +/** + * fo_print_context_beginpage: + * @fpc: + * @name: + * + * TODO: Write me + */ +void +fo_print_context_beginpage(FoPrintContext *fpc, const gchar* name) +{ + g_return_if_fail(fpc); + g_return_if_fail(name); + + g_assert(fpc->gpc); + + gnome_print_beginpage (fpc->gpc, name); +} + +/** + * fo_print_context_showpage: + * @fpc: + * + * TODO: Write me + */ +void +fo_print_context_showpage (FoPrintContext *fpc) +{ + g_return_if_fail(fpc); + + g_assert(fpc->gpc); + + gnome_print_showpage (fpc->gpc); +} + +/** + * fo_print_context_test_rect: + * @fpc: + * @rect: + * @label: + * + * TODO: Write me + */ +void +fo_print_context_test_rect(FoPrintContext *fpc, const FoRect *rect, const gchar *label) +{ + GnomeFont *font; + + g_return_if_fail(fpc); + + g_assert(fpc->gpc); + + if (label) { + font = gnome_font_find_closest ("Helvetica", 12); + + gnome_print_setfont (fpc->gpc, font); + gnome_print_moveto (fpc->gpc, rect->x, rect->y); + gnome_print_show (fpc->gpc, label); + } + + gnome_print_rect_stroked(fpc->gpc, rect->x, rect->y, rect->w, rect->h); + +} + +/** + * fo_print_context_push_state: + * @fpc: + * + * TODO: Write me + */ +void +fo_print_context_push_state(FoPrintContext *fpc) +{ + g_return_if_fail(fpc); + + g_assert(fpc->gpc); + + gnome_print_gsave(fpc->gpc); +} + +/** + * fo_print_context_pop_state: + * @fpc: + * + * TODO: Write me + */ +void +fo_print_context_pop_state(FoPrintContext *fpc) +{ + g_return_if_fail(fpc); + + g_assert(fpc->gpc); + + gnome_print_grestore(fpc->gpc); +} + +/** + * fo_print_context_translate: + * @fpc: + * @x: + * @y: + * + * TODO: Write me + */ +void +fo_print_context_translate(FoPrintContext *fpc, FoUnit x, FoUnit y) +{ + g_return_if_fail(fpc); + + g_assert(fpc->gpc); + gnome_print_translate(fpc->gpc, + x, + y); +} + diff -urN aa/conglomerate-0.7.14/src/fo-rect.c conglomerate-0.7.14/src/fo-rect.c --- aa/conglomerate-0.7.14/src/fo-rect.c 1970-01-01 01:00:00.000000000 +0100 +++ conglomerate-0.7.14/src/fo-rect.c 2004-07-05 01:03:41.098873928 +0200 @@ -0,0 +1,72 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* + * fo-rect.c + * + * Copyright (C) 2002 David Malcolm + * + * FIXME: This file is currently licensed under the GPL, but I intend it to eventually become part of a library licensed under the LGPL + * + * Authors: David Malcolm + */ + +#include "global.h" +#include "fo.h" + +/* FoRect methods: */ +/** + * fo_rect_set_xywh: + * @rect: + * @x: + * @y: + * @w: + * @h: + * + * TODO: Write me + */ +void +fo_rect_set_xywh(FoRect *rect, FoUnit x, FoUnit y, FoUnit w, FoUnit h) +{ + g_return_if_fail(rect); + + rect->x=x; + rect->y=y; + rect->w=w; + rect->h=h; +} + +/** + * fo_rect_set_xyxy: + * @rect: + * @x0: + * @y0: + * @x1: + * @y1: + * + * TODO: Write me + */ +void +fo_rect_set_xyxy(FoRect *rect, FoUnit x0, FoUnit y0, FoUnit x1, FoUnit y1) +{ + g_return_if_fail(rect); + + rect->x=x0; + rect->y=y0; + rect->w=x1-x0; + rect->h=y1-y0; +} + +/** + * fo_rect_test_render: + * @rect: + * @fpc: + * @label: + * + * TODO: Write me + */ +void +fo_rect_test_render(const FoRect *rect, FoPrintContext *fpc, const gchar *label) +{ + fo_print_context_test_rect(fpc, rect, label); +} + diff -urN aa/conglomerate-0.7.14/src/fo-solver-result.c conglomerate-0.7.14/src/fo-solver-result.c --- aa/conglomerate-0.7.14/src/fo-solver-result.c 1970-01-01 01:00:00.000000000 +0100 +++ conglomerate-0.7.14/src/fo-solver-result.c 2004-07-05 01:03:14.998841736 +0200 @@ -0,0 +1,452 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* + * fo-solver-result.c + * + * Copyright (C) 2002 David Malcolm + * + * FIXME: This file is currently licensed under the GPL, but I intend it to eventually become part of a library licensed under the LGPL + * + * Authors: David Malcolm + */ + +#include "global.h" +#include "fo.h" + +#if 0 +void fo_solver_area_add_child(FoSolverArea *area, FoSolverArea *child) +{ + g_assert(child->parent==NULL); + + area->children = g_list_append(area->children, child); + child->parent = area; +} + +void fo_solver_area_render_recursive(FoSolverArea *area, FoPrintContext *fpc) +{ + GList *iter; + + g_return_if_fail(area); + g_return_if_fail(fpc); + + fo_print_context_push_state(fpc); + + /* Render this, if appropriate: */ + if (FO_OBJECT(area)->klass) { + if (FO_SOLVER_AREA_CLASS(FO_OBJECT(area)->klass)->render) { + FO_SOLVER_AREA_CLASS(FO_OBJECT(area)->klass)->render(area, + fpc); + } + } + + /* Recurse through children: */ + for (iter = area->children; iter; iter=iter->next) { + FoSolverArea *child = iter->data; + + fo_solver_area_render_recursive(child, fpc); + } + + fo_print_context_pop_state(fpc); +}; + +/* FoSolverResult internals: */ +void test_rect_render(FoSolverArea *area, + FoPrintContext *fpc) +{ + FoSolverTestRect *test_rect = FO_SOLVER_TEST_RECT(area); + + fo_rect_test_render(&test_rect->rect, fpc, test_rect->text); +} + +const FoSolverAreaClass test_rect_class = +{ + {"test_rect_class"}, + test_rect_render +}; + +FoSolverTestRect *fo_solver_test_rect_new(const FoRect *rect, const gchar *text) +{ + FoSolverTestRect *test_rect; + + test_rect = g_new0(FoSolverTestRect,1); + FO_OBJECT(test_rect)->klass = FO_CLASS(&test_rect_class); + + test_rect->rect = *rect; + test_rect->text = g_strdup(text); + + return test_rect; +}; + +void rect_render(FoSolverArea *area, + FoPrintContext *fpc) +{ + FoSolverRect *rect = FO_SOLVER_RECT(area); + + fo_print_context_translate(fpc, rect->rect.x, rect->rect.y); +} + +const FoSolverAreaClass rect_class = +{ + {"rect_class"}, + rect_render +}; + +FoSolverRect *fo_solver_rect_new(const FoRect *rect) +{ + FoSolverRect *solver_rect; + + solver_rect = g_new0(FoSolverRect,1); + FO_OBJECT(solver_rect)->klass = FO_CLASS(&rect_class); + + solver_rect->rect = *rect; + + return solver_rect; +}; + +void text_render(FoSolverArea *area, + FoPrintContext *fpc) +{ + FoSolverText *text = FO_SOLVER_TEXT(area); + + FoRect rect; + + fo_rect_set_xywh(&rect, ((double)rand()*5000.0)/(double)RAND_MAX,((double)rand()*5000.0)/(double)RAND_MAX,200,20); + + fo_rect_test_render(&rect, fpc, text->text); +} + +const FoSolverAreaClass text_class = +{ + {"text_class"}, + text_render +}; + +const FoSolverAreaClass page_class = +{ + {"page_class"}, + + NULL +}; + +FoSolverPage *fo_solver_page_new(FoSimplePageMaster *spm) +{ + FoSolverPage *page = g_new0(FoSolverPage,1); + + FO_OBJECT(page)->klass = FO_CLASS(&page_class); + + page->spm = spm; + + return page; +} + + +static void add_page(FoSolverResult *solver_result, FoSolverPage *page) +{ + solver_result->list_of_solver_page = g_list_append(solver_result->list_of_solver_page, page); + solver_result->num_pages++; +#if 0 + solver_result->current_page = page; + solver_result->insertion_y = 26*30.0; +#endif +} + +static void pour_single_area(FoSolverResult *solver_result, FoSolverArea *area, FoSolverArea *insertion_area) +{ +#if 1 + fo_solver_area_add_child(insertion_area, area); +#else + FoRect rect; + FoSolverRect *solver_rect; + + if (solver_result->insertion_y<30.0f) { + /* We've run out of room; start a new page: */ + + FoSimplePageMaster *spm; + FoSolverPage *page; + + /* generate a page; uses first spm for now: */ + spm = solver_result->parser_result->list_of_simple_page_master->data; + page = fo_solver_page_new(spm); + + add_page(solver_result, page); + } + + fo_rect_set_xywh(&rect, 150.0, solver_result->insertion_y, 200.0, 20.0); + + solver_rect = fo_solver_rect_new(&rect); + + fo_solver_area_add_child(FO_SOLVER_AREA(solver_result->current_page), FO_SOLVER_AREA(solver_rect)); + fo_solver_area_add_child(FO_SOLVER_AREA(solver_rect), FO_SOLVER_AREA(area)); + solver_result->insertion_y-=30.0; +#endif +} + +/* Currently very hackish: */ +static void pour_flow_recursive(FoSolverResult *solver_result, xmlNodePtr node, FoSolverArea *insertion_area) +{ + xmlNodePtr iter; + + /* Handle this node: */ + + if (0==xmlStrcmp(node->name, "block")) { + /* create block area(s) */ + FoSolverBlockArea *block_area; + + block_area = g_new0(FoSolverBlockArea,1); + + pour_single_area(solver_result, FO_SOLVER_AREA(block_area), insertion_area ); + + insertion_area = FO_SOLVER_AREA(block_area); + + } else if (0==xmlStrcmp(node->name, "inline")) { + /* create inline area(s) */ + FoSolverInlineArea *inline_area; + + inline_area = g_new0(FoSolverInlineArea,1); + + pour_single_area(solver_result, FO_SOLVER_AREA(inline_area), insertion_area ); + + insertion_area = FO_SOLVER_AREA(inline_area); + + } else if (node->type==XML_TEXT_NODE) { + + /* Split the text into a list of PangoItem: */ + { + PangoAttrList* attr_list; + PangoAttribute *attribute; + GList *list_of_pango_item; + GList *iter; + + attr_list = pango_attr_list_new(); + + attribute = pango_attr_family_new("Serif"); + /* attribute = pango_attr_family_new("Sans"); */ + /* attribute = pango_attr_family_new("Monospace"); */ + + /* is this code necessary? */ + attribute->start_index = 0; + attribute->end_index = 5; /* g_strlen(node->content); */ + + pango_attr_list_insert( attr_list, attribute ); + + list_of_pango_item = pango_itemize(solver_result->pango_context, + node->content, + 0, /* int start_index, */ + strlen(node->content), /* int length (in bytes, hence strlen is appropriate) */ + attr_list, /* PangoAttrList *attrs, */ + NULL /* PangoAttrIterator *cached_iter */); + + /* For each PangoItem: */ /* FIXME: should there always be one at the moment? */ + for (iter = list_of_pango_item; iter; iter=iter->next) { + PangoItem *item = iter->data; + PangoLogAttr *attrs; + int i; + int start_of_line; + + #if 0 + { + gchar *item_text = g_strndup(node->content + item->offset, item->num_chars); + + g_message("got pango item: \"%s\"\n", item_text); + + g_free(item_text); + } + #endif + + attrs = g_new0(PangoLogAttr, item->num_chars+1); + + /* Calculate linebreak properties of the characters in the text: */ + pango_break(node->content + item->offset, + item->length, + &item->analysis, + attrs, + item->num_chars+1); + + start_of_line = 0; + for (i=0;inum_chars;i++) { + if (attrs[i].is_line_break) { + /* g_message("char %i is possible line break\n", i); */ + + if (i>start_of_line) { + /* Then we have a run of text between two possible line-breaks; convert it to a glyph string */ + FoSolverText *solver_text; + + solver_text = g_new0(FoSolverText,1); + FO_OBJECT(solver_text)->klass = FO_CLASS(&text_class); + solver_text->glyph_string = pango_glyph_string_new(); + solver_text->pango_font = item->analysis.font; + solver_text->text = g_strndup(g_utf8_offset_to_pointer(node->content + item->offset, start_of_line), + i-start_of_line); + + /* Convert characters into glyphs: */ + pango_shape( g_utf8_offset_to_pointer(node->content + item->offset, start_of_line), + g_utf8_offset_to_pointer(node->content + item->offset, i) - g_utf8_offset_to_pointer(node->content + item->offset, start_of_line), + &item->analysis, + solver_text->glyph_string); + + /* Find out the extent of the string: */ + pango_glyph_string_extents( solver_text->glyph_string, + solver_text->pango_font, + &solver_text->ink_rect, + &solver_text->logical_rect); + + /* Add an area: */ + pour_single_area(solver_result, FO_SOLVER_AREA(solver_text), insertion_area ); + } + + start_of_line = i+1; + } + } + + g_free(attrs); + } + } + + } + + /* Recurse through children: */ + for (iter = node->children; iter; iter = iter->next) { + pour_flow_recursive(solver_result, iter, insertion_area); + } + +} + +static void pour_flow(FoSolverResult *solver_result, FoFlow *flow) +{ + pour_flow_recursive(solver_result, FO_PARSER_OBJECT(flow)->node, FO_SOLVER_AREA(solver_result->list_of_solver_page->data)); +} + +void run_solver(FoSolverResult *solver_result, FoParserResult *parser_result) +{ + GList *iter; + + solver_result->parser_result = parser_result; + + solver_result->pango_context = pango_context_new(); + + solver_result->pango_font_map = pango_ft2_font_map_for_display(); /* FIXME: will this be available? */ + + pango_context_set_font_map(solver_result->pango_context, + solver_result->pango_font_map); + + + + { + PangoFontFamily **families; + int n_families; + int i; + + pango_font_map_list_families(solver_result->pango_font_map, + &families, + &n_families); + + for (i=0;ilist_of_page_sequence; iter; iter = iter->next) { + FoPageSequence *ps; + FoSimplePageMaster *spm; + FoSolverPage *page; + int i; + + ps = iter->data; + g_assert(ps->psg); + + solver_result->current_ps = ps; + +#if 1 + + /* generate a page; uses first spm for now: */ + spm = parser_result->list_of_simple_page_master->data; + page = fo_solver_page_new(spm); + + add_page(solver_result, page); + + /* Generate some content: */ + { +#if 1 + if (ps->flow) { + pour_flow(solver_result, ps->flow); + } +#else + FoRect rect; + + fo_rect_set_xywh(&rect, 150.0, 100.0, 200.0, 200.0); + fo_solver_area_add_child(FO_SOLVER_AREA(page), FO_SOLVER_AREA(fo_solver_test_rect_new(&rect, "test1"))); + + fo_rect_set_xywh(&rect, 250.0, 100.0, 200.0, 200.0); + fo_solver_area_add_child(FO_SOLVER_AREA(page), FO_SOLVER_AREA(fo_solver_test_rect_new(&rect, "test2"))); + + fo_rect_set_xywh(&rect, 150.0, 150.0, 200.0, 200.0); + fo_solver_area_add_child(FO_SOLVER_AREA(page), FO_SOLVER_AREA(fo_solver_test_rect_new(&rect, "test3"))); +#endif + } +#else + for (i=0;i<5;i++) { + + spm = fo_page_sequence_generator_get_master_for_next_page(ps->psg, + (solver_result->num_pages+1), + (i==0), /* gboolean is_first_of_sequence, */ + (i==4), /* gboolean is_last_of_sequence, */ + FALSE /* gboolean is_blank */); + + g_assert(spm); + g_message("Using spm \"%s\"\n", spm->base.name); + } +#endif + } + + +} + +/* FoSolverResult methods: */ +FoSolverResult *fo_solver_result_new_from_parser_result(FoParserResult *parser_result) +{ + FoSolverResult *solver_result; + + g_return_val_if_fail(parser_result, NULL); + + solver_result = g_new0(FoSolverResult, 1); + + run_solver(solver_result, parser_result); + + return solver_result; +} + +void fo_solver_result_delete(FoSolverResult *result) +{ + g_return_if_fail(result); + + /* FIXME: cleanup! */ + + g_free(result); +} + +void fo_solver_result_render(FoSolverResult *result, FoPrintContext *fpc) +{ + GList *iter; + + g_return_if_fail(result); + g_return_if_fail(fpc); + + /* This algorithm is done; we simply need to generate the areas... */ + for (iter = result->list_of_solver_page; iter; iter = iter->next) { + FoSolverPage *page = iter->data; + FoRect rect; + + fo_print_context_beginpage(fpc, page->spm->base.name); + + fo_solver_area_render_recursive(FO_SOLVER_AREA(page), fpc); + + fo_print_context_showpage (fpc); + + } + +} + +#endif diff -urN aa/conglomerate-0.7.14/src/fo-tests.c conglomerate-0.7.14/src/fo-tests.c --- aa/conglomerate-0.7.14/src/fo-tests.c 1970-01-01 01:00:00.000000000 +0100 +++ conglomerate-0.7.14/src/fo-tests.c 2004-07-05 01:02:57.569491400 +0200 @@ -0,0 +1,77 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ + +/* + * fo-tests.c + * + * Copyright (C) 2002 David Malcolm + * + * FIXME: This file is currently licensed under the GPL, but I intend it to eventually become part of a library licensed under the LGPL + * + * Authors: David Malcolm + */ + +#include "global.h" +#include "fo.h" + +#if 0 +void cong_gnome_print_render_xslfo(xmlDocPtr xml_doc, GnomePrintJob *gpm) +{ + GnomePrintContext *gpc; + FoPrintContext *fpc; + FoParserResult *parser_result; + FoSolverResult *solver_result; + + g_return_if_fail(xml_doc); + g_return_if_fail(gpm); + + gpc = gnome_print_job_get_context (gpm); + + fpc = fo_print_context_new_from_gnome_print(gpc); + +#if 1 + { + parser_result = fo_parser_result_new_from_xmldoc(xml_doc); + + if (parser_result) { + +#if 1 + /* View solver result: */ + solver_result = fo_solver_result_new_from_parser_result(parser_result); + + if (solver_result) { + fo_solver_result_render(solver_result, fpc); + + fo_solver_result_delete(solver_result); + } +#else + /* View parser result: */ + fo_parser_result_test_render(parser_result, fpc); +#endif + + fo_parser_result_delete(parser_result); + + } + } +#else + { + GnomeFont *font; + font = gnome_font_find_closest ("Helvetica", 12); + + gnome_print_beginpage (gpc, "1"); + + gnome_print_setfont (gpc, font); + gnome_print_moveto (gpc, 100, 400); + gnome_print_show (gpc, "This will eventually be the text from the FO doc..."); + + gnome_print_moveto (gpc, 100, 200); + gnome_print_lineto (gpc, 200, 200); + gnome_print_stroke (gpc); + + gnome_print_showpage (gpc); + } +#endif + + fo_print_context_delete(fpc); + +} +#endif