Пример #1
0
        public void AddTask(string s, Font font, Brush brush, PointF point)
        {
            if (!(brush is SolidBrush))
            {
                throw new NotSupportedException("brush");
            }
            _colors.Add((brush as SolidBrush).Color);
            MyFont myFont = FontManager.GetFont(FontManager.FindClosestFont(font));

            string[] lines = s.Split('\n');
            float    k     = (font.SizeInPoints / myFont.FontInfo.Pt);
            //k = 1;
            int glyphHeight = (int)(k * myFont.FontInfo.Height);
            int realStrLen  = 0;

            foreach (string str in lines)
            {
                int strLen = str.Length;
                realStrLen += strLen;
                float x = point.X;
                for (int j = 0; j < strLen; j++)
                {
                    if (!myFont.Symbols.ContainsKey(str[j]))
                    {
                        realStrLen--;
                        continue;
                    }
                    GlyphData symbol = myFont.Symbols[str[j]];
                    AddVertex(x + symbol.XOffset * k,
                              point.Y + symbol.YOffset * k,
                              symbol.TextureXPos,
                              symbol.TextureYPos);
                    AddVertex(x + (symbol.XOffset + symbol.Width) * k,
                              point.Y + symbol.YOffset * k,
                              symbol.TextureWidth,
                              symbol.TextureYPos);
                    AddVertex(x + symbol.XOffset * k,
                              point.Y + (symbol.YOffset + symbol.Height) * k,
                              symbol.TextureXPos,
                              symbol.TextureHeight);

                    AddVertex(x + (symbol.XOffset + symbol.Width) * k,
                              point.Y + symbol.YOffset * k,
                              symbol.TextureWidth,
                              symbol.TextureYPos);
                    AddVertex(x + (symbol.XOffset + symbol.Width) * k,
                              point.Y + (symbol.YOffset + symbol.Height) * k,
                              symbol.TextureWidth,
                              symbol.TextureHeight);
                    AddVertex(x + symbol.XOffset * k,
                              point.Y + (symbol.YOffset + symbol.Height) * k,
                              symbol.TextureXPos,
                              symbol.TextureHeight);
                    x += (myFont.Symbols[str[j]].OrigW + (j != strLen - 1 ? myFont.GetKerningDelta(str[j], str[j + 1]) : 0.0f)) * k;
                }
                point.Y += glyphHeight;
            }
            _stringLens.Add(realStrLen);
            _fontTextures.Add(myFont.FontTexture);
        }
Пример #2
0
        private void ProcessTextAdv(string text, int index, out GlyphData glyphData, out Rect uvRect, out float glyphXAdv, out float glyphXOff, out float glyphYOff)
        {
            char glyph     = text[index];
            int  charIndex = (int)glyph > this.charLookup.Length ? 0 : this.charLookup[(int)glyph];

            this.texture.LookupAtlas(charIndex, out uvRect);

            this.GetGlyphData(glyph, out glyphData);
            glyphXOff = -glyphData.OffsetX;
            glyphYOff = -glyphData.OffsetY;

            if (this.kerning && !this.monospace)
            {
                char      glyphNext = index + 1 < text.Length ? text[index + 1] : ' ';
                GlyphData glyphDataNext;
                this.GetGlyphData(glyphNext, out glyphDataNext);

                int minSum = int.MaxValue;
                for (int k = 0; k < glyphData.KerningSamplesRight.Length; k++)
                {
                    minSum = Math.Min(minSum, glyphData.KerningSamplesRight[k] + glyphDataNext.KerningSamplesLeft[k]);
                }

                glyphXAdv = glyphData.Width - glyphData.OffsetX + this.spacing - minSum;
            }
            else
            {
                glyphXAdv = (this.monospace ? this.maxGlyphWidth : (glyphData.Width - glyphData.OffsetX)) + this.spacing;
            }
        }
        public string Serialize1(GlyphData glyphData)
        {
            StringWriter   sw     = new StringWriter();
            JsonTextWriter writer = new JsonTextWriter(sw);


            writer.WriteStartObject();

            if (glyphData.FormDefinitionKey.HasValue)
            {
                writer.WritePropertyName("FormDefinitionKey");
                writer.WriteValue(glyphData.FormDefinitionKey);
            }

            if (glyphData.CorrelationKey.HasValue)
            {
                writer.WritePropertyName("CorrelationKey");
                writer.WriteValue(glyphData.CorrelationKey);
            }

            writer.WritePropertyName("PageNumber");
            writer.WriteValue(glyphData.PageNumber);

            writer.WriteEndObject();

            return(sw.ToString());
        }
Пример #4
0
        public GlyphData AddUniqueGlyph(ushort glyph, float width)
        {
            GlyphData glyphData = new GlyphData(glyph, width);

            if (this.UniqueGlyphs.BinarySearch(glyphData) >= 0)
            {
                return(null);
            }
            int num = 0;

            while (num < this.UniqueGlyphs.Count)
            {
                if (glyphData.Glyph >= this.UniqueGlyphs[num].Glyph)
                {
                    num++;
                    continue;
                }
                this.UniqueGlyphs.Insert(num, glyphData);
                break;
            }
            if (num == this.UniqueGlyphs.Count)
            {
                this.UniqueGlyphs.Add(glyphData);
            }
            return(glyphData);
        }
        /**
         * Build vertical metrics with Identity CIDToGIDMap (for embedding full font).
         */
        private void BuildVerticalMetrics(PdfDictionary cidFont)
        {
            if (!BuildVerticalHeader(cidFont))
            {
                return;
            }

            int cidMax = ttf.NumberOfGlyphs;

            int[]
            gidMetrics = new int[cidMax * 4];
            for (int cid = 0; cid < cidMax; cid++)
            {
                GlyphData glyph = ttf.Glyph.GetGlyph(cid);
                if (glyph == null)
                {
                    gidMetrics[cid * 4] = int.MinValue;
                }
                else
                {
                    gidMetrics[cid * 4]     = cid;
                    gidMetrics[cid * 4 + 1] = ttf.VerticalMetrics.GetAdvanceHeight(cid);
                    gidMetrics[cid * 4 + 2] = ttf.HorizontalMetrics.GetAdvanceWidth(cid);
                    gidMetrics[cid * 4 + 3] = glyph.YMaximum + ttf.VerticalMetrics.GetTopSideBearing(cid);
                }
            }

            cidFont[PdfName.W2] = GetVerticalMetrics(gidMetrics);
        }
