Markup parser fix: subscript/superscript/overbar handling

This commit is contained in:
Ola Rinta-Koski 2022-02-08 18:50:53 +00:00 committed by jean-pierre charras
parent 58c38d2830
commit 44c93e48e9
3 changed files with 73 additions and 64 deletions

View File

@ -196,35 +196,37 @@ VECTOR2I drawMarkup( BOX2I* aBoundingBox, std::vector<std::unique_ptr<GLYPH>>* a
{
VECTOR2I nextPosition = aPosition;
TEXT_STYLE_FLAGS textStyle = aTextStyle;
if( aNode ) {
TEXT_STYLE_FLAGS textStyle = aTextStyle;
if( !aNode->is_root() )
{
if( aNode->isSubscript() )
textStyle = TEXT_STYLE::SUBSCRIPT;
else if( aNode->isSuperscript() )
textStyle = TEXT_STYLE::SUPERSCRIPT;
if( aNode->isOverbar() )
textStyle |= TEXT_STYLE::OVERBAR;
if( aNode->has_content() )
if( !aNode->is_root() )
{
std::string txt = aNode->string();
BOX2I bbox;
if( aNode->isSubscript() )
textStyle = TEXT_STYLE::SUBSCRIPT;
else if( aNode->isSuperscript() )
textStyle = TEXT_STYLE::SUPERSCRIPT;
nextPosition = aFont->GetTextAsGlyphs( &bbox, aGlyphs, txt, aSize, aPosition, aAngle,
aMirror, aOrigin, textStyle );
if( aNode->isOverbar() )
textStyle |= TEXT_STYLE::OVERBAR;
if( aBoundingBox )
aBoundingBox->Merge( bbox );
if( aNode->has_content() )
{
std::string txt = aNode->string();
BOX2I bbox;
nextPosition = aFont->GetTextAsGlyphs( &bbox, aGlyphs, txt, aSize, aPosition, aAngle,
aMirror, aOrigin, textStyle );
if( aBoundingBox )
aBoundingBox->Merge( bbox );
}
}
}
for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
{
nextPosition = drawMarkup( aBoundingBox, aGlyphs, child, nextPosition, aFont, aSize,
aAngle, aMirror, aOrigin, textStyle );
for( const std::unique_ptr<MARKUP::NODE>& child : aNode->children )
{
nextPosition = drawMarkup( aBoundingBox, aGlyphs, child, nextPosition, aFont, aSize,
aAngle, aMirror, aOrigin, textStyle );
}
}
return nextPosition;

View File

@ -27,9 +27,17 @@ using namespace MARKUP;
std::unique_ptr<NODE> MARKUP_PARSER::Parse()
{
//string_input<> in( source, "from_input" );
auto root = parse_tree::parse<MARKUP::grammar, MARKUP::NODE, MARKUP::selector>( in );
return root;
try
{
auto root = parse_tree::parse<MARKUP::grammar, MARKUP::NODE, MARKUP::selector>( in );
return root;
}
catch ( tao::pegtl::parse_error& parseError )
{
// couldn't parse text item
// TODO message to user?
return nullptr;
}
}
@ -39,6 +47,7 @@ std::string NODE::typeString() const
if( is_type<MARKUP::subscript>() ) os << "SUBSCRIPT";
else if( is_type<MARKUP::superscript>() ) os << "SUPERSCRIPT";
else if( is_type<MARKUP::overbar>() ) os << "OVERBAR";
else if( is_type<MARKUP::anyString>() ) os << "ANYSTRING";
else if( is_type<MARKUP::anyStringWithinBraces>() ) os << "ANYSTRINGWITHINBRACES";
else if( is_type<MARKUP::varNamespaceName>() ) os << "VARNAMESPACENAME";

View File

@ -47,66 +47,64 @@ struct NODE : parse_tree::basic_node<NODE>
bool isSuperscript() const { return is_type<MARKUP::superscript>(); }
};
struct varPrefix : string<'$', '{'> {};
struct subPrefix : string<'_', '{'> {};
struct supPrefix : string<'^', '{'> {};
struct tildePrefix : string<'~', '{'> {};
struct closeBrace : string<'}'> {};
struct varName : plus<sor<identifier_other, string<' '>>> {};
struct varNamespaceName : plus<identifier> {};
struct varNamespace : seq<varNamespaceName, string<':'>> {};
struct variable : seq<varPrefix, opt<varNamespace>, varName, closeBrace> {};
struct variable : seq< string< '$', '{' >, opt<varNamespace>, varName, string< '}' > > {};
template< typename ControlChar >
struct plain : seq< not_at< seq< ControlChar, string< '{' > > >, ControlChar > {};
struct plainControlChar : sor< plain< string<'$'> >,
plain< string<'_'> >,
plain< string<'^'> >,
plain< string<'~'> > > {};
/**
* anyString =
* a run of characters that do not start a command sequence, or if they do, they do not start
* a complete command prefix (command char + open brace)
*/
struct anyString : plus<sor<utf8::not_one<'~', '$', '_', '^'>,
seq<not_at<subPrefix>, string<'_'>>,
seq<not_at<supPrefix>, string<'^'>>,
seq<not_at<tildePrefix>, string<'~'>>>> {};
struct anyString : plus< sor< utf8::not_one< '~', '$', '_', '^' >,
plainControlChar > > {};
struct prefixedSuperscript : seq<supPrefix, superscript> {};
struct anyStringWithinBraces : plus< sor< utf8::not_one< '~', '$', '_', '^', '}' >,
plainControlChar > > {};
struct prefixedSubscript : seq<subPrefix, subscript> {};
template< typename ControlChar >
struct braces : seq< seq< ControlChar, string< '{' > >,
until< string< '}' >, sor< anyStringWithinBraces,
variable,
subscript,
superscript,
overbar > > > {};
struct prefixedOverbar : seq<tildePrefix, overbar> {};
struct anyStringWithinBraces : plus<sor<utf8::not_one<'~', '$', '_', '^', '}'>>> {};
struct superscript : until<closeBrace, sor<variable, anyStringWithinBraces>> {};
struct subscript : until<closeBrace, sor<variable, anyStringWithinBraces>> {};
struct overbar : until<closeBrace, sor<variable, anyStringWithinBraces>> {};
struct superscript : braces< string< '^' > > {};
struct subscript : braces< string< '_' > > {};
struct overbar : braces< string< '~' > > {};
/**
* Finally, the full grammar
*/
struct grammar : star<sor<variable,
prefixedSubscript,
prefixedSuperscript,
prefixedOverbar,
anyString>> {};
struct anything : sor< anyString,
variable,
subscript,
superscript,
overbar > {};
struct grammar : until< tao::pegtl::eof, anything > {};
template <typename Rule>
using selector = parse_tree::selector< Rule,
parse_tree::store_content::on<varNamespaceName,
varName,
anyString,
anyStringWithinBraces>,
parse_tree::discard_empty::on<superscript,
subscript,
overbar>>;
parse_tree::store_content::on< varNamespaceName,
varName,
anyStringWithinBraces,
anyString >,
parse_tree::discard_empty::on< superscript,
subscript,
overbar > >;
class MARKUP_PARSER
{