Path: blob/master/thirdparty/graphite/src/gr_logging.cpp
9902 views
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later1// Copyright 2010, SIL International, All rights reserved.23#include <cstdio>45#include "graphite2/Log.h"6#include "inc/debug.h"7#include "inc/CharInfo.h"8#include "inc/Slot.h"9#include "inc/Segment.h"10#include "inc/json.h"11#include "inc/Collider.h"1213#if defined _WIN3214#include "windows.h"15#endif1617using namespace graphite2;1819#if !defined GRAPHITE2_NTRACING20json *global_log = 0;21#endif2223extern "C" {2425bool gr_start_logging(GR_MAYBE_UNUSED gr_face * face, const char *log_path)26{27if (!log_path) return false;2829#if !defined GRAPHITE2_NTRACING30gr_stop_logging(face);31#if defined _WIN3232int n = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, log_path, -1, 0, 0);33if (n == 0 || n > MAX_PATH - 12) return false;3435LPWSTR wlog_path = gralloc<WCHAR>(n);36if (!wlog_path) return false;37FILE *log = 0;38if (wlog_path && MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, log_path, -1, wlog_path, n))39log = _wfopen(wlog_path, L"wt");4041free(wlog_path);42#else // _WIN3243FILE *log = fopen(log_path, "wt");44#endif // _WIN3245if (!log) return false;4647if (face)48{49face->setLogger(log);50if (!face->logger()) return false;5152*face->logger() << json::array;53#ifdef GRAPHITE2_TELEMETRY54*face->logger() << face->tele;55#endif56}57else58{59global_log = new json(log);60*global_log << json::array;61}6263return true;64#else // GRAPHITE2_NTRACING65return false;66#endif // GRAPHITE2_NTRACING67}6869bool graphite_start_logging(FILE * /* log */, GrLogMask /* mask */)70{71//#if !defined GRAPHITE2_NTRACING72// graphite_stop_logging();73//74// if (!log) return false;75//76// dbgout = new json(log);77// if (!dbgout) return false;78//79// *dbgout << json::array;80// return true;81//#else82return false;83//#endif84}8586void gr_stop_logging(GR_MAYBE_UNUSED gr_face * face)87{88#if !defined GRAPHITE2_NTRACING89if (face && face->logger())90{91FILE * log = face->logger()->stream();92face->setLogger(0);93fclose(log);94}95else if (!face && global_log)96{97FILE * log = global_log->stream();98delete global_log;99global_log = 0;100fclose(log);101}102#endif103}104105void graphite_stop_logging()106{107// if (dbgout) delete dbgout;108// dbgout = 0;109}110111} // extern "C"112113#ifdef GRAPHITE2_TELEMETRY114size_t * graphite2::telemetry::_category = 0UL;115#endif116117#if !defined GRAPHITE2_NTRACING118119#ifdef GRAPHITE2_TELEMETRY120121json & graphite2::operator << (json & j, const telemetry & t) throw()122{123j << json::object124<< "type" << "telemetry"125<< "silf" << t.silf126<< "states" << t.states127<< "starts" << t.starts128<< "transitions" << t.transitions129<< "glyphs" << t.glyph130<< "code" << t.code131<< "misc" << t.misc132<< "total" << (t.silf + t.states + t.starts + t.transitions + t.glyph + t.code + t.misc)133<< json::close;134return j;135}136#else137json & graphite2::operator << (json & j, const telemetry &) throw()138{139return j;140}141#endif142143144json & graphite2::operator << (json & j, const CharInfo & ci) throw()145{146return j << json::object147<< "offset" << ci.base()148<< "unicode" << ci.unicodeChar()149<< "break" << ci.breakWeight()150<< "flags" << ci.flags()151<< "slot" << json::flat << json::object152<< "before" << ci.before()153<< "after" << ci.after()154<< json::close155<< json::close;156}157158159json & graphite2::operator << (json & j, const dslot & ds) throw()160{161assert(ds.first);162assert(ds.second);163const Segment & seg = *ds.first;164const Slot & s = *ds.second;165const SlotCollision *cslot = seg.collisionInfo(ds.second);166167j << json::object168<< "id" << objectid(ds)169<< "gid" << s.gid()170<< "charinfo" << json::flat << json::object171<< "original" << s.original()172<< "before" << s.before()173<< "after" << s.after()174<< json::close175<< "origin" << s.origin()176<< "shift" << Position(float(s.getAttr(0, gr_slatShiftX, 0)),177float(s.getAttr(0, gr_slatShiftY, 0)))178<< "advance" << s.advancePos()179<< "insert" << s.isInsertBefore()180<< "break" << s.getAttr(&seg, gr_slatBreak, 0);181if (s.just() > 0)182j << "justification" << s.just();183if (s.getBidiLevel() > 0)184j << "bidi" << s.getBidiLevel();185if (!s.isBase())186j << "parent" << json::flat << json::object187<< "id" << objectid(dslot(&seg, s.attachedTo()))188<< "level" << s.getAttr(0, gr_slatAttLevel, 0)189<< "offset" << s.attachOffset()190<< json::close;191j << "user" << json::flat << json::array;192for (int n = 0; n!= seg.numAttrs(); ++n)193j << s.userAttrs()[n];194j << json::close;195if (s.firstChild())196{197j << "children" << json::flat << json::array;198for (const Slot *c = s.firstChild(); c; c = c->nextSibling())199j << objectid(dslot(&seg, c));200j << json::close;201}202if (cslot)203{204// Note: the reason for using Positions to lump together related attributes is to make the205// JSON output slightly more compact.206j << "collision" << json::flat << json::object207// << "shift" << cslot->shift() -- not used pass level, only within the collision routine itself208<< "offset" << cslot->offset()209<< "limit" << cslot->limit()210<< "flags" << cslot->flags()211<< "margin" << Position(cslot->margin(), cslot->marginWt())212<< "exclude" << cslot->exclGlyph()213<< "excludeoffset" << cslot->exclOffset();214if (cslot->seqOrder() != 0)215{216j << "seqclass" << Position(cslot->seqClass(), cslot->seqProxClass())217<< "seqorder" << cslot->seqOrder()218<< "seqabove" << Position(cslot->seqAboveXoff(), cslot->seqAboveWt())219<< "seqbelow" << Position(cslot->seqBelowXlim(), cslot->seqBelowWt())220<< "seqvalign" << Position(cslot->seqValignHt(), cslot->seqValignWt());221}222j << json::close;223}224return j << json::close;225}226227228graphite2::objectid::objectid(const dslot & ds) throw()229{230const Slot * const p = ds.second;231uint32 s = uint32(reinterpret_cast<size_t>(p));232sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), uint16(p ? p->userAttrs()[ds.first->silf()->numUser()] : 0), uint16(s));233name[sizeof name-1] = 0;234}235236graphite2::objectid::objectid(const Segment * const p) throw()237{238uint32 s = uint32(reinterpret_cast<size_t>(p));239sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), 0, uint16(s));240name[sizeof name-1] = 0;241}242243#endif244245246