draw all strokes, then draw all symbols

This commit is contained in:
GenevensiS
2026-01-14 06:40:28 +01:00
parent 68d6da3133
commit d10a71e925
2 changed files with 160 additions and 150 deletions
+33 -20
View File
@@ -277,21 +277,22 @@ void SymbolFont::draw(RotatedDC& dc, Context& ctx, const RealRect& rect, double
draw(dc, rect, scale, font, symbols);
}
void SymbolFont::draw(RotatedDC& dc, RealRect rect, double scale, const SymbolFontRef& font, const SplitSymbols& text) {
void SymbolFont::draw(RotatedDC& dc, RealRect rect, double scale, const SymbolFontRef& font, const SplitSymbols& symbols) {
vector<Bitmap> bmps;
vector<RealSize> bmp_sizes;
vector<RealPoint> bmp_poss;
double stretch = dc.getStretch();
FOR_EACH_CONST(sym, text) {
RealSize size = dc.trInvS(symbolSize(dc.trS(scale * font.size), sym));
double font_size = scale * font.size();
double font_size_ext = dc.trS(font_size);
double s_scale = font_size_ext / 15.;
int count = symbols.size();
for (int s = 0 ; s < count ; ++s) {
// 1. find bitmap, size and pos
auto const& dsym = symbols[s];
RealSize size = dc.trInvS(symbolSize(font_size_ext, dsym));
size = RealSize(size.width*stretch, size.height);
RealRect sym_rect = split_left(rect, size);
// TODO: draw all stroke effects and shadows first, then draw all symbols
drawSymbol(dc, sym_rect, scale, font, *sym.symbol, sym.draw_text, stretch);
}
}
void SymbolFont::drawSymbol(RotatedDC& dc, RealRect sym_rect, double scale, const SymbolFontRef& font, SymbolInFont& sym, const String& text, double stretch) {
// 1. find bitmap and pos
double font_size = scale * font.size();
double font_size_ext = dc.trS(scale * font.size());
SymbolInFont& sym = *dsym.symbol;
Bitmap bmp = sym.getBitmap(*this, font_size_ext);
if (!almost_equal(stretch, 1.0)) {
bmp = Bitmap(resample(bmp.ConvertToImage(), bmp.GetWidth() * stretch, bmp.GetHeight()));
@@ -299,7 +300,6 @@ void SymbolFont::drawSymbol(RotatedDC& dc, RealRect sym_rect, double scale, cons
RealSize bmp_size = dc.trInvS(RealSize(bmp));
RealPoint bmp_pos = align_in_rect(font.alignment(), bmp_size, sym_rect);
// 2. draw potential stroke or shadow
double s_scale = font_size_ext / 15.;
if (font.hasStroke()) {
// add margin
Image img = bmp.ConvertToImage();
@@ -392,24 +392,35 @@ void SymbolFont::drawSymbol(RotatedDC& dc, RealRect sym_rect, double scale, cons
RealPoint s_pos(bmp_pos.x - (s_size.width - bmp_size.width)/2, bmp_pos.y - (s_size.height - bmp_size.height)/2);
dc.DrawImage(s_img, s_pos + RealPoint(font.shadow_displacement_x(), font.shadow_displacement_y()) * scale);
}
// 3. draw bitmap
bmps.push_back(std::move(bmp));
bmp_sizes.push_back(bmp_size);
bmp_poss.push_back(bmp_pos);
}
for (int s = 0 ; s < count ; ++s) {
// 3. restart loop to draw bitmap
auto const& dsym = symbols[s];
const String& text = dsym.draw_text;
SymbolInFont& sym = *dsym.symbol;
Bitmap& bmp = bmps[s];
RealSize& bmp_size = bmp_sizes[s];
RealPoint& bmp_pos = bmp_poss[s];
dc.DrawBitmap(bmp, bmp_pos);
// 4. draw text
if (text.empty() || !sym.text_font) return;
if (text.empty() || !sym.text_font) continue;
// only use the bitmap rectangle
sym_rect = RealRect(bmp_pos, bmp_size);
RealRect sym_rect = RealRect(bmp_pos, bmp_size);
// subtract margins from size
sym_rect.x += font_size * sym.text_margin_left;
sym_rect.y += font_size * sym.text_margin_top;
sym_rect.width -= font_size * (sym.text_margin_left + sym.text_margin_right);
sym_rect.height -= font_size * (sym.text_margin_top + sym.text_margin_bottom);
// setup text, shrink it
double size = font_size * sym.text_font->size;
double text_size = font_size * sym.text_font->size;
double text_stretch = 1.0;
RealSize ts;
while (true) {
if (size <= 0) return; // text too small
dc.SetFont(*sym.text_font, size / sym.text_font->size);
if (text_size <= 0) goto continue_outer; // text too small
dc.SetFont(*sym.text_font, text_size / sym.text_font->size);
ts = dc.GetTextExtent(text);
if (ts.height <= sym_rect.height) {
if (ts.width <= sym_rect.width) {
@@ -421,12 +432,14 @@ void SymbolFont::drawSymbol(RotatedDC& dc, RealRect sym_rect, double scale, cons
}
}
// text doesn't fit
size -= dc.getFontSizeStep();
text_size -= dc.getFontSizeStep();
}
// align text
RealPoint text_pos = align_in_rect(sym.text_alignment, ts, sym_rect);
// draw text
dc.DrawTextWithShadowOrStroke(text, *sym.text_font, text_pos, font_size, text_stretch);
continue_outer:;
}
}
Image SymbolFont::getImage(double font_size, const DrawableSymbol& sym) {
+1 -4
View File
@@ -62,7 +62,7 @@ public:
void getCharInfo(RotatedDC& dc, Context& ctx, double font_size, const String& text, vector<CharInfo>& out);
/// Draw a piece of text prepared using split
void draw(RotatedDC& dc, RealRect rect, double scale, const SymbolFontRef& font, const SplitSymbols& text);
void draw(RotatedDC& dc, RealRect rect, double scale, const SymbolFontRef& font, const SplitSymbols& symbols);
/// Get information on characters in a string
void getCharInfo(RotatedDC& dc, double font_size, const SplitSymbols& text, vector<CharInfo>& out);
@@ -99,9 +99,6 @@ private:
/** may return nullptr */
SymbolInFont* defaultSymbol() const;
/// Draws a single symbol inside the given rectangle
void drawSymbol(RotatedDC& dc, RealRect sym_rect, double scale, const SymbolFontRef& font, SymbolInFont& sym, const String& text, double stretch);
/// Size of a single symbol, including spacing
RealSize symbolSize (double font_size, const DrawableSymbol& sym);
public: