feedback
Apr 23 2008

Dynamic Text Replacement with JavaScript and C# ASP.NET

by John Dyer

What it Does

You write some basic markup and include a JavaScript file and some code which replaces normal text with a .NET generated image:

<style type="text/css">
h2 { color: #9E100F; size: 22px; }
</style>

<!-- This says "Frequently asked questions in zh-TW -->
<!-- If you just see boxes, you need to install Asian fonts on your machine --> <h2>關於網上教育常見的問題</h2> <script type="text/javascript" src="fontreplacer.js"></script> <script type="text/javascript"> FontReplacer.replace('h2','*', 'MyGreatFont'); </script>

This will take all h2 tags with any class (*) and replace them with and image rendered using 'MyGreatFont'. This font needs to be installed the c:\windows\fonts\ folder of your server or in the same folder as the .NET script which generates it. Initially the page will look like this (using the standard font for Chinese script on a PC which is 'MS Mincho'):

image

But after the replacement happens, it looks like this:

image

With another less formal font, it could look like this:

image

Of course, you can use any font installed on the server and it is not limited to Chinese text. Here is an example replacing the default Times New Roman text with Century Gothic:

image

image

This may be useful in other scenarios for viewing Unicode text on a machine without Unicode fonts installed (Greek, Hebrew, Arabic, etc.).

It can also produce anti-aliased PNGs for use on top of an image:

image image

Why I did it

Recently, I needed to have the titles for a series of webpages be rendered in a specific Chinese font (see http://www.dts.edu/chinese and click on "zh-TW" in the upper right) because the default doesn't look very official (according to my Chinese friends). I wanted to use sIFR which replaces the HTML text node with a Flash file that has the font embedded. The problem is that Chinese fonts are 3-8MB which means the user has to download a gigantic SWF. Also, there can be copyright problems with using sIFR.

So I turned to .NET to generate images using the font. The basic technique was first published back in a 2004 A List Apart article titled Dynamic Text Replacement. ALA used JavaScript and PHP and, since then, there have been many permutations of the basic idea, some using pure CSS instead of JavaScript. I haven't seen a good one for .NET, so I had to write my own. I don't like using CSS for some of the reasons mentioned here, so I went with JavaScript for the replacement. This way users without images or JavaScript can still see the text. Users with images and JavaScript get a slightly nicer view.

How it Works

The JavaScript method looks at the HTML element(s) you send it and pulls out the text and font color. It then sends a request to ASP.NET to return an image which renders the text using your assigned font and colors. There are three ways to call it:

// elements by tag and class
FontReplacer.replace(tag, class, fontName);
// elements by tag and class inside a given elmenent
FontReplacer.replaceIn(element, tag, class, fontName);
// replace array of elements
FontReplacer.replaceElements(elementArray, fontName);

This calls up a .NET script which writes the text to an image using the specified font. The C# code can generate a JPG or transparent PNG which happily sits on top of any background and looks very nice. (There is a flag in the JavaScript to to allow the PNG transparency). There are some tricks in .NET for generating a PNG with alpha channels and for saving a JPEG with a specified quality, so here's the full code for that part.

if (backColor == "transparent")
{
	MemoryStream io = new MemoryStream();
	bitmap.Save(io, ImageFormat.Png);

	context.Response.ContentType = "image/png";
	context.Response.BinaryWrite(io.GetBuffer());
}
else
{
	context.Response.ContentType = "image/jpg";
	SaveAsJpeg(bitmap, context.Response.OutputStream, (long)100);
}
void SaveAsJpeg(Image inputImage, Stream stream, long quality)
{
	 // generate JPEG stuff
	 ImageCodecInfo codecEncoder = GetEncoder("image/jpeg");
	 EncoderParameters encoderParams = new EncoderParameters(1);
	 EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
	 encoderParams.Param[0] = qualityParam;
	 inputImage.Save(stream, codecEncoder, encoderParams);
}
ImageCodecInfo GetEncoder(string mimeType)
{
	ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
	foreach (ImageCodecInfo codec in codecs)
	{
		if (codec.MimeType == mimeType)
		{
			return codec;
		}
	}
	return null;

}

There are also flags in the JavaScript to force the returned image to be the same height and width as the element you are replacing. By default, the height is forced so that the page doesn't jerk at all, but you should be aware that browsers often report the font size inaccurately. Also, .NET's measurement of the size a given string will take up can include some padding depending on the font, so you may have to play with it for your scenario.

Lastly, there are some important things to know about using fonts on the server.

  1. When you install a font on c:\windows\fonts\, IIS doesn't immediately know it's there. You'll need to run the "resetiis" command for IIS to pick up the new fonts.
  2. If you're in a hosted environment and can't install fonts, you're still in luck. There is some code to load a *.TTF file in the fontwriter.ashx script. In this case, you'll need to specify the font file name ('gothic.ttf') rather than the installed font name ('Century Gothic').
  3. You might want to adjust the TextRenderingHint hint property at the top if you don't want anti-aliased rendering.

Download & Example

Apr 16 2008

var baby = john.Meiosis() + amber.Meiosis();

by John Dyer

Just a little genetics (my college major) humor written in C# 3.0 syntax (with overloaded operators and an implicitely typed local var) to announce that we're going to be parents later this fall! Check out the sweet spin moves below. I'm calling all-star running back...

offspring01_sonogram
This video requires Adobe Flash player

Behold, children are a gift of the LORD; The fruit of the womb is a reward.” Psalm 127:3

 

Apr 14 2008

Dallas Seminary Mobile Site

by John Dyer

Since Microsoft and Apple finally decided to allow/license versions of Flash Lite 3.0 for their mobile devices (Windows Mobile and iPhone), I created an initial build of a mobile site for Dallas Seminary which will eventually use Flash Lite 3.0 for all the audio and video content.

The goal was to make it look like an iPhone application using the list format, but have it work properly on other mobile devices by not specifically targeting the iPhone's screen size such as Windows Mobile and Blackberry. It's a bit more cramped on the smaller WM screen, but it works well.

Here are a few screen shots:

iPhone Windows Mobile
image dts_wm_home
image dts_wm_media

 

There is one gotcha on the iPhone that doesn't show up using Safari. The iPhone may try to startup zoomed out like it would need for a normal website. If your <div> tags are set to expand, the iPhone will stretch everything out and then zoom out.

 image

To fix this add the following:

<meta name="viewport" content="user-scalable=no,width=320,scale=1.0" />
Apr 10 2008

Totally Unobtrusive (and totally awesome) Upside Down Text

by John Dyer

There is a huge need for upside down text on the web. With everyone "going mobile," developers cannot simply rely on users having their screens oriented the same way all the time. I went through all of the possible options for creating upside down text and finally came up with a totally unobtrusive, Unicode enabled, completely web-changing piece of code (which is mostly from someone else and using this and this).

Options for Upside Down Text

  1. Images - The most obvious option for upside down text is to open up Photoshop, enter some text, and use Rotate Canvas.
    Pros: easy to do.
    Cons: must be done for every piece of text. Not every OS/browser in the world can display images. This is just unacceptable.

  2. sIFR - I know it's a little 2005 of me to say it, but a great use of Flash is to replace text and rotate it around.
    Pros: works for any HTML text element.
    Cons: requires Flash which has even less support than images. Also, requires extra coding.

  3. Canvas - one day it might be possible to do more with text drawing on a canvas tag, but right now its not
    Pros: none, for now.
    Cons: doesn't exist.

  4. JavaScript - Everyone knows JavaScript can do anything. See my experiments in 3D and color and this guy's port of Mario. Using this great script its possible to simulate upside down characters using Unicode equivalents.
    Pros: is awesome.
    Cons: nothing at all.

Usage &Implementation

Just give your HTML element a class called "upsidedowntext" and add the script in the header and you have pure greatness:

<script type="text/javascript" src="upsidedown.js"></script>

<div class="upsidedowntext">I can be read in any orientation</div>
<div>I can be read in any orientation</div> <div class="upsidedowntext">This is Tom Cruise taking your picture</div> <div>This is a boring Russian Mig</div>

Result:

uoıʇɐʇuǝıɹo ʎuɐ uı pɐǝɹ ǝq uɐɔ ı
I can be read in any orientation

ǝɹnʇɔıd ɹnoʎ ƃuıʞɐʇ ǝsınɹɔ ɯoʇ sı sıɥʇ
This is a boring Russian Mig

Demo and Download


Note: this post was intended to be an light-hearted (late) April's fools poke at all the random stuff developers are doing with JavaScript, sometimes in the name of a standard or idea that really isn't really needed. Also, I think upside down text is funny.