TtfFont::TheGlyph &TtfFont::getGlyph(uint32_t fontSize, char32_t character) { SizeCharMap::iterator fSize = m_charMap.find(fontSize); if(fSize != m_charMap.end()) { CharMap::iterator rc = fSize->second.find(character); if(rc != fSize->second.end()) return rc->second; return loadGlyph(fontSize, character); } return loadGlyph(fontSize, character); }
void QFontEngineQPF::ensureGlyphsLoaded(const QGlyphLayout *glyphs, int len) { if (readOnly) return; bool locked = false; for (int i = 0; i < len; ++i) { if (!glyphs[i].glyph) continue; const Glyph *g = findGlyph(glyphs[i].glyph); if (g) continue; if (!locked) { if (!lockFile()) return; locked = true; g = findGlyph(glyphs[i].glyph); if (g) continue; } loadGlyph(glyphs[i].glyph); } if (locked) { unlockFile(); #if defined(DEBUG_FONTENGINE) qDebug() << "Finished rendering glyphs\n"; #endif } }
void Font::loadFont( const char* xmlFile ) { XMLParser parser( xmlFile ); XMLDocument& doc = parser.getDocument(); if( !doc.Error() ) { XMLNode* root = doc.FirstChildElement( "FontDefinition" ); XMLNode* fontInfo = root->FirstChildElement( "FontInfo" ); m_fontName = parser.getXMLAttributeAsString( fontInfo, "name", "" ); m_fontLocale = parser.getXMLAttributeAsString( fontInfo, "local", "en" ); m_pixelHeight = parser.getXMLAttributeAsInt( fontInfo, "cellPixelHeight", 1 ); XMLNode* element; for( element = root->FirstChildElement( "Glyph" ); element != 0; element = element->NextSiblingElement( "Glyph" ) ) { Glyph g = loadGlyph( parser, element ); m_glyphs.insert( std::pair< unsigned char, Glyph >( g.ucsIndex, g ) ); } } else { MonkyException::simpleErrorMessageBox( "Failed to load font", "File could not be opened" ); } }
bool CPetRemote::loadGlyphs(const Common::Array<uint> &indexes) { for (uint idx = 0; idx < indexes.size(); ++idx) { if (!loadGlyph(indexes[idx])) return false; } return true; }
Glyph::Glyph(Parameter parameter, const LibraryParameter &library) : slot(loadGlyph(parameter.character, library.face)), size(slot->bitmap.width, slot->bitmap.rows), bearing(slot->bitmap_left, slot->bitmap_top), advance(slot->advance.x, slot->advance.y), texture(Image(size, slot->bitmap.buffer, Texture::InternalFormat::Red, Texture::Format::Red)) { }
qreal ScFace::ScFaceData::glyphWidth(gid_type gl, qreal size) const { if (gl >= CONTROL_GLYPHS) return 0.0; else if (! m_glyphWidth.contains(gl)) { loadGlyph(gl); } return m_glyphWidth[gl] * size; }
void setUpFreetype( unsigned int characterIndex) { FT_Error error = FT_Init_FreeType( &library); assert(!error); error = FT_New_Face( library, ARIAL_FONT_FILE, 0, &face); assert(!error); loadGlyph( characterIndex); }
//----------------------------------------------------------- ofTexture ofTrueTypeFont::getStringTexture(const std::string& str, bool vflip) const{ string str_valid; utf8::replace_invalid(str.begin(),str.end(),back_inserter(str_valid)); vector<glyph> glyphs; vector<ofVec2f> glyphPositions; utf8::iterator<const char*> it(&str_valid.front(), &str_valid.front(), (&str_valid.back())+1); utf8::iterator<const char*> end((&str_valid.back())+1, &str_valid.front(), (&str_valid.back())+1); int x = 0; int y = 0; long height = 0; uint32_t prevC = 0; while(it != end){ try{ auto c = *it; if (c == '\n') { y += lineHeight; x = 0 ; //reset X Pos back to zero prevC = 0; } else { glyphs.push_back(loadGlyph(c)); if(prevC>0){ x += getKerning(c,prevC); }else if(settings.direction == ofTtfSettings::RightToLeft){ x += glyphs.back().props.width; } glyphPositions.emplace_back(static_cast<float>(x), static_cast<float>(y)); x += glyphs.back().props.advance * letterSpacing; height = max(height, glyphs.back().props.ymax + y + long(getLineHeight())); } ++it; prevC = c; }catch(...){ break; } } ofTexture tex; ofPixels totalPixels; totalPixels.allocate(x, height, OF_PIXELS_GRAY_ALPHA); //-------------------------------- clear data: totalPixels.set(0,255); // every luminance pixel = 255 totalPixels.set(1,0); size_t i = 0; for(auto & g: glyphs){ if(settings.direction == ofTtfSettings::LeftToRight){ g.pixels.blendInto(totalPixels, glyphPositions[i].x, glyphPositions[i].y + getLineHeight() + g.props.ymin + getDescenderHeight() ); }else{ g.pixels.blendInto(totalPixels, x-glyphPositions[i].x, glyphPositions[i].y + getLineHeight() + g.props.ymin + getDescenderHeight() ); } i++; if(i==glyphPositions.size()){ break; } } tex.allocate(totalPixels); return tex; }
Glyph Font::getGlyph(const char c){ std::map<char, Glyph>::iterator it = glyphs.find(c); if(it != glyphs.end()){ return it->second; } else{ Glyph g = loadGlyph(c); return (glyphs[c] = g); } }
FPoint ScFace::ScFaceData::glyphOrigin(gid_type gl, qreal sz) const { if (gl == 0 || gl >= CONTROL_GLYPHS) return FPoint(0,0); else if (! m_glyphWidth.contains(gl)) { loadGlyph(gl); } const struct GlyphData & res(m_glyphOutline[gl]); return FPoint(res.x, res.y) * sz; }
FPointArray ScFace::ScFaceData::glyphOutline(gid_type gl, qreal sz) const { if (gl >= CONTROL_GLYPHS) return FPointArray(); else if (! m_glyphWidth.contains(gl)) { loadGlyph(gl); } FPointArray res = m_glyphOutline[gl].Outlines.copy(); if (sz != 1.0) res.scale(sz, sz); return res; }
void loadText() { fontInit(20,0); width = 1024,height = 1024; int x = 0,y = 0,maxy = 0; unsigned char *lol = new unsigned char[width * height]; memset(lol,0,width * height); for (int i = 32;i< 128;i++) { loadGlyph(i); int w = glyphs[i -32]->bitmap.width; int h = glyphs[i -32]->bitmap.rows; maxy = maxy > h ? maxy : h; if ((x + w) > width) y+= maxy + 3,x = 0,maxy = 0; glyphsPos[i -32].x = x; glyphsPos[i -32].y = y; for (int l = 0;l<h;l++) memcpy(lol + (l +y)*width + x,glyphs[i -32]->bitmap.buffer + l * w,w); x+=w + 3; } glActiveTexture(GL_TEXTURE1); GLuint texttext;; glGenTextures(1,&texttext); glBindTexture(GL_TEXTURE_2D,texttext); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); glTexImage2D(GL_TEXTURE_2D,0,GL_ALPHA,width,height,0,GL_ALPHA,GL_UNSIGNED_BYTE,lol ); glUniform1i(TextUniform,1); }
//----------------------------------------------------------- ofTexture ofTrueTypeFont::getStringTexture(const std::string& str, bool vflip) const { vector<glyph> glyphs; vector<ofVec2f> glyphPositions; long height = 0; int width = 0; int lineWidth = 0; uint32_t prevC = 0; iterateString(str, 0, 0, vflip, [&](uint32_t c, ofVec2f pos) { try { if (c != '\n') { auto g = loadGlyph(c); glyphs.push_back(g); int x = pos.x + g.props.xmin; int y = g.props.ymax + pos.y; glyphPositions.emplace_back(x, y); lineWidth += glyphs.back().props.advance * letterSpacing; width = max(width, lineWidth); height = max(height, y + long(getLineHeight())); } else { lineWidth = 0; } } catch(...) { } }); ofTexture tex; ofPixels totalPixels; totalPixels.allocate(width, height, OF_PIXELS_GRAY_ALPHA); //-------------------------------- clear data: totalPixels.set(0,255); // every luminance pixel = 255 totalPixels.set(1,0); size_t i = 0; for(auto & g: glyphs) { if(settings.direction == ofTtfSettings::LeftToRight) { g.pixels.blendInto(totalPixels, glyphPositions[i].x, glyphPositions[i].y + getLineHeight() + g.props.ymin + getDescenderHeight() ); } else { g.pixels.blendInto(totalPixels, width-glyphPositions[i].x, glyphPositions[i].y + getLineHeight() + g.props.ymin + getDescenderHeight() ); } i++; if(i==glyphPositions.size()) { break; } } tex.allocate(totalPixels); return tex; }
GlyphMetrics ScFace::ScFaceData::glyphBBox(gid_type gl, qreal sz) const { GlyphMetrics res; if (gl == 0 || gl >= CONTROL_GLYPHS) { res.width = glyphWidth(gl, sz); res.ascent = (gl == 0? ascent(sz) : 0); res.descent = 0; return res; } else if (! m_glyphWidth.contains(gl)) { loadGlyph(gl); } const struct GlyphData & data(m_glyphOutline[gl]); res.width = data.bbox_width * sz; res.ascent = data.bbox_ascent * sz; res.descent = data.bbox_descent * sz; return res; }
//----------------------------------------------------------- ofVec2f ofTrueTypeFont::getFirstGlyphPosForTexture(const std::string & str, bool vflip) const { if(!str.empty()) { try { auto c = *ofUTF8Iterator(str).begin(); if (c == '\n') { return {0.f, 0.f}; } else { auto g = loadGlyph(c); if(settings.direction == ofTtfSettings::LeftToRight) { return {-float(g.props.xmin), getLineHeight() + g.props.ymin + getDescenderHeight()}; } else { return {-float(g.props.xmin), getLineHeight() + g.props.ymin + getDescenderHeight()}; } } } catch(...) { return {0.f, 0.f}; } } }
FPointArray ScFace::ScFaceData::glyphOutline(uint gl, qreal sz) const { if (gl >= CONTROL_GLYPHS) return FPointArray(); else if (gl == 0) { sz *= 10; FPointArray sq; sq.addQuadPoint(0,0,0,0,sz,0,sz,0); sq.addQuadPoint(sz,0,sz,0,sz,sz,sz,sz); sq.addQuadPoint(sz,sz,sz,sz,0,sz,0,sz); sq.addQuadPoint(0,sz,0,sz,0,0,0,0); return sq; } else if (! m_glyphWidth.contains(gl)) { loadGlyph(gl); } FPointArray res = m_glyphOutline[gl].Outlines.copy(); if (sz != 1.0) res.scale(sz, sz); return res; }
int FTPixmapFont::getWidth( const char* text ) { if( text == 0 ) return 0; int w= 0; for(;;) { int ch= (unsigned char) *(text++); if( ch == 0 ) break; loadGlyph(ch); if( pixmaps[ch] == 0 ) continue; w+= pixmaps[ch]->getAdvance(); } return w / 64; }
const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold) const { // Get the page corresponding to the character size GlyphTable& glyphs = m_pages[characterSize].glyphs; // Build the key by combining the code point and the bold flag Uint32 key = ((bold ? 1 : 0) << 31) | codePoint; // Search the glyph into the cache GlyphTable::const_iterator it = glyphs.find(key); if (it != glyphs.end()) { // Found: just return it return it->second; } else { // Not found: we have to load it Glyph glyph = loadGlyph(codePoint, characterSize, bold); return glyphs.insert(std::make_pair(key, glyph)).first->second; } }
const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, float outlineThickness) const { // Get the page corresponding to the character size GlyphTable& glyphs = m_pages[characterSize].glyphs; // Build the key by combining the glyph index (based on code point), bold flag, and outline thickness Uint64 key = combine(outlineThickness, bold, FT_Get_Char_Index(static_cast<FT_Face>(m_face), codePoint)); // Search the glyph into the cache GlyphTable::const_iterator it = glyphs.find(key); if (it != glyphs.end()) { // Found: just return it return it->second; } else { // Not found: we have to load it Glyph glyph = loadGlyph(codePoint, characterSize, bold, outlineThickness); return glyphs.emplace(key, glyph).first->second; } }
const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, float outlineThickness) const { // Get the page corresponding to the character size GlyphTable& glyphs = m_pages[characterSize].glyphs; // Build the key by combining the code point, bold flag, and outline thickness Uint64 key = (static_cast<Uint64>(*reinterpret_cast<Uint32*>(&outlineThickness)) << 32) | (static_cast<Uint64>(bold ? 1 : 0) << 31) | static_cast<Uint64>(codePoint); // Search the glyph into the cache GlyphTable::const_iterator it = glyphs.find(key); if (it != glyphs.end()) { // Found: just return it return it->second; } else { // Not found: we have to load it Glyph glyph = loadGlyph(codePoint, characterSize, bold, outlineThickness); return glyphs.insert(std::make_pair(key, glyph)).first->second; } }
static void msdfgen_hello_world() { msdfgen::FreetypeHandle* ft = msdfgen::initializeFreetype(); if ( ft ) { msdfgen::FontHandle* font = loadFont( ft, "OpenSans.ttf" ); if ( font ) { msdfgen::Shape shape; if ( loadGlyph( shape, font, 'A' )) { shape.normalize(); // max. angle edgeColoringSimple( shape, 3.0 ); // image width, height msdfgen::Bitmap<msdfgen::FloatRGB> msdf( 32, 32 ); // range, scale, translation generateMSDF( msdf, shape, 4.0, 1.0, msdfgen::Vector2( 4.0, 4.0 )); } destroyFont( font ); } deinitializeFreetype( ft ); } }
void Font::loadGlyph(const UTF8String & str) { UCodePoint codePoint; for ( auto it = str.getBegin(); str.iterate(&it, &codePoint);) { loadGlyph(codePoint); } }
bool ofTrueTypeFont::load(const ofTtfSettings & _settings){ #if defined(TARGET_ANDROID) ofAddListener(ofxAndroidEvents().unloadGL,this,&ofTrueTypeFont::unloadTextures); ofAddListener(ofxAndroidEvents().reloadGL,this,&ofTrueTypeFont::reloadTextures); #endif initLibraries(); settings = _settings; if( settings.dpi == 0 ){ settings.dpi = ttfGlobalDpi; } bLoadedOk = false; //--------------- load the library and typeface FT_Face loadFace; if(!loadFontFace(settings.fontName,settings.fontSize,loadFace,settings.fontName)){ return false; } face = std::shared_ptr<struct FT_FaceRec_>(loadFace,FT_Done_Face); if(settings.ranges.empty()){ settings.ranges.push_back(ofUnicode::Latin1Supplement); } int border = 1; FT_Set_Char_Size( face.get(), settings.fontSize << 6, settings.fontSize << 6, settings.dpi, settings.dpi); fontUnitScale = (float(settings.fontSize * settings.dpi)) / (72 * face->units_per_EM); lineHeight = face->height * fontUnitScale; ascenderHeight = face->ascender * fontUnitScale; descenderHeight = face->descender * fontUnitScale; glyphBBox.set(face->bbox.xMin * fontUnitScale, face->bbox.yMin * fontUnitScale, (face->bbox.xMax - face->bbox.xMin) * fontUnitScale, (face->bbox.yMax - face->bbox.yMin) * fontUnitScale); //--------------- initialize character info and textures auto nGlyphs = std::accumulate(settings.ranges.begin(), settings.ranges.end(), 0u, [](uint32_t acc, ofUnicode::range range){ return acc + range.getNumGlyphs(); }); cps.resize(nGlyphs); if(settings.contours){ charOutlines.resize(nGlyphs); charOutlinesNonVFlipped.resize(nGlyphs); charOutlinesContour.resize(nGlyphs); charOutlinesNonVFlippedContour.resize(nGlyphs); }else{ charOutlines.resize(1); } vector<ofTrueTypeFont::glyph> all_glyphs; uint32_t areaSum=0; //--------------------- load each char ----------------------- auto i = 0u; for(auto & range: settings.ranges){ for (uint32_t g = range.begin; g <= range.end; g++, i++){ all_glyphs.push_back(loadGlyph(g)); all_glyphs[i].props.characterIndex = i; glyphIndexMap[g] = i; cps[i] = all_glyphs[i].props; areaSum += (cps[i].tW+border*2)*(cps[i].tH+border*2); if(settings.contours){ if(printVectorInfo){ std::string str; ofAppendUTF8(str,g); ofLogNotice("ofTrueTypeFont") << "character " << str; } //int character = i + NUM_CHARACTER_TO_START; charOutlines[i] = makeContoursForCharacter( face.get() ); charOutlinesContour[i] = charOutlines[i]; charOutlinesContour[i].setFilled(false); charOutlinesContour[i].setStrokeWidth(1); charOutlinesNonVFlipped[i] = charOutlines[i]; charOutlinesNonVFlipped[i].translate(ofVec3f(0,cps[i].height)); charOutlinesNonVFlipped[i].scale(1,-1); charOutlinesNonVFlippedContour[i] = charOutlines[i]; charOutlinesNonVFlippedContour[i].setFilled(false); charOutlinesNonVFlippedContour[i].setStrokeWidth(1); if(settings.simplifyAmt>0){ charOutlines[i].simplify(settings.simplifyAmt); charOutlinesNonVFlipped[i].simplify(settings.simplifyAmt); charOutlinesContour[i].simplify(settings.simplifyAmt); charOutlinesNonVFlippedContour[i].simplify(settings.simplifyAmt); } } } } vector<ofTrueTypeFont::glyphProps> sortedCopy = cps; sort(sortedCopy.begin(),sortedCopy.end(),[](const ofTrueTypeFont::glyphProps & c1, const ofTrueTypeFont::glyphProps & c2){ if(c1.tH == c2.tH) return c1.tW > c2.tW; else return c1.tH > c2.tH; }); // pack in a texture, algorithm to calculate min w/h from // http://upcommons.upc.edu/pfc/bitstream/2099.1/7720/1/TesiMasterJonas.pdf //ofLogNotice("ofTrueTypeFont") << "loadFont(): areaSum: " << areaSum bool packed = false; float alpha = logf(areaSum)*1.44269f; int w; int h; while(!packed){ w = pow(2,floor((alpha/2.f) + 0.5f)); // there doesn't seem to be a round in cmath for windows. //w = pow(2,round(alpha/2.f)); h = w;//pow(2,round(alpha - round(alpha/2.f))); int x=0; int y=0; auto maxRowHeight = sortedCopy[0].tH + border*2; packed = true; for(auto & glyph: sortedCopy){ if(x+glyph.tW + border*2>w){ x = 0; y += maxRowHeight; maxRowHeight = glyph.tH + border*2; if(y + maxRowHeight > h){ alpha++; packed = false; break; } } x+= glyph.tW + border*2; } } ofPixels atlasPixelsLuminanceAlpha; atlasPixelsLuminanceAlpha.allocate(w,h,OF_PIXELS_GRAY_ALPHA); atlasPixelsLuminanceAlpha.set(0,255); atlasPixelsLuminanceAlpha.set(1,0); int x=0; int y=0; auto maxRowHeight = sortedCopy[0].tH + border*2; for(auto & glyph: sortedCopy){ ofPixels & charPixels = all_glyphs[glyph.characterIndex].pixels; if(x+glyph.tW + border*2>w){ x = 0; y += maxRowHeight; maxRowHeight = glyph.tH + border*2; } cps[glyph.characterIndex].t1 = float(x + border)/float(w); cps[glyph.characterIndex].v1 = float(y + border)/float(h); cps[glyph.characterIndex].t2 = float(cps[glyph.characterIndex].tW + x + border)/float(w); cps[glyph.characterIndex].v2 = float(cps[glyph.characterIndex].tH + y + border)/float(h); charPixels.pasteInto(atlasPixelsLuminanceAlpha,x+border,y+border); x+= glyph.tW + border*2; } texAtlas.allocate(atlasPixelsLuminanceAlpha,false); texAtlas.setRGToRGBASwizzles(true); if(settings.antialiased && settings.fontSize>20){ texAtlas.setTextureMinMagFilter(GL_LINEAR,GL_LINEAR); }else{ texAtlas.setTextureMinMagFilter(GL_NEAREST,GL_NEAREST); } texAtlas.loadData(atlasPixelsLuminanceAlpha); bLoadedOk = true; return true; }
void FTPixmapFont::load( int from /* = 0 */, int to /* = 255 */ ) { for( int i= from; i <= to; ++i ) loadGlyph(i); }
/** \fn DIA_ocrGen \brief Dialog to select input & output files before calling the actual ocr engine */ uint8_t DIA_ocrGen(void) { vobSubParam subparam={NULL,0,0}; char *srtFileName=NULL; char *glyphFileName=NULL; admGlyph head(16,16); char *globalGlyph=NULL; uint32_t globalGlyphOn=0; ADM_OCR_SOURCE source; memset(&source,0,sizeof(source)); source.type=ADM_OCR_TYPE_VOBSUB; source.subparam=&subparam; prefs->get(FEATURE_GLOBAL_GLYPH_ACTIVE,&globalGlyphOn); if(globalGlyphOn) { prefs->get(FEATURE_GLOBAL_GLYPH_NAME,&globalGlyph); if(!*globalGlyph) { ADM_dezalloc(globalGlyph); globalGlyph=NULL; } } if(globalGlyph) { glyphFileName=globalGlyph; } _again: // Fist build a dialogFactory to get input and output files diaElemButton selectIdx(QT_TR_NOOP("Select idx file:"), cb_idx,&subparam,NULL); diaElemFile selectGlyph(1,&glyphFileName,QT_TR_NOOP("Use GlyphSet (optional):"), NULL, QT_TR_NOOP("Select GlyphSet file")); diaElemFile selectSrt(1,&srtFileName,QT_TR_NOOP("Output SRT file"), NULL, QT_TR_NOOP("Save SRT file")); diaElem *elems[]={&selectIdx,&selectSrt,&selectGlyph}; uint32_t n=3; if(globalGlyph) { n--; // Remove glyph from dialog } if(!diaFactoryRun(QT_TR_NOOP("Select input and ouput files"),n,elems)) { cleanupSub(&source); if(srtFileName )ADM_dezalloc(srtFileName); srtFileName=NULL; destroyGlyphTree(&head); return 0; } if(!ADM_fileExist(subparam.subname)) { GUI_Error_HIG(QT_TR_NOOP("File error"),QT_TR_NOOP("The idx/sub file does not exist.")); goto _again; } if(!srtFileName || !*srtFileName) { GUI_Error_HIG(QT_TR_NOOP("File error"),QT_TR_NOOP("Please Select a valid output SRT file.")); goto _again; } if(glyphFileName && *glyphFileName) { if(!ADM_fileExist(glyphFileName)) { GUI_Error_HIG(QT_TR_NOOP("File error"),QT_TR_NOOP("The idx/sub file does not exist.")); goto _again; } // Purge previous glyph set if any destroyGlyphTree(&head); uint32_t nb; printf("[OCR] Loading glyphset :<%s>\n",glyphFileName); if(!loadGlyph(glyphFileName,&head,&nb)) { GUI_Error_HIG(QT_TR_NOOP("File error"),QT_TR_NOOP("Cannot load the glyphset file.")); goto _again; } printf("[GLYPH] Found %u glyph\n"); } // We have our SRT and our idx/sub files : Go go go if(ADM_ocr_engine(source,srtFileName,&head)) { // Save glyph set if(globalGlyph) { uint32_t nb=1; saveGlyph(globalGlyph,&head,nb); } else { char *save=NULL; uint32_t nb=1; diaElemFile selectSave(1,&save,QT_TR_NOOP("GlyphSet filename"), NULL, QT_TR_NOOP("Save GlyphSet file")); diaElem *elems2[]={&selectSave}; if(diaFactoryRun(QT_TR_NOOP("Save Glyph"),1,elems2)) { saveGlyph(save,&head,nb); } if(save) ADM_dezalloc(save); } } cleanupSub(&source); if(srtFileName )ADM_dezalloc(srtFileName); srtFileName=NULL; destroyGlyphTree(&head); return 1; }
/** \fn DIA_glyphEdit \brief Dialog to edit glyph */ uint8_t DIA_glyphEdit(void) { char *glyphName; admGlyph head(1,1); uint32_t nbGlyph=0; uint8_t ret=0; // First select a file GUI_FileSelRead(QT_TR_NOOP("Select GlyphFile to edit"), &glyphName); if(!glyphName) return 0; // Try to load it if(!loadGlyph(glyphName,&head,&nbGlyph) || !nbGlyph) { destroyGlyphTree(&head); return 0; } // Convert the linear glyph to glyph array admGlyph *glyphArray[nbGlyph]; admGlyph *cur=head.next; uint32_t idx=0; while(cur) { glyphArray[idx++]=cur; cur=cur->next; } ADM_assert(idx<=nbGlyph); nbGlyph=idx; // Glyph loaded, here we go currentGlyph=head.next; dialog=create_dialog1 (); gtk_register_dialog(dialog); // Register callbacks #define ASSOCIATE(x,y) gtk_dialog_add_action_widget (GTK_DIALOG (dialog), WID(x),y) #define CONNECT(x,y,z) gtk_signal_connect(GTK_OBJECT(WID(x)), #y,GTK_SIGNAL_FUNC(z), NULL); #define ACTION_PREV 10 #define ACTION_NEXT 20 #define ACTION_PREV_EMPTY 30 #define ACTION_NEXT_EMPTY 40 #define ACTION_SAVE 50 #define ACTION_DELETE 60 #define ACTION_ACTIVATE 70 #define ACTION_SEARCH 80 #define ACTION_REWIND 90 ASSOCIATE(buttonPrev,ACTION_PREV); ASSOCIATE(buttonNext,ACTION_NEXT); ASSOCIATE(buttonEmptyPrev,ACTION_PREV_EMPTY); ASSOCIATE(buttonNextEmpty,ACTION_NEXT_EMPTY); ASSOCIATE(buttonSave,ACTION_SAVE); ASSOCIATE(buttonDelete,ACTION_DELETE); ASSOCIATE(buttonSearch,ACTION_SEARCH); ASSOCIATE(buttonRewind,ACTION_REWIND); CONNECT(drawingarea1,expose_event,glyphDraw); CONNECT(entry1,activate,glyphActivate); gtk_widget_show(dialog); glyphUpdate(); while(1) { gint b=gtk_dialog_run(GTK_DIALOG(dialog)); switch(b) { case ACTION_REWIND: currentGlyph=head.next; glyphUpdate(); continue; case ACTION_SEARCH: { char *tomatch=NULL; { // Dialog Factory to the rescue ! diaElemText txt(&tomatch,QT_TR_NOOP("String"),NULL); diaElem *elems[]={&txt}; if(!diaFactoryRun(QT_TR_NOOP("Search string"),1,elems)) { continue; break; } } printf("Searched string <%s>\n",tomatch); while(currentGlyph->next) { currentGlyph=currentGlyph->next; glyphUpdate(); if(currentGlyph->code) { printf("%s vs %s\n",currentGlyph->code,tomatch); if(!strcmp(currentGlyph->code,tomatch)) { glyphUpdate(); break; } } } ADM_dezalloc(tomatch); if(!currentGlyph->next) GUI_Error_HIG(QT_TR_NOOP("End reached"),QT_TR_NOOP("No more glyphs")); } continue; break; ; case ACTION_PREV: printf("PREV\n"); if(currentGlyph!=head.next) { admGlyph *father; father=glyphSearchFather(currentGlyph,&head); if(father) { currentGlyph=father; glyphUpdate(); } } continue;break; case ACTION_NEXT: printf("NEXT\n"); if(currentGlyph->next) { currentGlyph=currentGlyph->next; glyphUpdate(); } continue;break; case ACTION_NEXT_EMPTY: printf("NEXT EMPTY\n"); while(1) { if(currentGlyph->next) { currentGlyph=currentGlyph->next; glyphUpdate(); if(!currentGlyph->code || !*(currentGlyph->code)) { break; } } else { GUI_Error_HIG(QT_TR_NOOP("End reached"),QT_TR_NOOP("No more glyphs")); break; } } continue;break; case ACTION_PREV_EMPTY: printf("PREV EMPTY\n"); while(1) { if(currentGlyph!=head.next) { admGlyph *father; father=glyphSearchFather(currentGlyph,&head); if(father) { currentGlyph=father; glyphUpdate(); if(!currentGlyph->code || !*(currentGlyph->code)) { break; } continue; } } GUI_Error_HIG(QT_TR_NOOP("Head reached"),QT_TR_NOOP("No more glyphs")); break; } continue;break; case ACTION_SAVE: saveGlyph(glyphName,&head,nbGlyph); continue;break; case ACTION_DELETE: { admGlyph *father; father=glyphSearchFather(currentGlyph,&head); ADM_assert(father); father->next=currentGlyph->next; delete currentGlyph; currentGlyph=father; if(father==&head && head.next) currentGlyph=head.next; nbGlyph--; glyphUpdate(); continue;break; } case ACTION_ACTIVATE: { const gchar *old; if(currentGlyph->code) delete [] currentGlyph->code; currentGlyph->code=NULL; // Retrieve new one old=gtk_entry_get_text (GTK_ENTRY (WID(entry1))); if(old && strlen(old)) { currentGlyph->code=new char[strlen(old)+1]; strcpy(currentGlyph->code,old); } } continue;break; } break; // exit while(1) } gtk_unregister_dialog(dialog); gtk_widget_destroy(dialog); destroyGlyphTree(&head); return ret; }
/** \fn DIA_ocrDvb \brief Dialog to select input & output files before calling the actual ocr engine */ uint8_t DIA_ocrDvb(void) { vobSubParam subparam={NULL,0,0}; char *srtFileName=NULL; char *glyphFileName=NULL; char *tsFileName=NULL; admGlyph head(16,16); char *globalGlyph=NULL; uint32_t globalGlyphOn=0; uint32_t pid=0x96; ADM_OCR_SOURCE source; memset(&source,0,sizeof(source)); source.type=ADM_OCR_TYPE_TS; prefs->get(FEATURE_GLOBAL_GLYPH_ACTIVE,&globalGlyphOn); if(globalGlyphOn) { prefs->get(FEATURE_GLOBAL_GLYPH_NAME,&globalGlyph); if(!*globalGlyph) { ADM_dezalloc(globalGlyph); globalGlyph=NULL; } } if(globalGlyph) { glyphFileName=globalGlyph; } _againX: // Fist build a dialogFactory to get input and output files diaElemFile selectTs(1,&tsFileName,QT_TR_NOOP("Input TS:"), NULL, QT_TR_NOOP("Select TS file")); diaElemUInteger selectPid(&pid,QT_TR_NOOP("Subtitle PID:"),0,255); diaElemFile selectGlyph(1,&glyphFileName,QT_TR_NOOP("Use glyphset (optional):"), NULL, QT_TR_NOOP("Select GlyphSet file")); diaElemFile selectSrt(1,&srtFileName,QT_TR_NOOP("Output SRT file"), NULL, QT_TR_NOOP("Save SRT file")); diaElem *elems[]={&selectTs,&selectPid,&selectSrt,&selectGlyph}; uint32_t n=4; if(globalGlyph) { n--; // Remove glyph from dialog } if( !diaFactoryRun(QT_TR_NOOP("Select input and ouput files"),n,elems)) { cleanupSub(&source); if(srtFileName )ADM_dezalloc(srtFileName); srtFileName=NULL; destroyGlyphTree(&head); return 0; } // TS file exists ? if(!ADM_fileExist(tsFileName)) { GUI_Error_HIG(QT_TR_NOOP("File error"),QT_TR_NOOP("Please Select a valid TS file.")); goto _againX; } if(!srtFileName || !*srtFileName) { GUI_Error_HIG(QT_TR_NOOP("File error"),QT_TR_NOOP("Please Select a valid output SRT file.")); goto _againX; } if(glyphFileName && *glyphFileName) { if(!ADM_fileExist(glyphFileName)) { GUI_Error_HIG(QT_TR_NOOP("File error"),QT_TR_NOOP("The idx/sub file does not exist.")); goto _againX; } // Purge previous glyph set if any destroyGlyphTree(&head); uint32_t nb; printf("[OCR] Loading glyphset :<%s>\n",glyphFileName); if(!loadGlyph(glyphFileName,&head,&nb)) { GUI_Error_HIG(QT_TR_NOOP("File error"),QT_TR_NOOP("Cannot load the glyphset file.")); goto _againX; } printf("[GLYPH] Found %u glyph\n"); } // We have our SRT and our TS file // Call the OCR engine... source.TsFile=ADM_strdup(tsFileName); source.TsPid=pid; ADM_ocr_engine(source,srtFileName,&head); // Save glyph set if(globalGlyph) { uint32_t nb=1; saveGlyph(globalGlyph,&head,nb); }else { char *save=NULL; uint32_t nb=1; diaElemFile selectSave(1,&save,QT_TR_NOOP("GlyphSet filename"), NULL, QT_TR_NOOP("Save GlyphSet file")); diaElem *elems2[]={&selectSave}; if( diaFactoryRun(QT_TR_NOOP("Save GlyphSet"),1,elems2)) { saveGlyph(save,&head,nb); } if(save) ADM_dezalloc(save); } cleanupSub(&source); if(srtFileName )ADM_dezalloc(srtFileName); srtFileName=NULL; if(tsFileName )ADM_dezalloc(tsFileName); tsFileName=NULL; destroyGlyphTree(&head); return 1; }
/****************************************************************************************** Setup (input/output files etc..) *****************************************************************************************/ ReplyType setup(void) { int sel; char text[1024]; while(1) { //gtk_widget_set_sensitive(WID(buttonAccept),0); //gtk_widget_set_sensitive(WID(buttonSkip),0); //gtk_widget_set_sensitive(WID(entryEntry),0); GTK_PURGE; // Main loop : Only accept glyph load/save // Sub & srt select & start ocr gtk_widget_set_sensitive(WID(frameGlyph),1); gtk_widget_set_sensitive(WID(frameLoad),1); gtk_widget_set_sensitive(WID(buttonStart),1); gtk_widget_set_sensitive(WID(frameBitmap),0); //gtk_widget_set_sensitive(WID(Current_Glyph),0); switch(sel=gtk_dialog_run(GTK_DIALOG(dialog))) { case actionLoadVob: { subparam.index=lang_index; subparam.subname=NULL; if(DIA_vobsub(&subparam)) { lang_index=subparam.index; gtk_label_set_text(GTK_LABEL(WID(labelVobsub)),subparam.subname); } } break; case actionSaveSub: { char *srt=NULL; GUI_FileSelWrite(_("Select SRT to save"), &srt); if(srt) { gtk_label_set_text(GTK_LABEL(WID(labelSrt)),srt); } } break; case actionLoadGlyph: { char *gly=NULL; GUI_FileSelRead(_("Select Glyoh to save"), &gly); if(gly) { loadGlyph(gly); sprintf(text,"%03d",nbGlyphs); gtk_label_set_text(GTK_LABEL(WID(labelNbGlyphs)),text); } } break; case actionSaveGlyph: if(!nbGlyphs) { GUI_Error_HIG(_("No glyphs to save"), NULL); break; } saveGlyph(); break; case GTK_RESPONSE_CLOSE: printf("Close req\n"); return ReplyClose; default: printf("Other input:%d\n",sel); } // Everything selected, check if(sel==actionGo) return ReplyOk; } }