Пример #6
0
        public override void Execute(ref GlyphShaderContext context, ref GlyphData data, int index)
        {
            var timeoffset = (Int32)(DateTime.UtcNow.TimeOfDay.TotalMilliseconds / 25); // number here is speed
            var angle      = ((timeoffset + index) / 60.0) * Math.PI * 2.0;             // change for x scale

            data.Y += (Single)Math.Sin(angle) * 10f;                                    // number there is y scale
        }
 internal void AddSymbol(char symbol, GlyphData glyphData)
 {
     if (Symbols.ContainsKey(symbol))
     {
         return;
     }
     Symbols.Add(symbol, glyphData);
 }
        /**
         * Builds vertical metrics with a custom CIDToGIDMap (for embedding font subset).
         */
        private void BuildVerticalMetrics(Dictionary <int, int> cidToGid)
        {
            // The "vhea" and "vmtx" tables that specify vertical metrics shall never be used by a conforming
            // reader. The only way to specify vertical metrics in PDF shall be by means of the DW2 and W2
            // entries in a CIDFont dictionary.

            if (!BuildVerticalHeader(cidFont))
            {
                return;
            }

            float scaling = 1000f / ttf.Header.UnitsPerEm;

            VerticalHeaderTable    vhea = ttf.VerticalHeader;
            VerticalMetricsTable   vmtx = ttf.VerticalMetrics;
            GlyphTable             glyf = ttf.Glyph;
            HorizontalMetricsTable hmtx = ttf.HorizontalMetrics;

            long v_y = (long)Math.Round(vhea.Ascender * scaling);
            long w1  = (long)Math.Round(-vhea.AdvanceHeightMax * scaling);

            PdfArray heights = new PdfArray();
            PdfArray w2      = new PdfArray();
            int      prev    = int.MinValue;
            // Use a sorted list to get an optimal width array
            ISet <int> keys = new HashSet <int>(cidToGid.Keys);

            foreach (int cid in keys)
            {
                // Unlike buildWidths, we look up with cid (not gid) here because this is
                // the original TTF, not the rebuilt one.
                GlyphData glyph = glyf.GetGlyph(cid);
                if (glyph == null)
                {
                    continue;
                }
                long height  = (long)Math.Round((glyph.YMaximum + vmtx.GetTopSideBearing(cid)) * scaling);
                long advance = (long)Math.Round(-vmtx.GetAdvanceHeight(cid) * scaling);
                if (height == v_y && advance == w1)
                {
                    // skip default metrics
                    continue;
                }
                // c [w1_1y v_1x v_1y w1_2y v_2x v_2y ... w1_ny v_nx v_ny]
                if (prev != cid - 1)
                {
                    w2 = new PdfArray();
                    heights.Add(PdfInteger.Get(cid)); // c
                    heights.Add(w2);
                }
                w2.Add(PdfInteger.Get(advance));   // w1_iy
                long width = (long)Math.Round(hmtx.GetAdvanceWidth(cid) * scaling);
                w2.Add(PdfInteger.Get(width / 2)); // v_ix
                w2.Add(PdfInteger.Get(height));    // v_iy
                prev = cid;
            }
            cidFont[PdfName.W2] = heights;
        }
Пример #9
0
 public void Setup()
 {
     CompositeResolver.RegisterAndSetAsDefault(new IJsonFormatter[] { new GlyphDataFormatter() }, new[] { StandardResolver.Default });
     _glyphSource = new GlyphData()
     {
         FormDefinitionKey = Guid.NewGuid(), PageNumber = 1
     };
     _jsonSource = (new JsonGlyphSerializer()).Serialize(_glyphSource);
 }
Пример #10
0
 public GlyphData(GlyphData rhs)
 {
     info        = rhs.info;
     width       = rhs.width;
     height      = rhs.height;
     scaleNeeded = rhs.scaleNeeded;
     // don't support copying bitmap stuff yet.
     System.Diagnostics.Debug.Assert(rhs.bmp == null);
 }
Пример #11
0
            int IComparable.CompareTo(object o1)
            {
                GlyphData glyphData = (GlyphData)o1;

                if (Glyph < glyphData.Glyph)
                {
                    return(-1);
                }
                if (Glyph > glyphData.Glyph)
                {
                    return(1);
                }
                return(0);
            }
Пример #12
0
        /// <summary>
        /// Retrieves information about a single glyph.
        /// </summary>
        /// <param name="glyph">The glyph to retrieve information about.</param>
        /// <param name="data">A struct holding the retrieved information.</param>
        /// <returns>True, if successful, false if the specified glyph is not supported.</returns>
        public bool GetGlyphData(char glyph, out GlyphData data)
        {
            int glyphId = (int)glyph;

            if (glyphId >= this.charLookup.Length)
            {
                data = this.glyphs[0];
                return(false);
            }
            else
            {
                data = this.glyphs[this.charLookup[glyphId]];
                return(true);
            }
        }
Пример #13
0
        public GlyphData Deserialize1(string json)
        {
            Utf8JsonReader reader = new Utf8JsonReader(Encoding.ASCII.GetBytes(json));

            GlyphData glyphData = null;

            while (reader.Read())
            {
                switch (reader.TokenType)
                {
                case JsonTokenType.StartObject:
                    glyphData = new GlyphData();
                    break;

                case JsonTokenType.PropertyName:
                {
                    var value = reader.GetString();

                    reader.Read();
                    if (value.Equals("FormDefinitionKey"))
                    {
                        var s = reader.GetString();
                        if (s != null)
                        {
                            glyphData.FormDefinitionKey = Guid.Parse(s);
                        }
                    }
                    else if (value.Equals("CorrelationKey"))
                    {
                        var v = reader.GetString();
                        if (v != null)
                        {
                            glyphData.CorrelationKey = Guid.Parse(v);
                        }
                    }
                    else if (value.Equals("PageNumber"))
                    {
                        glyphData.PageNumber = reader.GetInt32();
                    }
                    break;
                }

                case JsonTokenType.EndObject:
                    return(glyphData);
                }
            }
            return(glyphData);
        }
        public GlyphData Deserialize1(string json)
        {
            JsonTextReader reader = new JsonTextReader(new StringReader(json));

            GlyphData glyphData = new GlyphData();

            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.PropertyName)
                {
                    switch (reader.Value)
                    {
                    case nameof(GlyphData.FormDefinitionKey):
                    {
                        var value = reader.ReadAsString();
                        if (value != null)
                        {
                            glyphData.FormDefinitionKey = Guid.Parse(value);
                        }

                        break;
                    }

                    case nameof(GlyphData.CorrelationKey):
                    {
                        var value = reader.ReadAsString();
                        if (value != null)
                        {
                            glyphData.CorrelationKey = Guid.Parse(value);
                        }
                        break;
                    }

                    case nameof(GlyphData.PageNumber):
                    {
                        var value = reader.ReadAsInt32();
                        if (value.HasValue)
                        {
                            glyphData.PageNumber = value.Value;
                        }
                        break;
                    }
                    }
                }
            }

            return(glyphData);
        }
Пример #15
0
 /// <summary>
 /// Executes the glyph shader.
 /// </summary>
 /// <param name="context">The glyph shader contxt in which to execute the shader.</param>
 /// <param name="data">The data for the glyph which is being drawn.</param>
 /// <param name="index">The index of the glyph within its source string.</param>
 public void Execute(ref GlyphShaderContext context, ref GlyphData data, Int32 index)
 {
     if (glyphShaderScopedStack != null)
     {
         foreach (var shader in glyphShaderScopedStack)
             shader.Value.Execute(ref context, ref data, index);
     }
     else if (glyphShaderStack != null)
     {
         foreach (var shader in glyphShaderStack)
             shader.Execute(ref context, ref data, index);
     }
     else if (glyphShader != null)
     {
         glyphShader.Execute(ref context, ref data, index);
     }
 }
        public void SetSnapshotAndUpdate(ITextSnapshot snapshot, IList <ITextViewLine> newOrReformattedLines, IList <ITextViewLine> translatedLines)
        {
            if (_glyphs.Count > 0)
            {
                // Go through all the existing visuals and invalidate or transform as appropriate.
                Dictionary <UIElement, GlyphData> newVisuals = new Dictionary <UIElement, GlyphData>(_glyphs.Count);

                foreach (var glyph in _glyphs)
                {
                    GlyphData data = glyph.Value;

                    if (!data.VisualSpan.HasValue)
                    {
                        newVisuals[glyph.Key] = data;
                    }
                    else
                    {
                        data.SetSnapshot(snapshot);

                        SnapshotSpan span = data.VisualSpan.Value;

                        if ((!_margin.TextView.TextViewLines.IntersectsBufferSpan(span)) ||
                            (GetStartingLine(newOrReformattedLines, span, returnLastLine: false) != null))
                        {
                            //Either visual is no longer visible or it crosses a line
                            //that was reformatted.

                            _canvas.Children.Remove(data.Element);
                        }
                        else
                        {
                            newVisuals[data.Element] = data;
                            ITextViewLine line = GetStartingLine(translatedLines, span, returnLastLine: true);
                            if (line != null)
                            {
                                data.SetTop(line.Top - _margin.TextView.ViewportTop);
                            }
                        }
                    }
                }

                _glyphs = newVisuals;
            }
        }
        public GlyphData FromString(string glyph)
        {
            GlyphData glyphData = new GlyphData();

            string[] glyphs = glyph.Split(';');
            if (glyphs[0] != "")
            {
                glyphData.FormDefinitionKey = Guid.Parse(glyphs[0]);
            }
            if (glyphs[1] != "")
            {
                glyphData.CorrelationKey = Guid.Parse(glyphs[1]);
            }
            if (glyphs[2] != "")
            {
                glyphData.PageNumber = Int32.Parse(glyphs[2]);
            }
            return(glyphData);
        }
Пример #18
0
        private GlyphData GetOrCreateGlyph(GlyphIndex glyphIndex)
        {
            // Try to find glyph in dictionary
            WeakReference <GlyphData> glyphDataRef;

            if (_glyphDictionary.TryGetValue(glyphIndex, out glyphDataRef))
            {
                GlyphData glyphData;
                if (glyphDataRef.TryGetTarget(out glyphData))
                {
                    return(glyphData);
                }
                _glyphDictionary.Remove(glyphIndex);
            }

            // Add and return
            {
                GlyphData glyphData = GdiCreateGlyph(glyphIndex);
                _glyphDictionary.Add(glyphIndex, new WeakReference <GlyphData>(glyphData));
                return(glyphData);
            }
        }
        public void RemoveGlyphsByVisualSpan(SnapshotSpan span)
        {
            List <UIElement> glyphsInSpan = new List <UIElement>();

            foreach (var glyph in _glyphs)
            {
                GlyphData data = glyph.Value;

                if (data.VisualSpan.HasValue)
                {
                    if (span.IntersectsWith(data.VisualSpan.Value))
                    {
                        glyphsInSpan.Add(glyph.Key);
                        _canvas.Children.Remove(data.Element);
                    }
                }
            }
            foreach (UIElement element in glyphsInSpan)
            {
                _glyphs.Remove(element);
            }
        }
Пример #20
0
        public string Serialize1(GlyphData glyphData)
        {
            using var ms     = new MemoryStream();
            using var writer = new Utf8JsonWriter(ms);

            writer.WriteStartObject();

            if (glyphData.FormDefinitionKey.HasValue)
            {
                writer.WriteString("FormDefinitionKey", glyphData.FormDefinitionKey.ToString());
            }

            if (glyphData.CorrelationKey.HasValue)
            {
                writer.WriteString("CorrelationKey", glyphData.CorrelationKey.ToString());
            }

            writer.WriteNumber("PageNumber", glyphData.PageNumber);

            writer.WriteEndObject();
            writer.Flush();
            return(Encoding.UTF8.GetString(ms.ToArray()));
        }
        public void AddGlyph(string text, SnapshotSpan span)
        {
            IWpfTextViewLineCollection lines = _margin.TextView.TextViewLines;

            bool visible = _margin.TextView.TextViewLines.IntersectsBufferSpan(span);

            if (visible)
            {
                ITextViewLine line = GetStartingLine(lines, span, returnLastLine: true);
                if (line != null)
                {
                    UIElement element = CreatePromptElement(text);

                    element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
                    double leftPlacement = (17.0 - element.DesiredSize.Width) / 2;
                    Canvas.SetLeft(element, leftPlacement);
                    GlyphData data = new GlyphData(span, element);
                    data.SetTop(line.TextTop - _margin.TextView.ViewportTop);

                    _glyphs[element] = data;
                    _canvas.Children.Add(element);
                }
            }
        }
Пример #22
0
        internal GlyphData AddUniqueGlyph(ushort glyph, float width)
        {
            GlyphData glyphData = new GlyphData(glyph, width);

            if (UniqueGlyphs.BinarySearch(glyphData) >= 0)
            {
                return(null);
            }
            int i;

            for (i = 0; i < UniqueGlyphs.Count; i++)
            {
                if (glyphData.Glyph < UniqueGlyphs[i].Glyph)
                {
                    UniqueGlyphs.Insert(i, glyphData);
                    break;
                }
            }
            if (i == UniqueGlyphs.Count)
            {
                UniqueGlyphs.Add(glyphData);
            }
            return(glyphData);
        }
