mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik glcd fontcreator aktuell


Autor: maddin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hagen Re (hagen)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: maddin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht 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
void glcdSelectFont(const void* data) {

    glcdFontData_t d = (glcdFontData_t)data;
    if (glcd.FontData == d) return;
    glcd.FontData = d;
    if (!(d)) return;
    d += 2;
    glcd.FontWidth = pgm_read_byte_inc(d);
    glcd.FontHeight = pgm_read_byte_inc(d);
    glcd.FontBitsPixel = pgm_read_byte_inc(d);
    glcd.FontFirstChar = pgm_read_byte_inc(d);
    glcd.FontLastChar = pgm_read_byte_inc(d);
    if (glcd.FontBitsPixel & 0x80) { // compressed font
      d = glcd.FontData + (GLCD_FONT_HEADER_SIZE + 1) + (glcd.FontLastChar - glcd.FontFirstChar);
      glcd.FontBitsHeight = pgm_read_byte_inc(d);
      glcd.FontRLE[0] = 1;
      glcd.FontRLE[1] = pgm_read_byte_inc(d);
      glcd.FontRLE[2] = pgm_read_byte_inc(d);
      glcd.FontRLE[3] = pgm_read_byte_inc(d);
    } else {
      glcd.FontBitsHeight = glcd.FontHeight * glcd.FontBitsPixel;
    }

}

