J'ai une application Silverlight que j'ai besoin d'intégrer certaines polices moins que communes. C'est assez simple pour que je puisse simplement copier sur le TTF / OTF et compiler avec mon application. Cependant, dans de nombreux cas, seuls 5-10 des caractères sont réellement utilisés. Dans d'autres cas, certains fichiers de polices sont incroyablement volumineux ( Arial Unicode MS System em> est de 22,1 Mo, à titre d'exemple). Les heures de téléchargement rapide de mon application sont vraiment importantes, afin d'optimiser les polices utilisées est primordiale. P>
Alors, ce que je pensais, c'est que j'ai vu dans des applications telles que l'expression mélangeur où un Je ne cherche pas de solution de contournement sournoise, comme l'exportation vers un fichier XPS et saisir le fichier .odtff. P>
Y a-t-il une manière programmatique (.NET / GDI +) pour créer un sous-ensemble d'une police avec seulement certains caractères et le compiler à un .ttf / .otf? En outre, cela aurait également besoin de fonctionner pour des fichiers .TTC. P>
5 Réponses :
L'API Native Createefontpackage peut être quoi vous cherchez. Vous pouvez transmettre une TTF et une liste de caractères à conserver. Si vous passez Voici un thread avec ce qui semble être le code d'un exemple de travail (en C , malheureusement). P> ttfcfp_subset code> pour
USSubsetFormat code>, vous récupérerez ensuite un TTF de travail avec uniquement ces caractères. P>
C'est intéressant, merci pour le lien. Espérait que quelque chose serait dans .NET, ou au moins un exemple d'utilisation de cela de .NET.
@Otaku: Ce message A > A le code P / invoke nécessaire (voir Second Post) pour utiliser l'API dans .NET.
dans WPF pour les polices Il existe une liaison statique et dynamique. Tout peut être défini dans le mélange. Avec une liaison statique des polices, seuls les caractères nécessaires sont compilés et intégrés dans votre assemblée. Avec une liaison dynamique, tout le jeu de polices est intégré. Ainsi, essayez de définir une liaison statique pour les polices sélectionnées et essayez si cela fonctionne si cela fonctionne.
Essayez d'ajouter le code suivant dans votre .csproj code> déposer. Ici, nous incluons les polices de Tahoma. La propriété Autofill définie sur True dit que nous allons intégrer à l'assemblage uniquement des caractères de nos commandes. L'ensemble des caractères dans
<ItemGroup>
<BlendEmbeddedFont Include="Fonts\tahoma.ttf">
<IsSystemFont>True</IsSystemFont>
<All>False</All>
<AutoFill>True</AutoFill>
<Characters>dasf</Characters>
<Uppercase>False</Uppercase>
<Lowercase>False</Lowercase>
<Numbers>False</Numbers>
<Punctuation>False</Punctuation>
</BlendEmbeddedFont>
<BlendEmbeddedFont Include="Fonts\tahomabd.ttf">
<IsSystemFont>True</IsSystemFont>
<All>False</All>
<AutoFill>True</AutoFill>
<Characters>dasf</Characters>
<Uppercase>False</Uppercase>
<Lowercase>False</Lowercase>
<Numbers>False</Numbers>
<Punctuation>False</Punctuation>
</BlendEmbeddedFont>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\Expression\Blend\3.0\WPF\Microsoft.Expression.Blend.WPF.targets" />
J'ai regardé msdn.microsoft.com/en-us/library/ms753303.aspx et cela indique spécifiquement que WPF n'a pas la possibilité de créer des polices de sous-ensemble. Je n'utilise pas non plus de mélange du tout pour cela, alors je cherche un moyen de le faire de manière programmatique .NET.
Voir la mise à jour. Si vous n'utilisez pas Mélange, cela peut vous aider (j'espère).
Cela semble vraiment i> prometteur - en fait, si je pouvais le faire fonctionner, ce serait exactement ce dont j'ai besoin. Cette page donne un échantillon: codeProject.com/kb/silverlight/newindianduppesyMBoldemo.aspx. L'échantillon fonctionne, mais quand j'essaie de le faire seul dans un projet séparé, il échoue. Je ne reçois pas un
Essayez d'installer MS Expression Blend au moins une version d'essai afin que cette extension apparaisse.
Ouais, j'ai essayé ça. Pas de chance. Avez-vous BlendembeddedFont B> dans la construction de l'action lors de l'ajout d'une police?
Non, je n'ai pas sur ma machine à domicile, seulement au travail (j'ai installé Blend 3.0). Vous devriez regarder vers
Oui, je vais me jouer avec elle pour voir si je peux le faire travailler.
Quel environnement avez-vous sur votre machine, je veux dire versions de VS, SL et Mélange?
Gagnez XP, VS2008 W / SP1, SL3, SL 3 SDK, Expressions Mélange 3 (essai)
Enfin, ça va travailler - belle! Remarque: Les expressions Blend ne sont pas nécessaires - juste le mélange 3.0 ou 4.0 SDK (gratuit) fonctionnera.
Super! Je suis content pour toi! Merci de note.
Fontforge ( http://fontforge.sourceforge.net/ ) est un éditeur de polices open source qui Permet des conversions de format automatisées. On dirait que c'est seulement python mais cela peut valoir la peine de vérifier. P>
Cela a une API pour la création de sous-ensembles de polices?
Modification de la réponse acceptée à celle-ci, car elle est pure .Net sans références externes. Utilise .NET 4.0:
Imports System.Windows.Media Imports System.Text.Encoding Imports System.Collections Public Sub CreateSubSet(sourceText As String, fontURI As Uri) Dim gt As FontEmbeddingManager = New FontEmbeddingManager Dim glyphTypeface As GlyphTypeface = New GlyphTypeface(fontURI) Dim Index As Generic.ICollection(Of UShort) Index = New Generic.List(Of UShort) Dim sourceTextBytes As Byte() = Unicode.GetBytes(sourceText) Dim sourceTextChars As Char() = Unicode.GetChars(sourceTextBytes) Dim sourceTextCharVal As Integer Dim glyphIndex As Integer For sourceTextCharPos = 0 To UBound(sourceTextChars) sourceTextCharVal = AscW(sourceTextChars(sourceTextCharPos)) glyphIndex = glyphTypeface.CharacterToGlyphMap(sourceTextCharVal) Index.Add(glyphIndex) Next Dim filebytes() As Byte = glyphTypeface.ComputeSubset(Index) Using fileStream As New System.IO.FileStream("C:\Users\Me\new-subset.ttf", System.IO.FileMode.Create) fileStream.Write(filebytes, 0, filebytes.Length) End Using End Sub
Je me demandais à quel point la Déclaration de GT sert-t-elle? Il n'est pas utilisé après que cela a été déclaré ...
@Brianthomas, ouais, désolé pour ça, c'était un artefact de plus de code. Ce n'est pas utilisé dans cet exemple. N'hésitez pas à éditer le code.
Je sais que c'est une vieille question, mais j'ai trouvé très difficile d'utiliser le Je suis Utilisation de l'API avec les glyphindices, vous pouvez l'utiliser directement avec les caractères en supprimant le drapeau Ceci est mon code: P> Createefontpackage Code> API de C # (comme indiqué par la réponse de @ Josh3736), donc je pensais partager mon code.
ttfcfp_flags_glyphlist code>. p>
public byte[] CreateSubset(byte[] inputData, IEnumerable<ushort> glyphIndices)
{
AllocProc allocProc = Marshal.AllocHGlobal;
ReallocProc reallocProc = (p, c) =>
p == IntPtr.Zero
? Marshal.AllocHGlobal(c)
: Marshal.ReAllocHGlobal(p, c);
FreeProc freeProc = Marshal.FreeHGlobal;
var resultCode = CreateFontPackage(
inputData, (uint) inputData.Length,
out var bufferPtr,
out _,
out var bytesWritten,
TTFCFP_FLAGS_SUBSET | TTFCFP_FLAGS_GLYPHLIST,
0,
TTFMFP_SUBSET,
0,
TTFCFP_MS_PLATFORMID,
TTFCFP_UNICODE_CHAR_SET,
glyphIndices,
(ushort)glyphIndices.Length,
allocProc, reallocProc, freeProc, (IntPtr)0);
if (resultCode != 0 || bufferPtr == IntPtr.Zero)
{
return null;
}
try
{
var buffer = new byte[bytesWritten];
Marshal.Copy(bufferPtr, buffer, 0, buffer.Length);
return buffer;
}
finally
{
freeProc(bufferPtr);
}
}
internal const ushort TTFCFP_FLAGS_SUBSET = 0x0001;
internal const ushort TTFCFP_FLAGS_COMPRESS = 0x0002;
internal const ushort TTFCFP_FLAGS_TTC = 0x0004;
internal const ushort TTFCFP_FLAGS_GLYPHLIST = 0x0008;
internal const ushort TTFMFP_SUBSET = 0x0000;
internal const ushort TTFCFP_UNICODE_PLATFORMID = 0x0000;
internal const ushort TTFCFP_MS_PLATFORMID = 0x0003;
internal const ushort TTFCFP_UNICODE_CHAR_SET = 0x0001;
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private delegate IntPtr AllocProc(Int32 size);
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private delegate IntPtr ReallocProc(IntPtr memBlock, IntPtr size);
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private delegate void FreeProc(IntPtr memBlock);
[DllImport("FontSub.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]
private static extern uint CreateFontPackage(
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
byte[] puchSrcBuffer,
uint ulSrcBufferSize,
out IntPtr puchFontPackageBufferPtr,
out uint pulFontPackageBufferSize,
out uint pulBytesWritten,
ushort usFlags,
ushort usTtcIndex,
ushort usSubsetFormat,
ushort usSubsetLanguage,
ushort usSubsetPlatform,
ushort usSubsetEncoding,
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 12)]
ushort[] pusSubsetKeepList,
ushort usSubsetKeepListCount,
AllocProc lpfnAllocate,
ReallocProc lpfnReAllocate,
FreeProc lpfnFree,
IntPtr lpvReserved
);