Forum: Mikrocontroller und Digitale Elektronik glcd fontcreator aktuell


von maddin (Gast)


Lesenswert?

hi,

ich suche einen fontcreator mit dem man nach wunsch komprimierte fonts 
als *.h datei erzeugen kann.

die breite des buchstaben sollte dabei auch mit berücksichtigt werden... 
und die höhe einstllbar sein..

es gab mal was von ape und auch von kranz, was könnt ihr mir momentan 
empfehlen?

gruß,
m.

von Hagen R. (hagen)


Angehängte Dateien:

Lesenswert?

ich habe den Font Editor im Attachment programmiert. In der CodeLib die 
Beiträge zum Nokia6100 und S65 mal durchlesen da dort das Format der 
Fonts beschrieben ist.

Gruß hagen

von maddin (Gast)


Lesenswert?

hallo hagen,

ich habe aus den letzten 2 jahren schon etliche versionen deiner tools.

soweit ich weiß hast du den fontcreator von ape, dessne seite es ja 
schon lang nicht mehr angewohnter stelle gibt, oder?

ich habe hier auch noch zahlreiche glcd zip files von 1 bis 7.

unter anderem sind dort die "eis-zahlen" deiner nokia uhr enthalten 
usw...

in meinem font editor gibt es den button compress noch nicht, werden 
dann die farben der buchstaben compressed oder würde auch ein 
einfarbiger buchstabe reduziert?

ich habe in den zip files sehr oft eine *.h datei gefunden, doch im font 
editor keine möglichkeit gefunden die *.h datei zu erzeugen...immer nur 
*.font (binärfile)...

könntest du die routine die die erzeugten font files(*.h) 
(breite,größe,und decompress) interpretiert hier nochmal dazu 
einstellen?



danke,
m.

von Hagen R. (hagen)


Lesenswert?

> soweit ich weiß hast du den fontcreator von ape

falsch, ape hat damals nur meine GLCD auf seiner Domain gehostet, und 
dazu gehören auch die Tools.

>in meinem font editor gibt es den button compress noch nicht...

Checkbox meinst du. Falls angehackt wird versucht den Font zu 
komprimieren. Bringt das Einsparungen dann wird der Font auch kompimiert 
gespeichert, ansonsten nicht. Ist kein Häckchen gesetzt so wird immer 
unkomprimiert gespeichert.

> ...oder würde auch ein einfarbiger buchstabe reduziert?

sicher doch, es werden die Pixeldaten komprimiert, nicht die Farben. 
Farbe ansich gibt es bei meinen Fonts garnicht, sondern nur Indizes in 
eine Tabelle die Farben enthält, quasi ist der Pixeldatenstrom wie Malen 
nach Zahlen. Somit kannst du während der Laufzeit deine Mehrfabigen 
Fonts in beliebigen Farben darstellen indem du einfach die Farbtabelle 
der GLCD anders belegst.


>ich habe in den zip files sehr oft eine *.h datei gefunden, doch im font
>editor keine möglichkeit gefunden die *.h datei zu erzeugen...immer nur
>*.font (binärfile)...

Button "Export" drücken. Über die Sektion [Export] in Font.ini stellst 
du ein nach welchem Format dieser Export erfolgt. Schau dir die Dateien 
Font.ini, Template.h, Template.c, Template.asm und Templates.txt an.

>könntest du die routine die die erzeugten font files(*.h)
>(breite,größe,und decompress) interpretiert hier nochmal dazu
>einstellen?

nachfolgend der Ausschnitt aus meiner S65 Library.