void glcdDrawText(const char* text, uint16_t size, uint8_t flashstored) {

    if ((text == 0) || (glcd.FontData == 0)) return;

    uint8_t flags = (flashstored ? 0x70 : 0x30) | (glcd.FontBitsPixel & 0x80) | (glcd.Flags.All & 0x07);
    uint8_t bitspixel = glcd.FontBitsPixel & 0x7F;
    uint8_t bitsmask = 0xFF >> (8 - bitspixel);
    uint8_t FontHeight = glcd.FontHeight, FontWidth = glcd.FontWidth, FontCharSpace = glcd.FontCharSpace;
    uint8_t FontFirstChar = glcd.FontFirstChar, FontLastChar = glcd.FontLastChar;
    uint8_t charofs = FontLastChar - FontFirstChar +5;
    glcdCoord_t Cursorx = glcd.Cursor.x, Cursory = glcd.Cursor.y;
    glcdCoord_t Windowx2 = glcd.Window.x2 +1, Windowy2 = glcd.Window.y2 +1, Windowx1 = glcd.Window.x1, Windowy1 = glcd.Window.y1;
    glcdFontData_t data, FontData = glcd.FontData + GLCD_FONT_HEADER_SIZE;
    uint16_t FontBitsHeight = glcd.FontBitsHeight;
    uint16_t* colors = &glcd.Colors[0];
    uint8_t* rle = &glcd.FontRLE[0];

    glcdColor_t color = 0;
    uint8_t c, i, width, charwidth, bitsmul, pixelcount, bitscount, leftspace, rightspace;
    uint32_t index;
    uint16_t bits;

    for (; size > 0; size--) {

      if (flags & 0x40) c = pgm_read_byte_inc(text);
        else c = *text++;

      if (!(c)) break;

      if (c == '\n') {
        Cursorx  = Windowx1;
        Cursory += FontHeight;
        if (Cursory + FontHeight > Windowy2) Cursory = Windowy1;
        flags |= 0x10;  // invalidate LCD address pointer
        continue;
      }

      if ((c < FontFirstChar) || (c > FontLastChar)) continue;

      data = FontData + c - FontFirstChar;
      charwidth = pgm_read_byte(data);
      if (!(charwidth)) continue;

      width = charwidth;
      if ((flags & 0x04) && (c < 128)) width++;
      if ((flags & 0x01) && (width < FontWidth)) width = FontWidth;  // FixedFont ??
      width += FontCharSpace;

      if (Cursorx + width > Windowx2) {  // LineFeed ??
        if (flags & 0x02) {
          Cursorx  = Windowx1;
          Cursory += FontHeight;
          if (Cursory + FontHeight > Windowy2) Cursory = Windowy1;
          flags |= 0x10;  // invalidate LCD address pointer
        } else break;
      }

      index = 0;
      data = FontData;
      if (flags & 0x80) data += charofs;
      for (i = c - FontFirstChar; i > 0; i--)
        index += pgm_read_byte_inc(data);

      index *= FontBitsHeight;
      data = FontData + charofs -4;
      if (flags & 0x80) {
        data += charofs;
        data += index;
        bits = 0;
        bitscount = 0;
      } else {
        bitscount = index & 0x07;
        index >>= 3;
        data += index;
        bits = pgm_read_byte_inc(data) >> bitscount;
        bitscount = 8 - bitscount;
      }

      leftspace = 0;
      rightspace = width - charwidth;
      if (flags & 0x01) { // FixedFont ??
        leftspace = rightspace / 2;
        rightspace -= leftspace;
        if ((leftspace > 0) && (colors[0] == NONE)) {
          flags |= 0x10;
          Cursorx += leftspace;
          width -= leftspace;
          leftspace = 0;
        }
      }

      if (flags & 0x20) { // initialize LCD ??
        flags ^= 0x20;
        GLCD_CS_ON();
      #ifdef GLCD_ROTATE
        GLCD_SETMODE(0x30 | GLCD_ROP_WNE);
      #else
        GLCD_SETMODE(0x38 | GLCD_ROP_WNE);
      #endif
        GLCD_SETCOMPARE(NONE);
      }
      
      if (flags & 0x10) { // LCD address pointer invalid ??
        flags ^= 0x10;
        GLCD_WAIT();
        GLCD_CS_PULSE();
        GLCD_WINDOW(Cursorx, Cursory, GLCD_RIGHT, Cursory + FontHeight -1);
        GLCD_SETADDR(Cursorx, Cursory);
        GLCD_STARTDATA();
      }
      Cursorx += width;

      if (leftspace > 0) {
        color = colors[0];
        do {
          i = FontHeight;
          do {
            GLCD_WAIT();
            GLCD_OUT(H8(color));
            GLCD_WAIT();
            GLCD_OUT(L8(color));
          } while (--i);
        } while (--leftspace);
      }

      bitsmul = pgm_read_byte(&powerof2[bitscount & 0x07]);
      if (bitscount < 8) {
        bitscount += 8;
        bits |= pgm_read_byte_inc(data) * bitsmul;    // faster as shifting
      }
      pixelcount = 1;
      do {
        i = FontHeight;
        do {
          if (!(--pixelcount)) {
            pixelcount++;
            if (flags & 0x80) { // compresed Font ??
              pixelcount = rle[bits & 0x03];
              bits >>= 2;
              bitscount -= 2;
            }
            bitscount -= bitspixel;
            bitsmul = pgm_read_byte(&powerof2[bitscount & 0x07]);
            color = colors[bits & bitsmask];
            bits >>= bitspixel;
          }
          GLCD_WAIT();
          GLCD_OUT(H8(color));
          if (bitscount < 8) { // read in advance while we wait for SPI
            bitscount += 8;
            bits |= pgm_read_byte_inc(data) * bitsmul;   // faster as shifting
          }
          GLCD_WAIT();
          GLCD_OUT(L8(color));
        } while (--i);
      } while (--charwidth);

      if (rightspace > 0) {
        color = colors[0];
        if (color == NONE) {
          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
        } else {
          do {
            i = FontHeight;
            do {
              GLCD_WAIT();
              GLCD_OUT(H8(color));
              GLCD_WAIT();
              GLCD_OUT(L8(color));
            } while (--i);
          } while (--rightspace);
        }
      }
    }
    if (!(flags & 0x20)) { // have LCD initialized, anything done ??
      GLCD_WAIT();
      GLCD_CS_PULSE();
      GLCD_RESETWINDOW();
      GLCD_SETMODE(0x30);
      GLCD_CS_OFF();
    }
    glcd.Cursor.x = Cursorx;
    glcd.Cursor.y = Cursory;
}

void glcdDrawChar(char value) {

    glcd.Buf[0] = value;
    glcdDrawText(glcd.Buf, 1, 0);
}

Autor: maddin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: maddin (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: maddin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.