/*
* This file is part of MoleculeViewer.
*
* MoleculeViewer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MoleculeViewer 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MoleculeViewer. If not, see <http://www.gnu.org/licenses/>.
*/
package astex;
import java.awt.*;
import java.awt.image.*;
/**
* Prepare an image of a string that looks like
* the rather groovy outlined font that Google maps
* uses.
*
* Needs an AWT component to do the offscreen font rendering.
*/
class GoogleFont {
/** We need a component for making images. */
private static Component component = null;
public static void setComponent(Component c){
component = c;
}
private static Font imageFont;
private static PixelGrabber pg;
private static final int maxWidth = 200;
private static final int maxHeight = 80;
private static final int matteColor = 0x00ffff;
private static int pix[] = null;
private static int impix[] = null;
private static int finalpix[] = null;
public static int[] makeFontImage(String s, int fg, int bg, int size[]){
if(component == null){
Frame frame = new Frame();
frame.addNotify();
component = (Component)frame;
if(component == null){
throw new Error("makeFontImage: you must call setComponent first");
}
}
if(imageFont == null){
imageFont = new Font("Arial", Font.PLAIN, 20);
}
Image image = component.createImage(maxWidth, maxHeight);
//Image image = Toolkit.getDefaultToolkit().createImage((ImageProducer)component);
Graphics gr = image.getGraphics();
// there are approximately 128,345 different
// bugs associated with offscreen images.
// do not under any circumstances attempt to
// change the current color, or specify the background
// or foreground color for the parent component.
// this silently does absolutely nothing under jdk1.1.8.
// you will use the colors that you are given and you
// will not moan about it
gr.setFont(imageFont);
gr.drawString(s, 10, maxHeight - 10);
if(pix == null){
pix = new int[maxWidth * maxHeight];
}
// pixelgrabber is one shot for some infathomable reason
pg = new PixelGrabber(image, 0, 0, maxWidth, maxHeight, pix, 0, maxWidth);
try {
pg.grabPixels();
}catch(Exception e){
throw new Error("makeFontImage: interrupted grabbing pixels");
}
Color foreground = component.getForeground();
int actualfg = foreground.getRGB() & 0xffffff;
// now get the boundary of the font.
int xmin = maxWidth;
int xmax = 0;
int ymin = maxHeight;
int ymax = 0;
int pixel = 0;
for(int y = 0; y < maxHeight; y++){
for(int x = 0; x < maxWidth; x++){
int p = pix[pixel++] & 0xffffff;
if(p == actualfg){
if(x < xmin) xmin = x;
if(y < ymin) ymin = y;
if(x > xmax) xmax = x;
if(y > ymax) ymax = y;
}
}
}
int border = 8;
if(impix == null){
impix = new int[(maxWidth + 2 * border) * (maxHeight + 2 * border)];
}
int w = xmax - xmin + 2 * border;
int h = ymax - ymin + 2 * border;
if(w % 2 == 1) w += 1;
if(h % 2 == 1) h += 1;
int pixelCount = w * h;
for(int p = 0; p < pixelCount; p++){
impix[p] = matteColor;
}
// copy text into centered new image
for(int y = ymin; y <= ymax; y++){
for(int x = xmin; x <= xmax; x++){
int oldp = x + maxWidth * y;
int newp = (x-xmin) + border + (((y-ymin) + border) * w);
if((pix[oldp] & 0xffffff) == actualfg){
impix[newp] = fg;
}
}
}
int actualBorder = 4;
int actualBorder2 = actualBorder * actualBorder;
int region = actualBorder + 2;
// fill in the background border around the lettering
for(int y = 0; y < h; y++){
for(int x = 0; x < w; x++){
int newp = x + y * w;
int p = impix[newp];
if(p == fg){
for(int y2 = y - region; y2 <= y + region; y2++){
for(int x2 = x - region; x2 <= x + region; x2++){
if(y2 >= 0 && y2 < h && x2 >= 0 && x2 < w){
int refp = x2 + y2 * w;
int p2 = impix[refp];
if(p2 != fg){
int dx = x2 - x;
int dy = y2 - y;
if(dx*dx + dy*dy <= actualBorder2){
impix[refp] = bg;
}
}
}
}
}
}
}
}
if(finalpix == null){
finalpix = new int[impix.length/4];
}
// now supersample
for(int y = 0; y < h; y += 2){
for(int x = 0; x < w; x += 2){
int a = 0;
int r = 0;
int g = 0;
int b = 0;
int matteCount = 0;
for(int xoff = 0; xoff < 2; xoff++){
for(int yoff = 0; yoff < 2; yoff++){
int poff = (x + xoff) + ((y + yoff)*w);
int p = impix[poff];
if(p == matteColor){
matteCount++;
}else{
r += (p & 0xff0000) >> 16;
g += (p & 0xff00) >> 8;
b += (p & 0xff);
}
}
}
r >>= 2;
g >>= 2;
b >>= 2;
switch(matteCount){
case 4: a = 0; break;
case 3: a = 64; break;
case 2: a = 128; break;
case 1: a = 192; break;
case 0: a = 255; break;
default: a = 255; break;
}
int dest = (x/2) + (y/2) * w/2;
finalpix[dest] = ((a&255)<< 24) | ((r&255)<<16) | ((g&255)<<8) | (b&255);
}
}
size[0] = w/2;
size[1] = h/2;
impix = null;
pix = null;
return finalpix;
}
}