protected GlyphDescriptor Localized(GlyphDescriptor gd, double x, double y) { // value type, just mutate the parameter gd.Size *= Size; gd.Offset.X += Offset.X + x; gd.Offset.Y += Offset.Y + y; return(gd); }
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; }
private bool FindSlot(IAtlasDescriptor descriptor, byte[] scan, GlyphDescriptor gi, ref Vec2i minsize) { long reqWidth = gi.Width; long reqHeight = gi.Height; long big = (long)descriptor.MaxSize; if (reqHeight == 0 || reqWidth == 0) { gi.X = (int)0; gi.Y = (int)0; return true; } // try to find an empty space within the current used box for (long y = 0; y <= (minsize.Y - reqHeight); y++) { for (long x = 0; x <= (minsize.X - reqWidth); x++) { long cx, cy; long incr = y * big; for (cy = y; cy < y + reqHeight; cy++) { for (cx = x; cx < x + reqWidth; cx++) { if (scan[incr + cx] != 0) { cy = 9999; break; } } incr += big; } // put it here if (cy < 9999) { gi.X = (int)x; gi.Y = (int)y; return true; } } } // if no space was found, expand the smallest edge of the used box, // which will keep the texture close to square if (minsize.X < minsize.Y) { if (minsize.X == descriptor.MaxSize - 1) { return false; } minsize.X += (int)reqWidth; if (minsize.X >= descriptor.MaxSize) { minsize.X = descriptor.MaxSize - 1; } } else { if (minsize.Y == descriptor.MaxSize - 1) { return false; } minsize.Y += (int)reqHeight; if (minsize.Y >= descriptor.MaxSize) { minsize.Y = descriptor.MaxSize - 1; } } return FindSlot(descriptor, scan, gi, ref minsize); }
public GlyphSegment(CmFont font, int charId) { CharId = charId; _glyphDescriptor = new GlyphDescriptor(font.GlyphTypeface(), CharId); }
protected GlyphDescriptor Localized(GlyphDescriptor gd) => Localized(gd, 0, 0);