void JFont::writechar(String s,ImageType *j,int x,int y,float scale,ColourType c) { // Doesn't work under RH6 int i=fcs.find(&fcalled,s); int i=fcs.findlike(&JFontfsamename,FontChar(s)); if (i>0) { FontChar *fc=fcs.p2num(i); fc->writetojbmp(j,x,y,scale,c); } }
void writechar(String s,RGBmp *j,int x,int y,float scale,myRGB c) { // Doesn't work under RH6 int i=fcs.find(&fcalled,s); int i=fcs.findlike(&JFontfsamename,FontChar(s)); if (i>0) { FontChar *fc=fcs.p2num(i); fc->writetojbmp(j,x,y,scale,c); } }
void main(int argc,String *argv) { ArgParser a=ArgParser(argc,argv); String fname=a.argafter("-i","Font file (.jf)"); float fw=a.floatafter("-fw","Font width",0.1); // We parse from List<String> lines=parsefileintolines(fname); // into List<FontChar> fcs=List<FontChar>(); for(int i=1;i<=lines.len;i++) { String current=lines.num(i); // printf("Parsing line %s\n",current); StringParser s=StringParser(current); String character=s.getbefore(":"); // printf("Reading character %s ...",character); FontChar fc=FontChar(character); while (s.someleft()) { char whatisit=s.getchar(); printf("It is a %c\n",whatisit); switch (whatisit) { case 'L': printf("Found a line\n"); float xa=tofloat(s.getbefore(",")); float ya=tofloat(s.getbefore("_")); bool keepgoing=true; while (keepgoing) { float xb=tofloat(s.getbefore(",")); float yb=s.getfloat(); fc.bs.add(FLine(xa,ya,xb,yb,fw)); char c=s.getchar(); if (c==';') keepgoing=false; else if (c!='_') printf("Expected _"); } break; /* case 'C': String type=s.getanyof("TBLRNESW"); float x=tofloat(s.getbefore(",")); float y=tofloat(s.getbefore(",")); float r=tofloat(s.getbefore(";")); FArc fa=FArc(x,y,r); if (Seq(type,"T") { fa.aa=0; fa.ab=2*pi; } if (Seq(type,"T") { fa.aa=-pi/2.0; fa.ab=pi/2.0; } if (Seq(type,"B") { fa.aa=pi/2.0; fa.ab=2*pi-pi/2.0; } if (Seq(type,"L") { fa.aa=-pi; fa.ab=0; } if (Seq(type,"R") { fa.aa=0; fa.ab=pi; } if (Seq(type,"NW") { fa.aa=-pi/2.0; fa.ab=0; } if (Seq(type,"NE") { fa.aa=0; fa.ab=pi/2.0; } if (Seq(type,"SE") { fa.aa=pi/2.0; fa.ab=pi; } if (Seq(type,"SW") { fa.aa=-pi; fa.ab=-pi/2.0; } fc.bs.add(fa); break; case '+': String search=s.getbefore(";"); int find=0; for (int j=1;j<i && find==0;j++) { if (Seq(search,fcs.p2num(j)->name)) find=j; } if (find==0) printf("You haven't defined character %s before %s",find,character); fc.bs.add(fcs.p2num(j)->bs); break; default: printf("What kind of FontBit is a %s?",toString(whatisit)); break; */ } }; fcs.add(fc); printf(" has %i bits\n",fc.bs.len); } }
List<FontChar> parsefontchars(String fname,float fwgiven) { // We parse from List<String> lines=readlinesfromfile(fname); // into List<FontChar> fcs=List<FontChar>(); float fw=tofloat(lines.num(1)); if (fwgiven>0) fw=fwgiven; for(int i=2;i<=lines.len;i++) { String current=lines.num(i); StringParser s=StringParser(current); if (s.someleft() && !Seq("//",Sleft(current,2))) { String character=s.getbefore(":"); FontChar fc=FontChar(character); while (s.someleft()) { char whatisit=s.getachar(); if (whatisit=='L') { String type=s.getanyof("HVRL"); float xa=tofloat(s.getbefore(",")); float ya=tofloat(s.getbefore("_")); bool keepgoing=true; while (keepgoing) { float xb=tofloat(s.getbefore(",")); float yb=s.getfloat(); // printf("new line %f %f %f %f\n",xa,ya,xb,yb); fc.bs.add(new FLine(xa,-ya,xb,-yb,fw,type)); xa=xb; ya=yb; // printf("one line added\n"); // printf("From %s we pick off ",s.current); char c=s.getachar(); // printf("%c, to get %s\n",c,s.current); if (c==';') keepgoing=false; else if (c!='_') s.error(Sformat("Expected _, got %c",c)); }; } if (whatisit=='C') { String type=s.getanyof("TBLRNESWXOr"); bool anti=Sdoremove(type,"X"); bool rounded=Sdoremove(type,"r"); float x=tofloat(s.getbefore(",")); float y=tofloat(s.getbefore(",")); // String next=( Seq(type,"O") ? "," : ";" ); String next; if (Seq(type,"O")) next=","; else next=";"; float r=tofloat(s.getbefore(next)); // printf("Arc rad %f ",r); FArc *fa=new FArc(x,y,r,fw,rounded); if (Slen(type)==0) { fa->aa=0; fa->ab=2*pi; } if (Seq(type,"O")) { fa->aa=tofloat(s.getbefore(","))*2*pi/8.0; fa->ab=tofloat(s.getbefore(";"))*2*pi/8.0; } if (Seq(type,"T")) { fa->aa=-pi/2.0; fa->ab=pi/2.0; } if (Seq(type,"B")) { fa->aa=pi/2.0; fa->ab=2*pi-pi/2.0; } if (Seq(type,"L")) { fa->aa=-pi; fa->ab=0; } if (Seq(type,"R")) { fa->aa=0; fa->ab=pi; } if (Seq(type,"NW")) { fa->aa=-pi/2.0; fa->ab=0; } if (Seq(type,"NE")) { fa->aa=0; fa->ab=pi/2.0; } if (Seq(type,"SE")) { fa->aa=pi/2.0; fa->ab=pi; } if (Seq(type,"SW")) { fa->aa=-pi; fa->ab=-pi/2.0; } if (anti) swap(&fa->aa,&fa->ab); /*if (Seq(type,"XSE")) { fa->aa=-pi; fa->ab=pi/2.0; } if (Seq(type,"XNW")) { fa->aa=0; fa->ab=2*pi-pi/2.0; }*/ fc.bs.add(fa); } if (whatisit=='+') { String search=s.getbefore(";"); int find=0; for (int j=1;j<=fcs.len && find==0;j++) { if (Seq(search,fcs.p2num(j)->name)) find=j; } if (find==0) error("You haven't defined character %s before %s",search,character); fc.bs.add(fcs.p2num(find)->bs); // default: // printf("What kind of FontBit is a %s?",toString(whatisit)); } }; fcs.add(fc); // printf("%s (%i) ... ",fc.name,fc.bs.len); } } printf("Parsed %s\n",fname); lines.freedom(); return fcs; }
FontChar clone() const { auto ptr = std::make_unique<uint8_t[]>(this->datasize()); memcpy(ptr.get(), this->data.get(), this->datasize()); return FontChar(std::move(ptr), this->offset, this->baseline, this->width, this->height, this->incby); }
// Constructor // Params : // - file_path : path to the font definition file (*.fv1) //============================================================================== explicit Font(const char * file_path) { //============================================================================== int fd; int b; // we start at space, no glyph for chars below 32 int file_size; TODO("Temporary disabling font to avoid useless messages in watchdog"); // LOG(LOG_INFO, "Reading font file %s", file_path); // RAZ of font chars table // Does font definition file exist and is it accessible ? if (access(file_path, F_OK)) { LOG(LOG_ERR, "create: error font file [%s] does not exist\n", file_path); goto ErrorReadingFontFile; } // Retrieves system stats about the file struct stat st; if (stat(file_path, &st)) { LOG(LOG_ERR, "create: can't stat file [%s]\n", file_path); goto ErrorReadingFontFile; } // Is file empty ? if (st.st_size < 1) { LOG(LOG_ERR, "create: empty font file [%s]\n", file_path); goto ErrorReadingFontFile; } // Allocate a buffer to read the whole file into file_size = st.st_size; if (-1 == (fd = open(file_path, O_RDONLY))){ LOG(LOG_ERR, "create: can't open font file [%s] for reading\n", file_path); goto ErrorReadingFontFile; } { std::size_t size_to_read = file_size; std::size_t const stream_buf_sz = 8192; char stream_buf[stream_buf_sz]; // Read header // ----------- while ((b = read(fd, stream_buf, stream_buf_sz)) < 0) { if (b >= 0){ break; } if ((errno == EAGAIN)||(errno == EINTR)){ continue; } LOG(LOG_ERR,"create: error reading font file [%s] error: %s\n", file_path, strerror(errno)); goto ErrorReadingFontFile; } InStream stream(stream_buf, b); size_to_read -= b; if (size_to_read == 0){ close(fd); fd = -1; } // Extract font info from the buffer //---------------------------------- stream.in_skip_bytes(4); // >>> 4 bytes for FNT1 (dropped) stream.in_copy_bytes(this->name, 32); // >>> 32 bytes for Font Name this->size = stream.in_uint16_le(); // >>> 2 bytes for Font Size TODO("temporary disabled to avoid warning in watchdog, see other TODO above to reenable later"); // LOG(LOG_INFO, "font name <%s> size <%u>", this->name, this->size); this->style = stream.in_uint16_le(); // >>> 2 bytes for Font Style stream.in_skip_bytes(8); // >>> 8 bytes for PAD (dropped) // Extract each character glyph for (int index = 32; index < NUM_GLYPHS ; index++) { unsigned remaining = stream.in_remain(); if (remaining < 1024){ if (size_to_read > 0){ TODO("Create a pack_left function in stream to do this"); //----------------------------------------------------- memmove(stream_buf, stream.get_current(), remaining); //----------------------------------------------------- while ((b = read(fd, stream_buf + remaining, std::min(size_to_read, stream_buf_sz - remaining))) < 0){ if (b >= 0){ break; } if ((errno == EAGAIN)||(errno == EINTR)){ continue; } LOG(LOG_ERR,"create: error reading font file [%s] error: %s\n", file_path, strerror(errno)); goto ErrorReadingFontFile; } stream = InStream(stream_buf, remaining + b); size_to_read -= b; if (size_to_read == 0){ close(fd); fd = -1; } } // no more remaining glyphs in file if (!stream.in_check_rem(1)){ LOG(LOG_INFO, "Font file %s defines glyphs up to %d", file_path, index); break; } if (!stream.in_check_rem(16)){ LOG(LOG_WARNING, "Font file %s defines glyphs up to %d, file looks broken", file_path, index); break; } } // LOG(LOG_INFO, "Reading definition for glyph %u", index); int width = stream.in_sint16_le(); // >>> 2 bytes for glyph width int height = stream.in_sint16_le(); // >>> 2 bytes for glyph height TODO(" baseline is always -height (seen from the code of fontdump) looks strange. It means that baseline is probably not used in current code."); int baseline = stream.in_sint16_le(); // >>> 2 bytes for glyph baseline int offset = stream.in_sint16_le(); // >>> 2 bytes for glyph offset int incby = stream.in_sint16_le(); // >>> 2 bytes for glyph incby stream.in_skip_bytes(6); // >>> 6 bytes for PAD (dropped) this->font_items[index] = FontChar(offset, baseline, width, height, incby); // Check if glyph data size make sense unsigned datasize = this->font_items[index].datasize(); if (datasize > 512) { // shouldn't happen, implies broken font file LOG(LOG_WARNING, "Error loading font %s. Wrong size for glyph %d" "width %d height %d \n", file_path, index, this->font_items[index].width, this->font_items[index].height); // one glyph is broken but we continue with other glyphs continue; } // Read the data only if there is enough space left in buffer if (!stream.in_check_rem(datasize)) { LOG(LOG_ERR , "Error loading font %s: not enough data for definition of glyph %d (expected %u, got %zu)\n" , file_path, index, datasize, stream.in_remain() ); goto ErrorReadingFontFile; } // >>> <datasize> bytes for glyph data (bitmap) stream.in_copy_bytes(this->font_items[index].data.get(), datasize); } } return; ErrorReadingFontFile: LOG(LOG_ERR, "Error reading font definition file %s, exiting proxy", file_path); exit(-1); }