package net.bible.service.font; import net.bible.android.SharedConstants; import net.bible.service.common.CommonUtils; import net.bible.service.common.Logger; import net.bible.service.download.GenericFileDownloader; import org.apache.commons.lang3.StringUtils; import org.crosswire.jsword.book.Book; import org.crosswire.jsword.book.install.InstallException; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.util.Properties; /** * @author Martin Denham [mjdenham at gmail dot com] * @see gnu.lgpl.License for license details.<br> * The copyright to this program is held by it's author. */ public class FontControl { private Properties fontProperties = new Properties(); private static final String FONT_DOWNLOAD_URL = "http://www.crosswire.org/and-bible/fonts/v1/"; private static String FONT_PROPERTIES_FILENAME = "fonts.properties"; private static String FONT_SIZE_ADJUSTMENT = ".fontSizeAdjustment"; private static String CSS_CLASS = ".cssClass"; private static FontControl SINGLETON = new FontControl(); private static final Logger log = new Logger(FontControl.class.getName()); private FontControl() { loadFontProperties(); } public void reloadProperties() { loadFontProperties(); } public static FontControl getInstance() { return SINGLETON; } public String getFontForBook(Book book) { String font = null; try { if (book!=null) { // sometimes an error occurs on following line - maybe due to missing language info in book metadata String langCode = book.getBookMetaData().getLanguage().getCode(); // is there a font for the book final String abbreviation = book.getAbbreviation(); font = fontProperties.getProperty(abbreviation); // is there a font for the language code if (StringUtils.isEmpty(font)) { font = fontProperties.getProperty(langCode); } log.debug("Book:" + abbreviation + " Language code:" + langCode + " Font:" + font); } } catch (Exception e) { // sometimes get here if a book has no initials - so do not attempt to print a books initials in the error log.warn("Problem getting font for book", e); } return font; } /** SBLGNT is a bit small so font size needs to be adjusted up, but the same method can be used for other fonts * adding * fontname.fontSizeAdjustment=2 * will increase the size when fontname is used */ public int getFontSizeAdjustment(String font, Book book) { int sizeAdjustment = 0; try { if (!StringUtils.isEmpty(font)) { // only modify font size if font is for whole page otherwise some characters are different sizes which looks odd if (StringUtils.isEmpty(getCssClassForCustomFont(book))) { String sizeAdjustmentString = fontProperties.getProperty(font+FONT_SIZE_ADJUSTMENT, "0"); sizeAdjustment = Integer.parseInt(sizeAdjustmentString); } } } catch (Exception e) { log.error("Error getting font size adjustment", e); } return sizeAdjustment; } public String getCssClassForCustomFont(Book book) { return fontProperties.getProperty(book.getAbbreviation()+CSS_CLASS, ""); } public boolean exists(String font) { return new File(SharedConstants.FONT_DIR, font).exists() || new File(SharedConstants.MANUAL_FONT_DIR, font).exists(); } public String getHtmlFontStyle(String font, String cssClass) { String fontStyle = ""; if (!StringUtils.isEmpty(font)) { if (StringUtils.isEmpty(cssClass)) { cssClass = "body"; } File fontFile = getFontFile(font); if (fontFile!=null && fontFile.exists()) { fontStyle = "<style>@font-face {font-family: 'CustomFont';src: url('"+getFontFile(font).toURI()+"'); font-weight:normal; font-style:normal; font-variant:normal;} "+ cssClass+" {font-family: 'CustomFont', 'Droid Sans';}</style>"; // if range specified the default font also changes e.g. unicode-range:U+0370-03FF,U+1F00-1FFE; } else { log.error("Font not found:"+font); } } return fontStyle; } public void downloadFont(String font) throws InstallException { log.debug("Download font "+font); URI source; try { source = new URI(FONT_DOWNLOAD_URL+font); } catch (URISyntaxException use) { log.error("Invalid URI", use); throw new InstallException("Error downloading font"); } File target = new File(SharedConstants.FONT_DIR, font); GenericFileDownloader downloader = new GenericFileDownloader(); downloader.downloadFileInBackground(source, target, "font"); } /** if font.properties refresh requested or does not exist then download font.properties */ public void checkFontPropertiesFile(boolean refresh) throws InstallException { if (refresh || !(new File(SharedConstants.FONT_DIR, FONT_PROPERTIES_FILENAME).exists())) { log.debug("Downloading "+FONT_PROPERTIES_FILENAME); URI source; try { source = new URI(FONT_DOWNLOAD_URL+FONT_PROPERTIES_FILENAME); } catch (URISyntaxException use) { log.error("Invalid URI", use); throw new InstallException("Error downloading font"); } File target = new File(SharedConstants.FONT_DIR, FONT_PROPERTIES_FILENAME); GenericFileDownloader downloader = new GenericFileDownloader(); downloader.downloadFile(source, target, "font definitions"); // now need to reload properties after new file fetched loadFontProperties(); } } private void loadFontProperties() { fontProperties.clear(); // load font properties from default install dir File fontPropFile = new File(SharedConstants.FONT_DIR, FONT_PROPERTIES_FILENAME); fontProperties.putAll(CommonUtils.loadProperties(fontPropFile)); // load font properties from manual install dir fontPropFile = new File(SharedConstants.MANUAL_FONT_DIR, FONT_PROPERTIES_FILENAME); fontProperties.putAll(CommonUtils.loadProperties(fontPropFile)); } /** find font in manual or default font dir */ public File getFontFile(String font) { File retVal = null; File autoFont = new File(SharedConstants.FONT_DIR, font); if (autoFont.exists()) { retVal = autoFont; } else { File manualFont = new File(SharedConstants.MANUAL_FONT_DIR, font); if (manualFont.exists()) { retVal = manualFont; } else { log.error("Font not found:"+font); } } return retVal; } }