Line data Source code
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 <cstdio>
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 : #include "inc/Collider.h"
36 :
37 : #if defined _WIN32
38 : #include "windows.h"
39 : #endif
40 :
41 : using namespace graphite2;
42 :
43 : #if !defined GRAPHITE2_NTRACING
44 : json *global_log = NULL;
45 : #endif
46 :
47 : extern "C" {
48 :
49 0 : bool gr_start_logging(GR_MAYBE_UNUSED gr_face * face, const char *log_path)
50 : {
51 0 : if (!log_path) return false;
52 :
53 : #if !defined GRAPHITE2_NTRACING
54 : gr_stop_logging(face);
55 : #if defined _WIN32
56 : int n = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, log_path, -1, 0, 0);
57 : if (n == 0 || n > MAX_PATH - 12) return false;
58 :
59 : LPWSTR wlog_path = gralloc<WCHAR>(n);
60 : if (!wlog_path) return false;
61 : FILE *log = 0;
62 : if (wlog_path && MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, log_path, -1, wlog_path, n))
63 : log = _wfopen(wlog_path, L"wt");
64 :
65 : free(wlog_path);
66 : #else // _WIN32
67 : FILE *log = fopen(log_path, "wt");
68 : #endif // _WIN32
69 : if (!log) return false;
70 :
71 : if (face)
72 : {
73 : face->setLogger(log);
74 : if (!face->logger()) return false;
75 :
76 : *face->logger() << json::array;
77 : #ifdef GRAPHITE2_TELEMETRY
78 : *face->logger() << face->tele;
79 : #endif
80 : }
81 : else
82 : {
83 : global_log = new json(log);
84 : *global_log << json::array;
85 : }
86 :
87 : return true;
88 : #else // GRAPHITE2_NTRACING
89 0 : return false;
90 : #endif // GRAPHITE2_NTRACING
91 : }
92 :
93 0 : bool graphite_start_logging(FILE * /* log */, GrLogMask /* mask */)
94 : {
95 : //#if !defined GRAPHITE2_NTRACING
96 : // graphite_stop_logging();
97 : //
98 : // if (!log) return false;
99 : //
100 : // dbgout = new json(log);
101 : // if (!dbgout) return false;
102 : //
103 : // *dbgout << json::array;
104 : // return true;
105 : //#else
106 0 : return false;
107 : //#endif
108 : }
109 :
110 0 : void gr_stop_logging(GR_MAYBE_UNUSED gr_face * face)
111 : {
112 : #if !defined GRAPHITE2_NTRACING
113 : if (face && face->logger())
114 : {
115 : FILE * log = face->logger()->stream();
116 : face->setLogger(0);
117 : fclose(log);
118 : }
119 : else if (!face && global_log)
120 : {
121 : FILE * log = global_log->stream();
122 : delete global_log;
123 : fclose(log);
124 : }
125 : #endif
126 0 : }
127 :
128 0 : void graphite_stop_logging()
129 : {
130 : // if (dbgout) delete dbgout;
131 : // dbgout = 0;
132 0 : }
133 :
134 : } // extern "C"
135 :
136 : #ifdef GRAPHITE2_TELEMETRY
137 : size_t * graphite2::telemetry::_category = 0UL;
138 : #endif
139 :
140 : #if !defined GRAPHITE2_NTRACING
141 :
142 : #ifdef GRAPHITE2_TELEMETRY
143 :
144 : json & graphite2::operator << (json & j, const telemetry & t) throw()
145 : {
146 : j << json::object
147 : << "type" << "telemetry"
148 : << "silf" << t.silf
149 : << "states" << t.states
150 : << "starts" << t.starts
151 : << "transitions" << t.transitions
152 : << "glyphs" << t.glyph
153 : << "code" << t.code
154 : << "misc" << t.misc
155 : << "total" << (t.silf + t.states + t.starts + t.transitions + t.glyph + t.code + t.misc)
156 : << json::close;
157 : return j;
158 : }
159 : #else
160 : json & graphite2::operator << (json & j, const telemetry &) throw()
161 : {
162 : return j;
163 : }
164 : #endif
165 :
166 :
167 : json & graphite2::operator << (json & j, const CharInfo & ci) throw()
168 : {
169 : return j << json::object
170 : << "offset" << ci.base()
171 : << "unicode" << ci.unicodeChar()
172 : << "break" << ci.breakWeight()
173 : << "flags" << ci.flags()
174 : << "slot" << json::flat << json::object
175 : << "before" << ci.before()
176 : << "after" << ci.after()
177 : << json::close
178 : << json::close;
179 : }
180 :
181 :
182 : json & graphite2::operator << (json & j, const dslot & ds) throw()
183 : {
184 : assert(ds.first);
185 : assert(ds.second);
186 : const Segment & seg = *ds.first;
187 : const Slot & s = *ds.second;
188 : const SlotCollision *cslot = seg.collisionInfo(ds.second);
189 :
190 : j << json::object
191 : << "id" << objectid(ds)
192 : << "gid" << s.gid()
193 : << "charinfo" << json::flat << json::object
194 : << "original" << s.original()
195 : << "before" << s.before()
196 : << "after" << s.after()
197 : << json::close
198 : << "origin" << s.origin()
199 : << "shift" << Position(float(s.getAttr(0, gr_slatShiftX, 0)),
200 : float(s.getAttr(0, gr_slatShiftY, 0)))
201 : << "advance" << s.advancePos()
202 : << "insert" << s.isInsertBefore()
203 : << "break" << s.getAttr(&seg, gr_slatBreak, 0);
204 : if (s.just() > 0)
205 : j << "justification" << s.just();
206 : if (s.getBidiLevel() > 0)
207 : j << "bidi" << s.getBidiLevel();
208 : if (!s.isBase())
209 : j << "parent" << json::flat << json::object
210 : << "id" << objectid(dslot(&seg, s.attachedTo()))
211 : << "level" << s.getAttr(0, gr_slatAttLevel, 0)
212 : << "offset" << s.attachOffset()
213 : << json::close;
214 : j << "user" << json::flat << json::array;
215 : for (int n = 0; n!= seg.numAttrs(); ++n)
216 : j << s.userAttrs()[n];
217 : j << json::close;
218 : if (s.firstChild())
219 : {
220 : j << "children" << json::flat << json::array;
221 : for (const Slot *c = s.firstChild(); c; c = c->nextSibling())
222 : j << objectid(dslot(&seg, c));
223 : j << json::close;
224 : }
225 : if (cslot)
226 : {
227 : // Note: the reason for using Positions to lump together related attributes is to make the
228 : // JSON output slightly more compact.
229 : j << "collision" << json::flat << json::object
230 : // << "shift" << cslot->shift() -- not used pass level, only within the collision routine itself
231 : << "offset" << cslot->offset()
232 : << "limit" << cslot->limit()
233 : << "flags" << cslot->flags()
234 : << "margin" << Position(cslot->margin(), cslot->marginWt())
235 : << "exclude" << cslot->exclGlyph()
236 : << "excludeoffset" << cslot->exclOffset();
237 : if (cslot->seqOrder() != 0)
238 : {
239 : j << "seqclass" << Position(cslot->seqClass(), cslot->seqProxClass())
240 : << "seqorder" << cslot->seqOrder()
241 : << "seqabove" << Position(cslot->seqAboveXoff(), cslot->seqAboveWt())
242 : << "seqbelow" << Position(cslot->seqBelowXlim(), cslot->seqBelowWt())
243 : << "seqvalign" << Position(cslot->seqValignHt(), cslot->seqValignWt());
244 : }
245 : j << json::close;
246 : }
247 : return j << json::close;
248 : }
249 :
250 :
251 : graphite2::objectid::objectid(const dslot & ds) throw()
252 : {
253 : const Slot * const p = ds.second;
254 : uint32 s = reinterpret_cast<size_t>(p);
255 : sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), uint16(p ? p->userAttrs()[ds.first->silf()->numUser()] : 0), uint16(s));
256 : name[sizeof name-1] = 0;
257 : }
258 :
259 : graphite2::objectid::objectid(const Segment * const p) throw()
260 : {
261 : uint32 s = reinterpret_cast<size_t>(p);
262 : sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), 0, uint16(s));
263 : name[sizeof name-1] = 0;
264 : }
265 :
266 : #endif
|