Robmaister / SharpFont.HarfBuzz

HarfBuzz bindings for C#
MIT License
19 stars 8 forks source link

Make GlyphInfo and GlyphPosition structs #8

Closed corliss closed 7 years ago

corliss commented 7 years ago

Currently GlyphInfo and GlyphPosition are classes. Allocating large numbers of these puts a lot of pressure on the GC. Therefore, these should be structs.

corliss commented 7 years ago

This turned out to be easy - just declare both types as struct and change the marshaling code to:

        public GlyphInfo[] GlyphInfo()
        {
            int length;
            IntPtr glyphInfoPtr = HB.hb_buffer_get_glyph_infos(reference, out length);
            var glyphInfos = new GlyphInfo[length];
            for (int i = 0; i < length; ++i)
            {
                glyphInfos[i] = Marshal.PtrToStructure<GlyphInfo>(glyphInfoPtr + 20 * i);
            }

            return glyphInfos;
        }
        public GlyphPosition[] GlyphPositions()
        {
            int length;
            IntPtr glyphPositionPtr = HB.hb_buffer_get_glyph_positions(reference, out length);
            var glyphPositions = new GlyphPosition[length];
            for (int i = 0; i < length; ++i)
            {
                glyphPositions[i] = Marshal.PtrToStructure<GlyphPosition>(glyphPositionPtr + 20 * i);
            }

            return glyphPositions;
        }

Note: It would be even better to directly marshal the result of HB.hb_buffer_get_glyph_infos() and HB.hb_buffer_get_glyph_positions() into c# arrays, thereby avoiding the loop. Haven't figured out how to do that, but seems like a common enough situation so it should be possible. But at least this fixes the issue of allocating lots of tiny classes.

Robmaister commented 7 years ago

Yes! Good catch! Arrays like this should be possible, my P/Invoke knowledge is a bit rusty but I'll see if I can make it work