package edu.byu.cs.roots.opg.util;
import java.awt.Font;
import java.awt.font.FontRenderContext;
public class NameAbbreviator {
public static FontRenderContext frc = null; //will be set by the JPanel used to draw charts
static double fontsize;
static String formattedName;
final static double MINFONTSCALE = 1;
public static double getSize() {
return fontsize;
}
public static String getName() {
return formattedName.trim();
}
public static void nameFit(String Prefix, String GivenNames, String Surname, String Postfix, float width, Font font) {
//System.out.println("prefix: " + prefix + "\tgivennames: " + GivenNames + "\tsurname: " + Surname + "\tpostfix: " + Postfix + "\twidth: " + width + "\tfont: " + font);
while(Prefix.indexOf(" ") != -1)
Prefix = Prefix.substring(0, Prefix.indexOf(" ")) + " " + Prefix.substring(Prefix.indexOf(" ") + 2);
while(GivenNames.indexOf(" ") != -1)
GivenNames = GivenNames.substring(0,GivenNames.indexOf(" ")) + " " + GivenNames.substring(GivenNames.indexOf(" ")+2);
while(Surname.indexOf(" ") != -1)
Surname = Surname.substring(0,Surname.indexOf(" ")) + " " + Surname.substring(Surname.indexOf(" ")+2);
while(Postfix.indexOf(" ") != -1)
Postfix = Postfix.substring(0,Postfix.indexOf(" ")) + " " + Postfix.substring(Postfix.indexOf(" ")+2);
String result = getFitInfo(Prefix, GivenNames, Surname, Postfix, width, font);
fontsize = Double.parseDouble(result.substring(0,result.indexOf(":")));
formattedName = result.substring(result.indexOf(":") + 1);
}
/****************************************************************
*
* @param Prefix
* @param GivenNames
* @param Surname
* @param Postfix
* @param width
* @param font
* @return the abbreviated name
*
* Order of Abbreviations:
* 1. check to see if the original can fit in given width
* 2. set each name to have the first letter capitalized and the rest lower case
* 3. remove the "or __" from the surname
* 4. remove the "or __" from the given names
* 5. remove (_) from surname
* 6. remove (_) from given names
* 7. reduce the middle name to only the middle initial
* 8. remove the post-fix
* 9. remove the middle initial
* 10. go through all the given names and one by one reduce the names
* to initials, until the name fits
* 11. remove one by one all the given initials until the name fits
* 12. go through and make all the surnames into initials except the last one
* until the name fits
* 13. remove all the surnames except the last name
* 14. remove the pre-fix
* 15. remove last name with ellipsis last portion that doesn't fit **NEEDS TO BE DONE!**
* 16. make the surname into an initial
* 17. if there is no room for any of this, return a blank String.
*/
private static String getFitInfo(String Prefix, String GivenNames, String Surname, String Postfix, float width, Font font) {
String name = Prefix + " " + GivenNames + " " + Surname + " " + Postfix;
//Full Name
double fontSize = CheckFit(name, width, font);
//if(fontSize > -1)
// return fontSize + ": " + name;
//System.out.println(name);
//DO THESE IMMEDIATELY (EVEN IF THEY WOULD/COULD FIT):
//Split Names
String[] Prefixes = Prefix.split(" ");
String[] Givens = GivenNames.split(" ");
String[] Surnames = Surname.split(" ");
String[] Postfixes = Postfix.split(" ");
//Convert names to having the first letter capitalized,
//and the rest lowercase (for uniformity)
Prefixes = firstLetterCapsOnly(Prefixes);
Givens = firstLetterCapsOnly(Givens);
Surnames = firstLetterCapsOnly(Surnames);
Postfixes = firstLetterCapsOnly(Postfixes);
Surnames = removeOrs(Surnames);
Givens = removeOrs(Givens);
//Remove ?'s from name
for(int i = 0; i < Surnames.length; i++) {
if (Surnames[i] != null) {
Surnames[i] = Surnames[i].replace('?', ' ');
Surnames[i] = Surnames[i].trim();
}
}
for(int i = 0; i < Givens.length; i++) {
if (Givens[i] != null) {
Givens[i] = Givens[i].replace('?', ' ');
Givens[i] = Givens[i].trim();
}
}
//check for fit
// name = GetName(Prefixes, Givens,Surnames,Postfixes);
// fontSize = CheckFit(name, width, font);
// if(fontSize > -1)
// return fontSize + ": " + name;
//System.out.println(name);
//Remove (_) from surname
for (int i=0; i<Surnames.length; i++) {
if(Surnames[i] != null && Surnames[i].startsWith("(")) {
while (i<Surnames.length) {
if (Surnames[i] != null && Surnames[i].endsWith(")")) {
Surnames[i] = null;
//++i; //Removed By: Spencer Hoffa 3/21/2013
break;
}
else if (Surnames[i] != null) {
Surnames[i] = null;
//++i; //Removed By: Spencer Hoffa 3/21/2013
}
++i; //Added By: Spencer Hoffa 3/21/2013 This should fix infinite loop problem.
}
}
}
//remove (_) from Surnames names that are inside (not necessarily at the front
for(int i=0; i<Surnames.length; i++) {
if(Surnames[i] != null) {
//System.out.println("name: " + Surnames[i]);
int k = 0;
while(k < Surnames[i].length()) {
//System.out.println("char: " + Surnames[i].charAt(k));
if(Surnames[i].charAt(k) == '(') {
//System.out.println("IN HERE!");
int p = k;
while(k < Surnames[i].length()) {
//System.out.println("char2: " + Surnames[i].charAt(k));
if(Surnames[i].charAt(k) == ')') {
k++;
//System.out.println("Substring: " + Surnames[i].substring(p, k));
Surnames[i] = Surnames[i].replace(Surnames[i].substring(p, k), "");
k -= 2;
break;
}
k++;
}
}
k++;
}
}
}
//check for fit
name = GetName(Prefixes, Givens, Surnames, Postfixes);
// fontSize = CheckFit(name, width, font);
// if(fontSize > -1)
// return fontSize + ": " + name;
//System.out.println(name);
//Remove (_) from given names
//ToDo: check that the () don't span over multiple names in GivenNames (see Mary Spoor)
for (int i=0; i<Givens.length; i++) {
if(Givens[i] != null && Givens[i].startsWith("(")) {
while(i < Givens.length) {
if (Givens[i] != null && Givens[i].endsWith(")")) {
Givens[i] = null;
//++i; //Removed By: Spencer Hoffa 3/21/2013
break;
}
else if (Givens[i] != null) {
Givens[i] = null;
//++i; //Removed By: Spencer Hoffa 3/21/2013
}
++i; //Added By: Spencer HOffa 3/21/2013 This should fix the infinite loop problem here.
}
}
}
//remove (_) from Given names that are inside (not necessarily at the front
for(int i=0; i<Givens.length; i++) {
if(Givens[i] != null) {
//System.out.println("name: " + Givens[i]);
int k = 0;
while(k < Givens[i].length()) {
//System.out.println("char: " + Givens[i].charAt(k));
if(Givens[i].charAt(k) == '(') {
//System.out.println("IN HERE!");
int p = k;
while(k < Givens[i].length()) {
//System.out.println("char2: " + Givens[i].charAt(k));
if(Givens[i].charAt(k) == ')') {
k++;
//System.out.println("Substring: " + Givens[i].substring(p, k));
Givens[i] = Givens[i].replace(Givens[i].substring(p, k), "");
k -= 2;
break;
}
k++;
}
}
k++;
}
}
}
//remove (_) from Prefixes names that are inside (not necessarily at the front
for(int i=0; i<Prefixes.length; i++) {
if(Prefixes[i] != null) {
//System.out.println("name: " + Prefixes[i]);
int k = 0;
while(k < Prefixes[i].length()) {
//System.out.println("char: " + Prefixes[i].charAt(k));
if(Prefixes[i].charAt(k) == '(') {
//System.out.println("IN HERE!");
int p = k;
while(k < Prefixes[i].length()) {
//System.out.println("char2: " + Prefixes[i].charAt(k));
if(Prefixes[i].charAt(k) == ')') {
k++;
//System.out.println("Substring: " + Prefixes[i].substring(p, k));
Prefixes[i] = Prefixes[i].replace(Prefixes[i].substring(p, k), "");
k -= 2;
break;
}
k++;
}
}
k++;
}
}
}
//remove (_) from Postfixes names that are inside (not necessarily at the front
for(int i=0; i<Postfixes.length; i++) {
if(Postfixes[i] != null) {
//System.out.println("name: " + Postfixes[i]);
int k = 0;
while(k < Postfixes[i].length()) {
//System.out.println("char: " + Postfixes[i].charAt(k));
if(Postfixes[i].charAt(k) == '(') {
//System.out.println("IN HERE!");
int p = k;
while(k < Postfixes[i].length()) {
//System.out.println("char2: " + Postfixes[i].charAt(k));
if(Postfixes[i].charAt(k) == ')') {
k++;
//System.out.println("Substring: " + Postfixes[i].substring(p, k));
Postfixes[i] = Postfixes[i].replace(Postfixes[i].substring(p, k), "");
k -= 2;
break;
}
k++;
}
}
k++;
}
}
}
//check for fit
name = GetName(Prefixes, Givens, Surnames, Postfixes);
//System.out.println(name);
fontSize = CheckFit(name, width, font);
if(fontSize > -1)
return fontSize + ": " + name;
//Middle Initials
for(int i=1;i<Givens.length;i++) {
if(Givens[i] != null && Givens[i].length() > 0) {
Givens[i] = Givens[i].substring(0,1);
}
}
//check for fit
name = GetName(Prefixes, Givens,Surnames,Postfixes);
fontSize = CheckFit(name, width, font);
if(fontSize > -1)
return fontSize + ": " + name;
//System.out.println(name);
//Remove Postfix
for(int i=0; i<Postfixes.length; i++) {
Postfixes[i] = null;
}
//check for fit
name = GetName(Prefixes, Givens,Surnames,Postfixes);
fontSize = CheckFit(name, width, font);
if(fontSize > -1)
return fontSize + ": " + name;
//System.out.println(name);
//Remove Middle Initials
for(int i=1;i<Givens.length;i++) {
Givens[i] = null;
}
//check for fit
name = GetName(Prefixes, Givens,Surnames,Postfixes);
fontSize = CheckFit(name, width, font);
if(fontSize > -1)
return fontSize + ": " + name;
//System.out.println(name);
//First Initial
if(Givens.length > 0 && Givens[0] != null && Givens[0].length() > 1)
Givens[0] = Givens[0].substring(0,1);
//check for fit
name = GetName(Prefixes, Givens,Surnames,Postfixes);
fontSize = CheckFit(name, width, font);
if(fontSize > -1)
return fontSize + ": " + name;
//System.out.println(name);
//Remove First Initial
Givens[0] = null;
//check for fit
name = GetName(Prefixes, Givens,Surnames,Postfixes);
fontSize = CheckFit(name, width, font);
if(fontSize > -1)
return fontSize + ": " + name;
//System.out.println(name);
//Initials of all but the last of the surname
for(int i=0;i<Surnames.length-1;i++) {
if(Surnames[i] != null && Surnames[i].length() > 0)
Surnames[i] = Surnames[i].substring(0,1);
}
//check for fit
name = GetName(Prefixes, Givens,Surnames,Postfixes);
fontSize = CheckFit(name, width, font);
if(fontSize > -1)
return fontSize + ": " + name;
//System.out.println(name);
//Remove all but the last of the surname
for(int i=0;i<Surnames.length-1;i++) {
Surnames[i] = null;
}
//check for fit
name = GetName(Prefixes, Givens,Surnames,Postfixes);
fontSize = CheckFit(name, width, font);
if(fontSize > -1)
return fontSize + ": " + name;
//System.out.println(name);
//TODO: last name with ellipsis last portion that doesn't fit
//Remove Prefix
for(int i=0; i<Prefixes.length; i++) {
Prefixes[i] = null;
}
//check for fit
name = GetName(Prefixes, Givens,Surnames,Postfixes);
fontSize = CheckFit(name, width, font);
if(fontSize > -1)
return fontSize + ": " + name;
//System.out.println(name);
//Last Initial
if(Surnames.length > 0 && Surnames[Surnames.length-1] != null && Surnames[Surnames.length-1].length() != 0) {
return font.getSize2D() + ": " + Surnames[Surnames.length-1].substring(0,1);
}
return "-1:none";
}
private static String[] removeOrs(String[] names) {
for (int i=0;i<names.length;i++) {
if(names[i] != null) {
if(names[i].toLowerCase().compareTo("or") == 0) {
while(i<names.length) {
names[i] = null;
++i;
}
}
}
}
return names;
}
private static String[] firstLetterCapsOnly(String[] names) {
for(int i = 0; i < names.length; i++) {
if (names[i] != null && names[i].length() != 0) {
names[i] = names[i].toLowerCase();
String lowerName = names[i].substring(1);
names[i] = Character.toString(Character.toUpperCase(names[i].charAt(0)));
names[i] = names[i].concat(lowerName);
}
}
return names;
}
public static String GetName(String[] Prefixes, String[] Givens, String[] Surnames, String[] Postfixes) {
String name = "";
for(int i=0;i<Prefixes.length;i++) {
if(Prefixes[i] != null)
name += Prefixes[i].trim() + " ";
}
for(int i=0;i<Givens.length;i++) {
if(Givens[i] != null)
name += Givens[i].trim() + " ";
}
for(int i=0;i<Surnames.length;i++) {
if(Surnames[i] != null)
name += Surnames[i].trim() + " ";
}
for(int i=0;i<Postfixes.length;i++) {
if(Postfixes[i] != null)
name += Postfixes[i].trim() + " ";
}
return name;
}
//returns font size if it fits and -1 if it doesn't fit
public static double CheckFit(String name, float width, Font font) {
double stringwidth = font.getStringBounds(name, frc).getWidth();
//double stringwidth = font.createGlyphVector(frc, name).getPixelBounds(frc, 0, 0).getWidth();
if(stringwidth <= width)
return font.getSize2D();
else if(stringwidth * MINFONTSCALE <= width) {
double minWidth = font.deriveFont((float)(font.getSize() * MINFONTSCALE)).getStringBounds(name, frc).getWidth();
double scaleFactor = (width - minWidth) / (stringwidth - minWidth);
double scaledFontSize = Math.floor((((1.0 - MINFONTSCALE) * scaleFactor) + MINFONTSCALE) * font.getSize2D());
double scaledWidth = font.deriveFont((float)scaledFontSize).getStringBounds(name, frc).getWidth();
if(scaledWidth <= width)
return scaledFontSize;
//return font.getSize2D() * newWidth/width;
}
return -1;
}
}