Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import XOR packed #40

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open

Import XOR packed #40

wants to merge 5 commits into from

Conversation

eltomjan
Copy link

@eltomjan eltomjan commented Mar 16, 2024

Made import preview, with optional UnXor - nice to see under the hood sometimes :-)
And there are 2 old fonts from ArduinoSimulator project in test folder.

Got lof of problems trying to add export - quite random bugs in the middle of some chars.
At the moment have only C# compression recovered from unfinished version (created 7 years ago...).
There is a special logic - GFXglyph / bitmapOffset holds bit size of char or compressed data now.
In case compression fail (size increase) there is full size and original bitmap is used

There were multiple compression versions like row bitmap array and column data bitmap and some others forgotten, but suppose bit 1 prefix was best version as it was latest I used in my old project.

#39

Let me know if you prefer JS compression implementation or if C# (/cmd project) will be enough.

Here temporary C# packer version
https://github.com/eltomjan/ETEhomeTools/tree/master/CSharp/GFXpack

@eltomjan
Copy link
Author

eltomjan commented Mar 19, 2024

Done !!!
It was not so complicated to translate C# back to JS.

  • packed is autodetected no need for separate button anymore
  • unXor optional feature - does not make much sense for standard user, but could be used for further font optimization(?)

Not sure if design fits nice and do not like useless jQuery - trying live without :-)

Just in case short description of current format:
Bitmaps is now single packed bit array.

  • 1B holds blockSize (<~ 256B), then
  • 1 prefix marks original data of blockSize
  • 0 blockSize * zeros (reduction by blockSize - 1)
  • Each char is trimmed right (useless end is not stored)

Glyphs offset now points to bit (almost)

  • suppose there could be overflow (if packed data are >8192B).
    for this case there is another calculation - average char position is substracted from original offset
  • 1st glyph offset is often useless - is 0 so they are moved back - 0 is known and offset holds first bit of next char used to get bit size
  • in case there is space in font (empty 1st char) there could be 0, for this case I am using workaround of I16_MIN (-32768) and adjust position to zero in code
  • during JS import glyphs positions are recalculated to simplify position calculations

Compressor is almost 1:1 picked from latest C# version, btw there is also small optimisation - to speedup check of non-/zero blocks - array holding sum of 1-s and I can compare 2 sum indexes instead of iterate all bits again and again.
And I need to update glyphs, so they are not text anymore (could be optional, but is it worth ??).
And there is size as line comment next to Bitmaps declaration to know if compression has any sense :-)

let glyphsOutput = 'const GFXglyph ' + name + 'Glyphs[] PROGMEM = {\n'
glyphsOutput += glyphs.join('\n') + '\n};\n\n'
glyphsOutput += '{' + glyphs.join("\n{") + '\n};\n\n'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

glyphs is an array of arrays now so I don't think that works 🤔 ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot tell looking to code, but if it would not...
Anyway I changed your logic here a bit - I am using array with data as I am changing offsets too so maybe it looks a bit different then before, also formatting was dropped at least for xored (simplicity).

Copy link
Author

@eltomjan eltomjan Apr 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, but even with plain JS you can do miracles :-)
glyphs

(93) [Array(6), Array(6), Array(6), ...]
0: (6) [45, 4, 34, 10, 5, "-33 },// 0x21 '!'"]
1: (6) [-102, 13, 12, 16, 2, `-33 },// 0x22 '"'`]

glyphs.join("\n{")
'45,4,34,10,5,-33 },// 0x21 \'!\'\n{-102,13,12,16,2,-33 },// 0x22 \'"\'\n{33,25,34,26,0,-33 },// 0x23 \'#\'\n{193,22,40,25,2,-35 },// 0x24 \'$\'\n{439,36,34,40,3,-33 },// 0x25 \'%\'\n{435,28,34,31,2,-33 },// 0x26 \'&\'\n{227,4,12,7,2,-33 },// 0x27 \'\'\'\n{268,11,43,15,3,-33 },// 0x28...

Would tell there is default toString() for small arrays and comma default separator(?) - by fortune there is nothing like [object Array]\n[object]... one would expect 👍
Also glyphs.toString() does almost same except LFs.

And if someone want to play with, may check ArduinoSimulator repo I used to build / test Arduino version - simple port of Arduino to C# (form) / C++ made in good old VS 2008(?) Express
But there is tricky Harvard architecture - you cannot distinguish program/data memory so real Atmel may not work same everytime.
Or pack / improve compression in C# GFXpack repo, great is CharBox/Row there show nice text version of data inside, you can edit by changing particular byte in arrays or say Xor even in Immediate window.

@tchapi
Copy link
Owner

tchapi commented Apr 5, 2024

Sorry @eltomjan for not coming back to you early on this — it's complicated to find personal time to contribute these days.

💪🏼 Thanks for the hard work on that.

  • I understand jQuery is not your preference, I'll rework the JS later (don't take it personally :))
  • I'm not sure of the unXor feature as, like you said, it's rather for very advanced user and will probably confuse most people
  • The "pack" option should rather be a checkbox to toggle when you export (but same, it's JS / jQuery, I'll take care of it)

👉🏼 What I would still need from you if you don't mind:

  • some comprehensive paragraph to add to the readme, for a normal user, so they can understand what the feature does, how to use it, etc. Basically: why packing the font, what's the use case? What does it do in practice? and the most important in my opinion: How to use the packed font in your Arduino project?

Thank you!

@eltomjan
Copy link
Author

eltomjan commented Apr 5, 2024

Made also a demo in meantime here eltomjan.github.io ... Adafruit-GFX-Font-Customiser.htm.

I respect your preferences - this great repo is your...

  • ok if you think there is any benefit or you prefer jQ...
  • yes, it is probably worthless for most users
  • no problem I made "backend" logic only and did not care much about UI design, logic, etc.

In short my usecase was out of FLASH (32kB), but client wanted better UI, big fonts and extend logic...
I found a way to pack these big fonts to aprox. 50% and was able to continue without problems...
Also made faster print for my Adafruit_ILI9340 LCD - it was possible to sent bitmap instead of X,Y + point color each time (inspired by fillRect method).
My old LinkedIn post contains most informations on one place. First link shows commit eltomjan/Adafruit-GFX-Library@8e89c8f with Adafruit_GFX.cpp changes, visual and xor demos, etc.

@eltomjan
Copy link
Author

eltomjan commented Apr 12, 2024

Finished test in Wokwi simulator (FreeSerifBoldItalic9pt7b) https://wokwi.com/projects/394882822504014849

XorPack changes commit (change from default GFX to XorPacked font on ILI9341) - changed files are in project folder(s)

@eltomjan
Copy link
Author

In case you do not have time, just give me instructions how to update PR and I can do that.
I do not like jQuery as it does not bring much new to JS except renaming and useless mangling existing JS/DOM methods.
Also had to live with jQ in DELMIA Apriso, but there it was real pain - lot of mixed parts, hard to be sure which one can appear, often no way to address them - most were named same / almost same and if you have jQ here, these unpredictable/repeated parts did unexpected things often - in JS/DOM you know what are you working with, but in jQ any event, etc. may be auto attached or refer to anything similar.
Also when code is not structured much, you have element, have to think how it can be refered and then search whole "universe" (neverending file-s) for handler - it was good idea to split UI and logic, but also context often get hidden/lost in real world.
And something used exceptions for normal run - jQ(?) - that is code smell - exceptions lost there exceptionality ??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants