Implemented exporting symbol fonts;

Rendering symbols to an image always uses anti-aliassing (by downsampling from a large size);
Finished the spoiler export template;
Added <soft-line> tag to make line breaks use the line height for soft line breaks

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@440 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2007-06-27 18:58:43 +00:00
parent ef1ac8fd5b
commit 31b7380d99
19 changed files with 532 additions and 132 deletions
+1
View File
@@ -48,6 +48,7 @@ struct ExportInfo {
String directory_relative; ///< The directory for storing extra files (or "" if !export->create_directory)
/// This is just the directory name
String directory_absolute; ///< The absolute path of the directory
set<String> exported_images; ///< Images (from symbol font) already exported
};
DECLARE_DYNAMIC_ARG(ExportInfo*, export_info);
+66 -23
View File
@@ -74,6 +74,9 @@ class SymbolInFont : public IntrusivePtrBase<SymbolInFont> {
public:
SymbolInFont();
/// Get a shrunk, zoomed image
Image getImage(Package& pkg, double size);
/// Get a shrunk, zoomed bitmap
Bitmap getBitmap(Package& pkg, double size);
@@ -107,23 +110,26 @@ SymbolInFont::SymbolInFont()
if (img_size <= 0) img_size = 1;
}
Image SymbolInFont::getImage(Package& pkg, double size) {
// generate new image
if (!image.isReady()) {
throw Error(_("No image specified for symbol with code '") + code + _("' in symbol font."));
}
Image img = image.generate(GeneratedImage::Options(0, 0, &pkg));
actual_size = wxSize(img.GetWidth(), img.GetHeight());
// scale to match expected size
Image resampled_image((int) (actual_size.GetWidth() * size / img_size),
(int) (actual_size.GetHeight() * size / img_size), false);
if (!resampled_image.Ok()) return Image(1,1);
resample(img, resampled_image);
return resampled_image;
}
Bitmap SymbolInFont::getBitmap(Package& pkg, double size) {
// is this bitmap already loaded/generated?
Bitmap& bmp = bitmaps[size];
if (!bmp.Ok()) {
// generate new bitmap
if (!image.isReady()) {
throw Error(_("No image specified for symbol with code '") + code + _("' in symbol font."));
}
Image img = image.generate(GeneratedImage::Options(0, 0, &pkg));
actual_size = wxSize(img.GetWidth(), img.GetHeight());
// scale to match expected size
Image resampled_image((int) (actual_size.GetWidth() * size / img_size),
(int) (actual_size.GetHeight() * size / img_size), false);
if (!resampled_image.Ok()) return Bitmap(1,1);
resample(img, resampled_image);
// convert to bitmap, store for later use
bmp = Bitmap(resampled_image);
// generate image, convert to bitmap, store for later use
bmp = Bitmap(getImage(pkg, size));
}
return bmp;
}
@@ -166,16 +172,6 @@ IMPLEMENT_REFLECTION(SymbolInFont) {
// ----------------------------------------------------------------------------- : SymbolFont : splitting
class SymbolFont::DrawableSymbol {
public:
DrawableSymbol(const String& text, SymbolInFont* symbol)
: text(text), symbol(symbol)
{}
String text; ///< Original text
SymbolInFont* symbol; ///< Symbol to draw, if nullptr, use the default symbol and draw the text
};
void SymbolFont::split(const String& text, SplitSymbols& out) const {
// read a single symbol until we are done with the text
for (size_t pos = 0 ; pos < text.size() ; ) {
@@ -286,6 +282,53 @@ void SymbolFont::drawWithText(RotatedDC& dc, const RealRect& rect, double font_s
dc.DrawText(text, text_pos);
}
Image SymbolFont::getImage(double font_size, const DrawableSymbol& sym) {
if (sym.symbol) {
return sym.symbol->getImage(*this, font_size);
} else {
if (!text_font) return Image(1,1); // failed
// draw on default symbol
SymbolInFont* def = defaultSymbol();
if (!def) return Image(1,1); // failed
Bitmap bmp(def->getImage(*this, font_size));
// memory dc to work with
wxMemoryDC dc;
dc.SelectObject(bmp);
RealRect sym_rect(0,0,bmp.GetWidth(),bmp.GetHeight());
RotatedDC rdc(dc, 0, sym_rect, 1, QUALITY_AA);
// subtract margins from size
sym_rect.x += text_margin_left;
sym_rect.y += text_margin_top;
sym_rect.width -= text_margin_left + text_margin_right;
sym_rect.height -= text_margin_top + text_margin_bottom;
// setup text, shrink it
double size = text_font->size; // TODO : incorporate shrink factor?
RealSize ts;
while (true) {
if (size <= 0) return def->getImage(*this, font_size); // text too small
rdc.SetFont(*text_font, size / text_font->size);
ts = rdc.GetTextExtent(sym.text);
if (ts.width <= sym_rect.width && ts.height <= sym_rect.height) {
break; // text fits
} else {
// text doesn't fit
size -= rdc.getFontSizeStep();
}
}
// align text
RealPoint text_pos = align_in_rect(text_alignment, ts, sym_rect);
// draw text
if (text_font->hasShadow()) {
rdc.SetTextForeground(text_font->shadow_color);
rdc.DrawText(sym.text, text_pos + text_font->shadow_displacement);
}
rdc.SetTextForeground(text_font->color);
rdc.DrawText(sym.text, text_pos);
// done
dc.SelectObject(wxNullBitmap);
return bmp.ConvertToImage();
}
}
// ----------------------------------------------------------------------------- : SymbolFont : sizes
+15 -2
View File
@@ -35,12 +35,22 @@ class SymbolFont : public Packaged {
// Script update
void update(Context& ctx) const;
class DrawableSymbol;
/// A symbol to be drawn
class DrawableSymbol {
public:
inline DrawableSymbol(const String& text, SymbolInFont* symbol)
: text(text), symbol(symbol)
{}
String text; ///< Original text
SymbolInFont* symbol; ///< Symbol to draw, if nullptr, use the default symbol and draw the text
};
typedef vector<DrawableSymbol> SplitSymbols;
/// Split a string into separate symbols for drawing and for determining their size
void split(const String& text, SplitSymbols& out) const;
/// Draw a piece of text prepared using split
/// Draw a piece of text
void draw(RotatedDC& dc, Context& ctx, const RealRect& rect, double font_size, const Alignment& align, const String& text);
/// Get information on characters in a string
void getCharInfo(RotatedDC& dc, Context& ctx, double font_size, const String& text, vector<CharInfo>& out);
@@ -50,6 +60,9 @@ class SymbolFont : public Packaged {
/// Get information on characters in a string
void getCharInfo(RotatedDC& dc, double font_size, const SplitSymbols& text, vector<CharInfo>& out);
/// Get the image for a symbol
Image getImage(double font_size, const DrawableSymbol& symbol);
static String typeNameStatic();
virtual String typeName() const;