Пример #23
0
        // todo: use this renderer; it's much better for monochrome fonts. for color there's still no better solution i know of.
        //// https://stackoverflow.com/questions/9080231/how-to-save-geometry-as-image
        //public static GenerateEmojiBitmapResults GenerateFontMap2(string fontName, int WidthAndHeight, string outputFileName)
        //{
        //  GlyphTypeface font;
        //  if (File.Exists(fontName))
        //  {
        //    font = new GlyphTypeface(new Uri(fontName));
        //  }
        //  else
        //  {
        //    Typeface face = new Typeface(fontName);
        //    face.TryGetGlyphTypeface(out font);
        //  }

        //  //int ColumnCount = 10;
        //  //int MaxDrawCount = 30; // use int.MaxValue to draw them all
        //  double fontSize = WidthAndHeight;
        //  // the height of each cell has to include over/underhanging glyphs
        //  SizeF cellSize = new SizeF((float)fontSize, (float)(fontSize * font.Height));

        //  var Glyphs = from glyphIndex in font.CharacterToGlyphMap.Values
        //               select font.GetGlyphOutline(glyphIndex, fontSize, 1d);

        //  int ColumnCount = (int)Math.Ceiling(Math.Sqrt(Glyphs.Count()));

        //  // now create the visual we'll draw them to
        //  DrawingVisual viz = new DrawingVisual();
        //  //int drawCount = -1;
        //  using (DrawingContext dc = viz.RenderOpen())
        //  {
        //    foreach (var g in Glyphs)
        //    {
        //      drawCount++;
        //      if (g.IsEmpty()) continue; // don't draw the blank ones
        //                                 // center horizontally in the cell
        //      double xOffset = (drawCount % ColumnCount) * cellSize.Width + cellSize.Width / 2d - g.Bounds.Width / 2d;
        //      // place the character on the baseline of the cell
        //      double yOffset = (drawCount / ColumnCount) * cellSize.Height + fontSize * font.Baseline;
        //      dc.PushTransform(new TranslateTransform(xOffset, yOffset));
        //      dc.DrawGeometry(System.Windows.Media.Brushes.Red, null, g);
        //      dc.Pop(); // get rid of the transform
        //    }
        //  }

        //  int RowCount = drawCount / ColumnCount;
        //  if (drawCount % ColumnCount != 0)
        //    RowCount++; // to include partial rows
        //  int bitWidth = (int)Math.Ceiling((double)(cellSize.Width * ColumnCount));
        //  int bitHeight = (int)Math.Ceiling((double)(cellSize.Height * RowCount));
        //  RenderTargetBitmap bmp = new RenderTargetBitmap(
        //                                                  bitWidth, bitHeight,
        //                                                  96, 96,
        //                                                  PixelFormats.Pbgra32);
        //  bmp.Render(viz);

        //  PngBitmapEncoder encoder = new PngBitmapEncoder();
        //  encoder.Frames.Add(BitmapFrame.Create(bmp));
        //  using (FileStream file = new FileStream(outputFileName, FileMode.Create))
        //    encoder.Save(file);
        //}



        public static GenerateEmojiBitmapResults GenerateEmojiBitmap(string fontName, int cellWidth, int cellHeight,
                                                                     float additionalScale, int shiftX, int shiftY, IEnumerable <EmojiInfo> codepointsToInclude,
                                                                     System.Drawing.Color[] backgroundPalette, System.Drawing.Color[] textPalette, float?aspectToleranceFromTarget, bool tryToFit,
                                                                     System.Windows.FontStyle fontStyle, System.Windows.FontWeight fontWeight, System.Windows.FontStretch fontStretch,
                                                                     bool strictGlyphChecking, d2.TextAntialiasMode aaMode)
        {
            System.Windows.Media.FontFamily fm = new System.Windows.Media.FontFamily(fontName);
            System.Windows.Media.Typeface   tf = new System.Windows.Media.Typeface(fm, fontStyle, fontWeight, fontStretch);
            PetsciiMapgen.ProgressReporter  pr = new PetsciiMapgen.ProgressReporter((ulong)codepointsToInclude.Count() * (ulong)backgroundPalette.Length * (ulong)textPalette.Length);
            if (!tf.TryGetGlyphTypeface(out System.Windows.Media.GlyphTypeface gtf))
            {
                PetsciiMapgen.Log.WriteLine("!!!!!!!!!! FONT FAMILY HAS NO GLYPH MAP; you will end up with unsupported glyphs in the map.");
                // throw new Exception();
            }

            // select codepoints to actually use
            PetsciiMapgen.Utils.ValueRangeInspector rangeX          = new PetsciiMapgen.Utils.ValueRangeInspector();
            PetsciiMapgen.Utils.ValueRangeInspector rangeY          = new PetsciiMapgen.Utils.ValueRangeInspector();
            PetsciiMapgen.Utils.ValueRangeInspector allAspects      = new PetsciiMapgen.Utils.ValueRangeInspector();
            PetsciiMapgen.Utils.ValueRangeInspector selectedAspects = new PetsciiMapgen.Utils.ValueRangeInspector();
            int rejectedBecauseNotInTypeface = 0;
            int rejectedBecauseAspect        = 0;

            int   targetWidth  = cellWidth;
            int   targetHeight = cellHeight;
            float targetAspect = (float)targetWidth / targetHeight;

            EmojiTest.Direct2DText dt = new EmojiTest.Direct2DText();
            dt.SetFont(fontName, targetHeight);

            var emoji = codepointsToInclude.Select(e =>
            {
                pr.Visit();
                GlyphData ret = new GlyphData();
                ret.info      = e;
                //ret.str = char.ConvertFromUtf32(cp);
                var sz     = dt.GetTextSize(ret.info.str);
                ret.width  = sz.Width;
                ret.height = sz.Height;
                rangeX.Visit(ret.width);
                rangeY.Visit(ret.height);
                allAspects.Visit(ret.width / ret.height);
                ret.scaleNeeded = 1;
                if (tryToFit)
                {
                    if (ret.height > 0 && ret.width > 0)
                    {
                        float scaleNeededY = (float)targetHeight / ret.height;// factor to match target
                        float scaleNeededX = (float)targetWidth / ret.width;
                        ret.scaleNeeded    = Math.Min(scaleNeededX, scaleNeededY);
                    }
                    else
                    {
                        ret.scaleNeeded = -1;
                    }
                }
                return(ret);
            })
                        .Where(o =>
            {
                if (o.info.forceInclude)
                {
                    return(true);
                }
                if (o.info.str == "\r" || o.info.str == "\n")
                {
                    return(false);
                }
                if (gtf != null)
                {
                    if (!gtf.CharacterToGlyphMap.ContainsKey(o.info.cps[0]))
                    {
                        rejectedBecauseNotInTypeface++;
                        if (strictGlyphChecking)
                        {
                            return(false);
                        }
                    }
                }
                float aspect = o.width / o.height;
                float da     = Math.Abs(aspect - targetAspect);
                if (aspectToleranceFromTarget.HasValue && da > aspectToleranceFromTarget)
                {
                    rejectedBecauseAspect++;
                    return(false);
                }

                selectedAspects.Visit(aspect);
                return(true);
            })
                        .OrderBy(o => o.scaleNeeded).ToArray();

            PetsciiMapgen.Log.WriteLine("EMOJI font encountered aspect ratios between {0}", allAspects);
            PetsciiMapgen.Log.WriteLine("Chars rejected because they don't have glyphs in this typeface: {0:N0}", rejectedBecauseNotInTypeface);
            PetsciiMapgen.Log.WriteLine("Chars rejected because aspect ratio out of range: {0:N0}", rejectedBecauseAspect);
            if (aspectToleranceFromTarget.HasValue)
            {
                PetsciiMapgen.Log.WriteLine("EMOJI font allowed aspect ratios between {0}", selectedAspects);
            }

            int totalCharCount = emoji.Count() * backgroundPalette.Length * textPalette.Length;
            int scaleChanges   = 0;

            int columns   = (int)Math.Ceiling(Math.Sqrt(totalCharCount));
            int rows      = columns;// we're aiming for square bitmap.
            int imgWidth  = columns * targetWidth;
            int imgHeight = rows * targetHeight;

            List <GlyphData> fullEmoji = new List <GlyphData>(totalCharCount);

            if (emoji.Length < 2)
            {
                throw new Exception("NOt enough glyphs to generate anything meaningful.");
            }

            foreach (var backgroundColor in backgroundPalette)
            {
                foreach (var textColor in textPalette)
                {
                    var bmp = new System.Drawing.Bitmap(imgWidth, imgHeight);
                    using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp))
                    {
                        float lastScale = 0;
                        //int iemoji = 0;
                        var pr2 = new PetsciiMapgen.ProgressReporter((ulong)emoji.Count());
                        //foreach (var e in emoji)
                        for (int iemoji = 0; iemoji < emoji.Length; ++iemoji)
                        {
                            var e = emoji[iemoji];
                            pr2.Visit();
                            if (e.scaleNeeded <= 0)
                            {
                                continue;
                            }
                            if (Math.Abs(lastScale - e.scaleNeeded) > 0.001)
                            {
                                scaleChanges++;
                                dt.SetFont(fontName, targetHeight * e.scaleNeeded * additionalScale);
                            }

                            //SharpDX.Size2F sz;
                            var n = new GlyphData(e);
                            fullEmoji.Add(n);

                            RawColor4 bg = new RawColor4(backgroundColor.R / 255.0f, backgroundColor.G / 255.0f, backgroundColor.B / 255.0f, 1);
                            dt.SetColor(textColor);
                            n.bmp = dt.TextToBitmap(n.info.str, out n.bmpSize, bg, aaMode);

                            // offset where to blit from, so it's centered.
                            int ox = (int)((n.bmpSize.Width - targetWidth) / 2);
                            int oy = (int)((n.bmpSize.Height - targetHeight) / 2);
                            n.blitSourcRect = new System.Drawing.Rectangle(ox - shiftX, oy - shiftY, targetWidth, targetHeight);
                            n.bgColor       = backgroundColor;
                            n.textColor     = textColor;

                            //int y = iemoji / columns;
                            //int x = iemoji % columns;
                            //g.DrawImage(bmpChar,
                            //  new System.Drawing.Rectangle(x * targetWidth, y * targetHeight, targetWidth, targetHeight),
                            //  new System.Drawing.Rectangle(ox - shiftX, oy - shiftY, targetWidth, targetHeight), System.Drawing.GraphicsUnit.Pixel
                            //  );

                            //bmpChar.Dispose();
                            //iemoji++;
                        }
                    }
                }
            }

            PetsciiMapgen.Log.WriteLine("Scale changes: {0}", scaleChanges);
            PetsciiMapgen.Log.WriteLine("Total char count: {0}", fullEmoji.Count);
            PetsciiMapgen.Log.WriteLine("Image size to hold entire colored charset: {0}, {1}", imgWidth, imgHeight);

            GenerateEmojiBitmapResults rv = new GenerateEmojiBitmapResults();

            //rv.bmp = bmp;
            rv.columns  = columns;
            rv.rows     = rows;
            rv.AllCells = fullEmoji.ToArray();
            return(rv);
        }
Пример #24
0
		private IEnumerable<Point> CalculateAnnotationLocations(GlyphData[] pageLabels, AnnotationData annot)
		{
			if (annot.Annotation.PositionMethod == PositioningMethod.Absolute)
			{
				yield return annot.Annotation.Position;
			}

			IEnumerable<GlyphData> matches;

			switch (annot.Annotation.MatchMethod)
			{
				case null:
				case LabelMatchMethod.ExactMatch:
					matches = pageLabels.Where(g => g.Glyphs.UnicodeString == annot.LabelMatchText);
					break;
				case LabelMatchMethod.ExactMatchIgnoreCase:
					matches = pageLabels.Where(g => g.LowerCaseText == annot.LabelMatchText);
					break;
				case LabelMatchMethod.RegularExpression:
					matches = pageLabels.Where(g => annot.LabelMatcher.IsMatch(g.LowerCaseText));
					break;
				default:
					throw new ArgumentOutOfRangeException("Invalid MatchMethod");
			}

			foreach (var match in matches)
			{
				var glyphs = match.Glyphs;
				var anchorPos = glyphs.RenderTransform.Transform(
					new Point(glyphs.OriginX, glyphs.OriginY));
				var pos = new Point(annot.Annotation.Position.X + anchorPos.X,
					(annot.Annotation.Position.Y + anchorPos.Y) - annot.Annotation.TextSize);

				yield return pos;
			}
		}
Пример #25
0
		private void ApplyAnnotation(AnnotationData annot, FixedPage page, int pageNumber, GlyphData[] pageLabels, Canvas canvas)
		{
			foreach (var location in CalculateAnnotationLocations(pageLabels, annot))
			{
				_annotatedPages.Add(pageNumber);
				
				var annotationText = new TextBlock(new Run(annot.Annotation.Text)
				{
					Foreground = GetForegroundBrush(annot.Annotation.ForegroundColor),
					FontSize = annot.Annotation.TextSize,
					FontWeight = annot.Annotation.FontWeight ?? FontWeights.Normal,
					FontFamily = new FontFamily(string.IsNullOrEmpty(annot.Annotation.FontName)
						? "Arial"
						: annot.Annotation.FontName),
					FontStyle = annot.Annotation.IsItalic 
						? FontStyles.Italic
						: FontStyles.Normal
				});

				if (annot.Annotation.CustomTransform != null)
				{
					annotationText.RenderTransform = annot.Annotation.CustomTransform;
				}

				Canvas.SetLeft(annotationText, location.X);
				Canvas.SetTop(annotationText, location.Y);
				canvas.Children.Add(annotationText);
			}
		}
Пример #26
0
        public void AddGlyph(string text, SnapshotSpan span)
        {
            IWpfTextViewLineCollection lines = _margin.TextView.TextViewLines;

            bool visible = _margin.TextView.TextViewLines.IntersectsBufferSpan(span);
            if (visible) {
                ITextViewLine line = GetStartingLine(lines, span, returnLastLine: true);
                if (line != null) {
                    UIElement element = CreatePromptElement(text);

                    element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
                    double leftPlacement = (17.0 - element.DesiredSize.Width) / 2;
                    Canvas.SetLeft(element, leftPlacement);
                    GlyphData data = new GlyphData(span, element);
                    data.SetTop(line.TextTop - _margin.TextView.ViewportTop);

                    _glyphs[element] = data;
                    _canvas.Children.Add(element);
                }
            }
        }
Пример #27
0
        public void DynamicRenderAtlas(GraphicsDevice gd, uint character, int texDims = 1024, uint baseChar = 0x54)
        {
            if (System.Threading.Thread.CurrentThread != GameMain.MainThread)
            {
                CrossThread.RequestExecutionOnMainThread(() =>
                {
                    DynamicRenderAtlas(gd, character, texDims, baseChar);
                });
                return;
            }

            byte[]      bitmap;
            int         glyphWidth; int glyphHeight;
            Fixed26Dot6 horizontalAdvance;
            Vector2     drawOffset;

            lock (mutex)
            {
                if (texCoords.ContainsKey(character))
                {
                    return;
                }
                if (textures.Count == 0)
                {
                    this.texDims  = texDims;
                    this.baseChar = baseChar;
                    face.SetPixelSizes(0, size);
                    face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal);
                    baseHeight = face.Glyph.Metrics.Height.ToInt32();
                    textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
                }

                uint glyphIndex = face.GetCharIndex(character);
                if (glyphIndex == 0)
                {
                    return;
                }

                face.SetPixelSizes(0, size);
                face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0)
                {
                    if (face.Glyph.Metrics.HorizontalAdvance > 0)
                    {
                        //glyph is empty, but char still applies advance
                        GlyphData blankData = new GlyphData();
                        blankData.advance  = (float)face.Glyph.Metrics.HorizontalAdvance;
                        blankData.texIndex = -1; //indicates no texture because the glyph is empty
                        texCoords.Add(character, blankData);
                    }
                    return;
                }

                //stacktrace doesn't really work that well when RenderGlyph throws an exception
                face.Glyph.RenderGlyph(RenderMode.Normal);
                bitmap            = (byte[])face.Glyph.Bitmap.BufferData.Clone();
                glyphWidth        = face.Glyph.Bitmap.Width;
                glyphHeight       = bitmap.Length / glyphWidth;
                horizontalAdvance = face.Glyph.Metrics.HorizontalAdvance;
                drawOffset        = new Vector2(face.Glyph.BitmapLeft, baseHeight * 14 / 10 - face.Glyph.BitmapTop);

                if (glyphWidth > texDims - 1 || glyphHeight > texDims - 1)
                {
                    throw new Exception(filename + ", " + size.ToString() + ", " + (char)character + "; Glyph dimensions exceed texture atlas dimensions");
                }

                currentDynamicAtlasNextY = Math.Max(currentDynamicAtlasNextY, glyphHeight + 2);
                if (currentDynamicAtlasCoords.X + glyphWidth + 2 > texDims - 1)
                {
                    currentDynamicAtlasCoords.X  = 0;
                    currentDynamicAtlasCoords.Y += currentDynamicAtlasNextY;
                    currentDynamicAtlasNextY     = 0;
                }
                //no more room in current texture atlas, create a new one
                if (currentDynamicAtlasCoords.Y + glyphHeight + 2 > texDims - 1)
                {
                    currentDynamicAtlasCoords.X = 0;
                    currentDynamicAtlasCoords.Y = 0;
                    currentDynamicAtlasNextY    = 0;
                    textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
                    currentDynamicPixelBuffer = null;
                }

                GlyphData newData = new GlyphData
                {
                    advance    = (float)horizontalAdvance,
                    texIndex   = textures.Count - 1,
                    texCoords  = new Rectangle((int)currentDynamicAtlasCoords.X, (int)currentDynamicAtlasCoords.Y, glyphWidth, glyphHeight),
                    drawOffset = drawOffset
                };
                texCoords.Add(character, newData);

                if (currentDynamicPixelBuffer == null)
                {
                    currentDynamicPixelBuffer = new uint[texDims * texDims];
                    textures[newData.texIndex].GetData <uint>(currentDynamicPixelBuffer, 0, texDims * texDims);
                }

                for (int y = 0; y < glyphHeight; y++)
                {
                    for (int x = 0; x < glyphWidth; x++)
                    {
                        byte byteColor = bitmap[x + y * glyphWidth];
                        currentDynamicPixelBuffer[((int)currentDynamicAtlasCoords.X + x) + ((int)currentDynamicAtlasCoords.Y + y) * texDims] = (uint)(byteColor << 24 | 0x00ffffff);
                    }
                }
                textures[newData.texIndex].SetData <uint>(currentDynamicPixelBuffer);

                currentDynamicAtlasCoords.X += glyphWidth + 2;
            }
        }
