Commit c12f7ebd authored by Drahomír Karchňák's avatar Drahomír Karchňák

Merge branch 'feature-image-export' into devel

parents 8c477081 eb8aee93
......@@ -258,19 +258,9 @@ def getVersionNameFromGit() {
}
def branchName = getBranchNameFromGit()
return stdoutVersion.toString().trim() + '-' + branchName
}
def getVersionCodeFromGit() {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-list', 'HEAD', '--count'
standardOutput = stdout
}
return stdout.toString().trim().toInteger()
}
def getBranchNameFromGit() {
def stdout = new ByteArrayOutputStream()
exec {
......@@ -281,6 +271,16 @@ def getBranchNameFromGit() {
return branchString.contains("/") ? branchString.substring(branchString.lastIndexOf("/") + 1) : branchString
}
def getVersionCodeFromGit() {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-list', 'HEAD', '--count'
standardOutput = stdout
}
return stdout.toString().trim().toInteger()
}
task wrapper(type: Wrapper) {
gradleVersion = '2.4'
}
package at.alladin.rmbt.statisticServer.export;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.text.FieldPosition;
import java.text.Format;
import java.util.Locale;
import javax.imageio.ImageIO;
import at.alladin.rmbt.shared.SignificantFormat;
public abstract class AbstractImageGenerator {
private static final String TEMPLATES_PATH = "templates/";
private static final String FONT_PATH = "fonts/";
private static final String FALLBACK_FONT_NAME = "Droid Sans";
/**
* Generates a image for showing the user its speed test result
* @param lang: Language of the image, currently either 'de' or 'en'
* @param upload: Upload speed in mbps
* @param download: Download speed in mbps
* @param ping: Ping in ms
* @param isp: ISP name
* @param typ: Test type (LAN, 3G, 4G, etc.)
* @param signal: Signal strength in dbm
* @param os: Plattform used for conducting the test (Android, IOS, Applet, Browser)
* @return rendered image
*/
public abstract BufferedImage generateImage(
String lang,
double upload,
double download,
double ping,
String isp,
String typ,
String signal,
String os,
String formattedTime,
String formattedDate
) throws IOException;
protected BufferedImage loadTemplateImage(String name) throws IOException {
return ImageIO.read(super.getClass().getResourceAsStream(TEMPLATES_PATH + name));
}
protected Font loadFont(String name) {
try {
InputStream fontInputStream = super.getClass().getResourceAsStream(FONT_PATH + name);
return Font.createFont(Font.TRUETYPE_FONT, fontInputStream);
} catch (FontFormatException | IOException e) {
e.printStackTrace();
System.out.println("Couldn't load font w/ name: " + name + ". Using fallback font!");
return new Font(FALLBACK_FONT_NAME, Font.PLAIN, 1);
}
}
/**
* Formats a number to 2 significant digits
* @param number the number
* @return the formatted number
*/
protected String formatNumber(double number, String lang) {
final Locale locale = new Locale(lang);
final Format format = new SignificantFormat(2, locale);
final StringBuffer buf = format.format(number, new StringBuffer(), new FieldPosition(0));
return buf.toString();
}
protected void drawCenteredString(String s, int x, int y, int w, int h, Graphics g) {
FontMetrics fm = g.getFontMetrics();
x += (w - fm.stringWidth(s)) / 2;
y += (fm.getAscent() + (h - (fm.getAscent() + fm.getDescent())) / 2);
g.drawString(s, x, y);
}
}
package at.alladin.rmbt.statisticServer.export;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class ForumBannerGenerator extends AbstractImageGenerator {
private static final int BANNER_WIDTH = 560;
private static final int BANNER_HEIGHT = 274;
private static final String UTC_FORMAT = "%s UTC";
private static final String TEMPLATE_FORMAT = "forumbanner_%s.png";
private static final String PRIMARY_FONT = "Roboto-Light.ttf";
private static final String SECONDARY_FONT = "Roboto-Medium.ttf";
private Font primaryFont = null;
private Font secondaryFont = null;
private enum UnknownValueMapping {
EN("en", "Unknown"),
CS("cs", "Neznamé"),
DE("de", "Unbekannt");
private static final String FALLBACK = "n/a";
private final String lang;
private final String unknownValue;
UnknownValueMapping(String lang, String unknownValue) {
this.lang = lang;
this.unknownValue = unknownValue;
}
protected static String getUnknownValue(String lang) {
for(UnknownValueMapping item : values()) {
if(item.lang.equals(lang)) return item.unknownValue;
}
return FALLBACK;
}
}
private enum AdditionalValuePositionMapping {
EN("en", 151, 432),
CS("cs", 130, 394),
DE("de", 128, 398);
private static final AdditionalValuePositionMapping FALLBACK = AdditionalValuePositionMapping.EN;
private final String lang;
private final int firstColumnX, secondColumnX;
AdditionalValuePositionMapping(String lang, int firstColumnX, int secondColumnX) {
this.lang = lang;
this.firstColumnX = firstColumnX;
this.secondColumnX = secondColumnX;
}
protected static int getFirstColumnX(String lang) {
for(AdditionalValuePositionMapping item : values()) {
if(item.lang.equals(lang)) return item.firstColumnX;
}
return FALLBACK.firstColumnX;
}
protected static int getSecondColumnX(String lang) {
for(AdditionalValuePositionMapping item : values()) {
if(item.lang.equals(lang)) return item.secondColumnX;
}
return FALLBACK.secondColumnX;
}
}
@Override
public BufferedImage generateImage(String lang, double upload, double download, double ping, String isp, String typ, String signal, String os, String formattedTime, String formattedDate) throws IOException {
//Initial setup of final image
BufferedImage finalImage = new BufferedImage(BANNER_WIDTH, BANNER_HEIGHT, BufferedImage.TYPE_INT_RGB);
Graphics2D finalImageGraphics = finalImage.createGraphics();
finalImageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
prepareFonts();
renderTemplate(lang, finalImageGraphics);
String downloadValue = formatNumber(download, lang);
String uploadValue = formatNumber(upload, lang);
String pingValue = formatNumber(ping, lang);
int optimalFontSize = getOptimalFontSize(
new String[] {downloadValue, uploadValue, pingValue},
new int[] {80, 74, 66, 60, 54, 48, 42, 36, 30, 24},
167,
primaryFont,
finalImageGraphics
);
if(optimalFontSize == -1) {
//At this point something went horribly wrong. Our values wont fit in the image even on the smallest size.
//We should probably give up on life at this point.
//TODO - Error handling?
System.out.println(ForumBannerGenerator.class + " Couldn't find optimal font size!");
optimalFontSize = 1; //Why not?
}
renderMainValue(downloadValue, 93, 118, optimalFontSize, finalImageGraphics);
renderMainValue(uploadValue, 280, 118, optimalFontSize, finalImageGraphics);
renderMainValue(pingValue, 469, 118, optimalFontSize, finalImageGraphics);
String unknownText = UnknownValueMapping.getUnknownValue(lang);
renderAdditionalValue(isp, unknownText, AdditionalValuePositionMapping.getFirstColumnX(lang), 219, finalImageGraphics);
renderAdditionalValue(typ, unknownText, AdditionalValuePositionMapping.getFirstColumnX(lang), 254, finalImageGraphics);
renderAdditionalValue(signal, unknownText, AdditionalValuePositionMapping.getSecondColumnX(lang), 219, finalImageGraphics);
renderAdditionalValue(os, unknownText, AdditionalValuePositionMapping.getSecondColumnX(lang), 254, finalImageGraphics);
renderTimeDateValue(formattedDate, unknownText, 550, 16, finalImageGraphics);
renderTimeDateValue(String.format(UTC_FORMAT, formattedTime), unknownText, 550, 40, finalImageGraphics);
return finalImage;
}
private void prepareFonts() {
primaryFont = loadFont(PRIMARY_FONT);
secondaryFont = loadFont(SECONDARY_FONT);
}
private void renderTemplate(String language, Graphics2D graphics) {
try {
BufferedImage templateImage = loadTemplateImage(String.format(TEMPLATE_FORMAT, language));
graphics.drawImage(templateImage, null, 0, 0);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Gets optimal size from possibleSizes for a font and maximumSize.
* @param values - Strings that need to fit in to maximumSize when rendered
* @param possibleSizes - Possible sizes to try
* @param maximumSize - All Strings from values array need to be smaller than this
* @param font - Font to use
* @param graphics - Graphics to use
* @return Actual optimal font size or -1 on failure.
*/
private int getOptimalFontSize(String[] values, int[] possibleSizes, int maximumSize, Font font, Graphics2D graphics) {
for(int currentSize : possibleSizes) {
Font currentFont = font.deriveFont((float)(currentSize));
FontMetrics fontMetrics = graphics.getFontMetrics(currentFont);
boolean success = true;
for(String currentValue : values) {
if(fontMetrics.stringWidth(currentValue) > maximumSize) {
success = false;
break;
}
}
if(success) return currentSize;
}
//Fallback - return -1
return -1;
}
private void renderMainValue(String value, int centerX, int centerY, float fontSize, Graphics2D graphics) {
graphics.setColor(Color.WHITE);
Font font = primaryFont.deriveFont(fontSize); //Need to be float
graphics.setFont(font);
FontMetrics fontMetrics = graphics.getFontMetrics(font);
int width = fontMetrics.stringWidth(value);
int height = fontMetrics.getHeight();
graphics.drawString(value, centerX - width/2f, centerY + height/2f);
}
private void renderAdditionalValue(String value, String unknownValue, int posX, int posY, Graphics2D graphics) {
if(value == null || value.isEmpty()) value = unknownValue;
graphics.setColor(Color.WHITE);
Font font = primaryFont.deriveFont(18f);
graphics.setFont(font);
FontMetrics fontMetrics = graphics.getFontMetrics(font);
int height = fontMetrics.getHeight();
graphics.drawString(value, posX, posY + height/2f);
}
private void renderTimeDateValue(String value, String unknownValue, int posX, int posY, Graphics2D graphics) {
if(value == null || value.isEmpty()) value = unknownValue;
graphics.setColor(new Color(22, 47, 103));
Font font = secondaryFont.deriveFont(20f);
graphics.setFont(font);
FontMetrics fontMetrics = graphics.getFontMetrics(font);
int width = fontMetrics.stringWidth(value);
int height = fontMetrics.getHeight();
graphics.drawString(value, posX - width, posY + height/2f);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment