mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
Added <prefix> and <suffix> tags;
Added prefix and suffix support to combined_editor; 'always symbol' now checks if the symbols are available in the symbol font; Fixed parser bug in spec_sort; A first information field is no longer used as set identification git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@653 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
+74
-47
@@ -75,6 +75,7 @@ struct TextElementsFromString {
|
||||
int soft, kwpph, param, line, soft_line;
|
||||
int code, code_kw, code_string, param_ref, error;
|
||||
int param_id;
|
||||
/// put angle brackets around the text?
|
||||
bool bracket;
|
||||
|
||||
TextElementsFromString()
|
||||
@@ -86,10 +87,15 @@ struct TextElementsFromString {
|
||||
void fromString(TextElements& te, const String& text, size_t start, size_t end, const TextStyle& style, Context& ctx) {
|
||||
te.elements.clear();
|
||||
end = min(end, text.size());
|
||||
size_t text_start = start;
|
||||
// for each character...
|
||||
for (size_t pos = start ; pos < end ; ) {
|
||||
Char c = text.GetChar(pos);
|
||||
if (c == _('<')) {
|
||||
if (text_start < pos) {
|
||||
// text element before this tag?
|
||||
addText(te, text, text_start, pos, style, ctx);
|
||||
}
|
||||
size_t tag_start = pos;
|
||||
pos = skip_tag(text, tag_start);
|
||||
if (is_substr(text, tag_start, _( "<b"))) bold += 1;
|
||||
@@ -132,69 +138,90 @@ struct TextElementsFromString {
|
||||
else if (is_substr(text, tag_start, _("<atom"))) {
|
||||
// 'atomic' indicator
|
||||
size_t end_tag = min(end, match_close_tag(text, tag_start));
|
||||
intrusive_ptr<AtomTextElement> e(new AtomTextElement(text, pos, end_tag));
|
||||
intrusive_ptr<AtomTextElement> e(new AtomTextElement(pos, end_tag));
|
||||
fromString(e->elements, text, pos, end_tag, style, ctx);
|
||||
te.elements.push_back(e);
|
||||
pos = skip_tag(text, end_tag);
|
||||
} else if (is_substr(text, tag_start, _( "<error"))) {
|
||||
// error indicator
|
||||
size_t end_tag = min(end, match_close_tag(text, tag_start));
|
||||
intrusive_ptr<ErrorTextElement> e(new ErrorTextElement(text, pos, end_tag));
|
||||
intrusive_ptr<ErrorTextElement> e(new ErrorTextElement(pos, end_tag));
|
||||
fromString(e->elements, text, pos, end_tag, style, ctx);
|
||||
te.elements.push_back(e);
|
||||
pos = skip_tag(text, end_tag);
|
||||
} else {
|
||||
// ignore other tags
|
||||
}
|
||||
text_start = pos;
|
||||
} else {
|
||||
c = untag_char(c); // unescape
|
||||
// A character of normal text, add to the last text element (if possible)
|
||||
SimpleTextElement* e = nullptr;
|
||||
if (!te.elements.empty()) e = dynamic_cast<SimpleTextElement*>(te.elements.back().get());
|
||||
if (e && e->end == (bracket ? pos + 1 : pos)) {
|
||||
e->end = bracket ? pos + 2 : pos + 1; // just move the end, no need to make a new element
|
||||
e->content += c;
|
||||
if (bracket) {
|
||||
// content is "<somethin>g" should be "<something>"
|
||||
swap(e->content[e->content.size() - 2], e->content[e->content.size() - 1]);
|
||||
}
|
||||
} else {
|
||||
// add a new element for this text
|
||||
if (symbol > 0 && style.symbol_font.valid()) {
|
||||
e = new SymbolTextElement(text, pos, pos + 1, style.symbol_font, &ctx);
|
||||
bracket = false;
|
||||
} else {
|
||||
FontP font = style.font.make(
|
||||
(bold > 0 ? FONT_BOLD : FONT_NORMAL) |
|
||||
(italic > 0 ? FONT_ITALIC : FONT_NORMAL) |
|
||||
(soft > 0 ? FONT_SOFT : FONT_NORMAL) |
|
||||
(kwpph > 0 ? FONT_SOFT : FONT_NORMAL) |
|
||||
(code > 0 ? FONT_CODE : FONT_NORMAL) |
|
||||
(code_kw > 0 ? FONT_CODE_KW : FONT_NORMAL) |
|
||||
(code_string > 0 ? FONT_CODE_STRING : FONT_NORMAL),
|
||||
param > 0 || param_ref > 0
|
||||
? ¶m_colors[(param_id++) % param_colors_count]
|
||||
: nullptr);
|
||||
bracket = kwpph > 0 || param > 0;
|
||||
e = new FontTextElement(
|
||||
text,
|
||||
bracket ? pos - 1 : pos,
|
||||
bracket ? pos + 2 : pos + 1,
|
||||
font,
|
||||
soft > 0 ? DRAW_ACTIVE : DRAW_NORMAL,
|
||||
line > 0 ? BREAK_LINE :
|
||||
soft_line > 0 ? BREAK_SOFT : BREAK_HARD);
|
||||
}
|
||||
if (bracket) {
|
||||
e->content = String(LEFT_ANGLE_BRACKET) + c + RIGHT_ANGLE_BRACKET;
|
||||
} else {
|
||||
e->content = c;
|
||||
}
|
||||
te.elements.push_back(TextElementP(e));
|
||||
}
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
if (text_start < end) {
|
||||
addText(te, text, text_start, end, style, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/// Create a text element for a piece of text
|
||||
void addText(TextElements& te, const String& text, size_t start, size_t end, const TextStyle& style, Context& ctx) {
|
||||
String content = untag(text.substr(start, end - start));
|
||||
assert(content.size() == end-start);
|
||||
// use symbol font?
|
||||
if (symbol > 0 && style.symbol_font.valid()) {
|
||||
te.elements.push_back(new_intrusive5<SymbolTextElement>(content, start, end, style.symbol_font, &ctx));
|
||||
} else {
|
||||
// text, possibly mixed with symbols
|
||||
DrawWhat what = soft > 0 ? DRAW_ACTIVE : DRAW_NORMAL;
|
||||
LineBreak line_break = line > 0 ? BREAK_LINE :
|
||||
soft_line > 0 ? BREAK_SOFT : BREAK_HARD;
|
||||
if (kwpph > 0 || param > 0) {
|
||||
// bracket the text
|
||||
content = String(LEFT_ANGLE_BRACKET) + content + RIGHT_ANGLE_BRACKET;
|
||||
start -= 1;
|
||||
end += 1;
|
||||
}
|
||||
if (style.always_symbol && style.symbol_font.valid()) {
|
||||
// mixed symbols/text, autodetected by symbol font
|
||||
size_t text_pos = 0;
|
||||
size_t pos = 0;
|
||||
FontP font;
|
||||
while (pos < end-start) {
|
||||
if (size_t n = style.symbol_font.font->recognizePrefix(content,pos)) {
|
||||
// at 'pos' there are n symbol font characters
|
||||
if (text_pos < pos) {
|
||||
// text before it?
|
||||
if (!font) font = makeFont(style);
|
||||
te.elements.push_back(new_intrusive6<FontTextElement>(content.substr(text_pos, pos-text_pos), start+text_pos, start+pos, font, what, line_break));
|
||||
}
|
||||
te.elements.push_back(new_intrusive5<SymbolTextElement>(content.substr(pos,n), start+pos, start+pos+n, style.symbol_font, &ctx));
|
||||
text_pos = pos += n;
|
||||
} else {
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
if (text_pos < pos) {
|
||||
if (!font) font = makeFont(style);
|
||||
te.elements.push_back(new_intrusive6<FontTextElement>(content.substr(text_pos), start+text_pos, end, font, what, line_break));
|
||||
}
|
||||
} else {
|
||||
te.elements.push_back(new_intrusive6<FontTextElement>(content, start, end, makeFont(style), what, line_break));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FontP makeFont(const TextStyle& style) {
|
||||
return style.font.make(
|
||||
(bold > 0 ? FONT_BOLD : FONT_NORMAL) |
|
||||
(italic > 0 ? FONT_ITALIC : FONT_NORMAL) |
|
||||
(soft > 0 ? FONT_SOFT : FONT_NORMAL) |
|
||||
(kwpph > 0 ? FONT_SOFT : FONT_NORMAL) |
|
||||
(code > 0 ? FONT_CODE : FONT_NORMAL) |
|
||||
(code_kw > 0 ? FONT_CODE_KW : FONT_NORMAL) |
|
||||
(code_string > 0 ? FONT_CODE_STRING : FONT_NORMAL),
|
||||
param > 0 || param_ref > 0
|
||||
? ¶m_colors[(param_id++) % param_colors_count]
|
||||
: nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+10
-25
@@ -57,12 +57,10 @@ struct CharInfo {
|
||||
/// A section of text that can be rendered using a TextViewer
|
||||
class TextElement : public IntrusivePtrBase<TextElement> {
|
||||
public:
|
||||
/// The text of which a subsection is drawn
|
||||
String text;
|
||||
/// What section of the input string is this element?
|
||||
size_t start, end;
|
||||
|
||||
inline TextElement(const String& text, size_t start ,size_t end) : text(text), start(start), end(end) {}
|
||||
inline TextElement(size_t start ,size_t end) : start(start), end(end) {}
|
||||
virtual ~TextElement() {}
|
||||
|
||||
/// Draw a subsection section of the text in the given rectangle
|
||||
@@ -109,8 +107,8 @@ class TextElements {
|
||||
/// A text element that just shows text
|
||||
class SimpleTextElement : public TextElement {
|
||||
public:
|
||||
SimpleTextElement(const String& text, size_t start, size_t end)
|
||||
: TextElement(text, start, end), content(text.substr(start,end-start))
|
||||
SimpleTextElement(const String& content, size_t start, size_t end)
|
||||
: TextElement(start, end), content(content)
|
||||
{}
|
||||
String content; ///< Text to show
|
||||
};
|
||||
@@ -118,8 +116,8 @@ class SimpleTextElement : public TextElement {
|
||||
/// A text element that uses a normal font
|
||||
class FontTextElement : public SimpleTextElement {
|
||||
public:
|
||||
FontTextElement(const String& text, size_t start, size_t end, const FontP& font, DrawWhat draw_as, LineBreak break_style)
|
||||
: SimpleTextElement(text, start, end)
|
||||
FontTextElement(const String& content, size_t start, size_t end, const FontP& font, DrawWhat draw_as, LineBreak break_style)
|
||||
: SimpleTextElement(content, start, end)
|
||||
, font(font), draw_as(draw_as), break_style(break_style)
|
||||
{}
|
||||
|
||||
@@ -136,8 +134,8 @@ class FontTextElement : public SimpleTextElement {
|
||||
/// A text element that uses a symbol font
|
||||
class SymbolTextElement : public SimpleTextElement {
|
||||
public:
|
||||
SymbolTextElement(const String& text, size_t start, size_t end, const SymbolFontRef& font, Context* ctx)
|
||||
: SimpleTextElement(text, start, end)
|
||||
SymbolTextElement(const String& content, size_t start, size_t end, const SymbolFontRef& font, Context* ctx)
|
||||
: SimpleTextElement(content, start, end)
|
||||
, font(font), ctx(*ctx)
|
||||
{}
|
||||
|
||||
@@ -155,7 +153,7 @@ class SymbolTextElement : public SimpleTextElement {
|
||||
/// A TextElement consisting of sub elements
|
||||
class CompoundTextElement : public TextElement {
|
||||
public:
|
||||
CompoundTextElement(const String& text, size_t start, size_t end) : TextElement(text, start, end) {}
|
||||
CompoundTextElement(size_t start, size_t end) : TextElement(start, end) {}
|
||||
|
||||
virtual void draw (RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const;
|
||||
virtual void getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const;
|
||||
@@ -168,7 +166,7 @@ class CompoundTextElement : public TextElement {
|
||||
/// A TextElement drawn using a grey background
|
||||
class AtomTextElement : public CompoundTextElement {
|
||||
public:
|
||||
AtomTextElement(const String& text, size_t start, size_t end) : CompoundTextElement(text, start, end) {}
|
||||
AtomTextElement(size_t start, size_t end) : CompoundTextElement(start, end) {}
|
||||
|
||||
virtual void draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const;
|
||||
};
|
||||
@@ -176,23 +174,10 @@ class AtomTextElement : public CompoundTextElement {
|
||||
/// A TextElement drawn using a red wavy underline
|
||||
class ErrorTextElement : public CompoundTextElement {
|
||||
public:
|
||||
ErrorTextElement(const String& text, size_t start, size_t end) : CompoundTextElement(text, start, end) {}
|
||||
ErrorTextElement(size_t start, size_t end) : CompoundTextElement(start, end) {}
|
||||
|
||||
virtual void draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : Other text elements
|
||||
/*
|
||||
/// A text element that displays a horizontal separator line
|
||||
class HorizontalLineTextElement : public TextElement {
|
||||
public:
|
||||
HorizontalLineTextElement(const String& text, size_t start ,size_t end) : TextElement(text, start, end) {}
|
||||
|
||||
virtual void draw (RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const;
|
||||
virtual void getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const;
|
||||
virtual double minScale() const;
|
||||
};
|
||||
*/
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
#endif
|
||||
|
||||
@@ -328,12 +328,7 @@ void TextViewer::setExactScrollPosition(double pos) {
|
||||
// ----------------------------------------------------------------------------- : Elements
|
||||
|
||||
void TextViewer::prepareElements(const String& text, const TextStyle& style, Context& ctx) {
|
||||
if (style.always_symbol) {
|
||||
elements.elements.clear();
|
||||
elements.elements.push_back(new_intrusive5<SymbolTextElement>(text, 0, text.size(), style.symbol_font, &ctx));
|
||||
} else {
|
||||
elements.fromString(text, 0, text.size(), style, ctx);
|
||||
}
|
||||
elements.fromString(text, 0, text.size(), style, ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user