int conicTo(FT_Vector* control, FT_Vector* to, void* fp) { if (firstpass) { if (to->x < xMin) xMin = to->x; } else { double px, py; double ox = prevx; double oy = prevy; if (fp!=NULL) { if (startcontour) { fprintf((FILE*)fp, "%s,%s",clearZeros((ox-xMin)*factor).c_str(), clearZeros(oy*factor).c_str()); startcontour = false; } else { fprintf((FILE*)fp, ";%s,%s",clearZeros((ox-xMin)*factor).c_str(), clearZeros(oy*factor).c_str()); } for (double t = 0.0; t<=1.0; t+=1.0/nodes) { px = pow(1.0-t, 2)*prevx + 2*t*(1.0-t)*control->x + t*t*to->x; py = pow(1.0-t, 2)*prevy + 2*t*(1.0-t)*control->y + t*t*to->y; fprintf((FILE*)fp, ";%s,%s",clearZeros((double)(px-xMin)*factor).c_str(), clearZeros((double)py*factor).c_str()); ox = px; oy = py; } } prevx = to->x; prevy = to->y; if (to->y>yMax) { yMax = to->y; } } return 0; }
int moveTo(FT_Vector* to, void* fp) { if (firstpass) { if (to->x < xMin) xMin = to->x; } else { prevx = to->x; prevy = to->y; if (fp!=NULL) { if (startcontour) { startcontour = false; fprintf((FILE*)fp, "%s,%s",clearZeros((double)(to->x-xMin)*factor).c_str(), clearZeros((double)to->y*factor).c_str()); } else { fprintf((FILE*)fp, "\n%s,%s",clearZeros((double)(to->x-xMin)*factor).c_str(), clearZeros((double)to->y*factor).c_str()); } } } return 0; }
int cubicTo(FT_Vector* /*control1*/, FT_Vector* /*control2*/, FT_Vector* to, void* fp) { if (firstpass) { if (to->x < xMin) xMin = to->x; } else { if (fp!=NULL) { if (startcontour) { fprintf((FILE*)fp, "%s,%s",clearZeros((double)(to->x-xMin)*factor).c_str(), clearZeros((double)to->y*factor).c_str()); startcontour = false; } else { fprintf((FILE*)fp, ";%s,%s",clearZeros((double)(to->x-xMin)*factor).c_str(), clearZeros((double)to->y*factor).c_str()); } } prevx = to->x; prevy = to->y; if (to->y>yMax) { yMax = to->y; } } return 0; }
/** * Main. */ int main(int argc, char* argv[]) { FT_Error error; std::string fTtf; std::string fLff; // init: fpLff = NULL; nodes = 4; std::string name = "Unknown"; double letterSpacing = 3.0; double wordSpacing = 6.75; double lineSpacingFactor = 1.0; std::string author = "Unknown"; std::string license = "Unknown"; precision = 6; // handle arguments: if (argc<2) { std::cout << "Usage: ttf2cxf <options> <ttf file> <cxf file>\n"; std::cout << " ttf file: An existing True Type Font file\n"; std::cout << " lff file: The LFF font file to create\n"; std::cout << "options are:\n"; std::cout << " -n nodes Number of nodes for quadratic and cubic splines (int)\n"; std::cout << " -a author Author of the font. Preferably full name and e-mail address\n"; std::cout << " -l letter spacing Letter spacing (float)\n"; std::cout << " -w word spacing Word spacing (float)\n"; std::cout << " -f line spacing factor Default is 1.0 (float)\n"; std::cout << " -d precision Number of decimal digits (int)\n"; std::cout << " -L license license of the font.\n"; exit(1); } for (int i=1; i<argc; ++i) { if (!strcmp(argv[i], "-n")) { ++i; nodes = atoi(argv[i]); } else if (!strcmp(argv[i], "-a")) { ++i; author = argv[i]; } else if (!strcmp(argv[i], "-l")) { ++i; letterSpacing = atof(argv[i]); } else if (!strcmp(argv[i], "-w")) { ++i; wordSpacing = atof(argv[i]); } else if (!strcmp(argv[i], "-d")) { ++i; precision = atoi(argv[i]); } else if (!strcmp(argv[i], "-f")) { ++i; lineSpacingFactor = atof(argv[i]); } else if (!strcmp(argv[i], "-L")) { ++i; license = argv[i]; } } fTtf = argv[argc-2]; fLff = argv[argc-1]; std::cout << "TTF file: " << fTtf.c_str() << "\n"; std::cout << "LFF file: " << fLff.c_str() << "\n"; // init freetype error = FT_Init_FreeType(&library); if (error) { std::cerr << "Error: FT_Init_FreeType\n"; } // load ttf font error = FT_New_Face(library, fTtf.c_str(), 0, &face); if (error==FT_Err_Unknown_File_Format) { std::cerr << "FT_New_Face: Unknown format\n"; } else if (error) { std::cerr << "FT_New_Face: Unknown error\n"; } std::cout << "family: " << face->family_name << "\n"; name = face->family_name; std::cout << "height: " << face->height << "\n"; std::cout << "ascender: " << face->ascender << "\n"; std::cout << "descender: " << face->descender << "\n"; // find out height by tracing 'A' yMax = -1000; convertGlyph(65); factor = 1.0/(1.0/9.0*yMax); std::cout << "factor: " << factor << "\n"; // write font file: fpLff = fopen(fLff.c_str(), "wt"); if (fpLff==NULL) { std::cerr << "Cannot open file " << fLff.c_str() << " for writing.\n"; exit(2); } sprintf(numFormat,"%%.%if", precision); // write font header fprintf(fpLff, "# Format: LibreCAD Font 1\n"); fprintf(fpLff, "# Creator: ttf2lff\n"); fprintf(fpLff, "# Version: 1\n"); fprintf(fpLff, "# Name: %s\n", name.c_str()); fprintf(fpLff, "# LetterSpacing: %s\n", clearZeros(letterSpacing).c_str()); fprintf(fpLff, "# WordSpacing: %s\n", clearZeros(wordSpacing).c_str()); fprintf(fpLff, "# LineSpacingFactor: %s\n", clearZeros(lineSpacingFactor).c_str()); time_t rawtime; struct tm * timeinfo; char buffer [12]; time ( &rawtime ); timeinfo = localtime ( &rawtime ); strftime (buffer,80,"%Y-%m-%d",timeinfo); fprintf(fpLff, "# Created: %s\n", buffer); fprintf(fpLff, "# Last modified: %s\n", buffer); fprintf(fpLff, "# Author: %s\n", author.c_str()); fprintf(fpLff, "# License: %s\n", license.c_str()); fprintf(fpLff, "\n"); uint first; FT_Get_First_Char(face, &first); FT_ULong charcode; FT_UInt gindex; // iterate through glyphs charcode = FT_Get_First_Char( face, &gindex ); while (gindex != 0) { convertGlyph(charcode); charcode = FT_Get_Next_Char(face, charcode, &gindex); } return 0; }
/** * Implementation of the method used for RS_Export to communicate * with this filter. * * @param file Full path to the LFF file that will be written. */ bool RS_FilterLFF::fileExport(RS_Graphic& g, const QString& file, RS2::FormatType /*type*/) { RS_DEBUG->print("LFF Filter: exporting file '%s'...", file.toLatin1().data()); RS_DEBUG->print("RS_FilterLFF::fileExport: open"); QFile f(file); QTextStream ts(&f); ts.setCodec("UTF-8"); if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { RS_DEBUG->print("RS_FilterLFF::fileExport: open: OK"); RS_DEBUG->print("RS_FilterLFF::fileExport: header"); // header: ts << "# Format: LibreCAD Font 1\n"; ts << QString("# Creator: %1\n").arg(RS_SYSTEM->getAppName()); ts << QString("# Version: %1\n").arg(RS_SYSTEM->getAppVersion()); QString ns = g.getVariableString("Names", ""); if (!ns.isEmpty()) { QStringList names = ns.split(','); RS_DEBUG->print("002"); for (int i = 0; i < names.size(); ++i) { ts << QString("# Name: %1\n").arg(names.at(i)); } } QString es = g.getVariableString("Encoding", ""); ts << QString("# Encoding: UTF-8\n"); ts << QString("# LetterSpacing: %1\n").arg( g.getVariableDouble("LetterSpacing", 3.0)); ts << QString("# WordSpacing: %1\n").arg( g.getVariableDouble("WordSpacing", 6.75)); ts << QString("# LineSpacingFactor: %1\n").arg( g.getVariableDouble("LineSpacingFactor", 1.0)); QString dateline = QDate::currentDate().toString ("yyyy-MM-dd"); ts << QString("# Created: %1\n").arg( g.getVariableString("Created", dateline)); ts << QString("# Last modified: %1\n").arg(dateline); QString sa = g.getVariableString("Authors", ""); RS_DEBUG->print("authors: %s", sa.toLocal8Bit().data()); if (!sa.isEmpty()) { QStringList authors = sa.split(','); RS_DEBUG->print("count: %d", authors.count()); QString a; for (int i = 0; i < authors.size(); ++i) { ts << QString("# Author: %1\n").arg(authors.at(i)); } } es = g.getVariableString("License", ""); if (!es.isEmpty()) { ts << QString("# License: %1\n").arg(es); } else ts << "# License: unknown\n"; RS_DEBUG->print("RS_FilterLFF::fileExport: header: OK"); // iterate through blocks (=letters of font) for (uint i=0; i<g.countBlocks(); ++i) { RS_Block* blk = g.blockAt(i); RS_DEBUG->print("block: %d", i); if (blk!=NULL) { RS_DEBUG->print("002a: %s", (blk->getName().toLocal8Bit().data())); ts << QString("\n%1\n").arg(blk->getName()); // iterate through entities of this letter: for (RS_Entity* e=blk->firstEntity(RS2::ResolveNone); e!=NULL; e=blk->nextEntity(RS2::ResolveNone)) { if (!e->isUndone()) { // lines: if (e->rtti()==RS2::EntityLine) { RS_Line* l = (RS_Line*)e; ts << clearZeros(l->getStartpoint().x, 5) << ','; ts << clearZeros(l->getStartpoint().y, 5) << ';'; ts << clearZeros(l->getEndpoint().x, 5) << ','; ts << clearZeros(l->getEndpoint().y, 5) << '\n'; } // arcs: else if (e->rtti()==RS2::EntityArc) { RS_Arc* a = (RS_Arc*)e; ts << clearZeros(a->getStartpoint().x, 5) << ','; ts << clearZeros(a->getStartpoint().y, 5) << ';'; ts << clearZeros(a->getEndpoint().x, 5) << ','; ts << clearZeros(a->getEndpoint().y, 5) << ",A"; ts << clearZeros(a->getBulge(), 5) << '\n'; } else if (e->rtti()==RS2::EntityBlock) { RS_Block* b = (RS_Block*)e; QString uCode; uCode.setNum(b->getName().at(0).unicode(), 16); if (uCode.length()<4) { uCode = uCode.rightJustified(4, '0'); } ts << QString("C%1\n").arg(uCode); } else if (e->rtti()==RS2::EntityPolyline) { RS_Polyline* p = (RS_Polyline*)e; ts << clearZeros(p->getStartpoint().x, 5) << ','; ts << clearZeros(p->getStartpoint().y, 5); for (RS_Entity* e2=p->firstEntity(RS2::ResolveNone); e2!=NULL; e2=p->nextEntity(RS2::ResolveNone)) { if (e2->rtti()==RS2::EntityLine){ RS_Line* l = (RS_Line*)e2; ts << ';' << clearZeros(l->getEndpoint().x, 5) << ','; ts << clearZeros(l->getEndpoint().y, 5); } else if (e2->rtti()==RS2::EntityArc){ RS_Arc* a = (RS_Arc*)e2; ts << ';' << clearZeros(a->getEndpoint().x, 5) << ','; ts << clearZeros(a->getEndpoint().y, 5) <<",A"; ts << clearZeros(a->getBulge(), 5); } } ts<<'\n'; } // Ignore entities other than arcs / lines else {} } } } } f.close(); RS_DEBUG->print("LFF Filter: exporting file: OK"); return true; } else { RS_DEBUG->print("LFF Filter: exporting file failed"); } return false; }
/** * Main. */ int main(int argc, char* argv[]) { FT_Error error; std::string fTtf; std::string fLff; // init: fpLff = NULL; nodes = 4; std::string name = "Unknown"; double letterSpacing = 3.0; double wordSpacing = 6.75; double lineSpacingFactor = 1.0; std::string author = "Unknown"; std::string license = "Unknown"; precision = 6; int i; int ret; library = NULL; face = NULL; // handle arguments: if (argc < 3) { usage(1); /* NOTREACHED */ } for (i=1; i<argc; ++i) { if (!strcmp(argv[i], "-n")) { ++i; nodes = atoi(argv[i]); } else if (!strcmp(argv[i], "-a")) { ++i; author = argv[i]; } else if (!strcmp(argv[i], "-l")) { ++i; letterSpacing = atof(argv[i]); } else if (!strcmp(argv[i], "-w")) { ++i; wordSpacing = atof(argv[i]); } else if (!strcmp(argv[i], "-d")) { ++i; precision = atoi(argv[i]); } else if (!strcmp(argv[i], "-f")) { ++i; lineSpacingFactor = atof(argv[i]); } else if (!strcmp(argv[i], "-h")) { usage(0); /* NOTREACHED */ } else if (!strcmp(argv[i], "-L")) { ++i; license = argv[i]; } else { break; } } if((argc - i) != 2) { usage(1); /* NOTREACHED */ } fTtf = argv[i++]; fLff = argv[i]; std::cout << "TTF file: " << fTtf.c_str() << "\n"; std::cout << "LFF file: " << fLff.c_str() << "\n"; ret = 0; // init freetype error = FT_Init_FreeType(&library); if (error) { std::cerr << "FT_Init_FreeType: " << FT_StrError(error) << std::endl; ret = 1; } else { // load ttf font error = FT_New_Face(library, fTtf.c_str(), 0, &face); if (error) { std::cerr << "FT_New_Face: " << fTtf << ": " << FT_StrError(error) << std::endl; ret = 1; } else { std::cout << "Family: " << face->family_name << "\n"; std::cout << "Height: " << face->height << "\n"; std::cout << "Ascender: " << face->ascender << "\n"; std::cout << "Descender: " << face->descender << "\n"; name = face->family_name; // find out height by tracing 'A' yMax = -1000; convertGlyph(65); factor = 1.0/(1.0/9.0*yMax); std::cout << "Factor: " << factor << "\n"; // write font file: fpLff = fopen(fLff.c_str(), "wt"); if (fpLff==NULL) { std::cerr << "Can not open " << fLff.c_str() << ": " << strerror(errno) << std::endl; ret = 2; } else { snprintf(numFormat,8,"%%.%if", precision); // write font header fprintf(fpLff, "# Format: LibreCAD Font 1\n"); fprintf(fpLff, "# Creator: ttf2lff\n"); fprintf(fpLff, "# Version: 1\n"); fprintf(fpLff, "# Name: %s\n", name.c_str()); fprintf(fpLff, "# LetterSpacing: %s\n", clearZeros(letterSpacing).c_str()); fprintf(fpLff, "# WordSpacing: %s\n", clearZeros(wordSpacing).c_str()); fprintf(fpLff, "# LineSpacingFactor: %s\n", clearZeros(lineSpacingFactor).c_str()); time_t rawtime; struct tm * timeinfo; char buffer [12]; time ( &rawtime ); timeinfo = localtime ( &rawtime ); strftime (buffer,sizeof(buffer),"%Y-%m-%d",timeinfo); fprintf(fpLff, "# Created: %s\n", buffer); fprintf(fpLff, "# Last modified: %s\n", buffer); fprintf(fpLff, "# Author: %s\n", author.c_str()); fprintf(fpLff, "# License: %s\n", license.c_str()); fprintf(fpLff, "\n"); unsigned first; FT_Get_First_Char(face, &first); FT_ULong charcode; FT_UInt gindex; // iterate through glyphs charcode = FT_Get_First_Char( face, &gindex ); while (gindex != 0) { convertGlyph(charcode); charcode = FT_Get_Next_Char(face, charcode, &gindex); } } } } if (face) { FT_Done_Face(face); } if (library) { FT_Done_Library(library); } return ret; }