Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* GRAPHITE2 LICENSING
3 Copyright 2010, SIL International
4 All rights reserved.
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.
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.
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.
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>
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"
36 #if defined _WIN32
37 #include "windows.h"
38 #endif
40 using namespace graphite2;
42 #if !defined GRAPHITE2_NTRACING
43 json *global_log = NULL;
44 #endif
46 extern "C" {
48 bool gr_start_logging(GR_MAYBE_UNUSED gr_face * face, const char *log_path)
49 {
50 if (!log_path) return false;
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;
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");
64 free(wlog_path);
65 #else // _WIN32
66 FILE *log = fopen(log_path, "wt");
67 #endif // _WIN32
68 if (!log) return false;
70 if (face)
71 {
72 face->setLogger(log);
73 if (!face->logger()) return false;
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 }
86 return true;
87 #else // GRAPHITE2_NTRACING
88 return false;
89 #endif // GRAPHITE2_NTRACING
90 }
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 }
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 }
127 void graphite_stop_logging()
128 {
129 // if (dbgout) delete dbgout;
130 // dbgout = 0;
131 }
133 } // extern "C"
135 #ifdef GRAPHITE2_TELEMETRY
136 size_t * graphite2::telemetry::_category = 0UL;
137 #endif
139 #if !defined GRAPHITE2_NTRACING
141 #ifdef GRAPHITE2_TELEMETRY
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
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 }
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;
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 }
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 }
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 }
242 #endif