in core/render2d/src/render_cdxml.cpp [160:473]
void RenderParamCdxmlInterface::_renderMols(RenderParams& params)
{
MoleculeCdxmlSaver saver(*params.rOpt.output);
Array<BaseMolecule*> mols;
Array<int> ids;
if (params.mols.size() != 0)
for (int i = 0; i < params.mols.size(); ++i)
mols.push(params.mols[i]);
else if (params.mol.get() != 0)
mols.push(params.mol.get());
Array<float> column_widths;
column_widths.resize(params.cnvOpt.gridColumnNumber);
column_widths.fill(0);
Array<float> title_widths;
title_widths.resize(mols.size());
title_widths.fill(0);
Array<float> key_widths;
key_widths.resize(mols.size());
key_widths.fill(0);
Array<float> prop_widths;
prop_widths.resize(mols.size());
prop_widths.fill(0);
Array<Pos> positions;
positions.resize(mols.size());
Array<float> title_heights;
title_heights.resize(mols.size());
title_heights.fill(0);
for (int mol_idx = 0; mol_idx < mols.size(); ++mol_idx)
{
int column = mol_idx % params.cnvOpt.gridColumnNumber;
Pos& p = positions[mol_idx];
_getBounds(params, mols[mol_idx]->asMolecule(), p.str_min, p.str_max, p.scale);
float width = p.str_max.x - p.str_min.x;
// Check titles width
if (mol_idx < params.titles.size())
{
const Array<char>& title = params.titles[mol_idx];
if (title.size() > 0)
{
int longest_line = _getLongestLine(title);
// On average letters has width 6
float letter_width = params.rOpt.titleFontFactor / 1.5f;
float title_width = longest_line * letter_width / MoleculeCdxmlSaver::SCALE;
title_widths[mol_idx] = title_width;
width = std::max(width, title_width);
}
}
if (params.rOpt.cdxml_context.get() != NULL)
{
RenderCdxmlContext& context = *params.rOpt.cdxml_context;
if (context.enabled)
{
RenderCdxmlContext::PropertyData& data = context.property_data.at(mol_idx);
float letter_width = context.propertyFontSize / 1.5f;
int longest_line = _getLongestLineXml(data.propertyName);
key_widths[mol_idx] = longest_line * letter_width / MoleculeCdxmlSaver::SCALE;
longest_line += _getLongestLineXml(data.propertyValue);
float prop_width = longest_line * letter_width / MoleculeCdxmlSaver::SCALE;
prop_widths[mol_idx] = prop_width;
width = std::max(width, prop_width);
}
}
column_widths[column] = std::max(width, column_widths[column]);
}
float x_margins_base = 1.1f, y_margins_base = 1.1f;
float x_grid_base = 1.5f;
Array<float> column_offset;
column_offset.resize(params.cnvOpt.gridColumnNumber);
column_offset[0] = params.cnvOpt.marginX / 10.0f + x_margins_base;
for (int i = 1; i < params.cnvOpt.gridColumnNumber; i++)
column_offset[i] = column_offset[i - 1] + column_widths[i - 1] + x_grid_base;
float page_y_offset_base = params.cnvOpt.marginY / 10.0f + y_margins_base;
float row_y_offset = page_y_offset_base;
int last_row = 0;
float max_y = 0;
float title_y = 0;
// Get each structure bounds
int row_moved = 0;
for (int mol_idx = 0; mol_idx < mols.size(); ++mol_idx)
{
Pos& p = positions[mol_idx];
int column = mol_idx % params.cnvOpt.gridColumnNumber;
int row = mol_idx / params.cnvOpt.gridColumnNumber;
p.page_offset.x = column_offset[column];
p.page_offset.y = row_y_offset;
p.size.diff(p.str_max, p.str_min);
p.all_size = p.size;
if (mol_idx < params.titles.size())
{
const Array<char>& title = params.titles[mol_idx];
if (title.size() > 0)
{
int lines = title.count('\n') + 1;
float letter_height = params.rOpt.titleFontFactor / MoleculeCdxmlSaver::SCALE;
// float title_height = lines * saver.textLineHeight();
// p.all_size.y += title_height + saver.textLineHeight(); // Add blank line
float title_height = lines * letter_height;
title_heights[mol_idx] = title_height;
p.all_size.y += title_height + letter_height; // Add blank line
}
}
if (params.rOpt.cdxml_context.get() != NULL)
{
RenderCdxmlContext& context = *params.rOpt.cdxml_context;
if (context.enabled)
{
RenderCdxmlContext::PropertyData& data = context.property_data.at(mol_idx);
int lines = data.propertyName.count('\n') + 1;
float letter_height = params.rOpt.titleFontFactor / MoleculeCdxmlSaver::SCALE;
float prop_height = lines * letter_height;
p.all_size.y += prop_height + letter_height; // Add blank line
}
}
// Check that the structure is fully on a single page
int pbegin = (int)(p.page_offset.y / saver.pageHeight());
int pend = (int)((p.page_offset.y + p.all_size.y) / saver.pageHeight());
// Additional check that we didn't moved this row before
if (pbegin != pend && row_moved != row)
{
// Update starting row_y_offset for the whole row and start this row again
row_y_offset = (pbegin + 1) * saver.pageHeight() + page_y_offset_base;
mol_idx = row * params.cnvOpt.gridColumnNumber - 1;
row_moved = row;
continue;
}
p.offset.x = p.page_offset.x - p.str_min.x + (column_widths[column] - p.size.x) / 2;
p.offset.y = -p.page_offset.y - p.str_max.y;
p.title_offset_y = -p.page_offset.y - p.size.y - 1.0f;
max_y = std::max(max_y, p.page_offset.y + p.all_size.y);
int next_row = (mol_idx + 1) / params.cnvOpt.gridColumnNumber;
if (last_row != next_row)
{
row_y_offset = max_y + 1.0f;
last_row = next_row;
}
}
if (params.cnvOpt.comment.size() > 0)
{
int lines = params.cnvOpt.comment.count('\n') + 1;
float comment_height = lines * 0.3f;
max_y += 0.3f;
title_y = max_y;
max_y += comment_height;
}
MoleculeCdxmlSaver::Bounds b;
b.min.set(0, 0);
float w = column_offset[params.cnvOpt.gridColumnNumber - 1] + column_widths[params.cnvOpt.gridColumnNumber - 1];
w += x_margins_base + params.cnvOpt.marginX / 10.0f;
b.max.set(w, max_y + y_margins_base);
saver.beginDocument(&b);
Array<char> font_attr;
ArrayOutput font_out(font_attr);
font_out.printf("<s size=\"%f\"", params.rOpt.titleFontFactor);
if (params.rOpt.cdxml_context.get() != NULL)
{
RenderCdxmlContext& context = *params.rOpt.cdxml_context;
if (context.fonttable.size() > 0)
{
saver.addFontTable(context.fonttable.ptr());
}
if (context.colortable.size() > 0)
{
saver.addColorTable(context.colortable.ptr());
}
if (context.titleFont.size() > 0)
{
font_out.printf(" font=\"%s\"", context.titleFont.ptr());
}
if (context.titleFace.size() > 0)
{
font_out.printf(" face=\"%s\"", context.titleFace.ptr());
}
}
font_out.printf(">");
font_attr.push(0);
// if (params.rOtitleFont.size() > 0) {
// font_out.printf("id=\"5\" charset=\"iso-8859-1\" name=\"%s\"", params.cnvOpt.titleFont.ptr());
// font_attr.push(0);
// saver.addFontTable(font_attr.ptr());
// /*
// * Set font as id 5 always
// */
// font_attr.clear();
// if (params.rOpt.titleFontFactor > 1)
// font_out.printf(" font=\"5\" size=\"%.0f\"", params.rOpt.titleFontFactor);
// else
// font_out.printf(" font=\"5\"");
//} else {
// if (params.rOpt.titleFontFactor > 1)
// font_out.printf(" size=\"%.0f\"", params.rOpt.titleFontFactor);
//}
// font_attr.push(0);
saver.beginPage(&b);
Array<char> title_font;
for (int mol_idx = 0; mol_idx < mols.size(); ++mol_idx)
{
int column = mol_idx % params.cnvOpt.gridColumnNumber;
Pos& p = positions[mol_idx];
Vec2f offset = p.offset;
offset.scale(1 / p.scale);
saver.saveMoleculeFragment(mols[mol_idx]->asMolecule(), offset, p.scale);
if (mol_idx < params.titles.size())
{
const Array<char>& title = params.titles[mol_idx];
if (title.size() > 0)
{
title_font.clear();
title_font.readString(font_attr.ptr(), false);
// Get title bounding box
float x = params.cnvOpt.titleAlign.getAnchorPoint(p.page_offset.x, column_widths[column], title_widths[mol_idx]);
const char* alignment_str = "";
MultilineTextLayout alignment = params.cnvOpt.titleAlign;
if (alignment.inbox_alignment == MultilineTextLayout::Center)
alignment_str = "Center";
if (alignment.inbox_alignment == MultilineTextLayout::Left)
alignment_str = "Left";
if (alignment.inbox_alignment == MultilineTextLayout::Right)
alignment_str = "Right";
Vec2f title_offset(x, p.title_offset_y);
title_font.appendString(title.ptr(), true);
title_font.appendString("</s>", true);
saver.addCustomText(title_offset, alignment_str, params.rOpt.titleFontFactor, title_font.ptr());
}
}
if (params.rOpt.cdxml_context.get() != NULL)
{
RenderCdxmlContext& context = *params.rOpt.cdxml_context;
if (context.enabled)
{
RenderCdxmlContext::PropertyData& data = context.property_data.at(mol_idx);
float prop_width = prop_widths[mol_idx];
float key_width = key_widths[mol_idx];
float prop_offset_y = p.title_offset_y - title_heights[mol_idx];
float x = params.cnvOpt.titleAlign.getAnchorPoint(p.page_offset.x, column_widths[column], prop_width);
float prop_offset_key = prop_width * 0.5f;
float prop_offset_val = prop_offset_key - (prop_width - key_width);
if (context.keyAlignment == RenderCdxmlContext::ALIGNMENT_LEFT)
{
Vec2f title_offset_key(x - prop_offset_key, prop_offset_y);
Vec2f title_offset_val(x + prop_offset_val, prop_offset_y);
saver.addCustomText(title_offset_key, "Left", context.propertyFontSize, data.propertyName.ptr());
saver.addCustomText(title_offset_val, "Left", context.propertyFontSize, data.propertyValue.ptr());
}
else
{
Vec2f title_offset_key(x + prop_offset_val, prop_offset_y);
Vec2f title_offset_val(x + prop_offset_val, prop_offset_y);
saver.addCustomText(title_offset_key, "Right", context.propertyFontSize, data.propertyName.ptr());
saver.addCustomText(title_offset_val, "Left", context.propertyFontSize, data.propertyValue.ptr());
}
}
}
}
if (params.cnvOpt.comment.size() > 0)
{
Vec2f pos(b.max.x / 2, -title_y);
saver.addText(pos, params.cnvOpt.comment.ptr());
}
saver.endPage();
saver.endDocument();
}