diff options
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/VectorRendererSpec.cpp | 6 | ||||
-rw-r--r-- | graphics/fonts/bdf.cpp | 177 | ||||
-rw-r--r-- | graphics/fonts/bdf.h | 9 | ||||
-rw-r--r-- | graphics/fonts/consolefont.cpp | 3 | ||||
-rw-r--r-- | graphics/fonts/newfont.cpp | 3 | ||||
-rw-r--r-- | graphics/fonts/newfont_big.cpp | 3 | ||||
-rw-r--r-- | graphics/macgui/macfontmanager.cpp | 282 | ||||
-rw-r--r-- | graphics/macgui/macfontmanager.h | 134 | ||||
-rw-r--r-- | graphics/macgui/macmenu.cpp | 13 | ||||
-rw-r--r-- | graphics/macgui/macwindow.cpp | 5 | ||||
-rw-r--r-- | graphics/macgui/macwindow.h | 2 | ||||
-rw-r--r-- | graphics/macgui/macwindowmanager.cpp | 130 | ||||
-rw-r--r-- | graphics/macgui/macwindowmanager.h | 29 | ||||
-rw-r--r-- | graphics/managed_surface.cpp | 6 | ||||
-rw-r--r-- | graphics/managed_surface.h | 6 | ||||
-rw-r--r-- | graphics/module.mk | 1 | ||||
-rw-r--r-- | graphics/screen.h | 4 | ||||
-rw-r--r-- | graphics/transparent_surface.cpp | 2 |
18 files changed, 645 insertions, 170 deletions
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 9aed3301fa..3dd9c86f45 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -850,7 +850,7 @@ blitSubSurfaceClip(const Graphics::Surface *source, const Common::Rect &r, const } template<typename PixelType> -void VectorRendererSpec<PixelType>:: +void VectorRendererSpec<PixelType>:: blitKeyBitmap(const Graphics::Surface *source, const Common::Rect &r) { int16 x = r.left; int16 y = r.top; @@ -3125,7 +3125,7 @@ drawBorderRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType co PixelType color1 = color; PixelType color2 = color; - + while (sw++ < Base::_strokeWidth) { blendFillClip(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t, x1 + r, y1 + sp/pitch); // top @@ -3297,7 +3297,7 @@ drawInteriorRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType x1 + r - x, y1 + h - r + y); gradientFillClip(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x, x1 + r - y, y1 + h - r + x); - + BE_DRAWCIRCLE_XCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r); } diff --git a/graphics/fonts/bdf.cpp b/graphics/fonts/bdf.cpp index 3476838911..e109d076a1 100644 --- a/graphics/fonts/bdf.cpp +++ b/graphics/fonts/bdf.cpp @@ -41,13 +41,27 @@ BdfFont::~BdfFont() { delete[] _data.bitmaps; delete[] _data.advances; delete[] _data.boxes; + delete[] _data.familyName; + delete[] _data.slant; } } +const char *BdfFont::getFamilyName() const { + return _data.familyName; +} + +const char *BdfFont::getFontSlant() const { + return _data.slant; +} + int BdfFont::getFontHeight() const { return _data.height; } +int BdfFont::getFontSize() const { + return _data.size; +} + int BdfFont::getMaxCharWidth() const { return _data.maxAdvance; } @@ -102,7 +116,7 @@ void BdfFont::drawChar(Surface *dst, uint32 chr, const int tx, const int ty, con // TODO: Where is the relation between the max advance being smaller or // equal to 50 and the decision of the theme designer? // asserting _data.maxAdvance <= 50: let the theme designer decide what looks best - assert(_data.maxAdvance <= 50); + //assert(_data.maxAdvance <= 50); assert(dst->format.bytesPerPixel == 1 || dst->format.bytesPerPixel == 2 || dst->format.bytesPerPixel == 4); const int idx = mapToIndex(chr); @@ -285,6 +299,7 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { memset(bitmaps, 0, sizeof(byte *) * font.numCharacters); byte *advances = new byte[font.numCharacters]; BdfBoundingBox *boxes = new BdfBoundingBox[font.numCharacters]; + char *familyName, *slant; int descent = -1; @@ -297,6 +312,8 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { delete[] bitmaps; delete[] advances; delete[] boxes; + delete[] familyName; + delete[] slant; return 0; } @@ -310,6 +327,8 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { delete[] bitmaps; delete[] advances; delete[] boxes; + delete[] familyName; + delete[] slant; return 0; } @@ -317,6 +336,17 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { font.defaultBox.height = height; font.defaultBox.xOffset = xOffset; font.defaultBox.yOffset = yOffset; + } else if (line.hasPrefix("PIXEL_SIZE ")) { + if (sscanf(line.c_str(), "PIXEL_SIZE %d", &font.size) != 1) { + warning("BdfFont::loadFont: Invalid PIXEL_SIZE"); + freeBitmaps(bitmaps, font.numCharacters); + delete[] bitmaps; + delete[] advances; + delete[] boxes; + delete[] familyName; + delete[] slant; + return 0; + } } else if (line.hasPrefix("FONT_ASCENT ")) { if (sscanf(line.c_str(), "FONT_ASCENT %d", &font.ascent) != 1) { warning("BdfFont::loadFont: Invalid FONT_ASCENT"); @@ -324,6 +354,8 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { delete[] bitmaps; delete[] advances; delete[] boxes; + delete[] familyName; + delete[] slant; return 0; } } else if (line.hasPrefix("FONT_DESCENT ")) { @@ -333,6 +365,8 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { delete[] bitmaps; delete[] advances; delete[] boxes; + delete[] familyName; + delete[] slant; return 0; } } else if (line.hasPrefix("DEFAULT_CHAR ")) { @@ -342,6 +376,8 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { delete[] bitmaps; delete[] advances; delete[] boxes; + delete[] familyName; + delete[] slant; return 0; } } else if (line.hasPrefix("STARTCHAR ")) { @@ -366,6 +402,8 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { delete[] bitmaps; delete[] advances; delete[] boxes; + delete[] familyName; + delete[] slant; return 0; } @@ -374,6 +412,40 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { advances[encoding] = advance; boxes[encoding] = box; } + } else if (line.hasPrefix("FAMILY_NAME \"")) { + familyName = new char[line.size()]; // We will definitely fit here + Common::strlcpy(familyName, &line.c_str()[13], line.size()); + char *p = &familyName[strlen(familyName)]; + while (p != familyName && *p != '"') + p--; + if (p == familyName) { + warning("BdfFont::loadFont: Invalid FAMILY_NAME"); + freeBitmaps(bitmaps, font.numCharacters); + delete[] bitmaps; + delete[] advances; + delete[] boxes; + delete[] familyName; + delete[] slant; + return 0; + } + *p = '\0'; // Remove last quote + } else if (line.hasPrefix("SLANT \"")) { + slant = new char[line.size()]; // We will definitely fit here + Common::strlcpy(slant, &line.c_str()[7], line.size()); + char *p = &slant[strlen(slant)]; + while (p != slant && *p != '"') + p--; + if (p == slant) { + warning("BdfFont::loadFont: Invalid SLANT"); + freeBitmaps(bitmaps, font.numCharacters); + delete[] bitmaps; + delete[] advances; + delete[] boxes; + delete[] familyName; + delete[] slant; + return 0; + } + *p = '\0'; // Remove last quote } else if (line == "ENDFONT") { break; } @@ -385,6 +457,8 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { delete[] bitmaps; delete[] advances; delete[] boxes; + delete[] familyName; + delete[] slant; return 0; } @@ -393,6 +467,8 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { font.bitmaps = bitmaps; font.advances = advances; font.boxes = boxes; + font.familyName = familyName; + font.slant = slant; int firstCharacter = font.numCharacters; int lastCharacter = -1; @@ -425,6 +501,8 @@ BdfFont *BdfFont::loadFont(Common::SeekableReadStream &stream) { delete[] font.bitmaps; delete[] font.advances; delete[] font.boxes; + delete[] familyName; + delete[] slant; return 0; } @@ -622,4 +700,101 @@ BdfFont *BdfFont::loadFromCache(Common::SeekableReadStream &stream) { return new BdfFont(data, DisposeAfterUse::YES); } +BdfFont *BdfFont::scaleFont(BdfFont *src, int newSize) { + if (!src) { + warning("Emtpy font reference in scale font"); + return NULL; + } + + if (src->getFontSize() == 0) { + warning("Requested to scale 0 size font"); + return NULL; + } + + float scale = (float)newSize / (float)src->getFontSize(); + + BdfFontData data; + + data.maxAdvance = (int)((float)src->_data.maxAdvance * scale); + data.height = (int)((float)src->_data.height * scale); + data.defaultBox.width = (int)((float)src->_data.defaultBox.width * scale); + data.defaultBox.height = (int)((float)src->_data.defaultBox.height * scale); + data.defaultBox.xOffset = (int)((float)src->_data.defaultBox.xOffset * scale); + data.defaultBox.yOffset = (int)((float)src->_data.defaultBox.yOffset * scale); + data.ascent = (int)((float)src->_data.ascent * scale); + data.firstCharacter = src->_data.firstCharacter; + data.defaultCharacter = src->_data.defaultCharacter; + data.numCharacters = src->_data.numCharacters; + data.familyName = strdup(src->_data.familyName); + data.slant = strdup(src->_data.slant); + + BdfBoundingBox *boxes = new BdfBoundingBox[data.numCharacters]; + for (int i = 0; i < data.numCharacters; ++i) { + boxes[i].width = (int)((float)src->_data.boxes[i].width * scale); + if (i == 40) + warning("char w: %d, scale: %g", boxes[i].width, scale); + boxes[i].height = (int)((float)src->_data.boxes[i].height * scale); + boxes[i].xOffset = (int)((float)src->_data.boxes[i].xOffset * scale); + boxes[i].yOffset = (int)((float)src->_data.boxes[i].yOffset * scale); + } + data.boxes = boxes; + + byte *advances = new byte[data.numCharacters]; + for (int i = 0; i < data.numCharacters; ++i) { + advances[i] = (int)((float)src->_data.advances[i] * scale); + } + data.advances = advances; + + byte **bitmaps = new byte *[data.numCharacters]; + + for (int i = 0; i < data.numCharacters; i++) { + const BdfBoundingBox &box = data.boxes ? data.boxes[i] : data.defaultBox; + const BdfBoundingBox &srcBox = data.boxes ? src->_data.boxes[i] : src->_data.defaultBox; + + if (src->_data.bitmaps[i]) { + const int bytes = ((box.width + 7) / 8) * box.height; // Dimensions have been already corrected + bitmaps[i] = new byte[bytes]; + + int srcPitch = (srcBox.width + 7) / 8; + int dstPitch = (box.width + 7) / 8; + + byte *ptr = bitmaps[i]; + + for (int y = 0; y < box.height; y++) { + byte *srcd = (byte *)&src->_data.bitmaps[i][((int)((float)y / scale)) * srcPitch]; + byte *dst = ptr; + byte b = 0; + + for (int x = 0; x < box.width; x++) { + int sx = (int)((float)x / scale); + + if (srcd[sx / 8] & (0x80 >> (sx % 8))) + b |= 1; + + if (!(x % 8) && x) { + *dst++ = b; + b = 0; + } + + b <<= 1; + } + + if (((box.width - 1) % 8)) { + b <<= 7 - ((box.width - 1) % 8); + *dst = b; + } + + ptr += dstPitch; + } + + } else { + bitmaps[i] = 0; + } + } + + data.bitmaps = bitmaps; + + return new BdfFont(data, DisposeAfterUse::YES); +} + } // End of namespace Graphics diff --git a/graphics/fonts/bdf.h b/graphics/fonts/bdf.h index b91834785f..d99b5fd401 100644 --- a/graphics/fonts/bdf.h +++ b/graphics/fonts/bdf.h @@ -40,8 +40,12 @@ struct BdfBoundingBox { }; struct BdfFontData { + const char *familyName; + const char *slant; + int maxAdvance; int height; + int size; BdfBoundingBox defaultBox; int ascent; @@ -65,9 +69,14 @@ public: virtual int getCharWidth(uint32 chr) const; virtual void drawChar(Surface *dst, uint32 chr, int x, int y, uint32 color) const; + const char *getFamilyName() const; + const char *getFontSlant() const; + int getFontSize() const; + static BdfFont *loadFont(Common::SeekableReadStream &stream); static bool cacheFontData(const BdfFont &font, const Common::String &filename); static BdfFont *loadFromCache(Common::SeekableReadStream &stream); + static BdfFont *scaleFont(BdfFont *src, int newSize); private: int mapToIndex(uint32 ch) const; diff --git a/graphics/fonts/consolefont.cpp b/graphics/fonts/consolefont.cpp index 748aa08a5c..6a84cdeaee 100644 --- a/graphics/fonts/consolefont.cpp +++ b/graphics/fonts/consolefont.cpp @@ -5850,8 +5850,11 @@ const byte *const bitmapTable[] = { // Font structure static const BdfFontData desc = { + "Fixed", // Family name + "R", // Slant 5, // Max advance 8, // Height + 8, // Size { 5, 8, 0, -1 }, // Bounding box 7, // Ascent diff --git a/graphics/fonts/newfont.cpp b/graphics/fonts/newfont.cpp index 4922e24676..8d1ce8b905 100644 --- a/graphics/fonts/newfont.cpp +++ b/graphics/fonts/newfont.cpp @@ -7634,8 +7634,11 @@ const byte *const bitmapTable[] = { // Font structure static const BdfFontData desc = { + "Schumacher", // Family name + "R", // Slant 6, // Max advance 12, // Height + 12, // Size { 6, 12, 0, -3 }, // Bounding box 9, // Ascent diff --git a/graphics/fonts/newfont_big.cpp b/graphics/fonts/newfont_big.cpp index 550d6dbfa9..28a1162434 100644 --- a/graphics/fonts/newfont_big.cpp +++ b/graphics/fonts/newfont_big.cpp @@ -5829,8 +5829,11 @@ static const BdfBoundingBox boxes[] = { // Font structure static const BdfFontData desc = { + "Helvetica", // Family name + "R", // Slant 13, // Max advance 14, // Height + 12, // Size { 13, 15, -1, -3 }, // Bounding box 11, // Ascent diff --git a/graphics/macgui/macfontmanager.cpp b/graphics/macgui/macfontmanager.cpp new file mode 100644 index 0000000000..21f9c08160 --- /dev/null +++ b/graphics/macgui/macfontmanager.cpp @@ -0,0 +1,282 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "common/archive.h" +#include "common/stream.h" +#include "common/unzip.h" +#include "graphics/fonts/bdf.h" + +#include "graphics/macgui/macfontmanager.h" + +namespace Graphics { + +// Source: Apple IIGS Technical Note #41, "Font Family Numbers" +// http://apple2.boldt.ca/?page=til/tn.iigs.041 +static const char *const fontNames[] = { + "Chicago", // system font + "Geneva", // application font + "New York", + "Geneva", + + "Monaco", + "Venice", + "London", + "Athens", + + "San Francisco", + "Toronto", + NULL, + "Cairo", + "Los Angeles", // 12 + + "Zapf Dingbats", + "Bookman", + "Helvetica Narrow", + "Palatino", + NULL, + "Zapf Chancery", + NULL, + + "Times", // 20 + "Helvetica", + "Courier", + "Symbol", + "Taliesin", // mobile? + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, // 30 + NULL, + NULL, + "Avant Garde", + "New Century Schoolbook" +}; + +MacFontManager::MacFontManager() { + for (uint i = 0; i < ARRAYSIZE(fontNames); i++) + if (fontNames[i]) + _fontNames.setVal(fontNames[i], i); + + loadFonts(); +} + +void MacFontManager::loadFonts() { + Common::Archive *dat; + + dat = Common::makeZipArchive("classicmacfonts.dat"); + + if (!dat) { + warning("Could not find classicmacfonts.dat. Falling back to built-in fonts"); + _builtInFonts = true; + + return; + } + + Common::ArchiveMemberList list; + dat->listMembers(list); + + for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { + Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName()); + + Graphics::BdfFont *font = Graphics::BdfFont::loadFont(*stream); + + delete stream; + + Common::String fontName; + MacFont *macfont; + + if (font->getFamilyName() && *font->getFamilyName()) { + fontName = Common::String::format("%s-%s-%d", font->getFamilyName(), font->getFontSlant(), font->getFontSize()); + + macfont = new MacFont(_fontNames.getVal(font->getFamilyName(), kMacFontNonStandard), font->getFontSize(), parseFontSlant(font->getFontSlant())); + } else { // Get it from the file name + fontName = (*it)->getName(); + + // Trim the .bdf extension + for (int i = fontName.size() - 1; i >= 0; --i) { + if (fontName[i] == '.') { + while ((uint)i < fontName.size()) { + fontName.deleteLastChar(); + } + break; + } + } + + macfont = new MacFont(kMacFontNonStandard); + macfont->setName(fontName); + } + + FontMan.assignFontToName(fontName, font); + macfont->setBdfFont(font); + _fontRegistry.setVal(fontName, macfont); + + debug(2, " %s", fontName.c_str()); + } + + _builtInFonts = false; + + delete dat; +} + +const Font *MacFontManager::getFont(MacFont macFont) { + const Font *font = 0; + + if (!_builtInFonts) { + if (macFont.getName().empty()) + macFont.setName(getFontName(macFont.getId(), macFont.getSize(), macFont.getSlant())); + + if (!_fontRegistry.contains(macFont.getName())) + generateFontSubstitute(macFont); + + font = FontMan.getFontByName(macFont.getName()); + + if (!font) { + warning("Cannot load font '%s'", macFont.getName().c_str()); + + font = FontMan.getFontByName(MacFont(kMacFontChicago, 12).getName()); + } + } + + if (_builtInFonts || !font) + font = FontMan.getFontByUsage(macFont.getFallback()); + + return font; +} + +int MacFontManager::parseFontSlant(Common::String slant) { + slant.toUppercase(); + + if (slant == "I") + return kMacFontItalic; + if (slant == "B") + return kMacFontBold; + if (slant == "R") + return kMacFontRegular; + + warning("Unknown font slant '%s'", slant.c_str()); + + return kMacFontRegular; +} + +const char *MacFontManager::getFontName(int id, int size, int slant) { + static char name[128]; + const char *sslant; + + switch (slant) { + case kMacFontItalic: + sslant = "I"; + break; + case kMacFontBold: + sslant = "B"; + break; + case kMacFontRegular: + default: + sslant = "R"; + break; + } + + if (id > ARRAYSIZE(fontNames)) + return NULL; + + snprintf(name, 128, "%s-%s-%d", fontNames[id], sslant, size); + + return name; +} + +const char *MacFontManager::getFontName(MacFont &font) { + return getFontName(font.getId(), font.getSize(), font.getSlant()); +} + +void MacFontManager::generateFontSubstitute(MacFont &macFont) { + Common::String name; + + // First we try twice size + name = getFontName(macFont.getId(), macFont.getSize() * 2, macFont.getSlant()); + if (_fontRegistry.contains(name) && !_fontRegistry[name]->isGenerated()) { + generateFont(macFont, *_fontRegistry[name]); + + return; + } + + // Now half size + name = getFontName(macFont.getId(), macFont.getSize() / 2, macFont.getSlant()); + if (_fontRegistry.contains(name) && !_fontRegistry[name]->isGenerated()) { + generateFont(macFont, *_fontRegistry[name]); + + return; + } + + // No simple substitute was found. Looking for neighborhood fonts + + // First we gather all font sizes for this font + Common::Array<int> sizes; + for (Common::HashMap<Common::String, MacFont *>::iterator i = _fontRegistry.begin(); i != _fontRegistry.end(); ++i) { + if (i->_value->getId() == macFont.getId() && i->_value->getSlant() == macFont.getSlant() && !i->_value->isGenerated()) + sizes.push_back(i->_value->getSize()); + } + + if (sizes.empty()) { + warning("No viable substitute found for font %s", getFontName(macFont)); + return; + } + + // Now looking next larger font, and store the largest one for next check + int candidate = 1000; + int maxSize = sizes[0]; + for (uint i = 0; i < sizes.size(); i++) { + if (sizes[i] > macFont.getSize() && sizes[i] < candidate) + candidate = sizes[i]; + + if (sizes[i] > maxSize) + maxSize = sizes[i]; + } + + if (candidate != 1000) { + generateFont(macFont, *_fontRegistry[getFontName(macFont.getId(), candidate, macFont.getSlant())]); + return; + } + + // Now next smaller font, which is the biggest we have + generateFont(macFont, *_fontRegistry[getFontName(macFont.getId(), maxSize, macFont.getSlant())]); +} + +void MacFontManager::generateFont(MacFont &toFont, MacFont &fromFont) { + debugN("Found font substitute for font '%s' ", getFontName(toFont)); + debug("as '%s'", getFontName(fromFont)); + + Graphics::BdfFont *font = Graphics::BdfFont::scaleFont(fromFont.getBdfFont(), toFont.getSize()); + + if (!font) { + warning("Failed to generate font '%s'", getFontName(toFont)); + } + + toFont.setGenerated(true); + toFont.setBdfFont(font); + + FontMan.assignFontToName(getFontName(toFont), font); + _fontRegistry.setVal(getFontName(toFont), new MacFont(toFont)); + + debug("Generated font '%s'", getFontName(toFont)); +} + +} // End of namespace Graphics diff --git a/graphics/macgui/macfontmanager.h b/graphics/macgui/macfontmanager.h new file mode 100644 index 0000000000..e429eeaada --- /dev/null +++ b/graphics/macgui/macfontmanager.h @@ -0,0 +1,134 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef GRAPHICS_MACGUI_MACFONTMANAGER_H +#define GRAPHICS_MACGUI_MACFONTMANAGER_H + +#include "graphics/fontman.h" + +namespace Graphics { + +enum { + kMacFontNonStandard = -1, + kMacFontChicago = 0, + kMacFontGeneva = 1, + kMacFontNewYork = 2, + kMacFontMonaco = 4, + kMacFontVenice = 5, + kMacFontLondon = 6, + kMacFontAthens = 7, + kMacFontSanFrancisco = 8, + kMacFontCairo = 11, + kMacFontLosAngeles = 12, + kMacFontPalatino = 16, + kMacFontTimes = 20, + kMacFontHelvetica = 21, + kMacFontCourier = 22, + kMacFontSymbol = 23 +}; + +enum { + kMacFontRegular, + kMacFontBold, + kMacFontItalic +}; + +class BdfFont; + +class MacFont { +public: + MacFont(int id = kMacFontChicago, int size = 12, int slant = kMacFontRegular, FontManager::FontUsage fallback = Graphics::FontManager::kBigGUIFont) { + _id = id; + _size = size; + _slant = slant; + _fallback = fallback; + _generated = false; + _bdfFont = NULL; + } + + int getId() { return _id; }; + int getSize() { return _size; } + int getSlant() { return _slant; } + Common::String getName() { return _name; } + void setName(Common::String &name) { _name = name; } + void setName(const char *name) { _name = name; } + FontManager::FontUsage getFallback() { return _fallback; } + bool isGenerated() { return _generated; } + void setGenerated(bool gen) { _generated = gen; } + BdfFont *getBdfFont() { return _bdfFont; } + void setBdfFont(BdfFont *bdfFont) { _bdfFont = bdfFont; } + +private: + int _id; + int _size; + int _slant; + Common::String _name; + FontManager::FontUsage _fallback; + + bool _generated; + BdfFont *_bdfFont; +}; + +class MacFontManager { +public: + MacFontManager(); + + /** + * Accessor method to check the presence of built-in fonts. + * @return True if there are bult-in fonts. + */ + bool hasBuiltInFonts() { return _builtInFonts; } + /** + * Retrieve a font from the available ones. + * @param name Name of the desired font. + * @param fallback Fallback policy in case the desired font isn't there. + * @return The requested font or the fallback. + */ + const Font *getFont(MacFont macFont); + +private: + void loadFonts(); + + /** + * Return font name from standard ID + * @param id ID of the font + * @param size size of the font + * @return the font name or NULL if ID goes beyond the mapping + */ + const char *getFontName(int id, int size, int slant = kMacFontRegular); + const char *getFontName(MacFont &font); + + void generateFontSubstitute(MacFont &macFont); + void generateFont(MacFont &toFont, MacFont &fromFont); + +private: + bool _builtInFonts; + Common::HashMap<Common::String, MacFont *> _fontRegistry; + + Common::HashMap<Common::String, int> _fontNames; + + int parseFontSlant(Common::String slant); +}; + +} // End of namespace Graphics + +#endif diff --git a/graphics/macgui/macmenu.cpp b/graphics/macgui/macmenu.cpp index 4f8c6f32b9..449cf58335 100644 --- a/graphics/macgui/macmenu.cpp +++ b/graphics/macgui/macmenu.cpp @@ -25,6 +25,7 @@ #include "graphics/primitives.h" #include "graphics/font.h" +#include "graphics/macgui/macfontmanager.h" #include "graphics/macgui/macwindowmanager.h" #include "graphics/macgui/macwindow.h" #include "graphics/macgui/macmenu.h" @@ -112,7 +113,7 @@ Menu::~Menu() { } void Menu::addStaticMenus(const MenuData *data) { - MenuItem *about = new MenuItem(_wm->hasBuiltInFonts() ? "\xa9" : "\xf0"); // (c) Symbol as the most resembling apple + MenuItem *about = new MenuItem(_wm->_fontMan->hasBuiltInFonts() ? "\xa9" : "\xf0"); // (c) Symbol as the most resembling apple _items.push_back(about); for (int i = 0; data[i].menunum; i++) { @@ -154,7 +155,7 @@ void Menu::calcDimensions() { _items[i]->bbox.left = x - kMenuLeftMargin; _items[i]->bbox.top = y; _items[i]->bbox.right = x + w + kMenuSpacing - kMenuLeftMargin; - _items[i]->bbox.bottom = y + _font->getFontHeight() + (_wm->hasBuiltInFonts() ? 3 : 2); + _items[i]->bbox.bottom = y + _font->getFontHeight() + (_wm->_fontMan->hasBuiltInFonts() ? 3 : 2); } calcMenuBounds(_items[i]); @@ -244,7 +245,7 @@ void Menu::createSubMenuFromString(int id, const char *str) { } const Font *Menu::getMenuFont() { - return _wm->getFont("Chicago-12", FontManager::kBigGUIFont); + return _wm->_fontMan->getFont(Graphics::MacFont(kMacFontChicago, 12)); } const char *Menu::getAcceleratorString(MenuSubItem *item, const char *prefix) { @@ -252,7 +253,7 @@ const char *Menu::getAcceleratorString(MenuSubItem *item, const char *prefix) { *res = 0; if (item->shortcut != 0) - sprintf(res, "%s%c%c", prefix, (_wm->hasBuiltInFonts() ? '^' : '\x11'), item->shortcut); + sprintf(res, "%s%c%c", prefix, (_wm->_fontMan->hasBuiltInFonts() ? '^' : '\x11'), item->shortcut); return res; } @@ -339,7 +340,7 @@ bool Menu::draw(ManagedSurface *g, bool forceRedraw) { renderSubmenu(it); } - _font->drawString(&_screen, it->name, it->bbox.left + kMenuLeftMargin, it->bbox.top + (_wm->hasBuiltInFonts() ? 2 : 1), it->bbox.width(), color); + _font->drawString(&_screen, it->name, it->bbox.left + kMenuLeftMargin, it->bbox.top + (_wm->_fontMan->hasBuiltInFonts() ? 2 : 1), it->bbox.width(), color); } g->transBlitFrom(_screen, kColorGreen); @@ -372,7 +373,7 @@ void Menu::renderSubmenu(MenuItem *menu) { int color = kColorBlack; if (i == (uint)_activeSubItem && !text.empty() && menu->subitems[i]->enabled) { color = kColorWhite; - Common::Rect trect(r->left, y - (_wm->hasBuiltInFonts() ? 1 : 0), r->right, y + _font->getFontHeight()); + Common::Rect trect(r->left, y - (_wm->_fontMan->hasBuiltInFonts() ? 1 : 0), r->right, y + _font->getFontHeight()); _screen.fillRect(trect, kColorBlack); } diff --git a/graphics/macgui/macwindow.cpp b/graphics/macgui/macwindow.cpp index 2a6e191ded..0fce19e482 100644 --- a/graphics/macgui/macwindow.cpp +++ b/graphics/macgui/macwindow.cpp @@ -23,6 +23,7 @@ #include "graphics/font.h" #include "graphics/primitives.h" #include "common/events.h" +#include "graphics/macgui/macfontmanager.h" #include "graphics/macgui/macwindowmanager.h" #include "graphics/macgui/macwindow.h" #include "image/bmp.h" @@ -67,7 +68,7 @@ MacWindow::~MacWindow() { } const Font *MacWindow::getTitleFont() { - return _wm->getFont("Chicago-12", FontManager::kBigGUIFont); + return _wm->_fontMan->getFont(Graphics::MacFont(kMacFontChicago, 12)); } void MacWindow::setActive(bool active) { @@ -276,7 +277,7 @@ void MacWindow::drawSimpleBorder(ManagedSurface *g) { if (drawTitle) { const Graphics::Font *font = getTitleFont(); - int yOff = _wm->hasBuiltInFonts() ? 3 : 1; + int yOff = _wm->_fontMan->hasBuiltInFonts() ? 3 : 1; int w = font->getStringWidth(_title) + 10; int maxWidth = width - size * 2 - 7; diff --git a/graphics/macgui/macwindow.h b/graphics/macgui/macwindow.h index 5d06da383d..5446b65678 100644 --- a/graphics/macgui/macwindow.h +++ b/graphics/macgui/macwindow.h @@ -23,6 +23,8 @@ #ifndef GRAPHICS_MACGUI_MACWINDOW_H #define GRAPHICS_MACGUI_MACWINDOW_H +#include "common/stream.h" + #include "graphics/managed_surface.h" #include "graphics/transparent_surface.h" #include "graphics/nine_patch.h" diff --git a/graphics/macgui/macwindowmanager.cpp b/graphics/macgui/macwindowmanager.cpp index 9e40c368dc..42cab7cf8e 100644 --- a/graphics/macgui/macwindowmanager.cpp +++ b/graphics/macgui/macwindowmanager.cpp @@ -22,16 +22,14 @@ #include "common/array.h" #include "common/events.h" #include "common/list.h" -#include "common/unzip.h" #include "common/system.h" -#include "common/stream.h" #include "graphics/cursorman.h" -#include "graphics/fonts/bdf.h" #include "graphics/managed_surface.h" #include "graphics/palette.h" #include "graphics/primitives.h" #include "graphics/macgui/macwindowmanager.h" +#include "graphics/macgui/macfontmanager.h" #include "graphics/macgui/macwindow.h" #include "graphics/macgui/macmenu.h" @@ -100,15 +98,13 @@ MacWindowManager::MacWindowManager() { _fullRefresh = true; - _builtInFonts = true; - for (int i = 0; i < ARRAYSIZE(fillPatterns); i++) _patterns.push_back(fillPatterns[i]); - loadFonts(); - g_system->getPaletteManager()->setPalette(palette, 0, ARRAYSIZE(palette) / 3); + _fontMan = new MacFontManager(); + CursorMan.replaceCursorPalette(palette, 0, ARRAYSIZE(palette) / 3); CursorMan.replaceCursor(macCursorArrow, 11, 16, 1, 1, 3); _cursorIsArrow = true; @@ -118,6 +114,8 @@ MacWindowManager::MacWindowManager() { MacWindowManager::~MacWindowManager() { for (int i = 0; i < _lastId; i++) delete _windows[i]; + + delete _fontMan; } MacWindow *MacWindowManager::addWindow(bool scrollable, bool resizable, bool editable) { @@ -322,124 +320,6 @@ void MacWindowManager::removeFromWindowList(BaseMacWindow *target) { _windows.remove_at(ndx); } -////////////////////// -// Font stuff -////////////////////// -void MacWindowManager::loadFonts() { - Common::Archive *dat; - - dat = Common::makeZipArchive("classicmacfonts.dat"); - - if (!dat) { - warning("Could not find classicmacfonts.dat. Falling back to built-in fonts"); - _builtInFonts = true; - - return; - } - - Common::ArchiveMemberList list; - dat->listMembers(list); - - for (Common::ArchiveMemberList::iterator it = list.begin(); it != list.end(); ++it) { - Common::SeekableReadStream *stream = dat->createReadStreamForMember((*it)->getName()); - - Graphics::BdfFont *font = Graphics::BdfFont::loadFont(*stream); - - delete stream; - - Common::String fontName = (*it)->getName(); - - // Trim the .bdf extension - for (int i = fontName.size() - 1; i >= 0; --i) { - if (fontName[i] == '.') { - while ((uint)i < fontName.size()) { - fontName.deleteLastChar(); - } - break; - } - } - - FontMan.assignFontToName(fontName, font); - - debug(2, " %s", fontName.c_str()); - } - - _builtInFonts = false; - - delete dat; -} - -const Graphics::Font *MacWindowManager::getFont(const char *name, Graphics::FontManager::FontUsage fallback) { - const Graphics::Font *font = 0; - - if (!_builtInFonts) { - font = FontMan.getFontByName(name); - - if (!font) - warning("Cannot load font %s", name); - } - - if (_builtInFonts || !font) - font = FontMan.getFontByUsage(fallback); - - return font; -} - -// Source: Apple IIGS Technical Note #41, "Font Family Numbers" -// http://apple2.boldt.ca/?page=til/tn.iigs.041 -static const char *const fontNames[] = { - "Chicago", // system font - "Geneva", // application font - "New York", - "Geneva", - - "Monaco", - "Venice", - "London", - "Athens", - - "San Francisco", - "Toronto", - NULL, - "Cairo", - "Los Angeles", // 12 - - "Zapf Dingbats", - "Bookman", - "Helvetica Narrow", - "Palatino", - NULL, - "Zapf Chancery", - NULL, - - "Times", // 20 - "Helvetica", - "Courier", - "Symbol", - "Taliesin", // mobile? - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, // 30 - NULL, - NULL, - "Avant Garde", - "New Century Schoolbook" -}; - -const char *MacWindowManager::getFontName(int id, int size) { - static char name[128]; - - if (id > ARRAYSIZE(fontNames)) - return NULL; - - snprintf(name, 128, "%s-%d", fontNames[id], size); - - return name; -} - ///////////////// // Cursor stuff ///////////////// diff --git a/graphics/macgui/macwindowmanager.h b/graphics/macgui/macwindowmanager.h index 96cc1e73a5..3449ab13c2 100644 --- a/graphics/macgui/macwindowmanager.h +++ b/graphics/macgui/macwindowmanager.h @@ -26,7 +26,6 @@ #include "common/array.h" #include "common/list.h" #include "common/events.h" -#include "common/archive.h" #include "graphics/fontman.h" #include "graphics/macgui/macwindow.h" @@ -62,6 +61,8 @@ class ManagedSurface; class Menu; +class MacFontManager; + typedef Common::Array<byte *> MacPatterns; /** @@ -80,27 +81,6 @@ public: */ void setScreen(ManagedSurface *screen) { _screen = screen; } /** - * Accessor method to check the presence of built-in fonts. - * @return True if there are bult-in fonts. - */ - bool hasBuiltInFonts() { return _builtInFonts; } - /** - * Retrieve a font from the available ones. - * @param name Name of the desired font. - * @param fallback Fallback policy in case the desired font isn't there. - * @return The requested font or the fallback. - */ - const Font *getFont(const char *name, FontManager::FontUsage fallback); - - /** - * Return font name from standard ID - * @param id ID of the font - * @param size size of the font - * @return the font name or NULL if ID goes beyond the mapping - */ - const char *getFontName(int id, int size); - - /** * Create a window with the given parameters. * Note that this method allocates the necessary memory for the window. * @param scrollable True if the window has to be scrollable. @@ -168,9 +148,11 @@ public: void pushArrowCursor(); void popCursor(); +public: + MacFontManager *_fontMan; + private: void drawDesktop(); - void loadFonts(); void removeMarked(); void removeFromStack(BaseMacWindow *target); @@ -194,7 +176,6 @@ private: Menu *_menu; - bool _builtInFonts; bool _cursorIsArrow; }; diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp index 273b15de55..0b9fa11181 100644 --- a/graphics/managed_surface.cpp +++ b/graphics/managed_surface.cpp @@ -28,7 +28,7 @@ namespace Graphics { const int SCALE_THRESHOLD = 0x100; -ManagedSurface::ManagedSurface() : +ManagedSurface::ManagedSurface() : w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) { } @@ -104,7 +104,7 @@ void ManagedSurface::create(uint16 width, uint16 height, const PixelFormat &pixe void ManagedSurface::create(ManagedSurface &surf, const Common::Rect &bounds) { free(); - + _offsetFromOwner = Common::Point(bounds.left, bounds.top); _innerSurface.setPixels(surf.getBasePtr(bounds.left, bounds.top)); _innerSurface.pitch = surf.pitch; @@ -164,7 +164,7 @@ void ManagedSurface::blitFrom(const Surface &src, const Common::Point &destPos) void ManagedSurface::blitFrom(const Surface &src, const Common::Rect &srcRect, const Common::Point &destPos) { Common::Rect srcBounds = srcRect; - Common::Rect destBounds(destPos.x, destPos.y, destPos.x + srcRect.width(), + Common::Rect destBounds(destPos.x, destPos.y, destPos.x + srcRect.width(), destPos.y + srcRect.height()); assert(src.format.bytesPerPixel == format.bytesPerPixel); diff --git a/graphics/managed_surface.h b/graphics/managed_surface.h index 8cbd463266..422b4610be 100644 --- a/graphics/managed_surface.h +++ b/graphics/managed_surface.h @@ -95,12 +95,12 @@ public: * Create the managed surface */ ManagedSurface(int width, int height); - + /** * Create the managed surface */ ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat); - + /** * Create the managed surface */ @@ -211,7 +211,7 @@ public: const Common::Rect getBounds() const { return Common::Rect(0, 0, this->w, this->h); } - + /** * Copies another surface into this one */ diff --git a/graphics/module.mk b/graphics/module.mk index 1c87e74ba7..b6e704bc29 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -12,6 +12,7 @@ MODULE_OBJS := \ fonts/ttf.o \ fonts/winfont.o \ maccursor.o \ + macgui/macfontmanager.o \ macgui/macmenu.o \ macgui/macwindow.o \ macgui/macwindowborder.o \ diff --git a/graphics/screen.h b/graphics/screen.h index b3bb2d3eb2..a727936f5c 100644 --- a/graphics/screen.h +++ b/graphics/screen.h @@ -36,7 +36,7 @@ namespace Graphics { /** * Implements a specialised surface that represents the screen. * It keeps track of any areas of itself that are updated by drawing - * calls, and provides an update that method that blits the affected + * calls, and provides an update that method that blits the affected * areas to the physical screen */ class Screen : public ManagedSurface { @@ -72,7 +72,7 @@ public: bool isDirty() const { return !_dirtyRects.empty(); } /** - * Marks the whole screen as dirty. This forces the next call to update + * Marks the whole screen as dirty. This forces the next call to update * to copy the entire screen contents */ void makeAllDirty(); diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp index 81b7f3d647..7ef7d00286 100644 --- a/graphics/transparent_surface.cpp +++ b/graphics/transparent_surface.cpp @@ -346,7 +346,7 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p TransparentSurface srcImage(*this, false); // TODO: Is the data really in the screen format? if (format.bytesPerPixel != 4) { - warning("TransparentSurface can only blit 32bpp images, but got %d", format.bytesPerPixel * 8); + warning("TransparentSurface can only blit 32bpp images, but got %d", format.bytesPerPixel * 8); return retSize; } |