Use a dedicated BitmapFont instance per Canvas.

Before this commit, updates to the bitmap font in the graphics window
cause missing characters in the text window and vice versa. This is
because BitmapFont contains a texture that's mutated, and sharing it
would also require sharing display lists between GL contexts, which
is not done (and overly complicated for this case anyway).
pull/106/head
EvilSpirit 2017-01-10 09:52:51 +07:00 committed by whitequark
parent 33c9ffb5ca
commit fb667fb8bb
7 changed files with 31 additions and 23 deletions

View File

@ -800,7 +800,7 @@ void GraphicsWindow::Draw(Canvas *canvas) {
}
void GraphicsWindow::Paint() {
if (!canvas) return;
if(!canvas) return;
havePainted = true;

View File

@ -211,6 +211,13 @@ Canvas::hFill Canvas::GetFill(const Fill &fill) {
return fills.AddAndAssignId(&fillCopy);
}
BitmapFont *Canvas::GetBitmapFont() {
if(bitmapFont.IsEmpty()) {
bitmapFont = BitmapFont::Create();
}
return &bitmapFont;
}
std::shared_ptr<BatchCanvas> Canvas::CreateBatch() {
return std::shared_ptr<BatchCanvas>();
}
@ -292,7 +299,7 @@ void UiCanvas::DrawPixmap(std::shared_ptr<const Pixmap> pm, int x, int y, int zI
}
void UiCanvas::DrawBitmapChar(char32_t codepoint, int x, int y, RgbaColor color, int zIndex) {
BitmapFont *font = BitmapFont::Builtin();
BitmapFont *font = canvas->GetBitmapFont();
Canvas::Fill fill = {};
fill.layer = Canvas::Layer::NORMAL;
@ -324,7 +331,7 @@ void UiCanvas::DrawBitmapChar(char32_t codepoint, int x, int y, RgbaColor color,
}
void UiCanvas::DrawBitmapText(const std::string &str, int x, int y, RgbaColor color, int zIndex) {
BitmapFont *font = BitmapFont::Builtin();
BitmapFont *font = canvas->GetBitmapFont();
for(char32_t codepoint : ReadUTF8(str)) {
DrawBitmapChar(codepoint, x, y, color, zIndex);

View File

@ -137,12 +137,14 @@ public:
IdList<Stroke, hStroke> strokes;
IdList<Fill, hFill> fills;
BitmapFont bitmapFont;
Canvas() : strokes(), fills() {}
Canvas() : strokes(), fills(), bitmapFont() {}
virtual void Clear();
hStroke GetStroke(const Stroke &stroke);
hFill GetFill(const Fill &fill);
BitmapFont *GetBitmapFont();
virtual const Camera &GetCamera() const = 0;

View File

@ -645,22 +645,19 @@ size_t BitmapFont::GetWidth(const std::string &str) {
return width;
}
BitmapFont *BitmapFont::Builtin() {
static BitmapFont Font;
if(Font.IsEmpty()) {
Font = BitmapFont::From(LoadStringFromGzip("fonts/unifont.hex.gz"));
// Unifont doesn't have a glyph for U+0020.
Font.AddGlyph(0x0020, Pixmap::Create(Pixmap::Format::RGB, 8, 16));
Font.AddGlyph(0xE000, LoadPng("fonts/private/0-check-false.png"));
Font.AddGlyph(0xE001, LoadPng("fonts/private/1-check-true.png"));
Font.AddGlyph(0xE002, LoadPng("fonts/private/2-radio-false.png"));
Font.AddGlyph(0xE003, LoadPng("fonts/private/3-radio-true.png"));
Font.AddGlyph(0xE004, LoadPng("fonts/private/4-stipple-dot.png"));
Font.AddGlyph(0xE005, LoadPng("fonts/private/5-stipple-dash-long.png"));
Font.AddGlyph(0xE006, LoadPng("fonts/private/6-stipple-dash.png"));
Font.AddGlyph(0xE007, LoadPng("fonts/private/7-stipple-zigzag.png"));
}
return &Font;
BitmapFont BitmapFont::Create() {
BitmapFont Font = BitmapFont::From(LoadStringFromGzip("fonts/unifont.hex.gz"));
// Unifont doesn't have a glyph for U+0020.
Font.AddGlyph(0x0020, Pixmap::Create(Pixmap::Format::RGB, 8, 16));
Font.AddGlyph(0xE000, LoadPng("fonts/private/0-check-false.png"));
Font.AddGlyph(0xE001, LoadPng("fonts/private/1-check-true.png"));
Font.AddGlyph(0xE002, LoadPng("fonts/private/2-radio-false.png"));
Font.AddGlyph(0xE003, LoadPng("fonts/private/3-radio-true.png"));
Font.AddGlyph(0xE004, LoadPng("fonts/private/4-stipple-dot.png"));
Font.AddGlyph(0xE005, LoadPng("fonts/private/5-stipple-dash-long.png"));
Font.AddGlyph(0xE006, LoadPng("fonts/private/6-stipple-dash.png"));
Font.AddGlyph(0xE007, LoadPng("fonts/private/7-stipple-zigzag.png"));
return Font;
}
//-----------------------------------------------------------------------------

View File

@ -62,7 +62,7 @@ public:
uint16_t nextPosition;
static BitmapFont From(std::string &&unifontData);
static BitmapFont *Builtin();
static BitmapFont Create();
bool IsEmpty() const { return unifontData.empty(); }
const Glyph &GetGlyph(char32_t codepoint);

View File

@ -292,6 +292,8 @@ void TextWindow::ClearScreen() {
}
void TextWindow::Printf(bool halfLine, const char *fmt, ...) {
if(!canvas) return;
va_list vl;
va_start(vl, fmt);
@ -429,7 +431,7 @@ void TextWindow::Printf(bool halfLine, const char *fmt, ...) {
}
for(utf8_iterator it(buf); *it; ++it) {
for(size_t i = 0; i < BitmapFont::Builtin()->GetWidth(*it); i++) {
for(size_t i = 0; i < canvas->GetBitmapFont()->GetWidth(*it); i++) {
if(c >= MAX_COLS) goto done;
text[r][c] = (i == 0) ? *it : ' ';
meta[r][c].fg = fg;

View File

@ -239,7 +239,7 @@ bool GraphicsWindow::ToolbarDrawOrHitTest(int mx, int my,
}
}
int tw = BitmapFont::Builtin()->GetWidth(tooltip) * 8 + 10,
int tw = canvas->canvas->GetBitmapFont()->GetWidth(tooltip) * 8 + 10,
th = SS.TW.LINE_HEIGHT + 2;
int ox = toolbarMouseX + 3, oy = toolbarMouseY + 3;