Пример #28
0
 /// <summary>
 /// Executes the glyph shader.
 /// </summary>
 /// <param name="data">The data for the glyph which is being drawn.</param>
 /// <param name="index">The index of the glyph within its source string.</param>
 public void Execute(ref GlyphData data, Int32 index)
 {
     glyphShader.Execute(ref this, ref data, index);
 }
 public override void Execute(ref GlyphShaderContext context, ref GlyphData data, Int32 index)
 {
     data.Color = Colors[index % Colors.Length];
 }
Пример #30
0
 public string Serialize(GlyphData glyphData)
 {
     return(JsonSerializer.Serialize(glyphData));
 }
 internal void AddSymbol(char symbol, GlyphData glyphData)
 {
   if(Symbols.ContainsKey(symbol))
     return;
   Symbols.Add(symbol, glyphData);
 }
Пример #32
0
		SpriteFont
#endif
		(Texture2D texture, Stream metricsDataStream, float internalScale)
		{
			this.texture = texture;
			this.internalScale = internalScale;

			using(BinaryReader br = new BinaryReader(metricsDataStream, Encoding.Unicode))
			{
				// Check for signature "ExEnFont"
				if(br.ReadInt32() != 0x6E457845 || br.ReadInt32() != 0x746E6F46)
					throw new ContentLoadException("Invalid ExEn font metrics file");
				if(br.ReadInt32() != 0)
					throw new ContentLoadException("Invalid version of ExEn font metrics file");

				// Read common properties:
				LineSpacing = br.ReadInt32();
				Spacing = br.ReadInt32();
				if(br.ReadBoolean())
					DefaultCharacter = br.ReadChar();
				else
					DefaultCharacter = null;

				// Read glyph list:
				int count = br.ReadInt32();
				for(int i = 0; i < count; i++)
				{
					char c = br.ReadChar();
					GlyphData g = new GlyphData();
					g.Glyph = br.ReadRectangle();
					g.Cropping = br.ReadRectangle();
					g.Kerning = br.ReadVector3();
					characterData.Add(c, g);
				}
			}
		}
 public string Serialize(GlyphData glyphData)
 {
     return(JsonConvert.SerializeObject(glyphData));
 }
Пример #34
0
        /// <summary>
        /// Applies a new set of rendered glyphs to the <see cref="Font"/>, adjusts its typeface metadata and clears out the <see cref="GlyphsDirty"/> flag.
        /// This method is used by the editor to update a Font after adjusting its properties.
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="atlas"></param>
        /// <param name="glyphs"></param>
        /// <param name="metrics"></param>
        public void SetGlyphData(PixelData bitmap, Rect[] atlas, GlyphData[] glyphs, FontMetrics metrics)
        {
            this.ReleaseResources();

            this.glyphs = glyphs;
            this.GenerateCharLookup();

            this.pixelData = new Pixmap(bitmap);
            this.pixelData.Atlas = atlas.ToList();

            this.metrics = metrics;

            // Copy metrics data into local fields.
            // Remove this on the next major version step.
            this.size = metrics.Size;
            this.height = metrics.Height;
            this.ascent = metrics.Ascent;
            this.bodyAscent = metrics.BodyAscent;
            this.descent = metrics.Descent;
            this.baseLine = metrics.BaseLine;
            this.monospace = metrics.Monospace;

            this.maxGlyphWidth = 0;
            for (int i = 0; i < this.glyphs.Length; i++)
            {
                this.maxGlyphWidth = Math.Max(this.maxGlyphWidth, this.glyphs[i].Width);
            }

            this.UpdateKerningData();
            this.GenerateTexture();
            this.GenerateMaterial();
        }
Пример #35
0
        public void GenerateFontSource(TextWriter writer, FontDescriptor fontDescriptor)
        {
            XmlWriterSettings settings = new XmlWriterSettings();

            settings.CloseOutput = false;
            settings.Indent      = true;
            settings.IndentChars = "    ";
            XmlWriter wr = XmlWriter.Create(writer, settings);

            try {
                FontData fontData = new FontData(fontDescriptor.Font);

                wr.WriteStartDocument();

                wr.WriteComment(" Creado con EosFontGenerator ");
                wr.WriteComment(" No modificar ");
                wr.WriteComment(String.Format(" Name  : {0} ", fontData.Name));
                wr.WriteComment(String.Format(" Size  : {0}pt ", fontDescriptor.Font.SizeInPoints));
                wr.WriteComment(String.Format(" Style : {0} ", fontDescriptor.Font.Style));

                wr.WriteStartElement("resources");
                wr.WriteStartElement("fontResource");
                wr.WriteAttributeString("version", "2.0");
                wr.WriteAttributeString("resourceId", fontData.Name.Replace(", ", ""));

                wr.WriteStartElement("font");
                wr.WriteAttributeString("name", fontData.Name);
                wr.WriteAttributeString("height", fontData.Height.ToString());
                wr.WriteAttributeString("ascent", fontData.Ascent.ToString());
                wr.WriteAttributeString("descent", fontData.Descent.ToString());

                foreach (CharacterDescriptor characterDescriptor in fontDescriptor.CharacterDescriptors)
                {
                    char        ch          = characterDescriptor.Character;
                    GlyphData   glyphData   = new GlyphData(characterDescriptor.Font, ch, GlyphFormat.L1);
                    GlyphBitmap glyphBitmap = glyphData.Glyph;

                    wr.WriteStartElement("char");
                    wr.WriteAttributeString("code", String.Format("0x{0:X2}", Convert.ToInt32(ch)));
                    wr.WriteAttributeString("advance", glyphData.Advance.ToString());

                    if (glyphBitmap != null)
                    {
                        wr.WriteStartElement("bitmap");
                        wr.WriteAttributeString("format", "L1");
                        wr.WriteAttributeString("left", glyphBitmap.OffsetX.ToString());
                        wr.WriteAttributeString("top", glyphBitmap.OffsetY.ToString());
                        wr.WriteAttributeString("width", glyphBitmap.Width.ToString());
                        wr.WriteAttributeString("height", glyphBitmap.Height.ToString());
                        for (int y = 0; y < glyphBitmap.Height; y++)
                        {
                            wr.WriteStartElement("scanLine");
                            StringBuilder sb = new StringBuilder();
                            try {
                                int black = Color.Black.ToArgb();
                                for (int x = 0; x < glyphBitmap.Width; x++)
                                {
                                    if (glyphBitmap.Bitmap.GetPixel(x, y).ToArgb() == black)
                                    {
                                        sb.Append('1');
                                    }
                                    else
                                    {
                                        sb.Append('.');
                                    }
                                }
                            }
                            catch {
                            }

                            wr.WriteString(sb.ToString());
                            wr.WriteEndElement();
                        }
                        wr.WriteEndElement();
                    }

                    wr.WriteEndElement();
                }

                wr.WriteEndElement();

                wr.WriteEndElement();
                wr.WriteEndElement();
                wr.WriteEndDocument();
            }
            finally {
                wr.Close();
            }
        }
Пример #36
0
        public override void Execute(ref GlyphShaderContext context, ref GlyphData data, int index)
        {
            var offset = (Int32)(DateTime.UtcNow.TimeOfDay.TotalMilliseconds / 50);

            data.Color = colors[(index + offset) % colors.Length];
        }
