Mercurial > otakunoraifu
comparison font/font_face.cc @ 52:15a18fbe6f21
* Known bugs added to the README
* Code cleaning (0 -> NULL when needed, indentation, spaces, ...)
author | thib |
---|---|
date | Sat, 18 Apr 2009 18:35:39 +0000 |
parents | fa8511a21d05 |
children | 4416cfac86ae |
comparison
equal
deleted
inserted
replaced
51:cbb301016a4e | 52:15a18fbe6f21 |
---|---|
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 #include <stdlib.h> | 28 #include <stdlib.h> |
29 #include <stdio.h> | 29 #include <stdio.h> |
30 #include"font.h" | 30 #include "font.h" |
31 #include"font_peer.h" | 31 #include "font_peer.h" |
32 #include <map> | 32 #include <map> |
33 #include <string> | 33 #include <string> |
34 #include <iostream> | 34 #include <iostream> |
35 | 35 |
36 namespace XKFont { | 36 namespace XKFont { |
37 | 37 |
38 class Cache : public std::map<unsigned int, Glyph*> { | 38 class Cache : public std::map<unsigned int, Glyph*> { |
39 public: | 39 public: |
40 Cache() {} | 40 Cache() {} |
41 ~Cache() { | 41 ~Cache() { |
42 iterator it; | |
43 for (it = begin(); it != end(); it++) | |
44 delete (it->second); | |
45 } | |
46 }; | |
47 | |
48 Face::Face(const char *name_orig, int index, int hsize, int vsize) | |
49 { | |
50 cache = new Cache; | |
51 | |
52 /* name: ';' 区切りで複数指定可能 */ | |
53 char* name = new char[strlen(name_orig)+1]; | |
54 while(*name_orig != 0) { | |
55 const char* next_name = strchr(name_orig, ';'); | |
56 if (next_name) { | |
57 strncpy(name, name_orig, next_name - name_orig); | |
58 name[next_name-name_orig] = 0; | |
59 name_orig = next_name + 1; | |
60 } else { | |
61 strcpy(name, name_orig); | |
62 name_orig += strlen(name_orig); | |
63 } | |
64 if (strstr(name, "fn.dat")) { | |
65 peer.push_back(new PeerFn(name, index, hsize, vsize)); | |
66 } else if (strstr(name, ".ttf") || strstr(name, ".ttc")) { | |
67 peer.push_back(new PeerFt2(name, index, hsize, vsize)); | |
68 #if USE_X11 | |
69 } else { | |
70 peer.push_back(new PeerX11(name, index, hsize, vsize)); | |
71 #endif | |
72 } | |
73 } | |
74 delete[] name; | |
75 return; | |
76 } | |
77 | |
78 Face::~Face() { | |
79 delete cache; | |
80 } | |
81 | |
82 Glyph* Face::GlyphLoad(unsigned int code) { | |
83 if (cache->count(code)) | |
84 return (*cache)[code]; | |
85 | |
86 Glyph* g = new Glyph; | |
42 iterator it; | 87 iterator it; |
43 for (it = begin(); it != end(); it++) | 88 for (it=peer.begin(); it != peer.end(); it++) { |
44 delete (it->second); | 89 if ( (*it)->GlyphCreate(code, g)) break; |
90 } | |
91 if (it == peer.end()) { | |
92 fprintf(stderr,"Cannot find glyph, code %04x\n",code); | |
93 g->bitmap_left = 0; | |
94 g->bitmap_top = 0; | |
95 g->bitmap.width = 0; | |
96 g->bitmap.rows = 0; | |
97 g->bitmap.buffer = new unsigned char[1]; | |
98 g->bitmap.buffer[0] = 0; | |
99 g->advance.x = 0; | |
100 g->advance.y = 0; | |
101 } | |
102 (*cache)[code] = g; | |
103 return g; | |
45 } | 104 } |
46 }; | |
47 | 105 |
48 Face::Face(const char *name_orig, int index, int hsize, int vsize) | 106 class FontImpl { |
49 { | 107 public: |
50 cache = new Cache; | 108 std::map<int, Face*> cache; |
109 std::string fontname; | |
110 int size; | |
111 ~FontImpl(); | |
112 }; | |
51 | 113 |
52 /* name: ';' 区切りで複数指定可能 */ | 114 FontImpl::~FontImpl() { |
53 char* name = new char[strlen(name_orig)+1]; | 115 std::map<int,Face*>::iterator it; |
54 while(*name_orig != 0) { | 116 for (it=cache.begin(); it!=cache.end(); it++) delete it->second; |
55 const char* next_name = strchr(name_orig, ';'); | 117 } |
56 if (next_name) { | 118 |
57 strncpy(name, name_orig, next_name - name_orig); | 119 Font::Font(const char* name, int size) { |
58 name[next_name-name_orig] = 0; | 120 pimpl = new FontImpl; |
59 name_orig = next_name + 1; | 121 pimpl->fontname = name; |
60 } else { | 122 pimpl->size = size; |
61 strcpy(name, name_orig); | 123 vsize = size; |
62 name_orig += strlen(name_orig); | 124 }; |
63 } | 125 |
64 if (strstr(name, "fn.dat")) { | 126 Font::~Font() { |
65 peer.push_back(new PeerFn(name, index, hsize, vsize)); | 127 delete pimpl; |
66 } else if (strstr(name, ".ttf") || strstr(name, ".ttc")) { | 128 } |
67 peer.push_back(new PeerFt2(name, index, hsize, vsize)); | 129 |
68 #if USE_X11 | 130 Face* Font::FaceLoad(double scale) { |
69 } else { | 131 std::map<int, Face*>& cache = pimpl->cache; |
70 peer.push_back(new PeerX11(name, index, hsize, vsize)); | 132 int size = int(scale * pimpl->size); |
71 #endif | 133 if (cache.find(size) != cache.end()) return cache[size]; |
134 try { | |
135 Face* face = new Face(pimpl->fontname.c_str(), 0, size, size); | |
136 cache[size] = face; | |
137 return face; | |
138 } catch(...) { | |
139 std::cerr << "Cannot create font face; font "<<pimpl->fontname<<", size "<<size<<std::endl; | |
140 /* 別の大きさを探す */ | |
141 int i; | |
142 for (i=0; i<size; i++) { | |
143 if (cache.find(size-i) != cache.end()) return cache[size-i]; | |
144 if (cache.find(size+i) != cache.end()) return cache[size+i]; | |
145 try { | |
146 Face* face = new Face(pimpl->fontname.c_str(), 0, size-i, size-i); | |
147 cache[size-i] = face; | |
148 return face; | |
149 } catch(...) {}; | |
150 try { | |
151 Face* face = new Face(pimpl->fontname.c_str(), 0, size+i, size+i); | |
152 cache[size+i] = face; | |
153 return face; | |
154 } catch(...) {}; | |
155 } | |
156 /* 見つからない */ | |
157 throw; | |
72 } | 158 } |
73 } | 159 } |
74 delete[] name; | |
75 return; | |
76 } | |
77 | |
78 Face::~Face() { | |
79 delete cache; | |
80 } | |
81 | |
82 Glyph* | |
83 Face::GlyphLoad(unsigned int code) { | |
84 if (cache->count(code)) | |
85 return (*cache)[code]; | |
86 | |
87 Glyph* g = new Glyph; | |
88 iterator it; | |
89 for (it=peer.begin(); it != peer.end(); it++) { | |
90 if ( (*it)->GlyphCreate(code, g)) break; | |
91 } | |
92 if (it == peer.end()) { | |
93 fprintf(stderr,"Cannot find glyph, code %04x\n",code); | |
94 g->bitmap_left = 0; | |
95 g->bitmap_top = 0; | |
96 g->bitmap.width = 0; | |
97 g->bitmap.rows = 0; | |
98 g->bitmap.buffer = new unsigned char[1]; | |
99 g->bitmap.buffer[0] = 0; | |
100 g->advance.x = 0; | |
101 g->advance.y = 0; | |
102 } | |
103 (*cache)[code] = g; | |
104 return g; | |
105 } | |
106 | |
107 class FontImpl { | |
108 public: | |
109 std::map<int, Face*> cache; | |
110 std::string fontname; | |
111 int size; | |
112 ~FontImpl(); | |
113 }; | |
114 | |
115 FontImpl::~FontImpl() { | |
116 std::map<int,Face*>::iterator it; | |
117 for (it=cache.begin(); it!=cache.end(); it++) delete it->second; | |
118 } | |
119 | |
120 Font::Font(const char* name, int size) { | |
121 pimpl = new FontImpl; | |
122 pimpl->fontname = name; | |
123 pimpl->size = size; | |
124 vsize = size; | |
125 }; | |
126 Font::~Font() { | |
127 delete pimpl; | |
128 } | |
129 Face* | |
130 Font::FaceLoad(double scale) { | |
131 std::map<int, Face*>& cache = pimpl->cache; | |
132 int size = int(scale * pimpl->size); | |
133 if (cache.find(size) != cache.end()) return cache[size]; | |
134 try { | |
135 Face* face = new Face(pimpl->fontname.c_str(), 0, size, size); | |
136 cache[size] = face; | |
137 return face; | |
138 } catch(...) { | |
139 std::cerr << "Cannot create font face; font "<<pimpl->fontname<<", size "<<size<<std::endl; | |
140 /* 別の大きさを探す */ | |
141 int i; | |
142 for (i=0; i<size; i++) { | |
143 if (cache.find(size-i) != cache.end()) return cache[size-i]; | |
144 if (cache.find(size+i) != cache.end()) return cache[size+i]; | |
145 try { | |
146 Face* face = new Face(pimpl->fontname.c_str(), 0, size-i, size-i); | |
147 cache[size-i] = face; | |
148 return face; | |
149 } catch(...) {}; | |
150 try { | |
151 Face* face = new Face(pimpl->fontname.c_str(), 0, size+i, size+i); | |
152 cache[size+i] = face; | |
153 return face; | |
154 } catch(...) {}; | |
155 } | |
156 /* 見つからない */ | |
157 throw; | |
158 } | |
159 } | |
160 | 160 |
161 } /* namespace XKFont */ | 161 } /* namespace XKFont */ |