Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

font.cpp

/* 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.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/engines/cruise/font.cpp $
 * $Id: font.cpp 30944 2008-02-23 22:50:18Z sev $
 *
 */

#include "common/file.h"
#include "common/util.h"

#include "cruise/cruise_main.h"

namespace Cruise {

// (old: fontProc1(int16 param, uint8* ptr1, uint8* ptr2))
int32 getLineHeight(int16 charCount, uint8 * fontPtr, uint8 * fontPrt_Desc) {
      uint8 *dest;
      int32 highestChar = 0;
      int32 i;

      if (!charCount) {
            return (0);
      }
      dest = fontPrt_Desc + 6;      // fontPtr + 20         // char height

      for (i = 0; i < charCount; i++) {
            if ((*(int16 *) dest) > highestChar) {
                  highestChar = *(int16 *) dest;
            }
            dest += 12;
      }
      return highestChar;
}

// this function determins how many lines the text will have (old: fontProc2(int32 param1, int32 param2, uint8* ptr, uint8* string))
int32 getTextLineCount(int32 rightBorder_X, int32 wordSpacingWidth,
          uint8 *ptr, const uint8 *textString) {
      const uint8 *localString = textString;
      const uint8 *currentStringPtr;
      uint8 character;

      int32 var_6 = 0;
      int32 lineLength = 0;

      const uint8 *tempPtr = 0;

      if (!*localString) {
            return (0);
      }
      currentStringPtr = localString;
      character = *localString;

      do {
            int32 charData = fontCharacterTable[character];

            if (character == '|') {
                  lineLength = rightBorder_X;
                  localString = tempPtr;
            } else {
                  if (charData >= 0) {    // + 0xA jump to last 2 bytes of the 12 bytes slice = letter width
                        lineLength +=
                            wordSpacingWidth + *(int16 *) (ptr + 0xA +
                            charData * 12);
                  } else {
                        if (character == ' ') {
                              lineLength += wordSpacingWidth + 5;
                              localString = currentStringPtr;
                        }
                  }
            }

            tempPtr = currentStringPtr;

            if (rightBorder_X <= lineLength) {
                  var_6 += rightBorder_X;
                  currentStringPtr = localString;
                  tempPtr = localString;
                  lineLength = 0;
            }

            character = *(tempPtr++);
            currentStringPtr = tempPtr;

      } while (character);

      if (lineLength == 0) {
            return (var_6 / rightBorder_X);
      } else {
            return ((var_6 + rightBorder_X) / rightBorder_X);
      }
}

void loadFNT(const char *fileName) {
      uint8 header[6];
      int32 fontSize;
      int32 data2;
      uint8 data3[6];

      _systemFNT = NULL;

      Common::File fontFileHandle;

      if (!fontFileHandle.exists(fileName)) {
            return;
      }

      fontFileHandle.open((const char *)fileName);

      fontFileHandle.read(header, 4);

      if (strcmp((char*)header, "FNT") == 0) {
            fontFileHandle.read(&fontSize, 4);
            flipLong(&fontSize);

            fontFileHandle.read(&data2, 4);
            flipLong(&data2);

            fontFileHandle.read(data3, 6);      // may need an endian flip ?
            flipGen(&data3, 6);

            _systemFNT = (uint8 *)mallocAndZero(fontSize);

            if (_systemFNT != NULL) {
                  int32 i;
                  uint8 *currentPtr;

                  fontFileHandle.seek(0);
                  fontFileHandle.read(header, 4);     // not really require, we could fseek to 4

                  fontFileHandle.read(_systemFNT, fontSize);

                  flipLong((int32 *) _systemFNT);
                  flipLong((int32 *) (_systemFNT + 4));
                  flipGen(_systemFNT + 8, 6);

                  currentPtr = _systemFNT + 14;

                  for (i = 0; i < *(int16 *)(_systemFNT + 8); i++) {
                        flipLong((int32 *)currentPtr);
                        currentPtr += 4;

                        flipGen(currentPtr, 8);
                        currentPtr += 8;
                  }
            }
      }

      fontFileHandle.close();
}

void initSystem(void) {
      int32 i;

      itemColor = 15;
      titleColor = 9;
      selectColor = 13;
      subColor = 10;

      for (i = 0; i < 64; i++) {
            strcpy(preloadData[i].name, "");
            preloadData[i].ptr = NULL;
            preloadData[i].nofree = 0;
      }

      lowMemory = 0;

      doFade = 0;
      fadeFlag = 0;
      scroll = 0;
      switchPal = 0;
      masterScreen = 0;

      changeCursor(CURSOR_NORMAL);

      strcpy(cmdLine, "");

      loadFNT("system.fnt");
}

void flipShort(int16 *var) {
      uint8 *varPtr = (uint8 *) var;
      SWAP(varPtr[0], varPtr[1]);
}

void flipShort(uint16 *var) {
      uint8 *varPtr = (uint8 *) var;
      SWAP(varPtr[0], varPtr[1]);
}

void flipLong(int32 *var) {
      char *varPtr = (char *)var;

      SWAP(varPtr[0], varPtr[3]);
      SWAP(varPtr[1], varPtr[2]);
}

void flipLong(uint32 *var) {
      char *varPtr = (char *)var;

      SWAP(varPtr[0], varPtr[3]);
      SWAP(varPtr[1], varPtr[2]);
}

void flipGen(void *var, int32 length) {
      int i;
      short int *varPtr = (int16 *) var;

      for (i = 0; i < (length / 2); i++) {
            flipShort(&varPtr[i]);
      }
}

void renderWord(uint8 * fontPtr_Data, uint8 * outBufferPtr,
          int32 drawPosPixel_X, int32 heightOff, int32 height, int32 param4,
      int32 stringRenderBufferSize, int32 width, int32 charWidth) {
      int i;
      int j;
      uint8 *fontPtr_Data2 = fontPtr_Data + height * 2;

      outBufferPtr += heightOff * width * 2;    // param2 = height , param6 = width
      outBufferPtr += drawPosPixel_X;     // param1 = drawPosPixel_X

      for (i = 0; i < height; i++) {      // y++
            uint16 currentColor1 =
                (*(fontPtr_Data) << 8) | *(fontPtr_Data + 1);
            uint16 currentColor2 =
                (*(fontPtr_Data2) << 8) | *(fontPtr_Data2 + 1);

            fontPtr_Data += 2;
            fontPtr_Data2 += 2;

            for (j = 0; j < charWidth; j++) {
                  *outBufferPtr =
                      ((currentColor1 >> 15) & 1) | ((currentColor2 >>
                        14) & 2);
                  outBufferPtr++;

                  currentColor1 <<= 1;
                  currentColor2 <<= 1;
            }
            outBufferPtr += (width * 2) - charWidth;
      }
}

// returns character count and pixel size (via pointer) per line of the string (old: prepareWordRender(int32 param, int32 var1, int16* out2, uint8* ptr3, uint8* string))
int32 prepareWordRender(int32 inRightBorder_X, int32 wordSpacingWidth,
          int16 * strPixelLength, uint8 * ptr3, const uint8 * textString) {
      const uint8 *localString = textString;

      int32 counter = 0;
      int32 finish = 0;
      int32 temp_pc = 0;      // var_A                // temporary pixel count save
      int32 temp_cc = 0;      // var_C                // temporary char  count save
      int32 pixelCount = 0;   // si

      do {
            uint8 character = *(localString++);
            int16 charData = fontCharacterTable[character];

            if (character == ' ') {
                  temp_cc = counter;
                  temp_pc = pixelCount;

                  if (pixelCount + wordSpacingWidth + 5 >=
                      inRightBorder_X) {
                        finish = 1;
                  } else {
                        pixelCount += wordSpacingWidth + 5;
                  }
            } else {
                  if (character == '|' || !character) {
                        finish = 1;
                  } else {
                        if (charData) {
                              if (pixelCount + wordSpacingWidth +
                                  *(int16 *) ((ptr3 +
                                        charData * 12) + 0xA) >=
                                  inRightBorder_X) {
                                    finish = 1;
                                    if (temp_pc) {
                                          pixelCount = temp_pc;
                                          counter = temp_cc;
                                    }
                              } else {
                                    pixelCount +=
                                        wordSpacingWidth +
                                        *(int16 *) ((ptr3 +
                                          charData * 12) + 0xA);
                              }
                        }
                  }
            }
            counter++;
      } while (!finish);

      *strPixelLength = (int16) pixelCount;
      return counter;
}

void drawString(int32 x, int32 y, uint8 *string, uint8 *buffer, uint8 color,
          int32 inRightBorder_X) {
      uint8 *fontPtr;
      uint8 *fontPtr_Data;    // ptr2
      uint8 *fontPtr_Desc;    // ptr3
      int32 wordSpacingWidth; // var1
      int32 wordSpacingHeight;      // var2
      int32 rightBorder_X;    // param2
      int32 lineHeight; // fontProc1result
      int32 numLines;
      int32 stringHeight;
      int32 stringFinished;
      int32 stringWidth;      // var_1C
      int32 stringRenderBufferSize;
      int32 useDynamicBuffer;
      uint8 *currentStrRenderBuffer;
      // int32 var_8;                                                         // don't need that on
      int32 heightOffset;     // var_12
      int32 renderBufferSize; // var_1E
      int needFlip;

      if (!buffer || !string) {
            return;
      }

      if (fontFileIndex != -1) {
            fontPtr = filesDatabase[fontFileIndex].subData.ptr;

            if (!fontPtr) {
                  fontPtr = _systemFNT;
            }
      } else {
            fontPtr = _systemFNT;
      }

      if (!fontPtr) {
            return;
      }

      fontPtr_Data = fontPtr + *(int16 *) (fontPtr + 4);
      fontPtr_Desc = fontPtr + 14;

      lineHeight = getLineHeight(*(int16 *) (fontPtr + 8), fontPtr, fontPtr_Desc);  // ok

      wordSpacingWidth = *(int16 *) (fontPtr + 10);
      wordSpacingHeight = *(int16 *) (fontPtr + 12);

      if (inRightBorder_X > 310) {
            rightBorder_X = 310;
      } else {
            rightBorder_X = inRightBorder_X;
      }
      if (x + rightBorder_X > 319) {
            x = 319 - rightBorder_X;
      }
      if (y < 0) {
            y = 0;
      }
      if (x < 0) {
            x = 0;
      }
      numLines = getTextLineCount(rightBorder_X, wordSpacingWidth, fontPtr_Desc, string); // ok

      if (!numLines) {
            return;
      }
      stringHeight = ((wordSpacingHeight + lineHeight + 2) * numLines) + 1;

      if (y + stringHeight > 199) {
            y = 200 - stringHeight;
      }
      stringFinished = 0;
      stringWidth = (rightBorder_X / 16) + 2;
      stringRenderBufferSize = stringWidth * stringHeight * 4;
      inRightBorder_X = rightBorder_X;

      if (stringRenderBufferSize > 0x2000) {
            currentStrRenderBuffer =
                (uint8 *) mallocAndZero(stringRenderBufferSize);

            if (!currentStrRenderBuffer) {
                  return;
            }
            useDynamicBuffer = 1;
      } else {
            currentStrRenderBuffer = (uint8 *) workBuffer;
            useDynamicBuffer = 0;
      }

      resetRaster(currentStrRenderBuffer, stringRenderBufferSize);

      // var_8        = 0;
      heightOffset = 0;
      renderBufferSize = stringRenderBufferSize;

      do {
            int spacesCount = 0;    // si
            char character = *(string);
            short int strPixelLength;     // var_16;
            uint8 *ptrStringEnd;    // var_4        //ok
            int drawPosPixel_X;     // di

            while (character == ' ') {
                  spacesCount++;
                  character = *(string + spacesCount);
            }

            string += spacesCount;
            ptrStringEnd = string + prepareWordRender(inRightBorder_X, wordSpacingWidth, &strPixelLength, fontPtr_Desc, string);    //ok

            if (inRightBorder_X > strPixelLength) {
                  drawPosPixel_X =
                      (inRightBorder_X - strPixelLength) / 2;
            } else {
                  drawPosPixel_X = 0;
            }
            // drawPosPixel_X = var_8;

            do {
                  character = *(string++);

                  short int data = fontCharacterTable[(int)character];

                  if (character) {
                        if (character == ' ' || character == 0x7D) {
                              drawPosPixel_X += wordSpacingWidth + 5;
                        } else {
                              if (data) {
                                    short int *si =
                                        (int16 *) (fontPtr_Desc +
                                        data * 12);
                                    //int var_2     = si[5];

                                    renderWord(fontPtr_Data +
                                        si[0],
                                        currentStrRenderBuffer,
                                        drawPosPixel_X,
                                        si[4] - si[3] +
                                        lineHeight + heightOffset,
                                        si[3], si[2],
                                        renderBufferSize / 2,
                                        stringWidth * 2, si[5]);

                                    drawPosPixel_X +=
                                        wordSpacingWidth + si[5];
                              }
                        }
                  } else {
                        stringFinished = 1;
                  }

                  if (ptrStringEnd <= string) {
                        break;
                  }

            } while (!stringFinished);

            // var_8  = 0;
            heightOffset = wordSpacingHeight + lineHeight;

      } while (!stringFinished);

      needFlip = 0;

      if (buffer == gfxModuleData.pPage00) {
            if (gfxModuleData.field_1 != 0) {
                  needFlip = 1;
                  gfxModuleData_field_90();
            }

            gfxModuleData_gfxWaitVSync();
      }

      gfxModuleData_field_64((char *)currentStrRenderBuffer, stringWidth,
          stringHeight, (char *)buffer, x, y, 0);
      gfxModuleData_field_64((char *)currentStrRenderBuffer, stringWidth,
          stringHeight, (char *)buffer, x, y, color);

      if (needFlip) {
            gfxModuleData_flip();
      }

      if (useDynamicBuffer) {
            free(currentStrRenderBuffer);
      }
}

// calculates all necessary datas and renders text
gfxEntryStruct *renderText(int inRightBorder_X, const uint8 *string) {
      uint8 *fontPtr;
      uint8 *fontPtr_Data;    // pt2
      uint8 *fontPtr_Desc;    // ptr3
      int32 wordSpacingWidth; // var1               //0 or -1
      int32 wordSpacingHeight;      // var2               //0 or -1
      int32 rightBorder_X;
      int32 lineHeight; // fontProc1result
      int32 numLines;
      int32 stringHeight;
      int32 stringFinished;
      int32 stringWidth;      // var_1C
      int32 stringRenderBufferSize;
      //  int32 useDynamicBuffer;
      uint8 *currentStrRenderBuffer;
      //  int32 var_8;                          // don't need that one
      int32 heightOffset;     // var_12     // how much pixel-lines have already been drawn
      //  int32 var_1E;
      gfxEntryStruct *generatedGfxEntry;

      // check if string is empty
      if (!string) {
            return NULL;
      }
      // check if font has been loaded, else get system font
      if (fontFileIndex != -1) {
            fontPtr = filesDatabase[fontFileIndex].subData.ptr;

            if (!fontPtr) {
                  fontPtr = _systemFNT;
            }
      } else {
            fontPtr = _systemFNT;
      }

      if (!fontPtr) {
            return NULL;
      }
      fontPtr_Data = fontPtr + *(int16 *) (fontPtr + 4);    // offset to char data
      fontPtr_Desc = fontPtr + 14;  // offset to char description

      lineHeight = getLineHeight(*(int16 *) (fontPtr + 8), fontPtr, fontPtr_Desc);  // ok

      wordSpacingWidth = *(int16 *) (fontPtr + 10);
      wordSpacingHeight = *(int16 *) (fontPtr + 12);

      // if right border is higher then screenwidth (+ spacing), adjust border
      if (inRightBorder_X > 310) {
            rightBorder_X = 310;
      } else {
            rightBorder_X = inRightBorder_X;
      }
      numLines = getTextLineCount(rightBorder_X, wordSpacingWidth, fontPtr_Desc, string); // ok

      if (!numLines) {
            return NULL;
      }

      stringHeight = ((wordSpacingHeight + lineHeight + 2) * numLines) + 1;
      stringFinished = 0;
      stringWidth = rightBorder_X + 2;    // max render width to the right
      stringRenderBufferSize = stringWidth * stringHeight * 4;
      inRightBorder_X = rightBorder_X;

      currentStrRenderBuffer =
          (uint8 *) mallocAndZero(stringRenderBufferSize);
      resetRaster(currentStrRenderBuffer, stringRenderBufferSize);

      generatedGfxEntry = (gfxEntryStruct *) malloc(sizeof(gfxEntryStruct));
      generatedGfxEntry->imagePtr = currentStrRenderBuffer;
      generatedGfxEntry->imageSize = stringRenderBufferSize / 2;
      generatedGfxEntry->fontIndex = fontFileIndex;
      generatedGfxEntry->height = stringHeight;
      generatedGfxEntry->width = stringWidth;   // maximum render width to the right

      // var_8 = 0;
      heightOffset = 0;

      do {
            int spacesCount = 0;    // si
            unsigned char character = *string;
            short int strPixelLength;     // var_16
            const uint8 *ptrStringEnd;    // var_4     //ok
            int drawPosPixel_X;     // di

            // find first letter in string, skip all spaces
            while (character == ' ') {
                  spacesCount++;
                  character = *(string + spacesCount);
            }

            string += spacesCount;

            // returns character count and pixel length (via pointer) per line of the text string
            ptrStringEnd = string + prepareWordRender(inRightBorder_X, wordSpacingWidth, &strPixelLength, fontPtr_Desc, string);    //ok

            // determine how much space is left to the right and left (center text)
            if (inRightBorder_X > strPixelLength) {
                  //var_8 = (inRightBorder_X - strPixelLength) / 2;
                  drawPosPixel_X =
                      (inRightBorder_X - strPixelLength) / 2;
            } else {
                  drawPosPixel_X = 0;
            }
            //drawPosPixel_X = var_8;

            // draw textline, character wise
            do {
                  character = *(string++);

                  short int charData = fontCharacterTable[character];   // get character position

                  if (character) {
                        if (character == ' ' || character == 0x7C) {
                              drawPosPixel_X += wordSpacingWidth + 5;   // if char = "space" adjust word starting postion (don't render space though);
                        } else {
                              if (charData >= 0) {
                                    short int *si = (int16 *) (fontPtr_Desc + charData * 12);   // offset font data
                                    // int var_2 = si[5];                                   // don't need this

                                    // should ist be stringRenderBufferSize/2 for the second last param?
                                    renderWord(fontPtr_Data +
                                        si[0],
                                        currentStrRenderBuffer,
                                        drawPosPixel_X,
                                        si[4] - si[3] +
                                        lineHeight + heightOffset,
                                        si[3], si[2],
                                        stringRenderBufferSize,
                                        stringWidth / 2, si[5]);

                                    drawPosPixel_X +=
                                        wordSpacingWidth + si[5];
                              }
                        }
                  } else {
                        stringFinished = 1;     // character = 0x00
                  }

                  // check if string already reached the end
                  if (ptrStringEnd <= string) {
                        break;
                  }
            } while (!stringFinished);

            // var_8 = 0;
            heightOffset += wordSpacingHeight + lineHeight;
      } while (!stringFinished);

      return generatedGfxEntry;
}

} // End of namespace Cruise

Generated by  Doxygen 1.6.0   Back to index