Пример #37
0
        // load one single glyph into the cache
        private GlyphData Load(char glyph, FormatOptions formatOptions)
        {
            int fontId = GetFontId(IsAnsiChar(glyph) ? formatOptions.AnsiFont : formatOptions.Font);
            var font = m_registeredFonts[fontId];
            uint glyphId = ((uint)fontId << 16) + glyph;

            GlyphData glyphData;
            if (m_loadedGlyphs.TryGetValue(glyphId, out glyphData))
            {
                glyphData.m_timeStamp = m_timeStamp;
                return glyphData;
            }

            var str = glyph.ToString();
            var chRect = MeasureCharacter(glyph, m_registeredFonts[fontId].m_fontObject);
            chRect.Inflate(font.m_outlineThickness * 0.5f, font.m_outlineThickness * 0.5f);

            int width = Math.Max((int)Math.Ceiling(chRect.Width), 1);
            int height = Math.Max((int)Math.Ceiling(chRect.Height), 1);
            int pagesInX = (width - 1) / PageSize + 1;
            int pagesInY = (height - 1) / PageSize + 1;

            GlyphPage[] pages = new GlyphPage[pagesInX * pagesInY];
            for (int i = 0; i < pages.Length; ++i)
            {
                pages[i].m_x = i % pagesInX;
                pages[i].m_y = i / pagesInX;
                pages[i].m_pageIndex = RequestPage();
            }

            using (var bmp = new SystemDrawing.Bitmap(pagesInX * PageSize, pagesInY * PageSize))
            using (var g = SystemDrawing.Graphics.FromImage(bmp))
            using (var memStream = new MemoryStream())
            {
                // draw text using GDI+
                g.TextRenderingHint = SystemDrawing.Text.TextRenderingHint.AntiAliasGridFit;
                g.SmoothingMode = SystemDrawing.Drawing2D.SmoothingMode.AntiAlias;
                g.InterpolationMode = SystemDrawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                if (font.m_outlineThickness > 0)
                {
                    SystemDrawing.Pen outlinePen;
                    if (!m_outlinePensWithWidths.TryGetValue(font.m_outlineThickness, out outlinePen))
                    {
                        outlinePen = new SystemDrawing.Pen(SystemDrawing.Color.Gray, font.m_outlineThickness);
                        outlinePen.MiterLimit = font.m_outlineThickness;
                        m_outlinePensWithWidths.Add(font.m_outlineThickness, outlinePen);
                    }

                    // draw outline
                    using (var outlinePath = new SystemDrawing.Drawing2D.GraphicsPath())
                    {
                        outlinePath.AddString(str,
                            font.m_fontObject.FontFamily,
                            (int)font.m_fontObject.Style,
                            g.DpiX * font.m_fontObject.SizeInPoints / 72,
                            new SystemDrawing.PointF(-chRect.Left, -chRect.Top),
                            SystemDrawing.StringFormat.GenericDefault);
                        g.DrawPath(outlinePen, outlinePath);
                        g.FillPath(m_whiteBrush, outlinePath);
                    }
                }
                else
                {
                    g.DrawString(str, font.m_fontObject, m_whiteBrush, new SystemDrawing.PointF(-chRect.Left, -chRect.Top));
                }

                bmp.Save(memStream, System.Drawing.Imaging.ImageFormat.Png);
                using (var tmpTexture = Texture2D.FromStream(GameApp.Instance.GraphicsDevice, memStream))
                {
                    var device = GameApp.Instance.GraphicsDevice;
                    device.DepthStencilState = DepthStencilState.None;
                    device.RasterizerState = RasterizerState.CullCounterClockwise;
                    device.Indices = null;

                    m_effect.CurrentTechnique = m_techBlit;
                    m_paramTexture.SetValue(tmpTexture);

                    foreach (var batch in pages.GroupBy(page => page.m_pageIndex / PagesInOneCacheTexture))
                    {
                        var textureId = batch.Key;
                        device.SetRenderTarget(m_cacheTextures[textureId].m_physicalRTTexture);
                        device.BlendState = m_channelMasks[textureId % 4];

                        var pagesInBatch = batch.ToArray();
                        var vertices = new VertexDataBlit[pagesInBatch.Length * 6];
                        for (int i = 0; i < pagesInBatch.Length; ++i)
                        {
                            var page = pagesInBatch[i];
                            var dstRectLeft = (page.m_pageIndex % PagesInOneCacheTexture) % PagesInOneRow * PageSize;
                            var dstRectTop = (page.m_pageIndex % PagesInOneCacheTexture) / PagesInOneRow * PageSize;

                            float posLeft = (dstRectLeft - 0.5f) / CacheTextureSize * 2 - 1;
                            float posTop = 1 - (dstRectTop - 0.5f) / CacheTextureSize * 2;
                            float posWidth = PageSize / (float)CacheTextureSize * 2;
                            float posHeight = -PageSize / (float)CacheTextureSize * 2;

                            float uvLeft = page.m_x / (float)pagesInX;
                            float uvTop = page.m_y / (float)pagesInY;
                            float uvWidth = 1.0f / pagesInX;
                            float uvHeight = 1.0f / pagesInY;

                            // left-top
                            vertices[i * 6 + 0].pos = new Vector2(posLeft, posTop);
                            vertices[i * 6 + 0].uv = new Vector2(uvLeft, uvTop);

                            // right-top
                            vertices[i * 6 + 1].pos = vertices[i * 6 + 4].pos = new Vector2(posLeft + posWidth, posTop);
                            vertices[i * 6 + 1].uv = vertices[i * 6 + 4].uv = new Vector2(uvLeft + uvWidth, uvTop);

                            // left-bottom
                            vertices[i * 6 + 2].pos = vertices[i * 6 + 3].pos = new Vector2(posLeft, posTop + posHeight);
                            vertices[i * 6 + 2].uv = vertices[i * 6 + 3].uv = new Vector2(uvLeft, uvTop + uvHeight);

                            // right-bottom
                            vertices[i * 6 + 5].pos = new Vector2(posLeft + posWidth, posTop + posHeight);
                            vertices[i * 6 + 5].uv = new Vector2(uvLeft + uvWidth, uvTop + uvHeight);
                        }

                        foreach (var pass in m_techBlit.Passes)
                        {
                            pass.Apply();
                            device.DrawUserPrimitives(PrimitiveType.TriangleList, vertices, 0, pagesInBatch.Length * 2);
                        }
                    }

                    device.SetRenderTarget(null);
                }
            }

            glyphData = new GlyphData();
            glyphData.m_pageIndices = new int[pagesInX, pagesInY];
            pages.ForEach(page => glyphData.m_pageIndices[page.m_x, page.m_y] = page.m_pageIndex);
            glyphData.m_glyphSize = chRect.Size;
            glyphData.m_timeStamp = m_timeStamp;
            m_loadedGlyphs.Add(glyphId, glyphData);
            return glyphData;
        }
Пример #38
0
        private void ProcessTextAdv(string text, int index, out GlyphData glyphData, out Rect uvRect, out float glyphXAdv, out float glyphXOff)
        {
            char glyph = text[index];
            int charIndex = (int)glyph > CharLookup.Length ? 0 : CharLookup[(int)glyph];
            this.texture.LookupAtlas(charIndex, out uvRect);

            this.GetGlyphData(glyph, out glyphData);
            glyphXOff = -glyphData.offsetX;

            if (this.kerning && !this.monospace && !this.needsReload)
            {
                char glyphNext = index + 1 < text.Length ? text[index + 1] : ' ';
                GlyphData glyphDataNext;
                this.GetGlyphData(glyphNext, out glyphDataNext);

                int minSum = int.MaxValue;
                for (int k = 0; k < glyphData.kerningSamplesRight.Length; k++)
                    minSum = Math.Min(minSum, glyphData.kerningSamplesRight[k] + glyphDataNext.kerningSamplesLeft[k]);

                glyphXAdv = (this.monospace ? this.maxGlyphWidth : -glyphData.offsetX + glyphData.width) + this.spacing - minSum;
            }
            else
                glyphXAdv = (this.monospace ? this.maxGlyphWidth : -glyphData.offsetX + glyphData.width) + this.spacing;
        }
