#ifndef MICROTEX_ATOM_ROW_H #define MICROTEX_ATOM_ROW_H #include #include "atom/atom.h" #include "atom/atom_text.h" #include "box/box.h" #include "unimath/uni_char.h" #include "utils/utils.h" namespace microtex { class AtomDecor; class FixedCharAtom; class CharSymbol; class Env; /** * A "composed atom": An atom that consists of child atoms that will be * displayed next to each other horizontally with glue between them. */ class Row { public: /** * Sets the given "decor" containing the atom that comes just before the first * child atom of this "composed atom". This method will always be called by * another composed atom, so this composed atom will be a child of it * (nested). This is necessary to determine the glue to insert between the * first child atom of this nested composed atom and the atom that the "decor" * contains. * * @param decor * the atom that comes just before this "composed atom" */ virtual void setPreviousAtom(const sptr& decor) = 0; }; /** * Used by RowAtom. The "textSymbol"-property and the type of an atom can changed * (according to the TeX-algorithms used). Or this atom can be replaced by a * ligature, (if it was a CharAtom). But atoms cannot be changed, otherwise * different boxes could be made from the same formula, and that is not * desired! This "atom decor" makes sure that changes to an atom (during the * createBox-method of a RowAtom) will be reset. */ class AtomDecor { private: sptr _atom; bool _textSymbol = false; public: AtomType _type = AtomType::none; AtomDecor() = delete; explicit AtomDecor(const sptr& atom) { _textSymbol = false; _atom = atom; _type = AtomType::none; } /** @return the changed type, or the old left type if it has not been changed */ inline AtomType leftType() const { return (_type != AtomType::none ? _type : _atom->leftType()); } /** @return the changed type, or the old right type if it has not been changed */ inline AtomType rightType() const { return (_type != AtomType::none ? _type : _atom->rightType()); } /** Test if this atom is a char-symbol. */ bool isChar() const; /** Test if this char is in math mode. */ bool isMathMode() const; /** This method will only be called if #isChar returns true. */ Char getChar(Env& env) const; /** Changes this atom into the given "ligature atom". */ void changeAtom(const sptr& atom); sptr createBox(Env& env); inline void markAsTextSymbol() { _textSymbol = true; } /** Test if this atom is a kern. */ bool isKern() const; /** Only for row-elements, for nested rows */ void setPreviousAtom(const sptr& prev); }; /** * An atom representing a horizontal row of other atoms, to be separated by * glue. It's also responsible for inserting kerns and ligature. */ class RowAtom : public Atom, public Row { private: // set of atom types that make a previous bin atom change to ord static std::bitset<16> _binSet; // set of atom types that can possibly need a kern or, together // with the previous atom, be replaced by a ligature static std::bitset<16> _ligKernSet; // whether the box generated can be broken bool _breakable; // atoms to be displayed horizontally next to each-other std::vector> _elements; // previous atom (for nested Row atoms) sptr _previousAtom; /** * Change the atom-type to ORD if necessary *

* i.e. for formula: `$+ e - f$`, the plus sign should be treat as * an ordinary type */ static void changeToOrd(AtomDecor* cur, AtomDecor* prev, Atom* next); sptr currentChar(int i); int processInvalid(const sptr& txt, bool isMathMode, int i, Env& env); sptr processContinues(int& i, bool isMathMode); public: static bool _breakEverywhere; bool _lookAtLastAtom; RowAtom() : _lookAtLastAtom(false), _breakable(true) {} explicit RowAtom(const sptr& atom); /** Get the atom at the front in the elements */ sptr getFirstAtom(); /** Get and remove the atom at the tail in the elements */ sptr popBack(); /** * Get the atom at position * * @param pos the position of the atom to retrieve */ sptr get(size_t pos); /** * Indicate the box generated by this atom can be broken or not * * @param breakable indicate whether the box can be broken */ inline void setBreakable(bool breakable) { _breakable = breakable; } /** Get the size of the elements */ inline size_t size() const { return _elements.size(); } /** Push an atom to back */ void add(const sptr& atom); sptr createBox(Env& env) override; void setPreviousAtom(const sptr& prev) override; AtomType leftType() const override; AtomType rightType() const override; }; } // namespace microtex #endif // MICROTEX_ATOM_ROW_H