Встраивание шрифтов в презентации на Android
Введение
Встраивание шрифтов сохраняет данные шрифта внутри презентации PowerPoint. Когда просмоторщик поддерживает встроенные шрифты, он может отображать текст с использованием этих шрифтов, даже если они не установлены в целевой системе. Это помогает сохранять разрывы строк, межбуквенные интервалы и макет слайдов.
Aspose.Slides for Android via Java позволяет получать, добавлять и удалять встроенные шрифты через интерфейс IFontsManager , возвращаемый Presentation.getFontsManager. Вы также можете уменьшить размер данных встроенного шрифта, удалив символы, которые не используются в презентации.
Приведённые ниже примеры работают с файлами PPTX. Перед встраиванием шрифта убедитесь, что его данные доступны Aspose.Slides и его лицензия разрешает встраивание.
Получение и удаление встроенных шрифтов
Используйте getEmbeddedFonts чтобы вывести список шрифтов, хранящихся в презентации. Чтобы удалить один, передайте шрифт из этого списка в removeEmbeddedFont, затем сохраните презентацию.
Следующий пример выводит список встроенных шрифтов в EmbeddedFonts.pptx и удаляет Calibri, если он присутствует:
import com.aspose.slides.IFontData;
import com.aspose.slides.IFontsManager;
import com.aspose.slides.Presentation;
import com.aspose.slides.SaveFormat;
Presentation presentation = new Presentation("EmbeddedFonts.pptx");
try {
IFontsManager fontsManager = presentation.getFontsManager();
IFontData[] embeddedFonts = fontsManager.getEmbeddedFonts();
for (IFontData font : embeddedFonts) {
System.out.println(font.getFontName());
}
IFontData fontToRemove = null;
for (IFontData font : embeddedFonts) {
if ("Calibri".equalsIgnoreCase(font.getFontName())) {
fontToRemove = font;
break;
}
}
if (fontToRemove != null) {
fontsManager.removeEmbeddedFont(fontToRemove);
presentation.save("WithoutEmbeddedCalibri.pptx", SaveFormat.Pptx);
} else {
System.out.println("Calibri is not embedded. No output file was created.");
}
} finally {
presentation.dispose();
}
Удаление встроенного шрифта удаляет его хранимые данные шрифта; это не изменяет шрифт, присвоенный тексту. Если шрифт установлен в целевой системе, текст всё равно может его использовать. В противном случае при рендеринге может потребоваться font substitution, что может повлиять на макет.
Проверка данных шрифта и прав на встраивание
Используйте интерфейс IFontsManager , чтобы проверить шрифты перед их встраиванием. Вызовите IFontsManager.getFonts , чтобы получить шрифты, используемые в презентации. Для каждого шрифта передайте объект IFontData и требуемое значение FontStyleType , в метод IFontsManager.getFontBytes. Метод возвращает бинарные данные для данного стиля шрифта или null, если запрашиваемый шрифт или стиль недоступны. Не передавайте результат null в IFontsManager.getFontEmbeddingLevel, так как этот метод требует массив байтов.
EmbeddingLevel — это перечисление флагов, которое сообщает о ограничениях встраивания, хранящихся в шрифте:
Installableразрешает встраивание и постоянную установку на другой системе, при условии соблюдения лицензии шрифта.Restrictedзапрещает встраивание, если только не получено разрешение от законного владельца шрифта, когда он является единственным флагом разрешения использования.PreviewPrintразрешает временное использование для просмотра и печати; документ, содержащий шрифт, должен быть только для чтения.Editableразрешает временное использование и позволяет документу быть отредактированным и сохранённым.NoSubsetting— дополнительное ограничение, запрещающее встраивание только подмножества глифов. При наличии этого флага необходимо встраивать все символы.BitmapOnly— дополнительное ограничение, позволяющее встраивать только растровые варианты шрифта, а не данные контура. Если у шрифта нет растровых вариантов, его нельзя встраивать.
Первые четыре значения описывают разрешение на использование, тогда как NoSubsetting и BitmapOnly могут комбинироваться с ними. Проверяйте модификаторы с помощью побитовых операций. Поскольку Installable равно нулю, маскируйте биты разрешения на использование и сравнивайте результат с Installable, а не проверяйте его как флаг. Текущие шрифты должны устанавливать не более одного бита разрешения. Для совместимости со старыми шрифтами, которые устанавливают более одного, вспомогательная функция ниже выбирает наименее ограничительное разрешение: Editable, затем PreviewPrint, затем Restricted.
Следующий пример проверяет обычные, полужирные, курсивные и полужирно‑курсивные данные, доступные для каждого шрифта, возвращённого getFonts. Он пропускает недоступные стили, ограниченные шрифты, шрифты только в виде битмапов, шрифты, ограниченные предварительным просмотром и печатью, поскольку вывод остаётся редактируемым, а также шрифты, уже встроенные. Если любой доступный стиль имеет NoSubsetting, то встраиваются все символы для этой семейства шрифтов.
import com.aspose.slides.EmbedFontCharacters;
import com.aspose.slides.EmbeddingLevel;
import com.aspose.slides.FontStyleType;
import com.aspose.slides.IFontData;
import com.aspose.slides.IFontsManager;
import com.aspose.slides.Presentation;
import com.aspose.slides.SaveFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
class EmbeddingPermission {
int getUsagePermission(int level) {
int permissionMask = EmbeddingLevel.Restricted | EmbeddingLevel.PreviewPrint | EmbeddingLevel.Editable;
int permissions = level & permissionMask;
if ((permissions & EmbeddingLevel.Editable) != 0) {
return EmbeddingLevel.Editable;
}
if ((permissions & EmbeddingLevel.PreviewPrint) != 0) {
return EmbeddingLevel.PreviewPrint;
}
if ((permissions & EmbeddingLevel.Restricted) != 0) {
return EmbeddingLevel.Restricted;
}
return EmbeddingLevel.Installable;
}
}
Presentation presentation = new Presentation("Fonts.pptx");
try {
IFontsManager fontsManager = presentation.getFontsManager();
int[] fontStyles = {
FontStyleType.Regular,
FontStyleType.Bold,
FontStyleType.Italic,
FontStyleType.Bold | FontStyleType.Italic
};
Set<String> embeddedFontNames = new HashSet<String>();
for (IFontData embeddedFont : fontsManager.getEmbeddedFonts()) {
embeddedFontNames.add(embeddedFont.getFontName().toLowerCase(Locale.ROOT));
}
EmbeddingPermission permissionHelper = new EmbeddingPermission();
List<IFontData> fontsToEmbed = new ArrayList<IFontData>();
List<Integer> embeddingRules = new ArrayList<Integer>();
for (IFontData font : fontsManager.getFonts()) {
if (embeddedFontNames.contains(font.getFontName().toLowerCase(Locale.ROOT))) {
System.out.println(font.getFontName() + ": already embedded.");
continue;
}
boolean hasAvailableData = false;
boolean allAvailableStylesCanBeEmbedded = true;
boolean previewPrintOnly = false;
boolean requiresFullFont = false;
for (int fontStyle : fontStyles) {
byte[] fontBytes = fontsManager.getFontBytes(font, fontStyle);
if (fontBytes == null) {
System.out.println(font.getFontName() + " (" + fontStyle + "): font data is unavailable.");
continue;
}
hasAvailableData = true;
int embeddingLevel = fontsManager.getFontEmbeddingLevel(fontBytes, font.getFontName());
int usagePermission = permissionHelper.getUsagePermission(embeddingLevel);
boolean noSubsetting = (embeddingLevel & EmbeddingLevel.NoSubsetting) != 0;
boolean bitmapOnly = (embeddingLevel & EmbeddingLevel.BitmapOnly) != 0;
requiresFullFont |= noSubsetting;
previewPrintOnly |= usagePermission == EmbeddingLevel.PreviewPrint;
allAvailableStylesCanBeEmbedded &= usagePermission != EmbeddingLevel.Restricted && !bitmapOnly;
System.out.println(font.getFontName() + " (" + fontStyle + "): " + embeddingLevel + ".");
}
if (!hasAvailableData) {
System.out.println(font.getFontName() + ": skipped because no requested style is available.");
} else if (!allAvailableStylesCanBeEmbedded) {
System.out.println(font.getFontName() + ": skipped because at least one available style does not permit outline embedding.");
} else if (previewPrintOnly) {
System.out.println(font.getFontName() + ": skipped because this example produces an editable presentation.");
} else {
int rule = requiresFullFont ? EmbedFontCharacters.All : EmbedFontCharacters.OnlyUsed;
fontsToEmbed.add(font);
embeddingRules.add(rule);
}
}
for (int i = 0; i < fontsToEmbed.size(); i++) {
fontsManager.addEmbeddedFont(fontsToEmbed.get(i), embeddingRules.get(i));
}
presentation.save("WithAuditedFonts.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Эта проверка сообщает об ограничениях, закодированных в каждом файле шрифта. Она не предоставляет лицензию, не доказывает, что вы законно получили шрифт, и не заменяет проверку лицензионного соглашения шрифта перед распространением встроенной копии.
Добавление встроенных шрифтов
Используйте addEmbeddedFont , чтобы встроить шрифт. Его перегрузки принимают либо объект IFontData , либо массив байтов, содержащий данные шрифта. Перечисление EmbedFontCharacters определяет, какие символы включаются:
- All встраивает все символы шрифта. Используйте эту опцию, когда получателям необходимо редактировать презентацию и вводить новый текст.
- OnlyUsed встраивает только символы, использованные в презентации, чтобы уменьшить размер файла. Выбирайте эту опцию для готовой презентации, предназначенной в основном для просмотра.
Следующий пример использует getFonts , чтобы получить шрифты, используемые в Fonts.pptx, и встраивает те, которые ещё не встроены. Шрифты для добавления должны быть доступны на устройстве Android или зарегистрированы в Aspose.Slides. Существующие встроенные шрифты сохраняют свои текущие наборы символов.
import com.aspose.slides.EmbedFontCharacters;
import com.aspose.slides.IFontData;
import com.aspose.slides.IFontsManager;
import com.aspose.slides.Presentation;
import com.aspose.slides.SaveFormat;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
Presentation presentation = new Presentation("Fonts.pptx");
try {
IFontsManager fontsManager = presentation.getFontsManager();
IFontData[] allFonts = fontsManager.getFonts();
IFontData[] embeddedFonts = fontsManager.getEmbeddedFonts();
Set<String> embeddedFontNames = new HashSet<String>();
for (IFontData embeddedFont : embeddedFonts) {
embeddedFontNames.add(embeddedFont.getFontName().toLowerCase(Locale.ROOT));
}
for (IFontData font : allFonts) {
String fontName = font.getFontName().toLowerCase(Locale.ROOT);
if (!embeddedFontNames.contains(fontName)) {
fontsManager.addEmbeddedFont(font, EmbedFontCharacters.All);
embeddedFontNames.add(fontName);
}
}
presentation.save("WithEmbeddedFonts.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Сжатие встроенных шрифтов
Compress.compressEmbeddedFonts уменьшает данные встроенного шрифта, удаляя неиспользуемые символы. Он работает с уже встроенными шрифтами, поэтому степень уменьшения размера зависит от того, сколько неиспользуемых данных шрифта содержится в презентации.
Следующий пример сжимает шрифты в EmbeddedFonts.pptx и сохраняет результат в отдельный файл:
import com.aspose.slides.Compress;
import com.aspose.slides.Presentation;
import com.aspose.slides.SaveFormat;
Presentation presentation = new Presentation("EmbeddedFonts.pptx");
try {
Compress.compressEmbeddedFonts(presentation);
presentation.save("CompressedEmbeddedFonts.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Сохраняйте оригинальный файл, если получателям может понадобиться добавить текст позже. Символы, удалённые во время сжатия, более недоступны из встроенного шрифта, даже если изначально вы встроили все символы.
Вопросы и ответы
Как проверить, будет ли встроенный шрифт всё ещё заменяться при рендеринге?
Вызовите getSubstitutions , в среде, где вы рендерите презентацию, чтобы увидеть, какие шрифты Aspose.Slides заменит. Также проверьте настройки font substitution и правила font fallback. Fallback обрабатывает отсутствующие символы, поэтому встраивание шрифта не решает проблему символов, которых нет в самом шрифте.
Стоит ли встраивать распространённые шрифты, такие как Arial и Calibri?
Решение следует принимать, исходя из целевой среды. Если требуемые шрифты доступны на каждом устройстве, открывающем или рендерящем презентацию, их встраивание может добавить ненужный размер файла. Если у получателей или серверов могут отсутствовать эти шрифты, их встраивание поможет сохранить задуманное отображение, при условии, что их лицензии позволяют это.