public static XGlyphTypeface GetOrCreateFromGdi(GdiFont gdiFont) { // $TODO THHO Lock??? string typefaceKey = ComputeKey(gdiFont); if (GlyphTypefaceCache.TryGetGlyphTypeface(typefaceKey, out XGlyphTypeface glyphTypeface)) { // We have the glyph typeface already in cache. return(glyphTypeface); } XFontFamily fontFamily = XFontFamily.GetOrCreateFromGdi(gdiFont); XFontSource fontSource = XFontSource.GetOrCreateFromGdi(typefaceKey, gdiFont); // Check if styles must be simulated. XStyleSimulations styleSimulations = XStyleSimulations.None; if (gdiFont.Bold && !fontSource.Fontface.os2.IsBold) { styleSimulations |= XStyleSimulations.BoldSimulation; } if (gdiFont.Italic && !fontSource.Fontface.os2.IsItalic) { styleSimulations |= XStyleSimulations.ItalicSimulation; } glyphTypeface = new XGlyphTypeface(typefaceKey, fontFamily, fontSource, styleSimulations, gdiFont); GlyphTypefaceCache.AddGlyphTypeface(glyphTypeface); return(glyphTypeface); }
/// <summary> /// A GDI+ font object is used to setup the internal font objects. /// </summary> void InitializeFromGdi() { try { Lock.EnterFontFactory(); if (GdiFontFamily != null) { // Create font based on its family. GdiFont = new GdiFont(GdiFontFamily, (float)Size, (GdiFontStyle)Style, GraphicsUnit.World); } if (GdiFont != null) { #if DEBUG_ string name1 = _gdiFont.Name; string name2 = _gdiFont.OriginalFontName; string name3 = _gdiFont.SystemFontName; #endif FamilyName = GdiFont.FontFamily.Name; // TODO: _glyphTypeface = XGlyphTypeface.GetOrCreateFrom(_gdiFont); } else { Debug.Assert(false); } if (GlyphTypeface == null) { GlyphTypeface = XGlyphTypeface.GetOrCreateFromGdi(GdiFont); } CreateDescriptorAndInitializeFontMetrics(); } finally { Lock.ExitFontFactory(); } }
internal static string ComputeKey(GdiFont gdiFont) { string name1 = gdiFont.Name; string name2 = gdiFont.OriginalFontName; string name3 = gdiFont.SystemFontName; string name = name1; GdiFontStyle style = gdiFont.Style; string key = KeyPrefix + name.ToLowerInvariant() + ((style & GdiFontStyle.Italic) == GdiFontStyle.Italic ? "/i" : "/n") + ((style & GdiFontStyle.Bold) == GdiFontStyle.Bold ? "/700" : "/400") + "/5"; // Stretch.Normal return(key); }
const string KeyPrefix = "tk:"; // "typeface key" #if CORE || GDI XGlyphTypeface(string key, XFontFamily fontFamily, XFontSource fontSource, XStyleSimulations styleSimulations, GdiFont gdiFont) { Key = key; FontFamily = fontFamily; FontSource = fontSource; Fontface = OpenTypeFontface.CetOrCreateFrom(fontSource); Debug.Assert(ReferenceEquals(FontSource.Fontface, Fontface)); GdiFont = gdiFont; StyleSimulations = styleSimulations; Initialize(); }
/// <summary> /// Initializes a new instance of the <see cref="XFont"/> class from a System.DrawingCore.Font. /// </summary> /// <param name="font">The System.DrawingCore.Font.</param> /// <param name="pdfOptions">Additional PDF options.</param> public XFont(GdiFont font, XPDFFontOptions pdfOptions) { if (font.Unit != GraphicsUnit.World) { throw new ArgumentException("Font must use GraphicsUnit.World."); } _gdiFont = font; Debug.Assert(font.Name == font.FontFamily.Name); _familyName = font.Name; _emSize = font.Size; _style = FontStyleFrom(font); _pdfOptions = pdfOptions; InitializeFromGdi(); }
private SizeF MeasureString(string s, Graphics g, System.DrawingCore.Font drawFont, StringFormat drawFormat) { if (s == null || s.Length == 0) { return(SizeF.Empty); } CharacterRange[] cr = { new CharacterRange(0, s.Length) }; drawFormat.SetMeasurableCharacterRanges(cr); Region[] rs = new Region[1]; rs = g.MeasureCharacterRanges(s, drawFont, new RectangleF(0, 0, float.MaxValue, float.MaxValue), drawFormat); RectangleF mr = rs[0].GetBounds(g); return(new SizeF(mr.Width, mr.Height)); }
//internal static XGlyphTypeface TryGetXGlyphTypeface(string familyName, XFontStyle style) //{ // string name = MakeName(familyName, style); // XGlyphTypeface typeface; // _global._typefaces.TryGetValue(name, out typeface); // return typeface; //} #if GDI internal static GdiFont TryCreateFont(string name, double size, GdiFontStyle style, out XFontSource fontSource) { fontSource = null; try { GdiPrivateFontCollection pfc = Singleton._privateFontCollection; if (pfc == null) { return(null); } #if true string key = MakeKey(name, (XFontStyle)style); if (Singleton._fontSources.TryGetValue(key, out fontSource)) { GdiFont font = new GdiFont(name, (float)size, style, GraphicsUnit.World); #if DEBUG_ Debug.Assert(StringComparer.OrdinalIgnoreCase.Compare(name, font.Name) == 0); Debug.Assert(font.Bold == ((style & GdiFontStyle.Bold) != 0)); Debug.Assert(font.Italic == ((style & GdiFontStyle.Italic) != 0)); #endif return(font); } return(null); #else foreach (GdiFontFamily family in pfc.Families) { if (string.Compare(family.Name, name, StringComparison.OrdinalIgnoreCase) == 0) { GdiFont font = new GdiFont(family, (float)size, style, GraphicsUnit.World); if (string.Compare(font.Name, name, StringComparison.OrdinalIgnoreCase) != 0) { // Style simulation is not implemented in GDI+. // Use WPF build. } return(font); } } #endif } catch (Exception ex) { // Ignore exception and return null. Debug.WriteLine(ex.ToString()); } return(null); }
public static GdiFont CreateFont(string familyName, double emSize, GdiFontStyle style, out XFontSource fontSource) { fontSource = null; // ReSharper disable once JoinDeclarationAndInitializer GdiFont font; // Use font resolver in CORE build. XPrivateFontCollection exists only in GDI and WPF build. #if GDI // Try private font collection first. font = XPrivateFontCollection.TryCreateFont(familyName, emSize, style, out fontSource); if (font != null) { // Get font source is different for this font because Win32 does not know it. return(font); } #endif // Create ordinary Win32 font. font = new GdiFont(familyName, (float)emSize, style, GraphicsUnit.World); return(font); }
/// <summary> /// Measures the location of words within a string; limited by .Net 1.1 to 32 words /// MEASUREMAX is a constant that defines that limit /// </summary> /// <param name="s"></param> /// <param name="g"></param> /// <param name="drawFont"></param> /// <param name="drawFormat"></param> /// <param name="cra"></param> /// <returns></returns> private WordStartFinish[] MeasureString32(string s, Graphics g, System.DrawingCore.Font drawFont, StringFormat drawFormat, CharacterRange[] cra) { if (s == null || s.Length == 0) { return(null); } drawFormat.SetMeasurableCharacterRanges(cra); Region[] rs = new Region[cra.Length]; rs = g.MeasureCharacterRanges(s, drawFont, new RectangleF(0, 0, float.MaxValue, float.MaxValue), drawFormat); WordStartFinish[] sz = new WordStartFinish[cra.Length]; int isz = 0; foreach (Region r in rs) { RectangleF mr = r.GetBounds(g); sz[isz].start = Measurement.PointsFromPixels(mr.Left, g.DpiX); sz[isz].end = Measurement.PointsFromPixels(mr.Right, g.DpiX); isz++; } return(sz); }
/// <summary> /// Create a GDI+ font and use its handle to retrieve font data using native calls. /// </summary> internal static XFontSource CreateFontSource(string familyName, FontResolvingOptions fontResolvingOptions, out GdiFont font, string typefaceKey) { if (String.IsNullOrEmpty(typefaceKey)) { typefaceKey = XGlyphTypeface.ComputeKey(familyName, fontResolvingOptions); } #if true_ if (familyName == "Cambria") { Debug - Break.Break(); } #endif GdiFontStyle gdiStyle = (GdiFontStyle)(fontResolvingOptions.FontStyle & XFontStyle.BoldItalic); // Create a 10 point GDI+ font as an exemplar. font = FontHelper.CreateFont(familyName, 10, gdiStyle, out XFontSource fontSource); if (fontSource != null) { Debug.Assert(font != null); // Case: Font was created by a GDI+ private font collection. #if true #if DEBUG Debug.Assert(FontFactory.TryGetFontSourceByTypefaceKey(typefaceKey, out XFontSource existingFontSource) && ReferenceEquals(fontSource, existingFontSource)); #endif #else // Win32 API cannot get font data from fonts created by private font collection, // because this is handled internally in GDI+. // Therefore the font source was created when the private font is added to the private font collection. if (!FontFactory.TryGetFontSourceByTypefaceKey(typefaceKey, out fontSource)) { // Simplify styles. // (The code is written for clarity - do not rearrange for optimization) if (font.Bold && font.Italic) { if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, true, false), out fontSource)) { // Use bold font. FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); } else if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, true), out fontSource)) { // Use italic font. FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); } else if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, false), out fontSource)) { // Use regular font. FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); } } else if (font.Bold || font.Italic) { // Use regular font. if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, false), out fontSource)) { FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); } } else { if (FontFactory.TryGetFontSourceByTypefaceKey(XGlyphTypeface.ComputeKey(font.Name, false, false), out fontSource)) { // Should never come here... FontFactory.CacheExistingFontSourceWithNewTypefaceKey(typefaceKey, fontSource); } } } #endif } else { // Get or create the font source and cache it under the specified typeface key. fontSource = XFontSource.GetOrCreateFromGdi(typefaceKey, font); } return(fontSource); }
public PlatformFontResolverInfo(string faceName, bool mustSimulateBold, bool mustSimulateItalic, GdiFont gdiFont) : base(faceName, mustSimulateBold, mustSimulateItalic) => GdiFont = gdiFont;
/// <summary> /// Measures the location of an arbritrary # of words within a string /// </summary> private WordStartFinish[] MeasureString(string s, Graphics g, System.DrawingCore.Font drawFont, StringFormat drawFormat, CharacterRange[] cra) { if (cra.Length <= MEASUREMAX) // handle the simple case of < MEASUREMAX words { return(MeasureString32(s, g, drawFont, drawFormat, cra)); } // Need to compensate for SetMeasurableCharacterRanges limitation of 32 (MEASUREMAX) int mcra = (cra.Length / MEASUREMAX); // # of full 32 arrays we need int ip = cra.Length % MEASUREMAX; // # of partial entries needed for last array (if any) WordStartFinish[] sz = new WordStartFinish[cra.Length]; // this is the final result; float startPos = 0; CharacterRange[] cra32 = new CharacterRange[MEASUREMAX]; // fill out int icra = 0; // index thru the cra for (int i = 0; i < mcra; i++) { // fill out the new array int ticra = icra; for (int j = 0; j < cra32.Length; j++) { cra32[j] = cra[ticra++]; cra32[j].First -= cra[icra].First; // adjust relative offsets of strings } // measure the word locations (in the new string) // ???? should I put a blank in front of it?? string ts = s.Substring(cra[icra].First, cra[icra + cra32.Length - 1].First + cra[icra + cra32.Length - 1].Length - cra[icra].First); WordStartFinish[] pos = MeasureString32(ts, g, drawFont, drawFormat, cra32); // copy the values adding in the new starting positions for (int j = 0; j < pos.Length; j++) { sz[icra].start = pos[j].start + startPos; sz[icra++].end = pos[j].end + startPos; } startPos = sz[icra - 1].end; // reset the start position for the next line } // handle the remaining character if (ip > 0) { // resize the range array cra32 = new CharacterRange[ip]; // fill out the new array int ticra = icra; for (int j = 0; j < cra32.Length; j++) { cra32[j] = cra[ticra++]; cra32[j].First -= cra[icra].First; // adjust relative offsets of strings } // measure the word locations (in the new string) // ???? should I put a blank in front of it?? string ts = s.Substring(cra[icra].First, cra[icra + cra32.Length - 1].First + cra[icra + cra32.Length - 1].Length - cra[icra].First); WordStartFinish[] pos = MeasureString32(ts, g, drawFont, drawFormat, cra32); // copy the values adding in the new starting positions for (int j = 0; j < pos.Length; j++) { sz[icra].start = pos[j].start + startPos; sz[icra++].end = pos[j].end + startPos; } } return(sz); }
private string[] MeasureString(PageText pt, Graphics g, out float[] width) { StyleInfo si = pt.SI; string s = pt.Text; System.DrawingCore.Font drawFont = null; StringFormat drawFormat = null; SizeF ms; string[] sa = null; width = null; try { // STYLE System.DrawingCore.FontStyle fs = 0; if (si.FontStyle == FontStyleEnum.Italic) { fs |= System.DrawingCore.FontStyle.Italic; } // WEIGHT switch (si.FontWeight) { case FontWeightEnum.Bold: case FontWeightEnum.Bolder: case FontWeightEnum.W500: case FontWeightEnum.W600: case FontWeightEnum.W700: case FontWeightEnum.W800: case FontWeightEnum.W900: fs |= System.DrawingCore.FontStyle.Bold; break; default: break; } drawFont = new System.DrawingCore.Font(StyleInfo.GetFontFamily(si.FontFamilyFull), si.FontSize, fs); drawFormat = new StringFormat(); drawFormat.Alignment = StringAlignment.Near; // Measure string // pt.NoClip indicates that this was generated by PageTextHtml Build. It has already word wrapped. if (pt.NoClip || pt.SI.WritingMode == WritingModeEnum.tb_rl) // TODO: support multiple lines for vertical text { ms = MeasureString(s, g, drawFont, drawFormat); width = new float[1]; width[0] = Measurement.PointsFromPixels(ms.Width, g.DpiX); // convert to points from pixels sa = new string[1]; sa[0] = s; return(sa); } // handle multiple lines; // 1) split the string into the forced line breaks (ie "\n and \r") // 2) foreach of the forced line breaks; break these into words and recombine s = s.Replace("\r\n", "\n"); // don't want this to result in double lines string[] flines = s.Split(LINEBREAK); List <string> lines = new List <string>(); List <float> lineWidths = new List <float>(); // remove the size reserved for left and right padding float ptWidth = pt.W - pt.SI.PaddingLeft - pt.SI.PaddingRight; if (ptWidth <= 0) { ptWidth = 1; } foreach (string tfl in flines) { string fl; if (tfl.Length > 0 && tfl[tfl.Length - 1] == ' ') { fl = tfl.TrimEnd(' '); } else { fl = tfl; } // Check if entire string fits into a line ms = MeasureString(fl, g, drawFont, drawFormat); float tw = Measurement.PointsFromPixels(ms.Width, g.DpiX); if (tw <= ptWidth) { // line fits don't need to break it down further lines.Add(fl); lineWidths.Add(tw); continue; } // Line too long; need to break into multiple lines // 1) break line into parts; then build up again keeping track of word positions string[] parts = fl.Split(WORDBREAK); // this is the maximum split of lines StringBuilder sb = new StringBuilder(fl.Length); CharacterRange[] cra = new CharacterRange[parts.Length]; for (int i = 0; i < parts.Length; i++) { int sc = sb.Length; // starting character sb.Append(parts[i]); // endding character if (i != parts.Length - 1) // last item doesn't need blank { sb.Append(" "); } int ec = sb.Length; CharacterRange cr = new CharacterRange(sc, ec - sc); cra[i] = cr; // add to character array } // 2) Measure the word locations within the line string wfl = sb.ToString(); WordStartFinish[] wordLocations = MeasureString(wfl, g, drawFont, drawFormat, cra); if (wordLocations == null) { continue; } // 3) Loop thru creating new lines as needed int startLoc = 0; CharacterRange crs = cra[startLoc]; CharacterRange cre = cra[startLoc]; float cwidth = wordLocations[0].end; // length of the first float bwidth = wordLocations[0].start; // characters need a little extra on start string ts; bool bLine = true; for (int i = 1; i < cra.Length; i++) { cwidth = wordLocations[i].end - wordLocations[startLoc].start + bwidth; if (cwidth > ptWidth) { // time for a new line cre = cra[i - 1]; ts = wfl.Substring(crs.First, cre.First + cre.Length - crs.First); lines.Add(ts); lineWidths.Add(wordLocations[i - 1].end - wordLocations[startLoc].start + bwidth); // Find the first non-blank character of the next line while (i < cra.Length && cra[i].Length == 1 && fl[cra[i].First] == ' ') { i++; } if (i < cra.Length) // any lines left? { // yes, continue on startLoc = i; crs = cre = cra[startLoc]; cwidth = wordLocations[i].end - wordLocations[startLoc].start + bwidth; } else // no, we can stop { bLine = false; } // bwidth = wordLocations[startLoc].start - wordLocations[startLoc - 1].end; } else { cre = cra[i]; } } if (bLine) { ts = fl.Substring(crs.First, cre.First + cre.Length - crs.First); lines.Add(ts); lineWidths.Add(cwidth); } } // create the final array from the Lists string[] la = lines.ToArray(); width = lineWidths.ToArray(); return(la); } finally { if (drawFont != null) { drawFont.Dispose(); } if (drawFormat != null) { drawFont.Dispose(); } } }
//drawstring justified with paragraph format public static void DrawStringJustified(System.DrawingCore.Graphics graphics, string s, System.DrawingCore.Font font, System.DrawingCore.Brush brush, System.DrawingCore.RectangleF layoutRectangle, char paragraphFormat) { try { //save the current state of the graphics handle GraphicsState graphicsState = graphics.Save(); //obtain the font height to be used as line height double lineHeight = (double)Math.Round(font.GetHeight(graphics), 1); //string builder to format the text StringBuilder text = new StringBuilder(s); var originalFont = new System.DrawingCore.Font(font.FontFamily, font.Size, font.Style); //adjust the text string to ease detection of carriage returns text = text.Replace("\r\n", " <CR> "); text = text.Replace("\r", " <CR> "); text.Append(" <CR> "); //ensure measure string will bring the best measures possible (antialias) graphics.TextRenderingHint = TextRenderingHint.AntiAlias; //create a string format object with the generic typographic to obtain the most accurate string measurements //strange, but the recommended for this case is to use a "cloned" stringformat var stringFormat = (System.DrawingCore.StringFormat)System.DrawingCore.StringFormat.GenericTypographic.Clone(); //allow the correct measuring of spaces stringFormat.FormatFlags = System.DrawingCore.StringFormatFlags.MeasureTrailingSpaces; //create a stringformat for leftalignment System.DrawingCore.StringFormat leftAlignHandle = new System.DrawingCore.StringFormat(); leftAlignHandle.LineAlignment = System.DrawingCore.StringAlignment.Near; //create a stringformat for rightalignment System.DrawingCore.StringFormat rightAlignHandle = new System.DrawingCore.StringFormat(); rightAlignHandle.LineAlignment = System.DrawingCore.StringAlignment.Far; //measure space for the given font var stringSize = graphics.MeasureString(" ", font, layoutRectangle.Size, stringFormat); double spaceWidth = stringSize.Width + 1; //measure paragraph format for the given font double paragraphFormatWidth = 0; if (paragraphFormat != ' ') { var paragraphFormatSize = graphics.MeasureString(paragraphFormat.ToString(), new System.DrawingCore.Font(font.FontFamily, font.Size, System.DrawingCore.FontStyle.Regular), layoutRectangle.Size, stringFormat); paragraphFormatWidth = paragraphFormatSize.Width; } //total word count int totalWords = Regex.Matches(text.ToString(), " ").Count; //array of words ArrayList words = new ArrayList(); //measure each word int n = 0; while (true) { //original word string word = Regex.Split(text.ToString(), " ").GetValue(n).ToString(); //add to words array the word without tags words.Add(new Word(word.Replace("<b>", "").Replace("</b>", "").Replace("<i>", "").Replace("</i>", ""))); //marque to start bolding or/and italic if (word.ToLower().Contains("<b>") && word.ToLower().Contains("<i>")) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Bold & System.DrawingCore.FontStyle.Italic); } else if (word.ToLower().Contains("<b>")) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Bold); } else if (word.ToLower().Contains("<i>")) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Italic); } Word currentWord = (Word)words[n]; currentWord.StartBold = word.ToLower().Contains("<b>"); currentWord.StopBold = word.ToLower().Contains("</b>"); currentWord.StartItalic = word.ToLower().Contains("<i>"); currentWord.StopItalic = word.ToLower().Contains("</i>"); //size of the word var wordSize = graphics.MeasureString(currentWord.String, font, layoutRectangle.Size, stringFormat); float wordWidth = wordSize.Width; if (wordWidth > layoutRectangle.Width && currentWord.String != "<CR>") { int reduce = 1; while (true) { int lengthChars = (int)Math.Round(currentWord.String.Length / (wordWidth / layoutRectangle.Width), 0) - reduce; string cutWord = currentWord.String.Substring(0, lengthChars); //the new size of the word wordSize = graphics.MeasureString(cutWord, font, layoutRectangle.Size, stringFormat); wordWidth = wordSize.Width; //update the word string ((Word)words[n]).String = cutWord; //add new word if (wordWidth <= layoutRectangle.Width) { totalWords++; words.Add(new Word("", 0, currentWord.StartBold, currentWord.StopBold, currentWord.StartItalic, currentWord.StopItalic)); text.Replace(currentWord.String, cutWord + " " + currentWord.String.Substring(lengthChars + 1), 0, 1); break; } reduce++; } } //update the word size ((Word)words[n]).Length = wordWidth; //marque to stop bolding or/and italic if (word.ToLower().Contains("</b>") && font.Style == System.DrawingCore.FontStyle.Italic) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Italic); } else if (word.ToLower().Contains("</i>") && font.Style == System.DrawingCore.FontStyle.Bold) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Bold); } else if (word.ToLower().Contains("</b>") || word.ToLower().Contains("</i>")) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Regular); } n++; if (n > totalWords - 1) { break; } } //before we start drawing, its wise to restore ou graphics objecto to its original state graphics.Restore(graphicsState); //restore to font to the original values font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, originalFont.Style); //start drawing word by word int currentLine = 0; for (int i = 0; i < totalWords; i++) { bool endOfSentence = false; double wordsWidth = 0; int wordsInLine = 0; int j = i; for (j = i; j < totalWords; j++) { if (((Word)words[j]).String == "<CR>") { endOfSentence = true; break; } wordsWidth += ((Word)words[j]).Length + spaceWidth; if (wordsWidth > layoutRectangle.Width && j > i) { wordsWidth = wordsWidth - ((Word)words[j]).Length - (spaceWidth * wordsInLine); break; } wordsInLine++; } if (j > totalWords) { endOfSentence = true; } double widthOfBetween = 0; if (endOfSentence) { widthOfBetween = spaceWidth; } else { widthOfBetween = (layoutRectangle.Width - wordsWidth) / (wordsInLine - 1); } double currentTop = layoutRectangle.Top + (int)(currentLine * lineHeight); if (currentTop > (layoutRectangle.Height + layoutRectangle.Top)) { i = totalWords; break; } double currentLeft = layoutRectangle.Left; bool lastWord = false; for (int currentWord = 0; currentWord < wordsInLine; currentWord++) { bool loop = false; if (((Word)words[i]).String == "<CR>") { i++; loop = true; } if (!loop) { //last word in sentence if (currentWord == wordsInLine && !endOfSentence) { lastWord = true; } if (wordsInLine == 1) { currentLeft = layoutRectangle.Left; lastWord = false; } System.DrawingCore.RectangleF rectangleF; System.DrawingCore.StringFormat stringFormatHandle; if (lastWord) { rectangleF = new System.DrawingCore.RectangleF(layoutRectangle.Left, (float)currentTop, layoutRectangle.Width, (float)(currentTop + lineHeight)); stringFormatHandle = rightAlignHandle; } else { //lets zero size for word to drawstring auto-size de word rectangleF = new System.DrawingCore.RectangleF((float)currentLeft, (float)currentTop, 0, 0); stringFormatHandle = leftAlignHandle; } //start bolding and/or italic if (((Word)words[i]).StartBold && ((Word)words[i]).StartItalic) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Bold & System.DrawingCore.FontStyle.Italic); } else if (((Word)words[i]).StartBold) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Bold); } else if (((Word)words[i]).StartItalic) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Italic); } //draw the word graphics.DrawString(((Word)words[i]).String, font, brush, rectangleF, stringFormatHandle); //stop bolding and/or italic if (((Word)words[i]).StopBold && font.Style == System.DrawingCore.FontStyle.Italic) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Regular); } else if (((Word)words[i]).StopItalic && font.Style == System.DrawingCore.FontStyle.Bold) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Bold); } else if (((Word)words[i]).StopBold || ((Word)words[i]).StopItalic) { font = new System.DrawingCore.Font(originalFont.FontFamily, originalFont.Size, System.DrawingCore.FontStyle.Regular); } //paragraph formating if (endOfSentence && currentWord == wordsInLine - 1 && paragraphFormat != ' ') { currentLeft += ((Word)words[i]).Length; //draw until end of line while (currentLeft + paragraphFormatWidth <= layoutRectangle.Left + layoutRectangle.Width) { rectangleF = new System.DrawingCore.RectangleF((float)currentLeft, (float)currentTop, 0, 0); //draw the paragraph format graphics.DrawString(paragraphFormat.ToString(), font, brush, rectangleF, stringFormatHandle); currentLeft += paragraphFormatWidth; } } else { currentLeft += ((Word)words[i]).Length + widthOfBetween; } //go to next word i++; } } currentLine++; if (i >= totalWords) { break; } //compensate endfor if (((Word)words[i]).String != "<CR>") { i--; } } } catch (Exception ex) { throw new Exception(ex.Message); } }
//drawstring justified without paragraph format public static void DrawStringJustified(System.DrawingCore.Graphics graphics, string s, System.DrawingCore.Font font, System.DrawingCore.Brush brush, System.DrawingCore.RectangleF layoutRectangle) { DrawStringJustified(graphics, s, font, brush, layoutRectangle, ' '); }
/// <summary> /// 创建验证码的图片 /// </summary> /// <param name="validateCode">验证码</param> /// <param name="height">图片高度</param> /// <param name="rightOffsetWidth">文字的右边偏移量宽度</param> /// <returns></returns> public static byte[] CreateValidateGraphic(string validateCode, int height, int leftOffsetWidth, int rightOffsetWidth) { int randAngle = 45; //随机转动角度 int mapwidth = (int)(validateCode.Length * 24) + leftOffsetWidth + rightOffsetWidth; Bitmap image = new Bitmap(mapwidth, height); //创建图片背景 Graphics graph = Graphics.FromImage(image); try { graph.Clear(Color.AliceBlue);//清除画面,填充背景 Random rand = new Random(); //验证码旋转,防止机器识别 char[] chars = validateCode.ToCharArray();//拆散字符串成单字符数组 //文字距中 StringFormat format = new StringFormat(StringFormatFlags.NoClip); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; //定义颜色 Color[] c = { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple }; //定义字体 string[] font = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial", "宋体" }; int cindex = rand.Next(7); for (int i = 0; i < chars.Length; i++) { int findex = rand.Next(5); Font f = new System.DrawingCore.Font(font[findex], 20, System.DrawingCore.FontStyle.Bold);//字体样式(参数2为字体大小) Brush b = new System.DrawingCore.SolidBrush(c[cindex]); Point dot = new Point(20, 12); //graph.DrawString(dot.X.ToString(),fontstyle,new SolidBrush(Color.Black),10,150);//测试X坐标显示间距的 float angle = rand.Next(-randAngle, randAngle); //转动的度数 graph.TranslateTransform(dot.X, dot.Y); //移动光标到指定位置 graph.RotateTransform(angle); graph.DrawString(chars[i].ToString(), f, b, 0, 5, format); //graph.DrawString(chars[i].ToString(),fontstyle,new SolidBrush(Color.Blue),1,1,format); graph.RotateTransform(-angle); //转回去 graph.TranslateTransform(-2, -dot.Y); //移动光标到指定位置,每个字符紧凑显示,避免被软件识别 } Brush lb = new System.DrawingCore.SolidBrush(c[cindex]); graph.TranslateTransform(-graph.Transform.OffsetX, -graph.Transform.OffsetY); // graph.DrawLine(new Pen(Color.DarkGray, 3), 0, image.Height / 2, image.Width, image.Height / 2); int x1 = 0; int x2 = 0; int y1 = 0; int y2 = 0; int lt = image.Width / 20; int dy = 2; //背景噪点生成 for (int i = 0; i < 30; i++) { x1 = i == 0 ? lt * i : x2; y1 = i == 0 ? (image.Height / 2 + rand.Next(-dy, dy)) : y2; x2 = x1 + lt; y2 = image.Height / 2 + rand.Next(-dy, dy); graph.DrawLine(new Pen(Color.DarkGray, 2), x1, y1, x2, y2); } //for (int i = 0; i < 0; i++) //{ // int x11 = rand.Next(image.Width); // int x12 = rand.Next(image.Width); // int y11 = rand.Next(image.Height); // int y12 = rand.Next(image.Height); // graph.DrawLine(new Pen(Color.DarkGray), x11, y11, x12, y12); //} //生成图片 using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { image.Save(ms, System.DrawingCore.Imaging.ImageFormat.Gif); return(ms.ToArray()); } } finally { graph.Dispose(); image.Dispose(); } }
/// <summary> /// Initializes a new instance of the <see cref="XFont"/> class from a System.DrawingCore.Font. /// </summary> /// <param name="font">The System.DrawingCore.Font.</param> public XFont(GdiFont font) : this(font, new XPDFFontOptions(GlobalFontSettings.DefaultFontEncoding)) { }
public static XGlyphTypeface GetOrCreateFrom(string familyName, FontResolvingOptions fontResolvingOptions) { // Check cache for requested type face. string typefaceKey = ComputeKey(familyName, fontResolvingOptions); XGlyphTypeface glyphTypeface; try { // Lock around TryGetGlyphTypeface and AddGlyphTypeface. Lock.EnterFontFactory(); if (GlyphTypefaceCache.TryGetGlyphTypeface(typefaceKey, out glyphTypeface)) { // Just return existing one. return(glyphTypeface); } // Resolve typeface by FontFactory. FontResolverInfo fontResolverInfo = FontFactory.ResolveTypeface(familyName, fontResolvingOptions, typefaceKey); if (fontResolverInfo == null) { // No fallback - just stop. throw new InvalidOperationException("No appropriate font found."); } #if CORE || GDI GdiFont gdiFont = null; #endif #if WPF WpfFontFamily wpfFontFamily = null; WpfTypeface wpfTypeface = null; WpfGlyphTypeface wpfGlyphTypeface = null; #endif #if UWP // Nothing to do. #endif // Now create the font family at the first. XFontFamily fontFamily; if (fontResolverInfo is PlatformFontResolverInfo platformFontResolverInfo) { // Case: fontResolverInfo was created by platform font resolver // and contains platform specific objects that are reused. #if CORE || GDI // Reuse GDI+ font from platform font resolver. gdiFont = platformFontResolverInfo.GdiFont; fontFamily = XFontFamily.GetOrCreateFromGdi(gdiFont); #endif #if WPF #if !SILVERLIGHT // Reuse WPF font family created from platform font resolver. wpfFontFamily = platformFontResolverInfo.WpfFontFamily; wpfTypeface = platformFontResolverInfo.WpfTypeface; wpfGlyphTypeface = platformFontResolverInfo.WpfGlyphTypeface; fontFamily = XFontFamily.GetOrCreateFromWpf(wpfFontFamily); #else fontFamily = XFontFamily.GetOrCreateFromWpf(new WpfFontFamily(familyName)); #endif #endif #if NETFX_CORE || UWP fontFamily = null; #endif } else { // Case: fontResolverInfo was created by custom font resolver. // Get or create font family for custom font resolver retrieved font source. fontFamily = XFontFamily.GetOrCreateFontFamily(familyName); } // We have a valid font resolver info. That means we also have an XFontSource object loaded in the cache. XFontSource fontSource = FontFactory.GetFontSourceByFontName(fontResolverInfo.FaceName); Debug.Assert(fontSource != null); // Each font source already contains its OpenTypeFontface. #if CORE || GDI glyphTypeface = new XGlyphTypeface(typefaceKey, fontFamily, fontSource, fontResolverInfo.StyleSimulations, gdiFont); #endif #if WPF glyphTypeface = new XGlyphTypeface(typefaceKey, fontFamily, fontSource, fontResolverInfo.StyleSimulations, wpfTypeface, wpfGlyphTypeface); #endif #if NETFX_CORE || UWP glyphTypeface = new XGlyphTypeface(typefaceKey, fontFamily, fontSource, fontResolverInfo.StyleSimulations); #endif GlyphTypefaceCache.AddGlyphTypeface(glyphTypeface); } finally { Lock.ExitFontFactory(); } return(glyphTypeface); }