///////////////////////////////////////////////////////////////////////////// // Name: object.h // Author: Laurent Pugin // Created: 2005 // Copyright (c) Authors and others. All rights reserved. ///////////////////////////////////////////////////////////////////////////// #ifndef __VRV_OBJECT_H__ #define __VRV_OBJECT_H__ #include #include #include #include #include #include //---------------------------------------------------------------------------- #include "attclasses.h" #include "boundingbox.h" #include "vrvdef.h" namespace vrv { class Doc; class DurationInterface; class EditorialElement; class Output; class Functor; class FunctorParams; class LinkingInterface; class FacsimileInterface; class PitchInterface; class PositionInterface; class ScoreDefInterface; class StemmedDrawingInterface; class TextDirInterface; class TimePointInterface; class TimeSpanningInterface; class Zone; #define UNLIMITED_DEPTH -10000 #define FORWARD true #define BACKWARD false //---------------------------------------------------------------------------- // Object //---------------------------------------------------------------------------- /** * This class represents a basic object */ class Object : public BoundingBox { public: /** * @name Constructors, destructors, and other standard methods * Reset method resets all attribute classes */ ///@{ Object(); Object(const std::string &classid); virtual ~Object(); virtual ClassId GetClassId() const; virtual std::string GetClassName() const { return "[MISSING]"; } ///@} /** * Make an object a reference object that do not own children. * This cannot be un-done and has to be set before any child is added. */ ///@{ void SetAsReferenceObject(); bool IsReferenceObject() const { return m_isReferenceObject; } ///@} /** * Wrapper for checking if an element is a floating object (system elements and control elements) */ bool IsFloatingObject() const { return (this->IsSystemElement() || this->IsControlElement()); } /** * Wrapper for checking if an element has a boundary start interface and also if is set as a boundary element */ bool IsBoundaryElement(); /** * @name Methods for checking if an object is part of a group of classId's. * For example, all LayerElement child class classId's are between LAYER_ELEMENT and LAYER_ELEMENT_max. * See classId enum. */ ///@{ bool IsControlElement() const { return (this->GetClassId() > CONTROL_ELEMENT && this->GetClassId() < CONTROL_ELEMENT_max); } bool IsEditorialElement() const { return (this->GetClassId() > EDITORIAL_ELEMENT && this->GetClassId() < EDITORIAL_ELEMENT_max); } bool IsLayerElement() const { return (this->GetClassId() > LAYER_ELEMENT && this->GetClassId() < LAYER_ELEMENT_max); } bool IsRunningElement() const { return (this->GetClassId() > RUNNING_ELEMENT && this->GetClassId() < RUNNING_ELEMENT_max); } bool IsScoreDefElement() const { return (this->GetClassId() > SCOREDEF_ELEMENT && this->GetClassId() < SCOREDEF_ELEMENT_max); } bool IsSystemElement() const { return (this->GetClassId() > SYSTEM_ELEMENT && this->GetClassId() < SYSTEM_ELEMENT_max); } bool IsTextElement() const { return (this->GetClassId() > TEXT_ELEMENT && this->GetClassId() < TEXT_ELEMENT_max); } ///@} /** * @name Methods for registering a MEI att class and for registering interfaces regrouping MEI att classes. */ ///@{ void RegisterAttClass(AttClassId attClassId) { m_attClasses.push_back(attClassId); } bool HasAttClass(AttClassId attClassId) const { return std::find(m_attClasses.begin(), m_attClasses.end(), attClassId) != m_attClasses.end(); } void RegisterInterface(std::vector *attClasses, InterfaceId interfaceId); bool HasInterface(InterfaceId interfaceId) const { return std::find(m_interfaces.begin(), m_interfaces.end(), interfaceId) != m_interfaces.end(); } ///@} virtual DurationInterface *GetDurationInterface() { return NULL; } virtual LinkingInterface *GetLinkingInterface() { return NULL; } virtual FacsimileInterface *GetFacsimileInterface() { return NULL; } virtual PitchInterface *GetPitchInterface() { return NULL; } virtual PlistInterface *GetPlistInterface() { return NULL; } virtual PositionInterface *GetPositionInterface() { return NULL; } virtual ScoreDefInterface *GetScoreDefInterface() { return NULL; } virtual StemmedDrawingInterface *GetStemmedDrawingInterface() { return NULL; } virtual TextDirInterface *GetTextDirInterface() { return NULL; } virtual TimePointInterface *GetTimePointInterface() { return NULL; } virtual TimeSpanningInterface *GetTimeSpanningInterface() { return NULL; } /** * Reset the object, that is 1) removing all childs and 2) resetting all attributes. * The method is virtual, so _always_ call the parent in the method overriding it. */ virtual void Reset(); /** * Copy constructor that also copy the children. * The children are copied using the Object::Clone virtual method that * needs to be overridden in the child class - otherwise, it will crash. * Because this will create a problem if we don't check this (the parents will * one the same child...) * UUID: the uuid is copied, is needs to be reset later if this is not wished */ Object(const Object &object); /** * Copy assignement - see copy constructor. */ Object &operator=(const Object &object); /** * Move all the children of the object passed as parameter to this one. * Objects must be of the same type. * After this operation, the object passed as parameter has no child anymore. * If idx is provided, move the children to the idx position in the object children. * Only moving to the same type is allow unless allowTypeChange is true. */ void MoveChildrenFrom(Object *sourceParent, int idx = -1, bool allowTypeChange = false); /** * Replace the currentChild with the replacingChild. * The currentChild is not deleted by the methods. */ void ReplaceChild(Object *currentChild, Object *replacingChild); /** * @name Insert an object before or after a given child */ ///@{ void InsertBefore(Object *child, Object *newChild); void InsertAfter(Object *child, Object *newChild); ///@} /** * Sort children by a function that takes two arguments and * returns true if the first argument is less than the second. * If the order of children changes, this returns true. */ typedef bool (*binaryComp)(Object *, Object *); void SortChildren(binaryComp comp); /** * Move an object to another parent. * The object is relinquished from its current parent - see Object::Relinquish */ void MoveItselfTo(Object *targetParent); /** * Method call for copying child classes. * The method has to be overridden. */ virtual Object *Clone() const; /** * Indicate whereas children have to be copied in copy / assignment constructors. * This is true by default but can be overriden (e.g., for Staff, Layer) */ virtual bool CopyChildren() const { return true; } /** * Reset pointers after a copy and assignment constructor call. * This methods has to be called expicitly when overriden because it is not called from the constructors. * Do not forget to call base-class equivalent whenever applicable (e.g, with more than one hierarchy level). */ virtual void CloneReset(); const std::string &GetUuid() const { return m_uuid; } void SetUuid(std::string uuid); void SwapUuid(Object *other); void ResetUuid(); /** * Methods for setting / getting comments */ std::string GetComment() const { return m_comment; } void SetComment(std::string comment) { m_comment = comment; } bool HasComment() { return !m_comment.empty(); } std::string GetClosingComment() const { return m_closingComment; } void SetClosingComment(std::string endComment) { m_closingComment = endComment; } bool HasClosingComment() { return !m_closingComment.empty(); } /** * @name Children count, with or without a ClassId. * Used for classes with several types of children. * The methods count at the first level. */ ///@{ int GetChildCount() const { return (int)m_children.size(); } int GetChildCount(const ClassId classId) const; int GetChildCount(const ClassId classId, int deepth); ///@} /** * Child access (generic) */ Object *GetChild(int idx) const; Object *GetChild(int idx, const ClassId classId); /** * Return a const pointer to the children */ virtual const ArrayOfObjects *GetChildren(bool docChildren = true) const { return &m_children; } /** * Return a pointer to the children that allows modification. * This method should be all only in AddChild overrides methods */ ArrayOfObjects *GetChildrenForModification() { return &m_children; } /** * Fill an array of pairs with all attributes and their values. * Return the number of attributes found. */ int GetAttributes(ArrayOfStrAttr *attributes) const; /** * Check if an Object has an attribute with the specified value */ bool HasAttribute(std::string attribute, std::string value) const; /** * @name Iterator methods for accessing children. * GetFirst returns the first element child of the specified type. * Its position and the specified type are stored and used of accessing next elements * The methods returns NULL when no child is found or when the end is reached. * Always call GetFirst before calling GetNext() or call GetNext(child) */ ///@{ Object *GetFirst(const ClassId classId = UNSPECIFIED); Object *GetNext(); ///@} /** * @name Retrieving next or previous sibling of a certain type. * Returns NULL is not found */ ///@{ Object *GetNext(const Object *child, const ClassId classId = UNSPECIFIED); Object *GetPrevious(const Object *child, const ClassId classId = UNSPECIFIED); ///@} /** * Return the last child of the object (if any, NULL otherwise) */ Object *GetLast() const; /** * Get the parent of the Object */ Object *GetParent() const { return m_parent; } /** * Set the parent of the Object. * The current parent is expected to be NULL. */ void SetParent(Object *parent); /** * Reset the parent of the Object. * The current parent is not expected to be NULL. */ void ResetParent() { m_parent = NULL; } /** * Base method for checking if a child can be added. * The method has to be overridden. */ virtual bool IsSupportedChild(Object *object); /** * Base method for adding children. * The method can be overridden. */ virtual void AddChild(Object *object); /** * Return the index position of the object in its parent (-1 if not found) */ int GetIdx() const; /** * @name Get the X and Y drawing position */ ///@{ virtual int GetDrawingX() const; virtual int GetDrawingY() const; ///@} /** * @name Reset the cached values of the drawingX and Y values. * Reset all children recursively */ ///@{ virtual void ResetCachedDrawingX() const; virtual void ResetCachedDrawingY() const; ///@} /** * Look for the Object in the children and return its position (-1 if not found) */ int GetChildIndex(const Object *child); /** * Look for all Objects of a class and return its position (-1 if not found) */ int GetDescendantIndex(const Object *child, const ClassId classId, int deepth); /** * Insert an element at the idx position. */ void InsertChild(Object *element, int idx); /** * Detach the child at the idx position (NULL if not found) * The parent pointer is set to NULL. */ Object *DetachChild(int idx); /** * Return true if the object has the child Object as descendant (reference of direct). * Processes in depth-first. */ bool HasDescendant(Object *child, int deepness = UNLIMITED_DEPTH) const; /** * Look for a descendant with the specified uuid (returns NULL if not found) * This method is a wrapper for the Object::FindByUuid functor. */ Object *FindDescendantByUuid(std::string uuid, int deepness = UNLIMITED_DEPTH, bool direction = FORWARD); /** * Look for a descendant with the specified type (returns NULL if not found) * This method is a wrapper for the Object::FindByType functor. */ Object *FindDescendantByType(ClassId classId, int deepness = UNLIMITED_DEPTH, bool direction = FORWARD); /** * Return the first element matching the Comparison functor * Deepness allow to limit the depth search (EditorialElements are not count) */ Object *FindDescendantByComparison( Comparison *comparison, int deepness = UNLIMITED_DEPTH, bool direction = FORWARD); /** * Return the element matching the extreme value with an Comparison functor * Deepness allow to limit the depth search (EditorialElements are not count) */ Object *FindDescendantExtremeByComparison( Comparison *comparison, int deepness = UNLIMITED_DEPTH, bool direction = FORWARD); /** * Return all the objects matching the Comparison functor * Deepness allow to limit the depth search (EditorialElements are not count) */ void FindAllDescendantByComparison(ListOfObjects *objects, Comparison *comparison, int deepness = UNLIMITED_DEPTH, bool direction = FORWARD, bool clear = true); /** * Return all the objects matching the Comparison functor and being between start and end in the tree. * The start and end objects are included in the result set. */ void FindAllDescendantBetween( ListOfObjects *objects, Comparison *comparison, Object *start, Object *end, bool clear = true); /** * Give up ownership of the child at the idx position (NULL if not found) * This is a method to be used only in the very particular case where the child * object cannot be detached straight away. It is typically the case * when this has to be done within an iterator. The parent of the object * will be set to NULL but the object will not be removed. If the parent * is not destroyed after that, you should expect problems unless Object::ClearRelinquishedChildren is called * In other words: do not use unless you are absolutely sure what you are doing */ Object *Relinquish(int idx); /** * Removes all the children that were previously relinquished. * This has to be used when children are moved but then the parent is not deleted. */ void ClearRelinquishedChildren(); /** * Clear the children vector and delete all the objects. */ void ClearChildren(); /** * Remove and delete the child. * Return false if the child could not be found. In that case it will not be deleted. */ bool DeleteChild(Object *child); /** * Return the first ancestor of the specified type. * The maxSteps parameter limits the search to a certain number of level if not -1. */ Object *GetFirstAncestor(const ClassId classId, int maxSteps = -1) const; Object *GetFirstAncestorInRange(const ClassId classIdMin, const ClassId classIdMax, int maxDepth = -1) const; /** * Return the last ancestor that is NOT of the specified type. * The maxSteps parameter limits the search to a certain number of level if not -1. */ Object *GetLastAncestorNot(const ClassId classId, int maxSteps = -1); /** * Return the first child that is NOT of the specified type. */ Object *GetFirstChildNot(const ClassId classId); /** * Fill the list of all the children LayerElement. * This is used for navigating in a Layer (See Layer::GetPrevious and Layer::GetNext). */ void FillFlatList(ArrayOfObjects *list); /** * Check if the content was modified or not */ bool IsModified() const { return m_isModified; } /** * Mark the object and its parent (if any) as modified */ void Modify(bool modified = true); /** * @name Setter and getter of the attribute flag */ ///@{ bool IsAttribute() const { return m_isAttribute; } void IsAttribute(bool isAttribute) { m_isAttribute = isAttribute; } ///@} /** * @name Setter and getter of the expansion flag */ ///@{ bool IsExpansion() const { return m_isExpansion; } void IsExpansion(bool isExpansion) { m_isExpansion = isExpansion; } ///@} /** * Return true if the object contains any editorial content */ bool HasEditorialContent(); /** * Return true if the object contains anything that is not editorial content */ bool HasNonEditorialContent(); /** * Saves the object (and its children) using the specified output stream. * Creates functors that will parse the tree. */ virtual int Save(Output *output); /** * Sort the child elements using std::stable_sort */ template void StableSort(Compare comp) { std::stable_sort(m_children.begin(), m_children.end(), comp); } virtual void ReorderByXPos(); Object *FindNextChild(Comparison *comp, Object *start); Object *FindPreviousChild(Comparison *comp, Object *start); /** * Main method that processes functors. * For each object, it will call the functor. * Depending on the code returned by the functor, it will also process it for all children. * The ArrayOfComparisons filter parameter makes is possible to process only objects of a * type that matches the attribute value given in the Comparison object. * This is the generic way for parsing the tree, e.g., for extracting one single staff or layer. * Deepness specifies how many child levels should be processed. UNLIMITED_DEPTH means no * limit (EditorialElement objects do not count). * skipFirst does not call the functor or endFunctor on the first (calling) level */ virtual void Process(Functor *functor, FunctorParams *functorParams, Functor *endFunctor = NULL, ArrayOfComparisons *filters = NULL, int deepness = UNLIMITED_DEPTH, bool direction = FORWARD, bool skipFirst = false); //----------------// // Static methods // //----------------// static void SeedUuid(unsigned int seed = 0); static std::string GenerateRandUuid(); static bool sortByUlx(Object *a, Object *b); //----------// // Functors // //----------// /** * Add each LayerElements and its children to a flat list */ virtual int AddLayerElementToFlatList(FunctorParams *functorParams); /** * @name Functors for finding objects */ ///@{ /** * Find a Object with a specified uuid. */ virtual int FindByUuid(FunctorParams *functorParams); /** * Find a Object with a Comparison functor . */ virtual int FindByComparison(FunctorParams *functorParams); /** * Find a Object with the extreme value with a Comparison functor . */ virtual int FindExtremeByComparison(FunctorParams *functorParams); /** * Find a all Object with an Comparison functor. */ virtual int FindAllByComparison(FunctorParams *functorParams); /** * Find a all Object between a start and end Object and with an Comparison functor. */ virtual int FindAllBetween(FunctorParams *functorParams); /** * Find a all Object to which another object points to in the data. */ virtual int FindAllReferencedObjects(FunctorParams *functorParams); /** * Look if the time / duration passed as parameter overlap with a space in the alignment references */ virtual int LayerCountInTimeSpan(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Look for all the layer elements that overlap with the time / duration within certain layer passed as parameter */ virtual int LayerElementsInTimeSpan(FunctorParams *functorParams) { return FUNCTOR_CONTINUE; } /** * Retrieve the layer elements spanned by two points */ virtual int FindSpannedLayerElements(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Retrieve the minimum left and maximum right for an alignment. * Used in GraceAligner::GetGraceGroupLeft and GraceAligner::GetGraceGroupRight */ virtual int GetAlignmentLeftRight(FunctorParams *functorParams); ///@} /** * @name Functors for loading and saving the docuement */ ///@{ /** * Convert top-level all container (section, endings) and editorial elements to boundary elements. */ ///@{ virtual int ConvertToPageBased(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int ConvertToPageBasedEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Convert mensural MEI into cast-off (measure) segments looking at the barLine objects. * Segment positions occur where a barLine is set on all staves. */ ///@{ virtual int ConvertToCastOffMensural(FunctorParams *functorParams); virtual int ConvertToUnCastOffMensural(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Convert analytical markup (@fermata, @tie) to elements. * See Doc::ConvertMarkupAnalyticalDoc */ ///@{ virtual int ConvertMarkupAnalytical(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int ConvertMarkupAnalyticalEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Convert markup of artic@artic multi value into distinct artic elements. * See Doc::ConvertMarkupAnalyticalDoc */ ///@{ virtual int ConvertMarkupArtic(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int ConvertMarkupArticEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Save the content of any object by calling the appropriate FileOutputStream method. */ ///@{ virtual int Save(FunctorParams *functorParams); virtual int SaveEnd(FunctorParams *functorParams); ///@} ///@} /** * @name Functors for aligning the content horizontally */ ///@{ /** * Reset the horizontal alignment environment for various types for object. */ virtual int ResetHorizontalAlignment(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Align horizontally the content of a page. * For each LayerElement, instanciate its Alignment. * It creates it if no other note or event occurs at its position. * At the end, for each Layer, align the grace note stacked in GraceAlignment. */ ///@{ virtual int AlignHorizontally(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int AlignHorizontallyEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Align the measures by adjusting the m_drawingXRel position looking at the MeasureAligner. * At the end, store the width of the system in the MeasureAligner for justification. */ ///@{ virtual int AlignMeasures(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int AlignMeasuresEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Set the position of the Alignment. * Looks at the time difference from the previous Alignment. */ virtual int SetAlignmentXPos(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Set the drawing position (m_drawingX and m_drawingY) values for objects */ virtual int SetAlignmentPitchPos(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Set the drawing stem positions, including for beams. */ virtual int CalcStem(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Set the note head flipped positions */ virtual int CalcChordNoteHeads(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Set the drawing dot positions, including for chords. */ virtual int CalcDots(FunctorParams *) { return FUNCTOR_CONTINUE; } /** */ ///@{ virtual int AdjustArpeg(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int AdjustArpegEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Adjust the spacing for clef changes. */ virtual int AdjustClefChanges(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Adjust the position of the dots for multiple layers */ ///@{ virtual int AdjustDots(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int AdjustDotsEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Adjust the position the outside articulations. */ virtual int AdjustLayers(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * @name Lay out the X positions of the grace notes looking at the bounding boxes. * The functor is redirected from the MeasureAligner and then from the appropriate * alignment to the GraceAligner */ ///@{ virtual int AdjustGraceXPos(FunctorParams *) { return FUNCTOR_CONTINUE; }; virtual int AdjustGraceXPosEnd(FunctorParams *) { return FUNCTOR_CONTINUE; }; ///@} /** * @name Adjust the horizontal position of harms by groups in order to avoid overlapping */ ///@{ virtual int AdjustHarmGrpsSpacing(FunctorParams *) { return FUNCTOR_CONTINUE; }; virtual int AdjustHarmGrpsSpacingEnd(FunctorParams *) { return FUNCTOR_CONTINUE; }; ///@} /** * Adjust the x position of accidental. */ virtual int AdjustAccidX(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Adjust the x position of accidental. */ virtual int AdjustTempo(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * @name Adjust the x position of a right barline in order to make sure the is no text content * overlflowing in the right margin */ ///@{ virtual int AdjustXOverflow(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int AdjustXOverflowEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Lay out the X positions of the staff content looking at the bounding boxes. * The functor process by aligned-staff content, that is from a rediction in the * MeasureAligner and then staff by staff but taking into account cross-staff elements */ ///@{ virtual int AdjustXPos(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int AdjustXPosEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Adjust the spacing of the syl processing verse by verse */ ///@{ virtual int AdjustSylSpacing(FunctorParams *) { return FUNCTOR_CONTINUE; }; virtual int AdjustSylSpacingEnd(FunctorParams *) { return FUNCTOR_CONTINUE; }; ///@} /** * Calculate the x position of tuplet brackets and num */ virtual int AdjustTupletsX(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * @name Functors for aligning the content vertically. */ ///@{ /** * Reset the verticall alignment environment for various types for object. */ virtual int ResetVerticalAlignment(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Align vertically the content of a page. * For each Staff, instanciate its StaffAlignment. */ ///@{ virtual int AlignVertically(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int AlignVerticallyEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Set the note position for each note in ligature */ virtual int CalcLigatureNotePos(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Set the note head flipped positions and calc the ledger lines */ virtual int CalcLedgerLines(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Calcultate the position the outside articulations. */ virtual int CalcArtic(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Calculate the vertical position adjustment for the beam if it overlaps with layer elements */ virtual int AdjustBeams(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Apply position adjustment that has been calculated previously */ virtual int AdjustBeamsEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Adjust the postion position of slurs. */ virtual int AdjustSlurs(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Adjust the position the articulations. */ virtual int AdjustArtic(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Adjust the position the outside articulations with slur. */ virtual int AdjustArticWithSlurs(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * @name Adjust the position of cross-staff element after the adjustment of the staves. * This is called by Chords and Tuplets with cross-staff content */ ///@{ virtual int AdjustCrossStaffYPos(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int AdjustCrossStaffYPosEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Adjust the position of all floating positionners, staff by staff. */ virtual int AdjustFloatingPositioners(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Adjust the position of floating positionners placed between staves */ virtual int AdjustFloatingPositionersBetween(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Adjust the position of all floating positionner that are grouped, staff by staff. */ virtual int AdjustFloatingPositionerGrps(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Calculate the overlap of the staff aligmnents by looking at the overflow bounding boxes */ virtual int AdjustStaffOverlap(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Calculate the y position of tuplet brackets and num */ virtual int AdjustTupletsY(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Calculate the y relative position of tupletNum based on overlaps with other elements */ virtual int AdjustTupletNumOverlap(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Adjust the position of the StaffAlignment. */ virtual int AdjustYPos(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Fill the arrays of bounding boxes (above and below) for each staff alignment for which the box overflows. */ virtual int SetOverflowBBoxes(FunctorParams *functorParams); /** * Fill the arrays of bounding boxes (above and below) for each staff alignment for which the box overflows. */ virtual int SetOverflowBBoxesEnd(FunctorParams *functorParams); /** * @name Align the system by adjusting the m_drawingYRel position looking at the SystemAligner. */ ///@{ virtual int AlignSystems(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int AlignSystemsEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} ///@} /** * @name Functors for aligning the content vertically. */ ///@{ /** * Apply the Pixel Per Unit factor of the page to its elements. */ virtual int ApplyPPUFactor(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Adjust the X/YRel positions taking into account the bounding boxes */ virtual int AdjustXRelForTranscription(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * @name Functors setting the current scoreDef. */ ///@{ /** * Replace the drawing values a staffDef. * Set the current / drawing clef, key signature, etc. to the StaffDef * Called form ScoreDef::ReplaceDrawingValues. */ virtual int ReplaceDrawingValuesInStaffDef(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Set the current scoreDef wherever need. * This is include a scoreDef for each system. * It also includes a scoreDef for each measure where a change occured before. * A change can be either a scoreDef before or a clef, meterSig, etc. within the previous measure. */ virtual int ScoreDefSetCurrent(FunctorParams *functorParams); /** * Optimize the scoreDef for each system. * For automatic breaks, looks for staves with only mRests. */ ///@{ virtual int ScoreDefOptimize(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int ScoreDefOptimizeEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Set the cautionnary scoreDef wherever need. */ virtual int SetCautionaryScoreDef(FunctorParams *functorParams); /** * Unset the initial scoreDef of each system and measure */ virtual int ScoreDefUnsetCurrent(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Set drawing flags for the StaffDef for indicating whether clefs, keysigs, etc. need * to be redrawn. * This typically occurs when a new System or a new ScoreDef is encountered. * See implementation and Object::SetStaffDefRedrawFlags for the parameters. */ virtual int SetStaffDefRedrawFlags(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * @name Functors for preparing drawing */ ///@{ /** * Set the drawing cue size of all LayerElement */ virtual int PrepareDrawingCueSize(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * See cross-staff / layer pointers on LayerElement */ ///@{ virtual int PrepareCrossStaff(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int PrepareCrossStaffEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Prepare group symbol starting and ending staffDefs for drawing */ virtual int ScoreDefSetGrpSym(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Associate LayerElement with @facs to the appropriate zone */ virtual int PrepareFacsimile(FunctorParams *functorParams); /** * Match linking element (e.g, @next). */ ///@{ virtual int PrepareLinking(FunctorParams *functorParams); ///@} /** * Builds a tree of ints (IntTree) with the staff/layer/verse numbers and for staff/layer to be then processed. */ virtual int PrepareProcessingLists(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Match elements of @plist. */ ///@{ virtual int PreparePlist(FunctorParams *functorParams); ///@} /** * Match start for TimePointingInterface elements (such as fermata or harm). */ ///@{ virtual int PrepareTimePointing(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int PrepareTimePointingEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Match start and end for TimeSpanningInterface elements (such as tie or slur). * If fillList is set to false, only the remaining elements will be matched. * This is used when processing a second time in the other direction */ ///@{ virtual int PrepareTimeSpanning(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int PrepareTimeSpanningEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Match start and end for TimeSpanningInterface elements with tstamp(2) attributes. * It is performed only on TimeSpanningInterface elements withouth @startid (or @endid). * It adds to the start (and end) measure a TimeStampAttr to the Measure::m_tstamps. */ ///@{ virtual int PrepareTimestamps(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int PrepareTimestampsEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Process by Layer and set drawing pointers. * Set Dot::m_drawingNote for Dot elements in mensural mode */ virtual int PreparePointersByLayer(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Set wordpos and connector ends * The functor is processed by staff/layer/verse using an ArrayOfComparisons filter. * At the end, the functor is processed by doc at the end of a document of closing opened syl. */ ///@{ virtual int PrepareLyrics(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int PrepareLyricsEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Functor for setting the artic parts. * Splits the artic content into different artic parts if necessary */ virtual int PrepareLayerElementParts(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Functor for setting mRpt drawing numbers (if required) * The functor is processed by staff/layer using an ArrayOfComparisons filter. */ virtual int PrepareRpt(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Functor for setting Measure of Ending */ virtual int PrepareBoundaries(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * @name Functor for grouping FloatingObject by drawingGrpId. * Also chains the Dynam and Hairpin */ ///@{ virtual int PrepareFloatingGrps(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int PrepareFloatingGrpsEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Go through all the TimeSpanningInterface elements and set them a current to each staff * where required. For Note with DrawingTieAttr, the functor is redirected to the tie object. * At the end, remove the TimeSpanningInterface element from the list when the last measure is reached. */ ///@{ virtual int FillStaffCurrentTimeSpanning(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int FillStaffCurrentTimeSpanningEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Reset the drawing values before calling PrepareDrawing after changes. */ virtual int ResetDrawing(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Go through all layer elements of the layer and return next/previous element relative to the specified * layer element. It will search recursively through children elements until note, chord or ftrem is found. * It can be used to look in neighboring layers for the similar search, but only first element will be checked. */ virtual int GetRelativeLayerElement(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * @name Functors for justification */ ///@{ /** * Justify the X positions */ virtual int JustifyX(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Justify the Y positions */ virtual int JustifyY(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * @name Functors for calculating the layout of a document. */ ///@{ /** * Fill a page by adding systems with the appropriate length. * At the end, add all the pending objects where reaching the end */ ///@{ virtual int CastOffSystems(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int CastOffSystemsEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * */ virtual int CastOffPages(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Cast off the document according to the encoding provided (pb and sb) */ virtual int CastOffEncoding(FunctorParams *) { return FUNCTOR_CONTINUE; } /** * Undo the cast of both pages and system. * This is used by Doc::ContinuousLayout for putting all pages / systems continously. */ virtual int UnCastOff(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * @name Functors for generating MIDI output. */ ///@{ /** * Prepare Note onsets */ ///@{ virtual int CalcOnsetOffset(FunctorParams *) { return FUNCTOR_CONTINUE; } virtual int CalcOnsetOffsetEnd(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Adjust note timings based on ties */ ///@{ virtual int ResolveMIDITies(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Export the object to a MidiFile */ ///@{ virtual int GenerateMIDI(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Export the object to a JSON timemap file. */ ///@{ virtual int GenerateTimemap(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Calculate the maximum duration of each measure. */ virtual int CalcMaxMeasureDuration(FunctorParams *) { return FUNCTOR_CONTINUE; } ///@} /** * Reorder elements by x-position. */ virtual int ReorderByXPos(FunctorParams *); virtual int FindNextChildByComparison(FunctorParams *); virtual int FindPreviousChildByComparison(FunctorParams *); /** * Transpose the content. */ virtual int Transpose(FunctorParams *) { return FUNCTOR_CONTINUE; } protected: // private: /** * Method for generating the uuid. */ void GenerateUuid(); /** * Initialisation method taking a uuid prefix argument. */ void Init(const std::string &); public: /** * Keep an array of unsupported attributes as pairs. * This can be used for writing back data */ ArrayOfStrAttr m_unsupported; protected: // private: /** * A vector of child objects. * Unless SetAsReferenceObject is set or with detached and relinquished, the children are own by it. */ ArrayOfObjects m_children; /** * A pointer to the parent object; */ Object *m_parent; /** * Members for storing / generating uuids */ ///@{ std::string m_uuid; std::string m_classid; ///@} /** * A reference object do not own children. * Destructor will not delete them. */ bool m_isReferenceObject; /** * Indicates whether the object content is up-to-date or not. * This is useful for object using sub-lists of objects when drawing. * For example, Beam has a list of children notes and this value indicates if the * list needs to be updated or not. Is is mostly an optimization feature. */ mutable bool m_isModified; /** * Members used for caching iterator values. * See Object::IterGetFirst, Object::IterGetNext and Object::IterIsNotEnd * Values are set when GetFirst is called (which is mandatory) */ ///@{ ArrayOfObjects::iterator m_iteratorEnd, m_iteratorCurrent; ClassId m_iteratorElementType; ///@} /** * A vector for storing the list of AttClassId (MEI att classes) implemented. */ std::vector m_attClasses; /** * A vector for storing the list of InterfaceId (group of MEI att classes) implemented. */ std::vector m_interfaces; /** * String for storing a comments attached to the object when printing an MEI element. * m_comment is to be printed immediately before the element * m_closingComment is to be printed before the closing tag of the element */ std::string m_comment; std::string m_closingComment; ///@} /** * A flag indicating if the Object represents an attribute in the original MEI. * For example, a Artic child in Note for an original @artic */ bool m_isAttribute; /** * A flag indicating if the Object is a copy created by an expanded expansion element. */ bool m_isExpansion; //----------------// // Static members // //----------------// /** * A static counter for uuid generation. */ static thread_local unsigned long s_objectCounter; }; //---------------------------------------------------------------------------- // ObjectListInterface //---------------------------------------------------------------------------- /** * This class is an pseudo interface for elements maintaining a flat list of * children LayerElement for processing. * The list is a flatten list of pointers to children elements. * It is not an abstract class but should not be instanciated directly. */ class ObjectListInterface { public: // constructors and destructors ObjectListInterface(){}; virtual ~ObjectListInterface(){}; ObjectListInterface(const ObjectListInterface &listInterface); // copy constructor; ObjectListInterface &operator=(const ObjectListInterface &listInterface); // copy assignement; /** * Look for the Object in the list and return its position (-1 if not found) */ int GetListIndex(const Object *listElement); /** * Gets the first item of type elementType starting at startFrom */ Object *GetListFirst(const Object *startFrom, const ClassId classId = UNSPECIFIED); Object *GetListFirstBackward(Object *startFrom, const ClassId classId = UNSPECIFIED); /** * Returns the previous object in the list (NULL if not found) */ Object *GetListPrevious(Object *listElement); /** * Returns the next object in the list (NULL if not found) */ Object *GetListNext(Object *listElement); /** * Return the list. * Before returning the list, it checks that the list is up-to-date with Object::IsModified * If not, it updates the list and also calls FilterList. * Because this is an interface, we need to pass the object - not the best design. */ const ArrayOfObjects *GetList(Object *node); private: mutable ArrayOfObjects m_list; ArrayOfObjects::iterator m_iteratorCurrent; protected: /** * Filter the list for a specific class. * For example, keep only notes in Beam */ virtual void FilterList(ArrayOfObjects *childList){}; public: /** * Reset the list of children and call FilterList(). * As for GetList, we need to pass the object. */ void ResetList(Object *node); }; //---------------------------------------------------------------------------- // TextListInterface //---------------------------------------------------------------------------- /** * This class is an pseudo interface for elements maintaining a flat list of * children LayerElement for processing. * The list is a flatten list of pointers to children elements. * It is not an abstract class but should not be instanciate directly. */ class TextListInterface : public ObjectListInterface { public: // constructors and destructors TextListInterface(){}; virtual ~TextListInterface(){}; /** * Returns a contatenated version of all the text children */ std::wstring GetText(Object *node); /** * Fill an array of lines with concatenated content of each line */ void GetTextLines(Object *node, std::vector &lines); protected: /** * Filter the list for a specific class. * For example, keep only notes in Beam */ virtual void FilterList(ArrayOfObjects *childList); private: // public: // private: }; //---------------------------------------------------------------------------- // abstract base class Functor //---------------------------------------------------------------------------- /** * This class is an abstact Functor for the object hierarchy. * Needs testing. */ class Functor { private: int (Object::*obj_fpt)(FunctorParams *functorParams); // pointer to member function public: // constructor - takes pointer to an object and pointer to a member and stores // them in two private variables Functor(); Functor(int (Object::*_obj_fpt)(FunctorParams *)); virtual ~Functor(){}; // override function "Call" virtual void Call(Object *ptr, FunctorParams *functorParams); private: // public: /** * The return code of the functor. * FUNCTOR_CONTINUE: continue processing * FUNCTOR_SIBLINGS: process only siblings (do not go deeper) * FUNCTOR_STOP: stop the functor (e.g., when an Object or a value is found) */ int m_returnCode; /** * A flag for indicating if only visible Object have to be processed. * The value is true by default. */ bool m_visibleOnly; private: }; //---------------------------------------------------------------------------- // ObjectComparison //---------------------------------------------------------------------------- /** * Unary predicate for comparing object types. * This is used for example in std::find_if. * See Object::GetFirst or Object::GetNext */ class ObjectComparison { public: ObjectComparison(const ClassId classId) { m_classId = classId; } bool operator()(Object *object) { if (m_classId == UNSPECIFIED) { return true; } return (object->GetClassId() == m_classId); } private: // public: // private: ClassId m_classId; }; //---------------------------------------------------------------------------- // ObjectFactory //---------------------------------------------------------------------------- class ObjectFactory { public: /** * A static method returning a static object in order to guarantee initialisation */ static ObjectFactory *GetInstance(); /** * Create the object from the MEI element string name by making a lookup in the register */ Object *Create(std::string name); /** * Add the name / constructor map entry to the static register */ void Register(std::string name, ClassId classId, std::function function); /** * Get the correspondings ClassIds from the vector of MEI element string names */ void GetClassIds(const std::vector &classStrings, std::vector &classIds); public: MapOfStrConstructors s_ctorsRegistry; MapOfStrClassIds s_classIdsRegistry; }; //---------------------------------------------------------------------------- // ClassRegistrar //---------------------------------------------------------------------------- template class ClassRegistrar { public: /** * The contructor registering the name / constructor map */ ClassRegistrar(std::string name, ClassId classId) { ObjectFactory::GetInstance()->Register(name, classId, [](void) -> Object * { return new T(); }); } }; } // namespace vrv #endif