mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-11 21:27:01 -04:00
Change tabs to two spaces.
This commit is contained in:
@@ -12,47 +12,47 @@
|
||||
// ----------------------------------------------------------------------------- : CompoundTextElement
|
||||
|
||||
void CompoundTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const {
|
||||
elements.draw(dc, scale, rect, xs, what, start, end);
|
||||
elements.draw(dc, scale, rect, xs, what, start, end);
|
||||
}
|
||||
void CompoundTextElement::getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const {
|
||||
elements.getCharInfo(dc, scale, start, end, out);
|
||||
elements.getCharInfo(dc, scale, start, end, out);
|
||||
}
|
||||
double CompoundTextElement::minScale() const {
|
||||
return elements.minScale();
|
||||
return elements.minScale();
|
||||
}
|
||||
double CompoundTextElement::scaleStep() const {
|
||||
return elements.scaleStep();
|
||||
return elements.scaleStep();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : AtomTextElement
|
||||
|
||||
void AtomTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const {
|
||||
if (what & DRAW_ACTIVE) {
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(Color(210,210,210));
|
||||
dc.DrawRectangle(rect);
|
||||
}
|
||||
CompoundTextElement::draw(dc, scale, rect, xs, what, start, end);
|
||||
if (what & DRAW_ACTIVE) {
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(Color(210,210,210));
|
||||
dc.DrawRectangle(rect);
|
||||
}
|
||||
CompoundTextElement::draw(dc, scale, rect, xs, what, start, end);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : ErrorTextElement
|
||||
|
||||
void ErrorTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const {
|
||||
// Draw wavy underline
|
||||
if (what & DRAW_ERRORS) {
|
||||
dc.SetPen(*wxRED_PEN);
|
||||
RealPoint pos = rect.bottomLeft() - dc.trInvS(RealSize(0,2));
|
||||
RealSize dx(dc.trInvS(2), 0), dy(0, dc.trInvS(1));
|
||||
while (pos.x + 1 < rect.right()) {
|
||||
dc.DrawLine(pos - dy, pos + dx + dy);
|
||||
pos += dx;
|
||||
dy = -dy;
|
||||
}
|
||||
if (pos.x < rect.right()) {
|
||||
// final piece
|
||||
dc.DrawLine(pos - dy, pos + dx * 0.5);
|
||||
}
|
||||
}
|
||||
// Draw the contents
|
||||
CompoundTextElement::draw(dc, scale, rect, xs, what, start, end);
|
||||
// Draw wavy underline
|
||||
if (what & DRAW_ERRORS) {
|
||||
dc.SetPen(*wxRED_PEN);
|
||||
RealPoint pos = rect.bottomLeft() - dc.trInvS(RealSize(0,2));
|
||||
RealSize dx(dc.trInvS(2), 0), dy(0, dc.trInvS(1));
|
||||
while (pos.x + 1 < rect.right()) {
|
||||
dc.DrawLine(pos - dy, pos + dx + dy);
|
||||
pos += dx;
|
||||
dy = -dy;
|
||||
}
|
||||
if (pos.x < rect.right()) {
|
||||
// final piece
|
||||
dc.DrawLine(pos - dy, pos + dx * 0.5);
|
||||
}
|
||||
}
|
||||
// Draw the contents
|
||||
CompoundTextElement::draw(dc, scale, rect, xs, what, start, end);
|
||||
}
|
||||
|
||||
+225
-225
@@ -18,258 +18,258 @@ DECLARE_POINTER_TYPE(FontTextElement);
|
||||
// ----------------------------------------------------------------------------- : TextElements
|
||||
|
||||
void TextElements::draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const {
|
||||
FOR_EACH_CONST(e, elements) {
|
||||
size_t start_ = max(start, e->start);
|
||||
size_t end_ = min(end, e->end);
|
||||
if (start_ < end_) {
|
||||
e->draw(dc, scale,
|
||||
RealRect(rect.x + xs[start_-start] - xs[0], rect.y,
|
||||
xs[end_-start] - xs[start_-start], rect.height),
|
||||
xs + start_ - start, what, start_, end_);
|
||||
}
|
||||
if (end <= e->end) return; // nothing can be after this
|
||||
}
|
||||
FOR_EACH_CONST(e, elements) {
|
||||
size_t start_ = max(start, e->start);
|
||||
size_t end_ = min(end, e->end);
|
||||
if (start_ < end_) {
|
||||
e->draw(dc, scale,
|
||||
RealRect(rect.x + xs[start_-start] - xs[0], rect.y,
|
||||
xs[end_-start] - xs[start_-start], rect.height),
|
||||
xs + start_ - start, what, start_, end_);
|
||||
}
|
||||
if (end <= e->end) return; // nothing can be after this
|
||||
}
|
||||
}
|
||||
|
||||
void TextElements::getCharInfo(RotatedDC& dc, double scale, size_t start, size_t end, vector<CharInfo>& out) const {
|
||||
FOR_EACH_CONST(e, elements) {
|
||||
// characters before this element, after the previous
|
||||
while (out.size() < e->start) {
|
||||
out.push_back(CharInfo());
|
||||
}
|
||||
e->getCharInfo(dc, scale, out);
|
||||
}
|
||||
while (out.size() < end) {
|
||||
out.push_back(CharInfo());
|
||||
}
|
||||
FOR_EACH_CONST(e, elements) {
|
||||
// characters before this element, after the previous
|
||||
while (out.size() < e->start) {
|
||||
out.push_back(CharInfo());
|
||||
}
|
||||
e->getCharInfo(dc, scale, out);
|
||||
}
|
||||
while (out.size() < end) {
|
||||
out.push_back(CharInfo());
|
||||
}
|
||||
}
|
||||
|
||||
double TextElements::minScale() const {
|
||||
double m = 0.0001;
|
||||
FOR_EACH_CONST(e, elements) {
|
||||
m = max(m, e->minScale());
|
||||
}
|
||||
return m;
|
||||
double m = 0.0001;
|
||||
FOR_EACH_CONST(e, elements) {
|
||||
m = max(m, e->minScale());
|
||||
}
|
||||
return m;
|
||||
}
|
||||
double TextElements::scaleStep() const {
|
||||
double m = 1;
|
||||
FOR_EACH_CONST(e, elements) {
|
||||
m = min(m, e->scaleStep());
|
||||
}
|
||||
return m;
|
||||
double m = 1;
|
||||
FOR_EACH_CONST(e, elements) {
|
||||
m = min(m, e->scaleStep());
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
// Colors for <atom-param> tags
|
||||
AColor param_colors[] =
|
||||
{ AColor(0,170,0)
|
||||
, AColor(0,0,200)
|
||||
, AColor(200,0,100)
|
||||
, AColor(200,200,0)
|
||||
, AColor(0,170,170)
|
||||
, AColor(200,0,0)
|
||||
};
|
||||
{ AColor(0,170,0)
|
||||
, AColor(0,0,200)
|
||||
, AColor(200,0,100)
|
||||
, AColor(200,200,0)
|
||||
, AColor(0,170,170)
|
||||
, AColor(200,0,0)
|
||||
};
|
||||
const size_t param_colors_count = sizeof(param_colors) / sizeof(param_colors[0]);
|
||||
|
||||
// Helper class for TextElements::fromString, to allow persistent formating state accross recusive calls
|
||||
struct TextElementsFromString {
|
||||
// What formatting is enabled?
|
||||
int bold, italic, symbol;
|
||||
int soft, kwpph, param, line, soft_line;
|
||||
int code, code_kw, code_string, param_ref, error;
|
||||
int param_id;
|
||||
vector<AColor> colors;
|
||||
vector<double> sizes;
|
||||
/// put angle brackets around the text?
|
||||
bool bracket;
|
||||
|
||||
TextElementsFromString()
|
||||
: bold(0), italic(0), symbol(0), soft(0), kwpph(0), param(0), line(0), soft_line(0)
|
||||
, code(0), code_kw(0), code_string(0), param_ref(0), error(0)
|
||||
, param_id(0), bracket(false) {}
|
||||
|
||||
// read TextElements from a string
|
||||
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);
|
||||
}
|
||||
// a (formatting) tag
|
||||
size_t tag_start = pos;
|
||||
pos = skip_tag(text, tag_start);
|
||||
if (is_substr(text, tag_start, _( "<b"))) bold += 1;
|
||||
else if (is_substr(text, tag_start, _("</b"))) bold -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<i"))) italic += 1;
|
||||
else if (is_substr(text, tag_start, _("</i"))) italic -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<sym"))) symbol += 1;
|
||||
else if (is_substr(text, tag_start, _("</sym"))) symbol -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<line"))) line += 1;
|
||||
else if (is_substr(text, tag_start, _("</line"))) line -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<soft-line"))) soft_line += 1;
|
||||
else if (is_substr(text, tag_start, _("</soft-line"))) soft_line -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<sep-soft"))) soft += 1;
|
||||
else if (is_substr(text, tag_start, _("</sep-soft"))) soft -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<soft"))) soft += 1; // must be after <soft-line
|
||||
else if (is_substr(text, tag_start, _("</soft"))) soft -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<atom-kwpph"))) kwpph += 1;
|
||||
else if (is_substr(text, tag_start, _("</atom-kwpph"))) kwpph -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<code-kw"))) code_kw += 1;
|
||||
else if (is_substr(text, tag_start, _("</code-kw"))) code_kw -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<code-str"))) code_string += 1;
|
||||
else if (is_substr(text, tag_start, _("</code-str"))) code_string -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<code"))) code += 1;
|
||||
else if (is_substr(text, tag_start, _("</code"))) code -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<color"))) {
|
||||
size_t colon = text.find_first_of(_(">:"), tag_start);
|
||||
if (colon < pos - 1 && text.GetChar(colon) == _(':')) {
|
||||
AColor c = parse_acolor(text.substr(colon+1, pos-colon-2));
|
||||
if (!c.Ok()) c = style.font.color;
|
||||
colors.push_back(c);
|
||||
}
|
||||
} else if (is_substr(text, tag_start, _("</color"))) {
|
||||
if (!colors.empty()) colors.pop_back();
|
||||
}
|
||||
else if (is_substr(text, tag_start, _( "<size"))) {
|
||||
size_t colon = text.find_first_of(_(">:"), tag_start);
|
||||
if (colon < pos - 1 && text.GetChar(colon) == _(':')) {
|
||||
double size = style.font.size;
|
||||
String v = text.substr(colon+1, pos-colon-2);
|
||||
v.ToDouble(&size);
|
||||
sizes.push_back(size);
|
||||
}
|
||||
} else if (is_substr(text, tag_start, _("</size"))) {
|
||||
if (!sizes.empty()) sizes.pop_back();
|
||||
}
|
||||
else if (is_substr(text, tag_start, _( "<ref-param"))) {
|
||||
// determine the param being referenced
|
||||
// from a tag <ref-param123>
|
||||
if (pos != String::npos) {
|
||||
String ref = text.substr(tag_start + 10, pos - tag_start - 11);
|
||||
long ref_n;
|
||||
if (ref.ToLong(&ref_n)) {
|
||||
param_id = (ref_n - 1)%param_colors_count + param_colors_count;
|
||||
}
|
||||
}
|
||||
param_ref += 1;
|
||||
}
|
||||
else if (is_substr(text, tag_start, _("</ref-param"))) param_ref -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<atom-param"))) param += 1;
|
||||
else if (is_substr(text, tag_start, _("</atom-param"))) param -= 1;
|
||||
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(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(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 starts again after the tag
|
||||
text_start = pos;
|
||||
} else {
|
||||
// normal text
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
if (text_start < end) {
|
||||
// remaining text at the end
|
||||
addText(te, text, text_start, end, style, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// What formatting is enabled?
|
||||
int bold, italic, symbol;
|
||||
int soft, kwpph, param, line, soft_line;
|
||||
int code, code_kw, code_string, param_ref, error;
|
||||
int param_id;
|
||||
vector<AColor> colors;
|
||||
vector<double> sizes;
|
||||
/// put angle brackets around the text?
|
||||
bool bracket;
|
||||
|
||||
TextElementsFromString()
|
||||
: bold(0), italic(0), symbol(0), soft(0), kwpph(0), param(0), line(0), soft_line(0)
|
||||
, code(0), code_kw(0), code_string(0), param_ref(0), error(0)
|
||||
, param_id(0), bracket(false) {}
|
||||
|
||||
// read TextElements from a string
|
||||
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);
|
||||
}
|
||||
// a (formatting) tag
|
||||
size_t tag_start = pos;
|
||||
pos = skip_tag(text, tag_start);
|
||||
if (is_substr(text, tag_start, _( "<b"))) bold += 1;
|
||||
else if (is_substr(text, tag_start, _("</b"))) bold -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<i"))) italic += 1;
|
||||
else if (is_substr(text, tag_start, _("</i"))) italic -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<sym"))) symbol += 1;
|
||||
else if (is_substr(text, tag_start, _("</sym"))) symbol -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<line"))) line += 1;
|
||||
else if (is_substr(text, tag_start, _("</line"))) line -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<soft-line"))) soft_line += 1;
|
||||
else if (is_substr(text, tag_start, _("</soft-line"))) soft_line -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<sep-soft"))) soft += 1;
|
||||
else if (is_substr(text, tag_start, _("</sep-soft"))) soft -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<soft"))) soft += 1; // must be after <soft-line
|
||||
else if (is_substr(text, tag_start, _("</soft"))) soft -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<atom-kwpph"))) kwpph += 1;
|
||||
else if (is_substr(text, tag_start, _("</atom-kwpph"))) kwpph -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<code-kw"))) code_kw += 1;
|
||||
else if (is_substr(text, tag_start, _("</code-kw"))) code_kw -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<code-str"))) code_string += 1;
|
||||
else if (is_substr(text, tag_start, _("</code-str"))) code_string -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<code"))) code += 1;
|
||||
else if (is_substr(text, tag_start, _("</code"))) code -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<color"))) {
|
||||
size_t colon = text.find_first_of(_(">:"), tag_start);
|
||||
if (colon < pos - 1 && text.GetChar(colon) == _(':')) {
|
||||
AColor c = parse_acolor(text.substr(colon+1, pos-colon-2));
|
||||
if (!c.Ok()) c = style.font.color;
|
||||
colors.push_back(c);
|
||||
}
|
||||
} else if (is_substr(text, tag_start, _("</color"))) {
|
||||
if (!colors.empty()) colors.pop_back();
|
||||
}
|
||||
else if (is_substr(text, tag_start, _( "<size"))) {
|
||||
size_t colon = text.find_first_of(_(">:"), tag_start);
|
||||
if (colon < pos - 1 && text.GetChar(colon) == _(':')) {
|
||||
double size = style.font.size;
|
||||
String v = text.substr(colon+1, pos-colon-2);
|
||||
v.ToDouble(&size);
|
||||
sizes.push_back(size);
|
||||
}
|
||||
} else if (is_substr(text, tag_start, _("</size"))) {
|
||||
if (!sizes.empty()) sizes.pop_back();
|
||||
}
|
||||
else if (is_substr(text, tag_start, _( "<ref-param"))) {
|
||||
// determine the param being referenced
|
||||
// from a tag <ref-param123>
|
||||
if (pos != String::npos) {
|
||||
String ref = text.substr(tag_start + 10, pos - tag_start - 11);
|
||||
long ref_n;
|
||||
if (ref.ToLong(&ref_n)) {
|
||||
param_id = (ref_n - 1)%param_colors_count + param_colors_count;
|
||||
}
|
||||
}
|
||||
param_ref += 1;
|
||||
}
|
||||
else if (is_substr(text, tag_start, _("</ref-param"))) param_ref -= 1;
|
||||
else if (is_substr(text, tag_start, _( "<atom-param"))) param += 1;
|
||||
else if (is_substr(text, tag_start, _("</atom-param"))) param -= 1;
|
||||
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(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(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 starts again after the tag
|
||||
text_start = pos;
|
||||
} else {
|
||||
// normal text
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
if (text_start < end) {
|
||||
// remaining text at the end
|
||||
addText(te, text, text_start, end, style, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/// Create a text element for a piece of text, text[start..end)
|
||||
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(intrusive(new 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(intrusive(new FontTextElement(content.substr(text_pos, pos-text_pos), start+text_pos, start+pos, font, what, line_break)));
|
||||
}
|
||||
te.elements.push_back(intrusive(new 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(intrusive(new FontTextElement(content.substr(text_pos), start+text_pos, end, font, what, line_break)));
|
||||
}
|
||||
} else {
|
||||
te.elements.push_back(intrusive(new 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]
|
||||
: !colors.empty()
|
||||
? &colors.back()
|
||||
: nullptr,
|
||||
!sizes.empty() ? &sizes.back() : nullptr
|
||||
);
|
||||
}
|
||||
/// Create a text element for a piece of text, text[start..end)
|
||||
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(intrusive(new 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(intrusive(new FontTextElement(content.substr(text_pos, pos-text_pos), start+text_pos, start+pos, font, what, line_break)));
|
||||
}
|
||||
te.elements.push_back(intrusive(new 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(intrusive(new FontTextElement(content.substr(text_pos), start+text_pos, end, font, what, line_break)));
|
||||
}
|
||||
} else {
|
||||
te.elements.push_back(intrusive(new 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]
|
||||
: !colors.empty()
|
||||
? &colors.back()
|
||||
: nullptr,
|
||||
!sizes.empty() ? &sizes.back() : nullptr
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
void TextElements::fromString(const String& text, size_t start, size_t end, const TextStyle& style, Context& ctx) {
|
||||
TextElementsFromString f;
|
||||
f.fromString(*this, text, start, end, style, ctx);
|
||||
TextElementsFromString f;
|
||||
f.fromString(*this, text, start, end, style, ctx);
|
||||
}
|
||||
/*
|
||||
// ----------------------------------------------------------------------------- : CompoundTextElement
|
||||
|
||||
void CompoundTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, DrawWhat what, size_t start, size_t end) const {
|
||||
elements.draw(dc, scale, rect, what, start, end);
|
||||
elements.draw(dc, scale, rect, what, start, end);
|
||||
}
|
||||
RealSize CompoundTextElement::charSize(RotatedDC& dc, double scale, size_t index) const {
|
||||
return elements.charSize(rot, scale, index);
|
||||
return elements.charSize(rot, scale, index);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
+93
-93
@@ -25,47 +25,47 @@ class SymbolFontRef;
|
||||
|
||||
/// Information on a linebreak
|
||||
enum LineBreak
|
||||
{ BREAK_NO // no line break ever
|
||||
, BREAK_MAYBE // break here when in "direction:vertical" mode
|
||||
, BREAK_SPACE // optional line break (' ')
|
||||
, BREAK_SOFT // always a line break, spacing as a soft break
|
||||
, BREAK_HARD // always a line break ('\n')
|
||||
, BREAK_LINE // line break with a separator line (<line>)
|
||||
{ BREAK_NO // no line break ever
|
||||
, BREAK_MAYBE // break here when in "direction:vertical" mode
|
||||
, BREAK_SPACE // optional line break (' ')
|
||||
, BREAK_SOFT // always a line break, spacing as a soft break
|
||||
, BREAK_HARD // always a line break ('\n')
|
||||
, BREAK_LINE // line break with a separator line (<line>)
|
||||
};
|
||||
|
||||
/// Information on a character in a TextElement
|
||||
struct CharInfo {
|
||||
RealSize size; ///< Size of this character
|
||||
LineBreak break_after : 31; ///< How/when to break after it?
|
||||
bool soft : 1; ///< Is this a 'soft' character? soft characters are ignored for alignment
|
||||
|
||||
explicit CharInfo()
|
||||
: break_after(BREAK_NO), soft(true)
|
||||
{}
|
||||
inline CharInfo(RealSize size, LineBreak break_after, bool soft = false)
|
||||
: size(size), break_after(break_after), soft(soft)
|
||||
{}
|
||||
RealSize size; ///< Size of this character
|
||||
LineBreak break_after : 31; ///< How/when to break after it?
|
||||
bool soft : 1; ///< Is this a 'soft' character? soft characters are ignored for alignment
|
||||
|
||||
explicit CharInfo()
|
||||
: break_after(BREAK_NO), soft(true)
|
||||
{}
|
||||
inline CharInfo(RealSize size, LineBreak break_after, bool soft = false)
|
||||
: size(size), break_after(break_after), soft(soft)
|
||||
{}
|
||||
};
|
||||
|
||||
/// A section of text that can be rendered using a TextViewer
|
||||
class TextElement : public IntrusivePtrBase<TextElement> {
|
||||
public:
|
||||
/// What section of the input string is this element?
|
||||
size_t start, 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
|
||||
/** xs give the x coordinates for each character
|
||||
* this->start <= start < end <= this->end <= text.size() */
|
||||
virtual void draw (RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const = 0;
|
||||
/// Get information on all characters in the range [start...end) and store them in out
|
||||
virtual void getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const = 0;
|
||||
/// Return the minimum scale factor allowed (starts at 1)
|
||||
virtual double minScale() const = 0;
|
||||
/// Return the steps the scale factor should take
|
||||
virtual double scaleStep() const = 0;
|
||||
/// What section of the input string is this element?
|
||||
size_t start, 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
|
||||
/** xs give the x coordinates for each character
|
||||
* this->start <= start < end <= this->end <= text.size() */
|
||||
virtual void draw (RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const = 0;
|
||||
/// Get information on all characters in the range [start...end) and store them in out
|
||||
virtual void getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const = 0;
|
||||
/// Return the minimum scale factor allowed (starts at 1)
|
||||
virtual double minScale() const = 0;
|
||||
/// Return the steps the scale factor should take
|
||||
virtual double scaleStep() const = 0;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : TextElements
|
||||
@@ -73,26 +73,26 @@ class TextElement : public IntrusivePtrBase<TextElement> {
|
||||
/// A list of text elements
|
||||
class TextElements {
|
||||
public:
|
||||
/// Draw all the elements (as need to show the range start..end)
|
||||
void draw (RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const;
|
||||
// Get information on all characters in the range [start...end) and store them in out
|
||||
void getCharInfo(RotatedDC& dc, double scale, size_t start, size_t end, vector<CharInfo>& out) const;
|
||||
/// Return the minimum scale factor allowed by all elements
|
||||
double minScale() const;
|
||||
/// Return the steps the scale factor should take
|
||||
double scaleStep() const;
|
||||
|
||||
/// The actual elements
|
||||
/** They must be in order of positions and not overlap, i.e.
|
||||
* i < j ==> elements[i].end <= elements[j].start
|
||||
*/
|
||||
vector<TextElementP> elements;
|
||||
|
||||
/// Find the element that contains the given index, if there is any
|
||||
vector<TextElementP>::const_iterator findByIndex(size_t index) const;
|
||||
|
||||
/// Read the elements from a string
|
||||
void fromString(const String& text, size_t start, size_t end, const TextStyle& style, Context& ctx);
|
||||
/// Draw all the elements (as need to show the range start..end)
|
||||
void draw (RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const;
|
||||
// Get information on all characters in the range [start...end) and store them in out
|
||||
void getCharInfo(RotatedDC& dc, double scale, size_t start, size_t end, vector<CharInfo>& out) const;
|
||||
/// Return the minimum scale factor allowed by all elements
|
||||
double minScale() const;
|
||||
/// Return the steps the scale factor should take
|
||||
double scaleStep() const;
|
||||
|
||||
/// The actual elements
|
||||
/** They must be in order of positions and not overlap, i.e.
|
||||
* i < j ==> elements[i].end <= elements[j].start
|
||||
*/
|
||||
vector<TextElementP> elements;
|
||||
|
||||
/// Find the element that contains the given index, if there is any
|
||||
vector<TextElementP>::const_iterator findByIndex(size_t index) const;
|
||||
|
||||
/// Read the elements from a string
|
||||
void fromString(const String& text, size_t start, size_t end, const TextStyle& style, Context& ctx);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : SimpleTextElement
|
||||
@@ -100,45 +100,45 @@ class TextElements {
|
||||
/// A text element that just shows text
|
||||
class SimpleTextElement : public TextElement {
|
||||
public:
|
||||
SimpleTextElement(const String& content, size_t start, size_t end)
|
||||
: TextElement(start, end), content(content)
|
||||
{}
|
||||
String content; ///< Text to show
|
||||
SimpleTextElement(const String& content, size_t start, size_t end)
|
||||
: TextElement(start, end), content(content)
|
||||
{}
|
||||
String content; ///< Text to show
|
||||
};
|
||||
|
||||
/// A text element that uses a normal font
|
||||
class FontTextElement : public SimpleTextElement {
|
||||
public:
|
||||
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)
|
||||
{}
|
||||
|
||||
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;
|
||||
virtual double scaleStep() const;
|
||||
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)
|
||||
{}
|
||||
|
||||
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;
|
||||
virtual double scaleStep() const;
|
||||
private:
|
||||
FontP font;
|
||||
DrawWhat draw_as;
|
||||
LineBreak break_style;
|
||||
FontP font;
|
||||
DrawWhat draw_as;
|
||||
LineBreak break_style;
|
||||
};
|
||||
|
||||
/// A text element that uses a symbol font
|
||||
class SymbolTextElement : public SimpleTextElement {
|
||||
public:
|
||||
SymbolTextElement(const String& content, size_t start, size_t end, const SymbolFontRef& font, Context* ctx)
|
||||
: SimpleTextElement(content, start, end)
|
||||
, font(font), ctx(*ctx)
|
||||
{}
|
||||
|
||||
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;
|
||||
virtual double scaleStep() const;
|
||||
SymbolTextElement(const String& content, size_t start, size_t end, const SymbolFontRef& font, Context* ctx)
|
||||
: SimpleTextElement(content, start, end)
|
||||
, font(font), ctx(*ctx)
|
||||
{}
|
||||
|
||||
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;
|
||||
virtual double scaleStep() const;
|
||||
private:
|
||||
const SymbolFontRef& font; // owned by TextStyle
|
||||
Context& ctx;
|
||||
const SymbolFontRef& font; // owned by TextStyle
|
||||
Context& ctx;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : CompoundTextElement
|
||||
@@ -146,30 +146,30 @@ class SymbolTextElement : public SimpleTextElement {
|
||||
/// A TextElement consisting of sub elements
|
||||
class CompoundTextElement : public TextElement {
|
||||
public:
|
||||
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;
|
||||
virtual double minScale() const;
|
||||
virtual double scaleStep() const;
|
||||
|
||||
TextElements elements; ///< the elements
|
||||
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;
|
||||
virtual double minScale() const;
|
||||
virtual double scaleStep() const;
|
||||
|
||||
TextElements elements; ///< the elements
|
||||
};
|
||||
|
||||
/// A TextElement drawn using a grey background
|
||||
class AtomTextElement : public CompoundTextElement {
|
||||
public:
|
||||
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;
|
||||
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;
|
||||
};
|
||||
|
||||
/// A TextElement drawn using a red wavy underline
|
||||
class ErrorTextElement : public CompoundTextElement {
|
||||
public:
|
||||
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;
|
||||
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;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
+32
-32
@@ -13,44 +13,44 @@
|
||||
// ----------------------------------------------------------------------------- : FontTextElement
|
||||
|
||||
void FontTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const {
|
||||
if ((what & draw_as) != draw_as) return; // don't draw
|
||||
// text
|
||||
String text = content.substr(start - this->start, end - start);
|
||||
if (!text.empty() && text.GetChar(text.size() - 1) == _('\n')) {
|
||||
text = text.substr(0, text.size() - 1); // don't draw last \n
|
||||
}
|
||||
// draw
|
||||
dc.SetFont(*font, scale);
|
||||
dc.DrawTextWithShadow(text, *font, rect.position());
|
||||
if ((what & draw_as) != draw_as) return; // don't draw
|
||||
// text
|
||||
String text = content.substr(start - this->start, end - start);
|
||||
if (!text.empty() && text.GetChar(text.size() - 1) == _('\n')) {
|
||||
text = text.substr(0, text.size() - 1); // don't draw last \n
|
||||
}
|
||||
// draw
|
||||
dc.SetFont(*font, scale);
|
||||
dc.DrawTextWithShadow(text, *font, rect.position());
|
||||
}
|
||||
|
||||
void FontTextElement::getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const {
|
||||
// font
|
||||
dc.SetFont(*font, scale);
|
||||
// find sizes & breaks
|
||||
double prev_width = 0;
|
||||
size_t line_start = start; // start of the current line
|
||||
for (size_t i = start ; i < end ; ++i) {
|
||||
Char c = content.GetChar(i - this->start);
|
||||
if (c == _('\n')) {
|
||||
out.push_back(CharInfo(RealSize(0, dc.GetCharHeight()), break_style, draw_as == DRAW_ACTIVE));
|
||||
line_start = i + 1;
|
||||
prev_width = 0;
|
||||
} else {
|
||||
RealSize s = dc.GetTextExtent(content.substr(line_start - this->start, i - line_start + 1));
|
||||
out.push_back(CharInfo(
|
||||
RealSize(s.width - prev_width, s.height),
|
||||
c == _(' ') ? BREAK_SPACE : BREAK_MAYBE,
|
||||
draw_as == DRAW_ACTIVE // from <soft> tag
|
||||
));
|
||||
prev_width = s.width;
|
||||
}
|
||||
}
|
||||
// font
|
||||
dc.SetFont(*font, scale);
|
||||
// find sizes & breaks
|
||||
double prev_width = 0;
|
||||
size_t line_start = start; // start of the current line
|
||||
for (size_t i = start ; i < end ; ++i) {
|
||||
Char c = content.GetChar(i - this->start);
|
||||
if (c == _('\n')) {
|
||||
out.push_back(CharInfo(RealSize(0, dc.GetCharHeight()), break_style, draw_as == DRAW_ACTIVE));
|
||||
line_start = i + 1;
|
||||
prev_width = 0;
|
||||
} else {
|
||||
RealSize s = dc.GetTextExtent(content.substr(line_start - this->start, i - line_start + 1));
|
||||
out.push_back(CharInfo(
|
||||
RealSize(s.width - prev_width, s.height),
|
||||
c == _(' ') ? BREAK_SPACE : BREAK_MAYBE,
|
||||
draw_as == DRAW_ACTIVE // from <soft> tag
|
||||
));
|
||||
prev_width = s.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double FontTextElement::minScale() const {
|
||||
return min(font->size(), font->scale_down_to) / max(0.01, font->size());
|
||||
return min(font->size(), font->scale_down_to) / max(0.01, font->size());
|
||||
}
|
||||
double FontTextElement::scaleStep() const {
|
||||
return 1. / max(font->size() * 4, 1.);
|
||||
return 1. / max(font->size() * 4, 1.);
|
||||
}
|
||||
|
||||
@@ -13,21 +13,21 @@
|
||||
// ----------------------------------------------------------------------------- : SymbolTextElement
|
||||
|
||||
void SymbolTextElement::draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const {
|
||||
if (!(what & DRAW_NORMAL)) return;
|
||||
if (font.font) {
|
||||
font.font->draw(dc, ctx, rect, font.size * scale, font.alignment, content.substr(start - this->start, end-start));
|
||||
}
|
||||
if (!(what & DRAW_NORMAL)) return;
|
||||
if (font.font) {
|
||||
font.font->draw(dc, ctx, rect, font.size * scale, font.alignment, content.substr(start - this->start, end-start));
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolTextElement::getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const {
|
||||
if (font.font) {
|
||||
font.font->getCharInfo(dc, ctx, font.size * scale, content.substr(start - this->start, end-start), out);
|
||||
}
|
||||
if (font.font) {
|
||||
font.font->getCharInfo(dc, ctx, font.size * scale, content.substr(start - this->start, end-start), out);
|
||||
}
|
||||
}
|
||||
|
||||
double SymbolTextElement::minScale() const {
|
||||
return min(font.size(), font.scale_down_to) / max(0.01, font.size());
|
||||
return min(font.size(), font.scale_down_to) / max(0.01, font.size());
|
||||
}
|
||||
double SymbolTextElement::scaleStep() const {
|
||||
return 1. / max(font.size * 4, 1.);
|
||||
return 1. / max(font.size * 4, 1.);
|
||||
}
|
||||
|
||||
+664
-664
File diff suppressed because it is too large
Load Diff
+116
-116
@@ -35,124 +35,124 @@
|
||||
*/
|
||||
class TextViewer {
|
||||
public:
|
||||
/// Information on a line in the textbox
|
||||
struct Line;
|
||||
|
||||
TextViewer();
|
||||
~TextViewer();
|
||||
|
||||
// --------------------------------------------------- : Drawing
|
||||
|
||||
/// Draw the given text with the given text style
|
||||
/** The drawing information is cached,
|
||||
* before calling draw again with different text/style reset() should be called
|
||||
*/
|
||||
void draw(RotatedDC& dc, const TextStyle& style, DrawWhat what);
|
||||
/// Draw an indicator for selected text
|
||||
void drawSelection(RotatedDC& dc, const TextStyle& style, size_t sel_start, size_t sel_end);
|
||||
/// Draw separators for <line> tags
|
||||
void drawSeparators(RotatedDC& dc);
|
||||
|
||||
/// Prepare the text for drawing, if it is not already prepared
|
||||
/** Returns true if something has been done */
|
||||
bool prepare(RotatedDC& dc, const String& text, TextStyle& style, Context&);
|
||||
/// Reset the cached data, at a new call to draw it will be recalculated
|
||||
/** If related, the new value is related to the old one, and layout information should be reused where possible
|
||||
*/
|
||||
void reset(bool related);
|
||||
/// Is the viewer prepare()d?
|
||||
bool prepared() const;
|
||||
|
||||
// --------------------------------------------------- : Positions
|
||||
|
||||
/// Find the character index that is on a line above/below index
|
||||
/** If this would move outisde the text, returns the input index */
|
||||
size_t moveLine(size_t index, int delta) const;
|
||||
|
||||
/// The character index of the start of the line that character #index is on
|
||||
size_t lineStart(size_t index) const;
|
||||
/// The character index past the end of the line that character #index is on
|
||||
size_t lineEnd (size_t index) const;
|
||||
|
||||
/// Find the index of the character at the given position
|
||||
/** If the position is before everything returns 0,
|
||||
* if it is after everything returns text.size().
|
||||
* The position is in internal coordinates */
|
||||
size_t indexAt(const RealPoint& pos) const;
|
||||
/// Find the position of the character at the given index
|
||||
/** The position is in internal coordinates */
|
||||
RealPoint posOf(size_t index) const;
|
||||
|
||||
/// Return the rectangle around a single character
|
||||
/** If 'first' prefers earlier lines */
|
||||
RealRect charRect(size_t index, bool first) const;
|
||||
/// Is the character at the given index visible?
|
||||
bool isVisible(size_t index) const;
|
||||
/// Find the first character index that is at/before/after the given index, and which has a nonzero width
|
||||
/** More precisely: it returns a position so that the character after it in the direction delta has nonzero width
|
||||
*/
|
||||
size_t firstVisibleChar(size_t index, int delta) const;
|
||||
|
||||
/// Return the height of the last line
|
||||
double heightOfLastLine() const;
|
||||
|
||||
// --------------------------------------------------- : Lines/scrolling
|
||||
|
||||
/// The total number of lines
|
||||
size_t lineCount() const;
|
||||
/// number of fully visible lines, height gives the height of the box
|
||||
size_t visibleLineCount(double height) const;
|
||||
/// the index of the first visible line
|
||||
size_t firstVisibleLine() const;
|
||||
// scroll so line_id becomes the first visible line
|
||||
void scrollTo(size_t line_id);
|
||||
/// Ensure the specified character is fully visible
|
||||
/* Always scrolls by a whole line.
|
||||
* Returns true if the editor has scrolled.
|
||||
*/
|
||||
bool ensureVisible(double height, size_t char_id);
|
||||
|
||||
/// Get exact scroll position
|
||||
double getExactScrollPosition() const;
|
||||
/// Set exact scroll position
|
||||
void setExactScrollPosition(double pos);
|
||||
|
||||
/// Information on a line in the textbox
|
||||
struct Line;
|
||||
|
||||
TextViewer();
|
||||
~TextViewer();
|
||||
|
||||
// --------------------------------------------------- : Drawing
|
||||
|
||||
/// Draw the given text with the given text style
|
||||
/** The drawing information is cached,
|
||||
* before calling draw again with different text/style reset() should be called
|
||||
*/
|
||||
void draw(RotatedDC& dc, const TextStyle& style, DrawWhat what);
|
||||
/// Draw an indicator for selected text
|
||||
void drawSelection(RotatedDC& dc, const TextStyle& style, size_t sel_start, size_t sel_end);
|
||||
/// Draw separators for <line> tags
|
||||
void drawSeparators(RotatedDC& dc);
|
||||
|
||||
/// Prepare the text for drawing, if it is not already prepared
|
||||
/** Returns true if something has been done */
|
||||
bool prepare(RotatedDC& dc, const String& text, TextStyle& style, Context&);
|
||||
/// Reset the cached data, at a new call to draw it will be recalculated
|
||||
/** If related, the new value is related to the old one, and layout information should be reused where possible
|
||||
*/
|
||||
void reset(bool related);
|
||||
/// Is the viewer prepare()d?
|
||||
bool prepared() const;
|
||||
|
||||
// --------------------------------------------------- : Positions
|
||||
|
||||
/// Find the character index that is on a line above/below index
|
||||
/** If this would move outisde the text, returns the input index */
|
||||
size_t moveLine(size_t index, int delta) const;
|
||||
|
||||
/// The character index of the start of the line that character #index is on
|
||||
size_t lineStart(size_t index) const;
|
||||
/// The character index past the end of the line that character #index is on
|
||||
size_t lineEnd (size_t index) const;
|
||||
|
||||
/// Find the index of the character at the given position
|
||||
/** If the position is before everything returns 0,
|
||||
* if it is after everything returns text.size().
|
||||
* The position is in internal coordinates */
|
||||
size_t indexAt(const RealPoint& pos) const;
|
||||
/// Find the position of the character at the given index
|
||||
/** The position is in internal coordinates */
|
||||
RealPoint posOf(size_t index) const;
|
||||
|
||||
/// Return the rectangle around a single character
|
||||
/** If 'first' prefers earlier lines */
|
||||
RealRect charRect(size_t index, bool first) const;
|
||||
/// Is the character at the given index visible?
|
||||
bool isVisible(size_t index) const;
|
||||
/// Find the first character index that is at/before/after the given index, and which has a nonzero width
|
||||
/** More precisely: it returns a position so that the character after it in the direction delta has nonzero width
|
||||
*/
|
||||
size_t firstVisibleChar(size_t index, int delta) const;
|
||||
|
||||
/// Return the height of the last line
|
||||
double heightOfLastLine() const;
|
||||
|
||||
// --------------------------------------------------- : Lines/scrolling
|
||||
|
||||
/// The total number of lines
|
||||
size_t lineCount() const;
|
||||
/// number of fully visible lines, height gives the height of the box
|
||||
size_t visibleLineCount(double height) const;
|
||||
/// the index of the first visible line
|
||||
size_t firstVisibleLine() const;
|
||||
// scroll so line_id becomes the first visible line
|
||||
void scrollTo(size_t line_id);
|
||||
/// Ensure the specified character is fully visible
|
||||
/* Always scrolls by a whole line.
|
||||
* Returns true if the editor has scrolled.
|
||||
*/
|
||||
bool ensureVisible(double height, size_t char_id);
|
||||
|
||||
/// Get exact scroll position
|
||||
double getExactScrollPosition() const;
|
||||
/// Set exact scroll position
|
||||
void setExactScrollPosition(double pos);
|
||||
|
||||
private:
|
||||
/// Scroll all lines a given amount
|
||||
void scrollBy(double delta);
|
||||
|
||||
/// Scroll all lines a given amount
|
||||
void scrollBy(double delta);
|
||||
|
||||
private:
|
||||
// --------------------------------------------------- : More drawing
|
||||
double scale; ///< Scale when drawing
|
||||
|
||||
// --------------------------------------------------- : Elements
|
||||
TextElements elements; ///< The elements of the prepared text
|
||||
|
||||
/// Find the elements in a string and add them to elements
|
||||
void prepareElements(const String&, const TextStyle& style, Context& ctx);
|
||||
|
||||
// --------------------------------------------------- : Lines
|
||||
vector<Line> lines; ///< The lines in the text box
|
||||
|
||||
/// Prepare the lines, layout the text
|
||||
void prepareLines(RotatedDC& dc, const String& text, TextStyle& style, Context& ctx);
|
||||
/// Find the scale to use for the text
|
||||
void prepareLinesTryScales(RotatedDC& dc, const String& text, const TextStyle& style, vector<CharInfo>& chars_out);
|
||||
/// Prepare the lines, layout the text; at a specific scale
|
||||
/** Stores output in lines_out */
|
||||
bool prepareLinesScale(RotatedDC& dc, const vector<CharInfo>& chars, const TextStyle& style, bool stop_if_too_long, vector<Line>& lines_out) const;
|
||||
/// Align the lines within the textbox
|
||||
void alignLines(RotatedDC& dc, const vector<CharInfo>& chars, const TextStyle& style);
|
||||
/// Align the lines of a single paragraph (a set of lines)
|
||||
void alignParagraph(size_t start_line, size_t end_line, const vector<CharInfo>& chars, const TextStyle& style, const RealRect& box);
|
||||
|
||||
/// Find the line the given index is on, returns the first line if the index is not found
|
||||
const Line& findLine(size_t index) const;
|
||||
|
||||
// helper : get the start coordinate of a line, this is 0 unless there is a contour mask
|
||||
double lineLeft (RotatedDC& dc, const TextStyle& style, double y) const;
|
||||
// helper : get the end coordinate of a line, this is width unless there is a contour mask
|
||||
double lineRight(RotatedDC& dc, const TextStyle& style, double y) const;
|
||||
// --------------------------------------------------- : More drawing
|
||||
double scale; ///< Scale when drawing
|
||||
|
||||
// --------------------------------------------------- : Elements
|
||||
TextElements elements; ///< The elements of the prepared text
|
||||
|
||||
/// Find the elements in a string and add them to elements
|
||||
void prepareElements(const String&, const TextStyle& style, Context& ctx);
|
||||
|
||||
// --------------------------------------------------- : Lines
|
||||
vector<Line> lines; ///< The lines in the text box
|
||||
|
||||
/// Prepare the lines, layout the text
|
||||
void prepareLines(RotatedDC& dc, const String& text, TextStyle& style, Context& ctx);
|
||||
/// Find the scale to use for the text
|
||||
void prepareLinesTryScales(RotatedDC& dc, const String& text, const TextStyle& style, vector<CharInfo>& chars_out);
|
||||
/// Prepare the lines, layout the text; at a specific scale
|
||||
/** Stores output in lines_out */
|
||||
bool prepareLinesScale(RotatedDC& dc, const vector<CharInfo>& chars, const TextStyle& style, bool stop_if_too_long, vector<Line>& lines_out) const;
|
||||
/// Align the lines within the textbox
|
||||
void alignLines(RotatedDC& dc, const vector<CharInfo>& chars, const TextStyle& style);
|
||||
/// Align the lines of a single paragraph (a set of lines)
|
||||
void alignParagraph(size_t start_line, size_t end_line, const vector<CharInfo>& chars, const TextStyle& style, const RealRect& box);
|
||||
|
||||
/// Find the line the given index is on, returns the first line if the index is not found
|
||||
const Line& findLine(size_t index) const;
|
||||
|
||||
// helper : get the start coordinate of a line, this is 0 unless there is a contour mask
|
||||
double lineLeft (RotatedDC& dc, const TextStyle& style, double y) const;
|
||||
// helper : get the end coordinate of a line, this is width unless there is a contour mask
|
||||
double lineRight(RotatedDC& dc, const TextStyle& style, double y) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user