Skip to content

Commit

Permalink
Document class improvements (#265)
Browse files Browse the repository at this point in the history
* Added support for the <body> fill attribute
* Fixed support for the <template> instruction
* Fixed issue with the parsing of <table> column values
* Fixed issue with the <cell> tag not being usable within templates
  • Loading branch information
paul-manias authored Oct 9, 2024
1 parent 1f7c12a commit 3a94e20
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/document/class/document_class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ static ERR feedback_view(objVectorViewport *View, FM Event)
/*********************************************************************************************************************
-ACTION-
Activate: Opens the current document selection.
Activate: Activates all child objects of the document.
Calling the Activate() action on a document object will forward Activate() calls to its child objects.
Expand Down
5 changes: 3 additions & 2 deletions src/document/defs/document.h
Original file line number Diff line number Diff line change
Expand Up @@ -1072,10 +1072,11 @@ class extDocument : public objDocument {
objXML *Templates; // All templates for the current document are stored here
objXML *PretextXML; // Execute this XML prior to loading a new page.
objSVG *SVG; // Allocated by the <svg> tag
XMLTag *PageTag; // Refers to a specific page that is being processed for the layout
objVectorRectangle *Bkgd; // Background fill object
XMLTag *PageTag; // Refers to a specific page that is being processed for the layout
objScript *ClientScript; // Allows the developer to define a custom default script.
objScript *DefaultScript;
doc_edit *ActiveEditDef; // As for ActiveEditCell, but refers to the active editing definition
doc_edit *ActiveEditDef; // As for ActiveEditCell, but refers to the active editing definition
objVectorScene *Scene; // A document specific scene is required to keep our resources away from the host
DOUBLE VPWidth, VPHeight; // Dimensions of the host Viewport
DOUBLE FontSize; // The default font-size, measured in 72 DPI pixels
Expand Down
25 changes: 23 additions & 2 deletions src/document/draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ ERR layout::position_widget(widget_mgr &Widget, doc_segment &Segment, objVectorV
// sensible for keeping them out of the layout loop.
//
// It is intended that the layout process generates the document's entire scene graph every time. Optimisations
// relating to things like obscuration of graphics elements are considered to be the job of the VectorScene's drawing
// functionality.
// relating to things like the obscuration of graphics elements are considered to be the job of the VectorScene's
// drawing functionality.

ERR layout::gen_scene_init(objVectorViewport *Viewport)
{
Expand Down Expand Up @@ -153,6 +153,27 @@ ERR layout::gen_scene_init(objVectorViewport *Viewport)
}
#endif

// Body background fill is initialised now, if specified.

if ((!Self->Background.empty()) and (!iequals("none", Self->Background))) {
if (Self->Bkgd = objVectorRectangle::create::global({
fl::Name("doc_body_fill"),
fl::Owner(Self->Page->UID),
fl::X(0), fl::Y(0),
fl::Width(Self->CalcWidth),
fl::Height(Self->PageHeight < Self->VPHeight ? Self->VPHeight : Self->PageHeight),
fl::Fill(Self->Background)
})) {

Self->UIObjects.push_back(Self->Bkgd->UID);

// Move-to-back required because vector objects are created within the page during the layout process.

acMoveToBack(Self->Bkgd);
}
}
else Self->Bkgd = NULL;

return ERR::Okay;
}

Expand Down
4 changes: 2 additions & 2 deletions src/document/layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ The layout process involves reading the serialised document stream and generatin
regions for graphics content. These segments have a dual purpose in that they can also be used for user
interaction.
The trickiest parts of the layout process are state management, word wrapping and page width extension.
The trickiest parts of the layout process are state management, word wrapping and page-width extension.
TABLES
------
Internally, the layout of tables is managed as follows:
The layout of tables is arranged as follows (left-to-right or top-to-bottom):
Border-Thickness, Cell-Spacing, Cell-Padding, Content, Cell-Padding, Cell-Spacing, ..., Border-Thickness
Expand Down
39 changes: 24 additions & 15 deletions src/document/parsing.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
The parsing code converts XML data to a serial byte stream, after which the XML data can be discarded. A DOM
of the original XML content is not maintained. After parsing, the stream will be ready for presentation via the
of the original XML content is *not* maintained. After parsing, the stream will be ready for presentation via the
layout code elsewhere in this code base.
The stream consists of byte codes represented by the entity class. Each type of code is represented by a C++
Expand Down Expand Up @@ -2621,27 +2621,27 @@ void parser::tag_template(XMLTag &Tag)

// Validate the template (must have a name)

LONG i;
for (i=1; i < std::ssize(Tag.Attribs); i++) {
if ((iequals("name", Tag.Attribs[i].Name)) and (!Tag.Attribs[i].Value.empty())) break;
if ((iequals("class", Tag.Attribs[i].Name)) and (!Tag.Attribs[i].Value.empty())) break;
LONG n;
for (n=1; n < std::ssize(Tag.Attribs); n++) {
if ((iequals("name", Tag.Attribs[n].Name)) and (!Tag.Attribs[n].Value.empty())) break;
}

if (i >= std::ssize(Tag.Attribs)) {
log.warning("A <template> is missing a name or class attribute.");
if (n >= std::ssize(Tag.Attribs)) {
log.warning("A <template> is missing a name attribute.");
return;
}

Self->RefreshTemplates = true;

// TODO: It would be nice if we scanned the existing templates and
// replaced them correctly, however we're going to be lazy and override
// styles by placing updated definitions at the end of the style list.

STRING strxml;
if (m_xml->serialise(Tag.ID, XMF::NIL, &strxml) IS ERR::Okay) {
Self->Templates->insertXML(0, XMI::PREV, strxml, 0);
// Remove any existing tag that uses the same name.
if (Self->TemplateIndex.contains(strihash(Tag.Attribs[n].Value))) {
Self->Templates->removeTag(Tag.ID, 1);
}

Self->Templates->insertXML(Self->Templates->Tags[0].ID, XMI::END, strxml, 0);
FreeResource(strxml);

Self->RefreshTemplates = true; // Force a refresh of the TemplateIndex because the pointers will be changed
}
else log.warning("Failed to convert template %d to an XML string.", Tag.ID);
}
Expand Down Expand Up @@ -3658,7 +3658,14 @@ void parser::tag_table(XMLTag &Tag)
unsigned i;
for (i=0; (i < table.columns.size()) and (i < list.size()); i++) {
table.columns[i].preset_width = strtod(list[i].c_str(), NULL);
if (list[i].find_first_of('%') != std::string::npos) table.columns[i].preset_width_rel = true;
if (list[i].find_first_of('%') != std::string::npos) {
table.columns[i].preset_width *= 0.01;
table.columns[i].preset_width_rel = true;
if ((table.columns[i].preset_width < 0.0000001) or (table.columns[i].preset_width > 1.0)) {
log.warning("A <table> column value is invalid.");
Self->Error = ERR::InvalidDimension;
}
}
}

if (i < table.columns.size()) log.warning("Warning - columns attribute '%s' did not define %d columns.", columns.c_str(), LONG(table.columns.size()));
Expand Down Expand Up @@ -3826,6 +3833,8 @@ void parser::tag_cell(XMLTag &Tag)

parser parse(Self, cell.stream);

parse.m_in_template = m_in_template;
parse.m_inject_tag = m_inject_tag;
parse.m_paragraph_depth++;
parse.parse_tags_with_style(Tag.Children, new_style);
parse.m_paragraph_depth--;
Expand Down

0 comments on commit 3a94e20

Please sign in to comment.