/* $NoKeywords: $ */ /* // // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved. // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert // McNeel & Associates. // // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF // MERCHANTABILITY ARE HEREBY DISCLAIMED. // // For complete openNURBS copyright information see . // //////////////////////////////////////////////////////////////// */ #ifndef OPENNURBS_TEXT_H_INCLUDED #define OPENNURBS_TEXT_H_INCLUDED #if defined(ON_DLL_TEMPLATE) ON_DLL_TEMPLATE template ON_ClassArray< class ON_Font >; ON_DLL_TEMPLATE template ON_SimpleArray< class ON_TextRun* >; ON_DLL_TEMPLATE template ON_SimpleArray< class ON_FontGlyph* >; #endif #define ON_TEXT_BRACKET_FRACTION class ON_CLASS ON_TextContent : public ON_Geometry { ON_OBJECT_DECLARE(ON_TextContent); public: static const ON_TextContent Empty; public: ON_TextContent()= default; ~ON_TextContent(); ON_TextContent(const ON_TextContent& src); ON_TextContent& operator=(const ON_TextContent& src); private: void Internal_Destroy(); void Internal_CopyFrom( const ON_TextContent& src ); public: /* Returns: A hash of the information that determines the text content using wrapped text with evaluated fields. */ ON_SHA1_Hash TextContentHash() const; /* Parameters: bApplyWrapping - [in] true - hash wrapped text false - has unwrapped text bEvaluateFields - [in] true - hash text with fields evaluated false - hash text with fields unevaluated Returns: A hash of the information that determines the text content without evaluating the fields. */ ON_SHA1_Hash TextContentHash( bool bApplyWrapping, bool bEvaluateFields ) const; public: bool IsValid( class ON_TextLog* text_log = nullptr ) const override; // Parses text string and makes runs bool Create( const wchar_t* RtfString, ON::AnnotationType annotation_type, // used to select type specific dimstyle properties like text alignment settings const ON_DimStyle* dimstyle, bool bWrapped, double rect_width, double text_rotation_radians ); bool Create( const wchar_t* RtfString, ON::AnnotationType annotation_type, // used to select type specific dimstyle properties like text alignment settings const ON_DimStyle* dimstyle ); bool ReplaceTextString( const wchar_t* RtfString, ON::AnnotationType annotation_type, // used to select type specific dimstyle properties like text alignment settings const ON_DimStyle* dimstyle ); bool RebuildRuns( ON::AnnotationType annotation_type, const ON_DimStyle* dimstyle ); /* Returns: The value of ON_DimStyle.TextPositionPropertiesHash() of the ON_DimStyle passed to Create(), ReplaceTextString(), or RebuildRuns(). */ ON_SHA1_Hash DimStyleTextPositionPropertiesHash() const; /* Returns: True if this text position information used to create this text is identical to the text position paramters on dimstyle. */ bool EqualTextPositionProperties( ON::AnnotationType annotation_type, const class ON_DimStyle* dimstyle ) const; bool GetGlyphContours( const ON_Font* text_font, bool bSingleStrokeFont, double text_height, ON_ClassArray< ON_ClassArray< ON_SimpleArray< ON_Curve* > > >& text_contours ) const; bool GetGlyphContours( const ON_Font* text_font, bool bSingleStrokeFont, const ON_Xform& text_xform, ON_ClassArray< ON_ClassArray< ON_SimpleArray< ON_Curve* > > >& text_contours ) const; private: static ON::AnnotationType Internal_AlignmentAnnotationType( ON::AnnotationType annotation_type ); private: bool Internal_SetText( const wchar_t* text, const ON_DimStyle* dimstyle); /* Parameters: dim_style - [in] Parse and compose text using the parameters in this dimstyle. If nullptr, then ON_DimStyle::Default is used as the dimstyle. bComposeAndUpdateRtf - [in] If true, then the parsed runs are passed to RtfComposer::Compose() to compose create an efficient and compressed rtf. Then ON_TextContent.m_text is set to the efficient and compressed rtf returned from RtfComposer::Compose(). When this->m_text might be a bloated result from a text editing control or a simple string like "Hello world" set during construction, then bComposeAndUpdateRtf should be true. When this->m_text has already been through RtfComposer::Compose() and you simply need to create the runs from m_text, then bComposeAndUpdateRtf should be false. Reading binary archives is one case when bComposeAndUpdateRtf should be false. Internal_ParseRtf() sets the m_dimstyle_text_position_properties_hash member on ON_TextContent */ bool Internal_ParseRtf( const wchar_t* rtf_string, const ON_DimStyle* dim_style, bool bComposeAndUpdateRtf ); bool Internal_ParseRtfDefault( const wchar_t* rtf_string, bool bComposeAndUpdateRtf ); public: /* Returns: Raw text that can contain rich text formatting instructions. Fields are not evaluated. */ const ON_wString RichText() const; /* Returns: Plain text information with any rich text formatting instructions removed. The result string from evaluating fields is included Field results may be cached from previous evaluation */ const ON_wString PlainText() const; /* Same as PlainText() but separated wrapped run lines with '\n' for soft return and '\r''\n' for hard returns */ const ON_wString WrappedPlainText() const; /* Returns: Plain text information with any rich text formatting instructions removed. Fields are not evaluated */ const ON_wString PlainTextWithFields() const; /* Same as PlainTextWithFields() but separated wrapped run lines with '\n' for soft return and '\r''\n' for hard returns */ const ON_wString WrappedPlainTextWithFields() const; private: void Internal_SetRunTextHeight(double height); public: void GetAlignment(ON::TextHorizontalAlignment& horz, ON::TextVerticalAlignment& vert) const; void SetAlignment(ON::TextHorizontalAlignment horz, ON::TextVerticalAlignment vert); // FormattingRectangleWidth is a width set by text wrapping. It's in model units double FormattingRectangleWidth() const; void SetFormattingRectangleWidth(double width); // Rotation in radians around origin double TextRotationRadians() const; void SetTextRotationRadians(double rotation); // Rotation in degrees around origin double TextRotationDegrees() const; void SetTextRotationDegrees(double rotation); unsigned int EvaluationSerialNumber() const; void SetEvaluationSerialNumber(unsigned int sn) const; void RealignTextRuns(ON::TextHorizontalAlignment new_h_align); // virtual void Dump( ON_TextLog& ) const override; // for debugging int Dimension() const override; ON::object_type ObjectType() const override; bool Write( ON_BinaryArchive& // serialize definition to binary archive ) const override; bool Read( ON_BinaryArchive& // restore definition from binary archive ) override; const ON_BoundingBox TextContentBoundingBox() const; // virtual ON_Geometry GetBBox override bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override; void ClearBoundingBox() override; bool Transform(const ON_Xform& xform) override; // Wrap text to a specified width in model space bool WrapText(double width) const; // True if text has wrapped runs, else false bool HasWrappedRuns() const; // True if flag to wrap is set bool TextIsWrapped() const; void SetTextIsWrapped(bool wrapped); private: void Internal_DeleteWrappedRuns() const; const ON_wString Internal_GetPlainText(bool evaluate_fields, bool wrapped) const; public: // Get the size of a 2d rectangle enclosing text bool Get2dSize(bool raw, double& width, double& height) const; // Get corners of the whole text object // corners requires space for 4 points bool Get2dCorners(ON_2dPoint corners[4]) const; // Get corners of the whole text object // corners requires space for 4 points // Basic size of text, not including annotation scaling or 2d rotation // And rotated and translated in 3d to text's plane (not object's plane) bool Get3dCorners(ON_3dPoint corners[4]) const; // Get corners of the whole text object // inflated by the border distance for mask drawing // corners requires space for 4 points bool Get3dMaskCorners(double border, ON_3dPoint corners[4]) const; // Gets endpoints of a line under the text offset down by textgap bool Get3dUnderline(ON_3dPoint ends[2], double scaled_gap) const; // Get corners of individual runs // corners requires space for 4 points bool GetRun3dCorners(const ON_TextRun* run, ON_3dPoint corners[4]) const; // returns the base point and with grip using the current alignments void GetGripPoints(ON_2dPoint& base, ON_2dPoint& width) const; ON_Mesh* Get2dPickMesh() const; ON_Mesh* Get3dPickMesh() const; // Returns pointer to either m_runs, the basic parsed and evaluated text // or m_wrapped_runs which is the runs after text wrapping // m_wrapped_runs will be null unless the text has been wrapped // If raw is false and m_wrapped_runs is not null, m_wrapped_runs will be returned // If raw is true or m_wrapped_runs is null, m_runs will be returned ON_TextRunArray* TextRuns(bool bRaw) const; const wchar_t* RtfText() const; /* With runs in place, compose the text in the runs and fill in the Text's string that is returned by RtfText */ bool ComposeText(); ///* //Parameters: // dimsytle - [in] //Returns: // true if style was passed as dimstyle paramter to Create(), ReplaceTextString(), // or RebuildRuns() and used to create the current text runs. //*/ //bool IsCurrentDimStyle( // const ON_DimStyle* dimsytle //) const; //void SetCurrentDimStyle(const ON_DimStyle* dimstyle) const; private: // Data members //----------------------- ON_wString m_text; // Rtf laden string double m_rect_width = 1.0e300; // formatting rectangle width in model units double m_rotation_radians = 0.0; // radians rotation around origin double m_reserved_dbl = 0.0; ON::TextHorizontalAlignment m_h_align = ON::TextHorizontalAlignment::Left; // Left, Center, Right ON::TextVerticalAlignment m_v_align = ON::TextVerticalAlignment::Bottom; // Top, Middle, Bottom // true when text is wrapped // Set by calling WrapText() or SetTextIsWrapped(true). // Query by calling TextIsWrapped(). mutable bool m_bWrapText = false; // m__runs and m__wrapped_runs are runtime information // generated by parsing m_text and other information. mutable ON_TextRunArray m__runs; mutable ON_TextRunArray* m__wrapped_runs = nullptr; // display cache runtime value mutable unsigned int m_run_evaluation_sn = 0; // annotation type used to select dimstyle text alignment settings. mutable ON::AnnotationType m_annotation_type = ON::AnnotationType::Unset; // dimstyle text position properties used to calculate the runs mutable ON_SHA1_Hash m_dimstyle_text_position_properties_hash = ON_SHA1_Hash::ZeroDigest; // hash of m_text, m_bWrapping, m_rect_width, m_rotation_radians, alignment mutable ON_SHA1_Hash m_text_content_sub_hash = ON_SHA1_Hash::ZeroDigest; ON_SHA1_Hash Internal_TextContentSubHash() const; void Internal_ClearTextContentHash() const; // runtime bounding box // Value of TextContentHash() when m_text_content_bbox was set. mutable ON_SHA1_Hash m_text_content_bbox_hash = ON_SHA1_Hash::ZeroDigest; mutable ON_BoundingBox m_text_content_bbox = ON_BoundingBox::EmptyBoundingBox; ON__INT_PTR m_reserved0 = (ON__INT_PTR)0; public: friend class ON_Text; /* Description: Calculates the size, spacing and position of the runs in the ON_TextContent Parameters: [in/out] ON_TextContent& text - Text to measure. Modified to store results [in] bool raw - if true, measure m_runs [in] bool wrapped - if true, measure m_wrapped_runs Returns: true = Success false = Failure Remarks: The runs in the text are modified to store the location info for positioning within the text object */ static bool MeasureTextContent(ON_TextContent* text, bool raw, bool wrapped); /* Description: Calculates the size, spacing and position of the runs in the ON_TextRunArray Parameters: [in/out] ON_TextRunArray* runs - TextRuns to measure. Modified to store results [in] ON::TextVerticalAlignment v_align - how to align the text [in] ON::TextHorizontalAlignment h_align) Returns: true = Success false = Failure Remarks: The runs in the text are modified to store the location info for positioning within the text object */ static bool MeasureTextRunArray( ON_TextRunArray* runs, ON::TextVerticalAlignment v_align, ON::TextHorizontalAlignment h_align); /* Description: Calculates the size, spacing and position of the ON_TextRun within an ON_TextContent object Parameters: [in/out] ON_TextRun& run - Run to measure. Modified to store results Returns: true = Success false = Failure Remarks: The runs in the text are modified to store the location info for positioning within the text object */ static bool MeasureTextRun(ON_TextRun* run); static bool CreateStackedText(ON_TextRun* run); static bool CreateStackedText( ON_TextRun* run, int cpcount, const ON__UINT32* cp, ON__UINT32 stack_delimiter = L'/'); /* Replaces runs[i] with stacked runs if any "[[xx/xx]]" strings are found in wstr Returns the number of runs added to the array */ static int FindAndStackFractions(ON_TextRunArray* runs, int i, ON_wString wstr); /* Description: Evaluates the field instructions in the run and puts the results in run->m_display_string. Parameters: [in/out] ON_TextRun& run - Run to evsluste. Modified to store results Returns: true = Success false = Failure Remarks: The runs in the text are modified to store the string result of evaluating any fields in the run m_string or m_codepoints */ static bool EvaluateField(ON_TextRun* run); /* Description: Returns the height in model units of the run, including text height and inter-line spacing */ static double GetLinefeedHeight(ON_TextRun& run); const ON_Font* FirstCharFont() const; // Dimension text formatting static bool FormatDistance( double distance, ON::LengthUnitSystem units_in, const ON_DimStyle* dimstyle, bool alternate, // Primary or alternate ON_wString& formatted_string); // Output static bool FormatTolerance( double distance, ON::LengthUnitSystem units_in, const ON_DimStyle* dimstyle, bool alternate, // Primary or alternate ON_wString& formatted_string); // Output static bool FormatDistanceAndTolerance( double distance, ON::LengthUnitSystem units_in, const ON_DimStyle* dimstyle, bool alternate, // Primary or alternate ON_wString& formatted_string); // Output static bool FormatDistanceMeasurement( double distance_in, ON::LengthUnitSystem units_in, const ON_DimStyle* dimstyle, const wchar_t* user_text, // Replace "<>" in user_text with formatted dimension ON_wString& formatted_string); // Output static bool FormatAngleMeasurement( double angle, const ON_DimStyle* dimstyle, // Angle format comes from dimstyle const wchar_t* user_text, ON_wString& formatted_string); }; #endif