mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-02 12:37:02 +08:00
933 lines
23 KiB
C++
933 lines
23 KiB
C++
//
|
|
// Copyright (c) 1993-2022 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>.
|
|
//
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
#if !defined(OPENNURBS_TEXTITERATOR_INC_)
|
|
#define OPENNURBS_TEXTITERATOR_INC_
|
|
|
|
#define RTFFIRSTCHAR
|
|
|
|
typedef struct tagFontKey
|
|
{
|
|
int rtf_font_index;
|
|
const ON_Font* managed_font;
|
|
} ON_FontKey;
|
|
|
|
class ON_FaceNameKey
|
|
{
|
|
public:
|
|
int m_rtf_font_index = -1;
|
|
|
|
// In reality, the RTF "face" name can be
|
|
// a PostScript name, LOGFONT.lfFaceName, DWrite Family Name,
|
|
// and probably more. It depends on what tool is used to create the RTF and we see
|
|
// all three of the above names in Rhino parsing and the current Eto Text controls
|
|
// generate RTF with all three of those "names" OS version.
|
|
ON_wString m_rtf_font_name;
|
|
|
|
unsigned int m_codepage = 1252;
|
|
unsigned int m_charset = 0;
|
|
};
|
|
|
|
// Converts wchar_t characters to Unicode codepoints
|
|
class ON_TextIterator
|
|
{
|
|
private:
|
|
ON_TextIterator() = delete;
|
|
|
|
public:
|
|
ON_TextIterator(const ON_wString& str);
|
|
ON_TextIterator(const wchar_t* str, size_t length);
|
|
|
|
public:
|
|
~ON_TextIterator() = default;
|
|
ON_TextIterator(const ON_TextIterator&) = default;
|
|
ON_TextIterator& operator=(const ON_TextIterator&) = default;
|
|
|
|
/*
|
|
Parameters:
|
|
unicode_code_point - [out]
|
|
current unicode code point returned here.
|
|
0 = end of string
|
|
Returns:
|
|
true if returned unicode_code_point is not zero
|
|
*/
|
|
bool PeekCodePoint(ON__UINT32& unicode_code_point) const;
|
|
|
|
/*
|
|
Description:
|
|
Gets the current unicode code point and calls Step() to advance the text iterator
|
|
by one code point.
|
|
Parameters:
|
|
unicode_code_point - [out]
|
|
current unicode code point returned here.
|
|
0 = end of string
|
|
Returns:
|
|
true if returned unicode_code_point is not zero
|
|
*/
|
|
bool ReadCodePoint(ON__UINT32& unicode_code_point);
|
|
|
|
|
|
bool Back(); // move position back and return current codepoint after moving back
|
|
|
|
// Get the next UNICODE code point encoded in m_text beginning at m_text[m_next_text_ci];
|
|
// Save this code point in m_cur_codepoint.
|
|
// Advance m_next_text_ci.
|
|
bool Step();
|
|
|
|
bool AtBackslashTic() const;
|
|
bool ReadCharValue(
|
|
unsigned char& c
|
|
);
|
|
private:
|
|
|
|
const wchar_t* m_text = nullptr;
|
|
size_t m_length = 0;
|
|
size_t m_prev_text_ci = 0; // previous offset in m_text wchar_t string
|
|
size_t m_next_text_ci = 0; // previous offset in m_text wchar_t string
|
|
size_t m_cur_text_ci = 0; // current offset in m_text wchar_t string
|
|
ON__UINT32 m_prev_codepoint = 0; // previous UNICODE code point
|
|
ON__UINT32 m_cur_codepoint = 0; // UNICODE code point read by last call to Step()
|
|
struct ON_UnicodeErrorParameters m_ue = ON_UnicodeErrorParameters::MaskErrors;
|
|
};
|
|
|
|
class ON_TextBuilder
|
|
{
|
|
public:
|
|
ON_TextBuilder();
|
|
|
|
virtual ~ON_TextBuilder();
|
|
|
|
class TextProps
|
|
{
|
|
public:
|
|
TextProps()
|
|
{}
|
|
TextProps(
|
|
double height,
|
|
double stackscale,
|
|
ON_Color color,
|
|
ON_DimStyle::stack_format stackformat,
|
|
bool bold,
|
|
bool italic,
|
|
bool underlined,
|
|
bool strikethrough,
|
|
unsigned int charset)
|
|
: m_height(height)
|
|
, m_stackscale(stackscale)
|
|
, m_color(color)
|
|
, m_stackformat(stackformat)
|
|
, m_bold(bold)
|
|
, m_italic(italic)
|
|
, m_underlined(underlined)
|
|
, m_strikethrough(strikethrough)
|
|
, m_codepage(1252)
|
|
{}
|
|
double Height() const
|
|
{
|
|
return m_height;
|
|
}
|
|
void SetHeight(double h)
|
|
{
|
|
if (h > 1e-8)
|
|
m_height = h;
|
|
}
|
|
double StackScale() const
|
|
{
|
|
return m_stackscale;
|
|
}
|
|
void SetStackScale(double s)
|
|
{
|
|
if (0.0 < s && 10.0 > s)
|
|
m_stackscale = s;
|
|
}
|
|
ON_Color Color() const
|
|
{
|
|
return m_color;
|
|
}
|
|
void SetColor(ON_Color c)
|
|
{
|
|
m_color = c;
|
|
}
|
|
ON_DimStyle::stack_format StackFormat() const
|
|
{
|
|
return m_stackformat;
|
|
}
|
|
void SetStackFormat(ON_DimStyle::stack_format s)
|
|
{
|
|
m_stackformat = s;
|
|
}
|
|
bool IsBold()
|
|
{
|
|
return m_bold;
|
|
}
|
|
void SetBold(bool bold)
|
|
{
|
|
m_bold = bold;
|
|
}
|
|
bool IsItalic()
|
|
{
|
|
return m_italic;
|
|
}
|
|
void SetItalic(bool italic)
|
|
{
|
|
m_italic = italic;
|
|
}
|
|
bool IsUnderlined()
|
|
{
|
|
return m_underlined;
|
|
}
|
|
void SetUnderlined(bool underlined)
|
|
{
|
|
m_underlined = underlined;
|
|
}
|
|
bool IsStrikethrough()
|
|
{
|
|
return m_strikethrough;
|
|
}
|
|
void SetStrikethrough(bool strikethrough)
|
|
{
|
|
m_strikethrough = strikethrough;
|
|
}
|
|
unsigned int CodePage()
|
|
{
|
|
return m_codepage;
|
|
}
|
|
void SetCodePage(unsigned int codepage)
|
|
{
|
|
m_codepage = codepage;
|
|
}
|
|
|
|
unsigned int CharSet()
|
|
{
|
|
return m_charset;
|
|
}
|
|
void SetCharSet(unsigned int charset, bool setcodepage)
|
|
{
|
|
m_charset = charset;
|
|
if (setcodepage)
|
|
{
|
|
m_codepage = ON_MapRTFcharsetToWindowsCodePage(charset, 1252);
|
|
}
|
|
}
|
|
bool FormatPending()
|
|
{
|
|
return m_format_pending;
|
|
}
|
|
void SetFormatPending(bool b)
|
|
{
|
|
m_format_pending = b;
|
|
}
|
|
|
|
private:
|
|
double m_height = 1.0;
|
|
double m_stackscale = 0.7;
|
|
ON_Color m_color = ON_Color::Black;
|
|
ON_DimStyle::stack_format m_stackformat = ON_DimStyle::stack_format::StackHorizontal;
|
|
bool m_bold = false;
|
|
bool m_italic = false;
|
|
bool m_underlined = false;
|
|
bool m_strikethrough = false;
|
|
unsigned int m_codepage = 1252;
|
|
unsigned int m_charset = 0; // Charset isn't really needed but is here to make debugging a little easier
|
|
bool m_format_pending = false;
|
|
};
|
|
|
|
ON_ClassArray< TextProps > m_prop_stack;
|
|
TextProps m_current_props;
|
|
TextProps m_pending_props;
|
|
|
|
// Rtf uses UTF-16 encoding and surrogate pairs need to be properly handled.
|
|
// For example, the single UNICODE code point ON_UnicodeCodePoint::Wastebasket U+1F5D1 (decimal 128465)
|
|
// is in the RTF string as ...{\ltrch \u-10179?\u-8751?}...
|
|
// The UNICODE code point U+1F5D1 is encoded as a UTF-16 surrogate pair is (0xD83D, 0xDDD1).
|
|
// \u-10179? -> unsigned short 0xD83D
|
|
// \u-8751? -> unsigned short 0xDDD1
|
|
enum : ON__UINT16
|
|
{
|
|
m_UFT16_waiting_mark = 0xEEEE, // value must be > 0xE000 and uncommon unicode code point
|
|
m_UFT16_unused_mark = 0xFFFF // value must be > m_UFT16_waiting, <= 0xFFFF, and uncommon unicode code point
|
|
};
|
|
ON__INT32 m_current_UTF16_buffer_count = 0;
|
|
ON__UINT16 m_current_UTF16_buffer[2];
|
|
|
|
ON_SimpleArray< ON__UINT32 > m_current_codepoints;
|
|
ON__INT32 m_in_run;
|
|
ON__INT32 m_level = 0;
|
|
ON__INT32 m_font_table_level = 10000;
|
|
ON__INT32 m_font_index = 0;
|
|
ON__INT32 m_default_font_index = 0;
|
|
private:
|
|
bool m_bReadingFontDefinition = false;
|
|
public:
|
|
ON_ClassArray< ON_FaceNameKey > m_facename_map;
|
|
|
|
virtual void InitBuilder(const ON_Font* default_font);
|
|
virtual void FlushText(size_t count, ON__UINT32* cp_array);
|
|
virtual void GroupBegin();
|
|
virtual void GroupEnd();
|
|
virtual void RunBegin();
|
|
virtual void RunEnd();
|
|
virtual void FinishFontDef();
|
|
virtual bool ReadingFontTable();
|
|
virtual bool ReadingFontDefinition();
|
|
virtual void SetReadingFontDefinition(bool b);
|
|
|
|
|
|
virtual void BeginHeader();
|
|
virtual void BeginFontTable();
|
|
virtual void DefaultFont(const wchar_t* value);
|
|
virtual void FontTag(const wchar_t* value);
|
|
virtual void FontSize(const wchar_t* value);
|
|
virtual void CharSet(const wchar_t* value);
|
|
virtual void CodePage(const wchar_t* value);
|
|
|
|
virtual void Newline();
|
|
virtual void Paragraph();
|
|
virtual void ParagraphDefaults();
|
|
virtual void Section();
|
|
virtual void Tab();
|
|
|
|
virtual void Bold(const wchar_t* value);
|
|
virtual void Italic(const wchar_t* value);
|
|
virtual void UnderlineOn();
|
|
virtual void UnderlineOff();
|
|
virtual void Strikethrough(const wchar_t* value);
|
|
|
|
virtual void Superscript();
|
|
virtual void Subscript();
|
|
virtual void NoSuperSub();
|
|
|
|
virtual void BeginColorTable();
|
|
virtual void ColorRed(const wchar_t* value);
|
|
virtual void ColorGreen(const wchar_t* value);
|
|
virtual void ColorBlue(const wchar_t* value);
|
|
virtual void ColorForeground(const wchar_t* value);
|
|
virtual void ColorBackground(const wchar_t* value);
|
|
|
|
virtual void SetStackScale(const wchar_t* value);
|
|
virtual void StackFraction(const wchar_t* value);
|
|
virtual void StackEnd();
|
|
|
|
virtual void TextField(const wchar_t* name);
|
|
|
|
virtual void UniEmbeddedDest(const wchar_t* value);
|
|
virtual void UniDest(const wchar_t* value);
|
|
|
|
virtual void UniCpCount(const wchar_t* value);
|
|
virtual void UniDecimal(const wchar_t* value);
|
|
|
|
virtual void LQuote();
|
|
virtual void RQuote();
|
|
virtual void LDblQuote();
|
|
virtual void RDblQuote();
|
|
virtual void Bullet();
|
|
virtual void EnDash();
|
|
virtual void EmDash();
|
|
|
|
virtual bool AppendCodePoint(ON__UINT32 codept);
|
|
virtual void FormatChange();
|
|
|
|
ON__UINT32* RunCodePoints(const ON_TextRun& run);
|
|
|
|
const ON_wString FaceNameFromMap(int nval);
|
|
unsigned int CodePageFromMap(int nval);
|
|
unsigned int CharSetFromMap(int nval);
|
|
|
|
private:
|
|
ON_TextBuilder operator=(const ON_TextBuilder& src);
|
|
};
|
|
|
|
|
|
|
|
class ON_TextRunBuilder : public ON_TextBuilder
|
|
{
|
|
public:
|
|
ON_TextRunBuilder(
|
|
ON_TextContent& text,
|
|
ON_TextRunArray& runs,
|
|
const ON_DimStyle* dimstyle,
|
|
double height,
|
|
ON_Color color);
|
|
|
|
virtual ~ON_TextRunBuilder();
|
|
|
|
ON_SimpleArray< const ON_Font* > m_font_stack;
|
|
|
|
const ON_Font* CurrentFont() const
|
|
{
|
|
// Keep this as a simple one-liner that unconditionally returns m_private_current_font.
|
|
return m_private_current_font;
|
|
}
|
|
|
|
void SetCurrentFont(const ON_Font* font)
|
|
{
|
|
// Keep this as a simple one-liner that unconditionally sets m_private_current_font.
|
|
m_private_current_font = font;
|
|
}
|
|
|
|
private:
|
|
// Please, in order to keep people debugging sane, always use
|
|
// CurrentFont() / SetCurrentFont() and never directly
|
|
// set m_private_current_font.
|
|
const ON_Font* m_private_current_font = &ON_Font::Default;
|
|
|
|
public:
|
|
ON_TextRun m_current_run;
|
|
ON_TextRunArray& m_runs;
|
|
ON_TextContent& m_text;
|
|
|
|
void FinishCurrentRun();
|
|
void AppendCurrentRun();
|
|
|
|
void InitBuilder(const ON_Font* default_font) override;
|
|
void FlushText(size_t count, ON__UINT32* cp_array) override;
|
|
void GroupBegin() override;
|
|
void GroupEnd() override;
|
|
void RunBegin() override;
|
|
void RunEnd() override;
|
|
void FinishFontDef() override;
|
|
bool AppendCodePoint(ON__UINT32 codept) override;
|
|
void FormatChange() override;
|
|
|
|
void BeginHeader() override;
|
|
void BeginFontTable() override;
|
|
void DefaultFont(const wchar_t* value) override;
|
|
void FontTag(const wchar_t* value) override;
|
|
void FontSize(const wchar_t* value) override;
|
|
|
|
void Newline() override;
|
|
void Paragraph() override;
|
|
void ParagraphDefaults() override;
|
|
void Section() override;
|
|
void Tab() override;
|
|
|
|
void Bold(const wchar_t* value) override;
|
|
void Italic(const wchar_t* value) override;
|
|
void UnderlineOn() override;
|
|
void UnderlineOff() override;
|
|
void Strikethrough(const wchar_t* value) override;
|
|
|
|
void Superscript() override;
|
|
void Subscript() override;
|
|
void NoSuperSub() override;
|
|
|
|
void BeginColorTable() override;
|
|
void ColorRed(const wchar_t* value) override;
|
|
void ColorGreen(const wchar_t* value) override;
|
|
void ColorBlue(const wchar_t* value) override;
|
|
void ColorForeground(const wchar_t* value) override;
|
|
void ColorBackground(const wchar_t* value) override;
|
|
|
|
void SetStackScale(const wchar_t* value) override;
|
|
void StackFraction(const wchar_t* value) override;
|
|
void StackEnd() override;
|
|
|
|
void TextField(const wchar_t* name) override;
|
|
|
|
void UniEmbeddedDest(const wchar_t* value) override;
|
|
void UniDest(const wchar_t* value) override;
|
|
|
|
private:
|
|
ON_TextRunBuilder operator=(const ON_TextRunBuilder& src);
|
|
};
|
|
|
|
class ON_RtfStringBuilder : public ON_TextBuilder
|
|
{
|
|
public:
|
|
ON_RtfStringBuilder(
|
|
const ON_DimStyle* dimstyle,
|
|
double height,
|
|
ON_Color color);
|
|
|
|
virtual ~ON_RtfStringBuilder();
|
|
|
|
class TextRun
|
|
{
|
|
public:
|
|
TextRun() {}
|
|
|
|
ON_TextRun::RunType Type() const
|
|
{
|
|
return m_run_type;
|
|
}
|
|
void SetType(ON_TextRun::RunType type)
|
|
{
|
|
m_run_type = type;
|
|
}
|
|
void InitRun()
|
|
{
|
|
m_run_type = ON_TextRun::RunType::kNone;
|
|
m_font_index = -1;
|
|
m_text.Empty();
|
|
m_bold = false;
|
|
m_italic = false;
|
|
m_underlined = false;
|
|
m_strikethrough = false;
|
|
}
|
|
int FontIndex()
|
|
{
|
|
return m_font_index;
|
|
}
|
|
void SetFontIndex(int index)
|
|
{
|
|
if(index >= -1)
|
|
m_font_index = index;
|
|
}
|
|
|
|
bool IsBold() const
|
|
{
|
|
return m_bold;
|
|
}
|
|
bool IsItalic() const
|
|
{
|
|
return m_italic;
|
|
}
|
|
bool IsUnderlined() const
|
|
{
|
|
return m_underlined;
|
|
}
|
|
bool IsStrikeThrough() const
|
|
{
|
|
return m_strikethrough;
|
|
}
|
|
void SetBold(bool b)
|
|
{
|
|
m_bold = b;
|
|
}
|
|
void SetItalic(bool b)
|
|
{
|
|
m_italic = b;
|
|
}
|
|
void SetUnderlined(bool b)
|
|
{
|
|
m_underlined = b;
|
|
}
|
|
void SetStrikeThrough(bool b)
|
|
{
|
|
m_strikethrough = b;
|
|
}
|
|
|
|
void AddControl(const wchar_t* str)
|
|
{
|
|
m_text += str;
|
|
size_t i = wcslen(str);
|
|
if(str[i-1] == L' ' || str[i-1] == L'{' || str[i-1] == L'}')
|
|
m_terminated = true;
|
|
else
|
|
m_terminated = false;
|
|
m_has_content = true;
|
|
}
|
|
|
|
void AddText(const wchar_t* str)
|
|
{
|
|
if (!m_terminated)
|
|
m_text += L' ';
|
|
m_terminated = true;
|
|
m_text += str;
|
|
m_has_content = true;
|
|
}
|
|
|
|
void AddChar(const wchar_t ch)
|
|
{
|
|
if (!m_terminated)
|
|
m_text += L' ';
|
|
m_terminated = true;
|
|
m_text += ch;
|
|
m_has_content = true;
|
|
}
|
|
|
|
void SetTerminated(bool terminated)
|
|
{
|
|
m_terminated = terminated;
|
|
}
|
|
|
|
bool IsTerminated()
|
|
{
|
|
return m_terminated;
|
|
}
|
|
|
|
void EmptyText()
|
|
{
|
|
m_text = ON_wString::EmptyString;
|
|
}
|
|
|
|
const ON_wString& TextString()
|
|
{
|
|
return m_text;
|
|
}
|
|
|
|
const bool HasContent()
|
|
{
|
|
return m_has_content;
|
|
}
|
|
|
|
const void ClearHasContent()
|
|
{
|
|
m_has_content = false;
|
|
}
|
|
|
|
private:
|
|
bool m_has_content = false;
|
|
bool m_terminated = true;
|
|
ON_wString m_text;
|
|
bool m_bold = false;
|
|
bool m_italic = false;
|
|
bool m_underlined = false;
|
|
bool m_strikethrough = false;
|
|
int m_font_index = -1;
|
|
ON_TextRun::RunType m_run_type = ON_TextRun::RunType::kNone;
|
|
};
|
|
|
|
private:
|
|
ON_wString m_string_out;
|
|
bool m_in_font_table = false;
|
|
bool m_in_color_table = false;
|
|
|
|
bool m_skip_color_tbl = false;
|
|
bool m_skip_bold = false;
|
|
bool m_skip_italic = false;
|
|
bool m_skip_underline = false;
|
|
bool m_skip_facename = false;
|
|
|
|
bool m_make_bold = false;
|
|
bool m_make_italic = false;
|
|
bool m_make_underline = false;
|
|
bool m_make_facename = false;
|
|
|
|
ON_wString m_default_facename;
|
|
ON_wString m_override_facename;
|
|
|
|
bool m_have_rtf = false;
|
|
|
|
public:
|
|
|
|
TextRun m_current_run;
|
|
ON_ClassArray< TextRun > m_run_stack;
|
|
|
|
void InitStringBuilder(const ON_DimStyle* default_style);
|
|
const ON_wString OutputString();
|
|
void PushRun(TextRun& run);
|
|
TextRun PopRun();
|
|
|
|
//bool InFontTable();
|
|
//void SetInFontTable(bool b);
|
|
bool InColorTable();
|
|
void SetInColorTable(bool b);
|
|
|
|
void SetSkipColorTbl(bool b);
|
|
void SetSkipBold(bool b);
|
|
void SetSkipItalic(bool b);
|
|
void SetSkipUnderline(bool b);
|
|
void SetSkipFacename(bool b);
|
|
|
|
bool SkipColorTbl();
|
|
bool SkipBold();
|
|
bool SkipItalic();
|
|
bool SkipUnderline();
|
|
bool SkipFacename();
|
|
|
|
void SetMakeBold(bool b);
|
|
void SetMakeItalic(bool b);
|
|
void SetMakeUnderline(bool b);
|
|
void SetMakeFacename(bool b);
|
|
|
|
bool MakeBold();
|
|
bool MakeItalic();
|
|
bool MakeUnderline();
|
|
bool MakeFacename();
|
|
|
|
bool SkippingFacename();
|
|
bool SettingFacename();
|
|
|
|
void SetDefaultFacename(const wchar_t* facename);
|
|
void SetOverrideFacename(const wchar_t* facename);
|
|
|
|
// virtuals
|
|
|
|
void GroupBegin() override;
|
|
void GroupEnd() override;
|
|
void RunBegin() override;
|
|
void RunEnd() override;
|
|
|
|
void BeginHeader() override;
|
|
void BeginFontTable() override;
|
|
void DefaultFont(const wchar_t* value) override;
|
|
void FontTag(const wchar_t* value) override;
|
|
void FontSize(const wchar_t* value) override;
|
|
|
|
void Newline() override;
|
|
void Paragraph() override;
|
|
void ParagraphDefaults() override;
|
|
void Section() override;
|
|
void Tab() override;
|
|
|
|
void Bold(const wchar_t* value) override;
|
|
void Italic(const wchar_t* value) override;
|
|
void UnderlineOn() override;
|
|
void UnderlineOff() override;
|
|
void Strikethrough(const wchar_t* value) override;
|
|
|
|
void Superscript() override;
|
|
void Subscript() override;
|
|
void NoSuperSub() override;
|
|
|
|
void BeginColorTable() override;
|
|
void ColorRed(const wchar_t* value) override;
|
|
void ColorGreen(const wchar_t* value) override;
|
|
void ColorBlue(const wchar_t* value) override;
|
|
void ColorForeground(const wchar_t* value) override;
|
|
void ColorBackground(const wchar_t* value) override;
|
|
|
|
void TextField(const wchar_t* name) override;
|
|
|
|
bool AppendCodePoint(ON__UINT32 codept) override;
|
|
|
|
void UniEmbeddedDest(const wchar_t* value) override;
|
|
void UniDecimal(const wchar_t* value) override;
|
|
void UniDest(const wchar_t* value) override;
|
|
|
|
private:
|
|
ON_RtfStringBuilder operator=(const ON_RtfStringBuilder& src);
|
|
};
|
|
|
|
#ifdef RTFFIRSTCHAR
|
|
|
|
class ON_RtfFirstChar : public ON_TextBuilder
|
|
{
|
|
public:
|
|
ON_RtfFirstChar(
|
|
const ON_DimStyle* dimstyle,
|
|
double height,
|
|
ON_Color color);
|
|
|
|
virtual ~ON_RtfFirstChar();
|
|
|
|
class TextRun
|
|
{
|
|
public:
|
|
TextRun() {}
|
|
|
|
ON_TextRun::RunType Type() const
|
|
{
|
|
return m_run_type;
|
|
}
|
|
void SetType(ON_TextRun::RunType type)
|
|
{
|
|
m_run_type = type;
|
|
}
|
|
void InitRun()
|
|
{
|
|
m_run_type = ON_TextRun::RunType::kNone;
|
|
m_font_index = -1;
|
|
m_text.Empty();
|
|
m_bold = false;
|
|
m_italic = false;
|
|
m_underlined = false;
|
|
m_strikethrough = false;
|
|
}
|
|
int FontIndex()
|
|
{
|
|
return m_font_index;
|
|
}
|
|
void SetFontIndex(int index)
|
|
{
|
|
if (index >= -1)
|
|
m_font_index = index;
|
|
}
|
|
|
|
bool IsBold() const
|
|
{
|
|
return m_bold;
|
|
}
|
|
bool IsItalic() const
|
|
{
|
|
return m_italic;
|
|
}
|
|
bool IsUnderlined() const
|
|
{
|
|
return m_underlined;
|
|
}
|
|
bool IsStrikeThrough() const
|
|
{
|
|
return m_strikethrough;
|
|
}
|
|
void SetBold(bool b)
|
|
{
|
|
m_bold = b;
|
|
}
|
|
void SetItalic(bool b)
|
|
{
|
|
m_italic = b;
|
|
}
|
|
void SetUnderlined(bool b)
|
|
{
|
|
m_underlined = b;
|
|
}
|
|
void SetStrikeThrough(bool b)
|
|
{
|
|
m_strikethrough = b;
|
|
}
|
|
|
|
void AddText(const wchar_t* str)
|
|
{
|
|
if (!m_terminated)
|
|
m_text += L' ';
|
|
m_terminated = true;
|
|
m_text += str;
|
|
m_has_content = true;
|
|
}
|
|
|
|
const ON_wString& Text()
|
|
{
|
|
return m_text;
|
|
}
|
|
|
|
private:
|
|
bool m_has_content = false;
|
|
bool m_terminated = true;
|
|
ON_wString m_text;
|
|
bool m_bold = false;
|
|
bool m_italic = false;
|
|
bool m_underlined = false;
|
|
bool m_strikethrough = false;
|
|
int m_font_index = -1;
|
|
ON_TextRun::RunType m_run_type = ON_TextRun::RunType::kNone;
|
|
};
|
|
|
|
private:
|
|
bool m_in_font_table = false;
|
|
bool m_in_color_table = false;
|
|
|
|
bool m_have_rtf = false;
|
|
|
|
public:
|
|
|
|
TextRun m_current_run;
|
|
ON_ClassArray< TextRun > m_run_stack;
|
|
|
|
void InitStringBuilder(const ON_DimStyle* default_style);
|
|
const ON_wString OutputString();
|
|
void PushRun(TextRun& run);
|
|
TextRun PopRun();
|
|
|
|
//bool InFontTable();
|
|
//void SetInFontTable(bool b);
|
|
bool InColorTable();
|
|
void SetInColorTable(bool b);
|
|
|
|
// virtuals
|
|
|
|
void GroupBegin() override;
|
|
void GroupEnd() override;
|
|
void RunBegin() override;
|
|
void RunEnd() override;
|
|
|
|
void BeginHeader() override;
|
|
void BeginFontTable() override;
|
|
void BeginColorTable() override;
|
|
void TextField(const wchar_t* name) override;
|
|
bool AppendCodePoint(ON__UINT32 codept) override;
|
|
|
|
void FontTag(const wchar_t* value) override;
|
|
|
|
void Bold(const wchar_t* value) override;
|
|
void Italic(const wchar_t* value) override;
|
|
void UnderlineOn() override;
|
|
void UnderlineOff() override;
|
|
void Strikethrough(const wchar_t* value) override;
|
|
|
|
private:
|
|
ON_RtfFirstChar operator=(const ON_RtfFirstChar& src);
|
|
};
|
|
|
|
#endif
|
|
|
|
class ON_RtfParser
|
|
{
|
|
public:
|
|
ON_RtfParser(ON_TextIterator& iter, ON_TextBuilder& builder);
|
|
bool Parse();
|
|
|
|
private:
|
|
ON__UINT32 Internal_ParseMBCSString(
|
|
const ON__UINT32 windows_code_page
|
|
);
|
|
|
|
ON_TextIterator& m_ti;
|
|
|
|
ON_TextBuilder& m_builder;
|
|
int m_p_level = 0;
|
|
bool m_in_real_rtf = false;
|
|
// suspend to close means ignore everything until the current group is closed
|
|
// It's used to skip over commands and parameters in optional tags
|
|
int m_suspend_to_close = 0;
|
|
|
|
bool FlushCurText(ON_SimpleArray< ON__UINT32 >& cp_array);
|
|
bool ReadTag(bool optional);
|
|
bool ReadOptionalTag();
|
|
bool ProcessTag(const wchar_t* name, const wchar_t* value, bool optional);
|
|
|
|
ON_RtfParser operator=(const ON_RtfParser& src);
|
|
};
|
|
|
|
class ON_CLASS RtfComposer
|
|
{
|
|
public:
|
|
class RunInfo
|
|
{
|
|
public:
|
|
ON_TextRun::RunType m_run_type = ON_TextRun::RunType::kNone;
|
|
ON_TextRun* m_text_run = nullptr;
|
|
ON_wString m_run_text;
|
|
bool m_bold = false;
|
|
bool m_italic = false;
|
|
bool m_underline = false;
|
|
bool m_strikeout = false;
|
|
ON_wString m_facename = L"Arial";
|
|
int m_facename_key = -1;
|
|
};
|
|
|
|
static bool Compose(
|
|
const ON_TextContent* text,
|
|
ON_wString& rtf,
|
|
bool bForceRtf);
|
|
|
|
static const ON_wString ComposeAppleRTF(
|
|
const ON_TextContent* text);
|
|
|
|
static bool RecomposeRTF();
|
|
static void SetRecomposeRTF(bool b);
|
|
|
|
static bool ComposeFS();
|
|
static void SetComposeFS(bool b);
|
|
static int TextEditorFontSize();
|
|
static void SetTextEditorFontSize(unsigned int size);
|
|
|
|
|
|
private:
|
|
static bool m_bComposeRTF;
|
|
static bool m_bComposeFS;
|
|
static int m_TextEditorSize;
|
|
|
|
RtfComposer();
|
|
|
|
static unsigned int GetFacenameKey(const ON_Font* font, ON_ClassArray< ON_wString >& fonttable);
|
|
static unsigned int GetFacenameKey(const wchar_t* facename, ON_ClassArray< ON_wString >& fonttable);
|
|
static unsigned int GetColorKey(ON_Color color, ON_SimpleArray< unsigned int >& colortable);
|
|
static bool FormatTextHeight(double height, ON_wString& str);
|
|
};
|
|
|
|
|
|
#endif
|
|
|