mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-05 23:27:38 +03:00
fix: covers not displaying when too large because of ram and transparency
This commit is contained in:
parent
9b7a6a4eed
commit
8162cf831e
@ -589,9 +589,9 @@ void GfxRenderer::drawBitmap(const Bitmap &bitmap, const int x, const int y,
|
|||||||
// 1 = Dark Gray (< 70)
|
// 1 = Dark Gray (< 70)
|
||||||
// 2 = Light Gray (< 140)
|
// 2 = Light Gray (< 140)
|
||||||
// 3 = White
|
// 3 = White
|
||||||
// Draw black for val < 2 (everything below 70), treating Light Gray as White.
|
// Draw black for val < 2, and white for val >= 2 (Opaque)
|
||||||
if (renderMode == BW && val < 2) {
|
if (renderMode == BW) {
|
||||||
drawPixel(screenX, screenY);
|
drawPixel(screenX, screenY, val < 2);
|
||||||
} else if (renderMode == GRAYSCALE_MSB && (val == 1 || val == 2)) {
|
} else if (renderMode == GRAYSCALE_MSB && (val == 1 || val == 2)) {
|
||||||
drawPixel(screenX, screenY, false);
|
drawPixel(screenX, screenY, false);
|
||||||
} else if (renderMode == GRAYSCALE_LSB && val == 1) {
|
} else if (renderMode == GRAYSCALE_LSB && val == 1) {
|
||||||
@ -811,10 +811,8 @@ void GfxRenderer::drawBitmap1Bit(const Bitmap &bitmap, const int x, const int y,
|
|||||||
const uint8_t val = outputRow[bmpX / 4] >> (6 - ((bmpX * 2) % 8)) & 0x3;
|
const uint8_t val = outputRow[bmpX / 4] >> (6 - ((bmpX * 2) % 8)) & 0x3;
|
||||||
|
|
||||||
// For 1-bit source: 0 or 1 -> map to black (0,1,2) or white (3)
|
// For 1-bit source: 0 or 1 -> map to black (0,1,2) or white (3)
|
||||||
// val < 3 means black pixel (draw it)
|
// Draw black if val < 3, Draw white if val == 3 (Opaque)
|
||||||
if (val < 3) {
|
drawPixel(screenX, screenY, val < 3);
|
||||||
drawPixel(screenX, screenY, true);
|
|
||||||
}
|
|
||||||
// White pixels (val == 3) are not drawn (leave background)
|
// White pixels (val == 3) are not drawn (leave background)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "ListElement.h"
|
#include "ListElement.h"
|
||||||
#include "ThemeManager.h"
|
#include "ThemeManager.h"
|
||||||
#include "ThemeTypes.h"
|
#include "ThemeTypes.h"
|
||||||
|
#include <GfxRenderer.h>
|
||||||
|
|
||||||
namespace ThemeEngine {
|
namespace ThemeEngine {
|
||||||
|
|
||||||
@ -20,62 +21,89 @@ void BitmapElement::draw(const GfxRenderer& renderer, const ThemeContext& contex
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we have a cached 1-bit render of this bitmap at this size
|
// Resolve simplified or relative paths
|
||||||
|
if (path.find('/') == std::string::npos || (path.length() > 0 && path[0] != '/')) {
|
||||||
|
path = ThemeManager::get().getAssetPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Check if we have a cached 1-bit render
|
||||||
const ProcessedAsset* processed = ThemeManager::get().getProcessedAsset(path, renderer.getOrientation(), absW, absH);
|
const ProcessedAsset* processed = ThemeManager::get().getProcessedAsset(path, renderer.getOrientation(), absW, absH);
|
||||||
if (processed && processed->w == absW && processed->h == absH) {
|
if (processed && processed->w == absW && processed->h == absH) {
|
||||||
// Draw cached 1-bit data directly
|
|
||||||
const int rowBytes = (absW + 7) / 8;
|
const int rowBytes = (absW + 7) / 8;
|
||||||
for (int y = 0; y < absH; y++) {
|
for (int y = 0; y < absH; y++) {
|
||||||
const uint8_t* srcRow = processed->data.data() + y * rowBytes;
|
const uint8_t* srcRow = processed->data.data() + y * rowBytes;
|
||||||
for (int x = 0; x < absW; x++) {
|
for (int x = 0; x < absW; x++) {
|
||||||
|
// Cached 1-bit data: 0=Black, 1=White
|
||||||
bool isBlack = !(srcRow[x / 8] & (1 << (7 - (x % 8))));
|
bool isBlack = !(srcRow[x / 8] & (1 << (7 - (x % 8))));
|
||||||
if (isBlack) {
|
// Draw opaque (true=black, false=white)
|
||||||
renderer.drawPixel(absX + x, absY + y, true);
|
renderer.drawPixel(absX + x, absY + y, isBlack);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
markClean();
|
markClean();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load raw asset from cache (file data cached in memory)
|
bool drawSuccess = false;
|
||||||
|
|
||||||
|
// 2. Try Streaming (Absolute paths, large images)
|
||||||
|
if (path.length() > 0 && path[0] == '/') {
|
||||||
|
FsFile file;
|
||||||
|
if (SdMan.openFileForRead("HOME", path, file)) {
|
||||||
|
Bitmap bmp(file, true); // (file, dithering=true)
|
||||||
|
if (bmp.parseHeaders() == BmpReaderError::Ok) {
|
||||||
|
// Center logic
|
||||||
|
int drawX = absX;
|
||||||
|
int drawY = absY;
|
||||||
|
if (bmp.getWidth() < absW) drawX += (absW - bmp.getWidth()) / 2;
|
||||||
|
if (bmp.getHeight() < absH) drawY += (absH - bmp.getHeight()) / 2;
|
||||||
|
|
||||||
|
renderer.drawBitmap(bmp, drawX, drawY, absW, absH);
|
||||||
|
drawSuccess = true;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Fallback to RAM Cache (Standard method)
|
||||||
|
if (!drawSuccess) {
|
||||||
const std::vector<uint8_t>* data = ThemeManager::get().getCachedAsset(path);
|
const std::vector<uint8_t>* data = ThemeManager::get().getCachedAsset(path);
|
||||||
if (!data || data->empty()) {
|
if (data && !data->empty()) {
|
||||||
markClean();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap bmp(data->data(), data->size());
|
Bitmap bmp(data->data(), data->size());
|
||||||
if (bmp.parseHeaders() != BmpReaderError::Ok) {
|
if (bmp.parseHeaders() == BmpReaderError::Ok) {
|
||||||
markClean();
|
int drawX = absX;
|
||||||
return;
|
int drawY = absY;
|
||||||
|
if (bmp.getWidth() < absW) drawX += (absW - bmp.getWidth()) / 2;
|
||||||
|
if (bmp.getHeight() < absH) drawY += (absH - bmp.getHeight()) / 2;
|
||||||
|
|
||||||
|
renderer.drawBitmap(bmp, drawX, drawY, absW, absH);
|
||||||
|
drawSuccess = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw the bitmap (handles scaling internally)
|
// 4. Cache result if successful
|
||||||
renderer.drawBitmap(bmp, absX, absY, absW, absH);
|
if (drawSuccess) {
|
||||||
|
|
||||||
// Cache the result as 1-bit packed data for next time
|
|
||||||
ProcessedAsset asset;
|
ProcessedAsset asset;
|
||||||
asset.w = absW;
|
asset.w = absW;
|
||||||
asset.h = absH;
|
asset.h = absH;
|
||||||
asset.orientation = renderer.getOrientation();
|
asset.orientation = renderer.getOrientation();
|
||||||
|
|
||||||
const int rowBytes = (absW + 7) / 8;
|
const int rowBytes = (absW + 7) / 8;
|
||||||
asset.data.resize(rowBytes * absH, 0xFF); // Initialize to white
|
asset.data.resize(rowBytes * absH, 0xFF); // Initialize to 0xFF (White)
|
||||||
|
|
||||||
// Capture pixels using renderer's coordinate system
|
|
||||||
for (int y = 0; y < absH; y++) {
|
for (int y = 0; y < absH; y++) {
|
||||||
uint8_t* dstRow = asset.data.data() + y * rowBytes;
|
uint8_t* dstRow = asset.data.data() + y * rowBytes;
|
||||||
for (int x = 0; x < absW; x++) {
|
for (int x = 0; x < absW; x++) {
|
||||||
// Read pixel from framebuffer (this handles orientation)
|
// Read precise pixel state from framebuffer
|
||||||
bool isBlack = renderer.readPixel(absX + x, absY + y);
|
bool isBlack = renderer.readPixel(absX + x, absY + y);
|
||||||
if (isBlack) {
|
if (isBlack) {
|
||||||
|
// Clear bit for black (0)
|
||||||
dstRow[x / 8] &= ~(1 << (7 - (x % 8)));
|
dstRow[x / 8] &= ~(1 << (7 - (x % 8)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThemeManager::get().cacheProcessedAsset(path, asset, absW, absH);
|
ThemeManager::get().cacheProcessedAsset(path, asset, absW, absH);
|
||||||
|
}
|
||||||
|
|
||||||
markClean();
|
markClean();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user