Esempio n. 1
0
 static ContextReflection getContextReflection(Type t)
 {
     if (contextTypes.TryGetValue(t, out var r))
     {
         return(r);
     }
     r = new ContextReflection(t);
     contextTypes.Add(t, r);
     return(r);
 }
Esempio n. 2
0
        /// <summary>Compile all glyphs of the font into .NET codez</summary>
        static TDelegate compile <TDelegate>(int atlasLayersCount, IEnumerable <Font.GlyphData> glyphs, Type tContext, byte paddingPixel, uint paddingUV)
            where TDelegate : Delegate
        {
            // If needed, create moar layer index constants
            while (atlasLayersCount > layerConstants.Count)
            {
                byte layer = (byte)layerConstants.Count;
                layerConstants.Add(Expression.Constant(layer, typeof(byte)));
            }

            ContextReflection reflection = getContextReflection(tContext);

            // Build sorted map of these case expressions
            map.Clear();
            foreach (Font.GlyphData glyph in glyphs)
            {
                buildGlyph(ref reflection, glyph, paddingPixel, paddingUV);
            }
            // Add end of string switch-case, which tests for UINT_MAX and returns
            map.Add(uint.MaxValue, endOfStringCase);

            // Implement body of the loop
            loopBody.Clear();
            loopBody.Add(decodeCharacter);
            loopBody.Add(Expression.Switch(utf32, map.Values.ToArray()));
            loopBody.Add(switchBreakLabel);

            // Implement body of the function
            functionBody.Clear();
            functionBody.Add(createDecoder);
            functionBody.Add(Expression.Loop(Expression.Block(loopBody)));
            functionBody.Add(returnLabel);

            // Gather delegate parameters into a list
            parameters.Clear();
            parameters.Add(reflection.paramExpression);
            parameters.Add(paramString);

            // Finally, compile all that stuff into CIL. JIT compiler will do the rest.
            var       lambda = Expression.Lambda <TDelegate>(Expression.Block(localVariables, functionBody), parameters);
            TDelegate result = lambda.Compile();

            // Cleanup temporary stuff. Hopefully, all these no longer needed objects will be garbage collected right away, while still at generation 0.
            map.Clear();
            loopBody.Clear();
            functionBody.Clear();
            parameters.Clear();

            return(result);
        }
Esempio n. 3
0
        // Build SwitchCase expression for one UTF32 character
        static void buildGlyph(ref ContextReflection reflection, Font.GlyphData glyph, byte paddingPixel, uint paddingUV)
        {
            if (glyph.utf32 == '\n' && null != reflection.miNewLine)
            {
                addSwitchCase('\n', reflection.paramExpression, reflection.miNewLine);
                return;
            }
            if (glyph.utf32 == '\t' && null != reflection.miTab)
            {
                addSwitchCase('\t', reflection.paramExpression, reflection.miTab);
                return;
            }

            Expression advance  = Expression.Constant(glyph.data.advance);
            Expression lsbDelta = Expression.Constant(glyph.data.lsbDelta);
            Expression rsbDelta = Expression.Constant(glyph.data.rsbDelta);

            if (glyph.utf32 == nbsp && null != reflection.miNbsp)
            {
                addSwitchCase(nbsp, reflection.paramExpression, reflection.miNbsp,
                              advance, lsbDelta, rsbDelta);
                return;
            }

            if (glyph.data.hasSprite)
            {
                // The glyph has a bitmap on the atlas
                short left = glyph.data.left;
                short top  = glyph.data.top;
                left -= paddingPixel;
                top  -= paddingPixel;

                CSize size = glyph.sprite.size;
                size.cx += 2 * paddingPixel;
                size.cy += 2 * paddingPixel;

                Expression spriteLeft = Expression.Constant(left, typeof(short));
                Expression spriteTop  = Expression.Constant(top, typeof(short));
                Expression sx         = Expression.Constant((ushort)size.cx, typeof(ushort));
                Expression sy         = Expression.Constant((ushort)size.cy, typeof(ushort));

                ulong uv   = glyph.sprite.uv;
                uint  uvTL = (uint)(uv & uint.MaxValue);
                uint  uvBR = (uint)(uv >> 32);
                uvTL -= paddingUV;
                uvBR += paddingUV;

                Expression uvTopLeft     = Expression.Constant(uvTL, typeof(uint));
                Expression uvBottomRight = Expression.Constant(uvBR, typeof(uint));
                Expression layer         = layerConstants[glyph.sprite.layer];

                addSwitchCase(glyph.utf32, reflection.paramExpression, reflection.miEmit,
                              advance, lsbDelta, rsbDelta,
                              spriteLeft, spriteTop, sx, sy,
                              uvTopLeft, uvBottomRight, layer);
                return;
            }

            // The glyph does not have a bitmap. The most likely reason for that, it's a space character.
            addSwitchCase(glyph.utf32, reflection.paramExpression, reflection.miSkip,
                          advance, lsbDelta, rsbDelta);
        }