godot/thirdparty/graphite/src/gr_logging.cpp

// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.

#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

usingnamespacegraphite2;

#if !defined GRAPHITE2_NTRACING
json *global_log = 0;
#endif

extern "C" {

bool gr_start_logging(GR_MAYBE_UNUSED gr_face * face, const char *log_path)
{}

bool graphite_start_logging(FILE * /* log */, GrLogMask /* mask */)
{}

void gr_stop_logging(GR_MAYBE_UNUSED gr_face * face)
{}

void graphite_stop_logging()
{}

} // 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 = uint32(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 = uint32(reinterpret_cast<size_t>(p));
    sprintf(name, "%.4x-%.2x-%.4hx", uint16(s >> 16), 0, uint16(s));
    name[sizeof name-1] = 0;
}

#endif