00001 // Filename: charLayout.cxx 00002 // Created by: drose (16Feb01) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved 00008 // 00009 // All use of this software is subject to the terms of the Panda 3d 00010 // Software license. You should have received a copy of this license 00011 // along with this source code; you will also find a current copy of 00012 // the license at http://www.panda3d.org/license.txt . 00013 // 00014 // To contact the maintainers of this program write to 00015 // panda3d@yahoogroups.com . 00016 // 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include "charLayout.h" 00020 #include "charBitmap.h" 00021 00022 #include <notify.h> 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Function: CharLayout::reset 00026 // Access: Public 00027 // Description: Removes all the characters already placed on the 00028 // layout, and resets the parameters for a new attempt. 00029 //////////////////////////////////////////////////////////////////// 00030 void CharLayout:: 00031 reset(int working_xsize, int working_ysize, int working_buffer_pixels) { 00032 _working_xsize = working_xsize; 00033 _working_ysize = working_ysize; 00034 _working_buffer_pixels = working_buffer_pixels; 00035 00036 _placements.clear(); 00037 00038 _cx = _working_buffer_pixels; 00039 _cy = _working_buffer_pixels; 00040 _nexty = _cy; 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: CharLayout::place_character 00045 // Access: Public 00046 // Description: Given a character bitmap and font metrics extracted 00047 // from the pk file, find a place for it on the layout. 00048 // Returns true if the character was placed, false if we 00049 // ran out of room. 00050 //////////////////////////////////////////////////////////////////// 00051 bool CharLayout:: 00052 place_character(const CharBitmap *bm) { 00053 int width = bm->get_width() + _working_buffer_pixels; 00054 int height = bm->get_height() + _working_buffer_pixels; 00055 00056 int x, y; 00057 if (find_hole(x, y, width, height)) { 00058 _placements.push_back(CharPlacement(bm, x, y, width, height)); 00059 return true; 00060 } 00061 00062 return false; 00063 } 00064 00065 //////////////////////////////////////////////////////////////////// 00066 // Function: CharLayout::find_hole 00067 // Access: Private 00068 // Description: Searches for a hole of at least x_size by y_size 00069 // pixels somewhere within the layout. If a 00070 // suitable hole is found, sets x and y to the top left 00071 // corner and returns true; otherwise, returns false. 00072 //////////////////////////////////////////////////////////////////// 00073 bool CharLayout:: 00074 find_hole(int &x, int &y, int x_size, int y_size) const { 00075 y = _working_buffer_pixels; 00076 while (y + y_size <= _working_ysize) { 00077 int next_y = _working_ysize; 00078 // Scan along the row at 'y'. 00079 x = _working_buffer_pixels; 00080 while (x + x_size <= _working_xsize) { 00081 int next_x = x; 00082 00083 // Consider the spot at x, y. 00084 const CharPlacement *overlap = find_overlap(x, y, x_size, y_size); 00085 00086 if (overlap == (const CharPlacement *)NULL) { 00087 // Hooray! 00088 return true; 00089 } 00090 00091 next_x = overlap->_x + overlap->_width; 00092 next_y = min(next_y, overlap->_y + overlap->_height); 00093 nassertr(next_x > x, false); 00094 x = next_x; 00095 } 00096 00097 nassertr(next_y > y, false); 00098 y = next_y; 00099 } 00100 00101 // Nope, wouldn't fit anywhere. 00102 return false; 00103 } 00104 00105 //////////////////////////////////////////////////////////////////// 00106 // Function: CharLayout::find_overlap 00107 // Access: Private 00108 // Description: If the rectangle whose top left corner is x, y and 00109 // whose size is x_size, y_size describes an empty hole 00110 // that does not overlap any placed chars, returns 00111 // NULL; otherwise, returns the first placed texture 00112 // that the image does overlap. It is assumed the 00113 // rectangle lies completely within the boundaries of 00114 // the image itself. 00115 //////////////////////////////////////////////////////////////////// 00116 const CharPlacement *CharLayout:: 00117 find_overlap(int x, int y, int x_size, int y_size) const { 00118 Placements::const_iterator pi; 00119 for (pi = _placements.begin(); pi != _placements.end(); ++pi) { 00120 const CharPlacement &placement = (*pi); 00121 if (placement.intersects(x, y, x_size, y_size)) { 00122 return &placement; 00123 } 00124 } 00125 00126 return (const CharPlacement *)NULL; 00127 }