From d20c12fec6ca9ea2eca2749b1791ee8bbe2b0703 Mon Sep 17 00:00:00 2001 From: Jenny Diomidova Date: Tue, 9 Dec 2025 14:50:06 +0100 Subject: [PATCH] refactor code to add colors --- flake.nix | 2 +- icon.png | Bin 0 -> 277 bytes package.json | 7 ++- resources/digits.png | Bin 659 -> 563 bytes resources/frame.png | Bin 430 -> 329 bytes src/c/bitmaps.cpp | 98 ++++++++++++++++++++++++++++++++++++++++ src/c/bitmaps.hpp | 11 +++++ src/c/cryptic_clock.cpp | 22 +++++++-- src/c/digit_layer.cpp | 26 ++--------- 9 files changed, 138 insertions(+), 28 deletions(-) create mode 100644 icon.png create mode 100644 src/c/bitmaps.cpp create mode 100644 src/c/bitmaps.hpp diff --git a/flake.nix b/flake.nix index df69be9..f00e9b3 100644 --- a/flake.nix +++ b/flake.nix @@ -3,7 +3,7 @@ inputs = { # pebble.url = "github:pebble-dev/pebble.nix"; - pebble.url = "github:diomidov/pebble.nix"; + pebble.url = "github:diomidova/pebble.nix"; flake-utils.url = "github:numtide/flake-utils"; }; diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..99704d512f5cb3b8b17cd658f36e430aadc7e7a2 GIT binary patch literal 277 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%3?x6Bmj(hU#^NA%C&rs6b?Si}mUKs7M+SzC z{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fF5l;8~T z32_C|K=A+n|K_{rF9BJMB|(0{3=Yq3qyagc1s;*b3=De8Ak0{?)V>TT$X?><>&pI; zhm%*7|J7El?LZ+8`H-o3EpUXO@ GgeCxRl}&a4 literal 0 HcmV?d00001 diff --git a/package.json b/package.json index 7504a16..03a19f7 100644 --- a/package.json +++ b/package.json @@ -32,17 +32,20 @@ { "type": "bitmap", "name": "DIGITS", - "file": "digits.png" + "file": "digits.png", + "memoryFormat": "1BitPalette" }, { "type": "bitmap", "name": "FRAME", - "file": "frame.png" + "file": "frame.png", + "memoryFormat": "1BitPalette" }, { "type": "bitmap", "name": "MENU_ICON", "file": "icon.png", + "memoryFormat": "2BitPalette", "menuIcon": true } ] diff --git a/resources/digits.png b/resources/digits.png index 7e2a67f28bfa1e882e5abb468d665eb4b9662cb6..a293531ad7ed3fb22eb839cf6f25e5a7ef1fb281 100644 GIT binary patch delta 448 zcmbQtx|wByBnLAC14FoU@Y{)sJ~C_pJ|V6^J`gNT-+3NLF_r}R1v5B2yOB0AOQD{V zM^FFF>izSaU3WVBSl9Pi zN=ny%%G&3q2_6^XVKzDN+5f}I|BahJS?z0+SimUtpwV^7bVI)u77i}`4=%HwZk%q^ z*uu=gb-s4_`=d%ya=LcnJN+4bIs||D|17TmZ60o-+~L>Kn9dM?AcOTU%j)0vVImFh zf`gc9nN1vk$W?IX3#B<)N*gN#Pu`ZeqIM<6r{6(wpUnY7H>^6EPM-R=Y|Wda zEbU?v>T4Tzn|xx+XaJ&M#-`5}g@RhlDtQvz0&|Y9%ncA#_<2f%QSDh_R=skZ>7|}J z$%Hhy<$0{D*UGG)&pspT+10}xo!_NFp1H?xu;1&IlF)52!8eig%9D)<#Fzi;j^{~_*Z=?l=}AOERCwC$-OF;r zAPfailga=8GTnBvNFT8c(miL_=}Z7gs3djiaR7uG8_#VPop)!mL0!T2g*t7rvdvF^ zDC5y!qXD#OfB+hxw^wCjEO~}R+;f0@n3mw#`8FAL@f8()s)IFb{f6Q3N*aV#f5 zKm!EO00Bby4Den%-v{SDM0VX9PJqo4{Q7nJeT44Avp1IH-wE)%q^*8^_aUy$fBJol zCG+nDxM%aLIH#oXXOWsnTK{eL0cw8cmOTC}S{n)LcOM{t1_+=50-V9Iln zFXJyk_W7ylM1lO@%n1;Pr2zsOAbrBr7)yfuf*Bm1-AJ35rBKhw zE6T{r%f109(ctOg7!q;#?M+9n0}4E>7eD@+u6K89=p|Ry{i&O{G#=`1;T6nKWVDMUN1NAIfAv_2RIdxYckOnMRY>)Mbr-YuT@_SzJ7XK&{qj=lj6glNGiK}- zud{x$iYdGG{Oz&#GW=%z%{b}E9}Z#Dgfog#d#x13H$QF;z7#AYbNm3WZjCz^*u9>v KelF{r5}E+CaZj@V delta 316 zcmV-C0mJ^u0 + +using namespace Pebble; + +// TODO move this to pebble-cpp +bool operator==(const GColor8& lhs, const GColor8& rhs) { return lhs.argb == rhs.argb; } +bool operator!=(const GColor8& lhs, const GColor8& rhs) { return lhs.argb != rhs.argb; } + +namespace { + GOwnedBitmap digitsBitmap; + GOwnedBitmap digitBitmaps[10]; + GOwnedBitmap frameBitmap; + + GColor* digitColor; + GColor* frameColor; + + + int get_palette_size(GBitmapBase& bitmap){ + switch (bitmap.GetFormat()) { + case GBitmapFormat1BitPalette: return 2; + case GBitmapFormat2BitPalette: return 4; + case GBitmapFormat4BitPalette: return 16; + default: return 0; + } + } + + GColor* find_color(GBitmapBase& bitmap, GColor color) { + GColor* palette = bitmap.GetPalette(); + if (palette == nullptr) { + ERROR("Palette is null"); + return nullptr; + } + + int paletteSize = get_palette_size(bitmap); + if (paletteSize == 0) { + ERROR("Expected GBitmapFormat[124]BitPalette, got: %d", digitsBitmap.GetFormat()); + return nullptr; + } + for (int i = 0; i < paletteSize; i++) { + if (palette[i] == color) { + DEBUG("Found color 0x%02X at index %d", color, i); + return &palette[i]; + } + } + ERROR("Color 0x%02X not found in the palette", color); + return nullptr; + } +} + +void init_bitmaps() { + digitsBitmap = GOwnedBitmap::CreateWithResource(RESOURCE_ID_DIGITS); + auto size = digitsBitmap.GetBounds().size; + uint16_t w = size.w / 10; + uint16_t h = size.h; + for (int i = 0; i < 10; i++) { + digitBitmaps[i] = GOwnedBitmap::CreateSubBitmap(digitsBitmap, Pebble::GRect(i * w, 0, w, h)); + } + + frameBitmap = GOwnedBitmap::CreateWithResource(RESOURCE_ID_FRAME); + + digitColor = find_color(digitsBitmap, GColorBlack); + frameColor = find_color(frameBitmap, GColorBlack); +} + +void deinit_bitmaps() { + for (int i = 0; i < 10; i++) { + digitBitmaps[i] = GOwnedBitmap(); + } + digitsBitmap = GOwnedBitmap(); + frameBitmap = GOwnedBitmap(); + digitColor = nullptr; + frameColor = nullptr; +} + +GBitmapBase& get_digit_bitmap(uint16_t digit) {return digitBitmaps[digit];} +GBitmapBase& get_frame_bitmap() {return frameBitmap;} + + +void set_digit_color(GColor color) { + if (digitColor != nullptr) *digitColor = color; +} +void set_frame_color(GColor color) { + if (frameColor != nullptr) *frameColor = color; +} + +void print_palette(GBitmapBase& bitmap) { + int paletteSize = get_palette_size(bitmap); + if (paletteSize == 0) { + ERROR("Expected GBitmapFormat[124]BitPalette, got: %d", digitsBitmap.GetFormat()); + return; + } + DEBUG("%d colors:", paletteSize); + GColor8* palette = bitmap.GetPalette(); + for (int i = 0; i < paletteSize; i++) { + DEBUG("* 0x%02X = argb(%d,%d,%d,%d)", palette[i].argb, palette[i].a, palette[i].r, palette[i].g, palette[i].b); + } +} \ No newline at end of file diff --git a/src/c/bitmaps.hpp b/src/c/bitmaps.hpp new file mode 100644 index 0000000..a4a7c31 --- /dev/null +++ b/src/c/bitmaps.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +void init_bitmaps(); +void deinit_bitmaps(); +Pebble::GBitmapBase& get_digit_bitmap(uint16_t digit); +Pebble::GBitmapBase& get_frame_bitmap(); +void set_digit_color(GColor color); +void set_frame_color(GColor color); +void print_palette(Pebble::GBitmapBase& bitmap); \ No newline at end of file diff --git a/src/c/cryptic_clock.cpp b/src/c/cryptic_clock.cpp index 1a8c7f9..9e5ce68 100644 --- a/src/c/cryptic_clock.cpp +++ b/src/c/cryptic_clock.cpp @@ -1,7 +1,8 @@ #include -#include "pebble_bitmap_layer.hpp" #include <@rebble/sdk-c-utils/macros.h> +#include "pebble_bitmap_layer.hpp" #include "digit_layer.hpp" +#include "bitmaps.hpp" using namespace Pebble; @@ -9,10 +10,11 @@ using namespace Pebble; class MainWindow : public AppWindow, public TickTimer { DigitLayer digitLayers[4]; - GOwnedBitmap frameBitmap; Pebble::BitmapLayer frameLayer; protected: void OnLoad() { + init_bitmaps(); + auto bounds = this->GetBounds(); int16_t w2 = bounds.size.w / 2; int16_t h = bounds.size.h; @@ -30,8 +32,12 @@ protected: this->AddChild(this->digitLayers[i]); } - this->frameBitmap = Pebble::GOwnedBitmap::CreateWithResource(RESOURCE_ID_FRAME); - this->frameLayer.SetBitmap(this->frameBitmap); + // print_palette(get_digit_bitmap(0)); + // print_palette(get_frame_bitmap()); + // set_frame_color(GColorPictonBlue); + // print_palette(get_digit_bitmap(0)); + // print_palette(get_frame_bitmap()); + this->frameLayer.SetBitmap(get_frame_bitmap()); this->frameLayer.SetFrame(bounds); this->frameLayer.SetCompositingMode(GCompOpSet); this->AddChild(this->frameLayer); @@ -42,6 +48,14 @@ protected: TickTimerStart(MINUTE_UNIT); #endif UpdateTime(false); + + this->SetBackgroundColor(GColorBlack); + set_digit_color(GColorVividCerulean); + set_frame_color(GColorPictonBlue); + } + + void OnUnload() { + deinit_bitmaps(); } void UpdateTime(bool animate=true) { diff --git a/src/c/digit_layer.cpp b/src/c/digit_layer.cpp index c7ba869..bc2af76 100644 --- a/src/c/digit_layer.cpp +++ b/src/c/digit_layer.cpp @@ -1,37 +1,21 @@ #include "digit_layer.hpp" +#include "bitmaps.hpp" #include <@rebble/sdk-c-utils/macros.h> using namespace Pebble; namespace { - // NOTE: technically a memory leak, destructor will never be called. - // Can't make it a static variable in draw_digit, because `atexit` is broken on Pebble. - static GOwnedBitmap digitBitmaps[10]; - static bool bitmapsInitialized = false; - - static void draw_digit(const Pebble::GContext& ctx, const Pebble::GRect& bounds, const uint16_t digit) { - if (!bitmapsInitialized) { - auto bitmap = GOwnedBitmap::CreateWithResource(RESOURCE_ID_DIGITS); - auto size = bitmap.GetBounds().size; - uint16_t w = size.w / 10; - uint16_t h = size.h; - for (int i = 0; i < 10; i++) { - digitBitmaps[i] = GOwnedBitmap::CreateSubBitmap(bitmap, Pebble::GRect(i * w, 0, w, h)); - } - bitmapsInitialized = true; - } - - auto bitmap = &digitBitmaps[digit]; - auto rect = bitmap->GetBounds(); + void draw_digit(const Pebble::GContext& ctx, const Pebble::GRect& bounds, const uint16_t digit) { + Pebble::GBitmapBase& bitmap = get_digit_bitmap(digit); + auto rect = bitmap.GetBounds(); rect.Align(bounds, GAlignCenter, false); - ctx.DrawBitmapInRect(*bitmap, rect); + ctx.DrawBitmapInRect(bitmap, rect); } } void DigitLayerInner::OnUpdate(const Pebble::GContext& ctx) { auto bounds = this->GetBounds(); - ctx.SetFillColor(GColorBlack); ctx.SetCompositingMode(GCompOpSet); for (int i = 0; i <= this->digitCount + 2 * this->extraDigits; i++) { Pebble::GRect rect(0, i * this->digitHeight, bounds.size.w, this->digitHeight);