diff --git a/src/tests/apps/miniterminal/ViewBuffer.cpp b/src/tests/apps/miniterminal/ViewBuffer.cpp index 1b370d3521..d5d8ef25f2 100644 --- a/src/tests/apps/miniterminal/ViewBuffer.cpp +++ b/src/tests/apps/miniterminal/ViewBuffer.cpp @@ -9,6 +9,8 @@ * Distributed under the terms of the MIT License. */ +#include + #include "ViewBuffer.h" #define CHAR_WIDTH 7 @@ -38,18 +40,17 @@ static uint32 sPalette32[] = { ViewBuffer::ViewBuffer(BRect frame) - : BView(frame, "ViewBuffer", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS) + : BView(frame, "ViewBuffer", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS), + fColumns(frame.IntegerWidth() / CHAR_WIDTH), + fRows(frame.IntegerHeight() / CHAR_HEIGHT), + fGlyphGrid(NULL), + fResizeCallback(NULL), + // initially, the cursor is hidden + fCursorX(-1), + fCursorY(-1) { SetFont(be_fixed_font); - fColumns = frame.IntegerWidth() / CHAR_WIDTH; - fRows = frame.IntegerHeight() / CHAR_HEIGHT; - fResizeCallback = NULL; - - // initially, the cursor is hidden - fCursorX = -1; - fCursorY = -1; - // initialize private palette for (int i = 0; i < 8; i++) { fPalette[i].red = (sPalette32[i] >> 16) & 0xff; @@ -57,20 +58,51 @@ ViewBuffer::ViewBuffer(BRect frame) fPalette[i].blue = (sPalette32[i] >> 0) & 0xff; fPalette[i].alpha = 0xff; } + + // initialize glyph grid + uint32 size = fRows * fColumns; + if (size > 0) { + fGlyphGrid = new uint16[size]; + memset(fGlyphGrid, 0, size * sizeof(uint16)); + } } ViewBuffer::~ViewBuffer() { + delete[] fGlyphGrid; } void ViewBuffer::FrameResized(float width, float height) { + int32 oldColumns = fColumns; + int32 oldRows = fRows; + fColumns = (int32)width / CHAR_WIDTH; fRows = (int32)height / CHAR_HEIGHT; - + + // resize glyph grid + uint16* oldGlyphGrid = fGlyphGrid; + uint32 size = fRows * fColumns; + if (size > 0) { + fGlyphGrid = new uint16[size]; + memset(fGlyphGrid, 0, size * sizeof(uint16)); + } else + fGlyphGrid = NULL; + // transfer old glyph grid into new one + if (oldGlyphGrid && fGlyphGrid) { + int32 columns = min_c(oldColumns, fColumns); + int32 rows = min_c(oldRows, fRows); + for (int32 y = 0; y < rows; y++) { + for (int32 x = 0; x < columns; x++) { + fGlyphGrid[y * fColumns + x] = oldGlyphGrid[y * oldColumns + x]; + } + } + } + delete[] oldGlyphGrid; + if (fResizeCallback) fResizeCallback(fColumns, fRows, fResizeCallbackData); } @@ -149,20 +181,46 @@ ViewBuffer::FillGlyph(int32 x, int32 y, int32 width, int32 height, uint8 glyph, void ViewBuffer::RenderGlyph(int32 x, int32 y, uint8 glyph, uint8 attr) { - BPoint where(x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 3); - char string[2]; string[0] = glyph; string[1] = 0; if (LockLooper()) { - SetHighColor(GetPaletteEntry(ForegroundColor(attr))); - SetLowColor(GetPaletteEntry(BackgroundColor(attr))); - FillRect(BRect(x * CHAR_WIDTH, y * CHAR_HEIGHT, (x + 1) * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT), B_SOLID_LOW); - DrawString(string, where); + _RenderGlyph(x, y, string, attr); Sync(); UnlockLooper(); } + // remember the glyph in the grid + if (fGlyphGrid) { + fGlyphGrid[y * fColumns + x] = (glyph << 8) | attr; + } +} + + +void +ViewBuffer::Draw(BRect updateRect) +{ + if (fGlyphGrid) { + int32 startX = max_c(0, (int32)(updateRect.left / CHAR_WIDTH)); + int32 endX = min_c(fColumns - 1, (int32)(updateRect.right / CHAR_WIDTH) + 1); + int32 startY = max_c(0, (int32)(updateRect.top / CHAR_HEIGHT)); + int32 endY = min_c(fRows - 1, (int32)(updateRect.bottom / CHAR_HEIGHT) + 1); + + char string[2]; + string[1] = 0; + + for (int32 y = startY; y <= endY; y++) { + for (int32 x = startX; x <= endX; x++) { + uint16 grid = fGlyphGrid[y * fColumns + x]; + uint8 glyph = grid >> 8; + uint8 attr = grid & 0x00ff; + string[0] = glyph; + _RenderGlyph(x, y, string, attr, false); + } + } + } + + DrawCursor(fCursorX, fCursorY); } @@ -197,6 +255,49 @@ ViewBuffer::MoveCursor(int32 x, int32 y) void ViewBuffer::Blit(int32 srcx, int32 srcy, int32 width, int32 height, int32 destx, int32 desty) { + // blit inside the glyph grid + if (fGlyphGrid) { + int32 xOffset = destx - srcx; + int32 yOffset = desty - srcy; + + int32 xIncrement; + int32 yIncrement; + + uint16* src = fGlyphGrid + srcy * fColumns + srcx; + + if (xOffset > 0) { + // copy from right to left + xIncrement = -1; + src += width - 1; + } else { + // copy from left to right + xIncrement = 1; + } + + if (yOffset > 0) { + // copy from bottom to top + yIncrement = -fColumns; + src += (height - 1) * fColumns; + } else { + // copy from top to bottom + yIncrement = fColumns; + } + + uint16* dst = src + yOffset * fColumns + xOffset; + + for (int32 y = 0; y < height; y++) { + uint16* srcHandle = src; + uint16* dstHandle = dst; + for (int32 x = 0; x < width; x++) { + *dstHandle = *srcHandle; + srcHandle += xIncrement; + dstHandle += xIncrement; + } + src += yIncrement; + dst += yIncrement; + } + } + height *= CHAR_HEIGHT; width *= CHAR_WIDTH; @@ -229,4 +330,24 @@ ViewBuffer::Clear(uint8 attr) fCursorX = -1; fCursorY = -1; + + if (fGlyphGrid) + memset(fGlyphGrid, 0, fRows * fColumns * sizeof(uint16)); } + + +void +ViewBuffer::_RenderGlyph(int32 x, int32 y, const char* string, uint8 attr, bool fill) +{ + BPoint where(x * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT - 3); + + SetHighColor(GetPaletteEntry(ForegroundColor(attr))); + if (fill) { + SetLowColor(GetPaletteEntry(BackgroundColor(attr))); + FillRect(BRect(x * CHAR_WIDTH, y * CHAR_HEIGHT, + (x + 1) * CHAR_WIDTH, (y + 1) * CHAR_HEIGHT), + B_SOLID_LOW); + } + DrawString(string, where); +} + diff --git a/src/tests/apps/miniterminal/ViewBuffer.h b/src/tests/apps/miniterminal/ViewBuffer.h index 942f6bc279..6f3d69bbd4 100644 --- a/src/tests/apps/miniterminal/ViewBuffer.h +++ b/src/tests/apps/miniterminal/ViewBuffer.h @@ -23,6 +23,8 @@ virtual void FrameResized(float new_width, float new_height); void FillGlyph(int32 x, int32 y, int32 width, int32 height, uint8 glyph, uint8 attr); void RenderGlyph(int32 x, int32 y, uint8 glyph, uint8 attr); +virtual void Draw(BRect updateRect); + void DrawCursor(int32 x, int32 y); void MoveCursor(int32 x, int32 y); @@ -30,8 +32,13 @@ virtual void FrameResized(float new_width, float new_height); void Clear(uint8 attr); private: + void _RenderGlyph(int32 x, int32 y, const char* string, uint8 attr, bool fill = true); + int32 fColumns; int32 fRows; + + uint16* fGlyphGrid; + resize_callback fResizeCallback; void *fResizeCallbackData; int32 fCursorX;