mirror of
https://github.com/reactos/reactos.git
synced 2024-08-20 10:23:22 +00:00
251 lines
5.5 KiB
C
251 lines
5.5 KiB
C
//
|
|
// message.c
|
|
//
|
|
// Dissolve in/out messages into the "matrix"
|
|
//
|
|
//
|
|
//
|
|
#include <windows.h>
|
|
#include "globals.h"
|
|
#include "message.h"
|
|
#include "matrix.h"
|
|
|
|
//
|
|
// this isn't really a random-number generator. It's based on
|
|
// a 16bit CRC algorithm. With the right mask (0xb400) it is possible
|
|
// to call this function 65536 times and get a unique result every time
|
|
// with *NO* repeats. The results look random but they're not - if we
|
|
// call this function another 65536 times we get exactly the same results
|
|
// in the same order. This is necessary for fading in messages because
|
|
// we need to be guaranteed that all cells...it's completely uniform in
|
|
// operation but looks random enough to be very effective
|
|
//
|
|
WORD crc_msgrand(WORD reg)
|
|
{
|
|
const WORD mask = 0xb400;
|
|
|
|
if(reg & 1)
|
|
reg = (reg >> 1) ^ mask;
|
|
else
|
|
reg = (reg >> 1);
|
|
|
|
return reg;
|
|
}
|
|
|
|
//
|
|
// Set a new message based on font and text
|
|
//
|
|
void SetMatrixMessage(MATRIX_MESSAGE *msg, HFONT hFont, TCHAR *text)
|
|
{
|
|
HDC hdc;
|
|
RECT rect;
|
|
int x, y;
|
|
|
|
HDC hdcMessage;
|
|
HBITMAP hbmMessage;
|
|
|
|
HANDLE hOldFont, hOldBmp;
|
|
|
|
//
|
|
// Create a monochrome off-screen buffer
|
|
//
|
|
hdc = GetDC(NULL);
|
|
|
|
hdcMessage = CreateCompatibleDC(hdc);
|
|
hbmMessage = CreateBitmap(MAXMSG_WIDTH, MAXMSG_HEIGHT, 1, 1, 0);
|
|
hOldBmp = SelectObject(hdcMessage, hbmMessage);
|
|
|
|
ReleaseDC(NULL, hdc);
|
|
|
|
//
|
|
// Draw text into bitmap
|
|
//
|
|
SetRect(&rect, 0, 0, msg->width, MAXMSG_HEIGHT);
|
|
FillRect(hdcMessage, &rect, GetStockObject(WHITE_BRUSH));
|
|
|
|
hOldFont = SelectObject(hdcMessage, g_hFont);
|
|
DrawText(hdcMessage, text, -1, &rect, DT_CENTER|DT_VCENTER|DT_WORDBREAK|DT_CALCRECT);
|
|
|
|
OffsetRect(&rect, (msg->width-(rect.right-rect.left))/2, (msg->height-(rect.bottom-rect.top))/2);
|
|
DrawText(hdcMessage, text, -1, &rect, DT_CENTER|DT_VCENTER|DT_WORDBREAK);
|
|
|
|
//
|
|
// Convert bitmap into an array of cells for easy drawing
|
|
//
|
|
for(y = 0; y < msg->height; y++)
|
|
{
|
|
for(x = 0; x < msg->width; x++)
|
|
{
|
|
msg->message[x][y] = GetPixel(hdcMessage, x, y) ? 0 : 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Cleanup
|
|
//
|
|
SelectObject(hdcMessage, hOldFont);
|
|
SelectObject(hdcMessage, hOldBmp);
|
|
|
|
DeleteDC(hdcMessage);
|
|
DeleteObject(hbmMessage);
|
|
}
|
|
|
|
//
|
|
// Draw any part of the message that is visible. Make the
|
|
// message "shimmer" by using a random glyph each time
|
|
//
|
|
void DrawMatrixMessage(MATRIX *matrix, MATRIX_MESSAGE *msg, HDC hdc)
|
|
{
|
|
int x, y;
|
|
|
|
for(x = 0; x < msg->width; x++)
|
|
for(y = 0; y < msg->height; y++)
|
|
if((msg->message[x][y] & 0x8000) &&
|
|
(msg->message[x][y] & 0x00FF))
|
|
{
|
|
DrawGlyph(matrix, hdc, x * GLYPH_WIDTH, y * GLYPH_HEIGHT, RandomGlyph(MAX_INTENSITY));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Reveal specified amount of message
|
|
//
|
|
void RevealMatrixMessage(MATRIX_MESSAGE *msg, int amount)
|
|
{
|
|
while(amount--)
|
|
{
|
|
int pos;
|
|
|
|
msg->random_reg1 = crc_msgrand(msg->random_reg1);
|
|
pos = msg->random_reg1 & 0xffff;
|
|
|
|
msg->message[pos / 256][pos % 256] |= GLYPH_REDRAW;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Reset (hide) the message
|
|
//
|
|
void ClearMatrixMessage(MATRIX_MESSAGE *msg)
|
|
{
|
|
int x, y;
|
|
|
|
for(x = 0; x < msg->width; x++)
|
|
for(y = 0; y < msg->height; y++)
|
|
msg->message[x][y] = 0;
|
|
}
|
|
|
|
//
|
|
// convert from 50-500 (fast-slow) to slow(50) - fast(500)
|
|
//
|
|
int MessageSpeed()
|
|
{
|
|
return (MSGSPEED_MAX-MSGSPEED_MIN) - (g_nMessageSpeed-MSGSPEED_MIN) + MSGSPEED_MIN;
|
|
}
|
|
|
|
//
|
|
// Called once for each iteration of the matrix
|
|
//
|
|
void DoMatrixMessage(HDC hdc, MATRIX *matrix)
|
|
{
|
|
MATRIX_MESSAGE *msg = matrix->message;
|
|
|
|
int RealSpeed = MessageSpeed();
|
|
|
|
if(g_nNumMessages > 0)
|
|
{
|
|
// nothing to do yet..
|
|
if(msg->counter++ < 0)
|
|
return;
|
|
|
|
// has counter reached limit..clear the message
|
|
if(msg->counter++ == RealSpeed / 2 + (RealSpeed/4))
|
|
ClearMatrixMessage(msg);
|
|
|
|
// reset counter + display a new message
|
|
if(msg->counter >= RealSpeed)
|
|
{
|
|
// mark all message-cells as being "invisible" so the
|
|
// message gets cleared by the matrix decoding naturally
|
|
|
|
if(g_fRandomizeMessages)
|
|
msg->msgindex = crc_rand() % g_nNumMessages;
|
|
else
|
|
msg->msgindex = (msg->msgindex + 1) % g_nNumMessages;
|
|
|
|
// make a new message..initially invisible
|
|
SetMatrixMessage(msg, 0, g_szMessages[msg->msgindex]);
|
|
|
|
msg->counter = -(int)(crc_rand() % MSGSPEED_MAX);
|
|
}
|
|
// reveal the next part of the message
|
|
else if(msg->counter < RealSpeed / 2)
|
|
{
|
|
int w = (g_nMessageSpeed - MSGSPEED_MIN);
|
|
w = (1 << 16) + ((w<<16) / MSGSPEED_MAX);
|
|
w = (w * 3 * g_nMessageSpeed) >> 16;
|
|
|
|
RevealMatrixMessage(msg, w + 100);
|
|
}
|
|
|
|
//
|
|
// draw whatever part of the message is visible at this time
|
|
//
|
|
DrawMatrixMessage(matrix, msg, hdc);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set current font used for messages
|
|
//
|
|
void SetMessageFont(HWND hwnd, TCHAR *szFontName, int nPointSize, BOOL fBold)
|
|
{
|
|
int lfHeight;
|
|
HDC hdc;
|
|
HFONT hFont;
|
|
|
|
hdc = GetDC(hwnd);
|
|
|
|
lfHeight = -MulDiv(nPointSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
|
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
hFont = CreateFont(lfHeight, 0, 0, 0, fBold ? FW_BOLD: FW_NORMAL, 0, 0, 0,
|
|
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
|
ANTIALIASED_QUALITY, DEFAULT_PITCH, szFontName);
|
|
|
|
if(hFont != 0)
|
|
{
|
|
if(g_hFont != 0)
|
|
DeleteObject(g_hFont);
|
|
|
|
g_hFont = hFont;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create a message!
|
|
//
|
|
MATRIX_MESSAGE *InitMatrixMessage(HWND hwnd, int width, int height)
|
|
{
|
|
MATRIX_MESSAGE *msg;
|
|
|
|
if((msg = malloc(sizeof(MATRIX_MESSAGE))) == 0)
|
|
return 0;
|
|
|
|
ClearMatrixMessage(msg);
|
|
|
|
msg->msgindex = 0;
|
|
msg->width = min(width, MAXMSG_WIDTH);
|
|
msg->height = min(height, MAXMSG_HEIGHT);
|
|
msg->counter = -(int)(crc_rand() % MSGSPEED_MIN + MSGSPEED_MIN);
|
|
|
|
msg->random_reg1 = (WORD)GetTickCount();
|
|
|
|
SetMessageFont(hwnd, g_szFontName, g_nFontSize, g_fFontBold);
|
|
|
|
SetMatrixMessage(msg, 0, g_szMessages[0]);
|
|
|
|
return msg;
|
|
}
|