ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

sjis.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/scummsys.h"
00024 #include "graphics/sjis.h"
00025 
00026 #ifdef GRAPHICS_SJIS_H
00027 
00028 #include "common/debug.h"
00029 #include "common/archive.h"
00030 #include "common/endian.h"
00031 #include "common/stream.h"
00032 #include "common/textconsole.h"
00033 
00034 #include "graphics/surface.h"
00035 
00036 namespace Graphics {
00037 
00038 FontSJIS *FontSJIS::createFont(const Common::Platform platform) {
00039     FontSJIS *ret = 0;
00040 
00041     // Try the font ROM of the specified platform
00042     if (platform == Common::kPlatformFMTowns) {
00043         ret = new FontTowns();
00044         if (ret->loadData())
00045             return ret;
00046         delete ret;
00047     } else if (platform == Common::kPlatformPCEngine) {
00048         ret = new FontPCEngine();
00049         if (ret->loadData())
00050             return ret;
00051         delete ret;
00052     } // TODO: PC98 font rom support
00053     /* else if (platform == Common::kPlatformPC98) {
00054         ret = new FontPC98();
00055         if (ret->loadData())
00056             return ret;
00057         delete ret;
00058     }*/
00059 
00060     // Try ScummVM's font.
00061     ret = new FontSjisSVM(platform);
00062     if (ret->loadData())
00063         return ret;
00064     delete ret;
00065 
00066     return 0;
00067 }
00068 
00069 void FontSJIS::drawChar(Graphics::Surface &dst, uint16 ch, int x, int y, uint32 c1, uint32 c2) const {
00070     drawChar(dst.getBasePtr(x, y), ch, dst.pitch, dst.format.bytesPerPixel, c1, c2, dst.w - x, dst.h - y);
00071 }
00072 
00073 FontSJISBase::FontSJISBase()
00074 : _drawMode(kDefaultMode), _flippedMode(false), _fatPrint(false), _fontWidth(16), _fontHeight(16), _bitPosNewLineMask(0) {
00075 }
00076 
00077 void FontSJISBase::setDrawingMode(DrawingMode mode) {
00078     if (hasFeature(1 << mode))
00079         _drawMode = mode;
00080     else
00081         warning("Unsupported drawing mode selected");
00082 }
00083 
00084 void FontSJISBase::toggleFlippedMode(bool enable) {
00085     if (hasFeature(kFeatFlipped))
00086         _flippedMode = enable;
00087     else
00088         warning("Flipped mode unsupported by this font");
00089 }
00090 
00091 void FontSJISBase::toggleFatPrint(bool enable) {
00092     if (hasFeature(kFeatFatPrint))
00093         _fatPrint = enable;
00094     else
00095         warning("Fat print unsupported by this font");
00096 }
00097 
00098 uint FontSJISBase::getFontHeight() const {
00099     switch (_drawMode) {
00100     case kOutlineMode:
00101         return _fontHeight + 2;
00102 
00103     case kDefaultMode:
00104         return _fontHeight;
00105 
00106     default:
00107         return _fontHeight + 1;
00108     }
00109 }
00110 
00111 uint FontSJISBase::getMaxFontWidth() const {
00112     switch (_drawMode) {
00113     case kOutlineMode:
00114         return _fontWidth + 2;
00115 
00116     case kDefaultMode:
00117         return _fontWidth;
00118 
00119     default:
00120         return _fontWidth + 1;
00121     }
00122 }
00123 
00124 uint FontSJISBase::getCharWidth(uint16 ch) const {
00125     if (isASCII(ch))
00126         return ((_drawMode == kOutlineMode) ? 10 : (_drawMode == kDefaultMode ? 8 : 9));
00127     else
00128         return getMaxFontWidth();
00129 }
00130 
00131 template<typename Color>
00132 void FontSJISBase::blitCharacter(const uint8 *glyph, const int w, const int h, uint8 *dst, int pitch, Color c) const {
00133     uint8 bitPos = 0;
00134     uint8 mask = 0;
00135 
00136     for (int y = 0; y < h; ++y) {
00137         Color *d = (Color *)dst;
00138         dst += pitch;
00139 
00140         bitPos &= _bitPosNewLineMask;
00141         for (int x = 0; x < w; ++x) {
00142             if (!(bitPos % 8))
00143                 mask = *glyph++;
00144 
00145             if (mask & 0x80)
00146                 *d = c;
00147 
00148             ++d;
00149             ++bitPos;
00150             mask <<= 1;
00151         }
00152     }
00153 }
00154 
00155 void FontSJISBase::createOutline(uint8 *outline, const uint8 *glyph, const int w, const int h) const {
00156     const int glyphPitch = (w + 7) / 8;
00157     const int outlinePitch = (w + 9) / 8;
00158 
00159     uint8 *line1 = outline + 0 * outlinePitch;
00160     uint8 *line2 = outline + 1 * outlinePitch;
00161     uint8 *line3 = outline + 2 * outlinePitch;
00162 
00163     for (int y = 0; y < h; ++y) {
00164         for (int x = 0; x < glyphPitch; ++x) {
00165             const uint8 mask = *glyph++;
00166 
00167             const uint8 b1 = mask | (mask >> 1) | (mask >> 2);
00168             const uint8 b2 = (mask << 7) | ((mask << 6) & 0xC0);
00169 
00170             line1[x] |= b1;
00171             line2[x] |= b1;
00172             line3[x] |= b1;
00173 
00174             if (x + 1 < outlinePitch) {
00175                 line1[x + 1] |= b2;
00176                 line2[x + 1] |= b2;
00177                 line3[x + 1] |= b2;
00178             }
00179         }
00180 
00181         line1 += outlinePitch;
00182         line2 += outlinePitch;
00183         line3 += outlinePitch;
00184     }
00185 }
00186 
00187 #ifndef DISABLE_FLIPPED_MODE
00188 const uint8 *FontSJISBase::flipCharacter(const uint8 *glyph, const int w) const {
00189     static const uint8 flipData[] = {
00190         0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
00191         0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
00192         0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
00193         0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
00194         0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
00195         0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
00196         0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
00197         0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
00198         0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
00199         0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
00200         0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
00201         0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
00202         0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
00203         0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
00204         0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
00205         0x0F, 0x8F, 0x4F, 0xC7, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x97, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
00206     };
00207 
00208     for (int i = 0; i < w; i++) {
00209         _tempGlyph[i] = flipData[glyph[(w * 2 - 1) - i]];
00210         _tempGlyph[(w * 2 - 1) - i] = flipData[glyph[i]];
00211     }
00212 
00213     return _tempGlyph;
00214 }
00215 #endif
00216 
00217 const uint8 *FontSJISBase::makeFatCharacter(const uint8 *glyph, const int w) const {
00218     // This is the EOB II FM-Towns implementation.
00219     // The last bit to the right of each line is cut off so that the fat
00220     // character actually has the same width as it would normally have.
00221     if (w == 8) {
00222         for (int i = 0; i < 16; ++i) {
00223             _tempGlyph2[i] = *glyph | (*glyph >> 1);
00224             glyph++;
00225         }
00226     } else {
00227         for (int i = 0; i < 16; ++i) {
00228             uint16 l = READ_BE_UINT16(glyph);
00229             WRITE_BE_UINT16(&_tempGlyph2[i << 1], l | (l >> 1));
00230             glyph += 2;
00231         }
00232     }
00233     return _tempGlyph2;
00234 }
00235 
00236 void FontSJISBase::drawChar(void *dst, uint16 ch, int pitch, int bpp, uint32 c1, uint32 c2, int maxW, int maxH) const {
00237     const uint8 *glyphSource = 0;
00238     int width = 0, height = 0;
00239     int outlineExtraWidth = 2, outlineExtraHeight = 2;
00240     int outlineXOffset = 0, outlineYOffset = 0;
00241 
00242     if (isASCII(ch)) {
00243         glyphSource = getCharData(ch);
00244         width = 8;
00245         height = _fontHeight;
00246     } else {
00247         glyphSource = getCharData(ch);
00248         width = _fontWidth;
00249         height = _fontHeight;
00250     }
00251 
00252     if (maxW != -1 && maxW < width) {
00253         width = maxW;
00254         outlineExtraWidth = 0;
00255         outlineXOffset = 1;
00256     }
00257 
00258     if (maxH != -1 && maxH < height) {
00259         height = maxH;
00260         outlineExtraHeight = 0;
00261         outlineYOffset = 1;
00262     }
00263 
00264     if (width <= 0 || height <= 0)
00265         return;
00266 
00267     if (!glyphSource) {
00268         warning("FontSJISBase::drawChar: Font does not offer data for %02X %02X", ch & 0xFF, ch >> 8);
00269         return;
00270     }
00271 
00272     if (_fatPrint)
00273         glyphSource = makeFatCharacter(glyphSource, width);
00274 
00275 #ifndef DISABLE_FLIPPED_MODE
00276     if (_flippedMode)
00277         glyphSource = flipCharacter(glyphSource, width);
00278 #endif
00279     
00280     uint8 outline[18 * 18];
00281     if (_drawMode == kOutlineMode) {
00282         memset(outline, 0, sizeof(outline));
00283         createOutline(outline, glyphSource, width, height);
00284     }
00285 
00286     if (bpp == 1) {
00287         if (_drawMode == kOutlineMode) {
00288             blitCharacter<uint8>(outline, width + outlineExtraWidth, height + outlineExtraHeight, (uint8 *)dst, pitch, c2);
00289             blitCharacter<uint8>(glyphSource, width - outlineXOffset, height - outlineYOffset, (uint8 *)dst + pitch + 1, pitch, c1);
00290         } else {
00291             if (_drawMode != kDefaultMode) {
00292                 blitCharacter<uint8>(glyphSource, width - outlineXOffset, height, ((uint8 *)dst) + 1, pitch, c2);
00293                 blitCharacter<uint8>(glyphSource, width, height - outlineYOffset, ((uint8 *)dst) + pitch, pitch, c2);
00294                 if (_drawMode == kShadowMode)
00295                     blitCharacter<uint8>(glyphSource, width - outlineXOffset, height - outlineYOffset, ((uint8 *)dst) + pitch + 1, pitch, c2);
00296             }
00297 
00298             blitCharacter<uint8>(glyphSource, width, height, (uint8 *)dst, pitch, c1);
00299         }
00300     } else if (bpp == 2) {
00301         if (_drawMode == kOutlineMode) {
00302             blitCharacter<uint16>(outline, width + outlineExtraWidth, height + outlineExtraHeight, (uint8 *)dst, pitch, c2);
00303             blitCharacter<uint16>(glyphSource, width - outlineXOffset, height - outlineYOffset, (uint8 *)dst + pitch + 2, pitch, c1);
00304         } else {
00305             if (_drawMode != kDefaultMode) {
00306                 blitCharacter<uint16>(glyphSource, width - outlineXOffset, height, ((uint8 *)dst) + 2, pitch, c2);
00307                 blitCharacter<uint16>(glyphSource, width, height - outlineYOffset, ((uint8 *)dst) + pitch, pitch, c2);
00308                 if (_drawMode == kShadowMode)
00309                     blitCharacter<uint16>(glyphSource, width - outlineXOffset, height - outlineYOffset, ((uint8 *)dst) + pitch + 2, pitch, c2);
00310             }
00311 
00312             blitCharacter<uint16>(glyphSource, width, height, (uint8 *)dst, pitch, c1);
00313         }
00314     } else {
00315         error("FontSJISBase::drawChar: unsupported bpp: %d", bpp);
00316     }
00317 }
00318 
00319 bool FontSJISBase::isASCII(uint16 ch) const {
00320     if (ch >= 0xFF)
00321         return false;
00322     else if (ch <= 0x7F || (ch >= 0xA1 && ch <= 0xDF))
00323         return true;
00324     else
00325         return false;
00326 }
00327 
00328 // FM-TOWNS ROM font
00329 
00330 bool FontTowns::loadData() {
00331     Common::SeekableReadStream *data = SearchMan.createReadStreamForMember("FMT_FNT.ROM");
00332     if (!data)
00333         return false;
00334 
00335     data->read(_fontData16x16, kFont16x16Chars * 32);
00336     data->seek(251904, SEEK_SET);
00337     data->read(_fontData8x16, kFont8x16Chars * 16);
00338 
00339     bool retValue = !data->err();
00340     delete data;
00341     return retValue;
00342 }
00343 
00344 const uint8 *FontTowns::getCharData(uint16 ch) const {
00345     if (ch < kFont8x16Chars) {
00346         return _fontData8x16 + ch * 16;
00347     } else {
00348         uint8 f = ch & 0xFF;
00349         uint8 s = ch >> 8;
00350 
00351         // moved from scumm\charset.cpp
00352         enum {
00353             KANA = 0,
00354             KANJI = 1,
00355             EKANJI = 2
00356         };
00357 
00358         int base = s - ((s + 1) % 32);
00359         int c = 0, p = 0, chunk_f = 0, chunk = 0, cr = 0, kanjiType = KANA;
00360 
00361         if (f >= 0x81 && f <= 0x84) kanjiType = KANA;
00362         if (f >= 0x88 && f <= 0x9f) kanjiType = KANJI;
00363         if (f >= 0xe0 && f <= 0xea) kanjiType = EKANJI;
00364 
00365         if ((f > 0xe8 || (f == 0xe8 && base >= 0x9f)) || (f > 0x90 || (f == 0x90 && base >= 0x9f))) {
00366             c = 48; // correction
00367             p = -8; // correction
00368         }
00369 
00370         if (kanjiType == KANA) {
00371             chunk_f = (f - 0x81) * 2;
00372         } else if (kanjiType == KANJI) { // Standard Kanji
00373             p += f - 0x88;
00374             chunk_f = c + 2 * p;
00375         } else if (kanjiType == EKANJI) { // Enhanced Kanji
00376             p += f - 0xe0;
00377             chunk_f = c + 2 * p;
00378         }
00379 
00380         // Base corrections
00381         if (base == 0x7f && s == 0x7f)
00382             base -= 0x20;
00383         if (base == 0x9f && s == 0xbe)
00384             base += 0x20;
00385         if (base == 0xbf && s == 0xde)
00386             base += 0x20;
00387         //if (base == 0x7f && s == 0x9e)
00388         //  base += 0x20;
00389 
00390         switch (base) {
00391         case 0x3f:
00392             cr = 0; // 3f
00393             if (kanjiType == KANA) chunk = 1;
00394             else if (kanjiType == KANJI) chunk = 31;
00395             else if (kanjiType == EKANJI) chunk = 111;
00396             break;
00397         case 0x5f:
00398             cr = 0; // 5f
00399             if (kanjiType == KANA) chunk = 17;
00400             else if (kanjiType == KANJI) chunk = 47;
00401             else if (kanjiType == EKANJI) chunk = 127;
00402             break;
00403         case 0x7f:
00404             cr = -1; // 80
00405             if (kanjiType == KANA) chunk = 9;
00406             else if (kanjiType == KANJI) chunk = 63;
00407             else if (kanjiType == EKANJI) chunk = 143;
00408             break;
00409         case 0x9f:
00410             cr = 1; // 9e
00411             if (kanjiType == KANA) chunk = 2;
00412             else if (kanjiType == KANJI) chunk = 32;
00413             else if (kanjiType == EKANJI) chunk = 112;
00414             break;
00415         case 0xbf:
00416             cr = 1; // be
00417             if (kanjiType == KANA) chunk = 18;
00418             else if (kanjiType == KANJI) chunk = 48;
00419             else if (kanjiType == EKANJI) chunk = 128;
00420             break;
00421         case 0xdf:
00422             cr = 1; // de
00423             if (kanjiType == KANA) chunk = 10;
00424             else if (kanjiType == KANJI) chunk = 64;
00425             else if (kanjiType == EKANJI) chunk = 144;
00426             break;
00427         default:
00428             debug(4, "Invalid Char! f %x s %x base %x c %d p %d", f, s, base, c, p);
00429         }
00430 
00431         debug(6, "Kanji: %c%c f 0x%x s 0x%x base 0x%x c %d p %d chunk %d cr %d index %d", f, s, f, s, base, c, p, chunk, cr, ((chunk_f + chunk) * 32 + (s - base)) + cr);
00432         const int chunkNum = (((chunk_f + chunk) * 32 + (s - base)) + cr);
00433         if (chunkNum < 0 || chunkNum >= kFont16x16Chars)
00434             return 0;
00435         else
00436             return _fontData16x16 + chunkNum * 32;
00437     }
00438 }
00439 
00440 bool FontTowns::hasFeature(int feat) const {
00441     static const int features = kFeatDefault | kFeatOutline | kFeatShadow | kFeatFMTownsShadow | kFeatFlipped | kFeatFatPrint;
00442     return (features & feat) ? true : false;
00443 }
00444 
00445 // PC-Engine ROM font
00446 
00447 bool FontPCEngine::loadData() {
00448     Common::SeekableReadStream *data = SearchMan.createReadStreamForMember("pce.cdbios");
00449     if (!data)
00450         return false;
00451 
00452     data->seek((data->size() & 0x200) ? 0x30200 : 0x30000);
00453     data->read(_fontData12x12, kFont12x12Chars * 18);
00454 
00455     _fontWidth = _fontHeight = 12;
00456     _bitPosNewLineMask = _fontWidth & 7;
00457 
00458     bool retValue = !data->err();
00459     delete data;
00460     return retValue;
00461 }
00462 
00463 const uint8 *FontPCEngine::getCharData(uint16 ch) const {
00464     // Converts sjis code to pce font offset
00465     // (moved from scumm\charset.cpp).
00466     // rangeTbl maps SJIS char-codes to the PCE System Card font rom.
00467     // Each pair {<upperBound>,<lowerBound>} in the array represents a SJIS range.
00468     const int rangeCnt = 45;
00469     static const uint16 rangeTbl[rangeCnt][2] = {
00470         // Symbols
00471         { 0x8140, 0x817E }, { 0x8180, 0x81AC },
00472         // 0-9
00473         { 0x824F, 0x8258 },
00474         // Latin upper
00475         { 0x8260, 0x8279 },
00476         // Latin lower
00477         { 0x8281, 0x829A },
00478         // Kana
00479         { 0x829F, 0x82F1 }, { 0x8340, 0x837E }, { 0x8380, 0x8396},
00480         // Greek upper
00481         { 0x839F, 0x83B6 },
00482         // Greek lower
00483         { 0x83BF, 0x83D6 },
00484         // Cyrillic upper
00485         { 0x8440, 0x8460 },
00486         // Cyrillic lower
00487         { 0x8470, 0x847E }, { 0x8480, 0x8491},
00488         // Kanji
00489         { 0x889F, 0x88FC },
00490         { 0x8940, 0x897E }, { 0x8980, 0x89FC },
00491         { 0x8A40, 0x8A7E }, { 0x8A80, 0x8AFC },
00492         { 0x8B40, 0x8B7E }, { 0x8B80, 0x8BFC },
00493         { 0x8C40, 0x8C7E }, { 0x8C80, 0x8CFC },
00494         { 0x8D40, 0x8D7E }, { 0x8D80, 0x8DFC },
00495         { 0x8E40, 0x8E7E }, { 0x8E80, 0x8EFC },
00496         { 0x8F40, 0x8F7E }, { 0x8F80, 0x8FFC },
00497         { 0x9040, 0x907E }, { 0x9080, 0x90FC },
00498         { 0x9140, 0x917E }, { 0x9180, 0x91FC },
00499         { 0x9240, 0x927E }, { 0x9280, 0x92FC },
00500         { 0x9340, 0x937E }, { 0x9380, 0x93FC },
00501         { 0x9440, 0x947E }, { 0x9480, 0x94FC },
00502         { 0x9540, 0x957E }, { 0x9580, 0x95FC },
00503         { 0x9640, 0x967E }, { 0x9680, 0x96FC },
00504         { 0x9740, 0x977E }, { 0x9780, 0x97FC },
00505         { 0x9840, 0x9872 }
00506     };
00507 
00508     ch = (ch << 8) | (ch >> 8);
00509     int offset = 0;
00510     for (int i = 0; i < rangeCnt; ++i) {
00511         if (ch >= rangeTbl[i][0] && ch <= rangeTbl[i][1]) {
00512             return _fontData12x12 + 18 * (offset + ch - rangeTbl[i][0]);
00513             break;
00514         }
00515         offset += rangeTbl[i][1] - rangeTbl[i][0] + 1;
00516     }
00517 
00518     debug(4, "Invalid Char: 0x%x", ch);
00519     return 0;
00520 }
00521 
00522 bool FontPCEngine::hasFeature(int feat) const {
00523     // Outline mode not supported due to use of _bitPosNewLineMask. This could be implemented,
00524     // but is not needed for any particular target at the moment.
00525     // Flipped mode is also not supported since the hard coded table (taken from SCUMM 5 FM-TOWNS)
00526     // is set up for font sizes of 8/16. This mode is also not required at the moment, since
00527     // there aren't any SCUMM 5 PC-Engine games.
00528     static const int features = kFeatDefault | kFeatShadow | kFeatFMTownsShadow;
00529     return (features & feat) ? true : false;
00530 }
00531 
00532 // ScummVM SJIS font
00533 
00534 FontSjisSVM::FontSjisSVM(const Common::Platform platform)
00535     : _fontData16x16(0), _fontData16x16Size(0), _fontData8x16(0), _fontData8x16Size(0),
00536       _fontData12x12(0), _fontData12x12Size(0) {
00537 
00538     if (platform == Common::kPlatformPCEngine) {
00539         _fontWidth = 12;
00540         _fontHeight = 12;
00541     }
00542 }
00543 
00544 FontSjisSVM::~FontSjisSVM() {
00545     delete[] _fontData16x16;
00546     delete[] _fontData8x16;
00547     delete[] _fontData12x12;
00548 }
00549 
00550 bool FontSjisSVM::loadData() {
00551     Common::SeekableReadStream *data = SearchMan.createReadStreamForMember("SJIS.FNT");
00552     if (!data)
00553         return false;
00554 
00555     uint32 magic1 = data->readUint32BE();
00556     uint32 magic2 = data->readUint32BE();
00557 
00558     if (magic1 != MKTAG('S', 'C', 'V', 'M') || magic2 != MKTAG('S', 'J', 'I', 'S')) {
00559         delete data;
00560         return false;
00561     }
00562 
00563     uint32 version = data->readUint32BE();
00564     if (version != kSjisFontVersion) {
00565         warning("SJIS font version mismatch, expected: %d found: %u", kSjisFontVersion, version);
00566         delete data;
00567         return false;
00568     }
00569     uint numChars16x16 = data->readUint16BE();
00570     uint numChars8x16 = data->readUint16BE();
00571     uint numChars12x12 = data->readUint16BE();
00572 
00573     if (_fontWidth == 16) {
00574         _fontData16x16Size = numChars16x16 * 32;
00575         _fontData16x16 = new uint8[_fontData16x16Size];
00576         assert(_fontData16x16);
00577         data->read(_fontData16x16, _fontData16x16Size);
00578 
00579         _fontData8x16Size = numChars8x16 * 16;
00580         _fontData8x16 = new uint8[numChars8x16 * 16];
00581         assert(_fontData8x16);
00582         data->read(_fontData8x16, _fontData8x16Size);
00583     } else {
00584         data->skip(numChars16x16 * 32);
00585         data->skip(numChars8x16 * 16);
00586 
00587         _fontData12x12Size = numChars12x12 * 24;
00588         _fontData12x12 = new uint8[_fontData12x12Size];
00589         assert(_fontData12x12);
00590         data->read(_fontData12x12, _fontData12x12Size);
00591     }
00592 
00593     bool retValue = !data->err();
00594     delete data;
00595     return retValue;
00596 }
00597 
00598 const uint8 *FontSjisSVM::getCharData(uint16 c) const {
00599     if (_fontWidth == 12)
00600         return getCharDataPCE(c);
00601     else
00602         return getCharDataDefault(c);
00603 }
00604 
00605 bool FontSjisSVM::hasFeature(int feat) const {
00606     // Flipped mode is not supported since the hard coded table (taken from SCUMM 5 FM-TOWNS)
00607     // is set up for font sizes of 8/16. This mode is also not required at the moment, since
00608     // there aren't any SCUMM 5 PC-Engine games.
00609     static const int features16 = kFeatDefault | kFeatOutline | kFeatShadow | kFeatFMTownsShadow | kFeatFlipped | kFeatFatPrint;
00610     static const int features12 = kFeatDefault | kFeatOutline | kFeatShadow | kFeatFMTownsShadow;
00611     return (((_fontWidth == 12) ? features12 : features16) & feat) ? true : false;
00612 }
00613 
00614 const uint8 *FontSjisSVM::getCharDataPCE(uint16 c) const {
00615     if (isASCII(c))
00616         return 0;
00617 
00618     const uint8 fB = c & 0xFF;
00619     const uint8 sB = c >> 8;
00620 
00621     int base, index;
00622     mapKANJIChar(fB, sB, base, index);
00623 
00624     if (base == -1)
00625         return 0;
00626 
00627     const uint offset = (base * 0xBC + index) * 24;
00628     assert(offset + 16 <= _fontData12x12Size);
00629     return _fontData12x12 + offset;
00630 }
00631 
00632 const uint8 *FontSjisSVM::getCharDataDefault(uint16 c) const {
00633     const uint8 fB = c & 0xFF;
00634     const uint8 sB = c >> 8;
00635 
00636     if (isASCII(c)) {
00637         int index = fB;
00638 
00639         // half-width katakana
00640         if (fB >= 0xA1 && fB <= 0xDF)
00641             index -= 0x21;
00642 
00643         const uint offset = index * 16;
00644         assert(offset <= _fontData8x16Size);
00645         return _fontData8x16 + offset;
00646     } else {
00647         int base, index;
00648         mapKANJIChar(fB, sB, base, index);
00649 
00650         if (base == -1)
00651             return 0;
00652 
00653         const uint offset = (base * 0xBC + index) * 32;
00654         assert(offset + 16 <= _fontData16x16Size);
00655         return _fontData16x16 + offset;
00656     }
00657 }
00658 
00659 void FontSjisSVM::mapKANJIChar(const uint8 fB, const uint8 sB, int &base, int &index) const {
00660     base = index = -1;
00661 
00662     // We only allow 2 byte SJIS characters.
00663     if (fB <= 0x80 || fB >= 0xF0 || (fB >= 0xA0 && fB <= 0xDF) || sB == 0x7F)
00664         return;
00665 
00666     base = fB - 0x81;
00667     if (base >= 0x5F)
00668         base -= 0x40;
00669 
00670     index = sB - 0x40;
00671     if (index >= 0x3F)
00672         --index;
00673 
00674     // Another check if the passed character was an
00675     // correctly encoded SJIS character.
00676     if (index < 0 || index >= 0xBC || base < 0)
00677         base = index = -1;
00678 }
00679 
00680 } // End of namespace Graphics
00681 
00682 #endif // defined(GRAPHICS_SJIS_H)


Generated on Sat Mar 16 2019 05:01:54 for ResidualVM by doxygen 1.7.1
curved edge   curved edge