tesseract
3.03
|
00001 00002 // File: fontinfo.cpp 00003 // Description: Font information classes abstracted from intproto.h/cpp. 00004 // Author: rays@google.com (Ray Smith) 00005 // Created: Wed May 18 10:39:01 PDT 2011 00006 // 00007 // (C) Copyright 2011, Google Inc. 00008 // Licensed under the Apache License, Version 2.0 (the "License"); 00009 // you may not use this file except in compliance with the License. 00010 // You may obtain a copy of the License at 00011 // http://www.apache.org/licenses/LICENSE-2.0 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // 00019 00020 #include "fontinfo.h" 00021 #include "bitvector.h" 00022 #include "unicity_table.h" 00023 00024 namespace tesseract { 00025 00026 // Writes to the given file. Returns false in case of error. 00027 bool FontInfo::Serialize(FILE* fp) const { 00028 if (!write_info(fp, *this)) return false; 00029 if (!write_spacing_info(fp, *this)) return false; 00030 return true; 00031 } 00032 // Reads from the given file. Returns false in case of error. 00033 // If swap is true, assumes a big/little-endian swap is needed. 00034 bool FontInfo::DeSerialize(bool swap, FILE* fp) { 00035 if (!read_info(fp, this, swap)) return false; 00036 if (!read_spacing_info(fp, this, swap)) return false; 00037 return true; 00038 } 00039 00040 FontInfoTable::FontInfoTable() { 00041 set_compare_callback(NewPermanentTessCallback(CompareFontInfo)); 00042 set_clear_callback(NewPermanentTessCallback(FontInfoDeleteCallback)); 00043 } 00044 00045 FontInfoTable::~FontInfoTable() { 00046 } 00047 00048 // Writes to the given file. Returns false in case of error. 00049 bool FontInfoTable::Serialize(FILE* fp) const { 00050 return this->SerializeClasses(fp); 00051 } 00052 // Reads from the given file. Returns false in case of error. 00053 // If swap is true, assumes a big/little-endian swap is needed. 00054 bool FontInfoTable::DeSerialize(bool swap, FILE* fp) { 00055 truncate(0); 00056 return this->DeSerializeClasses(swap, fp); 00057 } 00058 00059 // Returns true if the given set of fonts includes one with the same 00060 // properties as font_id. 00061 bool FontInfoTable::SetContainsFontProperties( 00062 int font_id, const GenericVector<int>& font_set) const { 00063 uinT32 properties = get(font_id).properties; 00064 for (int f = 0; f < font_set.size(); ++f) { 00065 if (get(font_set[f]).properties == properties) 00066 return true; 00067 } 00068 return false; 00069 } 00070 00071 // Returns true if the given set of fonts includes multiple properties. 00072 bool FontInfoTable::SetContainsMultipleFontProperties( 00073 const GenericVector<int>& font_set) const { 00074 if (font_set.empty()) return false; 00075 int first_font = font_set[0]; 00076 uinT32 properties = get(first_font).properties; 00077 for (int f = 1; f < font_set.size(); ++f) { 00078 if (get(font_set[f]).properties != properties) 00079 return true; 00080 } 00081 return false; 00082 } 00083 00084 // Moves any non-empty FontSpacingInfo entries from other to this. 00085 void FontInfoTable::MoveSpacingInfoFrom(FontInfoTable* other) { 00086 set_compare_callback(NewPermanentTessCallback(CompareFontInfo)); 00087 set_clear_callback(NewPermanentTessCallback(FontInfoDeleteCallback)); 00088 for (int i = 0; i < other->size(); ++i) { 00089 GenericVector<FontSpacingInfo*>* spacing_vec = other->get(i).spacing_vec; 00090 if (spacing_vec != NULL) { 00091 int target_index = get_index(other->get(i)); 00092 if (target_index < 0) { 00093 // Bit copy the FontInfo and steal all the pointers. 00094 push_back(other->get(i)); 00095 other->get(i).name = NULL; 00096 } else { 00097 delete [] get(target_index).spacing_vec; 00098 get(target_index).spacing_vec = other->get(i).spacing_vec; 00099 } 00100 other->get(i).spacing_vec = NULL; 00101 } 00102 } 00103 } 00104 00105 // Moves this to the target unicity table. 00106 void FontInfoTable::MoveTo(UnicityTable<FontInfo>* target) { 00107 target->clear(); 00108 target->set_compare_callback(NewPermanentTessCallback(CompareFontInfo)); 00109 target->set_clear_callback(NewPermanentTessCallback(FontInfoDeleteCallback)); 00110 for (int i = 0; i < size(); ++i) { 00111 // Bit copy the FontInfo and steal all the pointers. 00112 target->push_back(get(i)); 00113 get(i).name = NULL; 00114 get(i).spacing_vec = NULL; 00115 } 00116 } 00117 00118 00119 // Compare FontInfo structures. 00120 bool CompareFontInfo(const FontInfo& fi1, const FontInfo& fi2) { 00121 // The font properties are required to be the same for two font with the same 00122 // name, so there is no need to test them. 00123 // Consequently, querying the table with only its font name as information is 00124 // enough to retrieve its properties. 00125 return strcmp(fi1.name, fi2.name) == 0; 00126 } 00127 // Compare FontSet structures. 00128 bool CompareFontSet(const FontSet& fs1, const FontSet& fs2) { 00129 if (fs1.size != fs2.size) 00130 return false; 00131 for (int i = 0; i < fs1.size; ++i) { 00132 if (fs1.configs[i] != fs2.configs[i]) 00133 return false; 00134 } 00135 return true; 00136 } 00137 00138 // Callbacks for GenericVector. 00139 void FontInfoDeleteCallback(FontInfo f) { 00140 if (f.spacing_vec != NULL) { 00141 f.spacing_vec->delete_data_pointers(); 00142 delete f.spacing_vec; 00143 } 00144 delete[] f.name; 00145 } 00146 void FontSetDeleteCallback(FontSet fs) { 00147 delete[] fs.configs; 00148 } 00149 00150 /*---------------------------------------------------------------------------*/ 00151 // Callbacks used by UnicityTable to read/write FontInfo/FontSet structures. 00152 bool read_info(FILE* f, FontInfo* fi, bool swap) { 00153 inT32 size; 00154 if (fread(&size, sizeof(size), 1, f) != 1) return false; 00155 if (swap) 00156 Reverse32(&size); 00157 char* font_name = new char[size + 1]; 00158 fi->name = font_name; 00159 if (static_cast<int>(fread(font_name, sizeof(*font_name), size, f)) != size) 00160 return false; 00161 font_name[size] = '\0'; 00162 if (fread(&fi->properties, sizeof(fi->properties), 1, f) != 1) return false; 00163 if (swap) 00164 Reverse32(&fi->properties); 00165 return true; 00166 } 00167 00168 bool write_info(FILE* f, const FontInfo& fi) { 00169 inT32 size = strlen(fi.name); 00170 if (fwrite(&size, sizeof(size), 1, f) != 1) return false; 00171 if (static_cast<int>(fwrite(fi.name, sizeof(*fi.name), size, f)) != size) 00172 return false; 00173 if (fwrite(&fi.properties, sizeof(fi.properties), 1, f) != 1) return false; 00174 return true; 00175 } 00176 00177 bool read_spacing_info(FILE *f, FontInfo* fi, bool swap) { 00178 inT32 vec_size, kern_size; 00179 if (fread(&vec_size, sizeof(vec_size), 1, f) != 1) return false; 00180 if (swap) Reverse32(&vec_size); 00181 ASSERT_HOST(vec_size >= 0); 00182 if (vec_size == 0) return true; 00183 fi->init_spacing(vec_size); 00184 for (int i = 0; i < vec_size; ++i) { 00185 FontSpacingInfo *fs = new FontSpacingInfo(); 00186 if (fread(&fs->x_gap_before, sizeof(fs->x_gap_before), 1, f) != 1 || 00187 fread(&fs->x_gap_after, sizeof(fs->x_gap_after), 1, f) != 1 || 00188 fread(&kern_size, sizeof(kern_size), 1, f) != 1) { 00189 return false; 00190 } 00191 if (swap) { 00192 ReverseN(&(fs->x_gap_before), sizeof(fs->x_gap_before)); 00193 ReverseN(&(fs->x_gap_after), sizeof(fs->x_gap_after)); 00194 Reverse32(&kern_size); 00195 } 00196 if (kern_size < 0) { // indication of a NULL entry in fi->spacing_vec 00197 delete fs; 00198 continue; 00199 } 00200 if (kern_size > 0 && (!fs->kerned_unichar_ids.DeSerialize(swap, f) || 00201 !fs->kerned_x_gaps.DeSerialize(swap, f))) { 00202 return false; 00203 } 00204 fi->add_spacing(i, fs); 00205 } 00206 return true; 00207 } 00208 00209 bool write_spacing_info(FILE* f, const FontInfo& fi) { 00210 inT32 vec_size = (fi.spacing_vec == NULL) ? 0 : fi.spacing_vec->size(); 00211 if (fwrite(&vec_size, sizeof(vec_size), 1, f) != 1) return false; 00212 inT16 x_gap_invalid = -1; 00213 for (int i = 0; i < vec_size; ++i) { 00214 FontSpacingInfo *fs = fi.spacing_vec->get(i); 00215 inT32 kern_size = (fs == NULL) ? -1 : fs->kerned_x_gaps.size(); 00216 if (fs == NULL) { 00217 // Valid to have the identical fwrites. Writing invalid x-gaps. 00218 if (fwrite(&(x_gap_invalid), sizeof(x_gap_invalid), 1, f) != 1 || 00219 fwrite(&(x_gap_invalid), sizeof(x_gap_invalid), 1, f) != 1 || 00220 fwrite(&kern_size, sizeof(kern_size), 1, f) != 1) { 00221 return false; 00222 } 00223 } else { 00224 if (fwrite(&(fs->x_gap_before), sizeof(fs->x_gap_before), 1, f) != 1 || 00225 fwrite(&(fs->x_gap_after), sizeof(fs->x_gap_after), 1, f) != 1 || 00226 fwrite(&kern_size, sizeof(kern_size), 1, f) != 1) { 00227 return false; 00228 } 00229 } 00230 if (kern_size > 0 && (!fs->kerned_unichar_ids.Serialize(f) || 00231 !fs->kerned_x_gaps.Serialize(f))) { 00232 return false; 00233 } 00234 } 00235 return true; 00236 } 00237 00238 bool read_set(FILE* f, FontSet* fs, bool swap) { 00239 if (fread(&fs->size, sizeof(fs->size), 1, f) != 1) return false; 00240 if (swap) 00241 Reverse32(&fs->size); 00242 fs->configs = new int[fs->size]; 00243 for (int i = 0; i < fs->size; ++i) { 00244 if (fread(&fs->configs[i], sizeof(fs->configs[i]), 1, f) != 1) return false; 00245 if (swap) 00246 Reverse32(&fs->configs[i]); 00247 } 00248 return true; 00249 } 00250 00251 bool write_set(FILE* f, const FontSet& fs) { 00252 if (fwrite(&fs.size, sizeof(fs.size), 1, f) != 1) return false; 00253 for (int i = 0; i < fs.size; ++i) { 00254 if (fwrite(&fs.configs[i], sizeof(fs.configs[i]), 1, f) != 1) return false; 00255 } 00256 return true; 00257 } 00258 00259 } // namespace tesseract. 00260