2016-10-06 23:48:50 +02:00
|
|
|
/* 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"
|
2017-01-17 20:28:12 +01:00
|
|
|
#include "common/macresman.h"
|
2016-10-06 23:48:50 +02:00
|
|
|
#include "graphics/fonts/bdf.h"
|
2017-01-17 20:28:12 +01:00
|
|
|
#include "graphics/fonts/macfont.h"
|
2016-10-06 23:48:50 +02:00
|
|
|
|
|
|
|
#include "graphics/macgui/macfontmanager.h"
|
|
|
|
|
|
|
|
namespace Graphics {
|
|
|
|
|
2016-10-08 14:46:49 +02:00
|
|
|
// 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"
|
|
|
|
};
|
|
|
|
|
2016-10-06 23:48:50 +02:00
|
|
|
MacFontManager::MacFontManager() {
|
2016-10-08 14:46:49 +02:00
|
|
|
for (uint i = 0; i < ARRAYSIZE(fontNames); i++)
|
|
|
|
if (fontNames[i])
|
|
|
|
_fontNames.setVal(fontNames[i], i);
|
|
|
|
|
2016-10-06 23:48:50 +02:00
|
|
|
loadFonts();
|
|
|
|
}
|
|
|
|
|
2017-01-17 20:28:12 +01:00
|
|
|
void MacFontManager::loadFontsBDF() {
|
2016-10-06 23:48:50 +02:00
|
|
|
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;
|
2016-10-08 14:46:49 +02:00
|
|
|
MacFont *macfont;
|
|
|
|
|
2016-10-06 23:48:50 +02:00
|
|
|
if (font->getFamilyName() && *font->getFamilyName()) {
|
2016-10-07 10:37:40 +02:00
|
|
|
fontName = Common::String::format("%s-%s-%d", font->getFamilyName(), font->getFontSlant(), font->getFontSize());
|
2016-10-08 14:46:49 +02:00
|
|
|
|
|
|
|
macfont = new MacFont(_fontNames.getVal(font->getFamilyName(), kMacFontNonStandard), font->getFontSize(), parseFontSlant(font->getFontSlant()));
|
2016-10-06 23:48:50 +02:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
}
|
2016-10-08 14:46:49 +02:00
|
|
|
|
|
|
|
macfont = new MacFont(kMacFontNonStandard);
|
|
|
|
macfont->setName(fontName);
|
2016-10-06 23:48:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
FontMan.assignFontToName(fontName, font);
|
2016-10-12 19:16:57 +02:00
|
|
|
macfont->setBdfFont(font);
|
2016-10-08 14:46:49 +02:00
|
|
|
_fontRegistry.setVal(fontName, macfont);
|
2016-10-06 23:48:50 +02:00
|
|
|
|
|
|
|
debug(2, " %s", fontName.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
_builtInFonts = false;
|
|
|
|
|
|
|
|
delete dat;
|
|
|
|
}
|
|
|
|
|
2017-01-17 20:28:12 +01:00
|
|
|
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());
|
|
|
|
|
|
|
|
Common::MacResManager *fontFile = new Common::MacResManager();
|
|
|
|
|
|
|
|
if (!fontFile->loadFromMacBinary(*stream))
|
|
|
|
error("Could not open %s as a resource fork", (*it)->getName().c_str());
|
|
|
|
|
|
|
|
Common::MacResIDArray fonds = fontFile->getResIDArray(MKTAG('F','O','N','D'));
|
|
|
|
if (fonds.size() > 0) {
|
|
|
|
for (Common::Array<uint16>::iterator iterator = fonds.begin(); iterator != fonds.end(); ++iterator) {
|
|
|
|
Common::SeekableReadStream *fond = fontFile->getResource(MKTAG('F', 'O', 'N', 'D'), *iterator);
|
|
|
|
|
|
|
|
Graphics::MacFontFamily fontFamily;
|
|
|
|
fontFamily.load(*fond);
|
|
|
|
|
|
|
|
Common::Array<Graphics::MacFontFamily::AsscEntry> *assoc = fontFamily.getAssocTable();
|
|
|
|
|
|
|
|
for (uint i = 0; i < assoc->size(); i++) {
|
|
|
|
debug("size: %d style: %d id: %d", (*assoc)[i]._fontSize, (*assoc)[i]._fontSize,
|
|
|
|
(*assoc)[i]._fontID);
|
|
|
|
}
|
|
|
|
|
|
|
|
delete fond;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
_builtInFonts = false;
|
|
|
|
|
|
|
|
delete dat;
|
|
|
|
}
|
|
|
|
|
2016-10-06 23:48:50 +02:00
|
|
|
const Font *MacFontManager::getFont(MacFont macFont) {
|
|
|
|
const Font *font = 0;
|
|
|
|
|
|
|
|
if (!_builtInFonts) {
|
|
|
|
if (macFont.getName().empty())
|
2016-10-07 19:42:55 +02:00
|
|
|
macFont.setName(getFontName(macFont.getId(), macFont.getSize(), macFont.getSlant()));
|
|
|
|
|
|
|
|
if (!_fontRegistry.contains(macFont.getName()))
|
|
|
|
generateFontSubstitute(macFont);
|
2016-10-06 23:48:50 +02:00
|
|
|
|
|
|
|
font = FontMan.getFontByName(macFont.getName());
|
|
|
|
|
|
|
|
if (!font) {
|
2016-10-12 19:16:57 +02:00
|
|
|
warning("Cannot load font '%s'", macFont.getName().c_str());
|
2016-10-06 23:48:50 +02:00
|
|
|
|
|
|
|
font = FontMan.getFontByName(MacFont(kMacFontChicago, 12).getName());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_builtInFonts || !font)
|
|
|
|
font = FontMan.getFontByUsage(macFont.getFallback());
|
|
|
|
|
|
|
|
return font;
|
|
|
|
}
|
|
|
|
|
2016-10-08 14:46:49 +02:00
|
|
|
int MacFontManager::parseFontSlant(Common::String slant) {
|
|
|
|
slant.toUppercase();
|
2016-10-06 23:48:50 +02:00
|
|
|
|
2016-10-08 14:46:49 +02:00
|
|
|
if (slant == "I")
|
|
|
|
return kMacFontItalic;
|
|
|
|
if (slant == "B")
|
|
|
|
return kMacFontBold;
|
|
|
|
if (slant == "R")
|
|
|
|
return kMacFontRegular;
|
2016-10-06 23:48:50 +02:00
|
|
|
|
2016-10-08 14:46:49 +02:00
|
|
|
warning("Unknown font slant '%s'", slant.c_str());
|
2016-10-06 23:48:50 +02:00
|
|
|
|
2016-10-08 14:46:49 +02:00
|
|
|
return kMacFontRegular;
|
|
|
|
}
|
2016-10-06 23:48:50 +02:00
|
|
|
|
2016-10-07 10:37:40 +02:00
|
|
|
const char *MacFontManager::getFontName(int id, int size, int slant) {
|
2016-10-06 23:48:50 +02:00
|
|
|
static char name[128];
|
2016-10-07 10:37:40 +02:00
|
|
|
const char *sslant;
|
|
|
|
|
|
|
|
switch (slant) {
|
|
|
|
case kMacFontItalic:
|
|
|
|
sslant = "I";
|
|
|
|
break;
|
|
|
|
case kMacFontBold:
|
|
|
|
sslant = "B";
|
|
|
|
break;
|
|
|
|
case kMacFontRegular:
|
|
|
|
default:
|
|
|
|
sslant = "R";
|
|
|
|
break;
|
|
|
|
}
|
2016-10-06 23:48:50 +02:00
|
|
|
|
|
|
|
if (id > ARRAYSIZE(fontNames))
|
|
|
|
return NULL;
|
|
|
|
|
2016-10-07 10:37:40 +02:00
|
|
|
snprintf(name, 128, "%s-%s-%d", fontNames[id], sslant, size);
|
2016-10-06 23:48:50 +02:00
|
|
|
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2016-10-07 19:42:55 +02:00
|
|
|
const char *MacFontManager::getFontName(MacFont &font) {
|
|
|
|
return getFontName(font.getId(), font.getSize(), font.getSlant());
|
|
|
|
}
|
|
|
|
|
2017-01-14 15:02:58 +11:00
|
|
|
int MacFontManager::getFontIdByName(Common::String name) {
|
|
|
|
for (int f = 0; f < ARRAYSIZE(fontNames); f++)
|
|
|
|
if (fontNames[f] != NULL && strcmp(fontNames[f], name.c_str()) == 0)
|
|
|
|
return f;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-10-07 19:42:55 +02:00
|
|
|
void MacFontManager::generateFontSubstitute(MacFont &macFont) {
|
2016-10-08 14:46:49 +02:00
|
|
|
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]);
|
2016-10-07 19:42:55 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-10-08 14:46:49 +02:00
|
|
|
// Now half size
|
|
|
|
name = getFontName(macFont.getId(), macFont.getSize() / 2, macFont.getSlant());
|
2016-10-12 19:16:57 +02:00
|
|
|
if (_fontRegistry.contains(name) && !_fontRegistry[name]->isGenerated()) {
|
2016-10-08 14:46:49 +02:00
|
|
|
generateFont(macFont, *_fontRegistry[name]);
|
2016-10-07 19:42:55 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2016-10-08 14:46:49 +02:00
|
|
|
|
|
|
|
// 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) {
|
2016-10-12 19:16:57 +02:00
|
|
|
if (i->_value->getId() == macFont.getId() && i->_value->getSlant() == macFont.getSlant() && !i->_value->isGenerated())
|
2016-10-08 14:46:49 +02:00
|
|
|
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) {
|
2016-10-12 19:16:57 +02:00
|
|
|
generateFont(macFont, *_fontRegistry[getFontName(macFont.getId(), candidate, macFont.getSlant())]);
|
2016-10-08 14:46:49 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now next smaller font, which is the biggest we have
|
2016-10-12 23:27:50 +02:00
|
|
|
generateFont(macFont, *_fontRegistry[getFontName(macFont.getId(), maxSize, macFont.getSlant())]);
|
2016-10-07 19:42:55 +02:00
|
|
|
}
|
|
|
|
|
2016-10-12 23:27:50 +02:00
|
|
|
void MacFontManager::generateFont(MacFont &toFont, MacFont &fromFont) {
|
2016-10-12 19:16:57 +02:00
|
|
|
debugN("Found font substitute for font '%s' ", getFontName(toFont));
|
|
|
|
debug("as '%s'", getFontName(fromFont));
|
2016-10-11 18:22:51 +02:00
|
|
|
|
2016-10-12 19:16:57 +02:00
|
|
|
Graphics::BdfFont *font = Graphics::BdfFont::scaleFont(fromFont.getBdfFont(), toFont.getSize());
|
2016-10-11 18:22:51 +02:00
|
|
|
|
2016-10-12 23:27:50 +02:00
|
|
|
if (!font) {
|
|
|
|
warning("Failed to generate font '%s'", getFontName(toFont));
|
|
|
|
}
|
|
|
|
|
2016-10-11 18:22:51 +02:00
|
|
|
toFont.setGenerated(true);
|
2016-10-12 19:16:57 +02:00
|
|
|
toFont.setBdfFont(font);
|
2016-10-11 18:22:51 +02:00
|
|
|
|
|
|
|
FontMan.assignFontToName(getFontName(toFont), font);
|
2016-10-12 19:16:57 +02:00
|
|
|
_fontRegistry.setVal(getFontName(toFont), new MacFont(toFont));
|
|
|
|
|
|
|
|
debug("Generated font '%s'", getFontName(toFont));
|
2016-10-07 19:42:55 +02:00
|
|
|
}
|
|
|
|
|
2016-10-06 23:48:50 +02:00
|
|
|
} // End of namespace Graphics
|