blob: 4ac7ca09fb842169a5f316ce1e34c9ee471dcc72 [file]
#ifdef WITH_RIVE_SCRIPTING
// The LuaAtoms name table and lookup, shared by the native runtime and the
// wasm script module build; both install it as the state's useratom callback
// so namecall dispatch and direct field getters agree everywhere.
#include "rive/lua/rive_lua_libs.hpp"
#include <array>
#include <string_view>
using namespace rive;
namespace
{
struct LuaAtomName
{
std::string_view name;
int16_t atom;
};
constexpr LuaAtomName atoms[] = {
{"length", (int16_t)LuaAtoms::length},
{"lengthSquared", (int16_t)LuaAtoms::lengthSquared},
{"normalized", (int16_t)LuaAtoms::normalized},
{"distance", (int16_t)LuaAtoms::distance},
{"distanceSquared", (int16_t)LuaAtoms::distanceSquared},
{"dot", (int16_t)LuaAtoms::dot},
{"lerp", (int16_t)LuaAtoms::lerp},
{"moveTo", (int16_t)LuaAtoms::moveTo},
{"lineTo", (int16_t)LuaAtoms::lineTo},
{"quadTo", (int16_t)LuaAtoms::quadTo},
{"cubicTo", (int16_t)LuaAtoms::cubicTo},
{"close", (int16_t)LuaAtoms::close},
{"type", (int16_t)LuaAtoms::type},
{"reset", (int16_t)LuaAtoms::reset},
{"add", (int16_t)LuaAtoms::add},
{"contours", (int16_t)LuaAtoms::contours},
{"measure", (int16_t)LuaAtoms::measure},
{"invert", (int16_t)LuaAtoms::invert},
{"isIdentity", (int16_t)LuaAtoms::isIdentity},
{"width", (int16_t)LuaAtoms::width},
{"height", (int16_t)LuaAtoms::height},
{"clamp", (int16_t)LuaAtoms::clamp},
{"repeat", (int16_t)LuaAtoms::repeat},
{"mirror", (int16_t)LuaAtoms::mirror},
{"bilinear", (int16_t)LuaAtoms::bilinear},
{"nearest", (int16_t)LuaAtoms::nearest},
{"style", (int16_t)LuaAtoms::style},
{"join", (int16_t)LuaAtoms::join},
{"cap", (int16_t)LuaAtoms::cap},
{"thickness", (int16_t)LuaAtoms::thickness},
{"blendMode", (int16_t)LuaAtoms::blendMode},
{"feather", (int16_t)LuaAtoms::feather},
{"gradient", (int16_t)LuaAtoms::gradient},
{"color", (int16_t)LuaAtoms::color},
{"stroke", (int16_t)LuaAtoms::stroke},
{"fill", (int16_t)LuaAtoms::fill},
{"miter", (int16_t)LuaAtoms::miter},
{"round", (int16_t)LuaAtoms::round},
{"bevel", (int16_t)LuaAtoms::bevel},
{"butt", (int16_t)LuaAtoms::butt},
{"square", (int16_t)LuaAtoms::square},
{"srcOver", (int16_t)LuaAtoms::srcOver},
{"screen", (int16_t)LuaAtoms::screen},
{"overlay", (int16_t)LuaAtoms::overlay},
{"darken", (int16_t)LuaAtoms::darken},
{"lighten", (int16_t)LuaAtoms::lighten},
{"colorDodge", (int16_t)LuaAtoms::colorDodge},
{"colorBurn", (int16_t)LuaAtoms::colorBurn},
{"hardLight", (int16_t)LuaAtoms::hardLight},
{"softLight", (int16_t)LuaAtoms::softLight},
{"difference", (int16_t)LuaAtoms::difference},
{"exclusion", (int16_t)LuaAtoms::exclusion},
{"multiply", (int16_t)LuaAtoms::multiply},
{"hue", (int16_t)LuaAtoms::hue},
{"saturation", (int16_t)LuaAtoms::saturation},
{"luminosity", (int16_t)LuaAtoms::luminosity},
{"copy", (int16_t)LuaAtoms::copy},
{"drawPath", (int16_t)LuaAtoms::drawPath},
{"drawImage", (int16_t)LuaAtoms::drawImage},
{"drawImageMesh", (int16_t)LuaAtoms::drawImageMesh},
{"clipPath", (int16_t)LuaAtoms::clipPath},
{"save", (int16_t)LuaAtoms::save},
{"restore", (int16_t)LuaAtoms::restore},
{"transform", (int16_t)LuaAtoms::transform},
{"value", (int16_t)LuaAtoms::value},
{"red", (int16_t)LuaAtoms::red},
{"green", (int16_t)LuaAtoms::green},
{"blue", (int16_t)LuaAtoms::blue},
{"alpha", (int16_t)LuaAtoms::alpha},
{"getNumber", (int16_t)LuaAtoms::getNumber},
{"getTrigger", (int16_t)LuaAtoms::getTrigger},
{"getString", (int16_t)LuaAtoms::getString},
{"getBoolean", (int16_t)LuaAtoms::getBoolean},
{"getColor", (int16_t)LuaAtoms::getColor},
{"getList", (int16_t)LuaAtoms::getList},
{"getViewModel", (int16_t)LuaAtoms::getViewModel},
{"getEnum", (int16_t)LuaAtoms::getEnum},
{"getIndex", (int16_t)LuaAtoms::getIndex},
{"getImage", (int16_t)LuaAtoms::getImage},
{"getFont", (int16_t)LuaAtoms::getFont},
{"getBlob", (int16_t)LuaAtoms::getBlob},
{"values", (int16_t)LuaAtoms::values},
{"addListener", (int16_t)LuaAtoms::addListener},
{"removeListener", (int16_t)LuaAtoms::removeListener},
{"fire", (int16_t)LuaAtoms::fire},
{"push", (int16_t)LuaAtoms::push},
{"insert", (int16_t)LuaAtoms::insert},
{"pop", (int16_t)LuaAtoms::pop},
{"swap", (int16_t)LuaAtoms::swap},
{"shift", (int16_t)LuaAtoms::shift},
{"clear", (int16_t)LuaAtoms::clear},
{"draw", (int16_t)LuaAtoms::draw},
{"advance", (int16_t)LuaAtoms::advance},
{"frameOrigin", (int16_t)LuaAtoms::frameOrigin},
{"data", (int16_t)LuaAtoms::data},
{"instance", (int16_t)LuaAtoms::instance},
{"animation", (int16_t)LuaAtoms::animation},
{"new", (int16_t)LuaAtoms::newAtom},
{"bounds", (int16_t)LuaAtoms::bounds},
{"pointerDown", (int16_t)LuaAtoms::pointerDown},
{"pointerUp", (int16_t)LuaAtoms::pointerUp},
{"pointerMove", (int16_t)LuaAtoms::pointerMove},
{"pointerExit", (int16_t)LuaAtoms::pointerExit},
{"isNumber", (int16_t)LuaAtoms::isNumber},
{"isString", (int16_t)LuaAtoms::isString},
{"isBoolean", (int16_t)LuaAtoms::isBoolean},
{"isColor", (int16_t)LuaAtoms::isColor},
{"hit", (int16_t)LuaAtoms::hit},
{"id", (int16_t)LuaAtoms::id},
{"position", (int16_t)LuaAtoms::position},
{"rotation", (int16_t)LuaAtoms::rotation},
{"scale", (int16_t)LuaAtoms::scale},
{"worldTransform", (int16_t)LuaAtoms::worldTransform},
{"scaleX", (int16_t)LuaAtoms::scaleX},
{"scaleY", (int16_t)LuaAtoms::scaleY},
{"decompose", (int16_t)LuaAtoms::decompose},
{"children", (int16_t)LuaAtoms::children},
{"parent", (int16_t)LuaAtoms::parent},
{"node", (int16_t)LuaAtoms::node},
{"paint", (int16_t)LuaAtoms::paint},
{"asPath", (int16_t)LuaAtoms::asPath},
{"asPaint", (int16_t)LuaAtoms::asPaint},
{"addToPath", (int16_t)LuaAtoms::addToPath},
{"positionAndTangent", (int16_t)LuaAtoms::positionAndTangent},
{"warp", (int16_t)LuaAtoms::warp},
{"extract", (int16_t)LuaAtoms::extract},
{"next", (int16_t)LuaAtoms::next},
{"isClosed", (int16_t)LuaAtoms::isClosed},
{"markNeedsUpdate", (int16_t)LuaAtoms::markNeedsUpdate},
{"viewModel", (int16_t)LuaAtoms::viewModel},
{"rootViewModel", (int16_t)LuaAtoms::rootViewModel},
{"globalViewModel", (int16_t)LuaAtoms::globalViewModel},
{"globalViewModelNames", (int16_t)LuaAtoms::globalViewModelNames},
{"dataContext", (int16_t)LuaAtoms::dataContext},
{"image", (int16_t)LuaAtoms::image},
{"blob", (int16_t)LuaAtoms::blob},
{"size", (int16_t)LuaAtoms::size},
{"name", (int16_t)LuaAtoms::name},
{"duration", (int16_t)LuaAtoms::duration},
{"setTime", (int16_t)LuaAtoms::setTime},
{"setTimeFrames", (int16_t)LuaAtoms::setTimeFrames},
{"setTimePercentage", (int16_t)LuaAtoms::setTimePercentage},
{"isPointerEvent", (int16_t)LuaAtoms::isPointerEvent},
{"isKeyboardEvent", (int16_t)LuaAtoms::isKeyboardEvent},
{"isTextInput", (int16_t)LuaAtoms::isTextInput},
{"previousPosition", (int16_t)LuaAtoms::previousPosition},
{"timeStamp", (int16_t)LuaAtoms::timeStamp},
{"isFocus", (int16_t)LuaAtoms::isFocus},
{"isReportedEvent", (int16_t)LuaAtoms::isReportedEvent},
{"isViewModelChange", (int16_t)LuaAtoms::isViewModelChange},
{"isNone", (int16_t)LuaAtoms::isNone},
{"isGamepadConnected", (int16_t)LuaAtoms::isGamepadConnected},
{"isGamepadEvent", (int16_t)LuaAtoms::isGamepadEvent},
{"isGamepadDisconnected", (int16_t)LuaAtoms::isGamepadDisconnected},
{"asPointerEvent", (int16_t)LuaAtoms::asPointerEvent},
{"asKeyboardEvent", (int16_t)LuaAtoms::asKeyboardEvent},
{"asTextInput", (int16_t)LuaAtoms::asTextInput},
{"asFocus", (int16_t)LuaAtoms::asFocus},
{"asReportedEvent", (int16_t)LuaAtoms::asReportedEvent},
{"asViewModelChange", (int16_t)LuaAtoms::asViewModelChange},
{"asGamepadConnected", (int16_t)LuaAtoms::asGamepadConnected},
{"asGamepadEvent", (int16_t)LuaAtoms::asGamepadEvent},
{"asGamepadDisconnected", (int16_t)LuaAtoms::asGamepadDisconnected},
{"gamepadEvent", (int16_t)LuaAtoms::gamepadEvent},
{"gamepadConnected", (int16_t)LuaAtoms::gamepadConnected},
{"gamepadDisconnected", (int16_t)LuaAtoms::gamepadDisconnected},
{"asNone", (int16_t)LuaAtoms::asNone},
{"key", (int16_t)LuaAtoms::key},
{"shift", (int16_t)LuaAtoms::shift},
{"alt", (int16_t)LuaAtoms::alt},
{"control", (int16_t)LuaAtoms::control},
{"meta", (int16_t)LuaAtoms::meta},
{"text", (int16_t)LuaAtoms::text},
{"phase", (int16_t)LuaAtoms::phase},
{"delaySeconds", (int16_t)LuaAtoms::delaySeconds},
{"deviceId", (int16_t)LuaAtoms::deviceId},
{"buttonMask", (int16_t)LuaAtoms::buttonMask},
{"remove", (int16_t)LuaAtoms::remove},
{"removeAt", (int16_t)LuaAtoms::removeAt},
{"removeAllOf", (int16_t)LuaAtoms::removeAllOf},
{"axes", (int16_t)LuaAtoms::axes},
{"gamepadMapping", (int16_t)LuaAtoms::gamepadMapping},
{"mapping", (int16_t)LuaAtoms::mapping},
{"isStandardMapping", (int16_t)LuaAtoms::isStandardMapping},
{"buttons", (int16_t)LuaAtoms::buttons},
{"buttonPressed", (int16_t)LuaAtoms::buttonPressed},
{"buttonValue", (int16_t)LuaAtoms::buttonValue},
{"axis", (int16_t)LuaAtoms::axis},
{"west", (int16_t)LuaAtoms::west},
{"south", (int16_t)LuaAtoms::south},
{"north", (int16_t)LuaAtoms::north},
{"east", (int16_t)LuaAtoms::east},
{"leftShoulder", (int16_t)LuaAtoms::leftShoulder},
{"rightShoulder", (int16_t)LuaAtoms::rightShoulder},
{"back", (int16_t)LuaAtoms::gamepadBack},
{"forward", (int16_t)LuaAtoms::gamepadForward},
{"leftStickButton", (int16_t)LuaAtoms::leftStickButton},
{"rightStickButton", (int16_t)LuaAtoms::rightStickButton},
{"dpadUp", (int16_t)LuaAtoms::dpadUp},
{"dpadDown", (int16_t)LuaAtoms::dpadDown},
{"dpadLeft", (int16_t)LuaAtoms::dpadLeft},
{"dpadRight", (int16_t)LuaAtoms::dpadRight},
{"start", (int16_t)LuaAtoms::start},
{"leftStick", (int16_t)LuaAtoms::leftStick},
{"rightStick", (int16_t)LuaAtoms::rightStick},
{"leftTrigger", (int16_t)LuaAtoms::leftTrigger},
{"rightTrigger", (int16_t)LuaAtoms::rightTrigger},
{"leftTriggerPressed", (int16_t)LuaAtoms::leftTriggerPressed},
{"rightTriggerPressed", (int16_t)LuaAtoms::rightTriggerPressed},
{"changeKind", (int16_t)LuaAtoms::changeKind},
{"changeIndex", (int16_t)LuaAtoms::changeIndex},
{"changeValue", (int16_t)LuaAtoms::changeValue},
{"hasStandardButtonIntent", (int16_t)LuaAtoms::hasStandardButtonIntent},
{"hasStandardAxisIntent", (int16_t)LuaAtoms::hasStandardAxisIntent},
{"intentButton", (int16_t)LuaAtoms::intentButton},
{"intentAxis", (int16_t)LuaAtoms::intentAxis},
{"audio", (int16_t)LuaAtoms::audio},
{"play", (int16_t)LuaAtoms::play},
{"playAtTime", (int16_t)LuaAtoms::playAtTime},
{"playInTime", (int16_t)LuaAtoms::playInTime},
{"playAtFrame", (int16_t)LuaAtoms::playAtFrame},
{"playInFrame", (int16_t)LuaAtoms::playInFrame},
{"stop", (int16_t)LuaAtoms::stop},
{"pause", (int16_t)LuaAtoms::pause},
{"resume", (int16_t)LuaAtoms::resume},
{"seek", (int16_t)LuaAtoms::seek},
{"seekFrame", (int16_t)LuaAtoms::seekFrame},
{"volume", (int16_t)LuaAtoms::volume},
{"completed", (int16_t)LuaAtoms::completed},
{"time", (int16_t)LuaAtoms::time},
{"timeFrame", (int16_t)LuaAtoms::timeFrame},
{"sampleRate", (int16_t)LuaAtoms::sampleRate},
// GPU
{"write", (int16_t)LuaAtoms::write},
{"upload", (int16_t)LuaAtoms::upload},
{"view", (int16_t)LuaAtoms::view},
{"setPipeline", (int16_t)LuaAtoms::setPipeline},
{"setVertexBuffer", (int16_t)LuaAtoms::setVertexBuffer},
{"setIndexBuffer", (int16_t)LuaAtoms::setIndexBuffer},
{"setBindGroup", (int16_t)LuaAtoms::setBindGroup},
{"setViewport", (int16_t)LuaAtoms::setViewport},
{"setScissorRect", (int16_t)LuaAtoms::setScissorRect},
{"setStencilReference", (int16_t)LuaAtoms::setStencilReference},
{"drawIndexed", (int16_t)LuaAtoms::drawIndexed},
{"finish", (int16_t)LuaAtoms::finish},
{"beginRenderPass", (int16_t)LuaAtoms::beginRenderPass},
{"beginFrame", (int16_t)LuaAtoms::beginFrame},
{"endFrame", (int16_t)LuaAtoms::endFrame},
{"colorView", (int16_t)LuaAtoms::colorView},
{"depthView", (int16_t)LuaAtoms::depthView},
{"setBlendColor", (int16_t)LuaAtoms::setBlendColor},
{"resize", (int16_t)LuaAtoms::resize},
{"canvas", (int16_t)LuaAtoms::canvas},
{"gpuCanvas", (int16_t)LuaAtoms::gpuCanvas},
{"features", (int16_t)LuaAtoms::features},
{"shader", (int16_t)LuaAtoms::shader},
{"format", (int16_t)LuaAtoms::format},
{"andThen", (int16_t)LuaAtoms::andThen},
{"catch", (int16_t)LuaAtoms::catch_},
{"finally", (int16_t)LuaAtoms::finally_},
{"cancel", (int16_t)LuaAtoms::cancel},
{"onCancel", (int16_t)LuaAtoms::onCancel},
{"getStatus", (int16_t)LuaAtoms::getStatus},
{"decodeImage", (int16_t)LuaAtoms::decodeImage},
// Mat4
{"transpose", (int16_t)LuaAtoms::transpose},
{"transformPoint", (int16_t)LuaAtoms::transformPoint},
{"transformVec4", (int16_t)LuaAtoms::transformVec4},
{"writeToBuffer", (int16_t)LuaAtoms::writeToBuffer},
{"invertAffine", (int16_t)LuaAtoms::invertAffine},
// Vector
{"writeVec4", (int16_t)LuaAtoms::writeVec4},
};
constexpr size_t atomCount = std::size(atoms);
// Power of two so the modulo is a mask, and roomy enough to keep probes short.
constexpr size_t atomSlotCount = 1024;
static_assert(atomCount < atomSlotCount,
"atomSlotCount must exceed the number of atoms");
constexpr uint32_t hashAtomName(std::string_view name)
{
uint32_t hash = 2166136261u;
for (char c : name)
{
hash = (hash ^ (uint8_t)c) * 16777619u;
}
return hash;
}
constexpr size_t longestAtomName()
{
size_t longest = 0;
for (const LuaAtomName& entry : atoms)
{
if (entry.name.size() > longest)
{
longest = entry.name.size();
}
}
return longest;
}
constexpr size_t maxAtomNameLength = longestAtomName();
// Slots hold an index into atoms biased by one so zero reads as empty.
constexpr std::array<uint16_t, atomSlotCount> buildAtomSlots()
{
std::array<uint16_t, atomSlotCount> slots{};
for (size_t i = 0; i < atomCount; i++)
{
size_t slot = hashAtomName(atoms[i].name) & (atomSlotCount - 1);
while (slots[slot] != 0 && atoms[slots[slot] - 1].name != atoms[i].name)
{
slot = (slot + 1) & (atomSlotCount - 1);
}
if (slots[slot] == 0)
{
slots[slot] = (uint16_t)(i + 1);
}
}
return slots;
}
constexpr std::array<uint16_t, atomSlotCount> atomSlots = buildAtomSlots();
int16_t findAtom(const char* chars, size_t length)
{
if (length > maxAtomNameLength)
{
return -1;
}
std::string_view name(chars, length);
size_t slot = hashAtomName(name) & (atomSlotCount - 1);
for (uint16_t index = atomSlots[slot]; index != 0;
index = atomSlots[slot = (slot + 1) & (atomSlotCount - 1)])
{
if (atoms[index - 1].name == name)
{
return atoms[index - 1].atom;
}
}
return -1;
}
} // namespace
namespace rive
{
int16_t rive_lua_findAtom(const char* chars, size_t length)
{
return findAtom(chars, length);
}
} // namespace rive
#endif