diff options
Diffstat (limited to 'gfx/graphite2/src/gr_logging.cpp')
-rw-r--r-- | gfx/graphite2/src/gr_logging.cpp | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/gfx/graphite2/src/gr_logging.cpp b/gfx/graphite2/src/gr_logging.cpp new file mode 100644 index 000000000..3e453ba8e --- /dev/null +++ b/gfx/graphite2/src/gr_logging.cpp @@ -0,0 +1,266 @@ +/* GRAPHITE2 LICENSING + + Copyright 2010, SIL International + All rights reserved. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should also have received a copy of the GNU Lesser General Public + License along with this library in the file named "LICENSE". + If not, write to the Free Software Foundation, 51 Franklin Street, + Suite 500, Boston, MA 02110-1335, USA or visit their web page on the + internet at http://www.fsf.org/licenses/lgpl.html. + +Alternatively, the contents of this file may be used under the terms of the +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public +License, as published by the Free Software Foundation, either version 2 +of the License or (at your option) any later version. +*/ +#include <cstdio> + +#include "graphite2/Log.h" +#include "inc/debug.h" +#include "inc/CharInfo.h" +#include "inc/Slot.h" +#include "inc/Segment.h" +#include "inc/json.h" +#include "inc/Collider.h" + +#if defined _WIN32 +#include "windows.h" +#endif + +using namespace graphite2; + +#if !defined GRAPHITE2_NTRACING +json *global_log = NULL; +#endif + +extern "C" { + +bool gr_start_logging(GR_MAYBE_UNUSED gr_face * face, const char *log_path) +{ + if (!log_path) return false; + +#if !defined GRAPHITE2_NTRACING + gr_stop_logging(face); +#if defined _WIN32 + int n = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, log_path, -1, 0, 0); + if (n == 0 || n > MAX_PATH - 12) return false; + + LPWSTR wlog_path = gralloc<WCHAR>(n); + if (!wlog_path) return false; + FILE *log = 0; + if (wlog_path && MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, log_path, -1, wlog_path, n)) + log = _wfopen(wlog_path, L"wt"); + + free(wlog_path); +#else // _WIN32 + FILE *log = fopen(log_path, "wt"); +#endif // _WIN32 + if (!log) return false; + + if (face) + { + face->setLogger(log); + if (!face->logger()) return false; + + *face->logger() << json::array; +#ifdef GRAPHITE2_TELEMETRY + *face->logger() << face->tele; +#endif + } + else + { + global_log = new json(log); + *global_log << json::array; + } + + return true; +#else // GRAPHITE2_NTRACING + return false; +#endif // GRAPHITE2_NTRACING +} + +bool graphite_start_logging(FILE * /* log */, GrLogMask /* mask */) +{ +//#if !defined GRAPHITE2_NTRACING +// graphite_stop_logging(); +// +// if (!log) return false; +// +// dbgout = new json(log); +// if (!dbgout) return false; +// +// *dbgout << json::array; +// return true; +//#else + return false; +//#endif +} + +void gr_stop_logging(GR_MAYBE_UNUSED gr_face * face) +{ +#if !defined GRAPHITE2_NTRACING + if (face && face->logger()) + { + FILE * log = face->logger()->stream(); + face->setLogger(0); + fclose(log); + } + else if (!face && global_log) + { + FILE * log = global_log->stream(); + delete global_log; + fclose(log); + } +#endif +} + +void graphite_stop_logging() +{ +// if (dbgout) delete dbgout; +// dbgout = 0; +} + +} // extern "C" + +#ifdef GRAPHITE2_TELEMETRY +size_t * graphite2::telemetry::_category = 0UL; +#endif + +#if !defined GRAPHITE2_NTRACING + +#ifdef GRAPHITE2_TELEMETRY + +json & graphite2::operator << (json & j, const telemetry & t) throw() +{ + j << json::object + << "type" << "telemetry" + << "silf" << t.silf + << "states" << t.states + << "starts" << t.starts + << "transitions" << t.transitions + << "glyphs" << t.glyph + << "code" << t.code + << "misc" << t.misc + << "total" << (t.silf + t.states + t.starts + t.transitions + t.glyph + t.code + t.misc) + << json::close; + return j; +} +#else +json & graphite2::operator << (json & j, const telemetry &) throw() +{ + return j; +} +#endif + + +json & graphite2::operator << (json & j, const CharInfo & ci) throw() +{ + return j << json::object + << "offset" << ci.base() + << "unicode" << ci.unicodeChar() + << "break" << ci.breakWeight() + << "flags" << ci.flags() + << "slot" << json::flat << json::object + << "before" << ci.before() + << "after" << ci.after() + << json::close + << json::close; +} + + +json & graphite2::operator << (json & j, const dslot & ds) throw() +{ + assert(ds.first); + assert(ds.second); + const Segment & seg = *ds.first; + const Slot & s = *ds.second; + const SlotCollision *cslot = seg.collisionInfo(ds.second); + + j << json::object + << "id" << objectid(ds) + << "gid" << s.gid() + << "charinfo" << json::flat << json::object + << "original" << s.original() + << "before" << s.before() + << "after" << s.after() + << json::close + << "origin" << s.origin() + << "shift" << Position(float(s.getAttr(0, gr_slatShiftX, 0)), + float(s.getAttr(0, gr_slatShiftY, 0))) + << "advance" << s.advancePos() + << "insert" << s.isInsertBefore() + << "break" << s.getAttr(&seg, gr_slatBreak, 0); + if (s.just() > 0) + j << "justification" << s.just(); + if (s.getBidiLevel() > 0) + j << "bidi" << s.getBidiLevel(); + if (!s.isBase()) + j << "parent" << json::flat << json::object + << "id" << objectid(dslot(&seg, s.attachedTo())) + << "level" << s.getAttr(0, gr_slatAttLevel, 0) + << "offset" << s.attachOffset() + << json::close; + j << "user" << json::flat << json::array; + for (int n = 0; n!= seg.numAttrs(); ++n) + j << s.userAttrs()[n]; + j << json::close; + if (s.firstChild()) + { + j << "children" << json::flat << json::array; + for (const Slot *c = s.firstChild(); c; c = c->nextSibling()) + j << objectid(dslot(&seg, c)); + j << json::close; + } + if (cslot) + { + // Note: the reason for using Positions to lump together related attributes is to make the + // JSON output slightly more compact. + j << "collision" << json::flat << json::object +// << "shift" << cslot->shift() -- not used pass level, only within the collision routine itself + << "offset" << cslot->offset() + << "limit" << cslot->limit() + << "flags" << cslot->flags() + << "margin" << Position(cslot->margin(), cslot->marginWt()) + << "exclude" << cslot->exclGlyph() + << "excludeoffset" << cslot->exclOffset(); + if (cslot->seqOrder() != 0) + { + j << "seqclass" << Position(cslot->seqClass(), cslot->seqProxClass()) + << "seqorder" << cslot->seqOrder() + << "seqabove" << Position(cslot->seqAboveXoff(), cslot->seqAboveWt()) + << "seqbelow" << Position(cslot->seqBelowXlim(), cslot->seqBelowWt()) + << "seqvalign" << Position(cslot->seqValignHt(), cslot->seqValignWt()); + } + j << json::close; + } + return j << json::close; +} + + +graphite2::objectid::objectid(const dslot & ds) throw() +{ + const Slot * const p = ds.second; + uint32 s = reinterpret_cast<size_t>(p); + sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), uint16(p ? p->userAttrs()[ds.first->silf()->numUser()] : 0), uint16(s)); + name[sizeof name-1] = 0; +} + +graphite2::objectid::objectid(const Segment * const p) throw() +{ + uint32 s = reinterpret_cast<size_t>(p); + sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), 0, uint16(s)); + name[sizeof name-1] = 0; +} + +#endif |