private ushort AnalyzeSentence(ByteAccess textSrc, ushort maxWidth, LineInfo[] line) { ushort lineNo = 0; var text = new ByteAccess(textSrc.Data, textSrc.Offset); var firstWord = true; while (text.Offset < text.Data.Length && text[0] != 0) { ushort wordWidth = 0; ushort wordLength = 0; while (text.Offset < text.Data.Length && (text[0] != ' ') && text[0] != 0) { wordWidth = (ushort)(wordWidth + CharWidth(text[0]) - Overlap); wordLength++; text.Offset++; } if (text.Offset < text.Data.Length && text[0] == ' ') text.Offset++; wordWidth += Overlap; // no overlap on final letter of word! if (firstWord) { // first word on first line, so no separating SPACE needed line[0].Width = wordWidth; line[0].Length = wordLength; firstWord = false; } else { // see how much extra space this word will need to fit on current line // (with a separating space character - also overlapped) var spaceNeeded = (ushort)(_joinWidth + wordWidth); if (line[lineNo].Width + spaceNeeded <= maxWidth) { line[lineNo].Width += spaceNeeded; line[lineNo].Length = (ushort)(line[lineNo].Length + 1 + wordLength); // NB. space+word characters } else { // put word (without separating SPACE) at start of next line lineNo++; Debug.Assert(lineNo < MaxLines); line[lineNo].Width = wordWidth; line[lineNo].Length = wordLength; } } } return (ushort)(lineNo + 1); // return no of lines }
public void MakeTextSprite(byte slot, ByteAccess text, ushort maxWidth, byte pen) { var lines = new LineInfo[MaxLines]; var numLines = AnalyzeSentence(text, maxWidth, lines); ushort sprWidth = 0; ushort lineCnt; for (lineCnt = 0; lineCnt < numLines; lineCnt++) if (lines[lineCnt].Width > sprWidth) sprWidth = lines[lineCnt].Width; var sprHeight = (ushort)(_charHeight * numLines); var sprSize = (uint)(sprWidth * sprHeight); Debug.Assert(_textBlocks[slot] == null); // if this triggers, the speechDriver failed to call Text::releaseText. _textBlocks[slot] = new FrameHeader(new byte[sprSize + FrameHeader.Size]); Array.Copy(new[] { (byte)'N', (byte)'u', (byte)' ', (byte)' ' }, 0, _textBlocks[slot].runTimeComp.Data, _textBlocks[slot].runTimeComp.Offset, 4); _textBlocks[slot].compSize = 0; _textBlocks[slot].width = _resMan.ReadUInt16(sprWidth); _textBlocks[slot].height = _resMan.ReadUInt16(sprHeight); _textBlocks[slot].offsetX = 0; _textBlocks[slot].offsetY = 0; var linePtr = new ByteAccess(_textBlocks[slot].Data.Data, _textBlocks[slot].Data.Offset + FrameHeader.Size); linePtr.Data.Set(linePtr.Offset, NoCol, (int)sprSize); for (lineCnt = 0; lineCnt < numLines; lineCnt++) { var sprPtr = (sprWidth - lines[lineCnt].Width) / 2; // center the text for (ushort pos = 0; pos < lines[lineCnt].Length; pos++) { sprPtr += CopyChar(text[0], new ByteAccess(linePtr.Data, linePtr.Offset + sprPtr), sprWidth, pen) - Overlap; text.Offset++; } text.Offset++; // skip space at the end of the line if (SystemVars.Platform == Platform.PSX) //Chars are half height in psx version linePtr.Offset += _charHeight / 2 * sprWidth; else linePtr.Offset += _charHeight * sprWidth; } }