1 23 package gnu.jpdf; 24 25 import java.awt.*; 26 import java.util.*; 27 28 54 public class BoundingBox extends Rectangle 55 { 56 57 public static final int LINE_SPACING_PERCENTAGE = 20; 58 59 60 public static final int VERT_ALIGN_CENTER = 0; 61 62 63 public static final int VERT_ALIGN_TOP = 1; 64 65 66 public static final int VERT_ALIGN_BOTTOM = 2; 67 68 69 public static final int HORIZ_ALIGN_CENTER = 3; 70 71 72 public static final int HORIZ_ALIGN_LEFT = 4; 73 74 75 public static final int HORIZ_ALIGN_RIGHT = 5; 76 77 78 public static final int SUBTRACT_FROM_TOP = 6; 79 80 81 public static final int SUBTRACT_FROM_BOTTOM = 7; 82 83 84 public static final int SUBTRACT_FROM_LEFT = 8; 85 86 87 public static final int SUBTRACT_FROM_RIGHT = 9; 88 89 private static final int[] VERT_ALIGNS = {VERT_ALIGN_CENTER, 90 VERT_ALIGN_TOP, 91 VERT_ALIGN_BOTTOM}; 92 93 private static final int[] HORIZ_ALIGNS = {HORIZ_ALIGN_CENTER, 94 HORIZ_ALIGN_LEFT, 95 HORIZ_ALIGN_RIGHT}; 96 97 private static final int[] SUBTRACTS = {SUBTRACT_FROM_TOP, 98 SUBTRACT_FROM_BOTTOM, 99 SUBTRACT_FROM_LEFT, 100 SUBTRACT_FROM_RIGHT}; 101 102 103 private Point drawingPoint; 104 105 106 private Point absoluteLocation; 107 108 109 private BoundingBox parent; 110 111 115 private String [] stringArray; 116 117 118 private String fullString; 119 120 126 public BoundingBox(Point p, Dimension d) { 127 super(p, d); 128 this.drawingPoint = this.getLocation(); 129 this.absoluteLocation = this.getLocation(); 130 } 131 132 133 134 140 public boolean hasParent() { 141 if (parent == null) { 142 return false; 143 } 144 else { 145 return true; 146 } 147 } 148 149 154 public BoundingBox getParent() { 155 return parent; 156 } 157 158 159 160 172 public void add(BoundingBox child) { 173 child.setParent(this); 174 } 175 176 177 178 183 public void setParent(BoundingBox parent) { 184 if (this == parent) { 186 return; 187 } 188 this.parent = parent; 189 190 if (this.getLocation().equals(this.getAbsoluteLocation())) { 193 int ancestorTranslateX = 0; 194 int ancestorTranslateY = 0; 195 196 BoundingBox ancestor = this; 197 while (ancestor.hasParent()) { 198 BoundingBox oldRef = ancestor; 199 ancestor = ancestor.getParent(); 200 if (ancestor == oldRef) { 202 break; 203 } 204 ancestorTranslateX += (int)ancestor.getLocation().getX(); 205 ancestorTranslateY += (int)ancestor.getLocation().getY(); 206 } 207 208 this.getAbsoluteLocation().translate(ancestorTranslateX, 209 ancestorTranslateY); 210 } } 213 214 215 216 217 223 public String [] getStringArray() { 224 return stringArray; 225 } 227 228 229 235 public void setStringArray(String [] strArray) { 236 this.stringArray = strArray; 237 } 238 239 240 245 public void setAbsoluteLocation(Point point) { 246 this.absoluteLocation = point; 247 } 248 249 250 251 254 public boolean boxExists() { 255 if ((this.getHeight() < 0) || (this.getWidth() < 0)) { 256 return false; 257 } 258 return true; 259 } 261 262 263 264 269 public Point getAbsoluteLocation() { 270 return absoluteLocation; 271 } 272 273 274 278 public String getFullString() { 279 return fullString; 280 } 281 282 283 288 public void setFullString(String string) { 289 this.fullString = string; 290 } 291 292 321 public BoundingBox getStringBounds(String string, 322 int hAlign, 323 int vAlign, 324 FontMetrics fm, 325 int padding, 326 boolean enforce) 327 throws IllegalArgumentException , StringTooLongException { 328 if (!checkHAlign(hAlign)) { 330 throw new IllegalArgumentException ("BoundingBox.getStringBounds, " + 331 "hAlign invalid : " + hAlign); 332 } 333 if (!checkVAlign(vAlign)) { 334 throw new IllegalArgumentException ("BoundingBox.getStringBounds, " + 335 "vAlign invalid : " + hAlign); 336 } 337 if (fm == null) { 338 throw new IllegalArgumentException ("BoundingBox.getStringBounds, " + 339 "FontMetrics null"); 340 } 341 if (string == null) { 342 throw new IllegalArgumentException ("BoundingBox.getStringBounds, " + 343 "String null"); 344 } 345 346 Point parentLocation = this.getLocation(); 351 Dimension parentSize = this.getSize(); 352 353 Point childLocation; 354 Dimension childSize; 355 356 int sa, sw, sh, pw, ph, cw, ch; 358 359 int cx, cy, px, py; 361 362 sa = fm.getMaxAscent(); 363 sw = fm.stringWidth(string); 364 sh = sa + fm.getMaxDescent(); 365 pw = (int)parentSize.getWidth(); 366 ph = (int)parentSize.getHeight(); 367 if (pw < 0) { 368 throw new StringTooLongException("The parent box has a negative width " + 369 " (" + pw + ")"); 370 } 371 if (ph < 0) { 372 throw new StringTooLongException("The parent box has a negative height"+ 373 " (" + ph + ")"); 374 } 375 cw = sw + padding*2; 376 ch = sh + padding*2; 377 px = (int)this.getX(); 378 py = (int)this.getY(); 379 380 String [] childStrArray = null; 381 382 if ((cw > pw) || (string.indexOf("\n") != -1)) { 383 cw = pw - (padding * 2); 384 childStrArray = createStringArray(string, fm, padding, pw); 385 ch = getWrappedHeight(childStrArray, fm, padding); 386 if (ch > ph) { 387 if (enforce) { 391 throw new StringTooLongException("The wrapped strings do not " + 392 "fit into the parent box, pw=" + pw + 393 ", ph=" + ph + ", ch=" + ch + ", cw=" + cw + 394 ", string: " + string); 395 } 396 } 397 } 398 399 401 if (vAlign == VERT_ALIGN_TOP) { 403 cy = 0; 404 } 405 else if (vAlign == VERT_ALIGN_CENTER) { 406 cy = (ph/2) - (ch/2); 407 } 408 else { 409 cy = ph - ch; 410 } 411 412 if (hAlign == HORIZ_ALIGN_LEFT) { 413 cx = 0; 414 } 415 else if (hAlign == HORIZ_ALIGN_CENTER) { 416 cx = (pw/2) - (cw/2); 417 } 418 else { 419 cx = pw - cw; 420 } 421 422 childLocation = new Point(cx, cy); 423 childSize = new Dimension(cw, ch); 424 425 int dpx, dpy, abx, aby; 429 430 int ancestorTranslateX = 0; 433 int ancestorTranslateY = 0; 434 435 BoundingBox ancestor = this; 436 while (ancestor.hasParent()) { 437 BoundingBox oldRef = ancestor; 438 ancestor = ancestor.getParent(); 439 if (ancestor == oldRef) { 441 break; 442 } 443 ancestorTranslateX += (int)ancestor.getLocation().getX(); 444 ancestorTranslateY += (int)ancestor.getLocation().getY(); 445 } 446 447 abx = px + cx + ancestorTranslateX; 449 aby = py + cy + ancestorTranslateY; 450 451 dpx = abx + padding; 453 dpy = aby + padding + sa; 454 455 Point drawingPoint = new Point(dpx, dpy); 456 BoundingBox returnChild = new BoundingBox(childLocation, 457 childSize, 458 drawingPoint, 459 new Point(abx, aby)); 460 this.add(returnChild); 461 returnChild.setFullString(string); 462 returnChild.setStringArray(childStrArray); 463 return returnChild; 464 465 } 467 468 487 public BoundingBox getStringBounds(String string, 488 int hAlign, 489 int vAlign, 490 FontMetrics fm, 491 int padding) 492 throws StringTooLongException, IllegalArgumentException { 493 return getStringBounds(string, hAlign, vAlign, fm, padding, true); 494 } 496 497 498 515 public void drawWrappedString(Graphics g, 516 FontMetrics fm, 517 int padding, 518 int hAlign) 519 throws IllegalArgumentException , StringTooLongException { 520 if (getStringArray() == null) { 521 Point p = getDrawingPoint(); 522 int xx = (int)p.getX(); 523 int yy = (int)p.getY(); 524 g.drawString(getFullString(), xx, yy); 525 } 526 else { 527 int len = stringArray.length; 528 for (int i = 0; i < len; i++) { 529 BoundingBox wrappedBox = null; 530 wrappedBox = getStringBounds(stringArray[i], 531 hAlign, 532 BoundingBox.VERT_ALIGN_TOP, 533 fm, 534 0); 535 Point pp = wrappedBox.getDrawingPoint(); 536 int xx = (int)pp.getX(); 537 if (hAlign == BoundingBox.HORIZ_ALIGN_RIGHT) { 538 xx -= padding; 539 } 540 if (hAlign == BoundingBox.HORIZ_ALIGN_LEFT) { 541 xx += padding; 542 } 543 int yy = (int)pp.getY() + padding; 544 g.drawString(stringArray[i], xx, yy); 545 subtract(wrappedBox, BoundingBox.SUBTRACT_FROM_BOTTOM); 546 } 547 } 548 } 550 551 562 public void drawWrappedStringTruncate(Graphics g, 563 FontMetrics fm, 564 int padding, 565 int hAlign) { 566 567 if (getStringArray() == null) { 568 Point p = getDrawingPoint(); 569 int xx = (int)p.getX(); 570 int yy = (int)p.getY(); 571 if (getFullString() != null) { 572 g.drawString(getFullString(), xx, yy); 573 } 574 else { 575 System.err.println("getStringArray and getFullString are null"); 576 } 577 } 578 else { 579 int totalHeight = 0; 580 int len = stringArray.length; 581 for (int i = 0; i < len; i++) { 582 BoundingBox wrappedBox = null; 583 try { 584 wrappedBox = getStringBounds(stringArray[i], 585 hAlign, 586 BoundingBox.VERT_ALIGN_TOP, 587 fm, 588 0, 589 false); 590 totalHeight += (int)wrappedBox.getHeight(); 591 if (getParent() != null) { 592 if (totalHeight > (int)(getParent().getHeight())) { 593 return; 594 } 595 } 596 } 597 catch (StringTooLongException stle) { 598 stle.printStackTrace(); 599 return; 600 } 601 wrappedBox.drawChoppedString(g, fm, padding, hAlign); 602 subtract(wrappedBox, BoundingBox.SUBTRACT_FROM_BOTTOM); 603 } 604 } 605 } 607 608 618 public void drawChoppedString(Graphics g, 619 FontMetrics fm, 620 int padding, 621 int hAlign) { 622 623 String string = ""; 624 if (getStringArray() != null) { 625 string = new String (getStringArray()[0]); 626 } 627 else { 628 string = new String (getFullString()); 629 } 630 BoundingBox choppedBox = null; 631 try { 632 choppedBox = getStringBounds(string, 633 hAlign, 634 VERT_ALIGN_TOP, 635 fm, 636 padding); 637 Point p = choppedBox.getDrawingPoint(); 638 int x = (int)p.getX(); 639 int y = (int)p.getY(); 640 g.drawString(string, x, y); 641 } 642 catch (StringTooLongException stle) { 643 StringBuffer buf = new StringBuffer ().append(string); 645 if (buf.length() == 0) { 646 System.out.println("BoundingBox.drawChoppedString, buf len 0 ??"); 647 throw new RuntimeException (); 649 } 650 buf.deleteCharAt(buf.length()-1); 651 while ((fm.stringWidth(buf.toString()) > (int)getWidth()) && 652 (buf.length() > 0)) { 653 buf.deleteCharAt(buf.length()-1); 654 } 655 656 try { 657 choppedBox = getStringBounds(buf.toString(), 658 hAlign, 659 VERT_ALIGN_TOP, 660 fm, 661 padding); 662 Point pp = choppedBox.getDrawingPoint(); 663 int xx = (int)pp.getX(); 664 int yy = (int)pp.getY(); 665 g.drawString(string, xx, yy); 666 } 667 catch (StringTooLongException sstle) { 668 sstle.printStackTrace(); 670 } 671 } 672 } 674 675 676 677 678 679 680 681 682 686 private int getWrappedHeight(String [] strings, FontMetrics fm, int padding) { 687 int ma = fm.getMaxAscent(); 688 int md = fm.getMaxDescent(); 689 int sh = ma + md; 690 int hPad = sh / LINE_SPACING_PERCENTAGE; 691 sh += hPad; 692 int total = sh * strings.length; 693 694 return total + (padding*2); 695 } 697 698 699 709 private String [] createStringArray(String string, 710 FontMetrics fm, 711 int padding, 712 int pw) { 713 if (string == null) { 714 System.err.println("Tried createStringArray with null String"); 715 return null; 716 } 717 if (fm == null) { 718 System.err.println("Tried createStringArray with null FontMetrics"); 719 } 720 721 int sw = fm.stringWidth(string); 722 int lw = pw - (padding*2); 723 724 725 726 Vector returnVector = new Vector(); 727 StringTokenizer st = new StringTokenizer(string, " \t\n\r\f", true); 729 StringBuffer tempBuffer = new StringBuffer (); 730 StringBuffer finalBuffer = new StringBuffer (); 731 732 while(st.hasMoreTokens()) { 733 String tempString = st.nextToken(); 735 tempBuffer.append(tempString); 736 737 if ((fm.stringWidth(tempBuffer.toString()) < lw) && 740 (tempBuffer.toString() 741 .charAt(tempBuffer.toString().length() - 1) != '\n') && 742 (tempBuffer.toString() 743 .charAt(tempBuffer.toString().length() - 1) != '\r')) { 744 finalBuffer.append(tempString); 745 continue; 746 } 747 else { 748 returnVector.addElement(finalBuffer.toString()); 749 finalBuffer.delete(0, finalBuffer.length()); 750 tempBuffer.delete(0, tempBuffer.length()); 751 if ((tempString.charAt(0) != '\n') && 752 (tempString.charAt(0) != '\r')) { 753 tempBuffer.append(tempString); 754 finalBuffer.append(tempString); 755 } 756 continue; 757 } 758 759 } returnVector.addElement(finalBuffer.toString()); 761 762 int len = returnVector.size(); 763 String [] childStrArray = new String [len]; 765 for (int i = 0; i < len; i++) { 766 String curStr = (String )returnVector.get(i); 767 childStrArray[i] = curStr; 768 } 769 770 return childStrArray; 771 772 } 774 775 776 794 public BoundingBox subtract(BoundingBox child, int subtractFrom) { 795 if (child == null) { 797 throw new IllegalArgumentException ("BoundingBox.subtract, " + 798 "BoundingBox child is null"); 799 } 800 if (!child.hasParent()) { 801 throw new IllegalArgumentException ("BoundingBox.subtract, " + 802 "BoundingBox child has no parent"); 803 } 804 else { 805 if (!(child.getParent() == this)) { 806 throw new IllegalArgumentException ("BoundingBox.subtract, " + 807 "this is not BoundingBox child's parent"); 808 } 809 else { 810 int len = SUBTRACTS.length; 813 boolean valid = false; 814 for (int i = 0; i < len; i++) { 815 if (subtractFrom == SUBTRACTS[i]) { 816 valid = true; 817 } 818 } 819 if (!valid) { 820 throw new IllegalArgumentException ("BoundingBox.subtract, " + 821 "subtractFrom invalid: " + subtractFrom); 822 } 823 824 827 child.setParent(null); 830 831 int cx = (int)child.getLocation().getX(); 832 int cy = (int)child.getLocation().getY(); 833 int cw = (int)child.getSize().getWidth(); 834 int ch = (int)child.getSize().getHeight(); 835 int px = (int)this.getLocation().getX(); 836 int py = (int)this.getLocation().getY(); 837 int pw = (int)this.getSize().getWidth(); 838 int ph = (int)this.getSize().getHeight(); 839 840 switch (subtractFrom) { 841 case SUBTRACT_FROM_LEFT: 842 pw = cx; 844 this.setSize(new Dimension(pw, ph)); 845 return this; 846 847 case SUBTRACT_FROM_RIGHT: 848 px = px + cw + cx; 850 pw = pw - cw - cx; 851 this.setLocation(new Point(px, py)); 852 this.setSize(new Dimension(pw, ph)); 853 return this; 854 855 case SUBTRACT_FROM_BOTTOM: 856 py = py + ch + cy; 857 ph = ph - ch - cy; 858 this.setLocation(new Point(px, py)); 859 this.setSize(new Dimension(pw, ph)); 860 return this; 861 862 case SUBTRACT_FROM_TOP: 863 ph = cy; 864 this.setSize(new Dimension(pw, ph)); 865 return this; 866 867 default: break; 869 } } 871 } 872 return this; 873 } 875 876 877 878 890 public Point getDrawingPoint() { 891 return drawingPoint; 892 } 893 894 895 896 897 898 900 901 902 907 public static void main(String [] args) { 908 Point upperLeft = new Point(5, 5); 909 Dimension bounds = new Dimension(100, 100); 910 BoundingBox parent = new BoundingBox(upperLeft, bounds); 911 String string = "Hello World!"; 912 Font font = new Font("SansSerif", Font.PLAIN, 12); 913 Frame frame = new Frame(); 914 frame.addNotify(); 915 try { 916 Image image = frame.createImage(100, 100); 917 if (image == null) { 918 System.err.println("image is null"); 919 } 920 Graphics graphics = image.getGraphics(); 921 FontMetrics fm = graphics.getFontMetrics(font); 922 BoundingBox child = parent 923 .getStringBounds(string, 924 BoundingBox.HORIZ_ALIGN_LEFT, 925 BoundingBox.VERT_ALIGN_TOP, 926 fm, 927 5); 928 System.out.println("Drawing Point: " + 929 child.getDrawingPoint().toString()); 930 System.out.println("Now testing subtract() method..."); 931 932 parent = new BoundingBox(new Point(10, 10), new Dimension(300, 300)); 933 System.out.println("parent: " + parent.toString()); 934 child = new BoundingBox(new Point(90, 110), new Dimension(100, 100)); 935 parent.add(child); 936 System.out.println("child: " + child.toString()); 937 System.out.println(); 938 System.out.println("subtracting the child from the parent"); 939 System.out.println("SUBTRACT_FROM_TOP: "); 940 parent = parent.subtract(child, SUBTRACT_FROM_TOP); 941 System.out.println("new parent: " + parent.toString()); 942 System.out.println(); 943 System.out.println("Resetting parent"); 944 parent = new BoundingBox(new Point(10, 10), new Dimension(300, 300)); 945 parent.add(child); 946 System.out.println("SUBTRACT_FROM_BOTTOM"); 947 parent.subtract(child, SUBTRACT_FROM_BOTTOM); 948 System.out.println("new parent: " + parent.toString()); 949 System.out.println(); 950 System.out.println("Resetting parent"); 951 parent = new BoundingBox(new Point(10, 10), new Dimension(300, 300)); 952 parent.add(child); 953 System.out.println("SUBTRACT_FROM_LEFT"); 954 parent.subtract(child, SUBTRACT_FROM_LEFT); 955 System.out.println("new parent: " + parent.toString()); 956 System.out.println(); 957 System.out.println("Resetting parent"); 958 parent = new BoundingBox(new Point(10, 10), new Dimension(300, 300)); 959 parent.add(child); 960 System.out.println("SUBTRACT_FROM_RIGHT"); 961 parent.subtract(child, SUBTRACT_FROM_RIGHT); 962 System.out.println("new parent: " + parent.toString()); 963 System.out.println(); 964 965 966 967 System.exit(0); 968 } 969 catch (Exception e) { 970 e.printStackTrace(); 971 System.exit(1); 972 } 973 } 974 975 976 978 985 private BoundingBox(Point p, 986 Dimension d, 987 Point drawingPoint, 988 Point absolute) { 989 super(p, d); 990 this.drawingPoint = drawingPoint; 991 this.absoluteLocation = absolute; 992 } 993 994 995 1002 private boolean checkHAlign(int hAlign) { 1003 int len = HORIZ_ALIGNS.length; 1004 for (int i = 0; i < len; i++) { 1005 if (hAlign == HORIZ_ALIGNS[i]) { 1006 return true; 1007 } 1008 } 1009 return false; 1010 } 1011 1012 1013 1014 1021 private boolean checkVAlign(int vAlign) { 1022 int len = VERT_ALIGNS.length; 1023 for (int i = 0; i < len; i++) { 1024 if (vAlign == VERT_ALIGNS[i]) { 1025 return true; 1026 } 1027 } 1028 return false; 1029 } 1030 1031} 1033 1034 1035 1036 | Popular Tags |