mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-13 05:57:00 -04:00
Added 'paragraph height' property to split a text field into multiple boxes.
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@666 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -76,6 +76,8 @@ The rest of the properties depend on the type of [[type:field]] this style is fo
|
|||||||
| ^^^ @line height soft max@ ^^^ ''disabled'' When there is still vertical room in the text box, increase the line heights to at most these values to spread the text more evenly.
|
| ^^^ @line height soft max@ ^^^ ''disabled'' When there is still vertical room in the text box, increase the line heights to at most these values to spread the text more evenly.
|
||||||
| ^^^ @line height hard max@ ^^^ ^^^ ^^^
|
| ^^^ @line height hard max@ ^^^ ^^^ ^^^
|
||||||
| ^^^ @line height line max@ ^^^ ^^^ ^^^
|
| ^^^ @line height line max@ ^^^ ^^^ ^^^
|
||||||
|
| ^^^ @paragraph height@ [[type:double]] ''flexible'' The height of paragraphs. If specified, each paragraph is given this much space, and aligned inside that space as specified by @alignment@.<br/>
|
||||||
|
A paragraph break is any line break that is not soft (i.e. caused by word wrap or a @"<soft>"@ break).
|
||||||
| ^^^ @mask@ [[type:filename]] ''none'' A mask that indicates where in the box text can be placed.<br/>
|
| ^^^ @mask@ [[type:filename]] ''none'' A mask that indicates where in the box text can be placed.<br/>
|
||||||
Text is never put in black areas of the box:<br/>
|
Text is never put in black areas of the box:<br/>
|
||||||
<img src="style-text-mask.png" alt=""/>
|
<img src="style-text-mask.png" alt=""/>
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ TextStyle::TextStyle(const TextFieldP& field)
|
|||||||
, line_height_soft_max(0.0)
|
, line_height_soft_max(0.0)
|
||||||
, line_height_hard_max(0.0)
|
, line_height_hard_max(0.0)
|
||||||
, line_height_line_max(0.0)
|
, line_height_line_max(0.0)
|
||||||
|
, paragraph_height(-1)
|
||||||
, direction(LEFT_TO_RIGHT)
|
, direction(LEFT_TO_RIGHT)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -114,6 +115,7 @@ IMPLEMENT_REFLECTION(TextStyle) {
|
|||||||
REFLECT(line_height_soft_max);
|
REFLECT(line_height_soft_max);
|
||||||
REFLECT(line_height_hard_max);
|
REFLECT(line_height_hard_max);
|
||||||
REFLECT(line_height_line_max);
|
REFLECT(line_height_line_max);
|
||||||
|
REFLECT(paragraph_height);
|
||||||
REFLECT_N("mask", mask_filename);
|
REFLECT_N("mask", mask_filename);
|
||||||
REFLECT(direction);
|
REFLECT(direction);
|
||||||
reflect_content(tag, *this);
|
reflect_content(tag, *this);
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ class TextStyle : public Style {
|
|||||||
double line_height_soft_max; ///< Maximum line height
|
double line_height_soft_max; ///< Maximum line height
|
||||||
double line_height_hard_max; ///< Maximum line height
|
double line_height_hard_max; ///< Maximum line height
|
||||||
double line_height_line_max; ///< Maximum line height
|
double line_height_line_max; ///< Maximum line height
|
||||||
|
double paragraph_height; ///< Fixed height of paragraphs
|
||||||
String mask_filename; ///< Filename of the mask
|
String mask_filename; ///< Filename of the mask
|
||||||
ContourMask mask; ///< Mask to fit the text to (may be null)
|
ContourMask mask; ///< Mask to fit the text to (may be null)
|
||||||
Direction direction; ///< In what direction is text layed out?
|
Direction direction; ///< In what direction is text layed out?
|
||||||
|
|||||||
+39
-15
@@ -635,17 +635,37 @@ double TextViewer::lineRight(RotatedDC& dc, const TextStyle& style, double y) co
|
|||||||
|
|
||||||
|
|
||||||
void TextViewer::alignLines(RotatedDC& dc, const vector<CharInfo>& chars, const TextStyle& style) {
|
void TextViewer::alignLines(RotatedDC& dc, const vector<CharInfo>& chars, const TextStyle& style) {
|
||||||
// Find height of the text, don't count the last lines if they are empty
|
// Size of the box
|
||||||
double height = 0;
|
|
||||||
FOR_EACH_REVERSE(l, lines) {
|
|
||||||
height = l.top + l.line_height;
|
|
||||||
if (l.line_height) break; // not an empty line
|
|
||||||
}
|
|
||||||
// amount to shift all lines vertically
|
|
||||||
RealSize s = add_diagonal(
|
RealSize s = add_diagonal(
|
||||||
dc.getInternalSize(),
|
dc.getInternalSize(),
|
||||||
-RealSize(style.padding_left+style.padding_right, style.padding_top + style.padding_bottom));
|
-RealSize(style.padding_left+style.padding_right, style.padding_top + style.padding_bottom));
|
||||||
|
if (style.paragraph_height <= 0) {
|
||||||
|
// whole text box alignment
|
||||||
|
alignParagraph(0, lines.size(), chars, style, RealRect(RealPoint(0,0),s));
|
||||||
|
} else {
|
||||||
|
// per paragraph alignment
|
||||||
|
size_t start = 0;
|
||||||
|
int n = 0;
|
||||||
|
for (size_t last = 0 ; last < lines.size() ; ++last) {
|
||||||
|
if (lines[last].break_after != BREAK_SOFT || last == lines.size()) {
|
||||||
|
alignParagraph(start, last + 1, chars, style, RealRect(0, n*style.paragraph_height, s.width, style.paragraph_height));
|
||||||
|
start = last + 1;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextViewer::alignParagraph(size_t start_line, size_t end_line, const vector<CharInfo>& chars, const TextStyle& style, const RealRect& s) {
|
||||||
|
if (start_line >= end_line) return;
|
||||||
|
// Find height of the text, don't count the last lines if they are empty
|
||||||
|
double height = 0;
|
||||||
|
for (size_t li = end_line - 1 ; li + 1 > start_line ; --li) {
|
||||||
|
Line& l = lines[li];
|
||||||
|
height = l.top + l.line_height;
|
||||||
|
if (l.line_height) break; // not an empty line
|
||||||
|
}
|
||||||
|
height -= lines[start_line].top;
|
||||||
// stretch lines by increasing the space between them
|
// stretch lines by increasing the space between them
|
||||||
if (height < s.height) {
|
if (height < s.height) {
|
||||||
double d_soft = max(0.0, style.line_height_soft_max - style.line_height_soft);
|
double d_soft = max(0.0, style.line_height_soft_max - style.line_height_soft);
|
||||||
@@ -662,7 +682,8 @@ void TextViewer::alignLines(RotatedDC& dc, const vector<CharInfo>& chars, const
|
|||||||
bool line = d_line >= stop;
|
bool line = d_line >= stop;
|
||||||
// sum of the line height we can apply this to?
|
// sum of the line height we can apply this to?
|
||||||
double sum = 0;
|
double sum = 0;
|
||||||
FOR_EACH(l, lines) {
|
for (size_t li = start_line ; li < end_line ; ++li) {
|
||||||
|
const Line& l = lines[li];
|
||||||
if ((soft && l.break_after == BREAK_SOFT)
|
if ((soft && l.break_after == BREAK_SOFT)
|
||||||
|| (hard && l.break_after == BREAK_HARD)
|
|| (hard && l.break_after == BREAK_HARD)
|
||||||
|| (line && l.break_after == BREAK_LINE)) sum += l.line_height;
|
|| (line && l.break_after == BREAK_LINE)) sum += l.line_height;
|
||||||
@@ -672,7 +693,8 @@ void TextViewer::alignLines(RotatedDC& dc, const vector<CharInfo>& chars, const
|
|||||||
double to_add = min(stop, (s.height - height) / sum);
|
double to_add = min(stop, (s.height - height) / sum);
|
||||||
// apply
|
// apply
|
||||||
double add = 0;
|
double add = 0;
|
||||||
FOR_EACH(l, lines) {
|
for (size_t li = start_line ; li < end_line ; ++li) {
|
||||||
|
Line& l = lines[li];
|
||||||
l.top += add;
|
l.top += add;
|
||||||
// adjust next line by..
|
// adjust next line by..
|
||||||
if ((soft && l.break_after == BREAK_SOFT)
|
if ((soft && l.break_after == BREAK_SOFT)
|
||||||
@@ -684,9 +706,11 @@ void TextViewer::alignLines(RotatedDC& dc, const vector<CharInfo>& chars, const
|
|||||||
}
|
}
|
||||||
if (style.alignment == ALIGN_TOP_LEFT) return;
|
if (style.alignment == ALIGN_TOP_LEFT) return;
|
||||||
// align
|
// align
|
||||||
double vdelta = align_delta_y(style.alignment, s.height, height);
|
double vdelta = align_delta_y(style.alignment, s.height, height)
|
||||||
|
+ s.y - lines[start_line].top;
|
||||||
// align all lines
|
// align all lines
|
||||||
FOR_EACH(l, lines) {
|
for (size_t li = start_line ; li < end_line ; ++li) {
|
||||||
|
Line& l = lines[li];
|
||||||
l.top += vdelta;
|
l.top += vdelta;
|
||||||
// amount to shift all characters horizontally
|
// amount to shift all characters horizontally
|
||||||
double width = l.positions[l.end_or_soft - l.start];
|
double width = l.positions[l.end_or_soft - l.start];
|
||||||
@@ -699,7 +723,7 @@ void TextViewer::alignLines(RotatedDC& dc, const vector<CharInfo>& chars, const
|
|||||||
if (count <= 0) count = 1; // prevent div by 0
|
if (count <= 0) count = 1; // prevent div by 0
|
||||||
int i = 0;
|
int i = 0;
|
||||||
FOR_EACH(c, l.positions) {
|
FOR_EACH(c, l.positions) {
|
||||||
c += hdelta * i++ / count;
|
c += s.x + hdelta * i++ / count;
|
||||||
}
|
}
|
||||||
} else if (style.alignment & ALIGN_JUSTIFY_WORDS) {
|
} else if (style.alignment & ALIGN_JUSTIFY_WORDS) {
|
||||||
// justify text, by words
|
// justify text, by words
|
||||||
@@ -712,13 +736,13 @@ void TextViewer::alignLines(RotatedDC& dc, const vector<CharInfo>& chars, const
|
|||||||
if (count == 0) count = 1; // prevent div by 0
|
if (count == 0) count = 1; // prevent div by 0
|
||||||
int i = 0; size_t j = l.start;
|
int i = 0; size_t j = l.start;
|
||||||
FOR_EACH(c, l.positions) {
|
FOR_EACH(c, l.positions) {
|
||||||
c += hdelta * i / count;
|
c += s.x + hdelta * i / count;
|
||||||
if (j < l.end_or_soft && chars[j++].break_after == BREAK_SPACE) i++;
|
if (j < l.end_or_soft && chars[j++].break_after == BREAK_SPACE) i++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// simple alignment
|
// simple alignment
|
||||||
justifying = false;
|
justifying = false;
|
||||||
double hdelta = align_delta_x(style.alignment, s.width, width);
|
double hdelta = s.x + align_delta_x(style.alignment, s.width, width);
|
||||||
FOR_EACH(c, l.positions) {
|
FOR_EACH(c, l.positions) {
|
||||||
c += hdelta;
|
c += hdelta;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,6 +143,8 @@ class TextViewer {
|
|||||||
bool prepareLinesScale(RotatedDC& dc, const vector<CharInfo>& chars, const TextStyle& style, bool stop_if_too_long, vector<Line>& lines_out) const;
|
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
|
/// Align the lines within the textbox
|
||||||
void alignLines(RotatedDC& dc, const vector<CharInfo>& chars, const TextStyle& style);
|
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
|
/// 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;
|
const Line& findLine(size_t index) const;
|
||||||
|
|||||||
Reference in New Issue
Block a user