[]
Custom embedded fonts are significant part of document portability. With fonts embedded in it, user can always open the word document with correct fonts even if the fonts do not exist on his system. This feature is especially useful while rendering word documents which use rare fonts not available on a usual system.
GcWord provides extensive API to enable users to define custom fonts, embed them in the Word document, apply them to the runs and so on.
GcWord allows you to create custom fonts using the FontInfo class which provides various properties to define custom font. The collection of these FontInfo objects for a document is represented by FontInfoCollection class. Hence, to add a custom font to a document, you need to add it to FontInfoCollection using Add method. To embed a font into a document, you can use Add method of the EmbeddedFontCollection class which represents the collection of embedded fonts in a document.
// Add the custom font to the document
// (in this case we simply duplicate "Times New Roman"):
var font1 = doc.Fonts.Add(myFontName1);
// Use "Times New Roman" font settings:
font1.CharSet = FontCharSet.Ansi;
font1.Family = FontFamily.Roman;
font1.Pitch = FontPitch.Variable;
font1.Panose = new List { 2, 2, 6, 3, 5, 4, 5, 2, 3, 4 };
font1.Signature.CodePageRange1 = 0x000001ff;
font1.Signature.CodePageRange2 = 0x00000000;
font1.Signature.UnicodeRange1 = 0xE0002EFF;
font1.Signature.UnicodeRange2 = 0xC000785B;
font1.Signature.UnicodeRange3 = 0x00000009;
font1.Signature.UnicodeRange4 = 0x00000000;
// Load the "Times New Roman" font data:
byte[] data1 = File.ReadAllBytes(@"..\..\..\Resources\Fonts\times.ttf");
// Embed font data into the document:
font1.Embedded.Add(EmbeddedFontType.Regular, FontDataType.ObfuscatedTrueTypeFont, data1);
To apply custom fonts to runs in your document, you can use Name property of the Font class.
const string myFontName1 = "My Font 1";
GcWordDocument doc = new GcWordDocument();
// Use first of the fonts to be embedded:
var p = doc.Body.Paragraphs.Add();
var run = p.GetRange().Runs.Add($"Text rendered using embedded font \"{myFontName1}\".");
// Apply custom font to the run:
run.Font.Name = myFontName1;
While creating word documents with GcWord, you can use FontCollection and Font classes from GrapeCity.Documents.Text namespace to embed fonts in a word document. You can embed a single font to the font collection of word document by using Add method of the FontInfoCollection class or, you can add a list of fonts to the font collection by using Append method. The SaveOptions class provides various embedded font settings which control how a document is saved.
// Load font from a .ttf file and set it as the font of the sample text:
var font = GrapeCity.Documents.Text.Font.FromFile(Path.Combine("Resources", "Fonts", "SEGA.ttf"));
// Assign the run's font to the font loaded from the file:
run.Font.Name = font.FontFamilyName;
// This embeds the font into the document, without this line the document won't display correctly
// on a system that does not have the SEGA.ttf font installed:
doc.Fonts.Add(font, true);
To fetch the type and name of fonts embedded in a document, loop through the embedded fonts inside font collection of the document and use Type property of the EmbeddedFont and Name property of the FontInfo object respectively.
GcWordDocument doc = new GcWordDocument();
// Load a DOCX that contains embedded font:
doc.Load(@"..\..\..\EmbedFonts.docx");
var embeddedFont = doc.Fonts.FirstOrDefault(fi_ => fi_.Embedded.Count > 1)?.Embedded[0];
doc.Body.Paragraphs.Add("Embedded fonts found in this document:", doc.Styles[BuiltInStyleId.Heading1]);
var myListTemplate = doc.ListTemplates.Add(BuiltInListTemplateId.BulletDefault, "myListTemplate");
// Enumerate the embedded fonts:
foreach (var fi in doc.Fonts)
{
foreach (var ef in fi.Embedded)
{
var p = doc.Body.Paragraphs.Add(doc.Styles[BuiltInStyleId.ListParagraph]);
p.ListFormat.Template = myListTemplate;
var run = p.GetRange().Runs.Add($"Found embedded font of type {ef.Type} in font \"{fi.Name}\".");
run.Font.Name = fi.Name;
if (ef.Type == EmbeddedFontType.Bold)
run.Font.Bold = true;
else if (ef.Type == EmbeddedFontType.Italic)
run.Font.Italic = true;
else if (ef.Type == EmbeddedFontType.BoldItalic)
run.Font.Bold = run.Font.Italic = true;
}
}
//Save Document
doc.Save("GetEmbeddedFonts.docx");
To find and remove embedded fonts from a document, you need to loop through the fonts collection of the document and call Clear method of the EmbeddedFontCollection which can be accessed through Embedded property of the FontInfo class.
GcWordDocument doc = new GcWordDocument();
// Load a DOCX that contains embedded font:
doc.Load(@"..\..\..\EmbedFonts.docx");
// Enumerate the embedded fonts:
foreach (var fi in doc.Fonts)
{
// Remove all embedded fonts:
fi.Embedded.Clear();
}
//Save Document
doc.Save("FindAndRemoveEmbeddedFont.docx");
GcWord provide Settings class to support Theme Fonts for different language cultures to render documents using multi-language Font scripts. You can fetch these theme fonts by using properties such as LocaleName, LocaleNameBi and LocaleNameFarEast. For a particular locale setting, GcWord finds the corresponding font script in Supplemental map from MinorFont and MajorFont theme font collection and marks them as 'in use'. If an appropriate font script is not found, GcWord defines font name from the MinorFont and MajorFont theme font collection. You can get the full list of font being used in the document by using GetFontsInUse method. All fonts from this list are candidates to be stored in the document but only fonts that are present in the SaveOptions.AvailableFonts are stored.
With this enhanced API support in place, GcWord also supports documents using cloud fonts. Following code shows how to embed cloud theme fonts in a Word document and also how to apply different language settings when Fonts from multiple languages are used
GcWordDocument doc = new GcWordDocument();
// set default languages for theme fonts
var settings = doc.Settings;
settings.LocaleName = "en-US";
settings.LocaleNameBi = "ar-AE";
settings.LocaleNameFarEast = "ja-JP";
// set languages for default font
// so you don't need specify them for each run
var defFont = doc.Styles.DefaultFont;
defFont.LocaleName = "en_US";
defFont.LocaleNameBi = "ar-AE";
defFont.LocaleNameFarEast = "ja-JP";
// set minor theme fonts for default font
// so you don't need specify them for each run
defFont.ThemeAscii = ThemeFontType.MinorHighAnsi;
defFont.ThemeBi = ThemeFontType.MinorBidi;
defFont.ThemeFarEast = ThemeFontType.MinorEastAsia;
// add a heading style that uses major theme fonts
Style hstyle = doc.Styles.Add("My Heading", StyleType.Paragraph);
hstyle.Font.Size = 20;
hstyle.Font.ThemeAscii = ThemeFontType.MajorHighAnsi;
hstyle.Font.ThemeBi = ThemeFontType.MajorBidi;
hstyle.Font.ThemeFarEast = ThemeFontType.MajorEastAsia;
hstyle.Font.ThemeOther = ThemeFontType.MajorHighAnsi;
// modern Microsoft Word documents uses cloud fonts:
// https://support.microsoft.com/en-us/office/cloud-fonts-in-office-f7b009fe-037f-45ed-a556-b5fe6ede6adb
// if Office 365 is installed on you computer, make your document readable for every one.
// specify minor theme fonts
var minorFont = doc.Theme.FontScheme.MinorFont;
minorFont.Latin.Name = "Calibri";
// you can specify fonts for any font script
minorFont.Supplemental["Arab"] = "Aldhabi";
minorFont.Supplemental["Jpan"] = "Yu Mincho";
// specify major theme fonts
var majorFont = doc.Theme.FontScheme.MajorFont;
majorFont.Latin.Name = "Calibri Light";
majorFont.Supplemental["Arab"] = "Traditional Arabic";
majorFont.Supplemental["Jpan"] = "Yu Gothic";
// add English text that will use minor and major Latin theme fonts automatically
var pars = doc.Body.Paragraphs;
pars.Add("Minor font");
pars.Add("Major font", hstyle);
// add Japanese text that will use minor and major East Asian theme fonts automatically
pars.Add("マイナーフォント");
pars.Add("メジャーフォント", hstyle);
// add Arabic text that will use minor and major Complex Scrip theme fonts
Paragraph p = pars.Add();
Run run = p.GetRange().Runs.Add("خط ثانوي");
// need to specify that the run is complex script
run.Font.RightToLeft = true;
run.Font.HintType = FontHintType.ComplexScript;
p = pars.Add(hstyle);
run = p.GetRange().Runs.Add("الخط الرئيسي");
run.Font.RightToLeft = true;
run.Font.HintType = FontHintType.ComplexScript;
// replace existing fonts and embed all fonts in use to the document
var saveOpts = doc.Settings.SaveOptions;
saveOpts.SaveFontInfos = SaveFontInfos.SaveAll;
saveOpts.FontEmbedMode = FontEmbedMode.All;
var fontsInUse = saveOpts.GetFontsInUse();
// check whether all fonts that are used in the document are available to embed
foreach (string name in fontsInUse.Keys)
{
if (saveOpts.AvailableFonts.FindFamilyName(name) == null)
{
// add cloud fonts to available font list
var fonts = new GrapeCity.Documents.Text.FontCollection();
string cloudFonts = @"c:\Users\\AppData\Local\Microsoft\FontCache\4\CloudFonts";
// Make sure fonts you assign are downloaded, if not just use them in Microsoft Word, so they will be loaded automatically
foreach (string fontFolder in Directory.EnumerateDirectories(cloudFonts))
fonts.RegisterDirectory(fontFolder);
saveOpts.AvailableFonts = fonts;
break;
}
}
// now this document will be displayed correctly on every machine
doc.Save(@"cloud-theme-fonts.docx");