private void Load( ) { Metrics = new FontMetrics(); LoadFontHeader(); LoadCharMetrics(); LoadKerningData(); }
protected internal override PdfDictionary GetFontDescriptor(String fontName) { if (fontName != null && fontName.Length > 0) { PdfDictionary fontDescriptor = new PdfDictionary(); MakeObjectIndirect(fontDescriptor); fontDescriptor.Put(PdfName.Type, PdfName.FontDescriptor); FontMetrics fontMetrics = fontProgram.GetFontMetrics(); fontDescriptor.Put(PdfName.CapHeight, new PdfNumber(fontMetrics.GetCapHeight())); fontDescriptor.Put(PdfName.ItalicAngle, new PdfNumber(fontMetrics.GetItalicAngle())); FontNames fontNames = fontProgram.GetFontNames(); fontDescriptor.Put(PdfName.FontWeight, new PdfNumber(fontNames.GetFontWeight())); fontDescriptor.Put(PdfName.FontName, new PdfName(fontName)); if (fontNames.GetFamilyName() != null && fontNames.GetFamilyName().Length > 0 && fontNames.GetFamilyName() [0].Length >= 4) { fontDescriptor.Put(PdfName.FontFamily, new PdfString(fontNames.GetFamilyName()[0][3])); } int flags = fontProgram.GetPdfFontFlags(); flags &= ~(FontDescriptorFlags.Symbolic | FontDescriptorFlags.Nonsymbolic); // reset both flags flags |= fontEncoding.IsFontSpecific() ? FontDescriptorFlags.Symbolic : FontDescriptorFlags.Nonsymbolic; // set based on font encoding fontDescriptor.Put(PdfName.Flags, new PdfNumber(flags)); return(fontDescriptor); } else { if (GetPdfObject().GetIndirectReference() != null && GetPdfObject().GetIndirectReference().GetDocument().IsTagged ()) { ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Font.PdfType3Font)); logger.Warn(iText.IO.LogMessageConstant.TYPE3_FONT_ISSUE_TAGGED_PDF); } } return(null); }
public override FontMetrics GetFontMetrics(Font font) { CTFont sysFont = font.RendererData as CTFont; if (sysFont == null || Math.Abs(font.RealSize - font.Size * Scale) > 2) { FreeFont(font); LoadFont(font); sysFont = font.RendererData as CTFont; } FontMetrics fm = new FontMetrics ( (float)(sysFont.AscentMetric + sysFont.DescentMetric - sysFont.LeadingMetric), (float)(sysFont.AscentMetric), (float)(sysFont.DescentMetric), (float)(sysFont.AscentMetric + sysFont.DescentMetric), (float)(sysFont.LeadingMetric), (float)(sysFont.AscentMetric + sysFont.DescentMetric), 0 ); return(fm); }
public override void LoadSurfaces() { var fontSurface = content.Load <Texture2D>("Images/font"); FontMetrics fontMetrics = BuildFontMetrics(); var bitmapFont = new BitmapFontTexture(fontSurface, fontMetrics, "LotaFont"); Font = new FontBuilder("LotaFont") .AddFontTexture(new FontSettings(16, FontStyles.None), bitmapFont) .Build(); Font.Size = 16; Character = content.Load <Texture2D>("Images/character"); Monsters = content.Load <Texture2D>("Images/OverworldMonsters"); Lota3DSurfaces.LoadSurfaces(content); foreach (var exinfo in data.ExhibitInfo.Values) { exinfo.LoadImage(content); } }
public override FontMetrics GetFontMetrics(Font font) { System.Drawing.Font sysFont = font.RendererData as System.Drawing.Font; if (sysFont == null || Math.Abs(font.RealSize - font.Size * Scale) > 2) { FreeFont(font); LoadFont(font); sysFont = font.RendererData as System.Drawing.Font; } // from: http://csharphelper.com/blog/2014/08/get-font-metrics-in-c float emHeight = sysFont.FontFamily.GetEmHeight(sysFont.Style); float emHeightPixels = ConvertToPixels(sysFont.Size, sysFont.Unit); float designToPixels = emHeightPixels / emHeight; float ascentPixels = designToPixels * sysFont.FontFamily.GetCellAscent(sysFont.Style); float descentPixels = designToPixels * sysFont.FontFamily.GetCellDescent(sysFont.Style); float cellHeightPixels = ascentPixels + descentPixels; float internalLeadingPixels = cellHeightPixels - emHeightPixels; float lineSpacingPixels = designToPixels * sysFont.FontFamily.GetLineSpacing(sysFont.Style); float externalLeadingPixels = lineSpacingPixels - cellHeightPixels; FontMetrics fm = new FontMetrics ( emHeightPixels, ascentPixels, descentPixels, cellHeightPixels, internalLeadingPixels, lineSpacingPixels, externalLeadingPixels ); return(fm); }
public static bool CheckAllCoverages( FontMetrics fontMetrics, LookupFlags lookupFlags, IGlyphShapingCollection collection, ushort index, int count, CoverageTable[] input, CoverageTable[] backtrack, CoverageTable[] lookahead) { // Check that there are enough context glyphs. if (index - backtrack.Length < 0 || input.Length + lookahead.Length > count) { return(false); } // Check all coverages: if any of them does not match, abort update. SkippingGlyphIterator iterator = new(fontMetrics, collection, index, lookupFlags); if (!MatchCoverageSequence(iterator, backtrack, -backtrack.Length)) { return(false); } if (!MatchCoverageSequence(iterator, input, 0)) { return(false); } if (!MatchCoverageSequence(iterator, lookahead, input.Length)) { return(false); } return(true); }
protected internal virtual void paintText(Graphics paramGraphics, int paramInt1, int paramInt2, int paramInt3, int paramInt4) { FontMetrics fontMetrics = paramGraphics.FontMetrics; string str = applicationButtonText; sbyte b1 = 40; sbyte b2 = 30; int i = paramInt1 + paramInt3 / 2 - fontMetrics.stringWidth(str) / 2; int j = paramInt2 + paramInt4 / 2 - fontMetrics.Height / 2; j += 2; Rectangle rectangle = new Rectangle(i, j, fontMetrics.stringWidth(str), fontMetrics.Height); while (str.Length != 0) { int k = fontMetrics.stringWidth(str); if (k <= rectangle.width) { break; } str = str.Substring(0, str.Length - 1); } paramGraphics.Color = Color.white; BasicGraphicsUtils.drawString(paramGraphics, str, -1, rectangle.x, rectangle.y + fontMetrics.Ascent); }
protected internal static double Width(Tree tree, FontMetrics fM) { return(WidthResult(tree, fM).width); }
public virtual Dimension GetTreeDimension(Tree tree, Font font) { FontMetrics fM = GetFontMetrics(font); return(new Dimension((int)Width(tree, fM), (int)Height(tree, fM))); }
private static void MakeBitmap(BitmapFontOptions options, ICharacterRenderer rend, out Drawing.Bitmap bmp, out FontMetrics glyphs) { Size bitmapSize = new Size(256, 64); bmp = new System.Drawing.Bitmap(bitmapSize.Width, bitmapSize.Height); Drawing.Graphics g = Drawing.Graphics.FromImage(bmp); Drawing.Font font = rend.Font; g.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit; glyphs = new FontMetrics(); const int bitmapPadding = 2; int x = rend.Padding, y = 2; int height = 0; char lastChar = ' '; // first measure the required height of the image. foreach (BitmapFontOptions.CharacterRange range in options.CharacterRanges) { for (char i = range.StartChar; i <= range.EndChar; i++) { Size sourceSize = rend.MeasureText(g, i.ToString()); if (options.CreateBorder) { sourceSize.Width += 2; sourceSize.Height += 2; } int thisWidth = sourceSize.Width + bitmapPadding; x += thisWidth; if (height < sourceSize.Height) { height = sourceSize.Height; } if (x > bitmapSize.Width) { x = 1 + thisWidth; y += height + bitmapPadding + 1; height = 0; } glyphs[i] = new GlyphMetrics(new Rectangle(0, 0, sourceSize.Width, sourceSize.Height)); lastChar = i; } } y += glyphs[lastChar].Height; if (y > bitmapSize.Height) { while (y > bitmapSize.Height) { bitmapSize.Height *= 2; } g.Dispose(); bmp.Dispose(); bmp = new System.Drawing.Bitmap(bitmapSize.Width, bitmapSize.Height); g = Drawing.Graphics.FromImage(bmp); } Drawing.Bitmap borderBmp = new System.Drawing.Bitmap(bmp.Width, bmp.Height); Drawing.Graphics borderG = Drawing.Graphics.FromImage(borderBmp); x = rend.Padding; y = 2; height = 0; Drawing.Color borderColor = System.Drawing.Color.FromArgb( options.BorderColor.A, options.BorderColor.R, options.BorderColor.G, options.BorderColor.B); foreach (BitmapFontOptions.CharacterRange range in options.CharacterRanges) { for (char i = range.StartChar; i <= range.EndChar; i++) { if (x + glyphs[i].Width > bitmapSize.Width) { x = rend.Padding; y += height + bitmapPadding + 1; height = 0; } if (options.CreateBorder) { rend.DrawText(borderG, i.ToString(), new Point(x, y + 1), borderColor); rend.DrawText(borderG, i.ToString(), new Point(x + 2, y + 1), borderColor); rend.DrawText(borderG, i.ToString(), new Point(x + 1, y), borderColor); rend.DrawText(borderG, i.ToString(), new Point(x + 1, y + 2), borderColor); rend.DrawText(g, i.ToString(), new Point(x + 1, y + 1), System.Drawing.Color.White); if (font.SizeInPoints >= 14.0) { glyphs[i].LeftOverhang = 1; } glyphs[i].RightOverhang = 1; } else { rend.DrawText(g, i.ToString(), new Point(x, y), System.Drawing.Color.White); } glyphs[i].SourceRect = new Rectangle( new Point(x, y), glyphs[i].Size); x += glyphs[i].Width + bitmapPadding; if (height < glyphs[i].Height) { height = glyphs[i].Height; } } } g.Dispose(); // do post processing of chars. PostProcessFont(options, bmp); // place the chars on the border image borderG.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height)); bmp.Dispose(); borderG.Dispose(); bmp = borderBmp; }
private Glyph ImportGlyph(Factory factory, FontFace fontFace, char character, FontMetrics fontMetrics, float fontSize, FontAntiAliasMode antiAliasMode) { var indices = fontFace.GetGlyphIndices(new int[] { character }); var metrics = fontFace.GetDesignGlyphMetrics(indices, false); var metric = metrics[0]; var width = (float)(metric.AdvanceWidth - metric.LeftSideBearing - metric.RightSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize; var height = (float)(metric.AdvanceHeight - metric.TopSideBearing - metric.BottomSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize; var xOffset = (float)metric.LeftSideBearing / fontMetrics.DesignUnitsPerEm * fontSize; var yOffset = (float)(metric.TopSideBearing - metric.VerticalOriginY) / fontMetrics.DesignUnitsPerEm * fontSize; var advanceWidth = (float)metric.AdvanceWidth / fontMetrics.DesignUnitsPerEm * fontSize; //var advanceHeight = (float)metric.AdvanceHeight / fontMetrics.DesignUnitsPerEm * fontSize; var pixelWidth = (int)Math.Ceiling(width + 4); var pixelHeight = (int)Math.Ceiling(height + 4); var matrix = new RawMatrix3x2 { M11 = 1, M22 = 1, M31 = -(float)Math.Floor(xOffset) + 1, M32 = -(float)Math.Floor(yOffset) + 1 }; Bitmap bitmap; if (char.IsWhiteSpace(character)) { bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb); } else { var glyphRun = new GlyphRun { FontFace = fontFace, Advances = new[] { (float)Math.Ceiling(advanceWidth) }, FontSize = fontSize, BidiLevel = 0, Indices = indices, IsSideways = false, Offsets = new[] { new GlyphOffset() } }; RenderingMode renderingMode; if (antiAliasMode != FontAntiAliasMode.Aliased) { var rtParams = new RenderingParams(factory); renderingMode = fontFace.GetRecommendedRenderingMode(fontSize, 1.0f, MeasuringMode.Natural, rtParams); rtParams.Dispose(); } else { renderingMode = RenderingMode.Aliased; } using (var runAnalysis = new GlyphRunAnalysis(factory, glyphRun, 1.0f, matrix, renderingMode, MeasuringMode.Natural, 0.0f, 0.0f)) { var bounds = new RawRectangle(0, 0, pixelWidth, pixelHeight); bitmap = new Bitmap(pixelWidth, pixelHeight, PixelFormat.Format32bppArgb); if (renderingMode == RenderingMode.Aliased) { var texture = new byte[pixelWidth * pixelHeight]; runAnalysis.CreateAlphaTexture(TextureType.Aliased1x1, bounds, texture, texture.Length); for (int y = 0; y < pixelHeight; y++) { for (int x = 0; x < pixelWidth; x++) { int pixelX = y * pixelWidth + x; var grey = texture[pixelX]; var color = Color.FromArgb(grey, grey, grey); bitmap.SetPixel(x, y, color); } } } else { var texture = new byte[pixelWidth * pixelHeight * 3]; runAnalysis.CreateAlphaTexture(TextureType.Cleartype3x1, bounds, texture, texture.Length); for (int y = 0; y < pixelHeight; y++) { for (int x = 0; x < pixelWidth; x++) { int pixelX = (y * pixelWidth + x) * 3; var red = LinearToGamma(texture[pixelX]); var green = LinearToGamma(texture[pixelX + 1]); var blue = LinearToGamma(texture[pixelX + 2]); var color = Color.FromArgb(red, green, blue); bitmap.SetPixel(x, y, color); } } } } } var glyph = new Glyph(character, bitmap) { XOffset = -matrix.M31, XAdvance = advanceWidth, YOffset = -matrix.M32, }; return(glyph); }
internal static double FontSizeFromLinesInHeight(this FontMetrics metric, int lines, double height) => height * metric.DesignUnitsPerEm / DesignUnitsHeightForLines(metric, lines);
internal static double HeightForLinesAtFontSize(this FontMetrics metric, int lines, double fontSize) => fontSize *DesignUnitsHeightForLines(metric, lines) / metric.DesignUnitsPerEm;
private Glyph ImportGlyph(Factory factory, FontFace fontFace, char character, FontMetrics fontMetrics, float fontSize, bool activateAntiAliasDetection) { var indices = fontFace.GetGlyphIndices(new int[] {character}); var metrics = fontFace.GetDesignGlyphMetrics(indices, false); var metric = metrics[0]; var width = (float)(metric.AdvanceWidth - metric.LeftSideBearing - metric.RightSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize; var height = (float)(metric.AdvanceHeight - metric.TopSideBearing - metric.BottomSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize; var xOffset = (float)metric.LeftSideBearing / fontMetrics.DesignUnitsPerEm * fontSize; var yOffset = (float)(metric.TopSideBearing - metric.VerticalOriginY) / fontMetrics.DesignUnitsPerEm * fontSize; var advanceWidth = (float)(metric.AdvanceWidth) / fontMetrics.DesignUnitsPerEm * fontSize; var advanceHeight = (float)(metric.AdvanceHeight) / fontMetrics.DesignUnitsPerEm * fontSize; var pixelWidth = (int)Math.Ceiling(width + 2); var pixelHeight = (int)Math.Ceiling(height + 2); Bitmap bitmap; if(char.IsWhiteSpace(character)) { bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb); } else { var glyphRun = new GlyphRun() { FontFace = fontFace, Advances = new[] { (float)Math.Round(advanceWidth) }, FontSize = fontSize, BidiLevel = 0, Indices = indices, IsSideways = false, Offsets = new[] {new GlyphOffset()} }; var matrix = SharpDX.Matrix.Identity; matrix.M41 = -(float)Math.Floor(xOffset - 1); matrix.M42 = -(float)Math.Floor(yOffset - 1); RenderingMode renderingMode; if (activateAntiAliasDetection) { var rtParams = new RenderingParams(factory); renderingMode = fontFace.GetRecommendedRenderingMode(fontSize, 1.0f, MeasuringMode.Natural, rtParams); rtParams.Dispose(); } else { renderingMode = RenderingMode.Aliased; } using(var runAnalysis = new GlyphRunAnalysis(factory, glyphRun, 1.0f, matrix, renderingMode, MeasuringMode.Natural, 0.0f, 0.0f)) { var bounds = new SharpDX.Rectangle(0, 0, pixelWidth, pixelHeight); bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb); if(renderingMode == RenderingMode.Aliased) { var texture = new byte[bounds.Width * bounds.Height]; runAnalysis.CreateAlphaTexture(TextureType.Aliased1x1, bounds, texture, texture.Length); bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb); for (int y = 0; y < bounds.Height; y++) { for (int x = 0; x < bounds.Width; x++) { int pixelX = y * bounds.Width + x; var grey = texture[pixelX]; var color = Color.FromArgb(grey, grey, grey); bitmap.SetPixel(x, y, color); } } } else { var texture = new byte[bounds.Width * bounds.Height * 3]; runAnalysis.CreateAlphaTexture(TextureType.Cleartype3x1, bounds, texture, texture.Length); for (int y = 0; y < bounds.Height; y++) { for (int x = 0; x < bounds.Width; x++) { int pixelX = (y * bounds.Width + x) * 3; var red = texture[pixelX]; var green = texture[pixelX + 1]; var blue = texture[pixelX + 2]; var color = Color.FromArgb(red, green, blue); bitmap.SetPixel(x, y, color); } } } //var positionUnderline = (float)fontMetrics.UnderlinePosition / fontMetrics.DesignUnitsPerEm * fontSize; //var positionUnderlineSize = (float)fontMetrics.UnderlineThickness / fontMetrics.DesignUnitsPerEm * fontSize; } } var glyph = new Glyph(character, bitmap) { XOffset = (float)Math.Floor(xOffset-1), XAdvance = (float)Math.Round(advanceWidth), YOffset = (float)Math.Floor(yOffset-1), }; return glyph; }
protected bool ProduceGlyphRuns(FlowLayoutSink flowSink, ref RectangleF rect, ref ClusterPosition clusterStart, ref ClusterPosition clusterEnd) { // Produce a series of glyph runs from the given range // and send them to the sink. If the entire text fit // into the rect, then we'll only pass on a single glyph // run. //////////////////////////////////////// // Figure out how many runs we cross, because this is the number // of distinct glyph runs we'll need to reorder visually. int runIndexEnd = clusterEnd.runIndex; if (clusterEnd.textPosition > runs_[runIndexEnd].textStart) { ++runIndexEnd; // Only partially cover the run, so round up. } int[] bidiOrdering = new int[100]; int totalRuns = Math.Min(bidiOrdering.Length, runIndexEnd - clusterStart.runIndex); ProduceBidiOrdering(clusterStart.runIndex, totalRuns, bidiOrdering); //////////////////////////////////////// // Ignore any trailing whitespace // Look backward from end until we find non-space. int trailingWsPosition; for (trailingWsPosition = clusterEnd.textPosition; trailingWsPosition > clusterStart.textPosition; --trailingWsPosition) { if (!breakpoints_[trailingWsPosition - 1].IsWhitespace) { break; // Encountered last significant character. } } // Set the glyph run's ending cluster to the last whitespace. ClusterPosition clusterWsEnd = clusterStart; SetClusterPosition(ref clusterWsEnd, trailingWsPosition); //////////////////////////////////////// // Produce justified advances to reduce the jagged edge. List <float> justifiedAdvances; ProduceJustifiedAdvances(ref rect, ref clusterStart, ref clusterWsEnd, out justifiedAdvances); int justificationGlyphStart = GetClusterGlyphStart(ref clusterStart); //////////////////////////////////////// // Determine starting point for alignment. float x = rect.Left; float y = rect.Bottom; FontMetrics fontMetrics = fontFace_.Metrics; float descent = (fontMetrics.Descent * fontEmSize_ / fontMetrics.DesignUnitsPerEm); y -= descent; if (readingDirection_ == ReadingDirection.RightToLeft) { // For RTL, we neeed the run width to adjust the origin // so it starts on the right side. int glyphStart = GetClusterGlyphStart(ref clusterStart); int glyphEnd = GetClusterGlyphStart(ref clusterWsEnd); if (glyphStart < glyphEnd) { float lineWidth = GetClusterRangeWidth( glyphStart - justificationGlyphStart, glyphEnd - justificationGlyphStart, justifiedAdvances.ToArray() ); x = rect.Right - lineWidth; } } //////////////////////////////////////// // Send each glyph run to the sink. for (int i = 0; i < totalRuns; ++i) { Run run = runs_[bidiOrdering[i]]; int glyphStart = run.glyphStart; int glyphEnd = glyphStart + run.glyphCount; // If the run is only partially covered, we'll need to find // the subsection of glyphs that were fit. if (clusterStart.textPosition > run.textStart) { glyphStart = GetClusterGlyphStart(ref clusterStart); } if (clusterWsEnd.textPosition < run.textStart + run.textLength) { glyphEnd = GetClusterGlyphStart(ref clusterWsEnd); } if ((glyphStart >= glyphEnd) || (run.script.Shapes == ScriptShapes.NoVisual)) { // The itemizer told us not to draw this character, // either because it was a formatting, control, or other hidden character. continue; } // The run width is needed to know how far to move forward, // and to flip the origin for right-to-left text. float runWidth = GetClusterRangeWidth( glyphStart - justificationGlyphStart, glyphEnd - justificationGlyphStart, justifiedAdvances.ToArray() ); // Flush this glyph run. //int glyphCount = glyphEnd - glyphStart; int glyphCount = justifiedAdvances.Count; short[] call_glyphIndices_ = new short[glyphCount]; Array.Copy(glyphIndices_, glyphStart, call_glyphIndices_, 0, call_glyphIndices_.Length); float[] call_justifiedAdvances = new float[justifiedAdvances.Count - (glyphStart - justificationGlyphStart)]; justifiedAdvances.CopyTo(glyphStart - justificationGlyphStart, call_justifiedAdvances, 0, call_justifiedAdvances.Length); GlyphOffset[] call_glyphOffsets_ = new GlyphOffset[glyphCount]; Array.Copy(glyphOffsets_, glyphStart, call_glyphOffsets_, 0, call_glyphOffsets_.Length); flowSink.SetGlyphRun( (run.bidiLevel % 2 != 0) ? (x + runWidth) : (x), // origin starts from right if RTL y, glyphCount, call_glyphIndices_, call_justifiedAdvances, call_glyphOffsets_, fontFace_, fontEmSize_, run.bidiLevel, run.isSideways ); x += runWidth; } return(true); }
private Glyph ImportGlyph(Factory factory, FontFace fontFace, char character, FontMetrics fontMetrics, float fontSize, FontAntiAliasMode antiAliasMode) { var indices = fontFace.GetGlyphIndices(new int[] { character }); var metrics = fontFace.GetDesignGlyphMetrics(indices, false); var metric = metrics[0]; var width = (float)(metric.AdvanceWidth - metric.LeftSideBearing - metric.RightSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize; var height = (float)(metric.AdvanceHeight - metric.TopSideBearing - metric.BottomSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize; var xOffset = (float)metric.LeftSideBearing / fontMetrics.DesignUnitsPerEm * fontSize; var yOffset = (float)(metric.TopSideBearing - metric.VerticalOriginY) / fontMetrics.DesignUnitsPerEm * fontSize; var advanceWidth = (float)metric.AdvanceWidth / fontMetrics.DesignUnitsPerEm * fontSize; //var advanceHeight = (float)metric.AdvanceHeight / fontMetrics.DesignUnitsPerEm * fontSize; var pixelWidth = (int)Math.Ceiling(width + 4); var pixelHeight = (int)Math.Ceiling(height + 4); var matrix = new RawMatrix3x2 { M11 = 1, M22 = 1, M31 = -(float)Math.Floor(xOffset) + 1, M32 = -(float)Math.Floor(yOffset) + 1 }; Bitmap bitmap; if (char.IsWhiteSpace(character)) { bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb); } else { var glyphRun = new GlyphRun { FontFace = fontFace, Advances = new[] { (float)Math.Ceiling(advanceWidth) }, FontSize = fontSize, BidiLevel = 0, Indices = indices, IsSideways = false, Offsets = new[] { new GlyphOffset() } }; RenderingMode renderingMode; if (antiAliasMode != FontAntiAliasMode.Aliased) { var rtParams = new RenderingParams(factory); renderingMode = fontFace.GetRecommendedRenderingMode(fontSize, 1.0f, MeasuringMode.Natural, rtParams); rtParams.Dispose(); } else { renderingMode = RenderingMode.Aliased; } using (var runAnalysis = new GlyphRunAnalysis(factory, glyphRun, 1.0f, matrix, renderingMode, MeasuringMode.Natural, 0.0f, 0.0f)) { var bounds = new RawRectangle(0, 0, pixelWidth, pixelHeight); bitmap = new Bitmap(pixelWidth, pixelHeight, PixelFormat.Format32bppArgb); if (renderingMode == RenderingMode.Aliased) { var texture = new byte[pixelWidth * pixelHeight]; runAnalysis.CreateAlphaTexture(TextureType.Aliased1x1, bounds, texture, texture.Length); for (int y = 0; y < pixelHeight; y++) { for (int x = 0; x < pixelWidth; x++) { int pixelX = y * pixelWidth + x; var grey = texture[pixelX]; var color = Color.FromArgb(grey, grey, grey); bitmap.SetPixel(x, y, color); } } } else { var texture = new byte[pixelWidth * pixelHeight * 3]; runAnalysis.CreateAlphaTexture(TextureType.Cleartype3x1, bounds, texture, texture.Length); for (int y = 0; y < pixelHeight; y++) { for (int x = 0; x < pixelWidth; x++) { int pixelX = (y * pixelWidth + x) * 3; var red = LinearToGamma(texture[pixelX]); var green = LinearToGamma(texture[pixelX + 1]); var blue = LinearToGamma(texture[pixelX + 2]); var color = Color.FromArgb(red, green, blue); bitmap.SetPixel(x, y, color); } } } } } var glyph = new Glyph(character, bitmap) { XOffset = -matrix.M31, XAdvance = advanceWidth, YOffset = -matrix.M32, }; return glyph; }
public override bool TryUpdatePosition( FontMetrics fontMetrics, GPosTable table, GlyphPositioningCollection collection, Tag feature, ushort index, int count) { // Implements Chained Contexts Substitution, Format 1: // https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#61-chained-contexts-substitution-format-1-simple-glyph-contexts ushort glyphId = collection[index][0]; if (glyphId == 0) { return(false); } // Search for the current glyph in the Coverage table. int offset = this.coverageTable.CoverageIndexOf(glyphId); if (offset <= -1) { return(false); } if (this.seqRuleSetTables is null || this.seqRuleSetTables.Length is 0) { return(false); } ChainedSequenceRuleSetTable seqRuleSet = this.seqRuleSetTables[offset]; if (seqRuleSet is null) { return(false); } // Apply ruleset for the given glyph id. ChainedSequenceRuleTable[] rules = seqRuleSet.SequenceRuleTables; SkippingGlyphIterator iterator = new(fontMetrics, collection, index, this.LookupFlags); for (int lookupIndex = 0; lookupIndex < rules.Length; lookupIndex++) { ChainedSequenceRuleTable rule = rules[lookupIndex]; if (!AdvancedTypographicUtils.ApplyChainedSequenceRule(iterator, rule)) { continue; } bool hasChanged = false; for (int j = 0; j < rule.SequenceLookupRecords.Length; j++) { SequenceLookupRecord sequenceLookupRecord = rule.SequenceLookupRecords[j]; LookupTable lookup = table.LookupList.LookupTables[sequenceLookupRecord.LookupListIndex]; ushort sequenceIndex = sequenceLookupRecord.SequenceIndex; if (lookup.TryUpdatePosition(fontMetrics, table, collection, feature, (ushort)(index + sequenceIndex), 1)) { hasChanged = true; } } return(hasChanged); } return(false); }
public override bool TryUpdatePosition( FontMetrics fontMetrics, GPosTable table, GlyphPositioningCollection collection, Tag feature, ushort index, int count) { // Implements Chained Contexts Substitution for Format 2: // https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#62-chained-contexts-substitution-format-2-class-based-glyph-contexts ushort glyphId = collection[index][0]; if (glyphId == 0) { return(false); } // Search for the current glyph in the Coverage table. int offset = this.coverageTable.CoverageIndexOf(glyphId); if (offset <= -1) { return(false); } // Search in the class definition table to find the class value assigned to the currently glyph. int classId = this.inputClassDefinitionTable.ClassIndexOf(glyphId); ChainedClassSequenceRuleTable[]? rules = classId >= 0 && classId < this.sequenceRuleSetTables.Length ? this.sequenceRuleSetTables[classId].SubRules : null; if (rules is null) { return(false); } // Apply ruleset for the given glyph class id. SkippingGlyphIterator iterator = new(fontMetrics, collection, index, this.LookupFlags); for (int lookupIndex = 0; lookupIndex < rules.Length; lookupIndex++) { ChainedClassSequenceRuleTable rule = rules[lookupIndex]; if (!AdvancedTypographicUtils.ApplyChainedClassSequenceRule(iterator, rule, this.inputClassDefinitionTable, this.backtrackClassDefinitionTable, this.lookaheadClassDefinitionTable)) { continue; } // It's a match. Perform position update and return true if anything changed. bool hasChanged = false; for (int j = 0; j < rule.SequenceLookupRecords.Length; j++) { SequenceLookupRecord sequenceLookupRecord = rule.SequenceLookupRecords[j]; LookupTable lookup = table.LookupList.LookupTables[sequenceLookupRecord.LookupListIndex]; ushort sequenceIndex = sequenceLookupRecord.SequenceIndex; if (lookup.TryUpdatePosition(fontMetrics, table, collection, feature, (ushort)(index + sequenceIndex), 1)) { hasChanged = true; } } return(hasChanged); } return(false); }
public static string[] WrapWords(string source, int lineWidth, FontMetrics metrics) { int pos = 0; int lastWrap = 0; int lastPossibleWrap = 0; int curWidth = 0; List <string> lines = new List <string>(); while (pos < source.Length) { char ch = source[pos]; int charWidth = metrics.GetCharacterWidth(ch); if (ch == '\n') { // wrap here string line = source.Substring(lastWrap, pos - lastWrap); lastWrap = lastPossibleWrap = pos; curWidth = 0; lines.Add(line.PadRight(line.Length + (lineWidth - StringWidth(line, metrics)) / metrics.HalfWidthHorizontalSpacing)); } else if (curWidth + charWidth > lineWidth) { if (lastPossibleWrap > lastWrap) { // check length of current word int end = pos; while (end < source.Length && !char.IsWhiteSpace(source[end]) && !IsFullWidthCharacter(source[end])) { end++; } string curWord = source.Substring(lastPossibleWrap, end - lastPossibleWrap).Trim(); if (StringWidth(curWord, metrics) > lineWidth) { // word wouldn't fit in its own line, so we keep its start on the current one and force a hard wrap (no padding) lines.Add(source.Substring(lastWrap, pos - lastWrap)); lastWrap = lastPossibleWrap = pos; curWidth = 0; } else { // push the current word to the next line string line = source.Substring(lastWrap, lastPossibleWrap - lastWrap); int curLineWidth = StringWidth(line, metrics); lastWrap = lastPossibleWrap; curWidth -= curLineWidth; // pad and add line lines.Add(line.PadRight(line.Length + (lineWidth - curLineWidth) / metrics.HalfWidthHorizontalSpacing)); } } else { // force a hard wrap here (no padding) lines.Add(source.Substring(lastWrap, pos - lastWrap)); lastWrap = lastPossibleWrap = pos; curWidth = 0; } } curWidth += charWidth; pos++; // allow soft wraps after each full-width character if (char.IsWhiteSpace(ch) || IsFullWidthCharacter(ch)) { lastPossibleWrap = pos; } } // add the last line if (pos > lastWrap) { string line = source.Substring(lastWrap, pos - lastWrap); if (line.Trim().Length > 0) { lines.Add(line.PadRight(line.Length + (lineWidth - StringWidth(line, metrics)) / metrics.HalfWidthHorizontalSpacing)); } } return(lines.ToArray()); }
public static int StringWidth(string str, FontMetrics metrics) { return(str.Aggregate(0, (int l, char ch) => l + metrics.GetCharacterWidth(ch))); }
/// <summary> /// Imports a single glyph as a bitmap using the msdfgen to convert it to a signed distance field image /// </summary> /// <param name="fontFace">FontFace, use to obtain the metrics for the glyph</param> /// <param name="character">The glyph's character code</param> /// <param name="fontMetrics">Font metrics, used to obtain design units scale</param> /// <param name="fontSize">Requested font size. The bigger, the more precise the SDF image is going to be</param> /// <returns></returns> private Glyph ImportGlyph(FontFace fontFace, char character, FontMetrics fontMetrics, float fontSize) { var indices = fontFace.GetGlyphIndices(new int[] { character }); var metrics = fontFace.GetDesignGlyphMetrics(indices, false); var metric = metrics[0]; var width = (float)(metric.AdvanceWidth - metric.LeftSideBearing - metric.RightSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize; var height = (float)(metric.AdvanceHeight - metric.TopSideBearing - metric.BottomSideBearing) / fontMetrics.DesignUnitsPerEm * fontSize; var xOffset = (float)metric.LeftSideBearing / fontMetrics.DesignUnitsPerEm * fontSize; var yOffset = (float)(metric.TopSideBearing - metric.VerticalOriginY) / fontMetrics.DesignUnitsPerEm * fontSize; var advanceWidth = (float)metric.AdvanceWidth / fontMetrics.DesignUnitsPerEm * fontSize; //var advanceHeight = (float)metric.AdvanceHeight / fontMetrics.DesignUnitsPerEm * fontSize; var pixelWidth = (int)Math.Ceiling(width + 4); var pixelHeight = (int)Math.Ceiling(height + 4); var matrixM31 = -(float)Math.Floor(xOffset) + 1; var matrixM32 = -(float)Math.Floor(yOffset) + 1; Bitmap bitmap; if (char.IsWhiteSpace(character)) { bitmap = new Bitmap(1, 1, PixelFormat.Format32bppArgb); } else { bitmap = LoadSDFBitmap(character, pixelWidth, pixelHeight, 1, 1); } var glyph = new Glyph(character, bitmap) { XOffset = -matrixM31, XAdvance = advanceWidth, YOffset = -matrixM32, }; return glyph; }
internal static double XHeightForFontSize(this FontMetrics metric, double fontSize) => fontSize *Math.Abs(metric.XHeight) / metric.DesignUnitsPerEm;
/** <summary>Loads the font data.</summary> */ private void Load( ) { LoadTableInfo(); FontName = GetName(NameID_FontPostscriptName); Metrics = new FontMetrics(); LoadTables(); LoadCMap(); LoadGlyphWidths(); LoadGlyphKerning(); }
public Point SizeOfCharacter(int index) { return(FontMetrics.MeasureStringRounded(TokenText[index].ToString())); }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(FontMetrics obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }
private static FontDescriptors[] DrawFonts(Graphics g, int width, int height, Font[] fonts) { float hborder = 4.0f; float safetyMargin = 2.0f * hborder; float y = 0; float LHS = safetyMargin; float x = LHS; var descriptors = new FontDescriptors[fonts.Length]; float lastHeight = -1.0f; float nextRowHeight = -1.0f; for (int i = 0; i < fonts.Length; i++) { Font f = fonts[i]; var metrics = FontMetrics.From(g, f); descriptors[i] = new FontDescriptors(f, metrics); IEnumerable <char> glyphs; glyphs = AnsiGlyphs; if (nextRowHeight < 0) { nextRowHeight = metrics.Height; } if (lastHeight >= metrics.Height) { } else { x = LHS; if (lastHeight > 0) { y += nextRowHeight + 1; nextRowHeight = metrics.Height; } } lastHeight = metrics.Height; var sf = StringFormat.GenericTypographic; foreach (char c in glyphs) { if (!metrics.IsGlyphAvailable(c)) { continue; } string s = new string(c, 1); int A = metrics.GetA(c) - (int)hborder; int B = metrics.GetB(c) + (int)safetyMargin; int C = metrics.GetC(c) - (int)hborder; float dx = (float)(B); if (x + dx >= width) { x = LHS; y += nextRowHeight + 1; nextRowHeight = metrics.Height; } float Tx = x - (float)A; descriptors[i].Add(c, A, B, C, (int)Tx, (int)y); if (metrics.Height > 22) { g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; } else { g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit; } TextRenderer.DrawText(g, s, f, new Point((int)Tx, (int)y), Color.White, TextFormatFlags.NoPadding); // g.DrawString(s, f, Brushes.White, new PointF(Tx, y), sf); x += dx + safetyMargin; } } return(descriptors); }
public static extern void DrawTextFontGetMetrics(IntPtr font, out FontMetrics metrics);
public FontDescriptors(Font f, FontMetrics metrics) { Name = f.Name; Height = f.Height; Ascent = metrics.Ascent; }
internal static double LineGapForFontSize(this FontMetrics metric, double fontSize) => fontSize *Math.Abs(metric.LineGap) / metric.DesignUnitsPerEm;
public virtual void paintComponent(Graphics paramGraphics) { if (Frame != null) { State = Frame.ExtendedState; } JRootPane jRootPane = RootPane; Window window1 = Window; bool @bool = (window1 == null) ? jRootPane.ComponentOrientation.LeftToRight : window1.ComponentOrientation.LeftToRight; int i = Width; int j = Height; Color color = CostOSWindowsLookAndFeel.ribbonTaskTitleTextForegroundColor; if (!CostOSRibbonUI.Instance.BackstageShowing) { paramGraphics.Color = CostOSWindowsLookAndFeel.ribbonBackground; paramGraphics.fillRect(0, 0, i, j); paramGraphics.drawImage(this.ribbonArtImg, i - this.ribbonArtImg.getWidth(this), 0, this.ribbonArtImg.getWidth(this), this.ribbonArtImg.getHeight(this), this); } else { int m = CostOSRibbonApplicationMenuPopupPanel.FirstLevelMenuWidth; paramGraphics.Color = CostOSWindowsLookAndFeel.applicationBackground; paramGraphics.fillRect(0, 0, i, j); paramGraphics.Color = CostOSWindowsLookAndFeel.ribbonBackground; paramGraphics.fillRect(0, 0, m, Height); if (this.ribbonBackstageArtImg != null) { paramGraphics.drawImage(this.ribbonBackstageArtImg, i - this.ribbonBackstageArtImg.getWidth(this), 0, this.ribbonBackstageArtImg.getWidth(this), this.ribbonBackstageArtImg.getHeight(this), this); } color = CostOSWindowsLookAndFeel.ribbonCommandButtonForegroundColor; } int k = @bool ? 5 : (i - 5); if (WindowDecorationStyle == 1) { k += (@bool ? 21 : -21); } string str = Title; if (!string.ReferenceEquals(str, null)) { FontMetrics fontMetrics = SwingUtilities2.getFontMetrics(jRootPane, paramGraphics); int m = (j - fontMetrics.Height) / 2 + fontMetrics.Ascent; Rectangle rectangle = new Rectangle(0, 0, 0, 0); if (this.iconifyButton != null && this.iconifyButton.Parent != null) { rectangle = this.iconifyButton.Bounds; } if (@bool) { if (rectangle.x == 0) { rectangle.x = window1.Width - (window1.Insets).right - 2; } int i2 = rectangle.x - k - 4; str = SwingUtilities2.clipStringIfNecessary(jRootPane, fontMetrics, str, i2); } else { int i2 = k - rectangle.x - rectangle.width - 4; str = SwingUtilities2.clipStringIfNecessary(jRootPane, fontMetrics, str, i2); k -= SwingUtilities2.stringWidth(jRootPane, fontMetrics, str); } int n = SwingUtilities2.stringWidth(jRootPane, fontMetrics, str); paramGraphics.Color = color; int i1 = (int)(i / 2.0F - n / 2.0F); SwingUtilities2.drawString(jRootPane, paramGraphics, str, i1, m); k += (@bool ? (n + 5) : -5); } }
internal static double FontSizeFromLineHeight(this FontMetrics metric, double lineHeight) => FontSizeFromLinesInHeight(metric, 1, lineHeight);
public static HopeFont CreateHopeFont(Typeface typeface) { int bitmapWH = 1024; int textSize = 160; // double scale = DeviceDisplay.MainDisplayInfo.Density; Paint paint = new Paint(PaintFlags.AntiAlias | PaintFlags.Dither) { Color = Color.White, TextSize = textSize }; paint.SetTypeface(typeface); paint.SetShadowLayer(0.4f, 0f, 1f, Color.DarkGray); // First create the canvas 1024x1024 with alpha Bitmap.Config bitmapConfig = Bitmap.Config.Argb8888; Bitmap bitmap = Bitmap.CreateBitmap(bitmapWH, bitmapWH, bitmapConfig); Canvas canvas = new Canvas(bitmap); Dictionary <char, Glyph> glyphs = new Dictionary <char, Glyph>(); FontMetrics metrics = paint.GetFontMetrics(); float lineHeight = metrics.Bottom - metrics.Top; float ascent = metrics.Ascent; List <char> missingChars = new List <char>(); missingChars.AddRange(chars.ToCharArray()); int currentLineIndex = 1; while (missingChars.Count > 0) { float currentLineHeight = lineHeight * currentLineIndex; int currentCharsCount; int index = -1; string currentChars; do { index++; currentCharsCount = missingChars.Count - index; currentChars = string.Join("", missingChars.GetRange(0, currentCharsCount)); } while (paint.MeasureText(currentChars) > bitmapWH); // Now we have the index of chars to write on this line missingChars.RemoveRange(0, currentCharsCount); canvas.DrawText(currentChars, 0, currentLineHeight, paint); float lastX = 0; foreach (char c in currentChars.ToCharArray()) { float[] widths = new float[1]; paint.GetTextWidths(c.ToString(), widths); float width = widths[0]; float relativeAscent = lineHeight + ascent + 5; float uvX = lastX / bitmapWH; float uvY = (currentLineHeight + relativeAscent) / bitmapWH; float uvW = width / bitmapWH; float uvH = lineHeight / bitmapWH; Glyph glyph = new Glyph(c, uvX, 1.0f - uvY, uvW, uvH); glyphs.Add(c, glyph); lastX += width; } currentLineIndex++; } return(new HopeFont(glyphs, new Texture(bitmap), lineHeight / bitmapWH)); }
/// <summary> /// Renders the <see cref="Duality.Resources.Font"/> using the specified system font. /// This method assumes that the system font's size and style match the one specified in /// the specified Duality font. /// </summary> private RenderedFontData RenderGlyphs(SysDrawFont internalFont, FontCharSet charSet, bool antialiazing, bool monospace) { DualityFont.GlyphData[] glyphs = new DualityFont.GlyphData[charSet.Chars.Length]; for (int i = 0; i < glyphs.Length; i++) { glyphs[i].Glyph = charSet.Chars[i]; } int bodyAscent = 0; int baseLine = 0; int descent = 0; int ascent = 0; TextRenderingHint textRenderingHint; if (antialiazing) { textRenderingHint = TextRenderingHint.AntiAliasGridFit; } else { textRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; } int cols; int rows; cols = rows = (int)Math.Ceiling(Math.Sqrt(glyphs.Length)); PixelData pixelLayer = new PixelData( MathF.RoundToInt(cols * internalFont.Size * 1.2f), MathF.RoundToInt(rows * internalFont.Height * 1.2f), ColorRgba.TransparentBlack); PixelData glyphTemp; PixelData glyphTempTypo; Bitmap bm; Bitmap measureBm = new Bitmap(1, 1); Rect[] atlas = new Rect[glyphs.Length]; using (Graphics measureGraphics = Graphics.FromImage(measureBm)) { Brush fntBrush = new SolidBrush(Color.Black); StringFormat formatDef = StringFormat.GenericDefault; formatDef.LineAlignment = StringAlignment.Near; formatDef.FormatFlags = 0; StringFormat formatTypo = StringFormat.GenericTypographic; formatTypo.LineAlignment = StringAlignment.Near; int x = 1; int y = 1; for (int i = 0; i < glyphs.Length; ++i) { string str = glyphs[i].Glyph.ToString(CultureInfo.InvariantCulture); bool isSpace = str == " "; SizeF charSize = measureGraphics.MeasureString(str, internalFont, pixelLayer.Width, formatDef); // Rasterize a single glyph for rendering bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), internalFont.Height + 1); using (Graphics glyphGraphics = Graphics.FromImage(bm)) { glyphGraphics.Clear(Color.Transparent); glyphGraphics.TextRenderingHint = textRenderingHint; glyphGraphics.DrawString(str, internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatDef); } glyphTemp = new PixelData(); glyphTemp.FromBitmap(bm); // Rasterize a single glyph in typographic mode for metric analysis if (!isSpace) { Point2 glyphTempOpaqueTopLeft; Point2 glyphTempOpaqueSize; glyphTemp.GetOpaqueBoundaries(out glyphTempOpaqueTopLeft, out glyphTempOpaqueSize); glyphTemp.SubImage(glyphTempOpaqueTopLeft.X, 0, glyphTempOpaqueSize.X, glyphTemp.Height); if (charSet.CharBodyAscentRef.Contains(glyphs[i].Glyph)) { bodyAscent += glyphTempOpaqueSize.Y; } if (charSet.CharBaseLineRef.Contains(glyphs[i].Glyph)) { baseLine += glyphTempOpaqueTopLeft.Y + glyphTempOpaqueSize.Y; } if (charSet.CharDescentRef.Contains(glyphs[i].Glyph)) { descent += glyphTempOpaqueTopLeft.Y + glyphTempOpaqueSize.Y; } bm = new Bitmap((int)Math.Ceiling(Math.Max(1, charSize.Width)), internalFont.Height + 1); using (Graphics glyphGraphics = Graphics.FromImage(bm)) { glyphGraphics.Clear(Color.Transparent); glyphGraphics.TextRenderingHint = textRenderingHint; glyphGraphics.DrawString(str, internalFont, fntBrush, new RectangleF(0, 0, bm.Width, bm.Height), formatTypo); } glyphTempTypo = new PixelData(); glyphTempTypo.FromBitmap(bm); glyphTempTypo.Crop(true, false); } else { glyphTempTypo = glyphTemp; } // Update xy values if it doesn't fit anymore if (x + glyphTemp.Width + 2 > pixelLayer.Width) { x = 1; y += internalFont.Height + MathF.Clamp((int)MathF.Ceiling(internalFont.Height * 0.1875f), 3, 10); } // Memorize atlas coordinates & glyph data glyphs[i].Width = glyphTemp.Width; glyphs[i].Height = glyphTemp.Height; glyphs[i].OffsetX = glyphTemp.Width - glyphTempTypo.Width; glyphs[i].OffsetY = 0; // ttf fonts are rendered on blocks that are the whole size of the height - so no need for offset if (isSpace) { glyphs[i].Width /= 2; glyphs[i].OffsetX /= 2; } atlas[i].X = x; atlas[i].Y = y; atlas[i].W = glyphTemp.Width; atlas[i].H = (internalFont.Height + 1); // Draw it onto the font surface glyphTemp.DrawOnto(pixelLayer, BlendMode.Solid, x, y); x += glyphTemp.Width + MathF.Clamp((int)MathF.Ceiling(internalFont.Height * 0.125f), 2, 10); } } // White out texture except alpha channel. for (int i = 0; i < pixelLayer.Data.Length; i++) { pixelLayer.Data[i].R = 255; pixelLayer.Data[i].G = 255; pixelLayer.Data[i].B = 255; } // Monospace offset adjustments if (monospace) { int maxGlyphWidth = 0; for (int i = 0; i < glyphs.Length; i++) { maxGlyphWidth = Math.Max(maxGlyphWidth, glyphs[i].Width); } for (int i = 0; i < glyphs.Length; ++i) { glyphs[i].OffsetX -= (int)Math.Round((maxGlyphWidth - glyphs[i].Width) / 2.0f); } } // Determine Font properties { float lineSpacing = internalFont.FontFamily.GetLineSpacing(internalFont.Style); float emHeight = internalFont.FontFamily.GetEmHeight(internalFont.Style); float cellAscent = internalFont.FontFamily.GetCellAscent(internalFont.Style); float cellDescent = internalFont.FontFamily.GetCellDescent(internalFont.Style); ascent = (int)Math.Round(cellAscent * internalFont.Size / emHeight); bodyAscent /= charSet.CharBodyAscentRef.Length; baseLine /= charSet.CharBaseLineRef.Length; descent = (int)Math.Round(((float)descent / charSet.CharDescentRef.Length) - (float)baseLine); } // Aggregate rendered and generated data into our return value FontMetrics metrics = new FontMetrics( size: internalFont.SizeInPoints, height: (int)internalFont.Height, ascent: ascent, bodyAscent: bodyAscent, descent: descent, baseLine: baseLine, monospace: monospace); return(new RenderedFontData { Bitmap = pixelLayer, Atlas = atlas, GlyphData = glyphs, Metrics = metrics }); }
public virtual void layoutContainer(Container param1Container) { Insets insets = param1Container.Insets; int i = outerInstance.TabButtonGap; bool bool1 = outerInstance.ribbon.ComponentOrientation.LeftToRight; int j = param1Container.Width; int k = outerInstance.TaskbarHeight; int m = insets.top; bool bool2 = outerInstance.UsingTitlePane; if (!bool2) { outerInstance.taskBarPanel.removeAll(); foreach (Component component in outerInstance.ribbon.TaskbarComponents) { outerInstance.taskBarPanel.add(component); } outerInstance.taskBarPanel.setBounds(insets.left, insets.top, j - insets.left - insets.right, k); m += k; } else { outerInstance.taskBarPanel.setBounds(0, 0, 0, 0); } Font font = outerInstance.ribbon.Font; if (font == null) { font = new Font("SansSerif", 0, 12); outerInstance.ribbon.Font = font; } FontMetrics fontMetrics = outerInstance.ribbon.getFontMetrics(font); int n = fontMetrics.stringWidth(CostOSRibbonApplicationMenuButtonUI.ApplicationMenuButtonText) + 24; int i1; for (i1 = 0; i1 < outerInstance.ribbon.TaskCount; i1++) { RibbonTask ribbonTask = outerInstance.ribbon.getTask(i1); n += fontMetrics.stringWidth(ribbonTask.Title) + 32; } n += 12; i1 = outerInstance.TaskToggleButtonHeight; int i2 = bool1 ? insets.left : (j - insets.right); int i3 = k + i1; if (!bool2) { outerInstance.applicationMenuButton.Visible = (outerInstance.ribbon.ApplicationMenu != null); if (outerInstance.ribbon.ApplicationMenu != null) { if (bool1) { outerInstance.applicationMenuButton.setBounds(-5, insets.top, i3 + 24, i3); } else { outerInstance.applicationMenuButton.setBounds(i2 - i3, insets.top, i3, i3); } } } else { outerInstance.applicationMenuButton.Visible = false; } i2 = bool1 ? (i2 + 2) : (i2 - 2); if (FlamingoUtilities.getApplicationMenuButton(SwingUtilities.getWindowAncestor(outerInstance.ribbon)) != null) { i2 = bool1 ? (i2 + i3 + 15) : (i2 - i3); } if (outerInstance.o_trailingButton != null && outerInstance.helpButton == null) { Dimension dimension = outerInstance.o_trailingButton.PreferredSize; if (bool1) { outerInstance.o_trailingButton.setBounds(j - insets.right - dimension.width, m, dimension.width, dimension.height); } else { outerInstance.o_trailingButton.setBounds(insets.left, m, dimension.width, dimension.height); } if (outerInstance.o_searchButton != null) { Dimension dimension1 = outerInstance.o_searchButton.PreferredSize; if (bool1) { outerInstance.o_searchButton.setBounds(n, m, dimension1.width, dimension1.height); } else { outerInstance.o_searchButton.setBounds(insets.left + dimension1.width, m, dimension1.width, dimension1.height); } } } if (outerInstance.helpButton != null) { Dimension dimension = outerInstance.helpButton.PreferredSize; if (bool1) { outerInstance.helpButton.setBounds(j - insets.right - dimension.width, m, dimension.width, dimension.height); } else { outerInstance.helpButton.setBounds(insets.left, m, dimension.width, dimension.height); } if (outerInstance.o_trailingButton != null) { Dimension dimension1 = outerInstance.o_trailingButton.PreferredSize; if (bool1) { outerInstance.o_trailingButton.setBounds(j - insets.right * 2 - dimension1.width + dimension.width, m, dimension1.width, dimension1.height); } else { outerInstance.o_trailingButton.setBounds(insets.left + dimension1.width, m, dimension1.width, dimension1.height); } } } int i4 = 0; if (bool1) { i4 = (outerInstance.o_trailingButton != null) ? (outerInstance.o_trailingButton.X - i - i2) : (param1Container.Width - insets.right - i2); if (outerInstance.helpButton != null && outerInstance.o_trailingButton != null) { i4 = outerInstance.o_trailingButton.X - i - i2; } if (outerInstance.o_searchButton != null && outerInstance.o_trailingButton != null) { i4 = outerInstance.o_searchButton.X - i - i2; } outerInstance.taskToggleButtonsScrollablePanel.setBounds(i2, m, i4, i1); } else { i4 = (outerInstance.helpButton != null) ? (i2 - i - outerInstance.helpButton.X - outerInstance.o_trailingButton.Width) : (i2 - insets.left); if (outerInstance.helpButton != null && outerInstance.o_trailingButton != null) { i4 = i2 - i - outerInstance.o_trailingButton.X - outerInstance.o_trailingButton.Width - outerInstance.helpButton.X - outerInstance.helpButton.Width; } outerInstance.taskToggleButtonsScrollablePanel.setBounds(i2 - i4, m, i4, i1); } BasicRibbonUI.TaskToggleButtonsHostPanel taskToggleButtonsHostPanel = (BasicRibbonUI.TaskToggleButtonsHostPanel)outerInstance.taskToggleButtonsScrollablePanel.View; int i5 = (taskToggleButtonsHostPanel.MinimumSize).width; taskToggleButtonsHostPanel.PreferredSize = new Dimension(i5, (this.this$0.taskToggleButtonsScrollablePanel.Bounds).height); outerInstance.taskToggleButtonsScrollablePanel.doLayout(); m += i1; int i6 = i1; if (!bool2) { i6 += k; } if (outerInstance.bandScrollablePanel.Parent == outerInstance.ribbon) { if (!outerInstance.ribbon.Minimized && outerInstance.ribbon.TaskCount > 0) { Insets insets1 = (outerInstance.ribbon.SelectedTask.BandCount == 0) ? new Insets(0, 0, 0, 0) : outerInstance.ribbon.SelectedTask.getBand(0).Insets; outerInstance.bandScrollablePanel.setBounds(1 + insets.left, m + insets1.top, param1Container.Width - 2 * insets.left - 2 * insets.right - 1, param1Container.Height - i6 - insets.top - insets.bottom - insets1.top - insets1.bottom); BasicRibbonUI.BandHostPanel bandHostPanel = (BasicRibbonUI.BandHostPanel)outerInstance.bandScrollablePanel.View; int i7 = (bandHostPanel.MinimumSize).width; bandHostPanel.PreferredSize = new Dimension(i7, (this.this$0.bandScrollablePanel.Bounds).height); outerInstance.bandScrollablePanel.doLayout(); bandHostPanel.doLayout(); } else { outerInstance.bandScrollablePanel.setBounds(0, 0, 0, 0); } } }
public static double GetDefaultBaseline(FontMetrics fontMetrics) { return(Math.Abs(fontMetrics.Ascent)); }
/// <summary> /// This method determines the common baselines for the paragraph. /// </summary> private void DetermineBaselines() { float baselineOffset = 0.0f; float strikethroughOffset = 0.0f; float underlineOffset = 0.0f; float strikethroughThickness = 0.0f; float underlineThickness = 0.0f; foreach(FormattedRun run in _OutputSink.Runs) { DxFontMetrics dxMetrics = run.Font.ResolveFace().Metrics; FontMetrics metrics = new FontMetrics( dxMetrics.Ascent, dxMetrics.Descent, dxMetrics.DesignUnitsPerEm); float blo = metrics.Measure(dxMetrics.Ascent + dxMetrics.Descent, run.PointSize); float sto = metrics.Measure(dxMetrics.StrikethroughPosition, run.PointSize); float ulo = metrics.Measure(dxMetrics.UnderlinePosition, run.PointSize); float stt = metrics.Measure(dxMetrics.StrikethroughThickness, run.PointSize); float ult = metrics.Measure(dxMetrics.UnderlineThickness, run.PointSize); baselineOffset = TakeAbsMax(baselineOffset, blo); strikethroughOffset = TakeAbsMax(strikethroughOffset, sto); underlineOffset = TakeAbsMax(underlineOffset, ulo); strikethroughThickness = TakeAbsMax(strikethroughThickness, stt); underlineThickness = TakeAbsMax(underlineThickness, ult); } _OutputSink.BaselineOffset = baselineOffset; _OutputSink.StrikethroughOffset = strikethroughOffset; _OutputSink.StrikethroughThickness = strikethroughThickness; _OutputSink.UnderlineOffset = underlineOffset; _OutputSink.UnderlineThickness = underlineThickness; }