mirror of
https://github.com/rdkit/rdkit.git
synced 2026-06-07 22:44:25 +08:00
* MolDraw2D refactoring - rename setupMoleculeDraw->initMoleculeDraw - track whether or not initDrawing() has been called - centralize calls to initDrawing() and clearDrawing() into initMoleculeDraw() - update svg hashes in tests * update some expected test results * support changing font scale and default scale add reaction test * does not work... this is hard * all tests pass * do something about legends * docs * more tests * more docs * cleanup * going around in circles... hopefully converging * cleanup * Single bond skeleton works. * Simple bond drawing seems to be working. * Initial addition of atom symbols. * Stash of not-quite-working atom symbols prior to major surgery. * Atom symbols seem to be working. Major surgery not required, just inverted Y coords at the outset. * Add classes to atom labels. * Renamed AtomLabel AtomSymbol. * Add highlights. * Fix bug from PR4839. * Molecule note. * Added atom notes. * Added bond notes. * Extract radicals. * Annotation via new DrawAnnotation class. * Add brackets. * Add linknodes. * Add close contacts. * Add attachment points. Fix wavy lines. * Draw molecules in grid. * Tidy. * Fix radicals when font has hit maxFontSize. Make getDrawCoords work. * Draw primitives take atom or draw coords. * Fix legends. * More fixing for tests. DrawMol::setScale now takes font scale as well. * tidy debug writes * Variable fraction of panel for legend. * Better legend positioning. * Fix sub- and super-script spacing. Added spaces to Freetype strings. * Basic reaction drawing. * Reaction highlighting. * Minor tweak to reacctions. * Tweaked reaction DrawMol widths. * Fix atomTags. * Fix catch tests except contours. * Contouring working in catch_tests.cpp. * Fix catch tests. * AtomSymbol and DrawAnnotation into MolDraw2D_detail. * DrawMol and DrawShape into MolDraw2D_detail. * DrawText inot MolDraw2D_detail. * Machete out. * DrawText goes private. * Move some stuff about, such as StringRect to its own header. * Python wrapper compiles (but crashes when Draw imported). * More tidying. Python DrawArrow failing. * Linux changes. * Fixed error in DrawShapeArrow spotted by valgrind. Fixed some warnings from gcc. * Maybe fixed DrawArrow. * Added basic argparse interface. * Added newlines. * Changes in response to review. Non-const args in move constructors and operator=. Added missing classes to MolDraw2D_detail. Deleted move operator= where it had been forgotten. Fixed copyright dates. * Deleted all default c'tors in derived classes. * Changes in response to review: Wedge widths now a proportion of mean bond length in draw coords.. Add padding below legend when positioning it. * Fix tests. * Fix the private/protected mess of the new classes. * Moved doesLineIntersect etc. * Reinstate original alignString for non-FT drawings. * More faffing about with reaction layouts. * Fix font sizes in testGitHub3391. * Fix atom notes fitting inside fat wedges. * Fix molecule annotation font size. * More fixes of rectangle/triangle collision detection. * Test for highlight linewidth multiplier. * Use push_back not emplace_back. * Attempt at better Freetype char spacing. * Option to turn off TEST_ASSERT. Currently off. * Fixed embarrassing maths to do with wedge fatness. * More tidying post-review. * Document highlight_linewidth_multipliers. * Expose baseFontSize to Python. * Changes in response to review. * Allow DrawMolecules molecules to be drawn to different scales. * Fix bond sneaking between C:8 in, for example, reactions. * Fix bad re-factoring. * Fix globbing. * Changes in response to review. * Add invariant check. * Add draw option to fix font size. * suggested changes * Update catch test results. * Fix expected freetype results. * Fix non-freetype drawers. * Fin non-freetype test results. * get the Qt drawer working too * Fix disappearing reaction highlights. * Changes as result of review. * Fixed non-FreeType hash codes for reaction SVGs. Extra comment in catch_tests. * reactant highlighting was clearning properties * Fix for failing contour python test. * fix a non-freetype problem * swig wrappers working * Bump timeouts in test. Co-authored-by: greg landrum <greg.landrum@gmail.com> Co-authored-by: David Cosgrove <david@cozchemix.co.uk>
207 lines
8.8 KiB
C++
207 lines
8.8 KiB
C++
//
|
|
// Copyright (C) 2020-2022 David Cosgrove and other RDKit contributors
|
|
//
|
|
// @@ All Rights Reserved @@
|
|
// This file is part of the RDKit.
|
|
// The contents are covered by the terms of the BSD license
|
|
// which is included in the file license.txt, found at the root
|
|
// of the RDKit source tree.
|
|
//
|
|
//
|
|
// Original author: David Cosgrove (CozChemIx).
|
|
//
|
|
// This is an abstract base class for drawing text into a MolDraw2D
|
|
// object.
|
|
|
|
#ifndef RDKIT_DRAWTEXT_H
|
|
#define RDKIT_DRAWTEXT_H
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <RDGeneral/export.h>
|
|
#include <Geometry/point.h>
|
|
#include <GraphMol/MolDraw2D/MolDraw2DHelpers.h>
|
|
#include <GraphMol/MolDraw2D/StringRect.h>
|
|
|
|
using RDGeom::Point2D;
|
|
|
|
namespace RDKit {
|
|
class MolDraw2D;
|
|
namespace MolDraw2D_detail {
|
|
|
|
// for aligning the drawing of text to the passed in coords.
|
|
enum class TextDrawType : unsigned char {
|
|
TextDrawNormal = 0,
|
|
TextDrawSuperscript,
|
|
TextDrawSubscript
|
|
};
|
|
std::ostream &operator<<(std::ostream &oss, const OrientType &o);
|
|
std::ostream &operator<<(std::ostream &oss, const TextAlignType &tat);
|
|
std::ostream &operator<<(std::ostream &oss, const TextDrawType &tdt);
|
|
|
|
// ****************************************************************************
|
|
// This is an implementation class, not intended to be used by the great
|
|
// unwashed. If you want to draw a string used MolDraw2D::drawString().
|
|
class RDKIT_MOLDRAW2D_EXPORT DrawText {
|
|
|
|
public:
|
|
virtual ~DrawText() = 0;
|
|
|
|
static constexpr double DEFAULT_FONT_SCALE =
|
|
0.6; // seems to be a good number
|
|
|
|
DrawText(double max_fnt_sz, double min_fnt_sz);
|
|
DrawText(const DrawText &) = delete;
|
|
DrawText(DrawText &&) = delete;
|
|
DrawText &operator=(const DrawText &) = delete;
|
|
DrawText &operator=(DrawText &&) = delete;
|
|
|
|
DrawColour const &colour() const;
|
|
void setColour(const DrawColour &col);
|
|
|
|
// size in "pixels" i.e scale() * base_font_size_.
|
|
double fontSize() const;
|
|
void setFontSize(double new_size);
|
|
double baseFontSize() const;
|
|
void setBaseFontSize(double new_size);
|
|
double maxFontSize() const;
|
|
void setMaxFontSize(double new_max);
|
|
double minFontSize() const;
|
|
void setMinFontSize(double new_max);
|
|
double fontScale() const;
|
|
// returns false if min or max font size is hit, true otherwise.
|
|
// ignoreLimits ignores minFontSize and maxFontSize.
|
|
bool setFontScale(double new_scale, bool ignoreLimits = false);
|
|
|
|
// these are only relevant for the FreeType DrawText classes.
|
|
virtual std::string getFontFile() const { return ""; }
|
|
virtual void setFontFile(const std::string &font_file) {
|
|
RDUNUSED_PARAM(font_file);
|
|
}
|
|
|
|
//! using the current scale, work out the size of the label
|
|
/*!
|
|
Bear in mind when implementing this, that, for example, NH2 will appear as
|
|
NH<sub>2</sub> to convey that the 2 is a subscript, and this needs to
|
|
be accounted for in the width and height.
|
|
*/
|
|
virtual void getStringSize(const std::string &label, double &label_width,
|
|
double &label_height) const;
|
|
// returns the extremes of the label, in draw (pixel) coords. dontSplit
|
|
// true suppresses the call to atomLabelToPieces.
|
|
void getStringExtremes(const std::string &label, OrientType orient,
|
|
double &x_min, double &y_min, double &x_max,
|
|
double &y_max, bool dontSplit = false) const;
|
|
// get the rectangles that go round each character of the string. If
|
|
// dontSplit is false, it assumes it's an atom label and splits it
|
|
// in a sensible way for that. If the OrientType is C, it applies
|
|
// textAlign, otherwise the text is aligned set appropriately for the
|
|
// OrientType.
|
|
void getStringRects(const std::string &text, OrientType orient,
|
|
std::vector<std::shared_ptr<StringRect>> &rects,
|
|
std::vector<TextDrawType> &draw_modes,
|
|
std::vector<char> &draw_chars, bool dontSplit = false,
|
|
TextAlignType textAlign = TextAlignType::MIDDLE) const;
|
|
|
|
//! drawString centres the string on cds.
|
|
virtual void drawString(const std::string &str, const Point2D &cds,
|
|
TextAlignType align);
|
|
// Aligns them according to OrientType. This version assumes it's an
|
|
// atomic symbol and calls atomLabelToPieces. This will behave
|
|
// badly with general text. Surround the string with <lit></lit>
|
|
// if that's an issue, or use the version above.
|
|
void drawString(const std::string &label, const Point2D &cds,
|
|
OrientType orient);
|
|
|
|
// put the label on end2, and then move end2 so that it is at
|
|
// the intersection of a string rectangle and the line from end1 to
|
|
// end2, if there is an intersection. Mostly for trimming bonds
|
|
// back from atom labels. end1 and end2 in draw coords.
|
|
void adjustLineForString(const std::string &label, OrientType orient,
|
|
const Point2D &end1, Point2D &end2) const;
|
|
|
|
// draw the char, with the bottom left hand corner at cds
|
|
virtual void drawChar(char c, const Point2D &cds) = 0;
|
|
|
|
// puts a colourful rectangle around each character in the string.
|
|
// For debugging, mostly.
|
|
void drawStringRects(const std::string &label, OrientType orient,
|
|
TextAlignType talign, const Point2D &cds,
|
|
MolDraw2D &mol_draw) const;
|
|
|
|
// cds in draw coords
|
|
// does the label at cds intersect the given StringRect.
|
|
bool doesRectIntersect(const std::string &label, OrientType orient,
|
|
const Point2D &cds, const StringRect &rect) const;
|
|
// does the vector of StringRects, each translated by cds, intersect the
|
|
// given StringRect.
|
|
bool doesRectIntersect(const std::vector<std::shared_ptr<StringRect>> &rects,
|
|
const Point2D &cds, const StringRect &rect) const;
|
|
bool doesLineIntersect(const std::string &label, OrientType orient,
|
|
const Point2D &cds, const Point2D &end1,
|
|
const Point2D &end2, double padding) const;
|
|
bool doesLineIntersect(const std::vector<std::shared_ptr<StringRect>> &rects,
|
|
const Point2D &cds, const Point2D &end1,
|
|
const Point2D &end2, double padding) const;
|
|
bool doesStringIntersect(
|
|
const std::vector<std::shared_ptr<StringRect>> &rects,
|
|
const Point2D &cds1, const std::string &label2, OrientType orient2,
|
|
const Point2D &cds2) const;
|
|
bool doesStringIntersect(const std::string &label1, OrientType orient1,
|
|
const Point2D &cds1, const std::string &label2,
|
|
OrientType orient2, const Point2D &cds2) const;
|
|
|
|
virtual void alignString(
|
|
TextAlignType align, const std::vector<TextDrawType> &draw_modes,
|
|
std::vector<std::shared_ptr<StringRect>> &rects) const;
|
|
// adjust the string rectangles up and down for super- and subscripts
|
|
void adjustStringRectsForSuperSubScript(
|
|
const std::vector<TextDrawType> &draw_modes,
|
|
std::vector<std::shared_ptr<StringRect>> &rects) const;
|
|
// return a scale factor appropriate for the character and draw type
|
|
// (normal or super- or subscript)
|
|
double selectScaleFactor(char c, TextDrawType draw_type) const;
|
|
|
|
// amount to scale subscripts and superscripts by
|
|
constexpr static double SUBS_SCALE = 0.66;
|
|
constexpr static double SUPER_SCALE = 0.66;
|
|
|
|
DrawColour colour_;
|
|
double font_scale_;
|
|
double max_font_size_;
|
|
double min_font_size_;
|
|
double base_font_size_ = DEFAULT_FONT_SCALE;
|
|
|
|
// return a vector of StringRects, one for each char in text, with
|
|
// super- and subscripts taken into account. Sizes in pixel coords,
|
|
// i.e. scaled by fontScale().
|
|
virtual void getStringRects(const std::string &text,
|
|
std::vector<std::shared_ptr<StringRect>> &rects,
|
|
std::vector<TextDrawType> &draw_modes,
|
|
std::vector<char> &draw_chars) const = 0;
|
|
void drawChars(const Point2D &a_cds,
|
|
const std::vector<std::shared_ptr<StringRect>> &rects,
|
|
const std::vector<TextDrawType> &draw_modes,
|
|
const std::vector<char> &draw_chars);
|
|
};
|
|
|
|
//! establishes whether to put string draw mode into super- or sub-script
|
|
//! mode based on contents of instring from i onwards. Increments i
|
|
//! appropriately
|
|
//! \returns true or false depending on whether it did something or not
|
|
RDKIT_MOLDRAW2D_EXPORT bool setStringDrawMode(const std::string &instring,
|
|
TextDrawType &draw_mode,
|
|
size_t &i);
|
|
|
|
// take the label for the given atom and return the individual pieces
|
|
// that need to be drawn for it. So NH<sub>2</sub> will return
|
|
// "N", "H<sub>2</sub>".
|
|
std::vector<std::string> atomLabelToPieces(const std::string &label,
|
|
OrientType orient);
|
|
|
|
} // namespace MolDraw2D_detail
|
|
} // namespace RDKit
|
|
|
|
#endif // RDKIT_DRAWTEXT_H
|