Пример #39
0
 /// <summary>
 /// Retrieves information about a single glyph.
 /// </summary>
 /// <param name="glyph">The glyph to retrieve information about.</param>
 /// <param name="data">A struct holding the retrieved information.</param>
 /// <returns>True, if successful, false if the specified glyph is not supported.</returns>
 public bool GetGlyphData(char glyph, out GlyphData data)
 {
     int glyphId = (int)glyph;
     if (glyphId >= CharLookup.Length)
     {
         data = this.glyphs[0];
         return false;
     }
     else
     {
         data = this.glyphs[CharLookup[glyphId]];
         return true;
     }
 }
Пример #40
0
 public override void Execute(ref GlyphShaderContext context, ref GlyphData data, int index)
 {
     data.X += r.Next(-2, 2);
     data.Y += r.Next(-2, 2);
 }
Пример #41
0
        /// <summary>
        /// Renders the font into at least one texture atlas, which is simply a collection of all glyphs in the ranges defined by charRanges.
        /// Don't call this too often or with very large sizes.
        /// </summary>
        /// <param name="gd">Graphics device, required to create textures.</param>
        /// <param name="charRanges">Character ranges between each even element with their corresponding odd element. Default is 0x20 to 0xFFFF.</param>
        /// <param name="texDims">Texture dimensions. Default is 512x512.</param>
        /// <param name="baseChar">Base character used to shift all other characters downwards when rendering. Defaults to T.</param>
        public void RenderAtlas(GraphicsDevice gd, uint[] charRanges = null, int texDims = 512, uint baseChar = 0x54)
        {
            if (charRanges == null)
            {
                charRanges = new uint[] { 0x20, 0xFFFF };
            }
            this.charRanges = charRanges;
            this.texDims    = texDims;
            this.baseChar   = baseChar;

            face.SetPixelSizes(0, size);
            textures.ForEach(t => t.Dispose());
            textures.Clear();
            texCoords.Clear();

            uint[] pixelBuffer = new uint[texDims * texDims];
            for (int i = 0; i < texDims * texDims; i++)
            {
                pixelBuffer[i] = 0;
            }

            textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
            int texIndex = 0;

            Vector2 currentCoords = Vector2.Zero;
            int     nextY         = 0;

            face.LoadGlyph(face.GetCharIndex(baseChar), LoadFlags.Default, LoadTarget.Normal);
            baseHeight = face.Glyph.Metrics.Height.ToInt32();
            //lineHeight = baseHeight;
            for (int i = 0; i < charRanges.Length; i += 2)
            {
                uint start = charRanges[i];
                uint end   = charRanges[i + 1];
                for (uint j = start; j <= end; j++)
                {
                    uint glyphIndex = face.GetCharIndex(j);
                    if (glyphIndex == 0)
                    {
                        continue;
                    }
                    face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal);
                    if (face.Glyph.Metrics.Width == 0 || face.Glyph.Metrics.Height == 0)
                    {
                        if (face.Glyph.Metrics.HorizontalAdvance > 0)
                        {
                            //glyph is empty, but char still applies advance
                            GlyphData blankData = new GlyphData();
                            blankData.advance  = (float)face.Glyph.Metrics.HorizontalAdvance;
                            blankData.texIndex = -1; //indicates no texture because the glyph is empty
                            texCoords.Add(j, blankData);
                        }
                        continue;
                    }
                    //stacktrace doesn't really work that well when RenderGlyph throws an exception
                    face.Glyph.RenderGlyph(RenderMode.Normal);
                    byte[] bitmap      = face.Glyph.Bitmap.BufferData;
                    int    glyphWidth  = face.Glyph.Bitmap.Width;
                    int    glyphHeight = bitmap.Length / glyphWidth;

                    //if (glyphHeight>lineHeight) lineHeight=glyphHeight;

                    if (glyphWidth > texDims - 1 || glyphHeight > texDims - 1)
                    {
                        throw new Exception(filename + ", " + size.ToString() + ", " + (char)j + "; Glyph dimensions exceed texture atlas dimensions");
                    }

                    nextY = Math.Max(nextY, glyphHeight + 2);

                    if (currentCoords.X + glyphWidth + 2 > texDims - 1)
                    {
                        currentCoords.X  = 0;
                        currentCoords.Y += nextY;
                        nextY            = 0;
                    }
                    if (currentCoords.Y + glyphHeight + 2 > texDims - 1)
                    {
                        currentCoords.X = 0;
                        currentCoords.Y = 0;
                        textures[texIndex].SetData <uint>(pixelBuffer);
                        textures.Add(new Texture2D(gd, texDims, texDims, false, SurfaceFormat.Color));
                        texIndex++;
                        for (int k = 0; k < texDims * texDims; k++)
                        {
                            pixelBuffer[k] = 0;
                        }
                    }

                    GlyphData newData = new GlyphData();
                    newData.advance    = (float)face.Glyph.Metrics.HorizontalAdvance;
                    newData.texIndex   = texIndex;
                    newData.texCoords  = new Rectangle((int)currentCoords.X, (int)currentCoords.Y, glyphWidth, glyphHeight);
                    newData.drawOffset = new Vector2(face.Glyph.BitmapLeft, baseHeight * 14 / 10 - face.Glyph.BitmapTop);
                    texCoords.Add(j, newData);

                    for (int y = 0; y < glyphHeight; y++)
                    {
                        for (int x = 0; x < glyphWidth; x++)
                        {
                            byte byteColor = bitmap[x + y * glyphWidth];
                            pixelBuffer[((int)currentCoords.X + x) + ((int)currentCoords.Y + y) * texDims] = (uint)(byteColor << 24 | byteColor << 16 | byteColor << 8 | byteColor);
                        }
                    }

                    currentCoords.X += glyphWidth + 2;
                }
                textures[texIndex].SetData <uint>(pixelBuffer);
            }

            graphicsDevice = gd;
        }
Пример #42
0
 /// <summary>
 /// Executes the glyph shader
 /// </summary>
 /// <param name="context">The current glyph shader context.</param>
 /// <param name="data">The data for the glyph being drawn.</param>
 /// <param name="index">The index of the glyph within its source string.</param>
 public abstract void Execute(ref GlyphShaderContext context, ref GlyphData data, Int32 index);
 public override void Execute(ref GlyphShaderContext context, ref GlyphData data, Int32 index)
 {
     data.Color = Colors[index % Colors.Length];
 }
Пример #44
0
		/// <summary>
		/// Applies a new set of rendered glyphs to the <see cref="Font"/>, adjusts its typeface metadata and clears out the <see cref="GlyphsDirty"/> flag.
		/// This method is used by the editor to update a Font after adjusting its properties.
		/// </summary>
		/// <param name="bitmap"></param>
		/// <param name="atlas"></param>
		/// <param name="glyphs"></param>
		/// <param name="height"></param>
		/// <param name="ascent"></param>
		/// <param name="bodyAscent"></param>
		/// <param name="descent"></param>
		/// <param name="baseLine"></param>
		public void SetGlyphData(PixelData bitmap, Rect[] atlas, GlyphData[] glyphs, int height, int ascent, int bodyAscent, int descent, int baseLine)
		{
			this.ReleaseResources();

			this.glyphs = glyphs;
			this.GenerateCharLookup();

			this.pixelData = new Pixmap(bitmap);
			this.pixelData.Atlas = atlas.ToList();
			this.height = height;
			this.ascent = ascent;
			this.bodyAscent = bodyAscent;
			this.descent = descent;
			this.baseLine = baseLine;
			for (int i = 0; i < this.glyphs.Length; i++)
			{
				this.maxGlyphWidth = Math.Max(this.maxGlyphWidth, this.glyphs[i].Width);
			}

			this.UpdateKerningData();
			this.GenerateTexMat();

			this.glyphsDirty = false;
		}