fix: support upscaling for bitmap render

This commit is contained in:
Brackyt 2026-01-25 21:16:23 +01:00
parent 302b37061e
commit 72de88c3bf

View File

@ -811,11 +811,11 @@ void GfxRenderer::drawTransparentBitmap(const Bitmap& bitmap, const int x, const
float scale = 1.0f; float scale = 1.0f;
bool isScaled = false; bool isScaled = false;
if (w > 0 && bitmap.getWidth() > w) { if (w > 0) {
scale = static_cast<float>(w) / static_cast<float>(bitmap.getWidth()); scale = static_cast<float>(w) / static_cast<float>(bitmap.getWidth());
isScaled = true; isScaled = true;
} }
if (h > 0 && bitmap.getHeight() > h) { if (h > 0) {
scale = std::min(scale, static_cast<float>(h) / static_cast<float>(bitmap.getHeight())); scale = std::min(scale, static_cast<float>(h) / static_cast<float>(bitmap.getHeight()));
isScaled = true; isScaled = true;
} }
@ -839,25 +839,34 @@ void GfxRenderer::drawTransparentBitmap(const Bitmap& bitmap, const int x, const
} }
const int bmpYOffset = bitmap.isTopDown() ? bmpY : bitmap.getHeight() - 1 - bmpY; const int bmpYOffset = bitmap.isTopDown() ? bmpY : bitmap.getHeight() - 1 - bmpY;
int screenY = y + (isScaled ? static_cast<int>(std::floor(bmpYOffset * scale)) : bmpYOffset);
if (screenY >= getScreenHeight()) continue; // Calculate target Y span
if (screenY < 0) continue; int startY = y + static_cast<int>(std::floor(bmpYOffset * scale));
int endY = y + static_cast<int>(std::floor((bmpYOffset + 1) * scale));
// Clamp to screen
if (startY < 0) startY = 0;
if (endY > getScreenHeight()) endY = getScreenHeight();
if (startY >= endY) continue;
for (int bmpX = 0; bmpX < bitmap.getWidth(); bmpX++) { for (int bmpX = 0; bmpX < bitmap.getWidth(); bmpX++) {
int screenX = x + (isScaled ? static_cast<int>(std::floor(bmpX * scale)) : bmpX); // Calculate target X span
int startX = x + static_cast<int>(std::floor(bmpX * scale));
int endX = x + static_cast<int>(std::floor((bmpX + 1) * scale));
if (screenX >= getScreenWidth()) break; if (startX < 0) startX = 0;
if (screenX < 0) continue; if (endX > getScreenWidth()) endX = getScreenWidth();
if (startX >= endX) continue;
// Get 2-bit value. For 1-bit BMPs from BmpReader: // Extract 2-bit value (0=Black, 3=White for 1-bit BMP)
// Black in BMP -> 0 (Black)
// White in BMP -> 3 (White)
const uint8_t val = outputRow[bmpX / 4] >> (6 - ((bmpX * 2) % 8)) & 0x3; const uint8_t val = outputRow[bmpX / 4] >> (6 - ((bmpX * 2) % 8)) & 0x3;
// Only draw if NOT white (val < 3)
if (val < 3) { if (val < 3) {
drawPixel(screenX, screenY, true); // True = Black for (int sy = startY; sy < endY; sy++) {
for (int sx = startX; sx < endX; sx++) {
drawPixel(sx, sy, true); // Black
}
}
} }
} }
} }
@ -875,11 +884,11 @@ void GfxRenderer::drawRoundedBitmap(const Bitmap& bitmap, const int x, const int
float scale = 1.0f; float scale = 1.0f;
bool isScaled = false; bool isScaled = false;
if (w > 0 && bitmap.getWidth() > w) { if (w > 0) {
scale = static_cast<float>(w) / static_cast<float>(bitmap.getWidth()); scale = static_cast<float>(w) / static_cast<float>(bitmap.getWidth());
isScaled = true; isScaled = true;
} }
if (h > 0 && bitmap.getHeight() > h) { if (h > 0) {
scale = std::min(scale, static_cast<float>(h) / static_cast<float>(bitmap.getHeight())); scale = std::min(scale, static_cast<float>(h) / static_cast<float>(bitmap.getHeight()));
isScaled = true; isScaled = true;
} }
@ -936,36 +945,44 @@ void GfxRenderer::drawRoundedBitmap(const Bitmap& bitmap, const int x, const int
} }
const int bmpYOffset = bitmap.isTopDown() ? bmpY : bitmap.getHeight() - 1 - bmpY; const int bmpYOffset = bitmap.isTopDown() ? bmpY : bitmap.getHeight() - 1 - bmpY;
int screenY = y + (isScaled ? static_cast<int>(std::floor(bmpYOffset * scale)) : bmpYOffset);
if (screenY >= getScreenHeight()) continue; // Calculate target Y span
if (screenY < 0) continue; int startY = y + static_cast<int>(std::floor(bmpYOffset * scale));
int endY = y + static_cast<int>(std::floor((bmpYOffset + 1) * scale));
// Relative Y for rounded check if (startY < 0) startY = 0;
int relY = screenY - y; if (endY > getScreenHeight()) endY = getScreenHeight();
if (relY < 0 || relY >= h) continue; if (startY >= endY) continue;
for (int bmpX = 0; bmpX < bitmap.getWidth(); bmpX++) { for (int bmpX = 0; bmpX < bitmap.getWidth(); bmpX++) {
int screenX = x + (isScaled ? static_cast<int>(std::floor(bmpX * scale)) : bmpX); int startX = x + static_cast<int>(std::floor(bmpX * scale));
int endX = x + static_cast<int>(std::floor((bmpX + 1) * scale));
if (screenX >= getScreenWidth()) break; if (startX < 0) startX = 0;
if (screenX < 0) continue; if (endX > getScreenWidth()) endX = getScreenWidth();
if (startX >= endX) continue;
// Relative X for rounded check
int relX = screenX - x;
if (relX < 0 || relX >= w) continue;
// Check mask
if (!isVisible(relX, relY)) continue;
const uint8_t val = outputRow[bmpX / 4] >> (6 - ((bmpX * 2) % 8)) & 0x3; const uint8_t val = outputRow[bmpX / 4] >> (6 - ((bmpX * 2) % 8)) & 0x3;
bool pixelBlack = false;
if (renderMode == BW) { if (renderMode == BW) {
drawPixel(screenX, screenY, val < 2); pixelBlack = (val < 2);
} else if (renderMode == GRAYSCALE_MSB && (val == 1 || val == 2)) { } else if (renderMode == GRAYSCALE_MSB) {
drawPixel(screenX, screenY, false); pixelBlack = (val < 3); // Draw all non-white as black for icons/covers
} else if (renderMode == GRAYSCALE_LSB && val == 1) { } else if (renderMode == GRAYSCALE_LSB) {
drawPixel(screenX, screenY, false); pixelBlack = (val == 0);
}
if (pixelBlack) {
for (int sy = startY; sy < endY; sy++) {
int relY = sy - y;
for (int sx = startX; sx < endX; sx++) {
int relX = sx - x;
if (isVisible(relX, relY)) {
drawPixel(sx, sy, true);
}
}
}
} }
} }
} }