|
1 /* GRAPHITE2 LICENSING |
|
2 |
|
3 Copyright 2010, SIL International |
|
4 All rights reserved. |
|
5 |
|
6 This library is free software; you can redistribute it and/or modify |
|
7 it under the terms of the GNU Lesser General Public License as published |
|
8 by the Free Software Foundation; either version 2.1 of License, or |
|
9 (at your option) any later version. |
|
10 |
|
11 This program is distributed in the hope that it will be useful, |
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
14 Lesser General Public License for more details. |
|
15 |
|
16 You should also have received a copy of the GNU Lesser General Public |
|
17 License along with this library in the file named "LICENSE". |
|
18 If not, write to the Free Software Foundation, 51 Franklin Street, |
|
19 Suite 500, Boston, MA 02110-1335, USA or visit their web page on the |
|
20 internet at http://www.fsf.org/licenses/lgpl.html. |
|
21 |
|
22 Alternatively, the contents of this file may be used under the terms of the |
|
23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public |
|
24 License, as published by the Free Software Foundation, either version 2 |
|
25 of the License or (at your option) any later version. |
|
26 */ |
|
27 #include <stdio.h> |
|
28 |
|
29 #include "graphite2/Log.h" |
|
30 #include "inc/debug.h" |
|
31 #include "inc/CharInfo.h" |
|
32 #include "inc/Slot.h" |
|
33 #include "inc/Segment.h" |
|
34 #include "inc/json.h" |
|
35 |
|
36 #if defined _WIN32 |
|
37 #include "windows.h" |
|
38 #endif |
|
39 |
|
40 using namespace graphite2; |
|
41 |
|
42 #if !defined GRAPHITE2_NTRACING |
|
43 json *global_log = NULL; |
|
44 #endif |
|
45 |
|
46 extern "C" { |
|
47 |
|
48 bool gr_start_logging(GR_MAYBE_UNUSED gr_face * face, const char *log_path) |
|
49 { |
|
50 if (!log_path) return false; |
|
51 |
|
52 #if !defined GRAPHITE2_NTRACING |
|
53 gr_stop_logging(face); |
|
54 #if defined _WIN32 |
|
55 int n = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, log_path, -1, 0, 0); |
|
56 if (n == 0 || n > MAX_PATH - 12) return false; |
|
57 |
|
58 LPWSTR wlog_path = gralloc<WCHAR>(n); |
|
59 if (!wlog_path) return false; |
|
60 FILE *log = 0; |
|
61 if (wlog_path && MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, log_path, -1, wlog_path, n)) |
|
62 log = _wfopen(wlog_path, L"wt"); |
|
63 |
|
64 free(wlog_path); |
|
65 #else // _WIN32 |
|
66 FILE *log = fopen(log_path, "wt"); |
|
67 #endif // _WIN32 |
|
68 if (!log) return false; |
|
69 |
|
70 if (face) |
|
71 { |
|
72 face->setLogger(log); |
|
73 if (!face->logger()) return false; |
|
74 |
|
75 *face->logger() << json::array; |
|
76 #ifdef GRAPHITE2_TELEMETRY |
|
77 *face->logger() << face->tele; |
|
78 #endif |
|
79 } |
|
80 else |
|
81 { |
|
82 global_log = new json(log); |
|
83 *global_log << json::array; |
|
84 } |
|
85 |
|
86 return true; |
|
87 #else // GRAPHITE2_NTRACING |
|
88 return false; |
|
89 #endif // GRAPHITE2_NTRACING |
|
90 } |
|
91 |
|
92 bool graphite_start_logging(FILE * /* log */, GrLogMask /* mask */) |
|
93 { |
|
94 //#if !defined GRAPHITE2_NTRACING |
|
95 // graphite_stop_logging(); |
|
96 // |
|
97 // if (!log) return false; |
|
98 // |
|
99 // dbgout = new json(log); |
|
100 // if (!dbgout) return false; |
|
101 // |
|
102 // *dbgout << json::array; |
|
103 // return true; |
|
104 //#else |
|
105 return false; |
|
106 //#endif |
|
107 } |
|
108 |
|
109 void gr_stop_logging(GR_MAYBE_UNUSED gr_face * face) |
|
110 { |
|
111 #if !defined GRAPHITE2_NTRACING |
|
112 if (face && face->logger()) |
|
113 { |
|
114 FILE * log = face->logger()->stream(); |
|
115 face->setLogger(0); |
|
116 fclose(log); |
|
117 } |
|
118 else if (!face && global_log) |
|
119 { |
|
120 FILE * log = global_log->stream(); |
|
121 delete global_log; |
|
122 fclose(log); |
|
123 } |
|
124 #endif |
|
125 } |
|
126 |
|
127 void graphite_stop_logging() |
|
128 { |
|
129 // if (dbgout) delete dbgout; |
|
130 // dbgout = 0; |
|
131 } |
|
132 |
|
133 } // extern "C" |
|
134 |
|
135 #ifdef GRAPHITE2_TELEMETRY |
|
136 size_t * graphite2::telemetry::_category = 0UL; |
|
137 #endif |
|
138 |
|
139 #if !defined GRAPHITE2_NTRACING |
|
140 |
|
141 #ifdef GRAPHITE2_TELEMETRY |
|
142 |
|
143 json & graphite2::operator << (json & j, const telemetry & t) throw() |
|
144 { |
|
145 j << json::object |
|
146 << "type" << "telemetry" |
|
147 << "silf" << t.silf |
|
148 << "states" << t.states |
|
149 << "starts" << t.starts |
|
150 << "transitions" << t.transitions |
|
151 << "glyphs" << t.glyph |
|
152 << "code" << t.code |
|
153 << "misc" << t.misc |
|
154 << "total" << (t.silf + t.states + t.starts + t.transitions + t.glyph + t.code + t.misc) |
|
155 << json::close; |
|
156 return j; |
|
157 } |
|
158 #else |
|
159 json & graphite2::operator << (json & j, const telemetry &) throw() |
|
160 { |
|
161 return j; |
|
162 } |
|
163 #endif |
|
164 |
|
165 |
|
166 json & graphite2::operator << (json & j, const CharInfo & ci) throw() |
|
167 { |
|
168 return j << json::object |
|
169 << "offset" << ci.base() |
|
170 << "unicode" << ci.unicodeChar() |
|
171 << "break" << ci.breakWeight() |
|
172 << "flags" << ci.flags() |
|
173 << "slot" << json::flat << json::object |
|
174 << "before" << ci.before() |
|
175 << "after" << ci.after() |
|
176 << json::close |
|
177 << json::close; |
|
178 } |
|
179 |
|
180 |
|
181 json & graphite2::operator << (json & j, const dslot & ds) throw() |
|
182 { |
|
183 assert(ds.first); |
|
184 assert(ds.second); |
|
185 const Segment & seg = *ds.first; |
|
186 const Slot & s = *ds.second; |
|
187 |
|
188 j << json::object |
|
189 << "id" << objectid(ds) |
|
190 << "gid" << s.gid() |
|
191 << "charinfo" << json::flat << json::object |
|
192 << "original" << s.original() |
|
193 << "before" << s.before() |
|
194 << "after" << s.after() |
|
195 << json::close |
|
196 << "origin" << s.origin() |
|
197 << "shift" << Position(float(s.getAttr(0, gr_slatShiftX, 0)), |
|
198 float(s.getAttr(0, gr_slatShiftY, 0))) |
|
199 << "advance" << s.advancePos() |
|
200 << "insert" << s.isInsertBefore() |
|
201 << "break" << s.getAttr(&seg, gr_slatBreak, 0); |
|
202 if (s.just() > 0) |
|
203 j << "justification" << s.just(); |
|
204 if (s.getBidiLevel() > 0) |
|
205 j << "bidi" << s.getBidiLevel(); |
|
206 if (!s.isBase()) |
|
207 j << "parent" << json::flat << json::object |
|
208 << "id" << objectid(dslot(&seg, s.attachedTo())) |
|
209 << "level" << s.getAttr(0, gr_slatAttLevel, 0) |
|
210 << "offset" << s.attachOffset() |
|
211 << json::close; |
|
212 j << "user" << json::flat << json::array; |
|
213 for (int n = 0; n!= seg.numAttrs(); ++n) |
|
214 j << s.userAttrs()[n]; |
|
215 j << json::close; |
|
216 if (s.firstChild()) |
|
217 { |
|
218 j << "children" << json::flat << json::array; |
|
219 for (const Slot *c = s.firstChild(); c; c = c->nextSibling()) |
|
220 j << objectid(dslot(&seg, c)); |
|
221 j << json::close; |
|
222 } |
|
223 return j << json::close; |
|
224 } |
|
225 |
|
226 |
|
227 graphite2::objectid::objectid(const dslot & ds) throw() |
|
228 { |
|
229 const Slot * const p = ds.second; |
|
230 uint32 s = reinterpret_cast<size_t>(p); |
|
231 sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), uint16(p ? p->userAttrs()[ds.first->silf()->numUser()] : 0), uint16(s)); |
|
232 name[sizeof name-1] = 0; |
|
233 } |
|
234 |
|
235 graphite2::objectid::objectid(const Segment * const p) throw() |
|
236 { |
|
237 uint32 s = reinterpret_cast<size_t>(p); |
|
238 sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), 0, uint16(s)); |
|
239 name[sizeof name-1] = 0; |
|
240 } |
|
241 |
|
242 #endif |