Files
opennurbs/opennurbs_text.h
2019-04-09 10:11:17 -07:00

508 lines
16 KiB
C++

/* $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 <http://www.opennurbs.org>.
//
////////////////////////////////////////////////////////////////
*/
#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