Friday, February 23, 2007

test 2


foo foo foo

test post

Friday, August 25, 2006

A stroll at the alma mater

I spent the past two days working in the bay area. I used to look forward to such trips because I'd visit my brother and his family, which was always a treat. They moved this summer though and no longer live there, so my level of interest in the trip was lower than usual.

For dinner last night one of the team leads suggested Macarthur Park. He was surprised that I knew exactly where it was. I mentioned that I had been taken there for dessert on my 19th birthday by friends in my dorm and that a former roommate's girlfriend had worked there. It is a bit of a curious location as it is at the very end of University Ave in Palo Alto, right between the Cal Train tracks and El Camino Real. After you cross El Camino you're onto campus and the road becomes Palm Drive.

Dinner was excellent, but that isn't what I want to dwell on here. After dinner I decided that as long as I was there at the edge of campus I'd take a stroll. I drove up Palm Drive and felt a flood of memories. I can remember approaching campus as a prospective freshman and driving up that same street and being impressed with the beauty of the place. But it was more than the fact that it is an attractive bit of road. At least it was last night, and I like to think there was a premonition of that in the spring of 1992 as well. Perhaps my memory is failing me. In any case, driving up Palm Drive was an oddly emotional and familiar experience last night.

I parked the car at the Oval and walked towards the main quad. I stopped to visit the Burgers of Calais. They had just taken up residence in their current location as I was graduating. I stopped in front of Mem Chu to admire the mosaic yet another time. I walked behind the church and then towards Meyer Library to see if the Thinker every resumed his post after getting vandalized yet again by Cal thugs. There was no sign of him. I wandered back past the Claw and the birdcage to Tressider, that architectural dung heap in the midst of an otherwise amazing campus. Ok, there are some other terrible edifices, the medical center for one.

I wandered back to the car and realized a few things. I was awash in a mixture of melancholy, gratitude, regret, and potential both lost and realized. The impact this place had on me came into sharp focus. Of course it wasn't the place but the people and the interactions, but for whatever reason the buildings of campus brought those experiences to mind and made them fresh in a way that I haven't experienced. I could recall particular classes, particular instants and interactions as I walked by buildings and classrooms.

I wanted my wife to be there with me. We met there, and that is where I began to fall in love with her, though she didn't reciprocate until a bit later. But we were great friends at the time and I felt that I wanted her to be there. I wanted to call her to share what I was feeling and try to articulate it, but it was late in CA and even later at home.

I also realized that I wanted my children to have the opportunity to have the same sort of experiences. To be surrounded by amazing peers, to be lifted up by them as well as to do their share of lifting. To have a world of possibilities open to them. I must admit that I'd love them to be able to go to Stanford, but what I want isn't for them to go to a particular place, but to have a university experience that is more than just classes and credits to graduate. There is a particular joy that my college experience brought me that I'm inclined to think doesn't happen without the right set of circumstances and that is something that I want my children to have.

I also decided that I needed to top off my visit with a trip to Yost. I got back the the car, drove around campus, parked illegally in Governor's Corner, and walked around the dorm. I'm guessing that I was an odd sight at 11:20 pm. If I had time I would have liked to visit all the dorms that I lived in, if only to drive by, but I figured that I'd get the most bang for my buck there. I peered in the window and saw bulletin boards that had been painted in either 96 or 97 to indicate that it was the Pop Culture Theme Dorm. I'm pretty sure that that is no longer the case, but the bulletin boards still advertise it, which made me smile.

So much happened there. Only parenthood has rivaled it when it comes to experiences that have taught me about myself. I cherish those bonds, those interactions, the critiques and the praises. I probably had the best series of four roommates possible.

Of course, as one of those roommates once reminded me, college life isn't the real world, and the real world is a much different place, one that I continue to enjoy. But it was fascinating to take a break from that world for a few moments to revisit an almost unreal time of life that is unique in so many dimensions.

Wednesday, June 07, 2006

Printing HTML from Java

I've been working on a project that uses a JEditorPane to display HTML. We also need to be able to print this information. Luckily Swing components know how to render themselves and Sun even has some helpful sample code up that seems to be six years old, but is still useful. The parts I thought were most helpful were the classes Vista, JComponentVista, and JBrowser.

However this code has at least two significant shortcomings.

The first is that while you can scale the rendered image in several ways, the only way to change how much text goes on a line is to actually change the size of the JBrowser window with the mouse. I tried repeatedly to have an offscreen JEditorPane that I could set to an independent width in order to render it for printing without regard to the width of the onscreen window and was constantly frustrated. If anybody knows how to do this I'd be interested. My crappy solution was to set the window to a reasonable width on application launch and let the user shoot themselves in the foot if they mess with it.

The second problem was less annoying to me but was actually noticed by the client, so I had to solve it. Since the JEditorPane is painting itself onto the pages using Graphics2D, it really is just creating a big image and then cropping it into pages. This method ignores page breaks. So you could easily get a line of text at the bottom of the page with its bottom half chopped off. The bottom half would appear at the top of the next page. Generally this is not good for readability.

Now looking back I probably should have gotten the source for JEditorPane and the HTMLEditorKit and looked at how it renders things and added a way to set the page length. This is not what I did.

Instead I figured that the way to do this was to examine the image that was rendered, look for text near the bottom of the page, and then look of a relatively pixel free line near the bottom of the page and set that as the boundary of the lower crop.

