Example #1
0
 private static extern uint GetGlyphOutline(IntPtr hdc, uint ch, uint format, out GLYPHMETRICS gm, uint cb, IntPtr buffer, ref MAT2 mat2);
Example #2
0
        public GlyphDescriptorCollection CollectGlyphs(IAtlasDescriptor descriptor, Action<float> progress, CancellationTokenSource cts)
        {
            ValidateSettings(descriptor);
            GlyphDescriptorCollection glyphs = new GlyphDescriptorCollection();

            HashSet<char> chars = null;

            if (descriptor.UseFonts)
            {
                chars = new HashSet<char>();

                // build set of characters
                foreach (ICharSet charSet in descriptor.CharSets)
                {
                    foreach (char ch in charSet.Characters)
                    {
                        chars.Add(ch);
                    }
                }
            }

            int count = 0;
            count += (descriptor.UseImages) ? descriptor.Images.Count : 0;
            count += (chars != null) ? chars.Count : 0;
            int current = 0;

            if (descriptor.UseImages)
            {
                int ch = descriptor.StartCode;

                foreach (ImageInfo ii in descriptor.Images)
                {
                    int width = ii.Image.Width;
                    int height = ii.Image.Height;

                    Vec2i offset;
                    Image image = CropImage(ii.Image, out offset);

                    ABC abc = new ABC();
                    abc.abcA = -(int)ii.Offset.X;
                    abc.abcB = (uint)(width + ii.Offset.X);
                    abc.abcC = 0;

                    ii.SortCode = ii.HasCustomCode ? ii.Code : UniqueCode(ref ch, descriptor.Images);
                    var gi = new GlyphDescriptor((char)ii.SortCode, abc, image, descriptor.Spacing * 2);
                    gi.Offset = offset - (Vec2i)ii.Offset;
                    gi.ImageInfo = ii;
                    glyphs.Add(gi);

                    if (progress != null)
                    {
                        progress((float)(++current) / count);
                    }

                    if (cts != null)
                    {
                        cts.Token.ThrowIfCancellationRequested();
                    }
                }
            }

            if (descriptor.UseFonts)
            {
                // build image for each glyph
                var gm = new GLYPHMETRICS();
                foreach (char ch in chars)
                {
                    Image image = null;

                    try
                    {
                        if (ch == 159)
                        {
                        }

                        image = TextHelper.GetGlyphOutlineImage(descriptor.Font, ch, out gm);
                        if (image == null)
                        {
                            continue;
                        }
                    }
                    catch
                    {
                        if (image != null)
                        {
                            image.Dispose();
                        }

                        // skip glyph
                        continue;
                    }

                    // flip Y offset
                    ABC abc = new ABC();
                    TextHelper.GetCharABCWidths(descriptor.Font, ch, out abc);

                    GlyphDescriptor glyph = new GlyphDescriptor(ch, abc, image, descriptor.Spacing * 2);
                    glyph.Offset = new Vec2i(gm.gmptGlyphOrigin.X, -gm.gmptGlyphOrigin.Y);
                    glyphs.Add(glyph);

                    if (progress != null)
                    {
                        progress((float)(++current) / count);
                    }

                    if (cts != null)
                    {
                        cts.Token.ThrowIfCancellationRequested();
                    }
                }

                if (descriptor.ForceSpace && glyphs.Find(32) == null)
                {
                    ABC abc = new ABC();
                    TextHelper.GetCharABCWidths(descriptor.Font, (char)32, out abc);
                    abc.abcB = (uint)(abc.abcA + abc.abcB + abc.abcC);
                    abc.abcC = 0;
                    glyphs.Add(new GlyphDescriptor((char)32, abc));
                }
            }

            return glyphs;
        }
Example #3
0
        public static Image GetGlyphOutlineImage(Font font, char ch, out GLYPHMETRICS gm)
        {
            byte[] alpha;
            int size;

            using (FontDC dc = new FontDC(font))
            {
                MAT2 mat = new MAT2();
                mat.eM11.value = 1;
                mat.eM22.value = 1;

                size = (int)GetGlyphOutline(dc.handle, ch, (uint)GlyphOutline.GGO_GRAY8_BITMAP, out gm, 0, IntPtr.Zero, ref mat);
                if (size <= 0)
                {
                    return null;
                }

                IntPtr bufptr = Marshal.AllocHGlobal(size);

                try
                {
                    alpha = new byte[size];
                    GetGlyphOutline(dc.handle, ch, (uint)GlyphOutline.GGO_GRAY8_BITMAP, out gm, (uint)size, bufptr, ref mat);
                    Marshal.Copy(bufptr, alpha, 0, size);
                }
                finally
                {
                    Marshal.FreeHGlobal(bufptr);
                }
            }

            int stride = (int)(gm.gmBlackBoxX + 3) & ~3; // dword alinged
            Bitmap bmp = new Bitmap(stride, (int)gm.gmBlackBoxY, PixelFormat.Format32bppArgb);
            BitmapData bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            int bmpSize = bd.Stride * bd.Height;
            byte[] bmpValues = new byte[bmpSize];
            Marshal.Copy(bd.Scan0, bmpValues, 0, bmpSize);

            const int bias = 0x40;
            for (int i = 0; i < size; i++)
            {
                byte v = (byte)((int)alpha[i] * 255 / bias);
                bmpValues[i * 4 + 0] = 0xff;
                bmpValues[i * 4 + 1] = 0xff;
                bmpValues[i * 4 + 2] = 0xff;
                bmpValues[i * 4 + 3] = v;
            }

            Marshal.Copy(bmpValues, 0, bd.Scan0, bmpSize);
            bmp.UnlockBits(bd);

            return bmp;
        }