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.
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
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.
> 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 | }
|
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.
...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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.