Gruß Hagen
1
void glcdSelectFont(const void* data) {
2
3
    glcdFontData_t d = (glcdFontData_t)data;
4
    if (glcd.FontData == d) return;
5
    glcd.FontData = d;
6
    if (!(d)) return;
7
    d += 2;
8
    glcd.FontWidth = pgm_read_byte_inc(d);
9
    glcd.FontHeight = pgm_read_byte_inc(d);
10
    glcd.FontBitsPixel = pgm_read_byte_inc(d);
11
    glcd.FontFirstChar = pgm_read_byte_inc(d);
12
    glcd.FontLastChar = pgm_read_byte_inc(d);
13
    if (glcd.FontBitsPixel & 0x80) { // compressed font
14
      d = glcd.FontData + (GLCD_FONT_HEADER_SIZE + 1) + (glcd.FontLastChar - glcd.FontFirstChar);
15
      glcd.FontBitsHeight = pgm_read_byte_inc(d);
16
      glcd.FontRLE[0] = 1;
17
      glcd.FontRLE[1] = pgm_read_byte_inc(d);
18
      glcd.FontRLE[2] = pgm_read_byte_inc(d);
19
      glcd.FontRLE[3] = pgm_read_byte_inc(d);
20
    } else {
21
      glcd.FontBitsHeight = glcd.FontHeight * glcd.FontBitsPixel;
22
    }
23
24
}
25
26
void glcdDrawText(const char* text, uint16_t size, uint8_t flashstored) {
27
28
    if ((text == 0) || (glcd.FontData == 0)) return;
29
30
    uint8_t flags = (flashstored ? 0x70 : 0x30) | (glcd.FontBitsPixel & 0x80) | (glcd.Flags.All & 0x07);
31
    uint8_t bitspixel = glcd.FontBitsPixel & 0x7F;
32
    uint8_t bitsmask = 0xFF >> (8 - bitspixel);
33
    uint8_t FontHeight = glcd.FontHeight, FontWidth = glcd.FontWidth, FontCharSpace = glcd.FontCharSpace;
34
    uint8_t FontFirstChar = glcd.FontFirstChar, FontLastChar = glcd.FontLastChar;
35
    uint8_t charofs = FontLastChar - FontFirstChar +5;
36
    glcdCoord_t Cursorx = glcd.Cursor.x, Cursory = glcd.Cursor.y;
37
    glcdCoord_t Windowx2 = glcd.Window.x2 +1, Windowy2 = glcd.Window.y2 +1, Windowx1 = glcd.Window.x1, Windowy1 = glcd.Window.y1;
38
    glcdFontData_t data, FontData = glcd.FontData + GLCD_FONT_HEADER_SIZE;
39
    uint16_t FontBitsHeight = glcd.FontBitsHeight;
40
    uint16_t* colors = &glcd.Colors[0];
41
    uint8_t* rle = &glcd.FontRLE[0];
42
43
    glcdColor_t color = 0;
44
    uint8_t c, i, width, charwidth, bitsmul, pixelcount, bitscount, leftspace, rightspace;
45
    uint32_t index;
46
    uint16_t bits;
47
48
    for (; size > 0; size--) {
49
50
      if (flags & 0x40) c = pgm_read_byte_inc(text);
51
        else c = *text++;
52
53
      if (!(c)) break;
54
55
      if (c == '\n') {
56
        Cursorx  = Windowx1;
57
        Cursory += FontHeight;
58
        if (Cursory + FontHeight > Windowy2) Cursory = Windowy1;
59
        flags |= 0x10;  // invalidate LCD address pointer
60
        continue;
61
      }
62
63
      if ((c < FontFirstChar) || (c > FontLastChar)) continue;
64
65
      data = FontData + c - FontFirstChar;
66
      charwidth = pgm_read_byte(data);
67
      if (!(charwidth)) continue;
68
69
      width = charwidth;
70
      if ((flags & 0x04) && (c < 128)) width++;
71
      if ((flags & 0x01) && (width < FontWidth)) width = FontWidth;  // FixedFont ??
72
      width += FontCharSpace;
73
74
      if (Cursorx + width > Windowx2) {  // LineFeed ??
75
        if (flags & 0x02) {
76
          Cursorx  = Windowx1;
77
          Cursory += FontHeight;
78
          if (Cursory + FontHeight > Windowy2) Cursory = Windowy1;
79
          flags |= 0x10;  // invalidate LCD address pointer
80
        } else break;
81
      }
82
83
      index = 0;
84
      data = FontData;
85
      if (flags & 0x80) data += charofs;
86
      for (i = c - FontFirstChar; i > 0; i--)
87
        index += pgm_read_byte_inc(data);
88
89
      index *= FontBitsHeight;
90
      data = FontData + charofs -4;
91
      if (flags & 0x80) {
92
        data += charofs;
93
        data += index;
94
        bits = 0;
95
        bitscount = 0;
96
      } else {
97
        bitscount = index & 0x07;
98
        index >>= 3;
99
        data += index;
100
        bits = pgm_read_byte_inc(data) >> bitscount;
101
        bitscount = 8 - bitscount;
102
      }
103
104
      leftspace = 0;
105
      rightspace = width - charwidth;
106
      if (flags & 0x01) { // FixedFont ??
107
        leftspace = rightspace / 2;
108
        rightspace -= leftspace;
109
        if ((leftspace > 0) && (colors[0] == NONE)) {
110
          flags |= 0x10;
111
          Cursorx += leftspace;
112
          width -= leftspace;
113
          leftspace = 0;
114
        }
115
      }
116
117
      if (flags & 0x20) { // initialize LCD ??
118
        flags ^= 0x20;
119
        GLCD_CS_ON();
120
      #ifdef GLCD_ROTATE
121
        GLCD_SETMODE(0x30 | GLCD_ROP_WNE);
122
      #else
123
        GLCD_SETMODE(0x38 | GLCD_ROP_WNE);
124
      #endif
125
        GLCD_SETCOMPARE(NONE);
126
      }
127
      
128
      if (flags & 0x10) { // LCD address pointer invalid ??
129
        flags ^= 0x10;
130
        GLCD_WAIT();
131
        GLCD_CS_PULSE();
132
        GLCD_WINDOW(Cursorx, Cursory, GLCD_RIGHT, Cursory + FontHeight -1);
133
        GLCD_SETADDR(Cursorx, Cursory);
134
        GLCD_STARTDATA();
135
      }
136
      Cursorx += width;
137
138
      if (leftspace > 0) {
139
        color = colors[0];
140
        do {
141
          i = FontHeight;
142
          do {
143
            GLCD_WAIT();
144
            GLCD_OUT(H8(color));
145
            GLCD_WAIT();
146
            GLCD_OUT(L8(color));
147
          } while (--i);
148
        } while (--leftspace);
149
      }
150
151
      bitsmul = pgm_read_byte(&powerof2[bitscount & 0x07]);
152
      if (bitscount < 8) {
153
        bitscount += 8;
154
        bits |= pgm_read_byte_inc(data) * bitsmul;    // faster as shifting
155
      }
156
      pixelcount = 1;
157
      do {
158
        i = FontHeight;
159
        do {
160
          if (!(--pixelcount)) {
161
            pixelcount++;
162
            if (flags & 0x80) { // compresed Font ??
163
              pixelcount = rle[bits & 0x03];
164
              bits >>= 2;
165
              bitscount -= 2;
166
            }
167
            bitscount -= bitspixel;
168
            bitsmul = pgm_read_byte(&powerof2[bitscount & 0x07]);
169
            color = colors[bits & bitsmask];
170
            bits >>= bitspixel;
171
          }
172
          GLCD_WAIT();
173
          GLCD_OUT(H8(color));
174
          if (bitscount < 8) { // read in advance while we wait for SPI
175
            bitscount += 8;
176
            bits |= pgm_read_byte_inc(data) * bitsmul;   // faster as shifting
177
          }
178
          GLCD_WAIT();
179
          GLCD_OUT(L8(color));
180
        } while (--i);
181
      } while (--charwidth);
182
183
      if (rightspace > 0) {
184
        color = colors[0];
185
        if (color == NONE) {
186
          flags |= 0x10; // ab >= 11 Pixel macht das Neusetzen des Windows Sinn, ergo FontHeight * rightspace >= 11, gilt auf für leftspace, hier ignorieren wir das aber
187
        } else {
188
          do {
189
            i = FontHeight;
190
            do {
191
              GLCD_WAIT();
192
              GLCD_OUT(H8(color));
193
              GLCD_WAIT();
194
              GLCD_OUT(L8(color));
195
            } while (--i);
196
          } while (--rightspace);
197
        }
198
      }
199
    }
200
    if (!(flags & 0x20)) { // have LCD initialized, anything done ??
201
      GLCD_WAIT();
202
      GLCD_CS_PULSE();
203
      GLCD_RESETWINDOW();
204
      GLCD_SETMODE(0x30);
205
      GLCD_CS_OFF();
206
    }
207
    glcd.Cursor.x = Cursorx;
208
    glcd.Cursor.y = Cursory;
209
}
210
211
void glcdDrawChar(char value) {
212
213
    glcd.Buf[0] = value;
214
    glcdDrawText(glcd.Buf, 1, 0);
215
}

