00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "pnmTextMaker.h"
00015 #include "pnmTextGlyph.h"
00016 #include "filename.h"
00017 #include "pnmImage.h"
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 PNMTextMaker::
00028 PNMTextMaker(const Filename &font_filename, int face_index) {
00029 initialize();
00030 _is_valid = load_font(font_filename, face_index);
00031 }
00032
00033
00034
00035
00036
00037
00038
00039
00040 PNMTextMaker::
00041 PNMTextMaker(const char *font_data, int data_length, int face_index) {
00042 initialize();
00043 _is_valid = load_font(font_data, data_length, face_index);
00044 }
00045
00046
00047
00048
00049
00050
00051 PNMTextMaker::
00052 PNMTextMaker(const PNMTextMaker ©) :
00053 FreetypeFont(copy),
00054 _is_valid(copy._is_valid),
00055 _align(copy._align),
00056 _interior_flag(copy._interior_flag),
00057 _fg(copy._fg),
00058 _interior(copy._interior)
00059 {
00060 }
00061
00062
00063
00064
00065
00066
00067 PNMTextMaker::
00068 ~PNMTextMaker() {
00069 empty_cache();
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079 int PNMTextMaker::
00080 generate_into(const wstring &text, PNMImage &dest_image, int x, int y) {
00081
00082 int width = calc_width(text);
00083
00084 int xp = x;
00085 int yp = y;
00086
00087 switch (_align) {
00088 case A_left:
00089 xp = x;
00090 break;
00091
00092 case A_center:
00093 xp = x - (width / 2);
00094 break;
00095
00096 case A_right:
00097 xp = x - width;
00098 break;
00099 }
00100
00101
00102 wstring::const_iterator ti;
00103 for (ti = text.begin(); ti != text.end(); ++ti) {
00104 int ch = (*ti);
00105 PNMTextGlyph *glyph = get_glyph(ch);
00106 if (_interior_flag) {
00107 glyph->place(dest_image, xp, yp, _fg, _interior);
00108 } else {
00109 glyph->place(dest_image, xp, yp, _fg);
00110 }
00111 xp += glyph->get_advance();
00112 }
00113
00114 return width;
00115 }
00116
00117
00118
00119
00120
00121
00122
00123 int PNMTextMaker::
00124 calc_width(const wstring &text) {
00125 int width = 0;
00126 wstring::const_iterator ti;
00127 for (ti = text.begin(); ti != text.end(); ++ti) {
00128 int ch = (*ti);
00129 PNMTextGlyph *glyph = get_glyph(ch);
00130 width += glyph->get_advance();
00131 }
00132 return width;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141 PNMTextGlyph *PNMTextMaker::
00142 get_glyph(int character) {
00143 FT_Face face = acquire_face();
00144 int glyph_index = FT_Get_Char_Index(face, character);
00145 release_face(face);
00146
00147 Glyphs::iterator gi;
00148 gi = _glyphs.find(glyph_index);
00149 if (gi != _glyphs.end()) {
00150 return (*gi).second;
00151 }
00152
00153 PNMTextGlyph *glyph = make_glyph(glyph_index);
00154 _glyphs.insert(Glyphs::value_type(glyph_index, glyph));
00155 return glyph;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164 void PNMTextMaker::
00165 initialize() {
00166 _align = A_left;
00167 _interior_flag = false;
00168 _fg.set(0.0f, 0.0f, 0.0f, 1.0f);
00169 _interior.set(0.5f, 0.5f, 0.5f, 1.0f);
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 PNMTextGlyph *PNMTextMaker::
00179 make_glyph(int glyph_index) {
00180 FT_Face face = acquire_face();
00181 if (!load_glyph(face, glyph_index)) {
00182 release_face(face);
00183 return (PNMTextGlyph *)NULL;
00184 }
00185
00186 FT_GlyphSlot slot = face->glyph;
00187
00188 FT_Bitmap &bitmap = slot->bitmap;
00189
00190 double advance = slot->advance.x / 64.0;
00191
00192 PNMTextGlyph *glyph = new PNMTextGlyph(advance);
00193
00194 if (bitmap.width == 0 || bitmap.rows == 0) {
00195
00196 glyph->rescale(_scale_factor);
00197
00198 } else {
00199 PNMImage &glyph_image = glyph->_image;
00200 glyph_image.clear(bitmap.width, bitmap.rows, 3);
00201 copy_bitmap_to_pnmimage(bitmap, glyph_image);
00202
00203 glyph->_top = slot->bitmap_top;
00204 glyph->_left = slot->bitmap_left;
00205
00206 if (_interior_flag) {
00207 glyph->determine_interior();
00208 }
00209 glyph->rescale(_scale_factor);
00210 }
00211
00212 release_face(face);
00213 return glyph;
00214 }
00215
00216
00217
00218
00219
00220
00221 void PNMTextMaker::
00222 empty_cache() {
00223 Glyphs::iterator gi;
00224 for (gi = _glyphs.begin(); gi != _glyphs.end(); ++gi) {
00225 PNMTextGlyph *glyph = (*gi).second;
00226 delete glyph;
00227 }
00228 }