I have a similar need. I need to deploy my web app to Azure Web Sites, and need some additional fonts in my reports. I can’t install them.
Can you please check the below code? It should do the job as it loads an inmemory font from an embedded resource. However, it only works if the font is pre-installed. (tested it with AR6). I am hoping that AR7 or 8 does work on this?
Please let me know if you can get me a sample that works.
Thx
Ries
—
using Amsterdam.Util;
using PPPBusLib;
using PPPDataLib.EntityClasses;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace PPPReports
{
public static class PPPCustomFonts
{
// This memory is not garbage collected, but is only static, it contains the embedded font data from the PPPReportLib.dll
private static GCHandle _pinnedArialFontArray;
private static PrivateFontCollection _embeddedFontCollection;
///
/// PPP-6725 Support japanese/chinese PDF reports via a setting
///
public static PrivateFontCollection EmbeddedFontCollection()
{
if (_embeddedFontCollection == null)
{
var arialUnicodeStream = ResourceUtil.GetResourceStream(@"PPPReports.Fonts.ARIALUNI.TTF");
PrivateFontCollection fontCollection = new PrivateFontCollection();
var bytes = arialUnicodeStream.ReadAllBytesFromStream();
_pinnedArialFontArray = GCHandle.Alloc(bytes, GCHandleType.Pinned);
IntPtr arialFontPointer = _pinnedArialFontArray.AddrOfPinnedObject();
fontCollection.AddMemoryFont(arialFontPointer, bytes.Length);
// Assign it at the end to prevent a race condition between two threads, risking that one thread sees the partial
// work of the other
_embeddedFontCollection = fontCollection;
}
return _embeddedFontCollection;
}
///
/// if the system does not support the user specified font name it will return null
///
public static FontFamily GetFontFamily(AdministrationEntity administration)
{
FontFamily result = null;
var fontFamilyName = administration.ReportFontFamily;
// First look in private/uploaded collection, then fall back to system font
if (!fontFamilyName.IsBlank())
{
var fontCollection = EmbeddedFontCollection();
result = fontCollection.Families.SingleOrDefault(f => f.Name.EqualsCaseInsensitiveTrim(fontFamilyName));
if (result == null &&
FontFamily.Families.Any(f => f.Name == fontFamilyName)) // check if the System Fonts has the user input name
result = new FontFamily(fontFamilyName);
}
return result;
}
}
}
In our reports:
In the constructor:
_overriddenFontFamily = PPPCustomFonts.GetFontFamily(fboLocation.Administration());
ApplyFontStyleFromReportSettings(sections: this.Sections);
///
/// a font specified in the report settings.
/// If the setting is blank, the default font is used.
///
// PPP-6725 Support japanese/chinese PDF reports via a setting
public void ApplyFontStyleFromReportSettings(SectionCollection sections)
{
foreach (Section section in sections)
{
foreach (ARControl control in section.Controls)
{
if (control is SubReport)
{
var activeReport = ((SubReport)control).Report;
if (activeReport != null)
ApplyFontStyleFromReportSettings(activeReport.Sections);
}
else
if (control is TextBox)
{
var textControl = (TextBox)control;
textControl.CanGrow = true;
if (_overriddenFontFamily != null)
textControl.Font = new Font(_overriddenFontFamily, textControl.Font.Size);
}
else
if (control is Label)
{
var labelControl = (Label)control;
labelControl.WordWrap = true;
if (_overriddenFontFamily != null)
labelControl.Font = new Font(_overriddenFontFamily, labelControl.Font.Size);
}
}
}
}