Unfortunately Graphics2D does not provide a simple way of examining what you've just drawn. In order to look for blank horizontal lines I did the following:


   public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException {


if (pageIndex >= mNumPages) {

throw new IndexOutOfBoundsException();

}
BufferedImage image = new BufferedImage(300,5000,BufferedImage.TYPE_INT_RGB);

Graphics2D imageGraphics = (Graphics2D)image.getGraphics();
double originX = (pageIndex % mNumPagesX) * mFormat.getImageableWidth();

//double originY = (pageIndex / mNumPagesX) * mFormat.getImageableHeight();
double originY = 0;

for (int i = 0; i < pageIndex; i++)
{
originY+=heights[i];
}
imageGraphics.translate(-originX/mScaleX, -originY/mScaleY);
//System.out.println("OrigX:"+originX+ " OrigY:"+originY);
//System.out.println("SOrigX:"+originX/mScaleX+ " SOrigY:"+originY/mScaleY);
mComponent.paint(imageGraphics);
Raster raster = image.getData();
DataBuffer db = raster.getDataBuffer();
SampleModel sm = raster.getSampleModel();
int[] pixels = new int[30000];
PageFormat pageFormat = getPageFormat();
//System.out.println("Printing page:"+pageIndex+ " Y: "+ pageFormat.getImageableHeight()/mScaleY);

pixels = sm.getPixels(100,(int) (pageFormat.getImageableHeight()/mScaleY )-50,200,50,pixels,db);


int bestRow = 49;
int bestCount = 0;

for (int row = 49; row >= 0; row--)
{
int count = 0;
for (int col = 0; col < 600; col ++)
{
count += pixels[row*600+col];
}
if (count > bestCount)
{
bestRow = row;
bestCount = count;
}
// System.out.println("Row:"+row +" Count:"+count);

}
/*
* The following print statements are quite
* useful for debugging but slow things down.
*
System.out.println("Best Row:"+bestRow +" Best Count:"+bestCount);

for (int i = 0; i < pixels.length; i+=3)
{

if (i%600 == 0)
{
System.out.print("\n");
if (i/600 == bestRow)
{
System.out.print("***");
}
else
{

if (i/600 < 100) System.out.print("0");
if (i/600 < 10 ) System.out.print("0");
System.out.print(i/600);
}
}
if (pixels[i]==0)
{
System.out.print("X");
}
else
{
System.out.print(" ");
}

}
*/
int diff = 50 - bestRow;

Paper newPaper = (Paper) pageFormat.getPaper().clone();
heights[pageIndex]= (int) (pageFormat.getImageableHeight()-diff*mScaleY);
newPaper.setImageableArea(72,72,pageFormat.getImageableWidth(), pageFormat.getImageableHeight()-diff*mScaleY);
pageFormat.setPaper(newPaper);
//System.out.print("\n");

return pageFormat;

}



So what does that do? First I create a BufferedImage in order to render to it. Then I figure out what page it is that is being rendered. I find the current position in the larger image by adding up the lengths of the previous pages. Note that these lengths will vary now. Then I translate the rendering context to that area and draw the image. Once I have it drawn I use a Raster, DataBuffer, and SampleModel to extract the pixels from the image. I then examine a small sample starting at the bottom and going up 50 lines. I am looking for the horizontal line with the least number of black pixels. If there is a tie I use the lower line. I've also got some commented out code there that outputs the last 50 lines of pixels as text. This was very useful for debugging purposes as it allowed me to see exactly what was happening.

This solution isn't perfect. It doesn't span the entire width of the page, which is something I could make it do pretty easily. It also does not calculate the total number of pages properly since some pages will be shorter now, which in some situations will mean that addtional pages must be printed. I should probably do all the pre-rendering when the number of pages is calculated. However it works well enough for now, and I thought it would be worthwhile to post this in this form since I was unable to find a solution to this problem on the web.

Feedback would be appreciated.

I should also mention that the client has suddenly decided to print white text on a blue background. This subverts the above code in an obvious way by making it actively try to split a line of text.

Friday, May 06, 2005

Coincidence?

Out of boredom I took a look at the webpage for my mission this week. I noticed an old guestbook entry by someone looking for the missionaries that taught them. One of the missionaires was Elder Thomas. There were two Elder Thomases there during the timeframe in question, one of which I know relatively well. I was going to respond to the inquiry, but the person who left it didn't leave a way of contacting them. So I looked up the Thomas that I know on Yahoo, given that I know what city he had moved to about two years ago. I found a number and tried to call. I got an answering machine that belonged to someone else. Maybe he had moved. I figured that it wasn't worth bothering his parents on the off chance that this person that I couldn't contact was trying to contact him.

The next day I get an email message that there is a new guestbook entry on the site, looking for Elder Thomas again. So I click it and this time the person has provided an email address. I write her back and explain that there were two and ask which one she wants. She responded the next day saying that she wants to contact the one that I know. I was able to pass along his parent's address, since I am no longer sure where he lives.

Now I wonder, is it mere coincidence that this person posted again with their email address within a day of my seeing their old post? I have no idea. Is it meaningful? I would guess that putting this woman back in contact with this person is more meaningful than the fact that she put up the second post just as a person that could help her was thinking about it.

Monday, March 21, 2005

this is a test of the first time blogging system

This is only a test. If this were an actual post it would contain a link to some code or something.