von maddin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Hagen,

danke für die ausführliche Antwort, ich habe heute mal ein wenig mit dem 
fontcreator rumgespielt, und werde ihn für mein projekt verwenden.

ich hatte leider noch alte versionen, im anhang ist eine meiner letzten, 
dort ist die option (compress) noch nicht vorhanden, zumindest konnte 
man sie noch nicht deaktivieren...

ich habe auch noch etwas ältere fontsätze, in denen das byte 5 (bit per 
pixel plus compression bit) fehlten...

static uint8_t Arial_Bold_14[] PROGMEM = {
    0x22, 0x08, // size
    0x0A, // width
    0x0E, // height
    0x20, // first char
    0x60, // char count

    // char widths
    0x04, 0x02, 0x05, 0x06, 0x07, 0x08, 0x09, 0x02, 0x03, 0x03,

die aktuelle struktur sieht dann ja wie folgt aus:

     // common shared fields
       uint16_t   font_Size_in_Bytes_over_all_included_Size_it_self;
       uint8_t    font_Width_in_Pixel_for_fixed_drawing;
       uint8_t    font_Height_in_Pixel_for_all_Characters;
       uint8_t    font_Bits_per_Pixels;
                    // if MSB are set then font is a compressed font
       uint8_t    font_First_Char;
       uint8_t    font_Last_Char;
       uint8_t    font_Char_Widths[font_Last_Char - font_First_Char +1];
                    // for each character the separate width in pixels,
                    // characters < 128 have an implicit
                   // characters with font_Char_Widths[] == 0 are

       // if compressed font then additional fields
       uint8_t    font_Byte_Padding;
                    // each Char in the table are aligned in size to
       uint8_t    font_RLE_Table[3];
                    // Run Length Encoding Table for compression
       uint8_t    font_Char_Size_in_Bytes[font_Last_Char - 
font_First_Char

                    // for each char the size in (bytes /

                    // this get us the table to seek to the right
                    // in the font_data[].

       // for compressed and uncompressed fonts
       uint8_t    font_data[];
                    // bit field of all characters

ich möchte gern ein anderes display damit steuern, deswegen ist für mich 
die schnittstelle zum display (set pixel(x,y,col) und die schnittstelle 
zum font ganz wichtig (set font(arial)).schreibst du byteweise ins 
display?

wo bekomme ich den rest deiner geposteten version her, ist diese aus dem 
thread von kranz zum s65 display.

ich habe heute mal angefangen die bytes in den erzeugten files zu 
interpretieren, dabei ist mir aufgefallen, das die pixeldaten in am msb 
orientiert sind, und das beim einsatz von entsprechend mehr farben mehr 
bist gewählt werden, nach welcher logik allerdings die anzahl der bits 
berechnet werden ist mir noch schleierhaft, ab wann nimmt er 4 bit oder 
7 oder 8? die farben sind ja alle als 24 bit in der ini definiert...(das 
mit der farbtabelle und der freien zuordnung ist klar, und die idee mit 
den frei "baubaren templates einfach klasse).

des weiteren ist es gut, das die compress funktion abwählbar ist, denn 
in den meisten meiner testfälle musste sie eh nicht greifen, da der 
reduzierte datensatz meist größer war, in anderen griff die dann 
teilweise unerwartet. ich habe es mal mit schwarzweiß schrift"symbolen" 
versucht, waagehrechte striche usw.. die eigentlich bytereihenfolge 
gleicher struktur erzeugen, dennoch war der reduzierte satz größer, aber 
ich habe das kompressionsverfahren auch noch nicht speziell in diesem 
fall durchgesehen. RLE ist ein beriff und die vorgehensweise ist klar, 
indikator, multiplikator usw... hat du das für diesen fall mal irgenwo 
beschrieben, oder hälst du dich an einen bestimmten standard? das 
gesamte projekt hilft sicher auch schon weiter, also die c dateien die 
zu dieser version des fontgenerators gehören...

gruß,
m.

gruß,
m.

von maddin (Gast)


Lesenswert?

...ich lese gerade in der codesammlung:

Autor: Hagen Re (hagen)
Datum: 03.10.2006 01:35


seit 2006 hat sich einiges geändert - toll nur weil manche das forum 
hier scheinbar komerziell ausnutzen, funktioniert das geben und nehmen 
nicht mehr, oder nur noch eingeschränkt - was?

tja, hagen ich weiß nicht ob du diesen code jetzt überhaupt schonmal 
rausgegeben hast, der fontcreator ist jedenfalls schonmal klasse.

nur die files die die fontstrukuren interpretieren, also zu einem 
pixeldatenstrom machen, die bereiten mir noch etwas kopfzerbrechen 
schwerpunktmässig das entpacken alles andere geht wohl, ich habe ein 
byteorientiertes display und wollte die über einen schattenspeicher und 
eine write byte oder write pixelfunktion lösen, muss mich nur an der 
richtigen stelle einhängen - obwohl mich dein konzept bei der sache 
natürlich interessiert,

naja, zur not muss ich sie eben selber schreiben....

gruß, und vielen dank bis hier,
maddin

von Hagen R. (hagen)


Lesenswert?

melde dich hier als registrierter Benutzer an und schreibe mir dann eine 
PN. Diese landet als EMail bei mir und ich kann dir die S65 Lib mailen.

8Bits per Pixel = 2^8 = 256, ergo maximal 256 Farben in Font, 4 BPP = 
2^4 = 16 ergo maximal 16 Farben. Egal ob du nun 9,10,..15 oder 16 Farben 
benutzt es sind immer 4 BPP. Erst bei <= 8 Farben sind es dann 3 BPP 
usw. Ergo: BPP = Trunc(Ln2(Farbanzahl) + 0.5).

>schreibst du byteweise ins display?

ist im Grunde egal und hängt von der Farbtiefe des Displays ab. Bei 
einem 16BPP Display also 2 Bytes pro Farbpixel. Die Fontdaten sind davon 
im grunde unberührt speichern diese ja nur einen Indiex in eine 
Farbtabelle pro Pixelblock. Ein Pixelblock besteht immer aus Pixel mit 
gelicher Farbe. Pro Pixelblock wird ein RLE Code gespeichert. Dieser 
Besteht aus dem Index in die Farbtabelle a x BPP Bits und einen 
Mini-Huffman-kodiertem 2 Bit Index in die RLE Tabelle die dann die 
Anzahl der zu setzenden Pixel enthält. Diese RLE Tabelle mit gerademal 4 
Längenangaben wird durch die PC Software so berechnet das zum jeweiligen 
Font die beste Komprimierungsrate rauskommt.

Ein Fontzeichen wird Spaltenweise abgespeichert, also von Links nach 
Rechts jede Pixelspalte von oben nach unten. Exakt so werden dann auch 
die Zeichen gezeichnet. Ergo sollte das Display am besten einen 
Schreibmodus unterstützen bei dem der interne Addresscounter zur 
Pixeladdress automatisch in der Y-Achse +1 inkrementiert und beim 
Überlauf des Addresszeigers aus dem Windows mit X +1 weitermacht. Das 
Display sollte somit auch ein einstellbares Zeichenwindow unterstützen.
Das wäre dann der Idealfall bei dem man mit einem AVR und maximalem SPI 
Takt die Darstellung der Zeichen mit maximalen Troughput möglich ist, 
also die Dekodierung der Fontstreams im Hintergrund während der SPI 
Datenübertragung. Aber auch jedes andere grafikfähige Display ginge, 
dann halt mit erhöhtem Aufwand in der Softwareansteuerung.

>RLE ist ein beriff und die vorgehensweise ist klar,
>indikator, multiplikator usw... hat du das für diesen fall mal irgenwo
>beschrieben, oder hälst du dich an einen bestimmten standard?

RLE ist nur ein Begriff und hat mit einem "Standard" nichts zu tun. 
Alles bei dem man die Länge eines Datenblockes abspeichert und somit die 
Speicherung der egentlichen Datenbytes einspart (also nur einmal 
Datenbyte  + Längenbyte als Wiederholungszähler dieses Datenbytes) ist 
RLE.

Die RLE Kodierung in meinen Fonts ist eine Eiegenentwicklung speziell 
auf die Fontdaten und die Möglichkeiten die uns der AVR bietet, 
abgestimmt. Dabei ist es ein dynamisches RLE, dh. für jeden Font kann es 
eine eigene Interpretation der Längenkodierung geben, eben über die RLE 
Tabelle. Ein Chunk sieht also so aus das 2 Bits RLE Index in die 
Längentabelle des Fonts und danach BPP Bits als Index in die Farbtabelle 
kommen. Nun setzt der AVR topdown und leftright die entsprechende Anzahl 
an Pixel mit der Farbe aus der Farbtabelle. Im Grunde also ein sehr 
einfaches Format.

Gruß Hagen

von maddin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Hagen,

wie der Zusammenhang zwischen bitbreite und farbtiefe ist, war mir klar, 
was ich nicht wusste war, wie in deinem tool der 1)zusammenhang zwischen 
der farbtiefe des tools und der farbtiefe die letztendlich heraus kommt, 
ist. weiter 2) wo man die farbtiefe am tool einstellt. hat sich beides 
geklärt, ist ein supergeiles konzept!

zu 1, es gibt keinen (muss man selbst herstellen, über zb 
farbtabelle(hagen))
zu 2, ist abhängig wo im farbalken im tool die farbe liegt

PN kommt

wie die RLE funktioniert, muss ich mal sehen in wieweit mir dein code 
weiterhilft...

Ich habe meine tests von gestern mal mit angehängt, fehlt noch die 
funktion der RLE.

gruß,
m.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.