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