adds bezel compensation settings
This commit is contained in:
@@ -621,15 +621,20 @@ void GfxRenderer::drawButtonHints(const int fontId, const char* btn1, const char
|
||||
const int pageHeight = getScreenHeight();
|
||||
constexpr int buttonWidth = 106;
|
||||
constexpr int buttonHeight = 40;
|
||||
constexpr int buttonY = 40; // Distance from bottom
|
||||
constexpr int textYOffset = 7; // Distance from top of button to text baseline
|
||||
constexpr int buttonPositions[] = {25, 130, 245, 350};
|
||||
constexpr int baseButtonY = 40; // Base distance from bottom
|
||||
constexpr int textYOffset = 7; // Distance from top of button to text baseline
|
||||
constexpr int baseButtonPositions[] = {25, 130, 245, 350};
|
||||
const char* labels[] = {btn1, btn2, btn3, btn4};
|
||||
|
||||
// Apply bezel compensation (in portrait mode, bottom bezel affects Y position)
|
||||
const int bezelBottom = getBezelOffsetBottom();
|
||||
const int bezelLeft = getBezelOffsetLeft();
|
||||
const int buttonY = baseButtonY + bezelBottom;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
// Only draw if the label is non-empty
|
||||
if (labels[i] != nullptr && labels[i][0] != '\0') {
|
||||
const int x = buttonPositions[i];
|
||||
const int x = baseButtonPositions[i] + bezelLeft;
|
||||
fillRect(x, pageHeight - buttonY, buttonWidth, buttonHeight, false);
|
||||
drawRect(x, pageHeight - buttonY, buttonWidth, buttonHeight);
|
||||
const int textWidth = getTextWidth(fontId, labels[i]);
|
||||
@@ -648,9 +653,14 @@ void GfxRenderer::drawSideButtonHints(const int fontId, const char* topBtn, cons
|
||||
const int screenWidth = getScreenWidth();
|
||||
constexpr int buttonWidth = 40; // Width on screen (height when rotated)
|
||||
constexpr int buttonHeight = 80; // Height on screen (width when rotated)
|
||||
constexpr int buttonX = 5; // Distance from right edge
|
||||
constexpr int baseButtonX = 5; // Base distance from right edge
|
||||
// Position for the button group - buttons share a border so they're adjacent
|
||||
constexpr int topButtonY = 345; // Top button position
|
||||
constexpr int baseTopButtonY = 345; // Base top button position
|
||||
|
||||
// Apply bezel compensation (in portrait mode)
|
||||
const int bezelRight = getBezelOffsetRight();
|
||||
const int buttonX = baseButtonX + bezelRight;
|
||||
const int topButtonY = baseTopButtonY; // Y position doesn't need adjustment for side buttons
|
||||
|
||||
const char* labels[] = {topBtn, bottomBtn};
|
||||
|
||||
@@ -979,31 +989,107 @@ void GfxRenderer::renderChar(const EpdFontFamily& fontFamily, const uint32_t cp,
|
||||
*x += glyph->advanceX;
|
||||
}
|
||||
|
||||
// Helper to map physical bezel edge to logical edge based on orientation
|
||||
// bezelEdge: 0=physical bottom, 1=physical top, 2=physical left, 3=physical right (in portrait)
|
||||
// Returns: 0=logical bottom, 1=logical top, 2=logical left, 3=logical right
|
||||
int mapPhysicalToLogicalEdge(int bezelEdge, GfxRenderer::Orientation orientation) {
|
||||
switch (orientation) {
|
||||
case GfxRenderer::Portrait:
|
||||
return bezelEdge;
|
||||
case GfxRenderer::LandscapeClockwise:
|
||||
switch (bezelEdge) {
|
||||
case 0: return 2; // Physical bottom -> logical left
|
||||
case 1: return 3; // Physical top -> logical right
|
||||
case 2: return 1; // Physical left -> logical top
|
||||
case 3: return 0; // Physical right -> logical bottom
|
||||
}
|
||||
break;
|
||||
case GfxRenderer::PortraitInverted:
|
||||
switch (bezelEdge) {
|
||||
case 0: return 1; // Physical bottom -> logical top
|
||||
case 1: return 0; // Physical top -> logical bottom
|
||||
case 2: return 3; // Physical left -> logical right
|
||||
case 3: return 2; // Physical right -> logical left
|
||||
}
|
||||
break;
|
||||
case GfxRenderer::LandscapeCounterClockwise:
|
||||
switch (bezelEdge) {
|
||||
case 0: return 3; // Physical bottom -> logical right
|
||||
case 1: return 2; // Physical top -> logical left
|
||||
case 2: return 0; // Physical left -> logical bottom
|
||||
case 3: return 1; // Physical right -> logical top
|
||||
}
|
||||
break;
|
||||
}
|
||||
return bezelEdge;
|
||||
}
|
||||
|
||||
int GfxRenderer::getViewableMarginTop() const {
|
||||
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||
return BASE_VIEWABLE_MARGIN_TOP + (logicalEdge == 1 ? bezelCompensation : 0);
|
||||
}
|
||||
|
||||
int GfxRenderer::getViewableMarginRight() const {
|
||||
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||
return BASE_VIEWABLE_MARGIN_RIGHT + (logicalEdge == 3 ? bezelCompensation : 0);
|
||||
}
|
||||
|
||||
int GfxRenderer::getViewableMarginBottom() const {
|
||||
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||
return BASE_VIEWABLE_MARGIN_BOTTOM + (logicalEdge == 0 ? bezelCompensation : 0);
|
||||
}
|
||||
|
||||
int GfxRenderer::getViewableMarginLeft() const {
|
||||
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||
return BASE_VIEWABLE_MARGIN_LEFT + (logicalEdge == 2 ? bezelCompensation : 0);
|
||||
}
|
||||
|
||||
int GfxRenderer::getBezelOffsetTop() const {
|
||||
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||
return (logicalEdge == 1) ? bezelCompensation : 0;
|
||||
}
|
||||
|
||||
int GfxRenderer::getBezelOffsetRight() const {
|
||||
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||
return (logicalEdge == 3) ? bezelCompensation : 0;
|
||||
}
|
||||
|
||||
int GfxRenderer::getBezelOffsetBottom() const {
|
||||
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||
return (logicalEdge == 0) ? bezelCompensation : 0;
|
||||
}
|
||||
|
||||
int GfxRenderer::getBezelOffsetLeft() const {
|
||||
int logicalEdge = mapPhysicalToLogicalEdge(bezelEdge, orientation);
|
||||
return (logicalEdge == 2) ? bezelCompensation : 0;
|
||||
}
|
||||
|
||||
void GfxRenderer::getOrientedViewableTRBL(int* outTop, int* outRight, int* outBottom, int* outLeft) const {
|
||||
// Get base margins rotated for current orientation, with bezel compensation applied
|
||||
switch (orientation) {
|
||||
case Portrait:
|
||||
*outTop = VIEWABLE_MARGIN_TOP;
|
||||
*outRight = VIEWABLE_MARGIN_RIGHT;
|
||||
*outBottom = VIEWABLE_MARGIN_BOTTOM;
|
||||
*outLeft = VIEWABLE_MARGIN_LEFT;
|
||||
*outTop = getViewableMarginTop();
|
||||
*outRight = getViewableMarginRight();
|
||||
*outBottom = getViewableMarginBottom();
|
||||
*outLeft = getViewableMarginLeft();
|
||||
break;
|
||||
case LandscapeClockwise:
|
||||
*outTop = VIEWABLE_MARGIN_LEFT;
|
||||
*outRight = VIEWABLE_MARGIN_TOP;
|
||||
*outBottom = VIEWABLE_MARGIN_RIGHT;
|
||||
*outLeft = VIEWABLE_MARGIN_BOTTOM;
|
||||
*outTop = BASE_VIEWABLE_MARGIN_LEFT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 1 ? bezelCompensation : 0);
|
||||
*outRight = BASE_VIEWABLE_MARGIN_TOP + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 3 ? bezelCompensation : 0);
|
||||
*outBottom = BASE_VIEWABLE_MARGIN_RIGHT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 0 ? bezelCompensation : 0);
|
||||
*outLeft = BASE_VIEWABLE_MARGIN_BOTTOM + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 2 ? bezelCompensation : 0);
|
||||
break;
|
||||
case PortraitInverted:
|
||||
*outTop = VIEWABLE_MARGIN_BOTTOM;
|
||||
*outRight = VIEWABLE_MARGIN_LEFT;
|
||||
*outBottom = VIEWABLE_MARGIN_TOP;
|
||||
*outLeft = VIEWABLE_MARGIN_RIGHT;
|
||||
*outTop = BASE_VIEWABLE_MARGIN_BOTTOM + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 1 ? bezelCompensation : 0);
|
||||
*outRight = BASE_VIEWABLE_MARGIN_LEFT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 3 ? bezelCompensation : 0);
|
||||
*outBottom = BASE_VIEWABLE_MARGIN_TOP + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 0 ? bezelCompensation : 0);
|
||||
*outLeft = BASE_VIEWABLE_MARGIN_RIGHT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 2 ? bezelCompensation : 0);
|
||||
break;
|
||||
case LandscapeCounterClockwise:
|
||||
*outTop = VIEWABLE_MARGIN_RIGHT;
|
||||
*outRight = VIEWABLE_MARGIN_BOTTOM;
|
||||
*outBottom = VIEWABLE_MARGIN_LEFT;
|
||||
*outLeft = VIEWABLE_MARGIN_TOP;
|
||||
*outTop = BASE_VIEWABLE_MARGIN_RIGHT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 1 ? bezelCompensation : 0);
|
||||
*outRight = BASE_VIEWABLE_MARGIN_BOTTOM + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 3 ? bezelCompensation : 0);
|
||||
*outBottom = BASE_VIEWABLE_MARGIN_LEFT + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 0 ? bezelCompensation : 0);
|
||||
*outLeft = BASE_VIEWABLE_MARGIN_TOP + (mapPhysicalToLogicalEdge(bezelEdge, orientation) == 2 ? bezelCompensation : 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,17 @@ class GfxRenderer {
|
||||
static_assert(BW_BUFFER_CHUNK_SIZE * BW_BUFFER_NUM_CHUNKS == EInkDisplay::BUFFER_SIZE,
|
||||
"BW buffer chunking does not line up with display buffer size");
|
||||
|
||||
// Base viewable margins (hardware-specific, before bezel compensation)
|
||||
static constexpr int BASE_VIEWABLE_MARGIN_TOP = 9;
|
||||
static constexpr int BASE_VIEWABLE_MARGIN_RIGHT = 3;
|
||||
static constexpr int BASE_VIEWABLE_MARGIN_BOTTOM = 3;
|
||||
static constexpr int BASE_VIEWABLE_MARGIN_LEFT = 3;
|
||||
|
||||
EInkDisplay& einkDisplay;
|
||||
RenderMode renderMode;
|
||||
Orientation orientation;
|
||||
int bezelCompensation = 0; // Pixels to add for bezel defect compensation
|
||||
int bezelEdge = 0; // Which physical edge (0=bottom, 1=top, 2=left, 3=right in portrait)
|
||||
uint8_t* bwBufferChunks[BW_BUFFER_NUM_CHUNKS] = {nullptr};
|
||||
std::map<int, EpdFontFamily> fontMap;
|
||||
void renderChar(const EpdFontFamily& fontFamily, uint32_t cp, int* x, const int* y, bool pixelState,
|
||||
@@ -42,10 +50,24 @@ class GfxRenderer {
|
||||
explicit GfxRenderer(EInkDisplay& einkDisplay) : einkDisplay(einkDisplay), renderMode(BW), orientation(Portrait) {}
|
||||
~GfxRenderer() { freeBwBufferChunks(); }
|
||||
|
||||
static constexpr int VIEWABLE_MARGIN_TOP = 9;
|
||||
static constexpr int VIEWABLE_MARGIN_RIGHT = 3;
|
||||
static constexpr int VIEWABLE_MARGIN_BOTTOM = 3;
|
||||
static constexpr int VIEWABLE_MARGIN_LEFT = 3;
|
||||
// Viewable margins (includes bezel compensation applied to the configured edge)
|
||||
int getViewableMarginTop() const;
|
||||
int getViewableMarginRight() const;
|
||||
int getViewableMarginBottom() const;
|
||||
int getViewableMarginLeft() const;
|
||||
|
||||
// Bezel compensation configuration
|
||||
void setBezelCompensation(int amount, int edge) {
|
||||
bezelCompensation = amount;
|
||||
bezelEdge = edge;
|
||||
}
|
||||
|
||||
// Get bezel offset for each logical edge (0 if not the compensated edge)
|
||||
// Use these to add bezel compensation to hardcoded margins in UI screens
|
||||
int getBezelOffsetTop() const;
|
||||
int getBezelOffsetRight() const;
|
||||
int getBezelOffsetBottom() const;
|
||||
int getBezelOffsetLeft() const;
|
||||
|
||||
// Setup
|
||||
void insertFont(int fontId, EpdFontFamily font);
|
||||
|
||||
Reference in New Issue
Block a user