/******************************************************************************* * Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com) * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt ******************************************************************************/ package com.opendoorlogistics.studio.appframe; import java.awt.Color; import java.awt.Component; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.TexturePaint; import java.awt.font.TextLayout; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Random; import javax.imageio.ImageIO; import com.opendoorlogistics.core.utils.Pair; import com.opendoorlogistics.core.utils.images.ImageUtils; import com.vividsolutions.jts.geom.Envelope; import com.vividsolutions.jts.index.quadtree.Quadtree; final public class AppBackground { // private static final BasicStroke INNER_TEXT_STROKE = new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.CAP_ROUND, 0, null, 0); private final Random random = new Random(123); private final int NB_POSITIONING_ATTEMPTS = 5000; private final HashMap<Pair<String, Integer>, Pair<TextLayout, Rectangle2D>> layouts = new HashMap<>(); private final int width; private final int height; private final Quadtree quadtree = new Quadtree(); private final Rectangle2D screen; private final BufferedImage image ; private final String[] strs = new String[] { "consultancy", "integration", "help & advice", "software development", "support", "training", "implementation", "bespoke solutions", // "territory design", "www.opendoorlogistics.com", "www.opendoorlogistics.com", "www.opendoorlogistics.com" }; private int nbConsecutiveFails = 0; private int step=0; private Graphics2D g; public static final Color BACKGROUND_COLOUR = new Color(230, 230, 230); public AppBackground(){ this(1000, 1000); } public AppBackground(int width, int height) { this.width = width; this.height = height; screen = new Rectangle2D.Double(0, 0, width, height); image = ImageUtils.createBlankImage(width, height, BACKGROUND_COLOUR); } public static void main(String[] args) throws IOException { BufferedImage img = new AppBackground(1000,1600).create(); ImageUtils.createImageFrame(img).setVisible(true); File outputfile = new File("c:\\temp\\background.png"); ImageIO.write(img, "png", outputfile); // File outputfile = new File("c:\\temp\\outputimage.png"); // ImageIO.write(img, "png", outputfile); } public BufferedImage create() { start(); while (nbConsecutiveFails < 100) { doStep(); } finish(); return image; } public int getNbConsecutiveFails() { return nbConsecutiveFails; } public void doStep() { String s = strs[random.nextInt(strs.length)]; int fontSize = 10 + random.nextInt(20); int buffer = 200; int x = 0; int y = 0; boolean okPos = false; // Shape shape = null; TextLayout textLayout = null; Rectangle2D textBounds = null; Rectangle2D untranslatedBounds = null; for (int j = 0; j < NB_POSITIONING_ATTEMPTS && okPos == false; j++) { // reduce font size if we're having trouble fitting in if (j > 0 && j % 50 == 0 && fontSize >= 8) { fontSize--; textLayout = null; } if (textLayout == null) { Pair<TextLayout, Rectangle2D> pair = getLayout(g, s, fontSize); textLayout = pair.getFirst(); untranslatedBounds = pair.getSecond(); } x = random.nextInt(width + buffer) - buffer; y = random.nextInt(height + buffer) - buffer; // get bounds by getting the shape and translating to screen position // AffineTransform affineTransform = new AffineTransform(); // affineTransform.translate(x, y); // shape = textLayout.getOutline(affineTransform); Rectangle2D initial = new Rectangle2D.Double(untranslatedBounds.getX() + x, untranslatedBounds.getY() + y, untranslatedBounds.getWidth(), untranslatedBounds.getHeight()); textBounds = new Rectangle2D.Double(initial.getX() - initial.getWidth() / 8, initial.getY() - initial.getHeight() / 8, initial.getWidth() * 1.25, initial.getHeight() * 1.25); okPos = true; if (!screen.contains(textBounds)) { okPos = false; } else { for (Object o : quadtree.query(toEnvelope(textBounds))) { Rectangle2D rect = (Rectangle2D) o; if (textBounds.intersects(rect)) { okPos = false; break; } } } } if (okPos) { Color col = new Color(fontCol(), fontCol(), fontCol(), 40 + random.nextInt(80)); // Color outlineCol = new Color(255, 255, 255, 100); // g.setStroke(INNER_TEXT_STROKE); // g.setColor(outlineCol); // g.draw(shape); g.setColor(col); textLayout.draw(g, x, y); quadtree.insert(toEnvelope(textBounds), textBounds); nbConsecutiveFails = 0; } else { nbConsecutiveFails++; } //System.out.println("Step=" +step + " rendered=" + quadtree.size() + " nbConsecutiveFails="+ nbConsecutiveFails + " - " + okPos); step++; } public BufferedImage getImage() { return image; } public void finish() { g.dispose(); } public void start() { g = image.createGraphics(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); } private Envelope toEnvelope(Rectangle2D r) { return new Envelope(r.getMinX(), r.getMaxX(), r.getMinY(), r.getMaxY()); } private Pair<TextLayout, Rectangle2D> getLayout(Graphics2D g, String s, int fontSize) { Pair<String, Integer> key = new Pair<String, Integer>(s, fontSize); Pair<TextLayout, Rectangle2D> ret = layouts.get(key); if (ret == null) { Font font = new Font(Font.SANS_SERIF, Font.BOLD, fontSize); TextLayout tl = new TextLayout(s, font, g.getFontRenderContext()); ret = new Pair<TextLayout, Rectangle2D>(tl, tl.getBounds()); layouts.put(key, ret); } return ret; } private int fontCol() { return 180 + random.nextInt(20); } public int getNbRendered(){ return quadtree.size(); } public static void paintBackground(Component c,Graphics g,BufferedImage background){ Graphics2D g2d = (Graphics2D) g; if (background != null) { TexturePaint paint = new TexturePaint(background, new Rectangle(0, 0, background.getWidth(), background.getHeight())); if (paint != null) { g2d.setPaint(paint); g2d.fill(g2d.getClip()); } } else { g2d.setColor(AppBackground.BACKGROUND_COLOUR); g2d.fillRect(0, 0, (int) c.getSize().getWidth(), (int) c.getSize().getHeight()); } } }