Ticket #8598: nut-renderer2.diff

File nut-renderer2.diff, 13.7 KB (added by eriktorbjorn, 14 years ago)

Patch against current SVN

  • engines/scumm/smush/smush_font.cpp

     
    7474                for (int j = 0; j < h; j++) {
    7575                        for (int i = 0; i < w; i++) {
    7676                                int8 value = *src++;
    77                                 if (value)
     77                                if (value != kDefaultTransparentColor)
    7878                                        dst[i] = value;
    7979                        }
    8080                        dst += dst_width;
     
    8989                                                dst[i] = 0xFF;
    9090                                        } else if (value == -31) {
    9191                                                dst[i] = 0;
    92                                         } else if (value) {
     92                                        } else if (value != kSmush44TransparentColor) {
    9393                                                dst[i] = value;
    9494                                        }
    9595                                }
     
    101101                                        int8 value = *src++;
    102102                                        if (value == 1) {
    103103                                                dst[i] = color;
    104                                         } else if (value) {
     104                                        } else if (value != kDefaultTransparentColor) {
    105105                                                dst[i] = 0;
    106106                                        }
    107107                                }
  • engines/scumm/charset.cpp

     
    16501650        if (chr == '@')
    16511651                return;
    16521652
    1653         shadow.left = _left - 1;
    1654         shadow.top = _top - 1;
     1653        shadow.left = _left;
     1654        shadow.top = _top;
    16551655
    1656         // Note that the character is drawn with a shadow, so it is slightly
    1657         // larger than the advertised dimensions. See drawShadowChar() for
    1658         // details.
    1659 
    16601656        if (_firstChar) {
    16611657                _str.left = (shadow.left >= 0) ? shadow.left : 0;
    16621658                _str.top = (shadow.top >= 0) ? shadow.top : 0;
     
    16711667        if (chr >= 256 && _vm->_useCJKMode)
    16721668                width = _vm->_2byteWidth;
    16731669
    1674         shadow.right = _left + width + 2;
    1675         shadow.bottom = _top + height + 2;
     1670        shadow.right = _left + width;
     1671        shadow.bottom = _top + height;
    16761672
    16771673        Graphics::Surface s;
    16781674        if (!ignoreCharsetMask) {
     
    16901686                drawTop -= _vm->_screenTop;
    16911687        }
    16921688
    1693         _current->drawShadowChar(s, chr, _left, drawTop, _color, _curId != 3);
     1689        if (chr >= 256 && _vm->_useCJKMode)
     1690                _current->draw2byte(s, chr, _left, drawTop, _color);
     1691        else
     1692                _current->drawChar(s, (byte)chr, _left, drawTop, _color);
    16941693        _vm->markRectAsDirty(kMainVirtScreen, shadow);
    16951694
    16961695        if (_str.left > _left)
  • engines/scumm/nut_renderer.cpp

     
    2727
    2828namespace Scumm {
    2929
    30 NutRenderer::NutRenderer(ScummEngine *vm, const char *filename, bool bitmap) :
     30NutRenderer::NutRenderer(ScummEngine *vm, const char *filename, bool compress) :
    3131        _vm(vm),
    32         _bitmapFont(bitmap),
    3332        _numChars(0),
    3433        _decodedData(0) {
    3534        memset(_chars, 0, sizeof(_chars));
    36         loadFont(filename);
     35        loadFont(filename, compress);
    3736}
    3837
    3938NutRenderer::~NutRenderer() {
     
    4847        for (h = 0; h < height; h++) {
    4948                size_line = READ_LE_UINT16(src);
    5049                src += 2;
    51                 byte bit = 0x80;
    5250                byte *dstPtrNext = dst + pitch;
    5351                while (size_line > 0) {
    5452                        code = *src++;
     
    5654                        length = (code >> 1) + 1;
    5755                        if (code & 1) {
    5856                                val = *src++;
     57                                _paletteMap[val] = 1;
    5958                                size_line--;
    60                                 if (_bitmapFont) {
    61                                         for (int i = 0; i < length; i++) {
    62                                                 if (val)
    63                                                         *dst |= bit;
    64                                                 bit >>= 1;
    65                                                 if (!bit) {
    66                                                         bit = 0x80;
    67                                                         dst++;
    68                                                 }
    69                                         }
    70                                 } else {
    71                                         if (val)
    72                                                 memset(dst, val, length);
    73                                         dst += length;
    74                                 }
     59                                if (val)
     60                                        memset(dst, val, length);
     61                                dst += length;
    7562                        } else {
    7663                                size_line -= length;
    7764                                while (length--) {
    7865                                        val = *src++;
    79                                         if (_bitmapFont) {
    80                                                 if (val)
    81                                                         *dst |= bit;
    82                                                 bit >>= 1;
    83                                                 if (!bit) {
    84                                                         bit = 0x80;
    85                                                         dst++;
    86                                                 }
    87                                         } else {
    88                                                 if (val)
    89                                                         *dst = val;
    90                                                 dst++;
    91                                         }
     66                                        _paletteMap[val] = 1;
     67                                        if (val)
     68                                                *dst = val;
     69                                        dst++;
    9270                                }
    9371                        }
    9472                }
     
    10280                const byte *srcPtrNext = src + 2 + READ_LE_UINT16(src);
    10381                src += 2;
    10482                int len = width;
    105                 byte bit = 0x80;
    10683                do {
    107                         int i;
    10884                        int offs = READ_LE_UINT16(src); src += 2;
    109                         if (_bitmapFont) {
    110                                 for (i = 0; i < offs; i++) {
    111                                         bit >>= 1;
    112                                         if (!bit) {
    113                                                 bit = 0x80;
    114                                                 dst++;
    115                                         }
    116                                 }
    117                         } else {
    118                                 dst += offs;
    119                         }
     85                        dst += offs;
    12086                        len -= offs;
    12187                        if (len <= 0) {
    12288                                break;
     
    13096                        //  src bytes equal to 255 are replaced by 0 in dst
    13197                        //  src bytes equal to 1 are replaced by a color passed as an argument in the original function
    13298                        //  other src bytes values are copied as-is
    133                         if (_bitmapFont) {
    134                                 for (i = 0; i < w; i++) {
    135                                         if (src[i])
    136                                                 *dst |= bit;
    137                                         bit >>= 1;
    138                                         if (!bit) {
    139                                                 bit = 0x80;
    140                                                 dst++;
    141                                         }
    142                                 }
    143                         } else {
    144                                 memcpy(dst, src, w);
    145                                 dst += w;
     99                        for (int i = 0; i < w; i++) {
     100                                _paletteMap[src[i]] = 1;
    146101                        }
     102                        memcpy(dst, src, w);
     103                        dst += w;
    147104                        src += w;
    148105                } while (len > 0);
    149106                dst = dstPtrNext;
     
    151108        }
    152109}
    153110
    154 void NutRenderer::loadFont(const char *filename) {
     111void NutRenderer::loadFont(const char *filename, bool compress) {
    155112        ScummFile file;
    156113        _vm->openFile(file, filename);
    157114        if (!file.isOpen()) {
     
    181138
    182139        uint32 offset = 0;
    183140        uint32 decodedLength = 0;
    184         for (int l = 0; l < _numChars; l++) {
     141        int l;
     142       
     143        _paletteMap = new byte[256];
     144        for (l = 0; l < 256; l++) {
     145                _paletteMap[l] = 0;
     146        }
     147
     148        for (l = 0; l < _numChars; l++) {
    185149                offset += READ_BE_UINT32(dataSrc + offset + 4) + 16;
    186150                int width = READ_LE_UINT16(dataSrc + offset + 14);
    187151                int height = READ_LE_UINT16(dataSrc + offset + 16);
    188                 if (_bitmapFont) {
    189                         decodedLength += (((width + 7) / 8) * height);
    190                 } else {
    191                         decodedLength += (width * height);
    192                 }
     152                decodedLength += (width * height);
    193153        }
    194154
    195         // If characters have transparency, then bytes just get skipped and
    196         // so there may appear some garbage. That's why we have to fill it
    197         // with zeroes first.
     155        debug(1, "NutRenderer::loadFont('%s') - decodedLength = %d", filename, decodedLength);
    198156
    199157        _decodedData = new byte[decodedLength];
    200         memset(_decodedData, 0, decodedLength);
    201 
    202158        byte *decodedPtr = _decodedData;
    203159
    204160        offset = 0;
    205         for (int l = 0; l < _numChars; l++) {
     161        for (l = 0; l < _numChars; l++) {
    206162                offset += READ_BE_UINT32(dataSrc + offset + 4) + 8;
    207163                if (READ_BE_UINT32(dataSrc + offset) != MKID_BE('FRME')) {
    208164                        error("NutRenderer::loadFont(%s) there is no FRME chunk %d (offset %x)", filename, l, offset);
     
    220176                _chars[l].height = READ_LE_UINT16(dataSrc + offset + 16);
    221177                _chars[l].src = decodedPtr;
    222178
    223                 int pitch;
     179                decodedPtr += (_chars[l].width * _chars[l].height);
    224180
    225                 if (_bitmapFont) {
    226                         pitch = (_chars[l].width + 7) / 8;
     181                // If characters have transparency, then bytes just get skipped and
     182                // so there may appear some garbage. That's why we have to fill it
     183                // with a default color first.
     184                if (codec == 44) {
     185                        memset(_chars[l].src, kSmush44TransparentColor, _chars[l].width * _chars[l].height);
     186                        _paletteMap[kSmush44TransparentColor] = 1;
    227187                } else {
    228                         pitch = _chars[l].width;
     188                        memset(_chars[l].src, kDefaultTransparentColor, _chars[l].width * _chars[l].height);
     189                        _paletteMap[kDefaultTransparentColor] = 1;
    229190                }
    230191
    231                 decodedPtr += (pitch * _chars[l].height);
    232 
    233192                const uint8 *fobjptr = dataSrc + offset + 22;
    234193                switch (codec) {
    235194                case 1:
    236                         codec1(_chars[l].src, fobjptr, _chars[l].width, _chars[l].height, pitch);
     195                        codec1(_chars[l].src, fobjptr, _chars[l].width, _chars[l].height, _chars[l].width);
    237196                        break;
    238197                case 21:
    239198                case 44:
    240                         codec21(_chars[l].src, fobjptr, _chars[l].width, _chars[l].height, pitch);
     199                        codec21(_chars[l].src, fobjptr, _chars[l].width, _chars[l].height, _chars[l].width);
    241200                        break;
    242201                default:
    243202                        error("NutRenderer::loadFont: unknown codec: %d", codec);
    244203                }
    245204        }
    246205
     206        if (compress) {
     207                int numColors = 0;
     208                for (l = 0; l < 256; l++) {
     209                        if (_paletteMap[l]) {
     210                                if (numColors < ARRAYSIZE(_palette)) {
     211                                        _paletteMap[l] = numColors;
     212                                        _palette[numColors] = l;
     213                                }
     214                                numColors++;
     215                        }
     216                }
     217
     218                // Now _palette contains all the used colors, and _paletteMap
     219                // maps the real color to the palette index.
     220
     221                if (numColors <= 2)
     222                        _bpp = 1;
     223                else if (numColors <= 4)
     224                        _bpp = 2;
     225                else if (numColors <= 16)
     226                        _bpp = 4;
     227                else
     228                        _bpp = 8;
     229
     230                if (_bpp < 8) {
     231                        int compressedLength = 0;
     232                        for (l = 0; l < 256; l++) {
     233                                compressedLength += (((_bpp * _chars[l].width + 7) / 8) * _chars[l].height);
     234                        }
     235
     236                        debug(1, "NutRenderer::loadFont('%s') - compressedLength = %d (%d bpp)", filename, compressedLength, _bpp);
     237
     238                        byte *compressedData = new byte[compressedLength];
     239                        memset(compressedData, 0, compressedLength);
     240
     241                        offset = 0;
     242
     243                        for (l = 0; l < 256; l++) {
     244                                byte *src = _chars[l].src;
     245                                byte *dst = compressedData + offset;
     246                                int srcPitch = _chars[l].width;
     247                                int dstPitch = (_bpp * _chars[l].width + 7) / 8;
     248
     249                                for (int h = 0; h < _chars[l].height; h++) {
     250                                        byte bit = 0x80;
     251                                        byte *nextDst = dst + dstPitch;
     252                                        for (int w = 0; w < srcPitch; w++) {
     253                                                byte color = _paletteMap[src[w]];
     254                                                for (int i = 0; i < _bpp; i++) {
     255                                                        if (color & (1 << i))
     256                                                                *dst |= bit;
     257                                                        bit >>= 1;
     258                                                }
     259                                                if (!bit) {
     260                                                        bit = 0x80;
     261                                                        dst++;
     262                                                }
     263                                        }
     264                                        src += srcPitch;
     265                                        dst = nextDst;
     266                                }
     267                                _chars[l].src = compressedData + offset;
     268                                offset += (dstPitch * _chars[l].height);
     269                        }
     270
     271                        delete [] _decodedData;
     272                        _decodedData = compressedData;
     273                } else
     274                        _bpp = 8;
     275                       
     276        }
     277
    247278        delete [] dataSrc;
     279        delete [] _paletteMap;
    248280}
    249281
    250282int NutRenderer::getCharWidth(byte c) const {
     
    267299        return _chars[c].height;
    268300}
    269301
    270 void NutRenderer::drawShadowChar(const Graphics::Surface &s, int c, int x, int y, byte color, bool showShadow) {
    271 
    272         // We draw the character a total of 7 times: 6 times shifted and in black
    273         // for the shadow, and once in the right color and position. This way we
    274         // achieve the exact look as the original CMI had.
    275         // However, this is not how the original engine handled it. Char glyphs
    276         // were compressed with codec 44. In the decoding routine, transparent
    277         // pixels are skipped. Other pixels are just filled with the decoded color
    278         // which can be equal to 0 (==shadow), 1 (==char color) or another value
    279         // (255, 224) which is just copied as-is in the destination buffer.
    280 
    281         static const int offsetX[7] = { -1,  0, 1, 0, 1, 2, 0 };
    282         static const int offsetY[7] = {  0, -1, 0, 1, 2, 1, 0 };
    283         const int cTable[7] = { 0, 0, 0, 0, 0, 0, color };
    284         int i = 0;
    285 
    286         if (!showShadow)
    287                 i = 6;
    288 
    289         for (; i < 7; i++) {
    290                 x += offsetX[i];
    291                 y += offsetY[i];
    292                 color = cTable[i];
    293 
    294                 if (c >= 256 && _vm->_useCJKMode)
    295                         draw2byte(s, c, x, y, color);
    296                 else
    297                         drawChar(s, (byte)c, x, y, color);
    298 
    299                 x -= offsetX[i];
    300                 y -= offsetY[i];
    301         }
    302 }
    303 
    304302void NutRenderer::drawFrame(byte *dst, int c, int x, int y) {
    305         assert(!_bitmapFont);
    306 
    307303        const int width = MIN((int)_chars[c].width, _vm->_screenWidth - x);
    308304        const int height = MIN((int)_chars[c].height, _vm->_screenHeight - y);
    309305        const byte *src = _chars[c].src;
     
    340336        const int width = MIN((int)_chars[c].width, s.w - x);
    341337        const int height = MIN((int)_chars[c].height, s.h - y);
    342338        const byte *src = _chars[c].src;
    343         int srcPitch;
     339        int srcPitch = (_bpp * _chars[c].width + 7) / 8;
    344340
    345         if (_bitmapFont) {
    346                 srcPitch = (_chars[c].width + 7) / 8;
    347         } else {
    348                 srcPitch = _chars[c].width;
    349         }
    350 
    351341        const int minX = x < 0 ? -x : 0;
    352342        const int minY = y < 0 ? -y : 0;
    353343
     
    361351        }
    362352
    363353        for (int ty = minY; ty < height; ty++) {
    364                 int tx;
     354                for (int tx = minX; tx < width; tx++) {
     355                        byte val;
    365356
    366                 for (tx = minX; tx < width; tx++) {
    367                         if (_bitmapFont) {
    368                                 if (src[tx / 8] & (0x80 >> (tx % 8))) {
    369                                         dst[tx] = color;
     357                        if (_bpp < 8) {
     358                                int offset;
     359                                byte bit;
     360
     361                                switch (_bpp) {
     362                                case 1:
     363                                        offset = tx / 8;
     364                                        bit = 0x80 >> (tx % 8);
     365                                        break;
     366                                case 2:
     367                                        offset = tx / 4;
     368                                        bit = 0x80 >> (2 * (tx % 4));
     369                                        break;
     370                                default:
     371                                        offset = tx / 2;
     372                                        bit = 0x80 >> (4 * (tx % 2));
     373                                        break;
    370374                                }
     375
     376                                val = 0;
     377
     378                                for (int i = 0; i < _bpp; i++) {
     379                                        if (src[offset] & (bit >> i))
     380                                                val |= (1 << i);
     381                                }
     382
     383                                val = _palette[val];
    371384                        } else {
    372                                 if (src[tx] != 0) {
     385                                val = src[tx];
     386                        }
     387
     388                        if (val != kSmush44TransparentColor) {
     389                                if (val == 1) {
    373390                                        dst[tx] = color;
     391                                } else {
     392                                        dst[tx] = val;
    374393                                }
    375394                        }
    376395                }
  • engines/scumm/nut_renderer.h

     
    3131
    3232class NutRenderer {
    3333protected:
     34
     35        enum {
     36                kDefaultTransparentColor = 0,
     37                kSmush44TransparentColor = 2
     38        };
     39
    3440        ScummEngine *_vm;
    35         bool _bitmapFont;
    3641        int _numChars;
    3742        byte *_decodedData;
     43        byte *_paletteMap;
     44        byte _bpp;
     45        byte _palette[16];
    3846        struct {
    3947                uint16 width;
    4048                uint16 height;
     
    4452        void codec1(byte *dst, const byte *src, int width, int height, int pitch);
    4553        void codec21(byte *dst, const byte *src, int width, int height, int pitch);
    4654
    47         void drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color);
    48         void draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color);
     55        void loadFont(const char *filename, bool compress);
    4956
    50         void loadFont(const char *filename);
    51 
    5257public:
    53         NutRenderer(ScummEngine *vm, const char *filename, bool bitmap);
     58        NutRenderer(ScummEngine *vm, const char *filename, bool compress);
    5459        virtual ~NutRenderer();
    5560        int getNumChars() const { return _numChars; }
    5661
    5762        void drawFrame(byte *dst, int c, int x, int y);
    58         void drawShadowChar(const Graphics::Surface &s, int c, int x, int y, byte color, bool showShadow);
     63        void drawChar(const Graphics::Surface &s, byte c, int x, int y, byte color);
     64        void draw2byte(const Graphics::Surface &s, int c, int x, int y, byte color);
    5965
    6066        int getCharWidth(byte c) const;
    6167        int getCharHeight(byte c) const;