diff --git a/uk/ac/babraham/FastQC/Dialogs/FastQCTitlePanel.java b/uk/ac/babraham/FastQC/Dialogs/FastQCTitlePanel.java index dd0f6f2..4058342 100644 --- a/uk/ac/babraham/FastQC/Dialogs/FastQCTitlePanel.java +++ b/uk/ac/babraham/FastQC/Dialogs/FastQCTitlePanel.java @@ -41,6 +41,7 @@ import javax.swing.JTextField; import uk.ac.babraham.FastQC.FastQCApplication; +import uk.ac.babraham.FastQC.Utilities.FontManager; /** * The Class SeqMonkTitlePanel. @@ -132,20 +133,20 @@ public void mouseClicked(MouseEvent e) { constraints.fill = GridBagConstraints.NONE; JLabel program = new SmoothJLabel("FastQC High Throughput Sequence QC Report",JLabel.CENTER); - program.setFont(new Font("Dialog",Font.BOLD,18)); + program.setFont(FontManager.getFont(Font.BOLD, 18f)); program.setForeground(new Color(200,0,0)); c.add(program,constraints); constraints.gridy++; JLabel version = new SmoothJLabel("Version: "+FastQCApplication.VERSION, JLabel.CENTER); - version.setFont(new Font("Dialog",Font.BOLD,15)); + version.setFont(FontManager.getFont(Font.BOLD, 15f)); version.setForeground(new Color(0,0,200)); c.add(version,constraints); constraints.gridy++; // Use a text field so they can copy this JLabel website = new JLabel(" www.bioinformatics.babraham.ac.uk/projects/ "); - website.setFont(new Font("Dialog",Font.PLAIN,14)); + website.setFont(FontManager.getFont(Font.PLAIN, 14f)); website.setBorder(null); website.setOpaque(false); website.setHorizontalAlignment(JTextField.CENTER); @@ -153,27 +154,27 @@ public void mouseClicked(MouseEvent e) { constraints.gridy++; JLabel copyright = new JLabel("\u00a9 Simon Andrews, Pierre Lindenbaum, Brian Howard, Phil Ewels 2011-26,", JLabel.CENTER); - copyright.setFont(new Font("Dialog",Font.PLAIN,14)); + copyright.setFont(FontManager.getFont(Font.PLAIN, 14f)); c.add(copyright,constraints); constraints.gridy++; JLabel copyright2 = new JLabel("HTSJDK BAM/SAM reader v2.24.1 from Samtools 2022", JLabel.CENTER); - copyright2.setFont(new Font("Dialog",Font.PLAIN,10)); + copyright2.setFont(FontManager.getFont(Font.PLAIN, 10f)); c.add(copyright2,constraints); constraints.gridy++; JLabel copyright3 = new JLabel("BZip decompression \u00a9Matthew J. Francis, 2011", JLabel.CENTER); - copyright3.setFont(new Font("Dialog",Font.PLAIN,10)); + copyright3.setFont(FontManager.getFont(Font.PLAIN, 10f)); c.add(copyright3,constraints); constraints.gridy++; JLabel copyright4 = new JLabel("Base64 encoding \u00a9Robert Harder, 2012", JLabel.CENTER); - copyright4.setFont(new Font("Dialog",Font.PLAIN,10)); + copyright4.setFont(FontManager.getFont(Font.PLAIN, 10f)); c.add(copyright4,constraints); constraints.gridy++; JLabel copyright5 = new JLabel("Java HDF5 reader \u00a9ETH, CISD and SIS, 2007-14", JLabel.CENTER); - copyright5.setFont(new Font("Dialog",Font.PLAIN,10)); + copyright5.setFont(FontManager.getFont(Font.PLAIN, 10f)); c.add(copyright5,constraints); add(c,BorderLayout.CENTER); diff --git a/uk/ac/babraham/FastQC/Graphs/LineGraph.java b/uk/ac/babraham/FastQC/Graphs/LineGraph.java index 3e935ba..49eabfd 100644 --- a/uk/ac/babraham/FastQC/Graphs/LineGraph.java +++ b/uk/ac/babraham/FastQC/Graphs/LineGraph.java @@ -29,6 +29,8 @@ import javax.swing.JPanel; +import uk.ac.babraham.FastQC.Utilities.FontManager; + public class LineGraph extends JPanel { private String [] xTitles; @@ -105,7 +107,8 @@ public Dimension getMinimumSize () { public void paint (Graphics g) { super.paint(g); - + + g.setFont(FontManager.defaultFont()); g.setColor(Color.WHITE); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(Color.BLACK); @@ -138,8 +141,10 @@ public void paint (Graphics g) { xOffset += 5; // Draw the graph title + g.setFont(FontManager.defaultBoldFont()); int titleWidth = g.getFontMetrics().stringWidth(graphTitle); g.drawString(graphTitle, (xOffset + ((getWidth()-(xOffset+10))/2)) - (titleWidth/2), 30); + g.setFont(FontManager.defaultFont()); // Now draw the axes @@ -174,7 +179,7 @@ public void paint (Graphics g) { if (baseNumberPosition > lastXLabelEnd) { g.drawString(baseNumber,baseNumberPosition, getHeight()-25); - lastXLabelEnd = baseNumberPosition+baseNumberWidth+5; + lastXLabelEnd = baseNumberPosition+baseNumberWidth+g.getFontMetrics().getHeight()-2; } } @@ -209,7 +214,7 @@ public void paint (Graphics g) { // Now draw the data legend // Make the letters thicker for this so we can see the colours better - g.setFont(g.getFont().deriveFont(Font.BOLD)); + g.setFont(FontManager.defaultBoldFont()); if (g instanceof Graphics2D) { ((Graphics2D)g).setStroke(new BasicStroke(1)); @@ -241,7 +246,7 @@ public void paint (Graphics g) { // Put the font back how we found it - g.setFont(g.getFont().deriveFont(Font.PLAIN)); + g.setFont(FontManager.defaultFont()); } diff --git a/uk/ac/babraham/FastQC/Graphs/QualityBoxPlot.java b/uk/ac/babraham/FastQC/Graphs/QualityBoxPlot.java index bc8028d..c6554b4 100644 --- a/uk/ac/babraham/FastQC/Graphs/QualityBoxPlot.java +++ b/uk/ac/babraham/FastQC/Graphs/QualityBoxPlot.java @@ -24,6 +24,8 @@ import javax.swing.JPanel; +import uk.ac.babraham.FastQC.Utilities.FontManager; + public class QualityBoxPlot extends JPanel { private double [] means; @@ -64,7 +66,8 @@ public QualityBoxPlot (double [] means, double [] medians, double [] lowest, dou public void paint (Graphics g) { super.paint(g); - + + g.setFont(FontManager.defaultFont()); g.setColor(Color.WHITE); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(Color.BLACK); @@ -102,8 +105,10 @@ public void paint (Graphics g) { // Draw the graph title + g.setFont(FontManager.defaultBoldFont()); int titleWidth = g.getFontMetrics().stringWidth(graphTitle); g.drawString(graphTitle, (xOffset + ((getWidth()-(xOffset+10))/2)) - (titleWidth/2), 30); + g.setFont(FontManager.defaultFont()); @@ -149,7 +154,7 @@ public void paint (Graphics g) { if (labelStart > lastXLabelEnd) { g.drawString(xLabels[i], labelStart, getHeight()-25); - lastXLabelEnd = labelStart+g.getFontMetrics().stringWidth(xLabels[i])+5; + lastXLabelEnd = labelStart+baseNumberWidth+g.getFontMetrics().getHeight()-2; } } diff --git a/uk/ac/babraham/FastQC/Graphs/TileGraph.java b/uk/ac/babraham/FastQC/Graphs/TileGraph.java index fdf2bb5..c094f1f 100644 --- a/uk/ac/babraham/FastQC/Graphs/TileGraph.java +++ b/uk/ac/babraham/FastQC/Graphs/TileGraph.java @@ -29,6 +29,7 @@ import javax.swing.JPanel; import uk.ac.babraham.FastQC.Modules.ModuleConfig; +import uk.ac.babraham.FastQC.Utilities.FontManager; import uk.ac.babraham.FastQC.Utilities.HotColdColourGradient; public class TileGraph extends JPanel { @@ -54,6 +55,7 @@ private int getY(double y) { public void paint (Graphics g) { super.paint(g); + g.setFont(FontManager.defaultFont()); g.setColor(Color.WHITE); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(Color.BLACK); @@ -81,8 +83,10 @@ public void paint (Graphics g) { // Draw the graph title String graphTitle = "Quality per tile"; + g.setFont(FontManager.defaultBoldFont()); int titleWidth = g.getFontMetrics().stringWidth(graphTitle); g.drawString(graphTitle, (xOffset + ((getWidth()-(xOffset+10))/2)) - (titleWidth/2), 30); + g.setFont(FontManager.defaultFont()); // Now draw the axes @@ -115,7 +119,7 @@ public void paint (Graphics g) { if (baseNumberPosition > lastXLabelEnd) { g.drawString(baseNumber,baseNumberPosition, getHeight()-25); - lastXLabelEnd = baseNumberPosition+baseNumberWidth+5; + lastXLabelEnd = baseNumberPosition+baseNumberWidth+g.getFontMetrics().getHeight()-2; } } diff --git a/uk/ac/babraham/FastQC/Resources/Fonts/LICENSE b/uk/ac/babraham/FastQC/Resources/Fonts/LICENSE new file mode 100644 index 0000000..aba73e8 --- /dev/null +++ b/uk/ac/babraham/FastQC/Resources/Fonts/LICENSE @@ -0,0 +1,102 @@ +Digitized data copyright (c) 2010 Google Corporation + with Reserved Font Arimo, Tinos and Cousine. +Copyright (c) 2012 Red Hat, Inc. + with Reserved Font Name Liberation. + +This Font Software is licensed under the SIL Open Font License, +Version 1.1. + +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 + +PREAMBLE The goals of the Open Font License (OFL) are to stimulate +worldwide development of collaborative font projects, to support the font +creation efforts of academic and linguistic communities, and to provide +a free and open framework in which fonts may be shared and improved in +partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. +The fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply to +any document created using the fonts or their derivatives. + + + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. +This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components +as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting ? in part or in whole ? +any of the components of the Original Version, by changing formats or +by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer +or other person who contributed to the Font Software. + + +PERMISSION & CONDITIONS + +Permission is hereby granted, free of charge, to any person obtaining a +copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components,in + Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, + redistributed and/or sold with any software, provided that each copy + contains the above copyright notice and this license. These can be + included either as stand-alone text files, human-readable headers or + in the appropriate machine-readable metadata fields within text or + binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font + Name(s) unless explicit written permission is granted by the + corresponding Copyright Holder. This restriction only applies to the + primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font + Software shall not be used to promote, endorse or advertise any + Modified Version, except to acknowledge the contribution(s) of the + Copyright Holder(s) and the Author(s) or with their explicit written + permission. + +5) The Font Software, modified or unmodified, in part or in whole, must + be distributed entirely under this license, and must not be distributed + under any other license. The requirement for fonts to remain under + this license does not apply to any document created using the Font + Software. + + + +TERMINATION +This license becomes null and void if any of the above conditions are not met. + + + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER +DEALINGS IN THE FONT SOFTWARE. + diff --git a/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Bold.ttf b/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Bold.ttf new file mode 100644 index 0000000..dc5d57f Binary files /dev/null and b/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Bold.ttf differ diff --git a/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-BoldItalic.ttf b/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-BoldItalic.ttf new file mode 100644 index 0000000..158488a Binary files /dev/null and b/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-BoldItalic.ttf differ diff --git a/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Italic.ttf b/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Italic.ttf new file mode 100644 index 0000000..25970d9 Binary files /dev/null and b/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Italic.ttf differ diff --git a/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Regular.ttf b/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Regular.ttf new file mode 100644 index 0000000..e633985 Binary files /dev/null and b/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Regular.ttf differ diff --git a/uk/ac/babraham/FastQC/Utilities/FontManager.java b/uk/ac/babraham/FastQC/Utilities/FontManager.java new file mode 100644 index 0000000..bc3e316 --- /dev/null +++ b/uk/ac/babraham/FastQC/Utilities/FontManager.java @@ -0,0 +1,100 @@ +/** + * Copyright Copyright 2010-26 Simon Andrews + * + * This file is part of FastQC. + * + * FastQC is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * FastQC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FastQC; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package uk.ac.babraham.FastQC.Utilities; + +import java.awt.Font; +import java.awt.FontFormatException; +import java.awt.GraphicsEnvironment; +import java.io.IOException; +import java.io.InputStream; + +/** + * Manages the bundled Liberation Sans font so that FastQC renders + * consistently without requiring any system-installed fonts. + */ +public class FontManager { + + /** The font family name used in SVG output, with Arial fallback */ + public static final String SVG_FONT_FAMILY = "'Liberation Sans', Arial, Helvetica, sans-serif"; + + private static Font regularFont; + private static Font boldFont; + + private static Font cachedDefaultFont; + private static Font cachedDefaultBoldFont; + + private static boolean initialized = false; + + /** + * Load and register the bundled Liberation Sans font variants. + * Safe to call multiple times; only loads once. + */ + public static synchronized void initialize() { + if (initialized) return; + + regularFont = loadFont("/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Regular.ttf"); + boldFont = loadFont("/uk/ac/babraham/FastQC/Resources/Fonts/LiberationSans-Bold.ttf"); + + cachedDefaultFont = regularFont.deriveFont(12f); + cachedDefaultBoldFont = boldFont.deriveFont(12f); + + initialized = true; + } + + private static Font loadFont(String resourcePath) { + try (InputStream is = FontManager.class.getResourceAsStream(resourcePath)) { + if (is == null) { + System.err.println("Warning: bundled font not found: " + resourcePath); + return new Font(Font.SANS_SERIF, Font.PLAIN, 12); + } + Font font = Font.createFont(Font.TRUETYPE_FONT, is); + GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font); + return font; + } catch (FontFormatException | IOException e) { + System.err.println("Warning: failed to load bundled font: " + resourcePath + " (" + e.getMessage() + ")"); + return new Font(Font.SANS_SERIF, Font.PLAIN, 12); + } + } + + /** + * Get a font at the given size and style. + * + * @param style Font.PLAIN or Font.BOLD + * @param size point size + * @return the derived font + */ + public static Font getFont(int style, float size) { + initialize(); + Font base = (style == Font.BOLD) ? boldFont : regularFont; + return base.deriveFont(size); + } + + /** Default 12pt plain font for graph rendering */ + public static Font defaultFont() { + initialize(); + return cachedDefaultFont; + } + + /** Default 12pt bold font for graph rendering */ + public static Font defaultBoldFont() { + initialize(); + return cachedDefaultBoldFont; + } +} diff --git a/uk/ac/babraham/FastQC/Utilities/ImageSaver/SVGGenerator.java b/uk/ac/babraham/FastQC/Utilities/ImageSaver/SVGGenerator.java index 4f6cebf..5c26197 100644 --- a/uk/ac/babraham/FastQC/Utilities/ImageSaver/SVGGenerator.java +++ b/uk/ac/babraham/FastQC/Utilities/ImageSaver/SVGGenerator.java @@ -33,6 +33,8 @@ import javax.swing.RepaintManager; +import uk.ac.babraham.FastQC.Utilities.FontManager; + /** * SVGGenerator is an implementation of the Graphics interface which can be * passed to any paint method and will generate an SVG version of the display. @@ -167,7 +169,7 @@ private class SVGGraphics extends Graphics { private Color color = Color.BLACK; /** The font. */ - private Font font = new Font("Default",Font.PLAIN,12); + private Font font = FontManager.defaultFont(); /** @@ -344,7 +346,7 @@ public void drawString(String string, int x, int y) { sb.append(y); sb.append("\" fill=\"rgb("); appendColor(); - sb.append(")\" font-family=\"Arial\" font-size=\""); + sb.append(")\" font-family=\"" + FontManager.SVG_FONT_FAMILY + "\" font-size=\""); sb.append(font.getSize()); if (font.isBold()) { sb.append("\" font-weight=\"bold");