diff --git a/examples/23-vectordisplay/fs_vectordisplay_blit.sc b/examples/23-vectordisplay/fs_vectordisplay_blit.sc new file mode 100644 index 00000000..62bc3995 --- /dev/null +++ b/examples/23-vectordisplay/fs_vectordisplay_blit.sc @@ -0,0 +1,13 @@ +$input v_color0, v_texcoord0 + +#include + +SAMPLER2D(s_textureSampler, 0); + +uniform float u_compose_alpha; +uniform float u_compose_mult; + +void main() { + gl_FragColor = texture2D(s_textureSampler, v_texcoord0.xy) * + vec4(u_compose_mult, u_compose_mult, u_compose_mult, u_compose_alpha*u_compose_mult); +} diff --git a/examples/23-vectordisplay/fs_vectordisplay_blur.sc b/examples/23-vectordisplay/fs_vectordisplay_blur.sc new file mode 100644 index 00000000..c323bb06 --- /dev/null +++ b/examples/23-vectordisplay/fs_vectordisplay_blur.sc @@ -0,0 +1,24 @@ +$input v_color0, v_texcoord0 + +#include + +SAMPLER2D(s_textureSampler, 0); + +uniform vec2 u_blur_scale; + +uniform float u_compose_alpha; +uniform float u_compose_mult; + +void main() { + vec4 color = texture2D(s_textureSampler, vec2(v_texcoord0.x-4.0*u_blur_scale.x, v_texcoord0.y-4.0*u_blur_scale.y))*0.05; + color += texture2D(s_textureSampler, vec2(v_texcoord0.x-3.0*u_blur_scale.x, v_texcoord0.y-3.0*u_blur_scale.y))*0.09; + color += texture2D(s_textureSampler, vec2(v_texcoord0.x-2.0*u_blur_scale.x, v_texcoord0.y-2.0*u_blur_scale.y))*0.12; + color += texture2D(s_textureSampler, vec2(v_texcoord0.x-1.0*u_blur_scale.x, v_texcoord0.y-1.0*u_blur_scale.y))*0.15; + color += texture2D(s_textureSampler, vec2(v_texcoord0.x+0.0*u_blur_scale.x, v_texcoord0.y+0.0*u_blur_scale.y))*0.16; + color += texture2D(s_textureSampler, vec2(v_texcoord0.x+1.0*u_blur_scale.x, v_texcoord0.y+1.0*u_blur_scale.y))*0.15; + color += texture2D(s_textureSampler, vec2(v_texcoord0.x+2.0*u_blur_scale.x, v_texcoord0.y+2.0*u_blur_scale.y))*0.12; + color += texture2D(s_textureSampler, vec2(v_texcoord0.x+3.0*u_blur_scale.x, v_texcoord0.y+3.0*u_blur_scale.y))*0.09; + color += texture2D(s_textureSampler, vec2(v_texcoord0.x+4.0*u_blur_scale.x, v_texcoord0.y+4.0*u_blur_scale.y))*0.05; + + gl_FragColor = color * vec4(u_compose_mult, u_compose_mult, u_compose_mult, u_compose_alpha*u_compose_mult); +} diff --git a/examples/23-vectordisplay/fs_vectordisplay_fb.sc b/examples/23-vectordisplay/fs_vectordisplay_fb.sc new file mode 100644 index 00000000..ac3f4b99 --- /dev/null +++ b/examples/23-vectordisplay/fs_vectordisplay_fb.sc @@ -0,0 +1,12 @@ +$input v_color0, v_texcoord0 + +#include + +SAMPLER2D(s_lineTexture, 0); + +uniform float u_compose_alpha; + +void main() { + vec4 texColor = texture2D(s_lineTexture, v_texcoord0.xy); + gl_FragColor = v_color0 * texColor * vec4(1.0, 1.0, 1.0, u_compose_alpha); +} diff --git a/examples/23-vectordisplay/main.cpp b/examples/23-vectordisplay/main.cpp new file mode 100644 index 00000000..f5d4da71 --- /dev/null +++ b/examples/23-vectordisplay/main.cpp @@ -0,0 +1,171 @@ +/* + * Copyright 2014 Kai Jourdan. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + * + */ + +#include "common.h" +#include "bgfx_utils.h" + +#include "vectordisplay.h" + +struct PosColorVertex +{ + float m_x; + float m_y; + float m_z; + uint32_t m_abgr; + + static void init() + { + ms_decl + .begin() + .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) + .end(); + } + + static bgfx::VertexDecl ms_decl; +}; + +bgfx::VertexDecl PosColorVertex::ms_decl; + +int _main_(int /*_argc*/, char** /*_argv*/) +{ + uint32_t width = 1280; + uint32_t height = 720; + uint32_t debug = BGFX_DEBUG_TEXT; + uint32_t reset = BGFX_RESET_VSYNC; + + bgfx::init(); + bgfx::reset(width, height, reset); + + const bgfx::RendererType::Enum renderer = bgfx::getRendererType(); + float texelHalf = bgfx::RendererType::Direct3D9 == renderer ? 0.5f : 0.0f; + bool originBottomLeft = bgfx::RendererType::OpenGL == renderer + || bgfx::RendererType::OpenGLES == renderer; + VectorDisplay vectorDisplay(originBottomLeft, texelHalf); + vectorDisplay.setup(width, height); + + // Enable debug text. + bgfx::setDebug(debug); + + // Set view 0 clear state. + bgfx::setViewClear(0, BGFX_CLEAR_COLOR_BIT | BGFX_CLEAR_DEPTH_BIT, 0x303030ff, 1.0f, 0); + + // Create vertex stream declaration. + PosColorVertex::init(); + + float at[3] = { 0.0f, 0.0f, 0.0f }; + float eye[3] = { 0.0f, 0.0f, -35.0f }; + + uint32_t oldWidth = width; + uint32_t oldHeight = height; + + while (!entry::processEvents(width, height, debug, reset) ) + { + if ( (oldWidth != width) + || (oldHeight != height) ) + { + oldWidth = width; + oldHeight = height; + vectorDisplay.resize(width, height); + } + + float view[16]; + float proj[16]; + bx::mtxLookAt(view, eye, at); + bx::mtxProj(proj, 60.0f, float(width) / float(height), 0.1f, 100.0f); + // Set view and projection matrix for view 0. + bgfx::setViewTransform(0, view, proj); + + // Set view 0 default viewport. + bgfx::setViewRect(0, 0, 0, width, height); + + // This dummy draw call is here to make sure that view 0 is cleared + // if no other draw calls are submitted to view 0. + bgfx::submit(0); + + int64_t now = bx::getHPCounter(); + static int64_t last = now; + const int64_t frameTime = now - last; + last = now; + const double freq = double(bx::getHPFrequency() ); + const double toMs = 1000.0 / freq; + + // Use debug font to print information about this example. + bgfx::dbgTextClear(); + bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/23-vectordisplay"); + bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Rendering lines as oldschool vectors."); + bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime) * toMs); + + vectorDisplay.beginFrame(); + + //simplex test + vectorDisplay.setDrawColor(0.7f, 0.7f, 1.0f); + vectorDisplay.drawSimplexFont(50, 80, 1.5, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + vectorDisplay.drawSimplexFont(50, 140, 1.5, "abcdefghijklmnopqrstuvwxyz"); + vectorDisplay.drawSimplexFont(50, 200, 1.5, "!@#$%^&*()-=<>/?;:'\"{}[]|\\+=-_"); + + vectorDisplay.setDrawColor(1.0f, 0.7f, 0.7f); + + //test pattern for lines + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < i; j++) //draw more intensive lines + { + vectorDisplay.drawLine(50.0f, 350.0f + 40 * i, 200.0f, 350.0f + 40 * i); + } + } + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j <= i; j++) + { + vectorDisplay.drawLine(50.0f + 40 * i, 600.0f, 50.0f + 40 * i, 700.0f); + } + } + + // + // test pattern for shapes + // + vectorDisplay.setDrawColor(0.7f, 0.7f, 1.0f); + vectorDisplay.drawCircle(250, 450, 10, 32); + vectorDisplay.drawCircle(300, 450, 30, 32); + vectorDisplay.drawCircle(400, 450, 60, 32); + vectorDisplay.drawCircle(500, 450, 80, 64); + + vectorDisplay.setDrawColor(0.7f, 1.0f, 0.7f); + vectorDisplay.drawBox(250, 600, 10, 10); + vectorDisplay.drawBox(300, 600, 30, 30); + vectorDisplay.drawBox(350, 600, 60, 60); + vectorDisplay.drawBox(450, 600, 80, 80); + + vectorDisplay.setDrawColor(1.0f, 0.7f, 1.0f); + vectorDisplay.drawWheel(bx::pi, 800, 450, 80); + vectorDisplay.drawWheel(3 * bx::pi / 4, 950, 450, 60); + vectorDisplay.drawWheel(bx::pi / 2, 1150, 450, 30); + vectorDisplay.drawWheel(bx::pi / 4, 1250, 450, 10); + + // draw moving shape + static float counter = 0.0f; + counter += 0.01f; + float posX = width / 2 + sin(counter * 3.18378f) * (width / 2); + float posY = height / 2 + cos(counter) * (height / 2); + vectorDisplay.drawCircle(posX, posY, 5, 10); + + vectorDisplay.endFrame(); + + // Advance to next frame. Rendering thread will be kicked to + // process submitted rendering primitives. + bgfx::frame(); + } + + // Cleanup. + vectorDisplay.teardown(); + + // Shutdown bgfx. + bgfx::shutdown(); + + return 0; +} diff --git a/examples/23-vectordisplay/makefile b/examples/23-vectordisplay/makefile new file mode 100644 index 00000000..5ce06621 --- /dev/null +++ b/examples/23-vectordisplay/makefile @@ -0,0 +1,17 @@ +# +# Copyright 2011-2014 Branimir Karadzic. All rights reserved. +# License: http://www.opensource.org/licenses/BSD-2-Clause +# + +BGFX_DIR=../.. +RUNTIME_DIR=$(BGFX_DIR)/examples/runtime +BUILD_DIR=../../.build + +include $(BGFX_DIR)/scripts/shader.mk + +rebuild: + @make -s --no-print-directory TARGET=0 clean all + @make -s --no-print-directory TARGET=1 clean all + @make -s --no-print-directory TARGET=2 clean all + @make -s --no-print-directory TARGET=3 clean all + @make -s --no-print-directory TARGET=4 clean all diff --git a/examples/23-vectordisplay/varying.def.sc b/examples/23-vectordisplay/varying.def.sc new file mode 100644 index 00000000..d26eb5ad --- /dev/null +++ b/examples/23-vectordisplay/varying.def.sc @@ -0,0 +1,6 @@ +vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0); +vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0); + +vec3 a_position : POSITION; +vec2 a_texcoord0 : TEXCOORD0; +vec4 a_color0 : COLOR0; diff --git a/examples/23-vectordisplay/vectordisplay.cpp b/examples/23-vectordisplay/vectordisplay.cpp new file mode 100644 index 00000000..1d1577ca --- /dev/null +++ b/examples/23-vectordisplay/vectordisplay.cpp @@ -0,0 +1,1529 @@ + +/* + * Copyright 2014 Kai Jourdan. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + * + * based on code from Brian Luczkiewicz + * https://github.com/blucz/Vector + * + * uses the SIMPLEX-Font which is a variant of the Hershey font (public domain) + * http://paulbourke.net/dataformats/hershey/ + */ + +#include "vectordisplay.h" + +#include "bgfx_utils.h" + +#define _USE_MATH_DEFINES +#include +#include +#include +#include + +#include + +//Config stuff +const int MAX_NUMBER_VERTICES = 20000; + +const int MAX_DECAY_STEPS = 60; +const int DEFAULT_DECAY_STEPS = 5; +const float DEFAULT_DECAY_VALUE = 0.8f; +const float DEFAULT_INITIAL_DECAY = 0.04f; +const float DEFAULT_DRAW_OFFSET_X = 0.0f; +const float DEFAULT_DRAW_OFFSET_Y = 0.0f; +const float DEFAULT_DRAW_SCALE = 1.0f; +const float DEFAULT_BRIGHTNESS = 1.0f; + +//internal config +const int TEXTURE_SIZE = 64; +const int HALF_TEXTURE_SIZE = TEXTURE_SIZE / 2; + +#define MIN(x, y) ( (x) < (y) ? (x) : (y) ) +#define MAX(x, y) ( (x) > (y) ? (x) : (y) ) + +struct PosColorUvVertex +{ + float m_x; + float m_y; + float m_z; + float m_u; + float m_v; + uint32_t m_abgr; + static void init() + { + ms_decl + .begin() + .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float) + .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) + .end(); + } + static bgfx::VertexDecl ms_decl; +}; +bgfx::VertexDecl PosColorUvVertex::ms_decl; + +VectorDisplay::VectorDisplay(bool _originBottomLeft, float _texelHalf) + : m_originBottomLeft(_originBottomLeft) + , m_texelHalf(_texelHalf) +{ +} + +void VectorDisplay::setup(uint16_t _width, uint16_t _height, int _view) +{ + PosColorUvVertex::init(); + + m_decayValue = DEFAULT_DECAY_VALUE; + setDrawColor(1.0f, 1.0f, 1.0f, 1.0f); + + m_screenWidth = _width; + m_screenHeight = _height; + m_glowWidth = m_screenWidth / 3; + m_glowHeight = m_screenHeight / 3; + m_initialDecay = DEFAULT_INITIAL_DECAY; + + m_drawOffsetX = DEFAULT_DRAW_OFFSET_X; + m_drawOffsetY = DEFAULT_DRAW_OFFSET_Y; + m_drawScale = DEFAULT_DRAW_SCALE; + m_brightness = DEFAULT_BRIGHTNESS; + + m_currentDrawStep = 0; + + setDefaultThickness(); + + setDecaySteps(DEFAULT_DECAY_STEPS); + + m_view = _view; + + m_drawToScreenShader = loadProgram("vs_vectordisplay_fb", "fs_vectordisplay_fb"); + u_compose_alpha = bgfx::createUniform("u_compose_alpha", bgfx::UniformType::Uniform1f); + + m_blurShader = loadProgram("vs_vectordisplay_fb", "fs_vectordisplay_blur"); + u_blur_scale = bgfx::createUniform("u_blur_scale", bgfx::UniformType::Uniform2fv); + u_compose_mult = bgfx::createUniform("u_compose_mult", bgfx::UniformType::Uniform1f); + + m_blitShader = loadProgram("vs_vectordisplay_fb", "fs_vectordisplay_blit"); + + //generate uniforms for sampler + s_textureSampler = bgfx::createUniform("u_tex1", bgfx::UniformType::Uniform1iv); + + genLinetex(); + + bgfx::setViewClear(_view, BGFX_CLEAR_COLOR_BIT | BGFX_CLEAR_DEPTH_BIT, 0x000000ff, 1.0f, 0); + + setupResDependent(); +} + +void VectorDisplay::resize(uint16_t _width, uint16_t _height) +{ + teardownResDependent(); + m_screenWidth = _width; + m_screenHeight = _height; + m_glowWidth = _width / 3; + m_glowHeight = _height / 3; + setupResDependent(); +} + +void VectorDisplay::teardown() +{ + teardownResDependent(); + + bgfx::destroyProgram(m_drawToScreenShader); + bgfx::destroyUniform(u_compose_alpha); + bgfx::destroyTexture(m_lineTexId); + bgfx::destroyUniform(s_lineTexture); + + bgfx::destroyProgram(m_blurShader); + bgfx::destroyUniform(u_blur_scale); + bgfx::destroyUniform(u_compose_mult); + + bgfx::destroyUniform(s_textureSampler); + + bgfx::destroyProgram(m_blitShader); +} + +void VectorDisplay::beginFrame() +{ + m_points.clear(); +} + +void VectorDisplay::endFrame() +{ + float proj[16]; + float ident[16]; + bx::mtxIdentity(ident); + + bx::mtxOrtho(proj, 0.0f, (float)m_screenWidth, (float)m_screenHeight, 0.0f, 0.0f, 1000.0f); + + bgfx::setViewRect(m_view, 0, 0, m_screenWidth, m_screenHeight); + bgfx::setViewFrameBuffer(m_view, m_sceneFrameBuffer); //render all geometry to this framebuffer + bgfx::setViewTransform(m_view, NULL, proj); + + // advance step + m_currentDrawStep = (m_currentDrawStep + 1) % m_numberDecaySteps; + + assert(m_points.size() < MAX_NUMBER_VERTICES); + + bgfx::updateDynamicVertexBuffer(m_vertexBuffers[m_currentDrawStep], bgfx::copy(m_points.data(), m_points.size() * sizeof(point_t) ) ); + m_vertexBuffersSize[m_currentDrawStep] = m_points.size(); + + //if the index buffer is cleared from the last "submit"-call everything is fine, but if not + //we clear it here again just to be sure it's not set... (the same for the Transform) + bgfx::IndexBufferHandle ib; + ib.idx = bgfx::invalidHandle; + bgfx::setIndexBuffer(ib); + + bgfx::setTransform(ident); + + for (int loopvar = 0; loopvar < m_numberDecaySteps; loopvar++) + { + int stepi = m_numberDecaySteps - loopvar - 1; + int i = (m_currentDrawStep + m_numberDecaySteps - stepi) % m_numberDecaySteps; + + if (m_vertexBuffersSize[i] != 0) //only draw if something is in the buffer + { + float alpha; + if (stepi == 0) + { + alpha = 1.0f; + } + else if (stepi == 1) + { + alpha = m_initialDecay; + } + else + { + alpha = pow(m_decayValue, stepi - 1) * m_initialDecay; + } + + bgfx::setUniform(u_compose_alpha, &alpha); + + bgfx::setTexture(0, s_lineTexture, m_lineTexId); + bgfx::setProgram(m_drawToScreenShader); + + bgfx::setVertexBuffer(m_vertexBuffers[i], m_vertexBuffersSize[i]); //expicitly feed vertex number! + + bgfx::setState(BGFX_STATE_RGB_WRITE + | BGFX_STATE_ALPHA_WRITE + | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_DST_ALPHA) + | BGFX_STATE_BLEND_EQUATION_SEPARATE(0x0, BGFX_STATE_BLEND_EQUATION_MAX) //0x0 means ADD! + ); + + bgfx::setViewName(m_view, "RenderVectorDisplay"); + bgfx::submit(m_view); + } + } + + int viewCounter = m_view + 1; + + float glow_iter_mult = 1.05f + ( (m_brightness - 1.0f) / 5.0f); + float glow_fin_mult = 1.25f + ( (m_brightness - 1.0f) / 2.0f); + + bx::mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f); + + if (m_brightness > 0) + { + float alpha = 1.0f; + bgfx::setUniform(u_compose_alpha, &alpha); + bgfx::setUniform(u_compose_mult, &glow_iter_mult); + + bgfx::setTexture(0, s_textureSampler, m_sceneFrameBuffer); + + int npasses = (int)(m_brightness * 4); + for (int pass = 0; pass < npasses; pass++) + { + // render the glow1 texture to the glow0 buffer with horizontal blur + + bgfx::setViewFrameBuffer(viewCounter, m_glow0FrameBuffer); //first glow pass + bgfx::setViewRect(viewCounter, 0, 0, m_glowWidth, m_glowHeight); + bgfx::setState(BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE); + float scale[2]; + scale[0] = 1.0f / m_glowWidth; + scale[1] = 0.0f; + bgfx::setUniform(u_blur_scale, &scale); + bgfx::setProgram(m_blurShader); + + bgfx::setViewTransform(viewCounter, NULL, proj); + screenSpaceQuad(m_glowWidth, m_glowHeight); + bgfx::setViewName(viewCounter, "BlendPassA"); + bgfx::submit(viewCounter); + + viewCounter++; + + bgfx::setViewFrameBuffer(viewCounter, m_glow1FrameBuffer); //second glow pass + bgfx::setViewRect(viewCounter, 0, 0, m_glowWidth, m_glowHeight); + bgfx::setTexture(0, s_textureSampler, m_glow0FrameBuffer); + bgfx::setProgram(m_blurShader); + + bgfx::setViewTransform(viewCounter, NULL, proj); + screenSpaceQuad(m_glowWidth, m_glowHeight); + + bgfx::setUniform(u_compose_alpha, &alpha); + bgfx::setUniform(u_compose_mult, &glow_iter_mult); + scale[0] = 0.0f; + scale[1] = 1.0f / m_glowHeight; + bgfx::setUniform(u_blur_scale, &scale); + + bgfx::setState(BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE); + + bgfx::setViewName(viewCounter, "BlendPassB"); + bgfx::submit(viewCounter); + + viewCounter++; + + //set for next iteration + bgfx::setTexture(0, s_textureSampler, m_glow1FrameBuffer); + } + } + + //now do last pass, combination of blur and normal buffer to screen + bgfx::setViewTransform(viewCounter, NULL, proj); + bgfx::setViewRect(viewCounter, 0, 0, m_screenWidth, m_screenHeight); + bgfx::setTexture(0, s_textureSampler, m_sceneFrameBuffer); + bgfx::setProgram(m_blitShader); + bgfx::setState(BGFX_STATE_RGB_WRITE + | BGFX_STATE_ALPHA_WRITE + | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE) + ); + + float tempOne = 1.0f; + bgfx::setUniform(u_compose_alpha, &tempOne); + bgfx::setUniform(u_compose_mult, &tempOne); + bgfx::setViewName(viewCounter, "BlendVectorToDisplay"); + screenSpaceQuad(m_screenWidth, m_screenHeight); + bgfx::submit(viewCounter); + viewCounter++; + + if (m_brightness > 0) + { + // blend in the glow + bgfx::setViewTransform(viewCounter, NULL, proj); + bgfx::setViewRect(viewCounter, 0, 0, m_screenWidth, m_screenHeight); + bgfx::setTexture(0, s_textureSampler, m_glow1FrameBuffer); + bgfx::setProgram(m_blitShader); + bgfx::setState(BGFX_STATE_RGB_WRITE + | BGFX_STATE_ALPHA_WRITE + | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_ONE, BGFX_STATE_BLEND_ONE) + ); + bgfx::setUniform(u_compose_mult, &glow_fin_mult); + bgfx::setViewName(viewCounter, "BlendBlurToDisplay"); + screenSpaceQuad(m_screenWidth, m_screenHeight); + bgfx::submit(viewCounter); + viewCounter++; + } +} + +void VectorDisplay::beginDraw(float _x, float _y) +{ + if (m_pendingPoints.size() != 0) + { + assert(!"begin draw on already filled buffer!"); + } + + pending_point_t point; + point.x = _x * m_drawScale + m_drawOffsetX; + point.y = _y * m_drawScale + m_drawOffsetY; + m_pendingPoints.push_back(point); +} + +void VectorDisplay::drawTo(float _x, float _y) +{ + pending_point_t point; + point.x = _x * m_drawScale + m_drawOffsetX; + point.y = _y * m_drawScale + m_drawOffsetY; + m_pendingPoints.push_back(point); +} + +void VectorDisplay::endDraw() +{ + if (m_pendingPoints.size() < 2) + { + m_pendingPoints.clear(); + return; + } + + // from the list of points, build a list of lines + size_t nlines = m_pendingPoints.size() - 1; + line_t* lines = (line_t*)alloca(nlines * sizeof(line_t) ); + + float t = effectiveThickness(); + int first_last_same = abs(m_pendingPoints[0].x - m_pendingPoints[m_pendingPoints.size() - 1].x) < 0.1 + && abs(m_pendingPoints[0].y - m_pendingPoints[m_pendingPoints.size() - 1].y) < 0.1; + + // compute basics + for (size_t i = 1; i < m_pendingPoints.size(); i++) + { + line_t* line = &lines[i - 1]; + line->is_first = i == 1; + line->is_last = i == nlines; + + // precomputed info for current line + line->x0 = m_pendingPoints[i - 1].x; + line->y0 = m_pendingPoints[i - 1].y; + line->x1 = m_pendingPoints[i].x; + line->y1 = m_pendingPoints[i].y; + line->a = atan2(line->y1 - line->y0, line->x1 - line->x0); // angle from positive x axis, increasing ccw, [-pi, pi] + line->sin_a = sin(line->a); + line->cos_a = cos(line->a); + line->len = sqrt( (line->x1 - line->x0) * (line->x1 - line->x0) + (line->y1 - line->y0) * (line->y1 - line->y0) ); + + // figure out what connections we have + line->has_prev = (!line->is_first + || (line->is_first + && first_last_same) ); + line->has_next = (!line->is_last + || (line->is_last + && first_last_same) ); + + // initialize thicknesses/shortens to default values + line->tl0 = line->tl1 = line->tr0 = line->tr1 = t; + line->s0 = line->s1 = 0.0; + } + + // compute adjustments for connected line segments + for (size_t i = 0; i < nlines; i++) + { + line_t* line = &lines[i], * pline = &lines[(nlines + i - 1) % nlines]; + + if (line->has_prev) + { + float pa2a = normalizef(pline->a - line->a); + float a2pa = normalizef(line->a - pline->a); + float maxshorten = MIN(line->len, pline->len) / 2.0f; + + if (MIN(a2pa, pa2a) <= (M_PI / 2 + FLT_EPSILON) ) + { + if (a2pa < pa2a) + { + float shorten = t * sin(a2pa / 2) / cos(a2pa / 2); + float a = ( (float)M_PI - a2pa) / 2.0f; + if (shorten > maxshorten) + { + line->s0 = pline->s1 = maxshorten; + line->tr0 = pline->tr1 = maxshorten * sin(a) / cos(a); + } + else + { + line->s0 = pline->s1 = shorten; + } + + //vector_display_debugf("ad = %f, shorten by %f (len=%f), rthickness %f (from %f)", a, line->s0, line->len, line->tr0, t); + } + else + { + float shorten = t * sin(pa2a / 2) / cos(pa2a / 2); + float a = ( (float)M_PI - pa2a) / 2.0f; + if (shorten > maxshorten) + { + line->s0 = pline->s1 = maxshorten; + line->tl0 = pline->tl1 = maxshorten * sin(a) / cos(a); + } + else + { + line->s0 = pline->s1 = shorten; + } + + //vector_display_debugf("ad = %f, shorten by %f (len=%f), rthickness by %f (from %f)", a, line->s0, line->len, line->tl0, t); + } + } + else + { + line->has_prev = 0; + } + } + + if (!line->has_prev) + { + pline->has_next = 0; + } + } + + // compute line geometry + for (size_t i = 0; i < nlines; i++) + { + line_t* line = &lines[i]; + + // shorten lines if needed + line->x0 = line->x0 + line->s0 * line->cos_a; + line->y0 = line->y0 + line->s0 * line->sin_a; + line->x1 = line->x1 - line->s1 * line->cos_a; + line->y1 = line->y1 - line->s1 * line->sin_a; + + // compute initial values for left,right,leftcenter,rightcenter points + line->xl0 = line->x0 + line->tl0 * line->sin_a; + line->yl0 = line->y0 - line->tl0 * line->cos_a; + line->xr0 = line->x0 - line->tr0 * line->sin_a; + line->yr0 = line->y0 + line->tr0 * line->cos_a; + line->xl1 = line->x1 + line->tl1 * line->sin_a; + line->yl1 = line->y1 - line->tl1 * line->cos_a; + line->xr1 = line->x1 - line->tr1 * line->sin_a; + line->yr1 = line->y1 + line->tr1 * line->cos_a; + + // compute tips + line->xlt0 = line->xl0 - t * line->cos_a; + line->ylt0 = line->yl0 - t * line->sin_a; + line->xrt0 = line->xr0 - t * line->cos_a; + line->yrt0 = line->yr0 - t * line->sin_a; + line->xlt1 = line->xl1 + t * line->cos_a; + line->ylt1 = line->yl1 + t * line->sin_a; + line->xrt1 = line->xr1 + t * line->cos_a; + line->yrt1 = line->yr1 + t * line->sin_a; + } + + // draw the lines + drawLines(lines, nlines); + m_pendingPoints.clear(); +} + +void VectorDisplay::drawLine(float _x0, float _y0, float _x1, float _y1) +{ + beginDraw(_x0, _y0); + drawTo(_x1, _y1); + endDraw(); +} + +void VectorDisplay::drawBox(float _x, float _y, float _w, float _h) +{ + beginDraw(_x, _y); + drawTo(_x + _w, _y); + drawTo(_x + _w, _y + _h); + drawTo(_x, _y + _h); + drawTo(_x, _y); + endDraw(); +} + +void VectorDisplay::drawCircle(float _x, float _y, float _radius, float _steps) +{ + float edgeangle = 0.0f; + float angadjust = 0.0f; + + float step = (float)M_PI * 2.0f / _steps; + + beginDraw(_x + _radius * sin(edgeangle + angadjust), + _y - _radius * cos(edgeangle + angadjust) ); + for (edgeangle = 0; edgeangle < 2 * M_PI - 0.001; edgeangle += step) + { + drawTo(_x + _radius * sin(edgeangle + step - angadjust), + _y - _radius * cos(edgeangle + step - angadjust) ); + } + + endDraw(); +} + +void VectorDisplay::drawWheel(float _angle, float _x, float _y, float _radius) +{ + float spokeradius = _radius - 2.0f; + // draw spokes + drawLine(_x + spokeradius * sin(_angle), + _y - spokeradius * cos(_angle), + _x - spokeradius * sin(_angle), + _y + spokeradius * cos(_angle) ); + drawLine(_x + spokeradius * sin(_angle + (float)M_PI / 4.0f), + _y - spokeradius * cos(_angle + (float)M_PI / 4.0f), + _x - spokeradius * sin(_angle + (float)M_PI / 4.0f), + _y + spokeradius * cos(_angle + (float)M_PI / 4.0f) ); + drawLine(_x + spokeradius * sin(_angle + (float)M_PI / 2.0f), + _y - spokeradius * cos(_angle + (float)M_PI / 2.0f), + _x - spokeradius * sin(_angle + (float)M_PI / 2.0f), + _y + spokeradius * cos(_angle + (float)M_PI / 2.0f) ); + drawLine(_x + spokeradius * sin(_angle + 3.0f * (float)M_PI / 4.0f), + _y - spokeradius * cos(_angle + 3.0f * (float)M_PI / 4.0f), + _x - spokeradius * sin(_angle + 3.0f * (float)M_PI / 4.0f), + _y + spokeradius * cos(_angle + 3.0f * (float)M_PI / 4.0f) ); + + float edgeangle = 0.0f; + float angadjust = 0.0f; + + beginDraw(_x + _radius * sin(_angle + edgeangle + angadjust), + _y - _radius * cos(_angle + edgeangle + angadjust) ); + for (edgeangle = 0; edgeangle < 2.0f * (float)M_PI - 0.001f; edgeangle += (float)M_PI / 4.0f) + { + drawTo(_x + _radius * sin(_angle + edgeangle + (float)M_PI / 4.0f - angadjust), + _y - _radius * cos(_angle + edgeangle + (float)M_PI / 4.0f - angadjust) ); + } + + endDraw(); +} + +float VectorDisplay::effectiveThickness() +{ + if (m_customThicknessEnabled) + { + return m_thickness * m_drawScale / 2.0f; + } + else + { + // this makes thickness=16 at 2048x1536 + float v = (0.01f * (m_screenWidth + m_screenHeight) / 2.0f) * m_drawScale / 2.0f; + return MAX(v, 6); + } +} + +void VectorDisplay::setTransform(float _offsetX, float _offsetY, float _scale) +{ + m_drawOffsetX = _offsetX; + m_drawOffsetY = _offsetY; + m_drawScale = _scale; +} + +bool VectorDisplay::setInitialDecay(float _initialDecay) +{ + if (_initialDecay < 0.0f + || _initialDecay >= 1.0f) + { + return false; + } + + m_initialDecay = _initialDecay; + return true; +} + +bool VectorDisplay::setThickness(float _thickness) +{ + if (_thickness <= 0) + { + return false; + } + + m_customThicknessEnabled = true; + m_thickness = _thickness; + return true; +} + +void VectorDisplay::setDefaultThickness() +{ + m_customThicknessEnabled = false; +} + +void VectorDisplay::setDrawColor(float _r, float _g, float _b, float _a) +{ + m_drawColorR = (uint8_t)(_r * 255); + m_drawColorG = (uint8_t)(_g * 255); + m_drawColorB = (uint8_t)(_b * 255); + m_drawColorA = (uint8_t)(_a * 255); +} + +void VectorDisplay::appendTexpoint(float _x, float _y, float _u, float _v) +{ + point_t point; + point.x = _x; + point.y = _y; + point.z = 0.0; + point.color = (m_drawColorA << 24) | (m_drawColorB << 16) | (m_drawColorG << 8) | m_drawColorR; + point.u = _u / TEXTURE_SIZE; + point.v = 1.0f - _v / TEXTURE_SIZE; + m_points.push_back(point); +} + +float VectorDisplay::normalizef(float _a) +{ + while (_a > 2.0f * M_PI + FLT_EPSILON) + { + _a -= 2.0f * (float)M_PI; + } + + while (_a < 0.0f - FLT_EPSILON) + { + _a += 2.0f * (float)M_PI; + } + + return _a; +} + +void VectorDisplay::drawFan(float _cx, float _cy, float _pa, float _a, float _t, float _s, float _e) +{ + float* angles; + int nsteps; + float pa2a = normalizef(_a - _pa); + float a2pa = normalizef(_pa - _a); + + int i; + if (a2pa < pa2a) + { + _t = -_t; + nsteps = (int)MAX(1, round(a2pa / (M_PI / 8) ) ); + angles = (float*)alloca(sizeof(float) * (nsteps + 1) ); + for (i = 0; i <= nsteps; i++) + { + angles[i] = _a + i * a2pa / nsteps; + } + } + else + { + nsteps = (int)MAX(1, round(pa2a / (M_PI / 8) ) ); + angles = (float*)alloca(sizeof(float) * (nsteps + 1) ); + for (i = 0; i <= nsteps; i++) + { + angles[i] = _pa + i * pa2a / nsteps; + } + } + + for (i = 1; i <= nsteps; i++) + { + appendTexpoint(_cx + _t * sin(angles[i - 1]), _cy - _t * cos(angles[i - 1]), _e, (float)HALF_TEXTURE_SIZE); + appendTexpoint(_cx, _cy, _s, (float)HALF_TEXTURE_SIZE); + appendTexpoint(_cx + _t * sin(angles[i]), _cy - _t * cos(angles[i]), _e, (float)HALF_TEXTURE_SIZE); + } +} + +void VectorDisplay::drawLines(line_t* _lines, int _numberLines) +{ + int i; + float t = effectiveThickness(); + + for (i = 0; i < _numberLines; i++) + { + line_t* line = &_lines[i], * pline = &_lines[(_numberLines + i - 1) % _numberLines]; + + if (line->has_prev) // draw fan for connection to previous + { + float pa2a = normalizef(pline->a - line->a); + float a2pa = normalizef(line->a - pline->a); + if (a2pa < pa2a) // inside of fan on right + { + drawFan(line->xr0, line->yr0, pline->a, line->a, line->tl0 + line->tr0, (float)HALF_TEXTURE_SIZE + (line->tr0 / t * (float)HALF_TEXTURE_SIZE), 0); + } + else // inside of fan on left + { + drawFan(line->xl0, line->yl0, pline->a, line->a, line->tl0 + line->tr0, (float)HALF_TEXTURE_SIZE - (line->tl0 / t * (float)HALF_TEXTURE_SIZE), (float)TEXTURE_SIZE); + } + } + + float tl0 = (float)HALF_TEXTURE_SIZE - (line->tl0 / t) * (float)HALF_TEXTURE_SIZE; + float tl1 = (float)HALF_TEXTURE_SIZE - (line->tl1 / t) * (float)HALF_TEXTURE_SIZE; + + float tr0 = (float)HALF_TEXTURE_SIZE + (line->tr0 / t) * (float)HALF_TEXTURE_SIZE; + float tr1 = (float)HALF_TEXTURE_SIZE + (line->tr1 / t) * (float)HALF_TEXTURE_SIZE; + + appendTexpoint(line->xr0, line->yr0, tr0, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xr1, line->yr1, tr1, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xl1, line->yl1, tl1, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xl0, line->yl0, tl0, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xr0, line->yr0, tr0, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xl1, line->yl1, tl1, (float)HALF_TEXTURE_SIZE); + + if (!line->has_prev) // draw startcap + { + appendTexpoint(line->xl0, line->yl0, tl0, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xlt0, line->ylt0, tl0, 0.0f); + appendTexpoint(line->xr0, line->yr0, tr0, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xr0, line->yr0, tr0, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xlt0, line->ylt0, tl0, 0.0f); + appendTexpoint(line->xrt0, line->yrt0, tr0, 0.0f); + } + + if (!line->has_next) // draw endcap + { + appendTexpoint(line->xlt1, line->ylt1, tl1, 0.0f); + appendTexpoint(line->xl1, line->yl1, tl1, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xr1, line->yr1, tr1, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xlt1, line->ylt1, tl1, 0.0f); + appendTexpoint(line->xr1, line->yr1, tr1, (float)HALF_TEXTURE_SIZE); + appendTexpoint(line->xrt1, line->yrt1, tr1, 0.0f); + } + } +} + +bool VectorDisplay::setDecaySteps(int _steps) +{ + if (_steps < 0 + || _steps > MAX_DECAY_STEPS) + { + return false; + } + + m_numberDecaySteps = _steps; + + if (m_vertexBuffers.size() != 0) + { + for (size_t i = 0; i < m_vertexBuffers.size(); ++i) + { + destroyDynamicVertexBuffer(m_vertexBuffers[i]); + } + + m_vertexBuffers.clear(); + m_vertexBuffersSize.clear(); + } + + for (int i = 0; i < m_numberDecaySteps; ++i) + { + m_vertexBuffers.push_back(bgfx::createDynamicVertexBuffer(MAX_NUMBER_VERTICES, PosColorUvVertex::ms_decl) ); + m_vertexBuffersSize.push_back(0); + } + + return true; +} + +bool VectorDisplay::setDecay(float _decay) +{ + if (_decay < 0.0f + || _decay >= 1.0f) + { + return false; + } + + m_decayValue = _decay; + return true; +} + +void VectorDisplay::setBrightness(float _brightness) +{ + m_brightness = _brightness; +} + +void VectorDisplay::getSize(float* _outWidth, float* _outHeight) +{ + *_outWidth = m_screenWidth; + *_outHeight = m_screenHeight; +} + +void VectorDisplay::screenSpaceQuad(float _textureWidth, float _textureHeight, float _width, float _height) +{ + if (bgfx::checkAvailTransientVertexBuffer(3, PosColorUvVertex::ms_decl) ) + { + bgfx::TransientVertexBuffer vb; + bgfx::allocTransientVertexBuffer(&vb, 3, PosColorUvVertex::ms_decl); + PosColorUvVertex* vertex = (PosColorUvVertex*)vb.data; + + const float zz = 0.0f; + + const float minx = -_width; + const float maxx = _width; + const float miny = 0.0f; + const float maxy = _height * 2.0f; + + const float texelHalfW = m_texelHalf / _textureWidth; + const float texelHalfH = m_texelHalf / _textureHeight; + const float minu = -1.0f + texelHalfW; + const float maxu = 1.0f + texelHalfW; + + float minv = texelHalfH; + float maxv = 2.0f + texelHalfH; + + if (m_originBottomLeft) + { + float temp = minv; + minv = maxv; + maxv = temp; + + minv -= 1.0f; + maxv -= 1.0f; + } + + vertex[0].m_x = minx; + vertex[0].m_y = miny; + vertex[0].m_z = zz; + vertex[0].m_abgr = 0xffffffff; + vertex[0].m_u = minu; + vertex[0].m_v = minv; + + vertex[1].m_x = maxx; + vertex[1].m_y = miny; + vertex[1].m_z = zz; + vertex[1].m_abgr = 0xffffffff; + vertex[1].m_u = maxu; + vertex[1].m_v = minv; + + vertex[2].m_x = maxx; + vertex[2].m_y = maxy; + vertex[2].m_z = zz; + vertex[2].m_abgr = 0xffffffff; + vertex[2].m_u = maxu; + vertex[2].m_v = maxv; + + bgfx::setVertexBuffer(&vb); + } +} + +void VectorDisplay::setupResDependent() +{ + const uint32_t samplerFlags = BGFX_TEXTURE_RT + | BGFX_TEXTURE_MIN_POINT + | BGFX_TEXTURE_MAG_POINT + | BGFX_TEXTURE_MIP_POINT + | BGFX_TEXTURE_U_CLAMP + | BGFX_TEXTURE_V_CLAMP + ; + m_sceneFrameBuffer = bgfx::createFrameBuffer(m_screenWidth, m_screenHeight, bgfx::TextureFormat::BGRA8, samplerFlags); + + m_glowWidth = m_screenWidth / 3; + m_glowHeight = m_screenHeight / 3; + + m_glow0FrameBuffer = bgfx::createFrameBuffer(m_glowWidth, m_glowHeight, bgfx::TextureFormat::BGRA8, samplerFlags); + m_glow1FrameBuffer = bgfx::createFrameBuffer(m_glowWidth, m_glowHeight, bgfx::TextureFormat::BGRA8, samplerFlags); +} + +void VectorDisplay::teardownResDependent() +{ + bgfx::destroyFrameBuffer(m_sceneFrameBuffer); + bgfx::destroyFrameBuffer(m_glow0FrameBuffer); + bgfx::destroyFrameBuffer(m_glow1FrameBuffer); +} + +void VectorDisplay::genLinetex() // generate the texture +{ + const bgfx::Memory* mem = bgfx::alloc(TEXTURE_SIZE * TEXTURE_SIZE * 4); + unsigned char* texbuf = (unsigned char*)mem->data; + + memset(texbuf, 0xff, mem->size); + int x, y; + for (x = 0; x < TEXTURE_SIZE; x++) + { + for (y = 0; y < TEXTURE_SIZE; y++) + { + float distance = sqrt( (float)( (x - HALF_TEXTURE_SIZE) * (x - HALF_TEXTURE_SIZE) + (y - HALF_TEXTURE_SIZE) * (y - HALF_TEXTURE_SIZE) ) ) / (float)HALF_TEXTURE_SIZE; + + if (distance > 1.0) + { + distance = 1.0; + } + + float line = pow(16, -2 * distance); + float glow = pow(2, -4 * distance) / 10.0f; + glow = 0; + float val = MAX(0, MIN(1, line + glow) ); // clamp + + texbuf[(x + y * TEXTURE_SIZE) * 4 + 0] = 0xff; + texbuf[(x + y * TEXTURE_SIZE) * 4 + 1] = 0xff; + texbuf[(x + y * TEXTURE_SIZE) * 4 + 2] = 0xff; + texbuf[(x + y * TEXTURE_SIZE) * 4 + 3] = (unsigned char)(val * 0xff); + } + } + + int flags = BGFX_TEXTURE_U_CLAMP | BGFX_TEXTURE_V_CLAMP | BGFX_TEXTURE_MIN_POINT | BGFX_TEXTURE_MAG_POINT; + + m_lineTexId = bgfx::createTexture2D(TEXTURE_SIZE, TEXTURE_SIZE, 1, bgfx::TextureFormat::BGRA8, flags, mem); + s_lineTexture = bgfx::createUniform("s_lineTexture", bgfx::UniformType::Uniform1iv); +} + +static int simplex[95][112] = +{ + { 0, 16, /* Ascii 32 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 10, /* Ascii 33 */ + 5, 21, 5, 7, -1, -1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 16, /* Ascii 34 */ + 4, 21, 4, 14, -1, -1, 12, 21, 12, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 21, /* Ascii 35 */ + 11, 25, 4, -7, -1, -1, 17, 25, 10, -7, -1, -1, 4, 12, 18, 12, -1, -1, 3, 6, 17, 6, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 26, 20, /* Ascii 36 */ + 8, 25, 8, -4, -1, -1, 12, 25, 12, -4, -1, -1, 17, 18, 15, 20, 12, 21, 8, 21, 5, 20, 3, + 18, 3, 16, 4, 14, 5, 13, 7, 12, 13, 10, 15, 9, 16, 8, 17, 6, 17, 3, 15, 1, 12, 0, + 8, 0, 5, 1, 3, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 31, 24, /* Ascii 37 */ + 21, 21, 3, 0, -1, -1, 8, 21, 10, 19, 10, 17, 9, 15, 7, 14, 5, 14, 3, 16, 3, 18, 4, + 20, 6, 21, 8, 21, 10, 20, 13, 19, 16, 19, 19, 20, 21, 21, -1, -1, 17, 7, 15, 6, 14, 4, + 14, 2, 16, 0, 18, 0, 20, 1, 21, 3, 21, 5, 19, 7, 17, 7, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 34, 26, /* Ascii 38 */ + 23, 12, 23, 13, 22, 14, 21, 14, 20, 13, 19, 11, 17, 6, 15, 3, 13, 1, 11, 0, 7, 0, 5, + 1, 4, 2, 3, 4, 3, 6, 4, 8, 5, 9, 12, 13, 13, 14, 14, 16, 14, 18, 13, 20, 11, 21, + 9, 20, 8, 18, 8, 16, 9, 13, 11, 10, 16, 3, 18, 1, 20, 0, 22, 0, 23, 1, 23, 2, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 10, /* Ascii 39 */ + 5, 19, 4, 20, 5, 21, 6, 20, 6, 18, 5, 16, 4, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 14, /* Ascii 40 */ + 11, 25, 9, 23, 7, 20, 5, 16, 4, 11, 4, 7, 5, 2, 7, -2, 9, -5, 11, -7, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 14, /* Ascii 41 */ + 3, 25, 5, 23, 7, 20, 9, 16, 10, 11, 10, 7, 9, 2, 7, -2, 5, -5, 3, -7, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 16, /* Ascii 42 */ + 8, 21, 8, 9, -1, -1, 3, 18, 13, 12, -1, -1, 13, 18, 3, 12, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 26, /* Ascii 43 */ + 13, 18, 13, 0, -1, -1, 4, 9, 22, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 10, /* Ascii 44 */ + 6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6, -1, 5, -3, 4, -4, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 26, /* Ascii 45 */ + 4, 9, 22, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 10, /* Ascii 46 */ + 5, 2, 4, 1, 5, 0, 6, 1, 5, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 22, /* Ascii 47 */ + 20, 25, 2, -7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 17, 20, /* Ascii 48 */ + 9, 21, 6, 20, 4, 17, 3, 12, 3, 9, 4, 4, 6, 1, 9, 0, 11, 0, 14, 1, 16, 4, 17, + 9, 17, 12, 16, 17, 14, 20, 11, 21, 9, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 4, 20, /* Ascii 49 */ + 6, 17, 8, 18, 11, 21, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 14, 20, /* Ascii 50 */ + 4, 16, 4, 17, 5, 19, 6, 20, 8, 21, 12, 21, 14, 20, 15, 19, 16, 17, 16, 15, 15, 13, 13, + 10, 3, 0, 17, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 15, 20, /* Ascii 51 */ + 5, 21, 16, 21, 10, 13, 13, 13, 15, 12, 16, 11, 17, 8, 17, 6, 16, 3, 14, 1, 11, 0, 8, + 0, 5, 1, 4, 2, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 20, /* Ascii 52 */ + 13, 21, 3, 7, 18, 7, -1, -1, 13, 21, 13, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 17, 20, /* Ascii 53 */ + 15, 21, 5, 21, 4, 12, 5, 13, 8, 14, 11, 14, 14, 13, 16, 11, 17, 8, 17, 6, 16, 3, 14, + 1, 11, 0, 8, 0, 5, 1, 4, 2, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 23, 20, /* Ascii 54 */ + 16, 18, 15, 20, 12, 21, 10, 21, 7, 20, 5, 17, 4, 12, 4, 7, 5, 3, 7, 1, 10, 0, 11, + 0, 14, 1, 16, 3, 17, 6, 17, 7, 16, 10, 14, 12, 11, 13, 10, 13, 7, 12, 5, 10, 4, 7, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 20, /* Ascii 55 */ + 17, 21, 7, 0, -1, -1, 3, 21, 17, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 29, 20, /* Ascii 56 */ + 8, 21, 5, 20, 4, 18, 4, 16, 5, 14, 7, 13, 11, 12, 14, 11, 16, 9, 17, 7, 17, 4, 16, + 2, 15, 1, 12, 0, 8, 0, 5, 1, 4, 2, 3, 4, 3, 7, 4, 9, 6, 11, 9, 12, 13, 13, + 15, 14, 16, 16, 16, 18, 15, 20, 12, 21, 8, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 23, 20, /* Ascii 57 */ + 16, 14, 15, 11, 13, 9, 10, 8, 9, 8, 6, 9, 4, 11, 3, 14, 3, 15, 4, 18, 6, 20, 9, + 21, 10, 21, 13, 20, 15, 18, 16, 14, 16, 9, 15, 4, 13, 1, 10, 0, 8, 0, 5, 1, 4, 3, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 10, /* Ascii 58 */ + 5, 14, 4, 13, 5, 12, 6, 13, 5, 14, -1, -1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 14, 10, /* Ascii 59 */ + 5, 14, 4, 13, 5, 12, 6, 13, 5, 14, -1, -1, 6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6, + -1, 5, -3, 4, -4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 24, /* Ascii 60 */ + 20, 18, 4, 9, 20, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 26, /* Ascii 61 */ + 4, 12, 22, 12, -1, -1, 4, 6, 22, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 3, 24, /* Ascii 62 */ + 4, 18, 20, 9, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 20, 18, /* Ascii 63 */ + 3, 16, 3, 17, 4, 19, 5, 20, 7, 21, 11, 21, 13, 20, 14, 19, 15, 17, 15, 15, 14, 13, 13, + 12, 9, 10, 9, 7, -1, -1, 9, 2, 8, 1, 9, 0, 10, 1, 9, 2, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 55, 27, /* Ascii 64 */ + 18, 13, 17, 15, 15, 16, 12, 16, 10, 15, 9, 14, 8, 11, 8, 8, 9, 6, 11, 5, 14, 5, 16, + 6, 17, 8, -1, -1, 12, 16, 10, 14, 9, 11, 9, 8, 10, 6, 11, 5, -1, -1, 18, 16, 17, 8, + 17, 6, 19, 5, 21, 5, 23, 7, 24, 10, 24, 12, 23, 15, 22, 17, 20, 19, 18, 20, 15, 21, 12, + 21, 9, 20, 7, 19, 5, 17, 4, 15, 3, 12, 3, 9, 4, 6, 5, 4, 7, 2, 9, 1, 12, 0, + 15, 0, 18, 1, 20, 2, 21, 3, -1, -1, 19, 16, 18, 8, 18, 6, 19, 5 }, + { 8, 18, /* Ascii 65 */ + 9, 21, 1, 0, -1, -1, 9, 21, 17, 0, -1, -1, 4, 7, 14, 7, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 23, 21, /* Ascii 66 */ + 4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 15, 17, 13, 16, 12, 13, + 11, -1, -1, 4, 11, 13, 11, 16, 10, 17, 9, 18, 7, 18, 4, 17, 2, 16, 1, 13, 0, 4, 0, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 18, 21, /* Ascii 67 */ + 18, 16, 17, 18, 15, 20, 13, 21, 9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, + 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 15, 21, /* Ascii 68 */ + 4, 21, 4, 0, -1, -1, 4, 21, 11, 21, 14, 20, 16, 18, 17, 16, 18, 13, 18, 8, 17, 5, 16, + 3, 14, 1, 11, 0, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 19, /* Ascii 69 */ + 4, 21, 4, 0, -1, -1, 4, 21, 17, 21, -1, -1, 4, 11, 12, 11, -1, -1, 4, 0, 17, 0, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 18, /* Ascii 70 */ + 4, 21, 4, 0, -1, -1, 4, 21, 17, 21, -1, -1, 4, 11, 12, 11, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 22, 21, /* Ascii 71 */ + 18, 16, 17, 18, 15, 20, 13, 21, 9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, + 3, 7, 1, 9, 0, 13, 0, 15, 1, 17, 3, 18, 5, 18, 8, -1, -1, 13, 8, 18, 8, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 22, /* Ascii 72 */ + 4, 21, 4, 0, -1, -1, 18, 21, 18, 0, -1, -1, 4, 11, 18, 11, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 8, /* Ascii 73 */ + 4, 21, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 16, /* Ascii 74 */ + 12, 21, 12, 5, 11, 2, 10, 1, 8, 0, 6, 0, 4, 1, 3, 2, 2, 5, 2, 7, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 21, /* Ascii 75 */ + 4, 21, 4, 0, -1, -1, 18, 21, 4, 7, -1, -1, 9, 12, 18, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 17, /* Ascii 76 */ + 4, 21, 4, 0, -1, -1, 4, 0, 16, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 24, /* Ascii 77 */ + 4, 21, 4, 0, -1, -1, 4, 21, 12, 0, -1, -1, 20, 21, 12, 0, -1, -1, 20, 21, 20, 0, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 22, /* Ascii 78 */ + 4, 21, 4, 0, -1, -1, 4, 21, 18, 0, -1, -1, 18, 21, 18, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 21, 22, /* Ascii 79 */ + 9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, + 1, 17, 3, 18, 5, 19, 8, 19, 13, 18, 16, 17, 18, 15, 20, 13, 21, 9, 21, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 13, 21, /* Ascii 80 */ + 4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 14, 17, 12, 16, 11, 13, + 10, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 24, 22, /* Ascii 81 */ + 9, 21, 7, 20, 5, 18, 4, 16, 3, 13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0, 13, 0, 15, + 1, 17, 3, 18, 5, 19, 8, 19, 13, 18, 16, 17, 18, 15, 20, 13, 21, 9, 21, -1, -1, 12, 4, + 18, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 16, 21, /* Ascii 82 */ + 4, 21, 4, 0, -1, -1, 4, 21, 13, 21, 16, 20, 17, 19, 18, 17, 18, 15, 17, 13, 16, 12, 13, + 11, 4, 11, -1, -1, 11, 11, 18, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 20, 20, /* Ascii 83 */ + 17, 18, 15, 20, 12, 21, 8, 21, 5, 20, 3, 18, 3, 16, 4, 14, 5, 13, 7, 12, 13, 10, 15, + 9, 16, 8, 17, 6, 17, 3, 15, 1, 12, 0, 8, 0, 5, 1, 3, 3, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 16, /* Ascii 84 */ + 8, 21, 8, 0, -1, -1, 1, 21, 15, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 22, /* Ascii 85 */ + 4, 21, 4, 6, 5, 3, 7, 1, 10, 0, 12, 0, 15, 1, 17, 3, 18, 6, 18, 21, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 18, /* Ascii 86 */ + 1, 21, 9, 0, -1, -1, 17, 21, 9, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 24, /* Ascii 87 */ + 2, 21, 7, 0, -1, -1, 12, 21, 7, 0, -1, -1, 12, 21, 17, 0, -1, -1, 22, 21, 17, 0, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 20, /* Ascii 88 */ + 3, 21, 17, 0, -1, -1, 17, 21, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 6, 18, /* Ascii 89 */ + 1, 21, 9, 11, 9, 0, -1, -1, 17, 21, 9, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 20, /* Ascii 90 */ + 17, 21, 3, 0, -1, -1, 3, 21, 17, 21, -1, -1, 3, 0, 17, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 14, /* Ascii 91 */ + 4, 25, 4, -7, -1, -1, 5, 25, 5, -7, -1, -1, 4, 25, 11, 25, -1, -1, 4, -7, 11, -7, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 14, /* Ascii 92 */ + 0, 21, 14, -3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 14, /* Ascii 93 */ + 9, 25, 9, -7, -1, -1, 10, 25, 10, -7, -1, -1, 3, 25, 10, 25, -1, -1, 3, -7, 10, -7, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 16, /* Ascii 94 */ + 6, 15, 8, 18, 10, 15, -1, -1, 3, 12, 8, 17, 13, 12, -1, -1, 8, 17, 8, 0, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 16, /* Ascii 95 */ + 0, -2, 16, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 7, 10, /* Ascii 96 */ + 6, 21, 5, 20, 4, 18, 4, 16, 5, 15, 6, 16, 5, 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 17, 19, /* Ascii 97 */ + 15, 14, 15, 0, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 17, 19, /* Ascii 98 */ + 4, 21, 4, 0, -1, -1, 4, 11, 6, 13, 8, 14, 11, 14, 13, 13, 15, 11, 16, 8, 16, 6, 15, + 3, 13, 1, 11, 0, 8, 0, 6, 1, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 14, 18, /* Ascii 99 */ + 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, + 0, 13, 1, 15, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 17, 19, /* Ascii 100 */ + 15, 21, 15, 0, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 17, 18, /* Ascii 101 */ + 3, 8, 15, 8, 15, 10, 14, 12, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 12, /* Ascii 102 */ + 10, 21, 8, 21, 6, 20, 5, 17, 5, 0, -1, -1, 2, 14, 9, 14, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 22, 19, /* Ascii 103 */ + 15, 14, 15, -2, 14, -5, 13, -6, 11, -7, 8, -7, 6, -6, -1, -1, 15, 11, 13, 13, 11, 14, 8, + 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 19, /* Ascii 104 */ + 4, 21, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 8, /* Ascii 105 */ + 3, 21, 4, 20, 5, 21, 4, 22, 3, 21, -1, -1, 4, 14, 4, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 10, /* Ascii 106 */ + 5, 21, 6, 20, 7, 21, 6, 22, 5, 21, -1, -1, 6, 14, 6, -3, 5, -6, 3, -7, 1, -7, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 17, /* Ascii 107 */ + 4, 21, 4, 0, -1, -1, 14, 14, 4, 4, -1, -1, 8, 8, 15, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 8, /* Ascii 108 */ + 4, 21, 4, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 18, 30, /* Ascii 109 */ + 4, 14, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0, -1, -1, 15, + 10, 18, 13, 20, 14, 23, 14, 25, 13, 26, 10, 26, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 19, /* Ascii 110 */ + 4, 14, 4, 0, -1, -1, 4, 10, 7, 13, 9, 14, 12, 14, 14, 13, 15, 10, 15, 0, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 17, 19, /* Ascii 111 */ + 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3, 16, + 6, 16, 8, 15, 11, 13, 13, 11, 14, 8, 14, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 17, 19, /* Ascii 112 */ + 4, 14, 4, -7, -1, -1, 4, 11, 6, 13, 8, 14, 11, 14, 13, 13, 15, 11, 16, 8, 16, 6, 15, + 3, 13, 1, 11, 0, 8, 0, 6, 1, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 17, 19, /* Ascii 113 */ + 15, 14, 15, -7, -1, -1, 15, 11, 13, 13, 11, 14, 8, 14, 6, 13, 4, 11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0, 11, 0, 13, 1, 15, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 13, /* Ascii 114 */ + 4, 14, 4, 0, -1, -1, 4, 8, 5, 11, 7, 13, 9, 14, 12, 14, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 17, 17, /* Ascii 115 */ + 14, 11, 13, 13, 10, 14, 7, 14, 4, 13, 3, 11, 4, 9, 6, 8, 11, 7, 13, 6, 14, 4, 14, + 3, 13, 1, 10, 0, 7, 0, 4, 1, 3, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 12, /* Ascii 116 */ + 5, 21, 5, 4, 6, 1, 8, 0, 10, 0, -1, -1, 2, 14, 9, 14, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 10, 19, /* Ascii 117 */ + 4, 14, 4, 4, 5, 1, 7, 0, 10, 0, 12, 1, 15, 4, -1, -1, 15, 14, 15, 0, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 16, /* Ascii 118 */ + 2, 14, 8, 0, -1, -1, 14, 14, 8, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 11, 22, /* Ascii 119 */ + 3, 14, 7, 0, -1, -1, 11, 14, 7, 0, -1, -1, 11, 14, 15, 0, -1, -1, 19, 14, 15, 0, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 5, 17, /* Ascii 120 */ + 3, 14, 14, 0, -1, -1, 14, 14, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 9, 16, /* Ascii 121 */ + 2, 14, 8, 0, -1, -1, 14, 14, 8, 0, 6, -4, 4, -6, 2, -7, 1, -7, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 8, 17, /* Ascii 122 */ + 14, 14, 3, 0, -1, -1, 3, 14, 14, 14, -1, -1, 3, 0, 14, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 39, 14, /* Ascii 123 */ + 9, 25, 7, 24, 6, 23, 5, 21, 5, 19, 6, 17, 7, 16, 8, 14, 8, 12, 6, 10, -1, -1, 7, + 24, 6, 22, 6, 20, 7, 18, 8, 17, 9, 15, 9, 13, 8, 11, 4, 9, 8, 7, 9, 5, 9, 3, + 8, 1, 7, 0, 6, -2, 6, -4, 7, -6, -1, -1, 6, 8, 8, 6, 8, 4, 7, 2, 6, 1, 5, + -1, 5, -3, 6, -5, 7, -6, 9, -7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 2, 8, /* Ascii 124 */ + 4, 25, 4, -7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 39, 14, /* Ascii 125 */ + 5, 25, 7, 24, 8, 23, 9, 21, 9, 19, 8, 17, 7, 16, 6, 14, 6, 12, 8, 10, -1, -1, 7, + 24, 8, 22, 8, 20, 7, 18, 6, 17, 5, 15, 5, 13, 6, 11, 10, 9, 6, 7, 5, 5, 5, 3, + 6, 1, 7, 0, 8, -2, 8, -4, 7, -6, -1, -1, 8, 8, 6, 6, 6, 4, 7, 2, 8, 1, 9, + -1, 9, -3, 8, -5, 7, -6, 5, -7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, + { 23, 24, /* Ascii 126 */ + 3, 6, 3, 8, 4, 11, 6, 12, 8, 12, 10, 11, 14, 8, 16, 7, 18, 7, 20, 8, 21, 10, -1, + -1, 3, 8, 4, 10, 6, 11, 8, 11, 10, 10, 14, 7, 16, 6, 18, 6, 20, 7, 21, 10, 21, 12, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } +}; + +//void VectorDisplay::simplexMeasure(float _scale, const char *_string, float *_outWidth, float *_outHeight) { +//not implemented :/ +//} + +void VectorDisplay::drawSimplexFont(float _x, float _y, float _scale, const char* _string) +{ + for (;;) + { + char c = *_string++; + if (!c) + { + break; + } + + if (c < 32 + || c > 126) + { + continue; + } + + int* chr = simplex[c - 32]; + + int nvertices = chr[0]; + int spacing = chr[1]; + + bool isDrawing = false; + int i; + for (i = 0; i < nvertices; i++) + { + int vx = chr[2 + i * 2]; + int vy = chr[2 + i * 2 + 1]; + if (vx == -1 + && vy == -1) + { + if (isDrawing) + { + endDraw(); + isDrawing = false; + } + } + else if (!isDrawing) + { + beginDraw(_x + vx * _scale, _y - vy * _scale); + isDrawing = true; + } + else + { + drawTo(_x + vx * _scale, _y - vy * _scale); + } + } + + _x += spacing * _scale; + if (isDrawing) + { + endDraw(); + } + } +} diff --git a/examples/23-vectordisplay/vectordisplay.h b/examples/23-vectordisplay/vectordisplay.h new file mode 100644 index 00000000..b5c7a870 --- /dev/null +++ b/examples/23-vectordisplay/vectordisplay.h @@ -0,0 +1,196 @@ + +/* + * Copyright 2014 Kai Jourdan. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + * + * based on code from Brian Luczkiewicz + * https://github.com/blucz/Vector + * + * uses the SIMPLEX-Font which is a variant of the Hershey font (public domain) + * http://paulbourke.net/dataformats/hershey/ + */ + +#ifndef __BGFX_VECTORDISPLAY_H__ +#define __BGFX_VECTORDISPLAY_H__ + +#include "bgfx.h" + +#include +#include +namespace stl = tinystl; + +class VectorDisplay { +public: +VectorDisplay(bool _originBottomLeft, float _texelHalf); +~VectorDisplay() +{ +} + +void setup(uint16_t _width, uint16_t _height, int _view = 2); +void resize(uint16_t _width, uint16_t _height); +void teardown(); + +void beginFrame(); +void endFrame(); + +// Draw a series of connected line segments. +void beginDraw(float _x, float _y); +void drawTo(float _x, float _y); +void endDraw(); + +//HighLevel draw functions +void drawLine(float _x0, float _y0, float _x1, float _y1); +void drawBox(float _x, float _y, float _w, float _h); +void drawCircle(float _x, float _y, float _radius, float _steps); +void drawWheel(float _spokeangle, float _x, float _y, float _radius); + +//Font Stuff (Simplex) +//void simplexMeasure(float _scale, const char *_string, float *_outWidth, float *_outHeight); +void drawSimplexFont(float _x, float _y, float _scale, const char* _string); + +// Set the current drawing color +void setDrawColor(float _r, float _g, float _b, float _a = 1.0f); + +// Set the number of frames of decay/fade to apply to the scene. +bool setDecaySteps(int _steps); + +// Set the brightness multipler applied on each decay frame after the first. +bool setDecay(float _decay); + +// Set the brightness multipler applied on the first decay frame. +bool setInitialDecay(float _initialDecay); + +// Set a 2d transformation for the display. +// +// This relates logical coordinates, as passed to vector_display_begin_draw, +// vector_display_draw_to, and vector_display_draw, to coordinates from (0,0) +// to (width,height) in the destination framebuffer. +// +// The parameters impact coordinates as follows: +// +// framebuffer_x = x * scale + offset_x +// framebuffer_y = y * scale + offset_y +// +void setTransform(float _offsetX, float _offsetY, float _scale); + +// Set the line thickness. +// +// The line thickness is measured in scene coordinates, and includes all pixels lit by +// the line before any post-processing. The apparent width of the line to the viewer +// is significantly narrower, since brightness decays exponentially to zero within the +// bounds of the line. +// +// Thickness, by default, is guessed based on width and height. +// +// This function clears the display. +bool setThickness(float _thickness); +void setDefaultThickness(); + +// Set the "brightness" of the display +// +// useful values range from [0.5, 1.5]. 0.0 disables all glow effects. +// +// Due to implementation details of the glow effect, glow is related to +// the pixel density of the framebuffer. It may require adjustment, +// particularly when moving between devices of very different pixel density. +// +void setBrightness(float _brightness); + +// Get the size from a vector display. +void getSize(float* _outWidth, float* _outHeight); +protected: +void screenSpaceQuad(float _textureWidth, float _textureHeight, float _width = 1.0f, float _height = 1.0f); + +typedef struct //has to match the spec submitted to the 3d-api! +{ float x, y, z; + float u, v; + uint32_t color; } point_t; + +typedef struct +{ + float x, y; +} pending_point_t; + +typedef struct +{ + float x0, y0, x1, y1; // nominal points + float a; // angle + float sin_a, cos_a; // precomputed trig + + float xl0, yl0, xl1, yl1; // left side of the box + float xr0, yr0, xr1, yr1; // right side of the box + + int is_first, is_last; + int has_next, has_prev; // booleans indicating whether this line connects to prev/next + + float xlt0, ylt0, xlt1, ylt1; // coordinates of endcaps (if !has_prev/!has_next) + float xrt0, yrt0, xrt1, yrt1; // coordinates of endcaps (if !has_prev/!has_next) + + float tl0, tl1, tr0, tr1; + + float s0, s1; // shorten line by this amount + + float len; +} line_t; + +float effectiveThickness(); +void setupResDependent(); +void teardownResDependent(); + +void appendTexpoint(float _x, float _y, float _u, float _v); + +float normalizef(float _a); + +void drawFan(float _cx, float _cy, float _pa, float _a, float _t, float _s, float _e); +void drawLines(line_t* _lines, int _numberLines); +void genLinetex(); + +bool m_originBottomLeft; +float m_texelHalf; + +bgfx::ProgramHandle m_drawToScreenShader; // program for drawing to the framebuffer +bgfx::UniformHandle u_compose_alpha; + +bgfx::FrameBufferHandle m_sceneFrameBuffer; + +bgfx::ProgramHandle m_blurShader; // program for gaussian blur +bgfx::UniformHandle u_blur_scale; +bgfx::UniformHandle u_compose_mult; +bgfx::UniformHandle s_textureSampler; //texture handle for blur + +bgfx::ProgramHandle m_blitShader; + +bgfx::FrameBufferHandle m_glow0FrameBuffer; // framebuffer for glow pass 0 +bgfx::FrameBufferHandle m_glow1FrameBuffer; // framebuffer for glow pass 1 + +int m_view; + +uint16_t m_screenWidth, m_screenHeight; +uint16_t m_glowWidth, m_glowHeight; + +int m_numberDecaySteps; +float m_decayValue; +uint8_t m_drawColorR, m_drawColorG, m_drawColorB, m_drawColorA; + +stl::vector m_points; +stl::vector m_pendingPoints; + +int m_currentDrawStep; +stl::vector m_vertexBuffers; +stl::vector m_vertexBuffersSize; + +bgfx::TextureHandle m_lineTexId; +bgfx::UniformHandle s_lineTexture; + +float m_initialDecay; + +float m_thickness; +bool m_customThicknessEnabled; + +float m_brightness; + +float m_drawOffsetX, m_drawOffsetY; +float m_drawScale; +}; + +#endif //#ifndef __BGFX_VECTORDISPLAY_H__ diff --git a/examples/23-vectordisplay/vs_vectordisplay_fb.sc b/examples/23-vectordisplay/vs_vectordisplay_fb.sc new file mode 100644 index 00000000..35d0ca43 --- /dev/null +++ b/examples/23-vectordisplay/vs_vectordisplay_fb.sc @@ -0,0 +1,10 @@ +$input a_position, a_texcoord0, a_color0 +$output v_texcoord0, v_color0 + +#include + +void main() { + gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) ); + v_color0 = a_color0; + v_texcoord0 = a_texcoord0; +}